diff options
author | Alan Mishchenko <alanmi@berkeley.edu> | 2007-09-30 08:01:00 -0700 |
---|---|---|
committer | Alan Mishchenko <alanmi@berkeley.edu> | 2007-09-30 08:01:00 -0700 |
commit | e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7 (patch) | |
tree | de3ffe87c3e17950351e3b7d97fa18318bd5ea9a /src/bdd | |
parent | 7d7e60f2dc84393cd4c5db22d2eaf7b1fb1a79b2 (diff) | |
download | abc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.tar.gz abc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.tar.bz2 abc-e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7.zip |
Version abc70930
Diffstat (limited to 'src/bdd')
105 files changed, 0 insertions, 81917 deletions
diff --git a/src/bdd/cas/cas.h b/src/bdd/cas/cas.h deleted file mode 100644 index fcc9f890..00000000 --- a/src/bdd/cas/cas.h +++ /dev/null @@ -1,62 +0,0 @@ -/**CFile**************************************************************** - - FileName [cas.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cas.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CAS_H__ -#define __CAS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -#define MAXINPUTS 1024 -#define MAXOUTPUTS 1024 - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== zzz.c ==========================================================*/ - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/cas/casCore.c b/src/bdd/cas/casCore.c deleted file mode 100644 index 579235b1..00000000 --- a/src/bdd/cas/casCore.c +++ /dev/null @@ -1,1263 +0,0 @@ -/**CFile**************************************************************** - - FileName [casCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] - - Synopsis [Entrance into the implementation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Spring 2002.] - - Revision [$Id: casCore.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include "extra.h" -#include "cas.h" - -//////////////////////////////////////////////////////////////////////// -/// static functions /// -//////////////////////////////////////////////////////////////////////// - -DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose ); -DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ); -DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew ); - -extern int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose ); - -void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName ); - -DdNode * Cudd_bddTransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); - -//////////////////////////////////////////////////////////////////////// -/// static varibles /// -//////////////////////////////////////////////////////////////////////// - -//static FILE * pTable = NULL; -//static long s_RemappingTime = 0; - -//////////////////////////////////////////////////////////////////////// -/// debugging macros /// -//////////////////////////////////////////////////////////////////////// - -#define PRD(p) printf( "\nDECOMPOSITION TREE:\n\n" ); PrintDecEntry( (p), 0 ) -#define PRB(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" ) -#define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" ) -#define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" ) - - -//////////////////////////////////////////////////////////////////////// -/// EXTERNAL FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose ) -{ - int i; - int nVars = nInputs; - int nOuts = nOutputs; - long clk1; - - int nVarsEnc; // the number of additional variables to encode outputs - DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars - - int nNames; // the total number of all inputs - char * pNames[MAXINPUTS]; // the temporary storage for the input (and output encoding) names - - DdNode * aFunc; // the encoded 0-1 BDD containing all the outputs - - char FileNameIni[100]; - char FileNameFin[100]; - char Buffer[100]; - - -//pTable = fopen( "stats.txt", "a+" ); -//fprintf( pTable, "%s ", pFileGeneric ); -//fprintf( pTable, "%d ", nVars ); -//fprintf( pTable, "%d ", nOuts ); - - - // assign the file names - strcpy( FileNameIni, pFileGeneric ); - strcat( FileNameIni, "_ENC.blif" ); - - strcpy( FileNameFin, pFileGeneric ); - strcat( FileNameFin, "_LUT.blif" ); - - - // create the variables to encode the outputs - nVarsEnc = Extra_Base2Log( nOuts ); - for ( i = 0; i < nVarsEnc; i++ ) - pbVarsEnc[i] = Cudd_bddNewVarAtLevel( dd, i ); - - - // store the input names - nNames = nVars + nVarsEnc; - for ( i = 0; i < nVars; i++ ) - { -// pNames[i] = Extra_UtilStrsav( pFunc->pInputNames[i] ); - sprintf( Buffer, "pi%03d", i ); - pNames[i] = Extra_UtilStrsav( Buffer ); - } - // set the encoding variable name - for ( ; i < nNames; i++ ) - { - sprintf( Buffer, "OutEnc_%02d", i-nVars ); - pNames[i] = Extra_UtilStrsav( Buffer ); - } - - - // print the variable order -// printf( "\n" ); -// printf( "Variable order is: " ); -// for ( i = 0; i < dd->size; i++ ) -// printf( " %d", dd->invperm[i] ); -// printf( "\n" ); - - // derive the single-output function - clk1 = clock(); - aFunc = GetSingleOutputFunction( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc, fVerbose ); Cudd_Ref( aFunc ); -// aFunc = GetSingleOutputFunctionRemapped( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( aFunc ); -// if ( fVerbose ) -// printf( "Single-output function computation time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - -//fprintf( pTable, "%d ", Cudd_SharingSize( pOutputs, nOutputs ) ); -//fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pOutputs, nOutputs) ); - - // dispose of the multiple-output function -// Extra_Dissolve( pFunc ); - - // reorder the single output function -// if ( fVerbose ) -// printf( "Reordering variables...\n"); - clk1 = clock(); -// if ( fVerbose ) -// printf( "Node count before = %6d\n", Cudd_DagSize( aFunc ) ); -// Cudd_ReduceHeap(dd, CUDD_REORDER_SIFT,1); - Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); - Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); - if ( fVerbose ) - printf( "MTBDD reordered = %6d nodes\n", Cudd_DagSize( aFunc ) ); - if ( fVerbose ) - printf( "Variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); -// printf( "\n" ); -// printf( "Variable order is: " ); -// for ( i = 0; i < dd->size; i++ ) -// printf( " %d", dd->invperm[i] ); -// printf( "\n" ); -//fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) ); -//fprintf( pTable, "%d ", Extra_ProfileWidthMax(dd, aFunc) ); - - // write the single-output function into BLIF for verification - clk1 = clock(); - if ( fCheck ) - WriteSingleOutputFunctionBlif( dd, aFunc, pNames, nNames, FileNameIni ); -// if ( fVerbose ) -// printf( "Single-output function writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - -/* - /////////////////////////////////////////////////////////////////// - // verification of single output function - clk1 = clock(); - { - BFunc g_Func; - DdNode * aRes; - - g_Func.dd = dd; - g_Func.FileInput = Extra_UtilStrsav(FileNameIni); - - if ( Extra_ReadFile( &g_Func ) == 0 ) - { - printf( "\nSomething did not work out while reading the input file for verification\n"); - Extra_Dissolve( &g_Func ); - return; - } - - aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); - - if ( aRes != aFunc ) - printf( "\nVerification FAILED!\n"); - else - printf( "\nVerification okay!\n"); - - Cudd_RecursiveDeref( dd, aRes ); - - // delocate - Extra_Dissolve( &g_Func ); - } - printf( "Preliminary verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - /////////////////////////////////////////////////////////////////// -*/ - - if ( !CreateDecomposedNetwork( dd, aFunc, pNames, nNames, FileNameFin, nLutSize, fCheck, fVerbose ) ) - return 0; - -/* - /////////////////////////////////////////////////////////////////// - // verification of the decomposed LUT network - clk1 = clock(); - { - BFunc g_Func; - DdNode * aRes; - - g_Func.dd = dd; - g_Func.FileInput = Extra_UtilStrsav(FileNameFin); - - if ( Extra_ReadFile( &g_Func ) == 0 ) - { - printf( "\nSomething did not work out while reading the input file for verification\n"); - Extra_Dissolve( &g_Func ); - return; - } - - aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); - - if ( aRes != aFunc ) - printf( "\nFinal verification FAILED!\n"); - else - printf( "\nFinal verification okay!\n"); - - Cudd_RecursiveDeref( dd, aRes ); - - // delocate - Extra_Dissolve( &g_Func ); - } - printf( "Final verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - /////////////////////////////////////////////////////////////////// -*/ - - // verify the results - if ( fCheck ) - { - extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); - extern void * Abc_FrameGetGlobalFrame(); - char Command[200]; - sprintf( Command, "cec %s %s", FileNameIni, FileNameFin ); - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); - } - - Cudd_RecursiveDeref( dd, aFunc ); - - // release the names - for ( i = 0; i < nNames; i++ ) - free( pNames[i] ); - - -//fprintf( pTable, "\n" ); -//fclose( pTable ); - - return 1; -} - -#if 0 - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Experiment2( BFunc * pFunc ) -{ - int i, x, RetValue; - int nVars = pFunc->nInputs; - int nOuts = pFunc->nOutputs; - DdManager * dd = pFunc->dd; - long clk1; - -// int nVarsEnc; // the number of additional variables to encode outputs -// DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars - - int nNames; // the total number of all inputs - char * pNames[MAXINPUTS]; // the temporary storage for the input (and output encoding) names - - DdNode * aFunc; // the encoded 0-1 BDD containing all the outputs - - char FileNameIni[100]; - char FileNameFin[100]; - char Buffer[100]; - - DdManager * DdNew; - -//pTable = fopen( "stats.txt", "a+" ); -//fprintf( pTable, "%s ", pFunc->FileGeneric ); -//fprintf( pTable, "%d ", nVars ); -//fprintf( pTable, "%d ", nOuts ); - - - // assign the file names - strcpy( FileNameIni, pFunc->FileGeneric ); - strcat( FileNameIni, "_ENC.blif" ); - - strcpy( FileNameFin, pFunc->FileGeneric ); - strcat( FileNameFin, "_LUT.blif" ); - - // derive the single-output function IN THE NEW MANAGER - clk1 = clock(); -// aFunc = GetSingleOutputFunction( dd, pFunc->pOutputs, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( aFunc ); - aFunc = GetSingleOutputFunctionRemappedNewDD( dd, pFunc->pOutputs, nOuts, &DdNew ); Cudd_Ref( aFunc ); - printf( "Single-output function derivation time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); -// s_RemappingTime = clock() - clk1; - - // dispose of the multiple-output function - Extra_Dissolve( pFunc ); - - // reorder the single output function - printf( "\nReordering variables in the new manager...\n"); - clk1 = clock(); - printf( "Node count before = %d\n", Cudd_DagSize( aFunc ) ); -// Cudd_ReduceHeap(DdNew, CUDD_REORDER_SIFT,1); - Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1); - printf( "Node count after = %d\n", Cudd_DagSize( aFunc ) ); - printf( "Variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - printf( "\n" ); - -//fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) ); -//fprintf( pTable, "%d ", Extra_ProfileWidthMax(DdNew, aFunc) ); - - - // create the names to be used with the new manager - nNames = DdNew->size; - for ( x = 0; x < nNames; x++ ) - { - sprintf( Buffer, "v%02d", x ); - pNames[x] = Extra_UtilStrsav( Buffer ); - } - - - - // write the single-output function into BLIF for verification - clk1 = clock(); - WriteSingleOutputFunctionBlif( DdNew, aFunc, pNames, nNames, FileNameIni ); - printf( "Single-output function writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - - - /////////////////////////////////////////////////////////////////// - // verification of single output function - clk1 = clock(); - { - BFunc g_Func; - DdNode * aRes; - - g_Func.dd = DdNew; - g_Func.FileInput = Extra_UtilStrsav(FileNameIni); - - if ( Extra_ReadFile( &g_Func ) == 0 ) - { - printf( "\nSomething did not work out while reading the input file for verification\n"); - Extra_Dissolve( &g_Func ); - return; - } - - aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); - - if ( aRes != aFunc ) - printf( "\nVerification FAILED!\n"); - else - printf( "\nVerification okay!\n"); - - Cudd_RecursiveDeref( DdNew, aRes ); - - // delocate - Extra_Dissolve( &g_Func ); - } - printf( "Preliminary verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - /////////////////////////////////////////////////////////////////// - - - CreateDecomposedNetwork( DdNew, aFunc, pNames, nNames, FileNameFin, nLutSize, 0 ); - -/* - /////////////////////////////////////////////////////////////////// - // verification of the decomposed LUT network - clk1 = clock(); - { - BFunc g_Func; - DdNode * aRes; - - g_Func.dd = DdNew; - g_Func.FileInput = Extra_UtilStrsav(FileNameFin); - - if ( Extra_ReadFile( &g_Func ) == 0 ) - { - printf( "\nSomething did not work out while reading the input file for verification\n"); - Extra_Dissolve( &g_Func ); - return; - } - - aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); - - if ( aRes != aFunc ) - printf( "\nFinal verification FAILED!\n"); - else - printf( "\nFinal verification okay!\n"); - - Cudd_RecursiveDeref( DdNew, aRes ); - - // delocate - Extra_Dissolve( &g_Func ); - } - printf( "Final verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - /////////////////////////////////////////////////////////////////// -*/ - - - Cudd_RecursiveDeref( DdNew, aFunc ); - - // release the names - for ( i = 0; i < nNames; i++ ) - free( pNames[i] ); - - - - ///////////////////////////////////////////////////////////////////// - // check for remaining references in the package - RetValue = Cudd_CheckZeroRef( DdNew ); - printf( "\nThe number of referenced nodes in the new manager = %d\n", RetValue ); - Cudd_Quit( DdNew ); - -//fprintf( pTable, "\n" ); -//fclose( pTable ); - -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// SINGLE OUTPUT FUNCTION /// -//////////////////////////////////////////////////////////////////////// - -// the bit count for the first 256 integer numbers -static unsigned char BitCount8[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; - -///////////////////////////////////////////////////////////// -static int s_SuppSize[MAXOUTPUTS]; -int CompareSupports( int *ptrX, int *ptrY ) -{ - return ( s_SuppSize[*ptrY] - s_SuppSize[*ptrX] ); -} -///////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////// -static int s_MintOnes[MAXOUTPUTS]; -int CompareMinterms( int *ptrX, int *ptrY ) -{ - return ( s_MintOnes[*ptrY] - s_MintOnes[*ptrX] ); -} -///////////////////////////////////////////////////////////// - -int GrayCode ( int BinCode ) -{ - return BinCode ^ ( BinCode >> 1 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose ) -{ - int i; - DdNode * bResult, * aResult; - DdNode * bCube, * bTemp, * bProd; - - int Order[MAXOUTPUTS]; -// int OrderMint[MAXOUTPUTS]; - - // sort the output according to their support size - for ( i = 0; i < nOuts; i++ ) - { - s_SuppSize[i] = Cudd_SupportSize( dd, pbOuts[i] ); -// s_MintOnes[i] = BitCount8[i]; - Order[i] = i; -// OrderMint[i] = i; - } - - // order the outputs - qsort( (void*)Order, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareSupports ); - // order the outputs -// qsort( (void*)OrderMint, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareMinterms ); - - - bResult = b0; Cudd_Ref( bResult ); - for ( i = 0; i < nOuts; i++ ) - { -// bCube = Cudd_bddBitsToCube( dd, OrderMint[i], nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); -// bProd = Cudd_bddAnd( dd, bCube, pbOuts[Order[nOuts-1-i]] ); Cudd_Ref( bProd ); - bCube = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc, 1 ); Cudd_Ref( bCube ); - bProd = Cudd_bddAnd( dd, bCube, pbOuts[Order[i]] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bCube ); - - bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - - // convert to the ADD -if ( fVerbose ) -printf( "Single BDD size = %6d nodes\n", Cudd_DagSize(bResult) ); - aResult = Cudd_BddToAdd( dd, bResult ); Cudd_Ref( aResult ); - Cudd_RecursiveDeref( dd, bResult ); -if ( fVerbose ) -printf( "MTBDD = %6d nodes\n", Cudd_DagSize(aResult) ); - Cudd_Deref( aResult ); - return aResult; -} -/* -DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ) -{ - int i; - DdNode * bResult, * aResult; - DdNode * bCube, * bTemp, * bProd; - - bResult = b0; Cudd_Ref( bResult ); - for ( i = 0; i < nOuts; i++ ) - { -// bCube = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); - bCube = Extra_bddBitsToCube( dd, nOuts-1-i, nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); - bProd = Cudd_bddAnd( dd, bCube, pbOuts[i] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bCube ); - - bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - - // conver to the ADD - aResult = Cudd_BddToAdd( dd, bResult ); Cudd_Ref( aResult ); - Cudd_RecursiveDeref( dd, bResult ); - - Cudd_Deref( aResult ); - return aResult; -} -*/ - - -//////////////////////////////////////////////////////////////////////// -/// INPUT REMAPPING /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ) -// returns the ADD of the remapped function -{ - static int Permute[MAXINPUTS]; - static DdNode * pRemapped[MAXOUTPUTS]; - - DdNode * bSupp, * bTemp; - int i, Counter; - int nSuppPrev = -1; - DdNode * bFunc; - DdNode * aFunc; - - Cudd_AutodynDisable(dd); - - // perform the remapping - for ( i = 0; i < nOuts; i++ ) - { - // get support - bSupp = Cudd_Support( dd, pOutputs[i] ); Cudd_Ref( bSupp ); - - // create the variable map - Counter = 0; - for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) - Permute[bTemp->index] = Counter++; - - // transfer the BDD and remap it - pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute ); Cudd_Ref( pRemapped[i] ); - - // remove support - Cudd_RecursiveDeref( dd, bSupp ); - } - - // perform the encoding - bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( bFunc ); - - // convert to ADD - aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc ); - Cudd_RecursiveDeref( dd, bFunc ); - - // deref the intermediate results - for ( i = 0; i < nOuts; i++ ) - Cudd_RecursiveDeref( dd, pRemapped[i] ); - - Cudd_Deref( aFunc ); - return aFunc; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew ) -// returns the ADD of the remapped function -{ - static int Permute[MAXINPUTS]; - static DdNode * pRemapped[MAXOUTPUTS]; - - static DdNode * pbVarsEnc[MAXINPUTS]; - int nVarsEnc; - - DdManager * ddnew; - - DdNode * bSupp, * bTemp; - int i, v, Counter; - int nSuppPrev = -1; - DdNode * bFunc; - - // these are in the new manager - DdNode * bFuncNew; - DdNode * aFuncNew; - - int nVarsMax = 0; - - // perform the remapping and write the DDs into the new manager - for ( i = 0; i < nOuts; i++ ) - { - // get support - bSupp = Cudd_Support( dd, pOutputs[i] ); Cudd_Ref( bSupp ); - - // create the variable map - // to remap the DD into the upper part of the manager - Counter = 0; - for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) - Permute[bTemp->index] = dd->invperm[Counter++]; - - // transfer the BDD and remap it - pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute ); Cudd_Ref( pRemapped[i] ); - - // remove support - Cudd_RecursiveDeref( dd, bSupp ); - - - // determine the largest support size - if ( nVarsMax < Counter ) - nVarsMax = Counter; - } - - // select the encoding variables to follow immediately after the original variables - nVarsEnc = Extra_Base2Log(nOuts); -/* - for ( v = 0; v < nVarsEnc; v++ ) - if ( nVarsMax + v < dd->size ) - pbVarsEnc[v] = dd->var[ dd->invperm[nVarsMax+v] ]; - else - pbVarsEnc[v] = Cudd_bddNewVar( dd ); -*/ - // create the new variables on top of the manager - for ( v = 0; v < nVarsEnc; v++ ) - pbVarsEnc[v] = Cudd_bddNewVarAtLevel( dd, v ); - -//fprintf( pTable, "%d ", Cudd_SharingSize( pRemapped, nOuts ) ); -//fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pRemapped, nOuts) ); - - - // perform the encoding - bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( bFunc ); - - - // find the cross-manager permutation - // the variable from the level v in the old manager - // should become a variable number v in the new manager - for ( v = 0; v < nVarsMax + nVarsEnc; v++ ) - Permute[dd->invperm[v]] = v; - - - /////////////////////////////////////////////////////////////////////////////// - // start the new manager - ddnew = Cudd_Init( nVarsMax + nVarsEnc, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); -// Cudd_AutodynDisable(ddnew); - Cudd_AutodynEnable(dd, CUDD_REORDER_SYMM_SIFT); - - // transfer it to the new manager - bFuncNew = Cudd_bddTransferPermute( dd, ddnew, bFunc, Permute ); Cudd_Ref( bFuncNew ); - /////////////////////////////////////////////////////////////////////////////// - - - // deref the intermediate results in the old manager - Cudd_RecursiveDeref( dd, bFunc ); - for ( i = 0; i < nOuts; i++ ) - Cudd_RecursiveDeref( dd, pRemapped[i] ); - - - /////////////////////////////////////////////////////////////////////////////// - // convert to ADD in the new manager - aFuncNew = Cudd_BddToAdd( ddnew, bFuncNew ); Cudd_Ref( aFuncNew ); - Cudd_RecursiveDeref( ddnew, bFuncNew ); - - // return the manager - *DdNew = ddnew; - /////////////////////////////////////////////////////////////////////////////// - - Cudd_Deref( aFuncNew ); - return aFuncNew; -} - -//////////////////////////////////////////////////////////////////////// -/// BLIF WRITING FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName ) -{ - int i; - FILE * pFile; - - // start the file - pFile = fopen( FileName, "w" ); - fprintf( pFile, ".model %s\n", FileName ); - - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nNames; i++ ) - fprintf( pFile, " %s", pNames[i] ); - fprintf( pFile, "\n" ); - fprintf( pFile, ".outputs F" ); - fprintf( pFile, "\n" ); - - // write the DD into the file - WriteDDintoBLIFfile( pFile, aFunc, "F", "", pNames ); - - fprintf( pFile, ".end\n" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ) -// writes the main part of the BLIF file -// Func is a BDD or a 0-1 ADD to be written -// OutputName is the name of the output -// Prefix is attached to each intermendiate signal to make it unique -// InputNames are the names of the input signals -// (some part of the code is borrowed from Cudd_DumpDot()) -{ - int i; - st_table * visited; - st_generator * gen = NULL; - long refAddr, diff, mask; - DdNode * Node, * Else, * ElseR, * Then; - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table( st_ptrcmp, st_ptrhash ); - - /* Collect all the nodes of this DD in the symbol table. */ - cuddCollectNodes( Cudd_Regular(Func), visited ); - - /* 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 )Cudd_Regular(Func); - diff = 0; - gen = st_init_gen( visited ); - while ( st_gen( gen, ( char ** ) &Node, NULL ) ) - { - diff |= refAddr ^ ( long ) Node; - } - st_free_gen( gen ); - gen = NULL; - - /* Choose the mask. */ - for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 ) - { - mask = ( 1 << i ) - 1; - if ( diff <= mask ) - break; - } - - - // write the buffer for the output - fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(Func) ) / sizeof(DdNode), OutputName ); - fprintf( pFile, "%s 1\n", (Cudd_IsComplement(Func))? "0": "1" ); - - - gen = st_init_gen( visited ); - while ( st_gen( gen, ( char ** ) &Node, NULL ) ) - { - if ( Node->index == CUDD_MAXINDEX ) - { - // write the terminal node - fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" ); - continue; - } - - Else = cuddE(Node); - ElseR = Cudd_Regular(Else); - Then = cuddT(Node); - - assert( InputNames[Node->index] ); - if ( Else == ElseR ) - { // no inverter - fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index], - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)Then ) / sizeof(DdNode), - Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, "01- 1\n" ); - fprintf( pFile, "1-1 1\n" ); - } - else - { // inverter - int * pSlot; - fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index], - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)Then ) / sizeof(DdNode), - Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, "01- 1\n" ); - fprintf( pFile, "1-1 1\n" ); - - // if the inverter is written, skip - if ( !st_find( visited, (char *)ElseR, (char ***)&pSlot ) ) - assert( 0 ); - if ( *pSlot ) - continue; - *pSlot = 1; - - fprintf( pFile, ".names %s%lx %s%lx_i\n", - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode) ); - fprintf( pFile, "0 1\n" ); - } - } - st_free_gen( gen ); - gen = NULL; - st_free_table( visited ); -} - - - - -static DdManager * s_ddmin; - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ) -// writes the main part of the BLIF file -// Func is a BDD or a 0-1 ADD to be written -// OutputName is the name of the output -// Prefix is attached to each intermendiate signal to make it unique -// InputNames are the names of the input signals -// (some part of the code is borrowed from Cudd_DumpDot()) -{ - int i; - st_table * visited; - st_generator * gen = NULL; - long refAddr, diff, mask; - DdNode * Node, * Else, * ElseR, * Then; - - - /////////////////////////////////////////////////////////////// - DdNode * bFmin; - int clk1; - - if ( s_ddmin == NULL ) - s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); - - clk1 = clock(); - bFmin = Cudd_bddTransfer( dd, s_ddmin, Func ); Cudd_Ref( bFmin ); - - // reorder - printf( "Nodes before = %d. ", Cudd_DagSize(bFmin) ); - Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT_CONV,1); - printf( "Nodes after = %d. \n", Cudd_DagSize(bFmin) ); - /////////////////////////////////////////////////////////////// - - - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table( st_ptrcmp, st_ptrhash ); - - /* Collect all the nodes of this DD in the symbol table. */ - cuddCollectNodes( Cudd_Regular(bFmin), visited ); - - /* 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 )Cudd_Regular(bFmin); - diff = 0; - gen = st_init_gen( visited ); - while ( st_gen( gen, ( char ** ) &Node, NULL ) ) - { - diff |= refAddr ^ ( long ) Node; - } - st_free_gen( gen ); - gen = NULL; - - /* Choose the mask. */ - for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 ) - { - mask = ( 1 << i ) - 1; - if ( diff <= mask ) - break; - } - - - // write the buffer for the output - fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(bFmin) ) / sizeof(DdNode), OutputName ); - fprintf( pFile, "%s 1\n", (Cudd_IsComplement(bFmin))? "0": "1" ); - - - gen = st_init_gen( visited ); - while ( st_gen( gen, ( char ** ) &Node, NULL ) ) - { - if ( Node->index == CUDD_MAXINDEX ) - { - // write the terminal node - fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" ); - continue; - } - - Else = cuddE(Node); - ElseR = Cudd_Regular(Else); - Then = cuddT(Node); - - assert( InputNames[Node->index] ); - if ( Else == ElseR ) - { // no inverter - fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index], - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)Then ) / sizeof(DdNode), - Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, "01- 1\n" ); - fprintf( pFile, "1-1 1\n" ); - } - else - { // inverter - fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index], - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)Then ) / sizeof(DdNode), - Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, "01- 1\n" ); - fprintf( pFile, "1-1 1\n" ); - - fprintf( pFile, ".names %s%lx %s%lx_i\n", - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode) ); - fprintf( pFile, "0 1\n" ); - } - } - st_free_gen( gen ); - gen = NULL; - st_free_table( visited ); - - - ////////////////////////////////////////////////// - Cudd_RecursiveDeref( s_ddmin, bFmin ); - ////////////////////////////////////////////////// -} - - - - -//////////////////////////////////////////////////////////////////////// -/// TRANSFER WITH MAPPING /// -//////////////////////////////////////////////////////////////////////// -static DdNode * cuddBddTransferPermuteRecur -ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, st_table * table, int * Permute )); - -static DdNode * cuddBddTransferPermute -ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute)); - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. The orders of the - variables in the two managers may be different. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise. The i-th entry in the array Permute tells what is the index - of the i-th variable from the old manager in the new manager.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_bddTransferPermute( DdManager * ddSource, - DdManager * ddDestination, DdNode * f, int * Permute ) -{ - DdNode *res; - do - { - ddDestination->reordered = 0; - res = cuddBddTransferPermute( ddSource, ddDestination, f, Permute ); - } - while ( ddDestination->reordered == 1 ); - return ( res ); - -} /* end of Cudd_bddTransferPermute */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddTransferPermute] - -******************************************************************************/ -DdNode * -cuddBddTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ) -{ - DdNode *res; - st_table *table = NULL; - st_generator *gen = NULL; - DdNode *key, *value; - - table = st_init_table( st_ptrcmp, st_ptrhash ); - if ( table == NULL ) - goto failure; - res = cuddBddTransferPermuteRecur( ddS, ddD, f, table, Permute ); - if ( res != NULL ) - cuddRef( res ); - - /* Dereference all elements in the table and dispose of the table. - ** This must be done also if res is NULL to avoid leaks in case of - ** reordering. */ - gen = st_init_gen( table ); - if ( gen == NULL ) - goto failure; - while ( st_gen( gen, ( char ** ) &key, ( char ** ) &value ) ) - { - Cudd_RecursiveDeref( ddD, value ); - } - st_free_gen( gen ); - gen = NULL; - st_free_table( table ); - table = NULL; - - if ( res != NULL ) - cuddDeref( res ); - return ( res ); - - failure: - if ( table != NULL ) - st_free_table( table ); - if ( gen != NULL ) - st_free_gen( gen ); - return ( NULL ); - -} /* end of cuddBddTransferPermute */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddTransferPermute.] - - Description [Performs the recursive step of Cudd_bddTransferPermute. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddBddTransferPermute] - -******************************************************************************/ -static DdNode * -cuddBddTransferPermuteRecur( DdManager * ddS, - DdManager * ddD, DdNode * f, st_table * table, int * Permute ) -{ - DdNode *ft, *fe, *t, *e, *var, *res; - DdNode *one, *zero; - int index; - int comple = 0; - - statLine( ddD ); - one = DD_ONE( ddD ); - comple = Cudd_IsComplement( f ); - - /* Trivial cases. */ - if ( Cudd_IsConstant( f ) ) - return ( Cudd_NotCond( one, comple ) ); - - /* Make canonical to increase the utilization of the cache. */ - f = Cudd_NotCond( f, comple ); - /* Now f is a regular pointer to a non-constant node. */ - - /* Check the cache. */ - if ( st_lookup( table, ( char * ) f, ( char ** ) &res ) ) - return ( Cudd_NotCond( res, comple ) ); - - /* Recursive step. */ - index = Permute[f->index]; - ft = cuddT( f ); - fe = cuddE( f ); - - t = cuddBddTransferPermuteRecur( ddS, ddD, ft, table, Permute ); - if ( t == NULL ) - { - return ( NULL ); - } - cuddRef( t ); - - e = cuddBddTransferPermuteRecur( ddS, ddD, fe, table, Permute ); - if ( e == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - return ( NULL ); - } - cuddRef( e ); - - zero = Cudd_Not( one ); - var = cuddUniqueInter( ddD, index, one, zero ); - if ( var == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - res = cuddBddIteRecur( ddD, var, t, e ); - if ( res == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - cuddRef( res ); - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - - if ( st_add_direct( table, ( char * ) f, ( char * ) res ) == - ST_OUT_OF_MEM ) - { - Cudd_RecursiveDeref( ddD, res ); - return ( NULL ); - } - return ( Cudd_NotCond( res, comple ) ); - -} /* end of cuddBddTransferPermuteRecur */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - - diff --git a/src/bdd/cas/casDec.c b/src/bdd/cas/casDec.c deleted file mode 100644 index a1eb5f36..00000000 --- a/src/bdd/cas/casDec.c +++ /dev/null @@ -1,508 +0,0 @@ -/**CFile**************************************************************** - - FileName [casDec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] - - Synopsis [BDD-based decomposition with encoding.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Spring 2002.] - - Revision [$Id: casDec.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <time.h> - -#include "extra.h" -#include "cas.h" - -//////////////////////////////////////////////////////////////////////// -/// type definitions /// -//////////////////////////////////////////////////////////////////////// - -typedef struct -{ - int nIns; // the number of LUT variables - int nInsP; // the number of inputs coming from the previous LUT - int nCols; // the number of columns in this LUT - int nMulti; // the column multiplicity, [log2(nCols)] - int nSimple; // the number of outputs implemented as direct connections to inputs of the previous block - int Level; // the starting level in the ADD in this LUT - -// DdNode ** pbVarsIn[32]; // the BDDs of the elementary input variables -// DdNode ** pbVarsOut[32]; // the BDDs of the elementary output variables - -// char * pNamesIn[32]; // the names of input variables -// char * pNamesOut[32]; // the names of output variables - - DdNode ** pbCols; // the array of columns represented by BDDs - DdNode ** pbCodes; // the array of codes (in terms of pbVarsOut) - DdNode ** paNodes; // the array of starting ADD nodes on the next level (also referenced) - - DdNode * bRelation; // the relation after encoding - - // the relation depends on the three groups of variables: - // (1) variables on top represent the outputs of the previous cascade - // (2) variables in the middle represent the primary inputs - // (3) variables below (CVars) represent the codes - // - // the replacement is done after computing the relation -} LUT; - - -//////////////////////////////////////////////////////////////////////// -/// static functions /// -//////////////////////////////////////////////////////////////////////// - -// the LUT-2-BLIF writing function -void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName ); - -// the function to write a DD (BDD or ADD) as a network of MUXES -extern void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); -extern void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); - -//////////////////////////////////////////////////////////////////////// -/// static varibles /// -//////////////////////////////////////////////////////////////////////// - -static int s_LutSize = 15; -static int s_nFuncVars; - -long s_EncodingTime; - -long s_EncSearchTime; -long s_EncComputeTime; - -//////////////////////////////////// -// temporary output variables -//FILE * pTable; -//long s_ReadingTime; -//long s_RemappingTime; -//////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// debugging macros /// -//////////////////////////////////////////////////////////////////////// - -#define PRB(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" ) -#define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" ) -#define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" ) - - -//////////////////////////////////////////////////////////////////////// -/// EXTERNAL FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose ) -// aFunc is a 0-1 ADD for the given function -// pNames (nNames) are the input variable names -// FileName is the name of the output file for the LUT network -// dynamic variable reordering should be disabled when this function is running -{ - static LUT * pLuts[MAXINPUTS]; // the LUT cascade - static int Profile[MAXINPUTS]; // the profile filled in with the info about the BDD width - static int Permute[MAXINPUTS]; // the array to store a temporary permutation of variables - - LUT * p; // the current LUT - int i, v; - - DdNode * bCVars[32]; // these are variables for the codes - - int nVarsRem; // the number of remaining variables - int PrevMulti; // column multiplicity on the previous level - int fLastLut; // flag to signal the last LUT - int nLuts; - int nLutsTotal = 0; - int nLutOutputs = 0; - int nLutOutputsOrig = 0; - - long clk1; - - s_LutSize = nLutSize; - - s_nFuncVars = nNames; - - // get the profile - clk1 = clock(); - Extra_ProfileWidth( dd, aFunc, Profile, -1 ); - - -// for ( v = 0; v < nNames; v++ ) -// printf( "Level = %2d, Width = %2d\n", v+1, Profile[v] ); - - -//printf( "\n" ); - - // mark-up the LUTs - // assuming that the manager has exactly nNames vars (new vars have not been introduced yet) - nVarsRem = nNames; // the number of remaining variables - PrevMulti = 0; // column multiplicity on the previous level - fLastLut = 0; - nLuts = 0; - do - { - p = (LUT*) malloc( sizeof(LUT) ); - memset( p, 0, sizeof(LUT) ); - - if ( nVarsRem + PrevMulti <= s_LutSize ) // this is the last LUT - { - p->nIns = nVarsRem + PrevMulti; - p->nInsP = PrevMulti; - p->nCols = 2; - p->nMulti = 1; - p->Level = nNames-nVarsRem; - - nVarsRem = 0; - PrevMulti = 1; - - fLastLut = 1; - } - else // this is not the last LUT - { - p->nIns = s_LutSize; - p->nInsP = PrevMulti; - p->nCols = Profile[nNames-(nVarsRem-(s_LutSize-PrevMulti))]; - p->nMulti = Extra_Base2Log(p->nCols); - p->Level = nNames-nVarsRem; - - nVarsRem = nVarsRem-(s_LutSize-PrevMulti); - PrevMulti = p->nMulti; - } - - if ( p->nMulti >= s_LutSize ) - { - printf( "The LUT size is too small\n" ); - return 0; - } - - nLutOutputsOrig += p->nMulti; - - -//if ( fVerbose ) -//printf( "Stage %2d: In = %3d, InP = %3d, Cols = %5d, Multi = %2d, Level = %2d\n", -// nLuts+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->Level ); - - - // there should be as many columns, codes, and nodes, as there are columns on this level - p->pbCols = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); - p->pbCodes = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); - p->paNodes = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); - - pLuts[nLuts] = p; - nLuts++; - } - while ( !fLastLut ); - - -//if ( fVerbose ) -//printf( "The number of cascades = %d\n", nLuts ); - - -//fprintf( pTable, "%d ", nLuts ); - - - // add the new variables at the bottom - for ( i = 0; i < s_LutSize; i++ ) - bCVars[i] = Cudd_bddNewVar(dd); - - // for each LUT - assign the LUT and encode the columns - s_EncodingTime = 0; - for ( i = 0; i < nLuts; i++ ) - { - int RetValue; - DdNode * bVars[32]; - int nVars; - DdNode * bVarsInCube; - DdNode * bVarsCCube; - DdNode * bVarsCube; - int CutLevel; - - p = pLuts[i]; - - // compute the columns of this LUT starting from the given set of nodes with the given codes - // (these codes have been remapped to depend on the topmost variables in the manager) - // for the first LUT, start with the constant 1 BDD - CutLevel = p->Level + p->nIns - p->nInsP; - if ( i == 0 ) - RetValue = Extra_bddNodePathsUnderCutArray( - dd, &aFunc, &(b1), 1, - p->paNodes, p->pbCols, CutLevel ); - else - RetValue = Extra_bddNodePathsUnderCutArray( - dd, pLuts[i-1]->paNodes, pLuts[i-1]->pbCodes, pLuts[i-1]->nCols, - p->paNodes, p->pbCols, CutLevel ); - assert( RetValue == p->nCols ); - // at this point, we have filled out p->paNodes[] and p->pbCols[] of this LUT - // pLuts[i-1]->paNodes depended on normal vars - // pLuts[i-1]->pbCodes depended on the topmost variables - // the resulting p->paNodes depend on normal ADD nodes - // the resulting p->pbCols depend on normal vars and topmost variables in the manager - - // perform the encoding - - // create the cube of these variables - // collect the topmost variables of the manager - nVars = p->nInsP; - for ( v = 0; v < nVars; v++ ) - bVars[v] = dd->vars[ dd->invperm[v] ]; - bVarsCCube = Extra_bddBitsToCube( dd, (1<<nVars)-1, nVars, bVars, 1 ); Cudd_Ref( bVarsCCube ); - - // collect the primary input variables involved in this LUT - nVars = p->nIns - p->nInsP; - for ( v = 0; v < nVars; v++ ) - bVars[v] = dd->vars[ dd->invperm[p->Level+v] ]; - bVarsInCube = Extra_bddBitsToCube( dd, (1<<nVars)-1, nVars, bVars, 1 ); Cudd_Ref( bVarsInCube ); - - // get the cube - bVarsCube = Cudd_bddAnd( dd, bVarsInCube, bVarsCCube ); Cudd_Ref( bVarsCube ); - Cudd_RecursiveDeref( dd, bVarsInCube ); - Cudd_RecursiveDeref( dd, bVarsCCube ); - - // get the encoding relation - if ( i == nLuts -1 ) - { - DdNode * bVar; - assert( p->nMulti == 1 ); - assert( p->nCols == 2 ); - assert( Cudd_IsConstant( p->paNodes[0] ) ); - assert( Cudd_IsConstant( p->paNodes[1] ) ); - - bVar = ( p->paNodes[0] == a1 )? bCVars[0]: Cudd_Not( bCVars[0] ); - p->bRelation = Cudd_bddIte( dd, bVar, p->pbCols[0], p->pbCols[1] ); Cudd_Ref( p->bRelation ); - } - else - { - long clk2 = clock(); -// p->bRelation = PerformTheEncoding( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation ); - p->bRelation = Extra_bddEncodingNonStrict( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation ); - s_EncodingTime += clock() - clk2; - } - - // update the number of LUT outputs - nLutOutputs += (p->nMulti - p->nSimple); - nLutsTotal += p->nMulti; - -//if ( fVerbose ) -//printf( "Stage %2d: Simple = %d\n", i+1, p->nSimple ); - -if ( fVerbose ) -printf( "Stage %3d: In = %3d InP = %3d Cols = %5d Multi = %2d Simple = %2d Level = %3d\n", - i+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->nSimple, p->Level ); - - // get the codes from the relation (these are not necessarily cubes) - { - int c; - for ( c = 0; c < p->nCols; c++ ) - { - p->pbCodes[c] = Cudd_bddAndAbstract( dd, p->bRelation, p->pbCols[c], bVarsCube ); Cudd_Ref( p->pbCodes[c] ); - } - } - - Cudd_RecursiveDeref( dd, bVarsCube ); - - // remap the codes to depend on the topmost varibles of the manager - // useful as a preparation for the next step - { - DdNode ** pbTemp; - int k, v; - - pbTemp = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); - - // create the identical permutation - for ( v = 0; v < dd->size; v++ ) - Permute[v] = v; - - // use the topmost variables of the manager - // to represent the previous level codes - for ( v = 0; v < p->nMulti; v++ ) - Permute[bCVars[v]->index] = dd->invperm[v]; - - Extra_bddPermuteArray( dd, p->pbCodes, pbTemp, p->nCols, Permute ); - // the array pbTemp comes already referenced - - // deref the old codes and assign the new ones - for ( k = 0; k < p->nCols; k++ ) - { - Cudd_RecursiveDeref( dd, p->pbCodes[k] ); - p->pbCodes[k] = pbTemp[k]; - } - free( pbTemp ); - } - } - if ( fVerbose ) - printf( "LUTs: Total = %5d. Final = %5d. Simple = %5d. (%6.2f %%) ", - nLutsTotal, nLutOutputs, nLutsTotal-nLutOutputs, 100.0*(nLutsTotal-nLutOutputs)/nLutsTotal ); - if ( fVerbose ) - printf( "Memory = %6.2f Mb\n", 1.0*nLutOutputs*(1<<nLutSize)/(1<<20) ); -// printf( "\n" ); - -//fprintf( pTable, "%d ", nLutOutputsOrig ); -//fprintf( pTable, "%d ", nLutOutputs ); - - if ( fVerbose ) - { - printf( "Pure decomposition time = %.2f sec\n", (float)(clock() - clk1 - s_EncodingTime)/(float)(CLOCKS_PER_SEC) ); - printf( "Encoding time = %.2f sec\n", (float)(s_EncodingTime)/(float)(CLOCKS_PER_SEC) ); -// printf( "Encoding search time = %.2f sec\n", (float)(s_EncSearchTime)/(float)(CLOCKS_PER_SEC) ); -// printf( "Encoding compute time = %.2f sec\n", (float)(s_EncComputeTime)/(float)(CLOCKS_PER_SEC) ); - } - - -//fprintf( pTable, "%.2f ", (float)(s_ReadingTime)/(float)(CLOCKS_PER_SEC) ); -//fprintf( pTable, "%.2f ", (float)(clock() - clk1 - s_EncodingTime)/(float)(CLOCKS_PER_SEC) ); -//fprintf( pTable, "%.2f ", (float)(s_EncodingTime)/(float)(CLOCKS_PER_SEC) ); -//fprintf( pTable, "%.2f ", (float)(s_RemappingTime)/(float)(CLOCKS_PER_SEC) ); - - - // write LUTs into the BLIF file - clk1 = clock(); - if ( fCheck ) - { - FILE * pFile; - // start the file - pFile = fopen( FileName, "w" ); - fprintf( pFile, ".model %s\n", FileName ); - - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nNames; i++ ) - fprintf( pFile, " %s", pNames[i] ); - fprintf( pFile, "\n" ); - fprintf( pFile, ".outputs F" ); - fprintf( pFile, "\n" ); - - // write the DD into the file - WriteLUTSintoBLIFfile( pFile, dd, pLuts, nLuts, bCVars, pNames, nNames, FileName ); - - fprintf( pFile, ".end\n" ); - fclose( pFile ); - if ( fVerbose ) - printf( "Output file writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - } - - - // updo the LUT cascade - for ( i = 0; i < nLuts; i++ ) - { - p = pLuts[i]; - for ( v = 0; v < p->nCols; v++ ) - { - Cudd_RecursiveDeref( dd, p->pbCols[v] ); - Cudd_RecursiveDeref( dd, p->pbCodes[v] ); - Cudd_RecursiveDeref( dd, p->paNodes[v] ); - } - Cudd_RecursiveDeref( dd, p->bRelation ); - - free( p->pbCols ); - free( p->pbCodes ); - free( p->paNodes ); - free( p ); - } - - return 1; -} - -void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName ) -{ - int i, v, o; - static char * pNamesLocalIn[MAXINPUTS]; - static char * pNamesLocalOut[MAXINPUTS]; - static char Buffer[100]; - DdNode * bCube, * bCof, * bFunc; - LUT * p; - - // go through all the LUTs - for ( i = 0; i < nLuts; i++ ) - { - // get the pointer to the LUT - p = pLuts[i]; - - if ( i == nLuts -1 ) - { - assert( p->nMulti == 1 ); - } - - - fprintf( pFile, "#----------------- LUT #%d ----------------------\n", i ); - - - // fill in the names for the current LUT - - // write the outputs of the previous LUT - if ( i != 0 ) - for ( v = 0; v < p->nInsP; v++ ) - { - sprintf( Buffer, "LUT%02d_%02d", i-1, v ); - pNamesLocalIn[dd->invperm[v]] = Extra_UtilStrsav( Buffer ); - } - // write the primary inputs of the current LUT - for ( v = 0; v < p->nIns - p->nInsP; v++ ) - pNamesLocalIn[dd->invperm[p->Level+v]] = Extra_UtilStrsav( pNames[dd->invperm[p->Level+v]] ); - // write the outputs of the current LUT - for ( v = 0; v < p->nMulti; v++ ) - { - sprintf( Buffer, "LUT%02d_%02d", i, v ); - if ( i != nLuts - 1 ) - pNamesLocalOut[v] = Extra_UtilStrsav( Buffer ); - else - pNamesLocalOut[v] = Extra_UtilStrsav( "F" ); - } - - - // write LUT outputs - - // get the prefix - sprintf( Buffer, "L%02d_", i ); - - // get the cube of encoding variables - bCube = Extra_bddBitsToCube( dd, (1<<p->nMulti)-1, p->nMulti, bCVars, 1 ); Cudd_Ref( bCube ); - - // write each output of the LUT - for ( o = 0; o < p->nMulti; o++ ) - { - // get the cofactor of this output - bCof = Cudd_Cofactor( dd, p->bRelation, bCVars[o] ); Cudd_Ref( bCof ); - // quantify the remaining variables to get the function - bFunc = Cudd_bddExistAbstract( dd, bCof, bCube ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bCof ); - - // write BLIF - sprintf( Buffer, "L%02d_%02d_", i, o ); - -// WriteDDintoBLIFfileReorder( dd, pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn ); - // does not work well; the advantage is marginal (30%), the run time is huge... - - WriteDDintoBLIFfile( pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn ); - Cudd_RecursiveDeref( dd, bFunc ); - } - Cudd_RecursiveDeref( dd, bCube ); - - // clean up the previous local names - for ( v = 0; v < dd->size; v++ ) - { - if ( pNamesLocalIn[v] ) - free( pNamesLocalIn[v] ); - pNamesLocalIn[v] = NULL; - } - for ( v = 0; v < p->nMulti; v++ ) - free( pNamesLocalOut[v] ); - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - - diff --git a/src/bdd/cas/module.make b/src/bdd/cas/module.make deleted file mode 100644 index 7830e47f..00000000 --- a/src/bdd/cas/module.make +++ /dev/null @@ -1,3 +0,0 @@ -SRC += src/bdd/cas/casCore.c \ - src/bdd/cas/casDec.c - diff --git a/src/bdd/cudd/cuBdd.make b/src/bdd/cudd/cuBdd.make deleted file mode 100644 index b16a27b3..00000000 --- a/src/bdd/cudd/cuBdd.make +++ /dev/null @@ -1,41 +0,0 @@ -CSRC_cu += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \ - cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \ - cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c \ - cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \ - cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \ - cuddExport.c cuddGenCof.c cuddGenetic.c \ - cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \ - cuddLCache.c cuddLevelQ.c \ - cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \ - cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \ - cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \ - cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \ - cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \ - cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c -HEADERS_cu += cudd.h cuddInt.h -MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html doc/cuddAllDet.html \ - doc/cuddExtAbs.html doc/cuddExtDet.html doc/cuddIntro.css \ - doc/cuddIntro.html doc/footnode.html doc/img1.gif doc/img2.gif \ - doc/img3.gif doc/img4.gif doc/img5.gif doc/index.html \ - doc/node1.html doc/node2.html doc/node3.html doc/node4.html \ - doc/node5.html doc/node6.html doc/node7.html doc/node8.html \ - doc/icons/change_begin.gif \ - doc/icons/change_delete.gif \ - doc/icons/change_end.gif \ - doc/icons/contents_motif.gif \ - doc/icons/cross_ref_motif.gif \ - doc/icons/foot_motif.gif \ - doc/icons/image.gif \ - doc/icons/index_motif.gif \ - doc/icons/next_group_motif.gif \ - doc/icons/next_group_motif_gr.gif \ - doc/icons/next_motif.gif \ - doc/icons/next_motif_gr.gif \ - doc/icons/previous_group_motif.gif \ - doc/icons/previous_group_motif_gr.gif \ - doc/icons/previous_motif.gif \ - doc/icons/previous_motif_gr.gif \ - doc/icons/up_motif.gif \ - doc/icons/up_motif_gr.gif - -DEPENDENCYFILES = $(CSRC_cu) diff --git a/src/bdd/cudd/cudd.h b/src/bdd/cudd/cudd.h deleted file mode 100644 index a31fcdae..00000000 --- a/src/bdd/cudd/cudd.h +++ /dev/null @@ -1,959 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [cudd.h] - - PackageName [cudd] - - Synopsis [The University of Colorado decision diagram package.] - - Description [External functions and data strucures of the CUDD package. - <ul> - <li> To turn on the gathering of statistics, define DD_STATS. - <li> To link with mis, define DD_MIS. - </ul> - Modified by Abelardo Pardo to interface it to VIS. - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: cudd.h,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $] - -******************************************************************************/ - -#ifndef _CUDD -#define _CUDD - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - -#include "mtr.h" -#include "epd.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define CUDD_VERSION "2.3.1" - -#ifndef SIZEOF_VOID_P -#define SIZEOF_VOID_P 4 -#endif -#ifndef SIZEOF_INT -#define SIZEOF_INT 4 -#endif -#ifndef SIZEOF_LONG -#define SIZEOF_LONG 4 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define CUDD_VALUE_TYPE double -#define CUDD_OUT_OF_MEM -1 -/* The sizes of the subtables and the cache must be powers of two. */ -#define CUDD_UNIQUE_SLOTS 256 /* initial size of subtables */ -#define CUDD_CACHE_SLOTS 262144 /* default size of the cache */ - -/* Constants for residue functions. */ -#define CUDD_RESIDUE_DEFAULT 0 -#define CUDD_RESIDUE_MSB 1 -#define CUDD_RESIDUE_TC 2 - -/* CUDD_MAXINDEX is defined in such a way that on 32-bit and 64-bit -** machines one can cast an index to (int) without generating a negative -** number. -*/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define CUDD_MAXINDEX (((DdHalfWord) ~0) >> 1) -#else -#define CUDD_MAXINDEX ((DdHalfWord) ~0) -#endif - -/* CUDD_CONST_INDEX is the index of constant nodes. Currently this -** is a synonim for CUDD_MAXINDEX. */ -#define CUDD_CONST_INDEX CUDD_MAXINDEX - -/* These constants define the digits used in the representation of -** arbitrary precision integers. The two configurations tested use 8 -** and 16 bits for each digit. The typedefs should be in agreement -** with these definitions. -*/ -#define DD_APA_BITS 16 -#define DD_APA_BASE (1 << DD_APA_BITS) -#define DD_APA_MASK (DD_APA_BASE - 1) -#define DD_APA_HEXPRINT "%04x" - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/**Enum************************************************************************ - - Synopsis [Type of reordering algorithm.] - - Description [Type of reordering algorithm.] - -******************************************************************************/ -typedef enum { - CUDD_REORDER_SAME, - CUDD_REORDER_NONE, - CUDD_REORDER_RANDOM, - CUDD_REORDER_RANDOM_PIVOT, - CUDD_REORDER_SIFT, - CUDD_REORDER_SIFT_CONVERGE, - CUDD_REORDER_SYMM_SIFT, - CUDD_REORDER_SYMM_SIFT_CONV, - CUDD_REORDER_WINDOW2, - CUDD_REORDER_WINDOW3, - CUDD_REORDER_WINDOW4, - CUDD_REORDER_WINDOW2_CONV, - CUDD_REORDER_WINDOW3_CONV, - CUDD_REORDER_WINDOW4_CONV, - CUDD_REORDER_GROUP_SIFT, - CUDD_REORDER_GROUP_SIFT_CONV, - CUDD_REORDER_ANNEALING, - CUDD_REORDER_GENETIC, - CUDD_REORDER_LINEAR, - CUDD_REORDER_LINEAR_CONVERGE, - CUDD_REORDER_LAZY_SIFT, - CUDD_REORDER_EXACT -} Cudd_ReorderingType; - - -/**Enum************************************************************************ - - Synopsis [Type of aggregation methods.] - - Description [Type of aggregation methods.] - -******************************************************************************/ -typedef enum { - CUDD_NO_CHECK, - CUDD_GROUP_CHECK, - CUDD_GROUP_CHECK2, - CUDD_GROUP_CHECK3, - CUDD_GROUP_CHECK4, - CUDD_GROUP_CHECK5, - CUDD_GROUP_CHECK6, - CUDD_GROUP_CHECK7, - CUDD_GROUP_CHECK8, - CUDD_GROUP_CHECK9 -} Cudd_AggregationType; - - -/**Enum************************************************************************ - - Synopsis [Type of hooks.] - - Description [Type of hooks.] - -******************************************************************************/ -typedef enum { - CUDD_PRE_GC_HOOK, - CUDD_POST_GC_HOOK, - CUDD_PRE_REORDERING_HOOK, - CUDD_POST_REORDERING_HOOK -} Cudd_HookType; - - -/**Enum************************************************************************ - - Synopsis [Type of error codes.] - - Description [Type of error codes.] - -******************************************************************************/ -typedef enum { - CUDD_NO_ERROR, - CUDD_MEMORY_OUT, - CUDD_TOO_MANY_NODES, - CUDD_MAX_MEM_EXCEEDED, - CUDD_INVALID_ARG, - CUDD_INTERNAL_ERROR -} Cudd_ErrorType; - - -/**Enum************************************************************************ - - Synopsis [Group type for lazy sifting.] - - Description [Group type for lazy sifting.] - -******************************************************************************/ -typedef enum { - CUDD_LAZY_NONE, - CUDD_LAZY_SOFT_GROUP, - CUDD_LAZY_HARD_GROUP, - CUDD_LAZY_UNGROUP -} Cudd_LazyGroupType; - - -/**Enum************************************************************************ - - Synopsis [Variable type.] - - Description [Variable type. Currently used only in lazy sifting.] - -******************************************************************************/ -typedef enum { - CUDD_VAR_PRIMARY_INPUT, - CUDD_VAR_PRESENT_STATE, - CUDD_VAR_NEXT_STATE -} Cudd_VariableType; - - -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -typedef unsigned int DdHalfWord; -#else -typedef unsigned short DdHalfWord; -#endif - -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - -typedef struct DdNode DdNode; - -typedef struct DdChildren { - struct DdNode *T; - struct DdNode *E; -} DdChildren; - -/* The DdNode structure is the only one exported out of the package */ -struct DdNode { - DdHalfWord index; - DdHalfWord ref; /* reference count */ - DdNode *next; /* next pointer for unique table */ - union { - CUDD_VALUE_TYPE value; /* for constant nodes */ - DdChildren kids; /* for internal nodes */ - } type; -}; - -#ifdef __osf__ -#pragma pointer_size restore -#endif - -typedef struct DdManager DdManager; - -typedef struct DdGen DdGen; - -/* These typedefs for arbitrary precision arithmetic should agree with -** the corresponding constant definitions above. */ -typedef unsigned short int DdApaDigit; -typedef unsigned long int DdApaDoubleDigit; -typedef DdApaDigit * DdApaNumber; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**Macro*********************************************************************** - - Synopsis [Returns 1 if the node is a constant node.] - - Description [Returns 1 if the node is a constant node (rather than an - internal node). All constant nodes have the same index - (CUDD_CONST_INDEX). The pointer passed to Cudd_IsConstant may be either - regular or complemented.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -#define Cudd_IsConstant(node) ((Cudd_Regular(node))->index == CUDD_CONST_INDEX) - - -/**Macro*********************************************************************** - - Synopsis [Complements a DD.] - - Description [Complements a DD by flipping the complement attribute of - the pointer (the least significant bit).] - - SideEffects [none] - - SeeAlso [Cudd_NotCond] - -******************************************************************************/ -#define Cudd_Not(node) ((DdNode *)((long)(node) ^ 01)) - - -/**Macro*********************************************************************** - - Synopsis [Complements a DD if a condition is true.] - - Description [Complements a DD if condition c is true; c should be - either 0 or 1, because it is used directly (for efficiency). If in - doubt on the values c may take, use "(c) ? Cudd_Not(node) : node".] - - SideEffects [none] - - SeeAlso [Cudd_Not] - -******************************************************************************/ -#define Cudd_NotCond(node,c) ((DdNode *)((long)(node) ^ (c))) - - -/**Macro*********************************************************************** - - Synopsis [Returns the regular version of a pointer.] - - Description [] - - SideEffects [none] - - SeeAlso [Cudd_Complement Cudd_IsComplement] - -******************************************************************************/ -#define Cudd_Regular(node) ((DdNode *)((unsigned long)(node) & ~01)) - - -/**Macro*********************************************************************** - - Synopsis [Returns the complemented version of a pointer.] - - Description [] - - SideEffects [none] - - SeeAlso [Cudd_Regular Cudd_IsComplement] - -******************************************************************************/ -#define Cudd_Complement(node) ((DdNode *)((unsigned long)(node) | 01)) - - -/**Macro*********************************************************************** - - Synopsis [Returns 1 if a pointer is complemented.] - - Description [] - - SideEffects [none] - - SeeAlso [Cudd_Regular Cudd_Complement] - -******************************************************************************/ -#define Cudd_IsComplement(node) ((int) ((long) (node) & 01)) - - -/**Macro*********************************************************************** - - Synopsis [Returns the then child of an internal node.] - - Description [Returns the then child of an internal node. If - <code>node</code> is a constant node, the result is unpredictable.] - - SideEffects [none] - - SeeAlso [Cudd_E Cudd_V] - -******************************************************************************/ -#define Cudd_T(node) ((Cudd_Regular(node))->type.kids.T) - - -/**Macro*********************************************************************** - - Synopsis [Returns the else child of an internal node.] - - Description [Returns the else child of an internal node. If - <code>node</code> is a constant node, the result is unpredictable.] - - SideEffects [none] - - SeeAlso [Cudd_T Cudd_V] - -******************************************************************************/ -#define Cudd_E(node) ((Cudd_Regular(node))->type.kids.E) - - -/**Macro*********************************************************************** - - Synopsis [Returns the value of a constant node.] - - Description [Returns the value of a constant node. If - <code>node</code> is an internal node, the result is unpredictable.] - - SideEffects [none] - - SeeAlso [Cudd_T Cudd_E] - -******************************************************************************/ -#define Cudd_V(node) ((Cudd_Regular(node))->type.value) - - -/**Macro*********************************************************************** - - Synopsis [Returns the current position in the order of variable - index.] - - Description [Returns the current position in the order of variable - index. This macro is obsolete and is kept for compatibility. New - applications should use Cudd_ReadPerm instead.] - - SideEffects [none] - - SeeAlso [Cudd_ReadPerm] - -******************************************************************************/ -#define Cudd_ReadIndex(dd,index) (Cudd_ReadPerm(dd,index)) - - -/**Macro*********************************************************************** - - Synopsis [Iterates over the cubes of a decision diagram.] - - Description [Iterates over the cubes of a decision diagram f. - <ul> - <li> DdManager *manager; - <li> DdNode *f; - <li> DdGen *gen; - <li> int *cube; - <li> CUDD_VALUE_TYPE value; - </ul> - Cudd_ForeachCube allocates and frees the generator. Therefore the - application should not try to do that. Also, the cube is freed at the - end of Cudd_ForeachCube and hence is not available outside of the loop.<p> - CAUTION: It is assumed that dynamic reordering will not occur while - there are open generators. It is the user's responsibility to make sure - that dynamic reordering does not occur. As long as new nodes are not created - during generation, and dynamic reordering is not called explicitly, - dynamic reordering will not occur. Alternatively, it is sufficient to - disable dynamic reordering. It is a mistake to dispose of a diagram - on which generation is ongoing.] - - SideEffects [none] - - SeeAlso [Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube Cudd_GenFree - Cudd_IsGenEmpty Cudd_AutodynDisable] - -******************************************************************************/ -#define Cudd_ForeachCube(manager, f, gen, cube, value)\ - for((gen) = Cudd_FirstCube(manager, f, &cube, &value);\ - Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ - (void) Cudd_NextCube(gen, &cube, &value)) - - -/**Macro*********************************************************************** - - Synopsis [Iterates over the nodes of a decision diagram.] - - Description [Iterates over the nodes of a decision diagram f. - <ul> - <li> DdManager *manager; - <li> DdNode *f; - <li> DdGen *gen; - <li> DdNode *node; - </ul> - The nodes are returned in a seemingly random order. - Cudd_ForeachNode allocates and frees the generator. Therefore the - application should not try to do that.<p> - CAUTION: It is assumed that dynamic reordering will not occur while - there are open generators. It is the user's responsibility to make sure - that dynamic reordering does not occur. As long as new nodes are not created - during generation, and dynamic reordering is not called explicitly, - dynamic reordering will not occur. Alternatively, it is sufficient to - disable dynamic reordering. It is a mistake to dispose of a diagram - on which generation is ongoing.] - - SideEffects [none] - - SeeAlso [Cudd_ForeachCube Cudd_FirstNode Cudd_NextNode Cudd_GenFree - Cudd_IsGenEmpty Cudd_AutodynDisable] - -******************************************************************************/ -#define Cudd_ForeachNode(manager, f, gen, node)\ - for((gen) = Cudd_FirstNode(manager, f, &node);\ - Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ - (void) Cudd_NextNode(gen, &node)) - - -/**Macro*********************************************************************** - - Synopsis [Iterates over the paths of a ZDD.] - - Description [Iterates over the paths of a ZDD f. - <ul> - <li> DdManager *manager; - <li> DdNode *f; - <li> DdGen *gen; - <li> int *path; - </ul> - Cudd_zddForeachPath allocates and frees the generator. Therefore the - application should not try to do that. Also, the path is freed at the - end of Cudd_zddForeachPath and hence is not available outside of the loop.<p> - CAUTION: It is assumed that dynamic reordering will not occur while - there are open generators. It is the user's responsibility to make sure - that dynamic reordering does not occur. As long as new nodes are not created - during generation, and dynamic reordering is not called explicitly, - dynamic reordering will not occur. Alternatively, it is sufficient to - disable dynamic reordering. It is a mistake to dispose of a diagram - on which generation is ongoing.] - - SideEffects [none] - - SeeAlso [Cudd_zddFirstPath Cudd_zddNextPath Cudd_GenFree - Cudd_IsGenEmpty Cudd_AutodynDisable] - -******************************************************************************/ -#define Cudd_zddForeachPath(manager, f, gen, path)\ - for((gen) = Cudd_zddFirstPath(manager, f, &path);\ - Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ - (void) Cudd_zddNextPath(gen, &path)) - - -/* These are potential duplicates. */ -#ifndef EXTERN -# ifdef __cplusplus -# define EXTERN extern "C" -# else -# define EXTERN extern -# endif -#endif -#ifndef ARGS -# if defined(__STDC__) || defined(__cplusplus) -# define ARGS(protos) protos /* ANSI C */ -# else /* !(__STDC__ || __cplusplus) */ -# define ARGS(protos) () /* K&R C */ -# endif /* !(__STDC__ || __cplusplus) */ -#endif - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - -EXTERN DdNode * Cudd_addNewVar ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_addNewVarAtLevel ARGS((DdManager *dd, int level)); -EXTERN DdNode * Cudd_bddNewVar ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_bddNewVarAtLevel ARGS((DdManager *dd, int level)); -EXTERN DdNode * Cudd_addIthVar ARGS((DdManager *dd, int i)); -EXTERN DdNode * Cudd_bddIthVar ARGS((DdManager *dd, int i)); -EXTERN DdNode * Cudd_zddIthVar ARGS((DdManager *dd, int i)); -EXTERN int Cudd_zddVarsFromBddVars ARGS((DdManager *dd, int multiplicity)); -EXTERN DdNode * Cudd_addConst ARGS((DdManager *dd, CUDD_VALUE_TYPE c)); -EXTERN int Cudd_IsNonConstant ARGS((DdNode *f)); -EXTERN void Cudd_AutodynEnable ARGS((DdManager *unique, Cudd_ReorderingType method)); -EXTERN void Cudd_AutodynDisable ARGS((DdManager *unique)); -EXTERN int Cudd_ReorderingStatus ARGS((DdManager *unique, Cudd_ReorderingType *method)); -EXTERN void Cudd_AutodynEnableZdd ARGS((DdManager *unique, Cudd_ReorderingType method)); -EXTERN void Cudd_AutodynDisableZdd ARGS((DdManager *unique)); -EXTERN int Cudd_ReorderingStatusZdd ARGS((DdManager *unique, Cudd_ReorderingType *method)); -EXTERN int Cudd_zddRealignmentEnabled ARGS((DdManager *unique)); -EXTERN void Cudd_zddRealignEnable ARGS((DdManager *unique)); -EXTERN void Cudd_zddRealignDisable ARGS((DdManager *unique)); -EXTERN int Cudd_bddRealignmentEnabled ARGS((DdManager *unique)); -EXTERN void Cudd_bddRealignEnable ARGS((DdManager *unique)); -EXTERN void Cudd_bddRealignDisable ARGS((DdManager *unique)); -EXTERN DdNode * Cudd_ReadOne ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_ReadZddOne ARGS((DdManager *dd, int i)); -EXTERN DdNode * Cudd_ReadZero ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_ReadLogicZero ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_ReadPlusInfinity ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_ReadMinusInfinity ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_ReadBackground ARGS((DdManager *dd)); -EXTERN void Cudd_SetBackground ARGS((DdManager *dd, DdNode *bck)); -EXTERN unsigned int Cudd_ReadCacheSlots ARGS((DdManager *dd)); -EXTERN double Cudd_ReadCacheUsedSlots ARGS((DdManager * dd)); -EXTERN double Cudd_ReadCacheLookUps ARGS((DdManager *dd)); -EXTERN double Cudd_ReadCacheHits ARGS((DdManager *dd)); -EXTERN double Cudd_ReadRecursiveCalls ARGS ((DdManager * dd)); -EXTERN unsigned int Cudd_ReadMinHit ARGS((DdManager *dd)); -EXTERN void Cudd_SetMinHit ARGS((DdManager *dd, unsigned int hr)); -EXTERN unsigned int Cudd_ReadLooseUpTo ARGS((DdManager *dd)); -EXTERN void Cudd_SetLooseUpTo ARGS((DdManager *dd, unsigned int lut)); -EXTERN unsigned int Cudd_ReadMaxCache ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_ReadMaxCacheHard ARGS((DdManager *dd)); -EXTERN void Cudd_SetMaxCacheHard ARGS((DdManager *dd, unsigned int mc)); -EXTERN int Cudd_ReadSize ARGS((DdManager *dd)); -EXTERN int Cudd_ReadZddSize ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_ReadSlots ARGS((DdManager *dd)); -EXTERN double Cudd_ReadUsedSlots ARGS((DdManager * dd)); -EXTERN double Cudd_ExpectedUsedSlots ARGS((DdManager * dd)); -EXTERN unsigned int Cudd_ReadKeys ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_ReadDead ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_ReadMinDead ARGS((DdManager *dd)); -EXTERN int Cudd_ReadReorderings ARGS((DdManager *dd)); -EXTERN long Cudd_ReadReorderingTime ARGS((DdManager * dd)); -EXTERN int Cudd_ReadGarbageCollections ARGS((DdManager * dd)); -EXTERN long Cudd_ReadGarbageCollectionTime ARGS((DdManager * dd)); -EXTERN double Cudd_ReadNodesFreed ARGS((DdManager * dd)); -EXTERN double Cudd_ReadNodesDropped ARGS((DdManager * dd)); -EXTERN double Cudd_ReadUniqueLookUps ARGS((DdManager * dd)); -EXTERN double Cudd_ReadUniqueLinks ARGS((DdManager * dd)); -EXTERN int Cudd_ReadSiftMaxVar ARGS((DdManager *dd)); -EXTERN void Cudd_SetSiftMaxVar ARGS((DdManager *dd, int smv)); -EXTERN int Cudd_ReadSiftMaxSwap ARGS((DdManager *dd)); -EXTERN void Cudd_SetSiftMaxSwap ARGS((DdManager *dd, int sms)); -EXTERN double Cudd_ReadMaxGrowth ARGS((DdManager *dd)); -EXTERN void Cudd_SetMaxGrowth ARGS((DdManager *dd, double mg)); -EXTERN double Cudd_ReadMaxGrowthAlternate ARGS((DdManager * dd)); -EXTERN void Cudd_SetMaxGrowthAlternate ARGS((DdManager * dd, double mg)); -EXTERN int Cudd_ReadReorderingCycle ARGS((DdManager * dd)); -EXTERN void Cudd_SetReorderingCycle ARGS((DdManager * dd, int cycle)); -EXTERN MtrNode * Cudd_ReadTree ARGS((DdManager *dd)); -EXTERN void Cudd_SetTree ARGS((DdManager *dd, MtrNode *tree)); -EXTERN void Cudd_FreeTree ARGS((DdManager *dd)); -EXTERN MtrNode * Cudd_ReadZddTree ARGS((DdManager *dd)); -EXTERN void Cudd_SetZddTree ARGS((DdManager *dd, MtrNode *tree)); -EXTERN void Cudd_FreeZddTree ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_NodeReadIndex ARGS((DdNode *node)); -EXTERN int Cudd_ReadPerm ARGS((DdManager *dd, int i)); -EXTERN int Cudd_ReadPermZdd ARGS((DdManager *dd, int i)); -EXTERN int Cudd_ReadInvPerm ARGS((DdManager *dd, int i)); -EXTERN int Cudd_ReadInvPermZdd ARGS((DdManager *dd, int i)); -EXTERN DdNode * Cudd_ReadVars ARGS((DdManager *dd, int i)); -EXTERN CUDD_VALUE_TYPE Cudd_ReadEpsilon ARGS((DdManager *dd)); -EXTERN void Cudd_SetEpsilon ARGS((DdManager *dd, CUDD_VALUE_TYPE ep)); -EXTERN Cudd_AggregationType Cudd_ReadGroupcheck ARGS((DdManager *dd)); -EXTERN void Cudd_SetGroupcheck ARGS((DdManager *dd, Cudd_AggregationType gc)); -EXTERN int Cudd_GarbageCollectionEnabled ARGS((DdManager *dd)); -EXTERN void Cudd_EnableGarbageCollection ARGS((DdManager *dd)); -EXTERN void Cudd_DisableGarbageCollection ARGS((DdManager *dd)); -EXTERN int Cudd_DeadAreCounted ARGS((DdManager *dd)); -EXTERN void Cudd_TurnOnCountDead ARGS((DdManager *dd)); -EXTERN void Cudd_TurnOffCountDead ARGS((DdManager *dd)); -EXTERN int Cudd_ReadRecomb ARGS((DdManager *dd)); -EXTERN void Cudd_SetRecomb ARGS((DdManager *dd, int recomb)); -EXTERN int Cudd_ReadSymmviolation ARGS((DdManager *dd)); -EXTERN void Cudd_SetSymmviolation ARGS((DdManager *dd, int symmviolation)); -EXTERN int Cudd_ReadArcviolation ARGS((DdManager *dd)); -EXTERN void Cudd_SetArcviolation ARGS((DdManager *dd, int arcviolation)); -EXTERN int Cudd_ReadPopulationSize ARGS((DdManager *dd)); -EXTERN void Cudd_SetPopulationSize ARGS((DdManager *dd, int populationSize)); -EXTERN int Cudd_ReadNumberXovers ARGS((DdManager *dd)); -EXTERN void Cudd_SetNumberXovers ARGS((DdManager *dd, int numberXovers)); -EXTERN long Cudd_ReadMemoryInUse ARGS((DdManager *dd)); -EXTERN int Cudd_PrintInfo ARGS((DdManager *dd, FILE *fp)); -EXTERN long Cudd_ReadPeakNodeCount ARGS((DdManager *dd)); -EXTERN int Cudd_ReadPeakLiveNodeCount ARGS((DdManager * dd)); -EXTERN long Cudd_ReadNodeCount ARGS((DdManager *dd)); -EXTERN long Cudd_zddReadNodeCount ARGS((DdManager *dd)); -EXTERN int Cudd_AddHook ARGS((DdManager *dd, int (*f)(DdManager *, char *, void *), Cudd_HookType where)); -EXTERN int Cudd_RemoveHook ARGS((DdManager *dd, int (*f)(DdManager *, char *, void *), Cudd_HookType where)); -EXTERN int Cudd_IsInHook ARGS((DdManager * dd, int (*f)(DdManager *, char *, void *), Cudd_HookType where)); -EXTERN int Cudd_StdPreReordHook ARGS((DdManager *dd, char *str, void *data)); -EXTERN int Cudd_StdPostReordHook ARGS((DdManager *dd, char *str, void *data)); -EXTERN int Cudd_EnableReorderingReporting ARGS((DdManager *dd)); -EXTERN int Cudd_DisableReorderingReporting ARGS((DdManager *dd)); -EXTERN int Cudd_ReorderingReporting ARGS((DdManager *dd)); -EXTERN Cudd_ErrorType Cudd_ReadErrorCode ARGS((DdManager *dd)); -EXTERN void Cudd_ClearErrorCode ARGS((DdManager *dd)); -EXTERN FILE * Cudd_ReadStdout ARGS((DdManager *dd)); -EXTERN void Cudd_SetStdout ARGS((DdManager *dd, FILE *fp)); -EXTERN FILE * Cudd_ReadStderr ARGS((DdManager *dd)); -EXTERN void Cudd_SetStderr ARGS((DdManager *dd, FILE *fp)); -EXTERN unsigned int Cudd_ReadNextReordering ARGS((DdManager *dd)); -EXTERN void Cudd_SetNextReordering ARGS((DdManager *dd, unsigned int next)); -EXTERN double Cudd_ReadSwapSteps ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_ReadMaxLive ARGS((DdManager *dd)); -EXTERN void Cudd_SetMaxLive ARGS((DdManager *dd, unsigned int maxLive)); -EXTERN long Cudd_ReadMaxMemory ARGS((DdManager *dd)); -EXTERN void Cudd_SetMaxMemory ARGS((DdManager *dd, long maxMemory)); -EXTERN int Cudd_bddBindVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddUnbindVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddVarIsBound ARGS((DdManager *dd, int index)); -EXTERN DdNode * Cudd_addExistAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * Cudd_addUnivAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * Cudd_addOrAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * Cudd_addApply ARGS((DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_addPlus ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addTimes ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addThreshold ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addSetNZ ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addDivide ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addMinus ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addMinimum ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addMaximum ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addOneZeroMaximum ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addDiff ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addAgreement ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addOr ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addNand ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addNor ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addXor ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addXnor ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addMonadicApply ARGS((DdManager * dd, DdNode * (*op)(DdManager *, DdNode *), DdNode * f)); -EXTERN DdNode * Cudd_addLog ARGS((DdManager * dd, DdNode * f)); -EXTERN DdNode * Cudd_addFindMax ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_addFindMin ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_addIthBit ARGS((DdManager *dd, DdNode *f, int bit)); -EXTERN DdNode * Cudd_addScalarInverse ARGS((DdManager *dd, DdNode *f, DdNode *epsilon)); -EXTERN DdNode * Cudd_addIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * Cudd_addIteConstant ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * Cudd_addEvalConst ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN int Cudd_addLeq ARGS((DdManager * dd, DdNode * f, DdNode * g)); -EXTERN DdNode * Cudd_addCmpl ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_addNegate ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_addRoundOff ARGS((DdManager *dd, DdNode *f, int N)); -EXTERN DdNode * Cudd_addWalsh ARGS((DdManager *dd, DdNode **x, DdNode **y, int n)); -EXTERN DdNode * Cudd_addResidue ARGS((DdManager *dd, int n, int m, int options, int top)); -EXTERN DdNode * Cudd_bddAndAbstract ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); -EXTERN int Cudd_ApaNumberOfDigits ARGS((int binaryDigits)); -EXTERN DdApaNumber Cudd_NewApaNumber ARGS((int digits)); -EXTERN void Cudd_ApaCopy ARGS((int digits, DdApaNumber source, DdApaNumber dest)); -EXTERN DdApaDigit Cudd_ApaAdd ARGS((int digits, DdApaNumber a, DdApaNumber b, DdApaNumber sum)); -EXTERN DdApaDigit Cudd_ApaSubtract ARGS((int digits, DdApaNumber a, DdApaNumber b, DdApaNumber diff)); -EXTERN DdApaDigit Cudd_ApaShortDivision ARGS((int digits, DdApaNumber dividend, DdApaDigit divisor, DdApaNumber quotient)); -EXTERN unsigned int Cudd_ApaIntDivision ARGS((int digits, DdApaNumber dividend, unsigned int divisor, DdApaNumber quotient)); -EXTERN void Cudd_ApaShiftRight ARGS((int digits, DdApaDigit in, DdApaNumber a, DdApaNumber b)); -EXTERN void Cudd_ApaSetToLiteral ARGS((int digits, DdApaNumber number, DdApaDigit literal)); -EXTERN void Cudd_ApaPowerOfTwo ARGS((int digits, DdApaNumber number, int power)); -EXTERN int Cudd_ApaCompare ARGS((int digitsFirst, DdApaNumber first, int digitsSecond, DdApaNumber second)); -EXTERN int Cudd_ApaCompareRatios ARGS ((int digitsFirst, DdApaNumber firstNum, unsigned int firstDen, int digitsSecond, DdApaNumber secondNum, unsigned int secondDen)); -EXTERN int Cudd_ApaPrintHex ARGS((FILE *fp, int digits, DdApaNumber number)); -EXTERN int Cudd_ApaPrintDecimal ARGS((FILE *fp, int digits, DdApaNumber number)); -EXTERN int Cudd_ApaPrintExponential ARGS((FILE * fp, int digits, DdApaNumber number, int precision)); -EXTERN DdApaNumber Cudd_ApaCountMinterm ARGS((DdManager *manager, DdNode *node, int nvars, int *digits)); -EXTERN int Cudd_ApaPrintMinterm ARGS((FILE *fp, DdManager *dd, DdNode *node, int nvars)); -EXTERN int Cudd_ApaPrintMintermExp ARGS((FILE * fp, DdManager * dd, DdNode * node, int nvars, int precision)); -EXTERN int Cudd_ApaPrintDensity ARGS((FILE * fp, DdManager * dd, DdNode * node, int nvars)); -EXTERN DdNode * Cudd_UnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality)); -EXTERN DdNode * Cudd_OverApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality)); -EXTERN DdNode * Cudd_RemapUnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, double quality)); -EXTERN DdNode * Cudd_RemapOverApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, double quality)); -EXTERN DdNode * Cudd_BiasedUnderApprox ARGS((DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0)); -EXTERN DdNode * Cudd_BiasedOverApprox ARGS((DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0)); -EXTERN DdNode * Cudd_bddExistAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * Cudd_bddXorExistAbstract ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); -EXTERN DdNode * Cudd_bddUnivAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * Cudd_bddBooleanDiff ARGS((DdManager *manager, DdNode *f, int x)); -EXTERN int Cudd_bddVarIsDependent ARGS((DdManager *dd, DdNode *f, DdNode *var)); -EXTERN double Cudd_bddCorrelation ARGS((DdManager *manager, DdNode *f, DdNode *g)); -EXTERN double Cudd_bddCorrelationWeights ARGS((DdManager *manager, DdNode *f, DdNode *g, double *prob)); -EXTERN DdNode * Cudd_bddIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * Cudd_bddIteConstant ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * Cudd_bddIntersect ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddAnd ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddOr ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddNand ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddNor ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddXor ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddXnor ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN int Cudd_bddLeq ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_addBddThreshold ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE value)); -EXTERN DdNode * Cudd_addBddStrictThreshold ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE value)); -EXTERN DdNode * Cudd_addBddInterval ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE lower, CUDD_VALUE_TYPE upper)); -EXTERN DdNode * Cudd_addBddIthBit ARGS((DdManager *dd, DdNode *f, int bit)); -EXTERN DdNode * Cudd_BddToAdd ARGS((DdManager *dd, DdNode *B)); -EXTERN DdNode * Cudd_addBddPattern ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_bddTransfer ARGS((DdManager *ddSource, DdManager *ddDestination, DdNode *f)); -EXTERN int Cudd_DebugCheck ARGS((DdManager *table)); -EXTERN int Cudd_CheckKeys ARGS((DdManager *table)); -EXTERN DdNode * Cudd_bddClippingAnd ARGS((DdManager *dd, DdNode *f, DdNode *g, int maxDepth, int direction)); -EXTERN DdNode * Cudd_bddClippingAndAbstract ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *cube, int maxDepth, int direction)); -EXTERN DdNode * Cudd_Cofactor ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddCompose ARGS((DdManager *dd, DdNode *f, DdNode *g, int v)); -EXTERN DdNode * Cudd_addCompose ARGS((DdManager *dd, DdNode *f, DdNode *g, int v)); -EXTERN DdNode * Cudd_addPermute ARGS((DdManager *manager, DdNode *node, int *permut)); -EXTERN DdNode * Cudd_addSwapVariables ARGS((DdManager *dd, DdNode *f, DdNode **x, DdNode **y, int n)); -EXTERN DdNode * Cudd_bddPermute ARGS((DdManager *manager, DdNode *node, int *permut)); -EXTERN DdNode * Cudd_bddVarMap ARGS((DdManager *manager, DdNode *f)); -EXTERN int Cudd_SetVarMap ARGS((DdManager *manager, DdNode **x, DdNode **y, int n)); -EXTERN DdNode * Cudd_bddSwapVariables ARGS((DdManager *dd, DdNode *f, DdNode **x, DdNode **y, int n)); -EXTERN DdNode * Cudd_bddAdjPermuteX ARGS((DdManager *dd, DdNode *B, DdNode **x, int n)); -EXTERN DdNode * Cudd_addVectorCompose ARGS((DdManager *dd, DdNode *f, DdNode **vector)); -EXTERN DdNode * Cudd_addGeneralVectorCompose ARGS((DdManager *dd, DdNode *f, DdNode **vectorOn, DdNode **vectorOff)); -EXTERN DdNode * Cudd_addNonSimCompose ARGS((DdManager *dd, DdNode *f, DdNode **vector)); -EXTERN DdNode * Cudd_bddVectorCompose ARGS((DdManager *dd, DdNode *f, DdNode **vector)); -EXTERN int Cudd_bddApproxConjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***conjuncts)); -EXTERN int Cudd_bddApproxDisjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***disjuncts)); -EXTERN int Cudd_bddIterConjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***conjuncts)); -EXTERN int Cudd_bddIterDisjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***disjuncts)); -EXTERN int Cudd_bddGenConjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***conjuncts)); -EXTERN int Cudd_bddGenDisjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***disjuncts)); -EXTERN int Cudd_bddVarConjDecomp ARGS((DdManager *dd, DdNode * f, DdNode ***conjuncts)); -EXTERN int Cudd_bddVarDisjDecomp ARGS((DdManager *dd, DdNode * f, DdNode ***disjuncts)); -EXTERN DdNode * Cudd_FindEssential ARGS((DdManager *dd, DdNode *f)); -EXTERN int Cudd_bddIsVarEssential ARGS((DdManager *manager, DdNode *f, int id, int phase)); -EXTERN int Cudd_DumpBlif ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, char *mname, FILE *fp)); -EXTERN int Cudd_DumpBlifBody ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN int Cudd_DumpDot ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN int Cudd_DumpDaVinci ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN int Cudd_DumpDDcal ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN int Cudd_DumpFactoredForm ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN DdNode * Cudd_bddConstrain ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * Cudd_bddRestrict ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * Cudd_addConstrain ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode ** Cudd_bddConstrainDecomp ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_addRestrict ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode ** Cudd_bddCharToVect ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_bddLICompaction ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * Cudd_bddSqueeze ARGS((DdManager *dd, DdNode *l, DdNode *u)); -EXTERN DdNode * Cudd_bddMinimize ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * Cudd_SubsetCompress ARGS((DdManager *dd, DdNode *f, int nvars, int threshold)); -EXTERN DdNode * Cudd_SupersetCompress ARGS((DdManager *dd, DdNode *f, int nvars, int threshold)); -EXTERN MtrNode * Cudd_MakeTreeNode ARGS((DdManager *dd, unsigned int low, unsigned int size, unsigned int type)); -EXTERN int Cudd_addHarwell ARGS((FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, DdNode ***xn, DdNode ***yn_, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy, int pr)); -EXTERN DdManager * Cudd_Init ARGS((unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory)); -EXTERN void Cudd_Quit ARGS((DdManager *unique)); -EXTERN int Cudd_PrintLinear ARGS((DdManager *table)); -EXTERN int Cudd_ReadLinear ARGS((DdManager *table, int x, int y)); -EXTERN DdNode * Cudd_bddLiteralSetIntersection ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_addMatrixMultiply ARGS((DdManager *dd, DdNode *A, DdNode *B, DdNode **z, int nz)); -EXTERN DdNode * Cudd_addTimesPlus ARGS((DdManager *dd, DdNode *A, DdNode *B, DdNode **z, int nz)); -EXTERN DdNode * Cudd_addTriangle ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode **z, int nz)); -EXTERN DdNode * Cudd_addOuterSum ARGS((DdManager *dd, DdNode *M, DdNode *r, DdNode *c)); -EXTERN DdNode * Cudd_PrioritySelect ARGS((DdManager *dd, DdNode *R, DdNode **x, DdNode **y, DdNode **z, DdNode *Pi, int n, DdNode * (*)(DdManager *, int, DdNode **, DdNode **, DdNode **))); -EXTERN DdNode * Cudd_Xgty ARGS((DdManager *dd, int N, DdNode **z, DdNode **x, DdNode **y)); -EXTERN DdNode * Cudd_Xeqy ARGS((DdManager *dd, int N, DdNode **x, DdNode **y)); -EXTERN DdNode * Cudd_addXeqy ARGS((DdManager *dd, int N, DdNode **x, DdNode **y)); -EXTERN DdNode * Cudd_Dxygtdxz ARGS((DdManager *dd, int N, DdNode **x, DdNode **y, DdNode **z)); -EXTERN DdNode * Cudd_Dxygtdyz ARGS((DdManager *dd, int N, DdNode **x, DdNode **y, DdNode **z)); -EXTERN DdNode * Cudd_CProjection ARGS((DdManager *dd, DdNode *R, DdNode *Y)); -EXTERN DdNode * Cudd_addHamming ARGS((DdManager *dd, DdNode **xVars, DdNode **yVars, int nVars)); -EXTERN int Cudd_MinHammingDist ARGS((DdManager *dd, DdNode *f, int *minterm, int upperBound)); -EXTERN DdNode * Cudd_bddClosestCube ARGS((DdManager *dd, DdNode * f, DdNode *g, int *distance)); -EXTERN int Cudd_addRead ARGS((FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, DdNode ***xn, DdNode ***yn_, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy)); -EXTERN int Cudd_bddRead ARGS((FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy)); -EXTERN void Cudd_Ref ARGS((DdNode *n)); -EXTERN void Cudd_RecursiveDeref ARGS((DdManager *table, DdNode *n)); -EXTERN void Cudd_IterDerefBdd ARGS((DdManager *table, DdNode *n)); -EXTERN void Cudd_DelayedDerefBdd ARGS((DdManager * table, DdNode * n)); -EXTERN void Cudd_RecursiveDerefZdd ARGS((DdManager *table, DdNode *n)); -EXTERN void Cudd_Deref ARGS((DdNode *node)); -EXTERN int Cudd_CheckZeroRef ARGS((DdManager *manager)); -EXTERN int Cudd_ReduceHeap ARGS((DdManager *table, Cudd_ReorderingType heuristic, int minsize)); -EXTERN int Cudd_ShuffleHeap ARGS((DdManager *table, int *permutation)); -EXTERN DdNode * Cudd_Eval ARGS((DdManager *dd, DdNode *f, int *inputs)); -EXTERN DdNode * Cudd_ShortestPath ARGS((DdManager *manager, DdNode *f, int *weight, int *support, int *length)); -EXTERN DdNode * Cudd_LargestCube ARGS((DdManager *manager, DdNode *f, int *length)); -EXTERN int Cudd_ShortestLength ARGS((DdManager *manager, DdNode *f, int *weight)); -EXTERN DdNode * Cudd_Decreasing ARGS((DdManager *dd, DdNode *f, int i)); -EXTERN DdNode * Cudd_Increasing ARGS((DdManager *dd, DdNode *f, int i)); -EXTERN int Cudd_EquivDC ARGS((DdManager *dd, DdNode *F, DdNode *G, DdNode *D)); -EXTERN int Cudd_bddLeqUnless ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *D)); -EXTERN int Cudd_EqualSupNorm ARGS((DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE tolerance, int pr)); -EXTERN DdNode * Cudd_bddMakePrime ARGS ((DdManager *dd, DdNode *cube, DdNode *f)); -EXTERN double * Cudd_CofMinterm ARGS((DdManager *dd, DdNode *node)); -EXTERN DdNode * Cudd_SolveEqn ARGS((DdManager * bdd, DdNode *F, DdNode *Y, DdNode **G, int **yIndex, int n)); -EXTERN DdNode * Cudd_VerifySol ARGS((DdManager * bdd, DdNode *F, DdNode **G, int *yIndex, int n)); -EXTERN DdNode * Cudd_SplitSet ARGS((DdManager *manager, DdNode *S, DdNode **xVars, int n, double m)); -EXTERN DdNode * Cudd_SubsetHeavyBranch ARGS((DdManager *dd, DdNode *f, int numVars, int threshold)); -EXTERN DdNode * Cudd_SupersetHeavyBranch ARGS((DdManager *dd, DdNode *f, int numVars, int threshold)); -EXTERN DdNode * Cudd_SubsetShortPaths ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)); -EXTERN DdNode * Cudd_SupersetShortPaths ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)); -EXTERN void Cudd_SymmProfile ARGS((DdManager *table, int lower, int upper)); -EXTERN unsigned int Cudd_Prime ARGS((unsigned int p)); -EXTERN int Cudd_PrintMinterm ARGS((DdManager *manager, DdNode *node)); -EXTERN int Cudd_bddPrintCover ARGS((DdManager *dd, DdNode *l, DdNode *u)); -EXTERN int Cudd_PrintDebug ARGS((DdManager *dd, DdNode *f, int n, int pr)); -EXTERN int Cudd_DagSize ARGS((DdNode *node)); -EXTERN int Cudd_EstimateCofactor ARGS((DdManager *dd, DdNode * node, int i, int phase)); -EXTERN int Cudd_EstimateCofactorSimple ARGS((DdNode * node, int i)); -EXTERN int Cudd_SharingSize ARGS((DdNode **nodeArray, int n)); -EXTERN double Cudd_CountMinterm ARGS((DdManager *manager, DdNode *node, int nvars)); -EXTERN int Cudd_EpdCountMinterm ARGS((DdManager *manager, DdNode *node, int nvars, EpDouble *epd)); -EXTERN double Cudd_CountPath ARGS((DdNode *node)); -EXTERN double Cudd_CountPathsToNonZero ARGS((DdNode *node)); -EXTERN DdNode * Cudd_Support ARGS((DdManager *dd, DdNode *f)); -EXTERN int * Cudd_SupportIndex ARGS((DdManager *dd, DdNode *f)); -EXTERN int Cudd_SupportSize ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_VectorSupport ARGS((DdManager *dd, DdNode **F, int n)); -EXTERN int * Cudd_VectorSupportIndex ARGS((DdManager *dd, DdNode **F, int n)); -EXTERN int Cudd_VectorSupportSize ARGS((DdManager *dd, DdNode **F, int n)); -EXTERN int Cudd_ClassifySupport ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode **common, DdNode **onlyF, DdNode **onlyG)); -EXTERN int Cudd_CountLeaves ARGS((DdNode *node)); -EXTERN int Cudd_bddPickOneCube ARGS((DdManager *ddm, DdNode *node, char *string)); -EXTERN DdNode * Cudd_bddPickOneMinterm ARGS((DdManager *dd, DdNode *f, DdNode **vars, int n)); -EXTERN DdNode ** Cudd_bddPickArbitraryMinterms ARGS((DdManager *dd, DdNode *f, DdNode **vars, int n, int k)); -EXTERN DdNode * Cudd_SubsetWithMaskVars ARGS((DdManager *dd, DdNode *f, DdNode **vars, int nvars, DdNode **maskVars, int mvars)); -EXTERN DdGen * Cudd_FirstCube ARGS((DdManager *dd, DdNode *f, int **cube, CUDD_VALUE_TYPE *value)); -EXTERN int Cudd_NextCube ARGS((DdGen *gen, int **cube, CUDD_VALUE_TYPE *value)); -EXTERN DdNode * Cudd_bddComputeCube ARGS((DdManager *dd, DdNode **vars, int *phase, int n)); -EXTERN DdNode * Cudd_addComputeCube ARGS((DdManager *dd, DdNode **vars, int *phase, int n)); -EXTERN DdNode * Cudd_CubeArrayToBdd ARGS((DdManager *dd, int *array)); -EXTERN int Cudd_BddToCubeArray ARGS((DdManager *dd, DdNode *cube, int *array)); -EXTERN DdGen * Cudd_FirstNode ARGS((DdManager *dd, DdNode *f, DdNode **node)); -EXTERN int Cudd_NextNode ARGS((DdGen *gen, DdNode **node)); -EXTERN int Cudd_GenFree ARGS((DdGen *gen)); -EXTERN int Cudd_IsGenEmpty ARGS((DdGen *gen)); -EXTERN DdNode * Cudd_IndicesToCube ARGS((DdManager *dd, int *array, int n)); -EXTERN void Cudd_PrintVersion ARGS((FILE *fp)); -EXTERN double Cudd_AverageDistance ARGS((DdManager *dd)); -EXTERN long Cudd_Random ARGS(()); -EXTERN void Cudd_Srandom ARGS((long seed)); -EXTERN double Cudd_Density ARGS((DdManager *dd, DdNode *f, int nvars)); -EXTERN void Cudd_OutOfMem ARGS((long size)); -EXTERN int Cudd_zddCount ARGS((DdManager *zdd, DdNode *P)); -EXTERN double Cudd_zddCountDouble ARGS((DdManager *zdd, DdNode *P)); -EXTERN DdNode * Cudd_zddProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddUnateProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddWeakDiv ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddDivide ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddWeakDivF ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddDivideF ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddComplement ARGS((DdManager *dd, DdNode *node)); -EXTERN MtrNode * Cudd_MakeZddTreeNode ARGS((DdManager *dd, unsigned int low, unsigned int size, unsigned int type)); -EXTERN DdNode * Cudd_zddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U, DdNode **zdd_I)); -EXTERN DdNode * Cudd_bddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U)); -EXTERN DdNode * Cudd_MakeBddFromZddCover ARGS((DdManager *dd, DdNode *node)); -EXTERN int Cudd_zddDagSize ARGS((DdNode *p_node)); -EXTERN double Cudd_zddCountMinterm ARGS((DdManager *zdd, DdNode *node, int path)); -EXTERN void Cudd_zddPrintSubtable ARGS((DdManager *table)); -EXTERN DdNode * Cudd_zddPortFromBdd ARGS((DdManager *dd, DdNode *B)); -EXTERN DdNode * Cudd_zddPortToBdd ARGS((DdManager *dd, DdNode *f)); -EXTERN int Cudd_zddReduceHeap ARGS((DdManager *table, Cudd_ReorderingType heuristic, int minsize)); -EXTERN int Cudd_zddShuffleHeap ARGS((DdManager *table, int *permutation)); -EXTERN DdNode * Cudd_zddIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * Cudd_zddUnion ARGS((DdManager *dd, DdNode *P, DdNode *Q)); -EXTERN DdNode * Cudd_zddIntersect ARGS((DdManager *dd, DdNode *P, DdNode *Q)); -EXTERN DdNode * Cudd_zddDiff ARGS((DdManager *dd, DdNode *P, DdNode *Q)); -EXTERN DdNode * Cudd_zddDiffConst ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); -EXTERN DdNode * Cudd_zddSubset1 ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN DdNode * Cudd_zddSubset0 ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN DdNode * Cudd_zddChange ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN void Cudd_zddSymmProfile ARGS((DdManager *table, int lower, int upper)); -EXTERN int Cudd_zddPrintMinterm ARGS((DdManager *zdd, DdNode *node)); -EXTERN int Cudd_zddPrintCover ARGS((DdManager *zdd, DdNode *node)); -EXTERN int Cudd_zddPrintDebug ARGS((DdManager *zdd, DdNode *f, int n, int pr)); -EXTERN DdGen * Cudd_zddFirstPath ARGS((DdManager *zdd, DdNode *f, int **path)); -EXTERN int Cudd_zddNextPath ARGS((DdGen *gen, int **path)); -EXTERN char * Cudd_zddCoverPathToString ARGS((DdManager *zdd, int *path, char *str)); -EXTERN int Cudd_zddDumpDot ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN int Cudd_bddSetPiVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetPsVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetNsVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsPiVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsPsVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsNsVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetPairIndex ARGS((DdManager *dd, int index, int pairIndex)); -EXTERN int Cudd_bddReadPairIndex ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetVarToBeGrouped ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetVarHardGroup ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddResetVarToBeGrouped ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsVarToBeGrouped ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetVarToBeUngrouped ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsVarToBeUngrouped ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsVarHardGroup ARGS((DdManager *dd, int index)); - -/**AutomaticEnd***************************************************************/ - -#endif /* _CUDD */ diff --git a/src/bdd/cudd/cudd.make b/src/bdd/cudd/cudd.make deleted file mode 100644 index 7cb342a2..00000000 --- a/src/bdd/cudd/cudd.make +++ /dev/null @@ -1,42 +0,0 @@ -CSRC += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \ - cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \ - cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c\ - cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \ - cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \ - cuddExport.c cuddGenCof.c cuddGenetic.c \ - cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \ - cuddLCache.c cuddLevelQ.c \ - cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \ - cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \ - cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \ - cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \ - cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \ - cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c - -HEADERS += cudd.h cuddInt.h -MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html doc/cuddAllDet.html \ - doc/cuddExtAbs.html doc/cuddExtDet.html doc/cuddIntro.css \ - doc/cuddIntro.html doc/footnode.html doc/img1.gif doc/img2.gif \ - doc/img3.gif doc/img4.gif doc/img5.gif doc/index.html \ - doc/node1.html doc/node2.html doc/node3.html doc/node4.html \ - doc/node5.html doc/node6.html doc/node7.html doc/node8.html \ - doc/icons/change_begin.gif \ - doc/icons/change_delete.gif \ - doc/icons/change_end.gif \ - doc/icons/contents_motif.gif \ - doc/icons/cross_ref_motif.gif \ - doc/icons/foot_motif.gif \ - doc/icons/image.gif \ - doc/icons/index_motif.gif \ - doc/icons/next_group_motif.gif \ - doc/icons/next_group_motif_gr.gif \ - doc/icons/next_motif.gif \ - doc/icons/next_motif_gr.gif \ - doc/icons/previous_group_motif.gif \ - doc/icons/previous_group_motif_gr.gif \ - doc/icons/previous_motif.gif \ - doc/icons/previous_motif_gr.gif \ - doc/icons/up_motif.gif \ - doc/icons/up_motif_gr.gif - -DEPENDENCYFILES = $(CSRC) diff --git a/src/bdd/cudd/cuddAPI.c b/src/bdd/cudd/cuddAPI.c deleted file mode 100644 index a16b82cf..00000000 --- a/src/bdd/cudd/cuddAPI.c +++ /dev/null @@ -1,4409 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAPI.c] - - PackageName [cudd] - - Synopsis [Application interface functions.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addNewVar() - <li> Cudd_addNewVarAtLevel() - <li> Cudd_bddNewVar() - <li> Cudd_bddNewVarAtLevel() - <li> Cudd_addIthVar() - <li> Cudd_bddIthVar() - <li> Cudd_zddIthVar() - <li> Cudd_zddVarsFromBddVars() - <li> Cudd_addConst() - <li> Cudd_IsNonConstant() - <li> Cudd_AutodynEnable() - <li> Cudd_AutodynDisable() - <li> Cudd_ReorderingStatus() - <li> Cudd_AutodynEnableZdd() - <li> Cudd_AutodynDisableZdd() - <li> Cudd_ReorderingStatusZdd() - <li> Cudd_zddRealignmentEnabled() - <li> Cudd_zddRealignEnable() - <li> Cudd_zddRealignDisable() - <li> Cudd_bddRealignmentEnabled() - <li> Cudd_bddRealignEnable() - <li> Cudd_bddRealignDisable() - <li> Cudd_ReadOne() - <li> Cudd_ReadZddOne() - <li> Cudd_ReadZero() - <li> Cudd_ReadLogicZero() - <li> Cudd_ReadPlusInfinity() - <li> Cudd_ReadMinusInfinity() - <li> Cudd_ReadBackground() - <li> Cudd_SetBackground() - <li> Cudd_ReadCacheSlots() - <li> Cudd_ReadCacheUsedSlots() - <li> Cudd_ReadCacheLookUps() - <li> Cudd_ReadCacheHits() - <li> Cudd_ReadMinHit() - <li> Cudd_SetMinHit() - <li> Cudd_ReadLooseUpTo() - <li> Cudd_SetLooseUpTo() - <li> Cudd_ReadMaxCache() - <li> Cudd_ReadMaxCacheHard() - <li> Cudd_SetMaxCacheHard() - <li> Cudd_ReadSize() - <li> Cudd_ReadSlots() - <li> Cudd_ReadUsedSlots() - <li> Cudd_ExpectedUsedSlots() - <li> Cudd_ReadKeys() - <li> Cudd_ReadDead() - <li> Cudd_ReadMinDead() - <li> Cudd_ReadReorderings() - <li> Cudd_ReadReorderingTime() - <li> Cudd_ReadGarbageCollections() - <li> Cudd_ReadGarbageCollectionTime() - <li> Cudd_ReadNodesFreed() - <li> Cudd_ReadNodesDropped() - <li> Cudd_ReadUniqueLookUps() - <li> Cudd_ReadUniqueLinks() - <li> Cudd_ReadSiftMaxVar() - <li> Cudd_SetSiftMaxVar() - <li> Cudd_ReadMaxGrowth() - <li> Cudd_SetMaxGrowth() - <li> Cudd_ReadMaxGrowthAlternate() - <li> Cudd_SetMaxGrowthAlternate() - <li> Cudd_ReadReorderingCycle() - <li> Cudd_SetReorderingCycle() - <li> Cudd_ReadTree() - <li> Cudd_SetTree() - <li> Cudd_FreeTree() - <li> Cudd_ReadZddTree() - <li> Cudd_SetZddTree() - <li> Cudd_FreeZddTree() - <li> Cudd_NodeReadIndex() - <li> Cudd_ReadPerm() - <li> Cudd_ReadInvPerm() - <li> Cudd_ReadVars() - <li> Cudd_ReadEpsilon() - <li> Cudd_SetEpsilon() - <li> Cudd_ReadGroupCheck() - <li> Cudd_SetGroupcheck() - <li> Cudd_GarbageCollectionEnabled() - <li> Cudd_EnableGarbageCollection() - <li> Cudd_DisableGarbageCollection() - <li> Cudd_DeadAreCounted() - <li> Cudd_TurnOnCountDead() - <li> Cudd_TurnOffCountDead() - <li> Cudd_ReadRecomb() - <li> Cudd_SetRecomb() - <li> Cudd_ReadSymmviolation() - <li> Cudd_SetSymmviolation() - <li> Cudd_ReadArcviolation() - <li> Cudd_SetArcviolation() - <li> Cudd_ReadPopulationSize() - <li> Cudd_SetPopulationSize() - <li> Cudd_ReadNumberXovers() - <li> Cudd_SetNumberXovers() - <li> Cudd_ReadMemoryInUse() - <li> Cudd_PrintInfo() - <li> Cudd_ReadPeakNodeCount() - <li> Cudd_ReadPeakLiveNodeCount() - <li> Cudd_ReadNodeCount() - <li> Cudd_zddReadNodeCount() - <li> Cudd_AddHook() - <li> Cudd_RemoveHook() - <li> Cudd_IsInHook() - <li> Cudd_StdPreReordHook() - <li> Cudd_StdPostReordHook() - <li> Cudd_EnableReorderingReporting() - <li> Cudd_DisableReorderingReporting() - <li> Cudd_ReorderingReporting() - <li> Cudd_ReadErrorCode() - <li> Cudd_ClearErrorCode() - <li> Cudd_ReadStdout() - <li> Cudd_SetStdout() - <li> Cudd_ReadStderr() - <li> Cudd_SetStderr() - <li> Cudd_ReadNextReordering() - <li> Cudd_SetNextReordering() - <li> Cudd_ReadSwapSteps() - <li> Cudd_ReadMaxLive() - <li> Cudd_SetMaxLive() - <li> Cudd_ReadMaxMemory() - <li> Cudd_SetMaxMemory() - <li> Cudd_bddBindVar() - <li> Cudd_bddUnbindVar() - <li> Cudd_bddVarIsBound() - <li> Cudd_bddSetPiVar() - <li> Cudd_bddSetPsVar() - <li> Cudd_bddSetNsVar() - <li> Cudd_bddIsPiVar() - <li> Cudd_bddIsPsVar() - <li> Cudd_bddIsNsVar() - <li> Cudd_bddSetPairIndex() - <li> Cudd_bddReadPairIndex() - <li> Cudd_bddSetVarToBeGrouped() - <li> Cudd_bddSetVarHardGroup() - <li> Cudd_bddResetVarToBeGrouped() - <li> Cudd_bddIsVarToBeGrouped() - <li> Cudd_bddSetVarToBeUngrouped() - <li> Cudd_bddIsVarToBeUngrouped() - <li> Cudd_bddIsVarHardGroup() - </ul> - Static procedures included in this module: - <ul> - <li> fixVarTree() - </ul>] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAPI.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void fixVarTree ARGS((MtrNode *treenode, int *perm, int size)); -static int addMultiplicityGroups ARGS((DdManager *dd, MtrNode *treenode, int multiplicity, char *vmask, char *lmask)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Returns a new ADD variable.] - - Description [Creates a new ADD variable. The new variable has an - index equal to the largest previous index plus 1. Returns a - pointer to the new variable if successful; NULL otherwise. - An ADD variable differs from a BDD variable because it points to the - arithmetic zero, instead of having a complement pointer to 1. ] - - SideEffects [None] - - SeeAlso [Cudd_bddNewVar Cudd_addIthVar Cudd_addConst - Cudd_addNewVarAtLevel] - -******************************************************************************/ -DdNode * -Cudd_addNewVar( - DdManager * dd) -{ - DdNode *res; - - if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); - do { - dd->reordered = 0; - res = cuddUniqueInter(dd,dd->size,DD_ONE(dd),DD_ZERO(dd)); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_addNewVar */ - - -/**Function******************************************************************** - - Synopsis [Returns a new ADD variable at a specified level.] - - Description [Creates a new ADD variable. The new variable has an - index equal to the largest previous index plus 1 and is positioned at - the specified level in the order. Returns a pointer to the new - variable if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel] - -******************************************************************************/ -DdNode * -Cudd_addNewVarAtLevel( - DdManager * dd, - int level) -{ - DdNode *res; - - if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); - if (level >= dd->size) return(Cudd_addIthVar(dd,level)); - if (!cuddInsertSubtables(dd,1,level)) return(NULL); - do { - dd->reordered = 0; - res = cuddUniqueInter(dd,dd->size - 1,DD_ONE(dd),DD_ZERO(dd)); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_addNewVarAtLevel */ - - -/**Function******************************************************************** - - Synopsis [Returns a new BDD variable.] - - Description [Creates a new BDD variable. The new variable has an - index equal to the largest previous index plus 1. Returns a - pointer to the new variable if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel] - -******************************************************************************/ -DdNode * -Cudd_bddNewVar( - DdManager * dd) -{ - DdNode *res; - - if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); - res = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one)); - - return(res); - -} /* end of Cudd_bddNewVar */ - - -/**Function******************************************************************** - - Synopsis [Returns a new BDD variable at a specified level.] - - Description [Creates a new BDD variable. The new variable has an - index equal to the largest previous index plus 1 and is positioned at - the specified level in the order. Returns a pointer to the new - variable if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddNewVar Cudd_bddIthVar Cudd_addNewVarAtLevel] - -******************************************************************************/ -DdNode * -Cudd_bddNewVarAtLevel( - DdManager * dd, - int level) -{ - DdNode *res; - - if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); - if (level >= dd->size) return(Cudd_bddIthVar(dd,level)); - if (!cuddInsertSubtables(dd,1,level)) return(NULL); - res = dd->vars[dd->size - 1]; - - return(res); - -} /* end of Cudd_bddNewVarAtLevel */ - - -/**Function******************************************************************** - - Synopsis [Returns the ADD variable with index i.] - - Description [Retrieves the ADD variable with index i if it already - exists, or creates a new ADD variable. Returns a pointer to the - variable if successful; NULL otherwise. An ADD variable differs from - a BDD variable because it points to the arithmetic zero, instead of - having a complement pointer to 1. ] - - SideEffects [None] - - SeeAlso [Cudd_addNewVar Cudd_bddIthVar Cudd_addConst - Cudd_addNewVarAtLevel] - -******************************************************************************/ -DdNode * -Cudd_addIthVar( - DdManager * dd, - int i) -{ - DdNode *res; - - if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); - do { - dd->reordered = 0; - res = cuddUniqueInter(dd,i,DD_ONE(dd),DD_ZERO(dd)); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_addIthVar */ - - -/**Function******************************************************************** - - Synopsis [Returns the BDD variable with index i.] - - Description [Retrieves the BDD variable with index i if it already - exists, or creates a new BDD variable. Returns a pointer to the - variable if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel - Cudd_ReadVars] - -******************************************************************************/ -DdNode * -Cudd_bddIthVar( - DdManager * dd, - int i) -{ - DdNode *res; - - if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); - if (i < dd->size) { - res = dd->vars[i]; - } else { - res = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); - } - - return(res); - -} /* end of Cudd_bddIthVar */ - - -/**Function******************************************************************** - - Synopsis [Returns the ZDD variable with index i.] - - Description [Retrieves the ZDD variable with index i if it already - exists, or creates a new ZDD variable. Returns a pointer to the - variable if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddIthVar Cudd_addIthVar] - -******************************************************************************/ -DdNode * -Cudd_zddIthVar( - DdManager * dd, - int i) -{ - DdNode *res; - DdNode *zvar; - DdNode *lower; - int j; - - if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); - - /* The i-th variable function has the following structure: - ** at the level corresponding to index i there is a node whose "then" - ** child points to the universe, and whose "else" child points to zero. - ** Above that level there are nodes with identical children. - */ - - /* First we build the node at the level of index i. */ - lower = (i < dd->sizeZ - 1) ? dd->univ[dd->permZ[i]+1] : DD_ONE(dd); - do { - dd->reordered = 0; - zvar = cuddUniqueInterZdd(dd, i, lower, DD_ZERO(dd)); - } while (dd->reordered == 1); - - if (zvar == NULL) - return(NULL); - cuddRef(zvar); - - /* Now we add the "filler" nodes above the level of index i. */ - for (j = dd->permZ[i] - 1; j >= 0; j--) { - do { - dd->reordered = 0; - res = cuddUniqueInterZdd(dd, dd->invpermZ[j], zvar, zvar); - } while (dd->reordered == 1); - if (res == NULL) { - Cudd_RecursiveDerefZdd(dd,zvar); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDerefZdd(dd,zvar); - zvar = res; - } - cuddDeref(zvar); - return(zvar); - -} /* end of Cudd_zddIthVar */ - - -/**Function******************************************************************** - - Synopsis [Creates one or more ZDD variables for each BDD variable.] - - Description [Creates one or more ZDD variables for each BDD - variable. If some ZDD variables already exist, only the missing - variables are created. Parameter multiplicity allows the caller to - control how many variables are created for each BDD variable in - existence. For instance, if ZDDs are used to represent covers, two - ZDD variables are required for each BDD variable. The order of the - BDD variables is transferred to the ZDD variables. If a variable - group tree exists for the BDD variables, a corresponding ZDD - variable group tree is created by expanding the BDD variable - tree. In any case, the ZDD variables derived from the same BDD - variable are merged in a ZDD variable group. If a ZDD variable group - tree exists, it is freed. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel] - -******************************************************************************/ -int -Cudd_zddVarsFromBddVars( - DdManager * dd /* DD manager */, - int multiplicity /* how many ZDD variables are created for each BDD variable */) -{ - int res; - int i, j; - int allnew; - int *permutation; - - if (multiplicity < 1) return(0); - allnew = dd->sizeZ == 0; - if (dd->size * multiplicity > dd->sizeZ) { - res = cuddResizeTableZdd(dd,dd->size * multiplicity - 1); - if (res == 0) return(0); - } - /* Impose the order of the BDD variables to the ZDD variables. */ - if (allnew) { - for (i = 0; i < dd->size; i++) { - for (j = 0; j < multiplicity; j++) { - dd->permZ[i * multiplicity + j] = - dd->perm[i] * multiplicity + j; - dd->invpermZ[dd->permZ[i * multiplicity + j]] = - i * multiplicity + j; - } - } - for (i = 0; i < dd->sizeZ; i++) { - dd->univ[i]->index = dd->invpermZ[i]; - } - } else { - permutation = ALLOC(int,dd->sizeZ); - if (permutation == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < dd->size; i++) { - for (j = 0; j < multiplicity; j++) { - permutation[i * multiplicity + j] = - dd->invperm[i] * multiplicity + j; - } - } - for (i = dd->size * multiplicity; i < dd->sizeZ; i++) { - permutation[i] = i; - } - res = Cudd_zddShuffleHeap(dd, permutation); - FREE(permutation); - if (res == 0) return(0); - } - /* Copy and expand the variable group tree if it exists. */ - if (dd->treeZ != NULL) { - Cudd_FreeZddTree(dd); - } - if (dd->tree != NULL) { - dd->treeZ = Mtr_CopyTree(dd->tree, multiplicity); - if (dd->treeZ == NULL) return(0); - } else if (multiplicity > 1) { - dd->treeZ = Mtr_InitGroupTree(0, dd->sizeZ); - if (dd->treeZ == NULL) return(0); - dd->treeZ->index = dd->invpermZ[0]; - } - /* Create groups for the ZDD variables derived from the same BDD variable. - */ - if (multiplicity > 1) { - char *vmask, *lmask; - - vmask = ALLOC(char, dd->size); - if (vmask == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - lmask = ALLOC(char, dd->size); - if (lmask == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < dd->size; i++) { - vmask[i] = lmask[i] = 0; - } - res = addMultiplicityGroups(dd,dd->treeZ,multiplicity,vmask,lmask); - FREE(vmask); - FREE(lmask); - if (res == 0) return(0); - } - return(1); - -} /* end of Cudd_zddVarsFromBddVars */ - - -/**Function******************************************************************** - - Synopsis [Returns the ADD for constant c.] - - Description [Retrieves the ADD for constant c if it already - exists, or creates a new ADD. Returns a pointer to the - ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addNewVar Cudd_addIthVar] - -******************************************************************************/ -DdNode * -Cudd_addConst( - DdManager * dd, - CUDD_VALUE_TYPE c) -{ - return(cuddUniqueConst(dd,c)); - -} /* end of Cudd_addConst */ - - -/**Function******************************************************************** - - Synopsis [Returns 1 if a DD node is not constant.] - - Description [Returns 1 if a DD node is not constant. This function is - useful to test the results of Cudd_bddIteConstant, Cudd_addIteConstant, - Cudd_addEvalConst. These results may be a special value signifying - non-constant. In the other cases the macro Cudd_IsConstant can be used.] - - SideEffects [None] - - SeeAlso [Cudd_IsConstant Cudd_bddIteConstant Cudd_addIteConstant - Cudd_addEvalConst] - -******************************************************************************/ -int -Cudd_IsNonConstant( - DdNode *f) -{ - return(f == DD_NON_CONSTANT || !Cudd_IsConstant(f)); - -} /* end of Cudd_IsNonConstant */ - - -/**Function******************************************************************** - - Synopsis [Enables automatic dynamic reordering of BDDs and ADDs.] - - Description [Enables automatic dynamic reordering of BDDs and - ADDs. Parameter method is used to determine the method used for - reordering. If CUDD_REORDER_SAME is passed, the method is - unchanged.] - - SideEffects [None] - - SeeAlso [Cudd_AutodynDisable Cudd_ReorderingStatus - Cudd_AutodynEnableZdd] - -******************************************************************************/ -void -Cudd_AutodynEnable( - DdManager * unique, - Cudd_ReorderingType method) -{ - unique->autoDyn = 1; - if (method != CUDD_REORDER_SAME) { - unique->autoMethod = method; - } -#ifndef DD_NO_DEATH_ROW - /* If reordering is enabled, using the death row causes too many - ** invocations. Hence, we shrink the death row to just one entry. - */ - cuddClearDeathRow(unique); - unique->deathRowDepth = 1; - unique->deadMask = unique->deathRowDepth - 1; - if ((unsigned) unique->nextDead > unique->deadMask) { - unique->nextDead = 0; - } - unique->deathRow = REALLOC(DdNodePtr, unique->deathRow, - unique->deathRowDepth); -#endif - return; - -} /* end of Cudd_AutodynEnable */ - - -/**Function******************************************************************** - - Synopsis [Disables automatic dynamic reordering.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_AutodynEnable Cudd_ReorderingStatus - Cudd_AutodynDisableZdd] - -******************************************************************************/ -void -Cudd_AutodynDisable( - DdManager * unique) -{ - unique->autoDyn = 0; - return; - -} /* end of Cudd_AutodynDisable */ - - -/**Function******************************************************************** - - Synopsis [Reports the status of automatic dynamic reordering of BDDs - and ADDs.] - - Description [Reports the status of automatic dynamic reordering of - BDDs and ADDs. Parameter method is set to the reordering method - currently selected. Returns 1 if automatic reordering is enabled; 0 - otherwise.] - - SideEffects [Parameter method is set to the reordering method currently - selected.] - - SeeAlso [Cudd_AutodynEnable Cudd_AutodynDisable - Cudd_ReorderingStatusZdd] - -******************************************************************************/ -int -Cudd_ReorderingStatus( - DdManager * unique, - Cudd_ReorderingType * method) -{ - *method = unique->autoMethod; - return(unique->autoDyn); - -} /* end of Cudd_ReorderingStatus */ - - -/**Function******************************************************************** - - Synopsis [Enables automatic dynamic reordering of ZDDs.] - - Description [Enables automatic dynamic reordering of ZDDs. Parameter - method is used to determine the method used for reordering ZDDs. If - CUDD_REORDER_SAME is passed, the method is unchanged.] - - SideEffects [None] - - SeeAlso [Cudd_AutodynDisableZdd Cudd_ReorderingStatusZdd - Cudd_AutodynEnable] - -******************************************************************************/ -void -Cudd_AutodynEnableZdd( - DdManager * unique, - Cudd_ReorderingType method) -{ - unique->autoDynZ = 1; - if (method != CUDD_REORDER_SAME) { - unique->autoMethodZ = method; - } - return; - -} /* end of Cudd_AutodynEnableZdd */ - - -/**Function******************************************************************** - - Synopsis [Disables automatic dynamic reordering of ZDDs.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_AutodynEnableZdd Cudd_ReorderingStatusZdd - Cudd_AutodynDisable] - -******************************************************************************/ -void -Cudd_AutodynDisableZdd( - DdManager * unique) -{ - unique->autoDynZ = 0; - return; - -} /* end of Cudd_AutodynDisableZdd */ - - -/**Function******************************************************************** - - Synopsis [Reports the status of automatic dynamic reordering of ZDDs.] - - Description [Reports the status of automatic dynamic reordering of - ZDDs. Parameter method is set to the ZDD reordering method currently - selected. Returns 1 if automatic reordering is enabled; 0 - otherwise.] - - SideEffects [Parameter method is set to the ZDD reordering method currently - selected.] - - SeeAlso [Cudd_AutodynEnableZdd Cudd_AutodynDisableZdd - Cudd_ReorderingStatus] - -******************************************************************************/ -int -Cudd_ReorderingStatusZdd( - DdManager * unique, - Cudd_ReorderingType * method) -{ - *method = unique->autoMethodZ; - return(unique->autoDynZ); - -} /* end of Cudd_ReorderingStatusZdd */ - - -/**Function******************************************************************** - - Synopsis [Tells whether the realignment of ZDD order to BDD order is - enabled.] - - Description [Returns 1 if the realignment of ZDD order to BDD order is - enabled; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddRealignEnable Cudd_zddRealignDisable - Cudd_bddRealignEnable Cudd_bddRealignDisable] - -******************************************************************************/ -int -Cudd_zddRealignmentEnabled( - DdManager * unique) -{ - return(unique->realign); - -} /* end of Cudd_zddRealignmentEnabled */ - - -/**Function******************************************************************** - - Synopsis [Enables realignment of ZDD order to BDD order.] - - Description [Enables realignment of the ZDD variable order to the - BDD variable order after the BDDs and ADDs have been reordered. The - number of ZDD variables must be a multiple of the number of BDD - variables for realignment to make sense. If this condition is not met, - Cudd_ReduceHeap will return 0. Let <code>M</code> be the - ratio of the two numbers. For the purpose of realignment, the ZDD - variables from <code>M*i</code> to <code>(M+1)*i-1</code> are - reagarded as corresponding to BDD variable <code>i</code>. Realignment - is initially disabled.] - - SideEffects [None] - - SeeAlso [Cudd_ReduceHeap Cudd_zddRealignDisable - Cudd_zddRealignmentEnabled Cudd_bddRealignDisable - Cudd_bddRealignmentEnabled] - -******************************************************************************/ -void -Cudd_zddRealignEnable( - DdManager * unique) -{ - unique->realign = 1; - return; - -} /* end of Cudd_zddRealignEnable */ - - -/**Function******************************************************************** - - Synopsis [Disables realignment of ZDD order to BDD order.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddRealignEnable Cudd_zddRealignmentEnabled - Cudd_bddRealignEnable Cudd_bddRealignmentEnabled] - -******************************************************************************/ -void -Cudd_zddRealignDisable( - DdManager * unique) -{ - unique->realign = 0; - return; - -} /* end of Cudd_zddRealignDisable */ - - -/**Function******************************************************************** - - Synopsis [Tells whether the realignment of BDD order to ZDD order is - enabled.] - - Description [Returns 1 if the realignment of BDD order to ZDD order is - enabled; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddRealignEnable Cudd_bddRealignDisable - Cudd_zddRealignEnable Cudd_zddRealignDisable] - -******************************************************************************/ -int -Cudd_bddRealignmentEnabled( - DdManager * unique) -{ - return(unique->realignZ); - -} /* end of Cudd_bddRealignmentEnabled */ - - -/**Function******************************************************************** - - Synopsis [Enables realignment of BDD order to ZDD order.] - - Description [Enables realignment of the BDD variable order to the - ZDD variable order after the ZDDs have been reordered. The - number of ZDD variables must be a multiple of the number of BDD - variables for realignment to make sense. If this condition is not met, - Cudd_zddReduceHeap will return 0. Let <code>M</code> be the - ratio of the two numbers. For the purpose of realignment, the ZDD - variables from <code>M*i</code> to <code>(M+1)*i-1</code> are - reagarded as corresponding to BDD variable <code>i</code>. Realignment - is initially disabled.] - - SideEffects [None] - - SeeAlso [Cudd_zddReduceHeap Cudd_bddRealignDisable - Cudd_bddRealignmentEnabled Cudd_zddRealignDisable - Cudd_zddRealignmentEnabled] - -******************************************************************************/ -void -Cudd_bddRealignEnable( - DdManager * unique) -{ - unique->realignZ = 1; - return; - -} /* end of Cudd_bddRealignEnable */ - - -/**Function******************************************************************** - - Synopsis [Disables realignment of ZDD order to BDD order.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_bddRealignEnable Cudd_bddRealignmentEnabled - Cudd_zddRealignEnable Cudd_zddRealignmentEnabled] - -******************************************************************************/ -void -Cudd_bddRealignDisable( - DdManager * unique) -{ - unique->realignZ = 0; - return; - -} /* end of Cudd_bddRealignDisable */ - - -/**Function******************************************************************** - - Synopsis [Returns the one constant of the manager.] - - Description [Returns the one constant of the manager. The one - constant is common to ADDs and BDDs.] - - SideEffects [None] - - SeeAlso [Cudd_ReadZero Cudd_ReadLogicZero Cudd_ReadZddOne] - -******************************************************************************/ -DdNode * -Cudd_ReadOne( - DdManager * dd) -{ - return(dd->one); - -} /* end of Cudd_ReadOne */ - - -/**Function******************************************************************** - - Synopsis [Returns the ZDD for the constant 1 function.] - - Description [Returns the ZDD for the constant 1 function. - The representation of the constant 1 function as a ZDD depends on - how many variables it (nominally) depends on. The index of the - topmost variable in the support is given as argument <code>i</code>.] - - SideEffects [None] - - SeeAlso [Cudd_ReadOne] - -******************************************************************************/ -DdNode * -Cudd_ReadZddOne( - DdManager * dd, - int i) -{ - if (i < 0) - return(NULL); - return(i < dd->sizeZ ? dd->univ[i] : DD_ONE(dd)); - -} /* end of Cudd_ReadZddOne */ - - - -/**Function******************************************************************** - - Synopsis [Returns the zero constant of the manager.] - - Description [Returns the zero constant of the manager. The zero - constant is the arithmetic zero, rather than the logic zero. The - latter is the complement of the one constant.] - - SideEffects [None] - - SeeAlso [Cudd_ReadOne Cudd_ReadLogicZero] - -******************************************************************************/ -DdNode * -Cudd_ReadZero( - DdManager * dd) -{ - return(DD_ZERO(dd)); - -} /* end of Cudd_ReadZero */ - - -/**Function******************************************************************** - - Synopsis [Returns the logic zero constant of the manager.] - - Description [Returns the zero constant of the manager. The logic zero - constant is the complement of the one constant, and is distinct from - the arithmetic zero.] - - SideEffects [None] - - SeeAlso [Cudd_ReadOne Cudd_ReadZero] - -******************************************************************************/ -DdNode * -Cudd_ReadLogicZero( - DdManager * dd) -{ - return(Cudd_Not(DD_ONE(dd))); - -} /* end of Cudd_ReadLogicZero */ - - -/**Function******************************************************************** - - Synopsis [Reads the plus-infinity constant from the manager.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_ReadPlusInfinity( - DdManager * dd) -{ - return(dd->plusinfinity); - -} /* end of Cudd_ReadPlusInfinity */ - - -/**Function******************************************************************** - - Synopsis [Reads the minus-infinity constant from the manager.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_ReadMinusInfinity( - DdManager * dd) -{ - return(dd->minusinfinity); - -} /* end of Cudd_ReadMinusInfinity */ - - -/**Function******************************************************************** - - Synopsis [Reads the background constant of the manager.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_ReadBackground( - DdManager * dd) -{ - return(dd->background); - -} /* end of Cudd_ReadBackground */ - - -/**Function******************************************************************** - - Synopsis [Sets the background constant of the manager.] - - Description [Sets the background constant of the manager. It assumes - that the DdNode pointer bck is already referenced.] - - SideEffects [None] - -******************************************************************************/ -void -Cudd_SetBackground( - DdManager * dd, - DdNode * bck) -{ - dd->background = bck; - -} /* end of Cudd_SetBackground */ - - -/**Function******************************************************************** - - Synopsis [Reads the number of slots in the cache.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadCacheUsedSlots] - -******************************************************************************/ -unsigned int -Cudd_ReadCacheSlots( - DdManager * dd) -{ - return(dd->cacheSlots); - -} /* end of Cudd_ReadCacheSlots */ - - -/**Function******************************************************************** - - Synopsis [Reads the fraction of used slots in the cache.] - - Description [Reads the fraction of used slots in the cache. The unused - slots are those in which no valid data is stored. Garbage collection, - variable reordering, and cache resizing may cause used slots to become - unused.] - - SideEffects [None] - - SeeAlso [Cudd_ReadCacheSlots] - -******************************************************************************/ -double -Cudd_ReadCacheUsedSlots( - DdManager * dd) -{ - unsigned long used = 0; - int slots = dd->cacheSlots; - DdCache *cache = dd->cache; - int i; - - for (i = 0; i < slots; i++) { - used += cache[i].h != 0; - } - - return((double)used / (double) dd->cacheSlots); - -} /* end of Cudd_ReadCacheUsedSlots */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of cache look-ups.] - - Description [Returns the number of cache look-ups.] - - SideEffects [None] - - SeeAlso [Cudd_ReadCacheHits] - -******************************************************************************/ -double -Cudd_ReadCacheLookUps( - DdManager * dd) -{ - return(dd->cacheHits + dd->cacheMisses + - dd->totCachehits + dd->totCacheMisses); - -} /* end of Cudd_ReadCacheLookUps */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of cache hits.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadCacheLookUps] - -******************************************************************************/ -double -Cudd_ReadCacheHits( - DdManager * dd) -{ - return(dd->cacheHits + dd->totCachehits); - -} /* end of Cudd_ReadCacheHits */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of recursive calls.] - - Description [Returns the number of recursive calls if the package is - compiled with DD_COUNT defined.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -double -Cudd_ReadRecursiveCalls( - DdManager * dd) -{ -#ifdef DD_COUNT - return(dd->recursiveCalls); -#else - return(-1.0); -#endif - -} /* end of Cudd_ReadRecursiveCalls */ - - - -/**Function******************************************************************** - - Synopsis [Reads the hit rate that causes resizinig of the computed - table.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetMinHit] - -******************************************************************************/ -unsigned int -Cudd_ReadMinHit( - DdManager * dd) -{ - /* Internally, the package manipulates the ratio of hits to - ** misses instead of the ratio of hits to accesses. */ - return((unsigned int) (0.5 + 100 * dd->minHit / (1 + dd->minHit))); - -} /* end of Cudd_ReadMinHit */ - - -/**Function******************************************************************** - - Synopsis [Sets the hit rate that causes resizinig of the computed - table.] - - Description [Sets the minHit parameter of the manager. This - parameter controls the resizing of the computed table. If the hit - rate is larger than the specified value, and the cache is not - already too large, then its size is doubled.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMinHit] - -******************************************************************************/ -void -Cudd_SetMinHit( - DdManager * dd, - unsigned int hr) -{ - /* Internally, the package manipulates the ratio of hits to - ** misses instead of the ratio of hits to accesses. */ - dd->minHit = (double) hr / (100.0 - (double) hr); - -} /* end of Cudd_SetMinHit */ - - -/**Function******************************************************************** - - Synopsis [Reads the looseUpTo parameter of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetLooseUpTo Cudd_ReadMinHit Cudd_ReadMinDead] - -******************************************************************************/ -unsigned int -Cudd_ReadLooseUpTo( - DdManager * dd) -{ - return(dd->looseUpTo); - -} /* end of Cudd_ReadLooseUpTo */ - - -/**Function******************************************************************** - - Synopsis [Sets the looseUpTo parameter of the manager.] - - Description [Sets the looseUpTo parameter of the manager. This - parameter of the manager controls the threshold beyond which no fast - growth of the unique table is allowed. The threshold is given as a - number of slots. If the value passed to this function is 0, the - function determines a suitable value based on the available memory.] - - SideEffects [None] - - SeeAlso [Cudd_ReadLooseUpTo Cudd_SetMinHit] - -******************************************************************************/ -void -Cudd_SetLooseUpTo( - DdManager * dd, - unsigned int lut) -{ - if (lut == 0) { - long datalimit = getSoftDataLimit(); - lut = (unsigned int) (datalimit / (sizeof(DdNode) * - DD_MAX_LOOSE_FRACTION)); - } - dd->looseUpTo = lut; - -} /* end of Cudd_SetLooseUpTo */ - - -/**Function******************************************************************** - - Synopsis [Returns the soft limit for the cache size.] - - Description [Returns the soft limit for the cache size. The soft limit] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxCache] - -******************************************************************************/ -unsigned int -Cudd_ReadMaxCache( - DdManager * dd) -{ - return(2 * dd->cacheSlots + dd->cacheSlack); - -} /* end of Cudd_ReadMaxCache */ - - -/**Function******************************************************************** - - Synopsis [Reads the maxCacheHard parameter of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetMaxCacheHard Cudd_ReadMaxCache] - -******************************************************************************/ -unsigned int -Cudd_ReadMaxCacheHard( - DdManager * dd) -{ - return(dd->maxCacheHard); - -} /* end of Cudd_ReadMaxCache */ - - -/**Function******************************************************************** - - Synopsis [Sets the maxCacheHard parameter of the manager.] - - Description [Sets the maxCacheHard parameter of the manager. The - cache cannot grow larger than maxCacheHard entries. This parameter - allows an application to control the trade-off of memory versus - speed. If the value passed to this function is 0, the function - determines a suitable maximum cache size based on the available memory.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxCacheHard Cudd_SetMaxCache] - -******************************************************************************/ -void -Cudd_SetMaxCacheHard( - DdManager * dd, - unsigned int mc) -{ - if (mc == 0) { - long datalimit = getSoftDataLimit(); - mc = (unsigned int) (datalimit / (sizeof(DdCache) * - DD_MAX_CACHE_FRACTION)); - } - dd->maxCacheHard = mc; - -} /* end of Cudd_SetMaxCacheHard */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of BDD variables in existance.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadZddSize] - -******************************************************************************/ -int -Cudd_ReadSize( - DdManager * dd) -{ - return(dd->size); - -} /* end of Cudd_ReadSize */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of ZDD variables in existance.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadSize] - -******************************************************************************/ -int -Cudd_ReadZddSize( - DdManager * dd) -{ - return(dd->sizeZ); - -} /* end of Cudd_ReadZddSize */ - - -/**Function******************************************************************** - - Synopsis [Returns the total number of slots of the unique table.] - - Description [Returns the total number of slots of the unique table. - This number ismainly for diagnostic purposes.] - - SideEffects [None] - -******************************************************************************/ -unsigned int -Cudd_ReadSlots( - DdManager * dd) -{ - return(dd->slots); - -} /* end of Cudd_ReadSlots */ - - -/**Function******************************************************************** - - Synopsis [Reads the fraction of used slots in the unique table.] - - Description [Reads the fraction of used slots in the unique - table. The unused slots are those in which no valid data is - stored. Garbage collection, variable reordering, and subtable - resizing may cause used slots to become unused.] - - SideEffects [None] - - SeeAlso [Cudd_ReadSlots] - -******************************************************************************/ -double -Cudd_ReadUsedSlots( - DdManager * dd) -{ - unsigned long used = 0; - int i, j; - int size = dd->size; - DdNodePtr *nodelist; - DdSubtable *subtable; - DdNode *node; - DdNode *sentinel = &(dd->sentinel); - - /* Scan each BDD/ADD subtable. */ - for (i = 0; i < size; i++) { - subtable = &(dd->subtables[i]); - nodelist = subtable->nodelist; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - if (node != sentinel) { - used++; - } - } - } - - /* Scan the ZDD subtables. */ - size = dd->sizeZ; - - for (i = 0; i < size; i++) { - subtable = &(dd->subtableZ[i]); - nodelist = subtable->nodelist; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - if (node != NULL) { - used++; - } - } - } - - /* Constant table. */ - subtable = &(dd->constants); - nodelist = subtable->nodelist; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - if (node != NULL) { - used++; - } - } - - return((double)used / (double) dd->slots); - -} /* end of Cudd_ReadUsedSlots */ - - -/**Function******************************************************************** - - Synopsis [Computes the expected fraction of used slots in the unique - table.] - - Description [Computes the fraction of slots in the unique table that - should be in use. This expected value is based on the assumption - that the hash function distributes the keys randomly; it can be - compared with the result of Cudd_ReadUsedSlots to monitor the - performance of the unique table hash function.] - - SideEffects [None] - - SeeAlso [Cudd_ReadSlots Cudd_ReadUsedSlots] - -******************************************************************************/ -double -Cudd_ExpectedUsedSlots( - DdManager * dd) -{ - int i; - int size = dd->size; - DdSubtable *subtable; - double empty = 0.0; - - /* To each subtable we apply the corollary to Theorem 8.5 (occupancy - ** distribution) from Sedgewick and Flajolet's Analysis of Algorithms. - ** The corollary says that for a a table with M buckets and a load ratio - ** of r, the expected number of empty buckets is asymptotically given - ** by M * exp(-r). - */ - - /* Scan each BDD/ADD subtable. */ - for (i = 0; i < size; i++) { - subtable = &(dd->subtables[i]); - empty += (double) subtable->slots * - exp(-(double) subtable->keys / (double) subtable->slots); - } - - /* Scan the ZDD subtables. */ - size = dd->sizeZ; - - for (i = 0; i < size; i++) { - subtable = &(dd->subtableZ[i]); - empty += (double) subtable->slots * - exp(-(double) subtable->keys / (double) subtable->slots); - } - - /* Constant table. */ - subtable = &(dd->constants); - empty += (double) subtable->slots * - exp(-(double) subtable->keys / (double) subtable->slots); - - return(1.0 - empty / (double) dd->slots); - -} /* end of Cudd_ExpectedUsedSlots */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of nodes in the unique table.] - - Description [Returns the total number of nodes currently in the unique - table, including the dead nodes.] - - SideEffects [None] - - SeeAlso [Cudd_ReadDead] - -******************************************************************************/ -unsigned int -Cudd_ReadKeys( - DdManager * dd) -{ - return(dd->keys); - -} /* end of Cudd_ReadKeys */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of dead nodes in the unique table.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadKeys] - -******************************************************************************/ -unsigned int -Cudd_ReadDead( - DdManager * dd) -{ - return(dd->dead); - -} /* end of Cudd_ReadDead */ - - -/**Function******************************************************************** - - Synopsis [Reads the minDead parameter of the manager.] - - Description [Reads the minDead parameter of the manager. The minDead - parameter is used by the package to decide whether to collect garbage - or resize a subtable of the unique table when the subtable becomes - too full. The application can indirectly control the value of minDead - by setting the looseUpTo parameter.] - - SideEffects [None] - - SeeAlso [Cudd_ReadDead Cudd_ReadLooseUpTo Cudd_SetLooseUpTo] - -******************************************************************************/ -unsigned int -Cudd_ReadMinDead( - DdManager * dd) -{ - return(dd->minDead); - -} /* end of Cudd_ReadMinDead */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of times reordering has occurred.] - - Description [Returns the number of times reordering has occurred in the - manager. The number includes both the calls to Cudd_ReduceHeap from - the application program and those automatically performed by the - package. However, calls that do not even initiate reordering are not - counted. A call may not initiate reordering if there are fewer than - minsize live nodes in the manager, or if CUDD_REORDER_NONE is specified - as reordering method. The calls to Cudd_ShuffleHeap are not counted.] - - SideEffects [None] - - SeeAlso [Cudd_ReduceHeap Cudd_ReadReorderingTime] - -******************************************************************************/ -int -Cudd_ReadReorderings( - DdManager * dd) -{ - return(dd->reorderings); - -} /* end of Cudd_ReadReorderings */ - - -/**Function******************************************************************** - - Synopsis [Returns the time spent in reordering.] - - Description [Returns the number of milliseconds spent reordering - variables since the manager was initialized. The time spent in collecting - garbage before reordering is included.] - - SideEffects [None] - - SeeAlso [Cudd_ReadReorderings] - -******************************************************************************/ -long -Cudd_ReadReorderingTime( - DdManager * dd) -{ - return(dd->reordTime); - -} /* end of Cudd_ReadReorderingTime */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of times garbage collection has occurred.] - - Description [Returns the number of times garbage collection has - occurred in the manager. The number includes both the calls from - reordering procedures and those caused by requests to create new - nodes.] - - SideEffects [None] - - SeeAlso [Cudd_ReadGarbageCollectionTime] - -******************************************************************************/ -int -Cudd_ReadGarbageCollections( - DdManager * dd) -{ - return(dd->garbageCollections); - -} /* end of Cudd_ReadGarbageCollections */ - - -/**Function******************************************************************** - - Synopsis [Returns the time spent in garbage collection.] - - Description [Returns the number of milliseconds spent doing garbage - collection since the manager was initialized.] - - SideEffects [None] - - SeeAlso [Cudd_ReadGarbageCollections] - -******************************************************************************/ -long -Cudd_ReadGarbageCollectionTime( - DdManager * dd) -{ - return(dd->GCTime); - -} /* end of Cudd_ReadGarbageCollectionTime */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of nodes freed.] - - Description [Returns the number of nodes returned to the free list if the - keeping of this statistic is enabled; -1 otherwise. This statistic is - enabled only if the package is compiled with DD_STATS defined.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNodesDropped] - -******************************************************************************/ -double -Cudd_ReadNodesFreed( - DdManager * dd) -{ -#ifdef DD_STATS - return(dd->nodesFreed); -#else - return(-1.0); -#endif - -} /* end of Cudd_ReadNodesFreed */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of nodes dropped.] - - Description [Returns the number of nodes killed by dereferencing if the - keeping of this statistic is enabled; -1 otherwise. This statistic is - enabled only if the package is compiled with DD_STATS defined.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNodesFreed] - -******************************************************************************/ -double -Cudd_ReadNodesDropped( - DdManager * dd) -{ -#ifdef DD_STATS - return(dd->nodesDropped); -#else - return(-1.0); -#endif - -} /* end of Cudd_ReadNodesDropped */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of look-ups in the unique table.] - - Description [Returns the number of look-ups in the unique table if the - keeping of this statistic is enabled; -1 otherwise. This statistic is - enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.] - - SideEffects [None] - - SeeAlso [Cudd_ReadUniqueLinks] - -******************************************************************************/ -double -Cudd_ReadUniqueLookUps( - DdManager * dd) -{ -#ifdef DD_UNIQUE_PROFILE - return(dd->uniqueLookUps); -#else - return(-1.0); -#endif - -} /* end of Cudd_ReadUniqueLookUps */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of links followed in the unique table.] - - Description [Returns the number of links followed during look-ups in the - unique table if the keeping of this statistic is enabled; -1 otherwise. - If an item is found in the first position of its collision list, the - number of links followed is taken to be 0. If it is in second position, - the number of links is 1, and so on. This statistic is enabled only if - the package is compiled with DD_UNIQUE_PROFILE defined.] - - SideEffects [None] - - SeeAlso [Cudd_ReadUniqueLookUps] - -******************************************************************************/ -double -Cudd_ReadUniqueLinks( - DdManager * dd) -{ -#ifdef DD_UNIQUE_PROFILE - return(dd->uniqueLinks); -#else - return(-1.0); -#endif - -} /* end of Cudd_ReadUniqueLinks */ - - -/**Function******************************************************************** - - Synopsis [Reads the siftMaxVar parameter of the manager.] - - Description [Reads the siftMaxVar parameter of the manager. This - parameter gives the maximum number of variables that will be sifted - for each invocation of sifting.] - - SideEffects [None] - - SeeAlso [Cudd_ReadSiftMaxSwap Cudd_SetSiftMaxVar] - -******************************************************************************/ -int -Cudd_ReadSiftMaxVar( - DdManager * dd) -{ - return(dd->siftMaxVar); - -} /* end of Cudd_ReadSiftMaxVar */ - - -/**Function******************************************************************** - - Synopsis [Sets the siftMaxVar parameter of the manager.] - - Description [Sets the siftMaxVar parameter of the manager. This - parameter gives the maximum number of variables that will be sifted - for each invocation of sifting.] - - SideEffects [None] - - SeeAlso [Cudd_SetSiftMaxSwap Cudd_ReadSiftMaxVar] - -******************************************************************************/ -void -Cudd_SetSiftMaxVar( - DdManager * dd, - int smv) -{ - dd->siftMaxVar = smv; - -} /* end of Cudd_SetSiftMaxVar */ - - -/**Function******************************************************************** - - Synopsis [Reads the siftMaxSwap parameter of the manager.] - - Description [Reads the siftMaxSwap parameter of the manager. This - parameter gives the maximum number of swaps that will be attempted - for each invocation of sifting. The real number of swaps may exceed - the set limit because the package will always complete the sifting - of the variable that causes the limit to be reached.] - - SideEffects [None] - - SeeAlso [Cudd_ReadSiftMaxVar Cudd_SetSiftMaxSwap] - -******************************************************************************/ -int -Cudd_ReadSiftMaxSwap( - DdManager * dd) -{ - return(dd->siftMaxSwap); - -} /* end of Cudd_ReadSiftMaxSwap */ - - -/**Function******************************************************************** - - Synopsis [Sets the siftMaxSwap parameter of the manager.] - - Description [Sets the siftMaxSwap parameter of the manager. This - parameter gives the maximum number of swaps that will be attempted - for each invocation of sifting. The real number of swaps may exceed - the set limit because the package will always complete the sifting - of the variable that causes the limit to be reached.] - - SideEffects [None] - - SeeAlso [Cudd_SetSiftMaxVar Cudd_ReadSiftMaxSwap] - -******************************************************************************/ -void -Cudd_SetSiftMaxSwap( - DdManager * dd, - int sms) -{ - dd->siftMaxSwap = sms; - -} /* end of Cudd_SetSiftMaxSwap */ - - -/**Function******************************************************************** - - Synopsis [Reads the maxGrowth parameter of the manager.] - - Description [Reads the maxGrowth parameter of the manager. This - parameter determines how much the number of nodes can grow during - sifting of a variable. Overall, sifting never increases the size of - the decision diagrams. This parameter only refers to intermediate - results. A lower value will speed up sifting, possibly at the - expense of quality.] - - SideEffects [None] - - SeeAlso [Cudd_SetMaxGrowth Cudd_ReadMaxGrowthAlternate] - -******************************************************************************/ -double -Cudd_ReadMaxGrowth( - DdManager * dd) -{ - return(dd->maxGrowth); - -} /* end of Cudd_ReadMaxGrowth */ - - -/**Function******************************************************************** - - Synopsis [Sets the maxGrowth parameter of the manager.] - - Description [Sets the maxGrowth parameter of the manager. This - parameter determines how much the number of nodes can grow during - sifting of a variable. Overall, sifting never increases the size of - the decision diagrams. This parameter only refers to intermediate - results. A lower value will speed up sifting, possibly at the - expense of quality.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate] - -******************************************************************************/ -void -Cudd_SetMaxGrowth( - DdManager * dd, - double mg) -{ - dd->maxGrowth = mg; - -} /* end of Cudd_SetMaxGrowth */ - - -/**Function******************************************************************** - - Synopsis [Reads the maxGrowthAlt parameter of the manager.] - - Description [Reads the maxGrowthAlt parameter of the manager. This - parameter is analogous to the maxGrowth paramter, and is used every - given number of reorderings instead of maxGrowth. The number of - reorderings is set with Cudd_SetReorderingCycle. If the number of - reorderings is 0 (default) maxGrowthAlt is never used.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate - Cudd_SetReorderingCycle Cudd_ReadReorderingCycle] - -******************************************************************************/ -double -Cudd_ReadMaxGrowthAlternate( - DdManager * dd) -{ - return(dd->maxGrowthAlt); - -} /* end of Cudd_ReadMaxGrowthAlternate */ - - -/**Function******************************************************************** - - Synopsis [Sets the maxGrowthAlt parameter of the manager.] - - Description [Sets the maxGrowthAlt parameter of the manager. This - parameter is analogous to the maxGrowth paramter, and is used every - given number of reorderings instead of maxGrowth. The number of - reorderings is set with Cudd_SetReorderingCycle. If the number of - reorderings is 0 (default) maxGrowthAlt is never used.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowth - Cudd_SetReorderingCycle Cudd_ReadReorderingCycle] - -******************************************************************************/ -void -Cudd_SetMaxGrowthAlternate( - DdManager * dd, - double mg) -{ - dd->maxGrowthAlt = mg; - -} /* end of Cudd_SetMaxGrowthAlternate */ - - -/**Function******************************************************************** - - Synopsis [Reads the reordCycle parameter of the manager.] - - Description [Reads the reordCycle parameter of the manager. This - parameter determines how often the alternate threshold on maximum - growth is used in reordering.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate - Cudd_SetReorderingCycle] - -******************************************************************************/ -int -Cudd_ReadReorderingCycle( - DdManager * dd) -{ - return(dd->reordCycle); - -} /* end of Cudd_ReadReorderingCycle */ - - -/**Function******************************************************************** - - Synopsis [Sets the reordCycle parameter of the manager.] - - Description [Sets the reordCycle parameter of the manager. This - parameter determines how often the alternate threshold on maximum - growth is used in reordering.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate - Cudd_ReadReorderingCycle] - -******************************************************************************/ -void -Cudd_SetReorderingCycle( - DdManager * dd, - int cycle) -{ - dd->reordCycle = cycle; - -} /* end of Cudd_SetReorderingCycle */ - - -/**Function******************************************************************** - - Synopsis [Returns the variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetTree Cudd_FreeTree Cudd_ReadZddTree] - -******************************************************************************/ -MtrNode * -Cudd_ReadTree( - DdManager * dd) -{ - return(dd->tree); - -} /* end of Cudd_ReadTree */ - - -/**Function******************************************************************** - - Synopsis [Sets the variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_FreeTree Cudd_ReadTree Cudd_SetZddTree] - -******************************************************************************/ -void -Cudd_SetTree( - DdManager * dd, - MtrNode * tree) -{ - if (dd->tree != NULL) { - Mtr_FreeTree(dd->tree); - } - dd->tree = tree; - if (tree == NULL) return; - - fixVarTree(tree, dd->perm, dd->size); - return; - -} /* end of Cudd_SetTree */ - - -/**Function******************************************************************** - - Synopsis [Frees the variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetTree Cudd_ReadTree Cudd_FreeZddTree] - -******************************************************************************/ -void -Cudd_FreeTree( - DdManager * dd) -{ - if (dd->tree != NULL) { - Mtr_FreeTree(dd->tree); - dd->tree = NULL; - } - return; - -} /* end of Cudd_FreeTree */ - - -/**Function******************************************************************** - - Synopsis [Returns the variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetZddTree Cudd_FreeZddTree Cudd_ReadTree] - -******************************************************************************/ -MtrNode * -Cudd_ReadZddTree( - DdManager * dd) -{ - return(dd->treeZ); - -} /* end of Cudd_ReadZddTree */ - - -/**Function******************************************************************** - - Synopsis [Sets the ZDD variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_FreeZddTree Cudd_ReadZddTree Cudd_SetTree] - -******************************************************************************/ -void -Cudd_SetZddTree( - DdManager * dd, - MtrNode * tree) -{ - if (dd->treeZ != NULL) { - Mtr_FreeTree(dd->treeZ); - } - dd->treeZ = tree; - if (tree == NULL) return; - - fixVarTree(tree, dd->permZ, dd->sizeZ); - return; - -} /* end of Cudd_SetZddTree */ - - -/**Function******************************************************************** - - Synopsis [Frees the variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetZddTree Cudd_ReadZddTree Cudd_FreeTree] - -******************************************************************************/ -void -Cudd_FreeZddTree( - DdManager * dd) -{ - if (dd->treeZ != NULL) { - Mtr_FreeTree(dd->treeZ); - dd->treeZ = NULL; - } - return; - -} /* end of Cudd_FreeZddTree */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of the node.] - - Description [Returns the index of the node. The node pointer can be - either regular or complemented.] - - SideEffects [None] - - SeeAlso [Cudd_ReadIndex] - -******************************************************************************/ -unsigned int -Cudd_NodeReadIndex( - DdNode * node) -{ - return((unsigned int) Cudd_Regular(node)->index); - -} /* end of Cudd_NodeReadIndex */ - - -/**Function******************************************************************** - - Synopsis [Returns the current position of the i-th variable in the - order.] - - Description [Returns the current position of the i-th variable in - the order. If the index is CUDD_CONST_INDEX, returns - CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns - -1.] - - SideEffects [None] - - SeeAlso [Cudd_ReadInvPerm Cudd_ReadPermZdd] - -******************************************************************************/ -int -Cudd_ReadPerm( - DdManager * dd, - int i) -{ - if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); - if (i < 0 || i >= dd->size) return(-1); - return(dd->perm[i]); - -} /* end of Cudd_ReadPerm */ - - -/**Function******************************************************************** - - Synopsis [Returns the current position of the i-th ZDD variable in the - order.] - - Description [Returns the current position of the i-th ZDD variable - in the order. If the index is CUDD_CONST_INDEX, returns - CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns - -1.] - - SideEffects [None] - - SeeAlso [Cudd_ReadInvPermZdd Cudd_ReadPerm] - -******************************************************************************/ -int -Cudd_ReadPermZdd( - DdManager * dd, - int i) -{ - if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); - if (i < 0 || i >= dd->sizeZ) return(-1); - return(dd->permZ[i]); - -} /* end of Cudd_ReadPermZdd */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of the variable currently in the i-th - position of the order.] - - Description [Returns the index of the variable currently in the i-th - position of the order. If the index is CUDD_CONST_INDEX, returns - CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.] - - SideEffects [None] - - SeeAlso [Cudd_ReadPerm Cudd_ReadInvPermZdd] - -******************************************************************************/ -int -Cudd_ReadInvPerm( - DdManager * dd, - int i) -{ - if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); - if (i < 0 || i >= dd->size) return(-1); - return(dd->invperm[i]); - -} /* end of Cudd_ReadInvPerm */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of the ZDD variable currently in the i-th - position of the order.] - - Description [Returns the index of the ZDD variable currently in the - i-th position of the order. If the index is CUDD_CONST_INDEX, returns - CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.] - - SideEffects [None] - - SeeAlso [Cudd_ReadPerm Cudd_ReadInvPermZdd] - -******************************************************************************/ -int -Cudd_ReadInvPermZdd( - DdManager * dd, - int i) -{ - if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); - if (i < 0 || i >= dd->sizeZ) return(-1); - return(dd->invpermZ[i]); - -} /* end of Cudd_ReadInvPermZdd */ - - -/**Function******************************************************************** - - Synopsis [Returns the i-th element of the vars array.] - - Description [Returns the i-th element of the vars array if it falls - within the array bounds; NULL otherwise. If i is the index of an - existing variable, this function produces the same result as - Cudd_bddIthVar. However, if the i-th var does not exist yet, - Cudd_bddIthVar will create it, whereas Cudd_ReadVars will not.] - - SideEffects [None] - - SeeAlso [Cudd_bddIthVar] - -******************************************************************************/ -DdNode * -Cudd_ReadVars( - DdManager * dd, - int i) -{ - if (i < 0 || i > dd->size) return(NULL); - return(dd->vars[i]); - -} /* end of Cudd_ReadVars */ - - -/**Function******************************************************************** - - Synopsis [Reads the epsilon parameter of the manager.] - - Description [Reads the epsilon parameter of the manager. The epsilon - parameter control the comparison between floating point numbers.] - - SideEffects [None] - - SeeAlso [Cudd_SetEpsilon] - -******************************************************************************/ -CUDD_VALUE_TYPE -Cudd_ReadEpsilon( - DdManager * dd) -{ - return(dd->epsilon); - -} /* end of Cudd_ReadEpsilon */ - - -/**Function******************************************************************** - - Synopsis [Sets the epsilon parameter of the manager to ep.] - - Description [Sets the epsilon parameter of the manager to ep. The epsilon - parameter control the comparison between floating point numbers.] - - SideEffects [None] - - SeeAlso [Cudd_ReadEpsilon] - -******************************************************************************/ -void -Cudd_SetEpsilon( - DdManager * dd, - CUDD_VALUE_TYPE ep) -{ - dd->epsilon = ep; - -} /* end of Cudd_SetEpsilon */ - - -/**Function******************************************************************** - - Synopsis [Reads the groupcheck parameter of the manager.] - - Description [Reads the groupcheck parameter of the manager. The - groupcheck parameter determines the aggregation criterion in group - sifting.] - - SideEffects [None] - - SeeAlso [Cudd_SetGroupcheck] - -******************************************************************************/ -Cudd_AggregationType -Cudd_ReadGroupcheck( - DdManager * dd) -{ - return(dd->groupcheck); - -} /* end of Cudd_ReadGroupCheck */ - - -/**Function******************************************************************** - - Synopsis [Sets the parameter groupcheck of the manager to gc.] - - Description [Sets the parameter groupcheck of the manager to gc. The - groupcheck parameter determines the aggregation criterion in group - sifting.] - - SideEffects [None] - - SeeAlso [Cudd_ReadGroupCheck] - -******************************************************************************/ -void -Cudd_SetGroupcheck( - DdManager * dd, - Cudd_AggregationType gc) -{ - dd->groupcheck = gc; - -} /* end of Cudd_SetGroupcheck */ - - -/**Function******************************************************************** - - Synopsis [Tells whether garbage collection is enabled.] - - Description [Returns 1 if garbage collection is enabled; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_EnableGarbageCollection Cudd_DisableGarbageCollection] - -******************************************************************************/ -int -Cudd_GarbageCollectionEnabled( - DdManager * dd) -{ - return(dd->gcEnabled); - -} /* end of Cudd_GarbageCollectionEnabled */ - - -/**Function******************************************************************** - - Synopsis [Enables garbage collection.] - - Description [Enables garbage collection. Garbage collection is - initially enabled. Therefore it is necessary to call this function - only if garbage collection has been explicitly disabled.] - - SideEffects [None] - - SeeAlso [Cudd_DisableGarbageCollection Cudd_GarbageCollectionEnabled] - -******************************************************************************/ -void -Cudd_EnableGarbageCollection( - DdManager * dd) -{ - dd->gcEnabled = 1; - -} /* end of Cudd_EnableGarbageCollection */ - - -/**Function******************************************************************** - - Synopsis [Disables garbage collection.] - - Description [Disables garbage collection. Garbage collection is - initially enabled. This function may be called to disable it. - However, garbage collection will still occur when a new node must be - created and no memory is left, or when garbage collection is required - for correctness. (E.g., before reordering.)] - - SideEffects [None] - - SeeAlso [Cudd_EnableGarbageCollection Cudd_GarbageCollectionEnabled] - -******************************************************************************/ -void -Cudd_DisableGarbageCollection( - DdManager * dd) -{ - dd->gcEnabled = 0; - -} /* end of Cudd_DisableGarbageCollection */ - - -/**Function******************************************************************** - - Synopsis [Tells whether dead nodes are counted towards triggering - reordering.] - - Description [Tells whether dead nodes are counted towards triggering - reordering. Returns 1 if dead nodes are counted; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_TurnOnCountDead Cudd_TurnOffCountDead] - -******************************************************************************/ -int -Cudd_DeadAreCounted( - DdManager * dd) -{ - return(dd->countDead == 0 ? 1 : 0); - -} /* end of Cudd_DeadAreCounted */ - - -/**Function******************************************************************** - - Synopsis [Causes the dead nodes to be counted towards triggering - reordering.] - - Description [Causes the dead nodes to be counted towards triggering - reordering. This causes more frequent reorderings. By default dead - nodes are not counted.] - - SideEffects [Changes the manager.] - - SeeAlso [Cudd_TurnOffCountDead Cudd_DeadAreCounted] - -******************************************************************************/ -void -Cudd_TurnOnCountDead( - DdManager * dd) -{ - dd->countDead = 0; - -} /* end of Cudd_TurnOnCountDead */ - - -/**Function******************************************************************** - - Synopsis [Causes the dead nodes not to be counted towards triggering - reordering.] - - Description [Causes the dead nodes not to be counted towards - triggering reordering. This causes less frequent reorderings. By - default dead nodes are not counted. Therefore there is no need to - call this function unless Cudd_TurnOnCountDead has been previously - called.] - - SideEffects [Changes the manager.] - - SeeAlso [Cudd_TurnOnCountDead Cudd_DeadAreCounted] - -******************************************************************************/ -void -Cudd_TurnOffCountDead( - DdManager * dd) -{ - dd->countDead = ~0; - -} /* end of Cudd_TurnOffCountDead */ - - -/**Function******************************************************************** - - Synopsis [Returns the current value of the recombination parameter used - in group sifting.] - - Description [Returns the current value of the recombination - parameter used in group sifting. A larger (positive) value makes the - aggregation of variables due to the second difference criterion more - likely. A smaller (negative) value makes aggregation less likely.] - - SideEffects [None] - - SeeAlso [Cudd_SetRecomb] - -******************************************************************************/ -int -Cudd_ReadRecomb( - DdManager * dd) -{ - return(dd->recomb); - -} /* end of Cudd_ReadRecomb */ - - -/**Function******************************************************************** - - Synopsis [Sets the value of the recombination parameter used in group - sifting.] - - Description [Sets the value of the recombination parameter used in - group sifting. A larger (positive) value makes the aggregation of - variables due to the second difference criterion more likely. A - smaller (negative) value makes aggregation less likely. The default - value is 0.] - - SideEffects [Changes the manager.] - - SeeAlso [Cudd_ReadRecomb] - -******************************************************************************/ -void -Cudd_SetRecomb( - DdManager * dd, - int recomb) -{ - dd->recomb = recomb; - -} /* end of Cudd_SetRecomb */ - - -/**Function******************************************************************** - - Synopsis [Returns the current value of the symmviolation parameter used - in group sifting.] - - Description [Returns the current value of the symmviolation - parameter. This parameter is used in group sifting to decide how - many violations to the symmetry conditions <code>f10 = f01</code> or - <code>f11 = f00</code> are tolerable when checking for aggregation - due to extended symmetry. The value should be between 0 and 100. A - small value causes fewer variables to be aggregated. The default - value is 0.] - - SideEffects [None] - - SeeAlso [Cudd_SetSymmviolation] - -******************************************************************************/ -int -Cudd_ReadSymmviolation( - DdManager * dd) -{ - return(dd->symmviolation); - -} /* end of Cudd_ReadSymmviolation */ - - -/**Function******************************************************************** - - Synopsis [Sets the value of the symmviolation parameter used - in group sifting.] - - Description [Sets the value of the symmviolation - parameter. This parameter is used in group sifting to decide how - many violations to the symmetry conditions <code>f10 = f01</code> or - <code>f11 = f00</code> are tolerable when checking for aggregation - due to extended symmetry. The value should be between 0 and 100. A - small value causes fewer variables to be aggregated. The default - value is 0.] - - SideEffects [Changes the manager.] - - SeeAlso [Cudd_ReadSymmviolation] - -******************************************************************************/ -void -Cudd_SetSymmviolation( - DdManager * dd, - int symmviolation) -{ - dd->symmviolation = symmviolation; - -} /* end of Cudd_SetSymmviolation */ - - -/**Function******************************************************************** - - Synopsis [Returns the current value of the arcviolation parameter used - in group sifting.] - - Description [Returns the current value of the arcviolation - parameter. This parameter is used in group sifting to decide how - many arcs into <code>y</code> not coming from <code>x</code> are - tolerable when checking for aggregation due to extended - symmetry. The value should be between 0 and 100. A small value - causes fewer variables to be aggregated. The default value is 0.] - - SideEffects [None] - - SeeAlso [Cudd_SetArcviolation] - -******************************************************************************/ -int -Cudd_ReadArcviolation( - DdManager * dd) -{ - return(dd->arcviolation); - -} /* end of Cudd_ReadArcviolation */ - - -/**Function******************************************************************** - - Synopsis [Sets the value of the arcviolation parameter used - in group sifting.] - - Description [Sets the value of the arcviolation - parameter. This parameter is used in group sifting to decide how - many arcs into <code>y</code> not coming from <code>x</code> are - tolerable when checking for aggregation due to extended - symmetry. The value should be between 0 and 100. A small value - causes fewer variables to be aggregated. The default value is 0.] - - SideEffects [None] - - SeeAlso [Cudd_ReadArcviolation] - -******************************************************************************/ -void -Cudd_SetArcviolation( - DdManager * dd, - int arcviolation) -{ - dd->arcviolation = arcviolation; - -} /* end of Cudd_SetArcviolation */ - - -/**Function******************************************************************** - - Synopsis [Reads the current size of the population used by the - genetic algorithm for reordering.] - - Description [Reads the current size of the population used by the - genetic algorithm for variable reordering. A larger population size will - cause the genetic algorithm to take more time, but will generally - produce better results. The default value is 0, in which case the - package uses three times the number of variables as population size, - with a maximum of 120.] - - SideEffects [None] - - SeeAlso [Cudd_SetPopulationSize] - -******************************************************************************/ -int -Cudd_ReadPopulationSize( - DdManager * dd) -{ - return(dd->populationSize); - -} /* end of Cudd_ReadPopulationSize */ - - -/**Function******************************************************************** - - Synopsis [Sets the size of the population used by the - genetic algorithm for reordering.] - - Description [Sets the size of the population used by the - genetic algorithm for variable reordering. A larger population size will - cause the genetic algorithm to take more time, but will generally - produce better results. The default value is 0, in which case the - package uses three times the number of variables as population size, - with a maximum of 120.] - - SideEffects [Changes the manager.] - - SeeAlso [Cudd_ReadPopulationSize] - -******************************************************************************/ -void -Cudd_SetPopulationSize( - DdManager * dd, - int populationSize) -{ - dd->populationSize = populationSize; - -} /* end of Cudd_SetPopulationSize */ - - -/**Function******************************************************************** - - Synopsis [Reads the current number of crossovers used by the - genetic algorithm for reordering.] - - Description [Reads the current number of crossovers used by the - genetic algorithm for variable reordering. A larger number of crossovers will - cause the genetic algorithm to take more time, but will generally - produce better results. The default value is 0, in which case the - package uses three times the number of variables as number of crossovers, - with a maximum of 60.] - - SideEffects [None] - - SeeAlso [Cudd_SetNumberXovers] - -******************************************************************************/ -int -Cudd_ReadNumberXovers( - DdManager * dd) -{ - return(dd->numberXovers); - -} /* end of Cudd_ReadNumberXovers */ - - -/**Function******************************************************************** - - Synopsis [Sets the number of crossovers used by the - genetic algorithm for reordering.] - - Description [Sets the number of crossovers used by the genetic - algorithm for variable reordering. A larger number of crossovers - will cause the genetic algorithm to take more time, but will - generally produce better results. The default value is 0, in which - case the package uses three times the number of variables as number - of crossovers, with a maximum of 60.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNumberXovers] - -******************************************************************************/ -void -Cudd_SetNumberXovers( - DdManager * dd, - int numberXovers) -{ - dd->numberXovers = numberXovers; - -} /* end of Cudd_SetNumberXovers */ - -/**Function******************************************************************** - - Synopsis [Returns the memory in use by the manager measured in bytes.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -long -Cudd_ReadMemoryInUse( - DdManager * dd) -{ - return(dd->memused); - -} /* end of Cudd_ReadMemoryInUse */ - - -/**Function******************************************************************** - - Synopsis [Prints out statistics and settings for a CUDD manager.] - - Description [Prints out statistics and settings for a CUDD manager. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_PrintInfo( - DdManager * dd, - FILE * fp) -{ - int retval; - Cudd_ReorderingType autoMethod, autoMethodZ; - - /* Modifiable parameters. */ - retval = fprintf(fp,"**** CUDD modifiable parameters ****\n"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Hard limit for cache size: %u\n", - Cudd_ReadMaxCacheHard(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache hit threshold for resizing: %u%%\n", - Cudd_ReadMinHit(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Garbage collection enabled: %s\n", - Cudd_GarbageCollectionEnabled(dd) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Limit for fast unique table growth: %u\n", - Cudd_ReadLooseUpTo(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp, - "Maximum number of variables sifted per reordering: %d\n", - Cudd_ReadSiftMaxVar(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp, - "Maximum number of variable swaps per reordering: %d\n", - Cudd_ReadSiftMaxSwap(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Maximum growth while sifting a variable: %g\n", - Cudd_ReadMaxGrowth(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Dynamic reordering of BDDs enabled: %s\n", - Cudd_ReorderingStatus(dd,&autoMethod) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Default BDD reordering method: %d\n", autoMethod); - if (retval == EOF) return(0); - retval = fprintf(fp,"Dynamic reordering of ZDDs enabled: %s\n", - Cudd_ReorderingStatusZdd(dd,&autoMethodZ) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Default ZDD reordering method: %d\n", autoMethodZ); - if (retval == EOF) return(0); - retval = fprintf(fp,"Realignment of ZDDs to BDDs enabled: %s\n", - Cudd_zddRealignmentEnabled(dd) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Realignment of BDDs to ZDDs enabled: %s\n", - Cudd_bddRealignmentEnabled(dd) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Dead nodes counted in triggering reordering: %s\n", - Cudd_DeadAreCounted(dd) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Group checking criterion: %d\n", - Cudd_ReadGroupcheck(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Recombination threshold: %d\n", Cudd_ReadRecomb(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Symmetry violation threshold: %d\n", - Cudd_ReadSymmviolation(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Arc violation threshold: %d\n", - Cudd_ReadArcviolation(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"GA population size: %d\n", - Cudd_ReadPopulationSize(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of crossovers for GA: %d\n", - Cudd_ReadNumberXovers(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Next reordering threshold: %u\n", - Cudd_ReadNextReordering(dd)); - if (retval == EOF) return(0); - - /* Non-modifiable parameters. */ - retval = fprintf(fp,"**** CUDD non-modifiable parameters ****\n"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Memory in use: %ld\n", Cudd_ReadMemoryInUse(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Peak number of nodes: %ld\n", - Cudd_ReadPeakNodeCount(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Peak number of live nodes: %d\n", - Cudd_ReadPeakLiveNodeCount(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of BDD variables: %d\n", dd->size); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of ZDD variables: %d\n", dd->sizeZ); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache entries: %u\n", dd->cacheSlots); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache look-ups: %.0f\n", - Cudd_ReadCacheLookUps(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache hits: %.0f\n", - Cudd_ReadCacheHits(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache insertions: %.0f\n", - dd->cacheinserts); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache collisions: %.0f\n", - dd->cachecollisions); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache deletions: %.0f\n", - dd->cachedeletions); - if (retval == EOF) return(0); - retval = cuddCacheProfile(dd,fp); - if (retval == 0) return(0); - retval = fprintf(fp,"Soft limit for cache size: %u\n", - Cudd_ReadMaxCache(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of buckets in unique table: %u\n", dd->slots); - if (retval == EOF) return(0); - retval = fprintf(fp,"Used buckets in unique table: %.2f%% (expected %.2f%%)\n", - 100.0 * Cudd_ReadUsedSlots(dd), - 100.0 * Cudd_ExpectedUsedSlots(dd)); - if (retval == EOF) return(0); -#ifdef DD_UNIQUE_PROFILE - retval = fprintf(fp,"Unique lookups: %.0f\n", dd->uniqueLookUps); - if (retval == EOF) return(0); - retval = fprintf(fp,"Unique links: %.0f (%g per lookup)\n", - dd->uniqueLinks, dd->uniqueLinks / dd->uniqueLookUps); - if (retval == EOF) return(0); -#endif - retval = fprintf(fp,"Number of BDD and ADD nodes: %u\n", dd->keys); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of ZDD nodes: %u\n", dd->keysZ); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of dead BDD and ADD nodes: %u\n", dd->dead); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of dead ZDD nodes: %u\n", dd->deadZ); - if (retval == EOF) return(0); - retval = fprintf(fp,"Total number of nodes allocated: %.0f\n", - dd->allocated); - if (retval == EOF) return(0); - retval = fprintf(fp,"Total number of nodes reclaimed: %.0f\n", - dd->reclaimed); - if (retval == EOF) return(0); -#if DD_STATS - retval = fprintf(fp,"Nodes freed: %.0f\n", dd->nodesFreed); - if (retval == EOF) return(0); - retval = fprintf(fp,"Nodes dropped: %.0f\n", dd->nodesDropped); - if (retval == EOF) return(0); -#endif -#if DD_COUNT - retval = fprintf(fp,"Number of recursive calls: %.0f\n", - Cudd_ReadRecursiveCalls(dd)); - if (retval == EOF) return(0); -#endif - retval = fprintf(fp,"Garbage collections so far: %d\n", - Cudd_ReadGarbageCollections(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Time for garbage collection: %.2f sec\n", - ((double)Cudd_ReadGarbageCollectionTime(dd)/1000.0)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Reorderings so far: %d\n", dd->reorderings); - if (retval == EOF) return(0); - retval = fprintf(fp,"Time for reordering: %.2f sec\n", - ((double)Cudd_ReadReorderingTime(dd)/1000.0)); - if (retval == EOF) return(0); -#if DD_COUNT - retval = fprintf(fp,"Node swaps in reordering: %.0f\n", - Cudd_ReadSwapSteps(dd)); - if (retval == EOF) return(0); -#endif - - return(1); - -} /* end of Cudd_PrintInfo */ - - -/**Function******************************************************************** - - Synopsis [Reports the peak number of nodes.] - - Description [Reports the peak number of nodes. This number includes - node on the free list. At the peak, the number of nodes on the free - list is guaranteed to be less than DD_MEM_CHUNK.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNodeCount Cudd_PrintInfo] - -******************************************************************************/ -long -Cudd_ReadPeakNodeCount( - DdManager * dd) -{ - long count = 0; - DdNodePtr *scan = dd->memoryList; - - while (scan != NULL) { - count += DD_MEM_CHUNK; - scan = (DdNodePtr *) *scan; - } - return(count); - -} /* end of Cudd_ReadPeakNodeCount */ - - -/**Function******************************************************************** - - Synopsis [Reports the peak number of live nodes.] - - Description [Reports the peak number of live nodes. This count is kept - only if CUDD is compiled with DD_STATS defined. If DD_STATS is not - defined, this function returns -1.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNodeCount Cudd_PrintInfo Cudd_ReadPeakNodeCount] - -******************************************************************************/ -int -Cudd_ReadPeakLiveNodeCount( - DdManager * dd) -{ - unsigned int live = dd->keys - dd->dead; - - if (live > dd->peakLiveNodes) { - dd->peakLiveNodes = live; - } - return((int)dd->peakLiveNodes); - -} /* end of Cudd_ReadPeakLiveNodeCount */ - - -/**Function******************************************************************** - - Synopsis [Reports the number of nodes in BDDs and ADDs.] - - Description [Reports the number of live nodes in BDDs and ADDs. This - number does not include the isolated projection functions and the - unused constants. These nodes that are not counted are not part of - the DDs manipulated by the application.] - - SideEffects [None] - - SeeAlso [Cudd_ReadPeakNodeCount Cudd_zddReadNodeCount] - -******************************************************************************/ -long -Cudd_ReadNodeCount( - DdManager * dd) -{ - long count; - int i; - -#ifndef DD_NO_DEATH_ROW - cuddClearDeathRow(dd); -#endif - - count = dd->keys - dd->dead; - - /* Count isolated projection functions. Their number is subtracted - ** from the node count because they are not part of the BDDs. - */ - for (i=0; i < dd->size; i++) { - if (dd->vars[i]->ref == 1) count--; - } - /* Subtract from the count the unused constants. */ - if (DD_ZERO(dd)->ref == 1) count--; - if (DD_PLUS_INFINITY(dd)->ref == 1) count--; - if (DD_MINUS_INFINITY(dd)->ref == 1) count--; - - return(count); - -} /* end of Cudd_ReadNodeCount */ - - - -/**Function******************************************************************** - - Synopsis [Reports the number of nodes in ZDDs.] - - Description [Reports the number of nodes in ZDDs. This - number always includes the two constants 1 and 0.] - - SideEffects [None] - - SeeAlso [Cudd_ReadPeakNodeCount Cudd_ReadNodeCount] - -******************************************************************************/ -long -Cudd_zddReadNodeCount( - DdManager * dd) -{ - return(dd->keysZ - dd->deadZ + 2); - -} /* end of Cudd_zddReadNodeCount */ - - -/**Function******************************************************************** - - Synopsis [Adds a function to a hook.] - - Description [Adds a function to a hook. A hook is a list of - application-provided functions called on certain occasions by the - package. Returns 1 if the function is successfully added; 2 if the - function was already in the list; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_RemoveHook] - -******************************************************************************/ -int -Cudd_AddHook( - DdManager * dd, - int (*f)(DdManager *, char *, void *) , - Cudd_HookType where) -{ - DdHook **hook, *nextHook, *newHook; - - switch (where) { - case CUDD_PRE_GC_HOOK: - hook = &(dd->preGCHook); - break; - case CUDD_POST_GC_HOOK: - hook = &(dd->postGCHook); - break; - case CUDD_PRE_REORDERING_HOOK: - hook = &(dd->preReorderingHook); - break; - case CUDD_POST_REORDERING_HOOK: - hook = &(dd->postReorderingHook); - break; - default: - return(0); - } - /* Scan the list and find whether the function is already there. - ** If so, just return. */ - nextHook = *hook; - while (nextHook != NULL) { - if (nextHook->f == f) { - return(2); - } - hook = &(nextHook->next); - nextHook = nextHook->next; - } - /* The function was not in the list. Create a new item and append it - ** to the end of the list. */ - newHook = ALLOC(DdHook,1); - if (newHook == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newHook->next = NULL; - newHook->f = f; - *hook = newHook; - return(1); - -} /* end of Cudd_AddHook */ - - -/**Function******************************************************************** - - Synopsis [Removes a function from a hook.] - - Description [Removes a function from a hook. A hook is a list of - application-provided functions called on certain occasions by the - package. Returns 1 if successful; 0 the function was not in the list.] - - SideEffects [None] - - SeeAlso [Cudd_AddHook] - -******************************************************************************/ -int -Cudd_RemoveHook( - DdManager * dd, - int (*f)(DdManager *, char *, void *) , - Cudd_HookType where) -{ - DdHook **hook, *nextHook; - - switch (where) { - case CUDD_PRE_GC_HOOK: - hook = &(dd->preGCHook); - break; - case CUDD_POST_GC_HOOK: - hook = &(dd->postGCHook); - break; - case CUDD_PRE_REORDERING_HOOK: - hook = &(dd->preReorderingHook); - break; - case CUDD_POST_REORDERING_HOOK: - hook = &(dd->postReorderingHook); - break; - default: - return(0); - } - nextHook = *hook; - while (nextHook != NULL) { - if (nextHook->f == f) { - *hook = nextHook->next; - FREE(nextHook); - return(1); - } - hook = &(nextHook->next); - nextHook = nextHook->next; - } - - return(0); - -} /* end of Cudd_RemoveHook */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a function is in a hook.] - - Description [Checks whether a function is in a hook. A hook is a list of - application-provided functions called on certain occasions by the - package. Returns 1 if the function is found; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_AddHook Cudd_RemoveHook] - -******************************************************************************/ -int -Cudd_IsInHook( - DdManager * dd, - int (*f)(DdManager *, char *, void *) , - Cudd_HookType where) -{ - DdHook *hook; - - switch (where) { - case CUDD_PRE_GC_HOOK: - hook = dd->preGCHook; - break; - case CUDD_POST_GC_HOOK: - hook = dd->postGCHook; - break; - case CUDD_PRE_REORDERING_HOOK: - hook = dd->preReorderingHook; - break; - case CUDD_POST_REORDERING_HOOK: - hook = dd->postReorderingHook; - break; - default: - return(0); - } - /* Scan the list and find whether the function is already there. */ - while (hook != NULL) { - if (hook->f == f) { - return(1); - } - hook = hook->next; - } - return(0); - -} /* end of Cudd_IsInHook */ - - -/**Function******************************************************************** - - Synopsis [Sample hook function to call before reordering.] - - Description [Sample hook function to call before reordering. - Prints on the manager's stdout reordering method and initial size. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_StdPostReordHook] - -******************************************************************************/ -int -Cudd_StdPreReordHook( - DdManager *dd, - char *str, - void *data) -{ - Cudd_ReorderingType method = (Cudd_ReorderingType) (ptruint) data; - int retval; - - retval = fprintf(dd->out,"%s reordering with ", str); - if (retval == EOF) return(0); - switch (method) { - case CUDD_REORDER_SIFT_CONVERGE: - case CUDD_REORDER_SYMM_SIFT_CONV: - case CUDD_REORDER_GROUP_SIFT_CONV: - case CUDD_REORDER_WINDOW2_CONV: - case CUDD_REORDER_WINDOW3_CONV: - case CUDD_REORDER_WINDOW4_CONV: - case CUDD_REORDER_LINEAR_CONVERGE: - retval = fprintf(dd->out,"converging "); - if (retval == EOF) return(0); - break; - default: - break; - } - switch (method) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - retval = fprintf(dd->out,"random"); - break; - case CUDD_REORDER_SIFT: - case CUDD_REORDER_SIFT_CONVERGE: - retval = fprintf(dd->out,"sifting"); - break; - case CUDD_REORDER_SYMM_SIFT: - case CUDD_REORDER_SYMM_SIFT_CONV: - retval = fprintf(dd->out,"symmetric sifting"); - break; - case CUDD_REORDER_LAZY_SIFT: - retval = fprintf(dd->out,"lazy sifting"); - break; - case CUDD_REORDER_GROUP_SIFT: - case CUDD_REORDER_GROUP_SIFT_CONV: - retval = fprintf(dd->out,"group sifting"); - break; - case CUDD_REORDER_WINDOW2: - case CUDD_REORDER_WINDOW3: - case CUDD_REORDER_WINDOW4: - case CUDD_REORDER_WINDOW2_CONV: - case CUDD_REORDER_WINDOW3_CONV: - case CUDD_REORDER_WINDOW4_CONV: - retval = fprintf(dd->out,"window"); - break; - case CUDD_REORDER_ANNEALING: - retval = fprintf(dd->out,"annealing"); - break; - case CUDD_REORDER_GENETIC: - retval = fprintf(dd->out,"genetic"); - break; - case CUDD_REORDER_LINEAR: - case CUDD_REORDER_LINEAR_CONVERGE: - retval = fprintf(dd->out,"linear sifting"); - break; - case CUDD_REORDER_EXACT: - retval = fprintf(dd->out,"exact"); - break; - default: - return(0); - } - if (retval == EOF) return(0); - - retval = fprintf(dd->out,": from %ld to ... ", strcmp(str, "BDD") == 0 ? - Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd)); - if (retval == EOF) return(0); - fflush(dd->out); - return(1); - -} /* end of Cudd_StdPreReordHook */ - - -/**Function******************************************************************** - - Synopsis [Sample hook function to call after reordering.] - - Description [Sample hook function to call after reordering. - Prints on the manager's stdout final size and reordering time. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_StdPreReordHook] - -******************************************************************************/ -int -Cudd_StdPostReordHook( - DdManager *dd, - char *str, - void *data) -{ - long initialTime = (long) data; - int retval; - long finalTime = util_cpu_time(); - double totalTimeSec = (double)(finalTime - initialTime) / 1000.0; - - retval = fprintf(dd->out,"%ld nodes in %g sec\n", strcmp(str, "BDD") == 0 ? - Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd), - totalTimeSec); - if (retval == EOF) return(0); - retval = fflush(dd->out); - if (retval == EOF) return(0); - return(1); - -} /* end of Cudd_StdPostReordHook */ - - -/**Function******************************************************************** - - Synopsis [Enables reporting of reordering stats.] - - Description [Enables reporting of reordering stats. - Returns 1 if successful; 0 otherwise.] - - SideEffects [Installs functions in the pre-reordering and post-reordering - hooks.] - - SeeAlso [Cudd_DisableReorderingReporting Cudd_ReorderingReporting] - -******************************************************************************/ -int -Cudd_EnableReorderingReporting( - DdManager *dd) -{ - if (!Cudd_AddHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) { - return(0); - } - if (!Cudd_AddHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) { - return(0); - } - return(1); - -} /* end of Cudd_EnableReorderingReporting */ - - -/**Function******************************************************************** - - Synopsis [Disables reporting of reordering stats.] - - Description [Disables reporting of reordering stats. - Returns 1 if successful; 0 otherwise.] - - SideEffects [Removes functions from the pre-reordering and post-reordering - hooks.] - - SeeAlso [Cudd_EnableReorderingReporting Cudd_ReorderingReporting] - -******************************************************************************/ -int -Cudd_DisableReorderingReporting( - DdManager *dd) -{ - if (!Cudd_RemoveHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) { - return(0); - } - if (!Cudd_RemoveHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) { - return(0); - } - return(1); - -} /* end of Cudd_DisableReorderingReporting */ - - -/**Function******************************************************************** - - Synopsis [Returns 1 if reporting of reordering stats is enabled.] - - Description [Returns 1 if reporting of reordering stats is enabled; - 0 otherwise.] - - SideEffects [none] - - SeeAlso [Cudd_EnableReorderingReporting Cudd_DisableReorderingReporting] - -******************************************************************************/ -int -Cudd_ReorderingReporting( - DdManager *dd) -{ - return(Cudd_IsInHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)); - -} /* end of Cudd_ReorderingReporting */ - - -/**Function******************************************************************** - - Synopsis [Returns the code of the last error.] - - Description [Returns the code of the last error. The error codes are - defined in cudd.h.] - - SideEffects [None] - - SeeAlso [Cudd_ClearErrorCode] - -******************************************************************************/ -Cudd_ErrorType -Cudd_ReadErrorCode( - DdManager *dd) -{ - return(dd->errorCode); - -} /* end of Cudd_ReadErrorCode */ - - -/**Function******************************************************************** - - Synopsis [Clear the error code of a manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadErrorCode] - -******************************************************************************/ -void -Cudd_ClearErrorCode( - DdManager *dd) -{ - dd->errorCode = CUDD_NO_ERROR; - -} /* end of Cudd_ClearErrorCode */ - - -/**Function******************************************************************** - - Synopsis [Reads the stdout of a manager.] - - Description [Reads the stdout of a manager. This is the file pointer to - which messages normally going to stdout are written. It is initialized - to stdout. Cudd_SetStdout allows the application to redirect it.] - - SideEffects [None] - - SeeAlso [Cudd_SetStdout Cudd_ReadStderr] - -******************************************************************************/ -FILE * -Cudd_ReadStdout( - DdManager *dd) -{ - return(dd->out); - -} /* end of Cudd_ReadStdout */ - - -/**Function******************************************************************** - - Synopsis [Sets the stdout of a manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadStdout Cudd_SetStderr] - -******************************************************************************/ -void -Cudd_SetStdout( - DdManager *dd, - FILE *fp) -{ - dd->out = fp; - -} /* end of Cudd_SetStdout */ - - -/**Function******************************************************************** - - Synopsis [Reads the stderr of a manager.] - - Description [Reads the stderr of a manager. This is the file pointer to - which messages normally going to stderr are written. It is initialized - to stderr. Cudd_SetStderr allows the application to redirect it.] - - SideEffects [None] - - SeeAlso [Cudd_SetStderr Cudd_ReadStdout] - -******************************************************************************/ -FILE * -Cudd_ReadStderr( - DdManager *dd) -{ - return(dd->err); - -} /* end of Cudd_ReadStderr */ - - -/**Function******************************************************************** - - Synopsis [Sets the stderr of a manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadStderr Cudd_SetStdout] - -******************************************************************************/ -void -Cudd_SetStderr( - DdManager *dd, - FILE *fp) -{ - dd->err = fp; - -} /* end of Cudd_SetStderr */ - - -/**Function******************************************************************** - - Synopsis [Returns the threshold for the next dynamic reordering.] - - Description [Returns the threshold for the next dynamic reordering. - The threshold is in terms of number of nodes and is in effect only - if reordering is enabled. The count does not include the dead nodes, - unless the countDead parameter of the manager has been changed from - its default setting.] - - SideEffects [None] - - SeeAlso [Cudd_SetNextReordering] - -******************************************************************************/ -unsigned int -Cudd_ReadNextReordering( - DdManager *dd) -{ - return(dd->nextDyn); - -} /* end of Cudd_ReadNextReordering */ - - -/**Function******************************************************************** - - Synopsis [Sets the threshold for the next dynamic reordering.] - - Description [Sets the threshold for the next dynamic reordering. - The threshold is in terms of number of nodes and is in effect only - if reordering is enabled. The count does not include the dead nodes, - unless the countDead parameter of the manager has been changed from - its default setting.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNextReordering] - -******************************************************************************/ -void -Cudd_SetNextReordering( - DdManager *dd, - unsigned int next) -{ - dd->nextDyn = next; - -} /* end of Cudd_SetNextReordering */ - - -/**Function******************************************************************** - - Synopsis [Reads the number of elementary reordering steps.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -double -Cudd_ReadSwapSteps( - DdManager *dd) -{ -#ifdef DD_COUNT - return(dd->swapSteps); -#else - return(-1); -#endif - -} /* end of Cudd_ReadSwapSteps */ - - -/**Function******************************************************************** - - Synopsis [Reads the maximum allowed number of live nodes.] - - Description [Reads the maximum allowed number of live nodes. When this - number is exceeded, the package returns NULL.] - - SideEffects [none] - - SeeAlso [Cudd_SetMaxLive] - -******************************************************************************/ -unsigned int -Cudd_ReadMaxLive( - DdManager *dd) -{ - return(dd->maxLive); - -} /* end of Cudd_ReadMaxLive */ - - -/**Function******************************************************************** - - Synopsis [Sets the maximum allowed number of live nodes.] - - Description [Sets the maximum allowed number of live nodes. When this - number is exceeded, the package returns NULL.] - - SideEffects [none] - - SeeAlso [Cudd_ReadMaxLive] - -******************************************************************************/ -void -Cudd_SetMaxLive( - DdManager *dd, - unsigned int maxLive) -{ - dd->maxLive = maxLive; - -} /* end of Cudd_SetMaxLive */ - - -/**Function******************************************************************** - - Synopsis [Reads the maximum allowed memory.] - - Description [Reads the maximum allowed memory. When this - number is exceeded, the package returns NULL.] - - SideEffects [none] - - SeeAlso [Cudd_SetMaxMemory] - -******************************************************************************/ -long -Cudd_ReadMaxMemory( - DdManager *dd) -{ - return(dd->maxmemhard); - -} /* end of Cudd_ReadMaxMemory */ - - -/**Function******************************************************************** - - Synopsis [Sets the maximum allowed memory.] - - Description [Sets the maximum allowed memory. When this - number is exceeded, the package returns NULL.] - - SideEffects [none] - - SeeAlso [Cudd_ReadMaxMemory] - -******************************************************************************/ -void -Cudd_SetMaxMemory( - DdManager *dd, - long maxMemory) -{ - dd->maxmemhard = maxMemory; - -} /* end of Cudd_SetMaxMemory */ - - -/**Function******************************************************************** - - Synopsis [Prevents sifting of a variable.] - - Description [This function sets a flag to prevent sifting of a - variable. Returns 1 if successful; 0 otherwise (i.e., invalid - variable index).] - - SideEffects [Changes the "bindVar" flag in DdSubtable.] - - SeeAlso [Cudd_bddUnbindVar] - -******************************************************************************/ -int -Cudd_bddBindVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].bindVar = 1; - return(1); - -} /* end of Cudd_bddBindVar */ - - -/**Function******************************************************************** - - Synopsis [Allows the sifting of a variable.] - - Description [This function resets the flag that prevents the sifting - of a variable. In successive variable reorderings, the variable will - NOT be skipped, that is, sifted. Initially all variables can be - sifted. It is necessary to call this function only to re-enable - sifting after a call to Cudd_bddBindVar. Returns 1 if successful; 0 - otherwise (i.e., invalid variable index).] - - SideEffects [Changes the "bindVar" flag in DdSubtable.] - - SeeAlso [Cudd_bddBindVar] - -******************************************************************************/ -int -Cudd_bddUnbindVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].bindVar = 0; - return(1); - -} /* end of Cudd_bddUnbindVar */ - - -/**Function******************************************************************** - - Synopsis [Tells whether a variable can be sifted.] - - Description [This function returns 1 if a variable is enabled for - sifting. Initially all variables can be sifted. This function returns - 0 only if there has been a previous call to Cudd_bddBindVar for that - variable not followed by a call to Cudd_bddUnbindVar. The function returns - 0 also in the case in which the index of the variable is out of bounds.] - - SideEffects [none] - - SeeAlso [Cudd_bddBindVar Cudd_bddUnbindVar] - -******************************************************************************/ -int -Cudd_bddVarIsBound( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return(0); - return(dd->subtables[dd->perm[index]].bindVar); - -} /* end of Cudd_bddVarIsBound */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable type to primary input.] - - Description [Sets a variable type to primary input. The variable type is - used by lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetPsVar Cudd_bddSetNsVar Cudd_bddIsPiVar] - -******************************************************************************/ -int -Cudd_bddSetPiVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return (0); - dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRIMARY_INPUT; - return(1); - -} /* end of Cudd_bddSetPiVar */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable type to present state.] - - Description [Sets a variable type to present state. The variable type is - used by lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetPiVar Cudd_bddSetNsVar Cudd_bddIsPsVar] - -******************************************************************************/ -int -Cudd_bddSetPsVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return (0); - dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRESENT_STATE; - return(1); - -} /* end of Cudd_bddSetPsVar */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable type to next state.] - - Description [Sets a variable type to next state. The variable type is - used by lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetPiVar Cudd_bddSetPsVar Cudd_bddIsNsVar] - -******************************************************************************/ -int -Cudd_bddSetNsVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return (0); - dd->subtables[dd->perm[index]].varType = CUDD_VAR_NEXT_STATE; - return(1); - -} /* end of Cudd_bddSetNsVar */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is primary input.] - - Description [Checks whether a variable is primary input. Returns 1 if - the variable's type is primary input; 0 if the variable exists but is - not a primary input; -1 if the variable does not exist.] - - SideEffects [none] - - SeeAlso [Cudd_bddSetPiVar Cudd_bddIsPsVar Cudd_bddIsNsVar] - -******************************************************************************/ -int -Cudd_bddIsPiVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return -1; - return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRIMARY_INPUT); - -} /* end of Cudd_bddIsPiVar */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is present state.] - - Description [Checks whether a variable is present state. Returns 1 if - the variable's type is present state; 0 if the variable exists but is - not a present state; -1 if the variable does not exist.] - - SideEffects [none] - - SeeAlso [Cudd_bddSetPsVar Cudd_bddIsPiVar Cudd_bddIsNsVar] - -******************************************************************************/ -int -Cudd_bddIsPsVar( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return -1; - return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRESENT_STATE); - -} /* end of Cudd_bddIsPsVar */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is next state.] - - Description [Checks whether a variable is next state. Returns 1 if - the variable's type is present state; 0 if the variable exists but is - not a present state; -1 if the variable does not exist.] - - SideEffects [none] - - SeeAlso [Cudd_bddSetNsVar Cudd_bddIsPiVar Cudd_bddIsPsVar] - -******************************************************************************/ -int -Cudd_bddIsNsVar( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return -1; - return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_NEXT_STATE); - -} /* end of Cudd_bddIsNsVar */ - - -/**Function******************************************************************** - - Synopsis [Sets a corresponding pair index for a given index.] - - Description [Sets a corresponding pair index for a given index. - These pair indices are present and next state variable. Returns 1 if - successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddReadPairIndex] - -******************************************************************************/ -int -Cudd_bddSetPairIndex( - DdManager *dd /* manager */, - int index /* variable index */, - int pairIndex /* corresponding variable index */) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].pairIndex = pairIndex; - return(1); - -} /* end of Cudd_bddSetPairIndex */ - - -/**Function******************************************************************** - - Synopsis [Reads a corresponding pair index for a given index.] - - Description [Reads a corresponding pair index for a given index. - These pair indices are present and next state variable. Returns the - corresponding variable index if the variable exists; -1 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetPairIndex] - -******************************************************************************/ -int -Cudd_bddReadPairIndex( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return -1; - return dd->subtables[dd->perm[index]].pairIndex; - -} /* end of Cudd_bddReadPairIndex */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable to be grouped.] - - Description [Sets a variable to be grouped. This function is used for - lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetVarHardGroup Cudd_bddResetVarToBeGrouped] - -******************************************************************************/ -int -Cudd_bddSetVarToBeGrouped( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - if (dd->subtables[dd->perm[index]].varToBeGrouped <= CUDD_LAZY_SOFT_GROUP) { - dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_SOFT_GROUP; - } - return(1); - -} /* end of Cudd_bddSetVarToBeGrouped */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable to be a hard group.] - - Description [Sets a variable to be a hard group. This function is used - for lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetVarToBeGrouped Cudd_bddResetVarToBeGrouped - Cudd_bddIsVarHardGroup] - -******************************************************************************/ -int -Cudd_bddSetVarHardGroup( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_HARD_GROUP; - return(1); - -} /* end of Cudd_bddSetVarHardGrouped */ - - -/**Function******************************************************************** - - Synopsis [Resets a variable not to be grouped.] - - Description [Resets a variable not to be grouped. This function is - used for lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetVarToBeGrouped Cudd_bddSetVarHardGroup] - -******************************************************************************/ -int -Cudd_bddResetVarToBeGrouped( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - if (dd->subtables[dd->perm[index]].varToBeGrouped <= - CUDD_LAZY_SOFT_GROUP) { - dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_NONE; - } - return(1); - -} /* end of Cudd_bddResetVarToBeGrouped */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is set to be grouped.] - - Description [Checks whether a variable is set to be grouped. This - function is used for lazy sifting.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_bddIsVarToBeGrouped( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(-1); - if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP) - return(0); - else - return(dd->subtables[dd->perm[index]].varToBeGrouped); - -} /* end of Cudd_bddIsVarToBeGrouped */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable to be ungrouped.] - - Description [Sets a variable to be ungrouped. This function is used - for lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddIsVarToBeUngrouped] - -******************************************************************************/ -int -Cudd_bddSetVarToBeUngrouped( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_UNGROUP; - return(1); - -} /* end of Cudd_bddSetVarToBeGrouped */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is set to be ungrouped.] - - Description [Checks whether a variable is set to be ungrouped. This - function is used for lazy sifting. Returns 1 if the variable is marked - to be ungrouped; 0 if the variable exists, but it is not marked to be - ungrouped; -1 if the variable does not exist.] - - SideEffects [none] - - SeeAlso [Cudd_bddSetVarToBeUngrouped] - -******************************************************************************/ -int -Cudd_bddIsVarToBeUngrouped( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(-1); - return dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP; - -} /* end of Cudd_bddIsVarToBeGrouped */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is set to be in a hard group.] - - Description [Checks whether a variable is set to be in a hard group. This - function is used for lazy sifting. Returns 1 if the variable is marked - to be in a hard group; 0 if the variable exists, but it is not marked to be - in a hard group; -1 if the variable does not exist.] - - SideEffects [none] - - SeeAlso [Cudd_bddSetVarHardGroup] - -******************************************************************************/ -int -Cudd_bddIsVarHardGroup( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(-1); - if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_HARD_GROUP) - return(1); - return(0); - -} /* end of Cudd_bddIsVarToBeGrouped */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Fixes a variable group tree.] - - Description [] - - SideEffects [Changes the variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static void -fixVarTree( - MtrNode * treenode, - int * perm, - int size) -{ - treenode->index = treenode->low; - treenode->low = ((int) treenode->index < size) ? - perm[treenode->index] : treenode->index; - if (treenode->child != NULL) - fixVarTree(treenode->child, perm, size); - if (treenode->younger != NULL) - fixVarTree(treenode->younger, perm, size); - return; - -} /* end of fixVarTree */ - - -/**Function******************************************************************** - - Synopsis [Adds multiplicity groups to a ZDD variable group tree.] - - Description [Adds multiplicity groups to a ZDD variable group tree. - Returns 1 if successful; 0 otherwise. This function creates the groups - for set of ZDD variables (whose cardinality is given by parameter - multiplicity) that are created for each BDD variable in - Cudd_zddVarsFromBddVars. The crux of the matter is to determine the index - each new group. (The index of the first variable in the group.) - We first build all the groups for the children of a node, and then deal - with the ZDD variables that are directly attached to the node. The problem - for these is that the tree itself does not provide information on their - position inside the group. While we deal with the children of the node, - therefore, we keep track of all the positions they occupy. The remaining - positions in the tree can be freely used. Also, we keep track of all the - variables placed in the children. All the remaining variables are directly - attached to the group. We can then place any pair of variables not yet - grouped in any pair of available positions in the node.] - - SideEffects [Changes the variable group tree.] - - SeeAlso [Cudd_zddVarsFromBddVars] - -******************************************************************************/ -static int -addMultiplicityGroups( - DdManager *dd /* manager */, - MtrNode *treenode /* current tree node */, - int multiplicity /* how many ZDD vars per BDD var */, - char *vmask /* variable pairs for which a group has been already built */, - char *lmask /* levels for which a group has already been built*/) -{ - int startV, stopV, startL; - int i, j; - MtrNode *auxnode = treenode; - - while (auxnode != NULL) { - if (auxnode->child != NULL) { - addMultiplicityGroups(dd,auxnode->child,multiplicity,vmask,lmask); - } - /* Build remaining groups. */ - startV = dd->permZ[auxnode->index] / multiplicity; - startL = auxnode->low / multiplicity; - stopV = startV + auxnode->size / multiplicity; - /* Walk down vmask starting at startV and build missing groups. */ - for (i = startV, j = startL; i < stopV; i++) { - if (vmask[i] == 0) { - MtrNode *node; - while (lmask[j] == 1) j++; - node = Mtr_MakeGroup(auxnode, j * multiplicity, multiplicity, - MTR_FIXED); - if (node == NULL) { - return(0); - } - node->index = dd->invpermZ[i * multiplicity]; - vmask[i] = 1; - lmask[j] = 1; - } - } - auxnode = auxnode->younger; - } - return(1); - -} /* end of addMultiplicityGroups */ - diff --git a/src/bdd/cudd/cuddAddAbs.c b/src/bdd/cudd/cuddAddAbs.c deleted file mode 100644 index b256ad0f..00000000 --- a/src/bdd/cudd/cuddAddAbs.c +++ /dev/null @@ -1,566 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddAbs.c] - - PackageName [cudd] - - Synopsis [Quantification functions for ADDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addExistAbstract() - <li> Cudd_addUnivAbstract() - <li> Cudd_addOrAbstract() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddAddExistAbstractRecur() - <li> cuddAddUnivAbstractRecur() - <li> cuddAddOrAbstractRecur() - </ul> - Static procedures included in this module: - <ul> - <li> addCheckPositiveCube() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddAbs.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - -static DdNode *two; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int addCheckPositiveCube ARGS((DdManager *manager, DdNode *cube)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Existentially Abstracts all the variables in cube from f.] - - Description [Abstracts all the variables in cube from f by summing - over all possible values taken by the variables. Returns the - abstracted ADD.] - - SideEffects [None] - - SeeAlso [Cudd_addUnivAbstract Cudd_bddExistAbstract - Cudd_addOrAbstract] - -******************************************************************************/ -DdNode * -Cudd_addExistAbstract( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *res; - - two = cuddUniqueConst(manager,(CUDD_VALUE_TYPE) 2); - if (two == NULL) return(NULL); - cuddRef(two); - - if (addCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err,"Error: Can only abstract cubes"); - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddAddExistAbstractRecur(manager, f, cube); - } while (manager->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(manager,two); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,two); - cuddDeref(res); - - return(res); - -} /* end of Cudd_addExistAbstract */ - - -/**Function******************************************************************** - - Synopsis [Universally Abstracts all the variables in cube from f.] - - Description [Abstracts all the variables in cube from f by taking - the product over all possible values taken by the variable. Returns - the abstracted ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addExistAbstract Cudd_bddUnivAbstract - Cudd_addOrAbstract] - -******************************************************************************/ -DdNode * -Cudd_addUnivAbstract( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *res; - - if (addCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err,"Error: Can only abstract cubes"); - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddAddUnivAbstractRecur(manager, f, cube); - } while (manager->reordered == 1); - - return(res); - -} /* end of Cudd_addUnivAbstract */ - - -/**Function******************************************************************** - - Synopsis [Disjunctively abstracts all the variables in cube from the - 0-1 ADD f.] - - Description [Abstracts all the variables in cube from the 0-1 ADD f - by taking the disjunction over all possible values taken by the - variables. Returns the abstracted ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addUnivAbstract Cudd_addExistAbstract] - -******************************************************************************/ -DdNode * -Cudd_addOrAbstract( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *res; - - if (addCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err,"Error: Can only abstract cubes"); - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddAddOrAbstractRecur(manager, f, cube); - } while (manager->reordered == 1); - return(res); - -} /* end of Cudd_addOrAbstract */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addExistAbstract.] - - Description [Performs the recursive step of Cudd_addExistAbstract. - Returns the ADD obtained by abstracting the variables of cube from f, - if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddAddExistAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *T, *E, *res, *res1, *res2, *zero; - - statLine(manager); - zero = DD_ZERO(manager); - - /* Cube is guaranteed to be a cube at this point. */ - if (f == zero || cuddIsConstant(cube)) { - return(f); - } - - /* Abstract a variable that does not appear in f => multiply by 2. */ - if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { - res1 = cuddAddExistAbstractRecur(manager, f, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - /* Use the "internal" procedure to be alerted in case of - ** dynamic reordering. If dynamic reordering occurs, we - ** have to abort the entire abstraction. - */ - res = cuddAddApplyRecur(manager,Cudd_addTimes,res1,two); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - cuddDeref(res); - return(res); - } - - if ((res = cuddCacheLookup2(manager, Cudd_addExistAbstract, f, cube)) != NULL) { - return(res); - } - - T = cuddT(f); - E = cuddE(f); - - /* If the two indices are the same, so are their levels. */ - if (f->index == cube->index) { - res1 = cuddAddExistAbstractRecur(manager, T, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddAddExistAbstractRecur(manager, E, cuddT(cube)); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = cuddAddApplyRecur(manager, Cudd_addPlus, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res); - cuddDeref(res); - return(res); - } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ - res1 = cuddAddExistAbstractRecur(manager, T, cube); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddAddExistAbstractRecur(manager, E, cube); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = (res1 == res2) ? res1 : - cuddUniqueInter(manager, (int) f->index, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res); - return(res); - } - -} /* end of cuddAddExistAbstractRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addUnivAbstract.] - - Description [Performs the recursive step of Cudd_addUnivAbstract. - Returns the ADD obtained by abstracting the variables of cube from f, - if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddAddUnivAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *T, *E, *res, *res1, *res2, *one, *zero; - - statLine(manager); - one = DD_ONE(manager); - zero = DD_ZERO(manager); - - /* Cube is guaranteed to be a cube at this point. - ** zero and one are the only constatnts c such that c*c=c. - */ - if (f == zero || f == one || cube == one) { - return(f); - } - - /* Abstract a variable that does not appear in f. */ - if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { - res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - /* Use the "internal" procedure to be alerted in case of - ** dynamic reordering. If dynamic reordering occurs, we - ** have to abort the entire abstraction. - */ - res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - cuddDeref(res); - return(res); - } - - if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) { - return(res); - } - - T = cuddT(f); - E = cuddE(f); - - /* If the two indices are the same, so are their levels. */ - if (f->index == cube->index) { - res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube)); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); - cuddDeref(res); - return(res); - } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ - res1 = cuddAddUnivAbstractRecur(manager, T, cube); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddAddUnivAbstractRecur(manager, E, cube); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = (res1 == res2) ? res1 : - cuddUniqueInter(manager, (int) f->index, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); - return(res); - } - -} /* end of cuddAddUnivAbstractRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addOrAbstract.] - - Description [Performs the recursive step of Cudd_addOrAbstract. - Returns the ADD obtained by abstracting the variables of cube from f, - if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddAddOrAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *T, *E, *res, *res1, *res2, *one; - - statLine(manager); - one = DD_ONE(manager); - - /* Cube is guaranteed to be a cube at this point. */ - if (cuddIsConstant(f) || cube == one) { - return(f); - } - - /* Abstract a variable that does not appear in f. */ - if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { - res1 = cuddAddOrAbstractRecur(manager, f, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - /* Use the "internal" procedure to be alerted in case of - ** dynamic reordering. If dynamic reordering occurs, we - ** have to abort the entire abstraction. - */ - res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res1); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - cuddDeref(res); - return(res); - } - - if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) { - return(res); - } - - T = cuddT(f); - E = cuddE(f); - - /* If the two indices are the same, so are their levels. */ - if (f->index == cube->index) { - res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - if (res1 != one) { - res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube)); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - } else { - res = res1; - } - cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); - cuddDeref(res); - return(res); - } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ - res1 = cuddAddOrAbstractRecur(manager, T, cube); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddAddOrAbstractRecur(manager, E, cube); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = (res1 == res2) ? res1 : - cuddUniqueInter(manager, (int) f->index, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); - return(res); - } - -} /* end of cuddAddOrAbstractRecur */ - - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Checks whether cube is an ADD representing the product - of positive literals.] - - Description [Checks whether cube is an ADD representing the product of - positive literals. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -addCheckPositiveCube( - DdManager * manager, - DdNode * cube) -{ - if (Cudd_IsComplement(cube)) return(0); - if (cube == DD_ONE(manager)) return(1); - if (cuddIsConstant(cube)) return(0); - if (cuddE(cube) == DD_ZERO(manager)) { - return(addCheckPositiveCube(manager, cuddT(cube))); - } - return(0); - -} /* end of addCheckPositiveCube */ - diff --git a/src/bdd/cudd/cuddAddApply.c b/src/bdd/cudd/cuddAddApply.c deleted file mode 100644 index 60c06de6..00000000 --- a/src/bdd/cudd/cuddAddApply.c +++ /dev/null @@ -1,917 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddApply.c] - - PackageName [cudd] - - Synopsis [Apply functions for ADDs and their operators.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addApply() - <li> Cudd_addMonadicApply() - <li> Cudd_addPlus() - <li> Cudd_addTimes() - <li> Cudd_addThreshold() - <li> Cudd_addSetNZ() - <li> Cudd_addDivide() - <li> Cudd_addMinus() - <li> Cudd_addMinimum() - <li> Cudd_addMaximum() - <li> Cudd_addOneZeroMaximum() - <li> Cudd_addDiff() - <li> Cudd_addAgreement() - <li> Cudd_addOr() - <li> Cudd_addNand() - <li> Cudd_addNor() - <li> Cudd_addXor() - <li> Cudd_addXnor() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddAddApplyRecur() - <li> cuddAddMonadicApplyRecur() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at Boulder. - The University of Colorado at Boulder makes no warranty about the - suitability of this software for any purpose. It is presented on an - AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddApply.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Applies op to the corresponding discriminants of f and g.] - - Description [Applies op to the corresponding discriminants of f and g. - Returns a pointer to the result if succssful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes - Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum - Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement - Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor] - -******************************************************************************/ -DdNode * -Cudd_addApply( - DdManager * dd, - DdNode * (*op)(DdManager *, DdNode **, DdNode **), - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddApplyRecur(dd,op,f,g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addApply */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point addition.] - - Description [Integer and floating point addition. Returns NULL if not - a terminal case; f+g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addPlus( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *res; - DdNode *F, *G; - CUDD_VALUE_TYPE value; - - F = *f; G = *g; - if (F == DD_ZERO(dd)) return(G); - if (G == DD_ZERO(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - value = cuddV(F)+cuddV(G); - res = cuddUniqueConst(dd,value); - return(res); - } - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addPlus */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point multiplication.] - - Description [Integer and floating point multiplication. Returns NULL - if not a terminal case; f * g otherwise. This function can be used also - to take the AND of two 0-1 ADDs.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addTimes( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *res; - DdNode *F, *G; - CUDD_VALUE_TYPE value; - - F = *f; G = *g; - if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd)); - if (F == DD_ONE(dd)) return(G); - if (G == DD_ONE(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - value = cuddV(F)*cuddV(G); - res = cuddUniqueConst(dd,value); - return(res); - } - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addTimes */ - - -/**Function******************************************************************** - - Synopsis [f if f>=g; 0 if f<g.] - - Description [Threshold operator for Apply (f if f >=g; 0 if f<g). - Returns NULL if not a terminal case; f op g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addThreshold( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G || F == DD_PLUS_INFINITY(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - if (cuddV(F) >= cuddV(G)) { - return(F); - } else { - return(DD_ZERO(dd)); - } - } - return(NULL); - -} /* end of Cudd_addThreshold */ - - -/**Function******************************************************************** - - Synopsis [This operator sets f to the value of g wherever g != 0.] - - Description [This operator sets f to the value of g wherever g != 0. - Returns NULL if not a terminal case; f op g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addSetNZ( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(F); - if (F == DD_ZERO(dd)) return(G); - if (G == DD_ZERO(dd)) return(F); - if (cuddIsConstant(G)) return(G); - return(NULL); - -} /* end of Cudd_addSetNZ */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point division.] - - Description [Integer and floating point division. Returns NULL if not - a terminal case; f / g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addDivide( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *res; - DdNode *F, *G; - CUDD_VALUE_TYPE value; - - F = *f; G = *g; - /* We would like to use F == G -> F/G == 1, but F and G may - ** contain zeroes. */ - if (F == DD_ZERO(dd)) return(DD_ZERO(dd)); - if (G == DD_ONE(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - value = cuddV(F)/cuddV(G); - res = cuddUniqueConst(dd,value); - return(res); - } - return(NULL); - -} /* end of Cudd_addDivide */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point subtraction.] - - Description [Integer and floating point subtraction. Returns NULL if - not a terminal case; f - g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addMinus( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *res; - DdNode *F, *G; - CUDD_VALUE_TYPE value; - - F = *f; G = *g; - if (F == G) return(DD_ZERO(dd)); - if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G)); - if (G == DD_ZERO(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - value = cuddV(F)-cuddV(G); - res = cuddUniqueConst(dd,value); - return(res); - } - return(NULL); - -} /* end of Cudd_addMinus */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point min.] - - Description [Integer and floating point min for Cudd_addApply. - Returns NULL if not a terminal case; min(f,g) otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addMinimum( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == DD_PLUS_INFINITY(dd)) return(G); - if (G == DD_PLUS_INFINITY(dd)) return(F); - if (F == G) return(F); -#if 0 - /* These special cases probably do not pay off. */ - if (F == DD_MINUS_INFINITY(dd)) return(F); - if (G == DD_MINUS_INFINITY(dd)) return(G); -#endif - if (cuddIsConstant(F) && cuddIsConstant(G)) { - if (cuddV(F) <= cuddV(G)) { - return(F); - } else { - return(G); - } - } - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addMinimum */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point max.] - - Description [Integer and floating point max for Cudd_addApply. - Returns NULL if not a terminal case; max(f,g) otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addMaximum( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(F); - if (F == DD_MINUS_INFINITY(dd)) return(G); - if (G == DD_MINUS_INFINITY(dd)) return(F); -#if 0 - /* These special cases probably do not pay off. */ - if (F == DD_PLUS_INFINITY(dd)) return(F); - if (G == DD_PLUS_INFINITY(dd)) return(G); -#endif - if (cuddIsConstant(F) && cuddIsConstant(G)) { - if (cuddV(F) >= cuddV(G)) { - return(F); - } else { - return(G); - } - } - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addMaximum */ - - -/**Function******************************************************************** - - Synopsis [Returns 1 if f > g and 0 otherwise.] - - Description [Returns 1 if f > g and 0 otherwise. Used in - conjunction with Cudd_addApply. Returns NULL if not a terminal - case.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addOneZeroMaximum( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - - if (*f == *g) return(DD_ZERO(dd)); - if (*g == DD_PLUS_INFINITY(dd)) - return DD_ZERO(dd); - if (cuddIsConstant(*f) && cuddIsConstant(*g)) { - if (cuddV(*f) > cuddV(*g)) { - return(DD_ONE(dd)); - } else { - return(DD_ZERO(dd)); - } - } - - return(NULL); - -} /* end of Cudd_addOneZeroMaximum */ - - -/**Function******************************************************************** - - Synopsis [Returns plusinfinity if f=g; returns min(f,g) if f!=g.] - - Description [Returns NULL if not a terminal case; f op g otherwise, - where f op g is plusinfinity if f=g; min(f,g) if f!=g.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addDiff( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(DD_PLUS_INFINITY(dd)); - if (F == DD_PLUS_INFINITY(dd)) return(G); - if (G == DD_PLUS_INFINITY(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - if (cuddV(F) != cuddV(G)) { - if (cuddV(F) < cuddV(G)) { - return(F); - } else { - return(G); - } - } else { - return(DD_PLUS_INFINITY(dd)); - } - } - return(NULL); - -} /* end of Cudd_addDiff */ - - -/**Function******************************************************************** - - Synopsis [f if f==g; background if f!=g.] - - Description [Returns NULL if not a terminal case; f op g otherwise, - where f op g is f if f==g; background if f!=g.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addAgreement( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(F); - if (F == dd->background) return(F); - if (G == dd->background) return(G); - if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background); - return(NULL); - -} /* end of Cudd_addAgreement */ - - -/**Function******************************************************************** - - Synopsis [Disjunction of two 0-1 ADDs.] - - Description [Disjunction of two 0-1 ADDs. Returns NULL - if not a terminal case; f OR g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addOr( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd)); - if (cuddIsConstant(F)) return(G); - if (cuddIsConstant(G)) return(F); - if (F == G) return(F); - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addOr */ - - -/**Function******************************************************************** - - Synopsis [NAND of two 0-1 ADDs.] - - Description [NAND of two 0-1 ADDs. Returns NULL - if not a terminal case; f NAND g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addNand( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd)); - if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addNand */ - - -/**Function******************************************************************** - - Synopsis [NOR of two 0-1 ADDs.] - - Description [NOR of two 0-1 ADDs. Returns NULL - if not a terminal case; f NOR g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addNor( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd)); - if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd)); - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addNor */ - - -/**Function******************************************************************** - - Synopsis [XOR of two 0-1 ADDs.] - - Description [XOR of two 0-1 ADDs. Returns NULL - if not a terminal case; f XOR g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addXor( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(DD_ZERO(dd)); - if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd)); - if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd)); - if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addXor */ - - -/**Function******************************************************************** - - Synopsis [XNOR of two 0-1 ADDs.] - - Description [XNOR of two 0-1 ADDs. Returns NULL - if not a terminal case; f XNOR g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addXnor( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(DD_ONE(dd)); - if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd)); - if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd)); - if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addXnor */ - - -/**Function******************************************************************** - - Synopsis [Applies op to the discriminants of f.] - - Description [Applies op to the discriminants of f. - Returns a pointer to the result if succssful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply Cudd_addLog] - -******************************************************************************/ -DdNode * -Cudd_addMonadicApply( - DdManager * dd, - DdNode * (*op)(DdManager *, DdNode *), - DdNode * f) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddMonadicApplyRecur(dd,op,f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addMonadicApply */ - - -/**Function******************************************************************** - - Synopsis [Natural logarithm of an ADD.] - - Description [Natural logarithm of an ADDs. Returns NULL - if not a terminal case; log(f) otherwise. The discriminants of f must - be positive double's.] - - SideEffects [None] - - SeeAlso [Cudd_addMonadicApply] - -******************************************************************************/ -DdNode * -Cudd_addLog( - DdManager * dd, - DdNode * f) -{ - if (cuddIsConstant(f)) { - CUDD_VALUE_TYPE value = log(cuddV(f)); - DdNode *res = cuddUniqueConst(dd,value); - return(res); - } - return(NULL); - -} /* end of Cudd_addLog */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addApply.] - - Description [Performs the recursive step of Cudd_addApply. Returns a - pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddAddMonadicApplyRecur] - -******************************************************************************/ -DdNode * -cuddAddApplyRecur( - DdManager * dd, - DdNode * (*op)(DdManager *, DdNode **, DdNode **), - DdNode * f, - DdNode * g) -{ - DdNode *res, - *fv, *fvn, *gv, *gvn, - *T, *E; - unsigned int ford, gord; - unsigned int index; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - - /* Check terminal cases. Op may swap f and g to increase the - * cache hit rate. - */ - statLine(dd); - res = (*op)(dd,&f,&g); - if (res != NULL) return(res); - - /* Check cache. */ - cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) op; - res = cuddCacheLookup2(dd,cacheOp,f,g); - if (res != NULL) return(res); - - /* Recursive step. */ - ford = cuddI(dd,f->index); - gord = cuddI(dd,g->index); - if (ford <= gord) { - index = f->index; - fv = cuddT(f); - fvn = cuddE(f); - } else { - index = g->index; - fv = fvn = f; - } - if (gord <= ford) { - gv = cuddT(g); - gvn = cuddE(g); - } else { - gv = gvn = g; - } - - T = cuddAddApplyRecur(dd,op,fv,gv); - if (T == NULL) return(NULL); - cuddRef(T); - - E = cuddAddApplyRecur(dd,op,fvn,gvn); - if (E == NULL) { - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - - res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert2(dd,cacheOp,f,g,res); - - return(res); - -} /* end of cuddAddApplyRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addMonadicApply.] - - Description [Performs the recursive step of Cudd_addMonadicApply. Returns a - pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddAddApplyRecur] - -******************************************************************************/ -DdNode * -cuddAddMonadicApplyRecur( - DdManager * dd, - DdNode * (*op)(DdManager *, DdNode *), - DdNode * f) -{ - DdNode *res, *ft, *fe, *T, *E; - unsigned int ford; - unsigned int index; - - /* Check terminal cases. */ - statLine(dd); - res = (*op)(dd,f); - if (res != NULL) return(res); - - /* Check cache. */ - res = cuddCacheLookup1(dd,op,f); - if (res != NULL) return(res); - - /* Recursive step. */ - ford = cuddI(dd,f->index); - index = f->index; - ft = cuddT(f); - fe = cuddE(f); - - T = cuddAddMonadicApplyRecur(dd,op,ft); - if (T == NULL) return(NULL); - cuddRef(T); - - E = cuddAddMonadicApplyRecur(dd,op,fe); - if (E == NULL) { - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - - res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert1(dd,op,f,res); - - return(res); - -} /* end of cuddAddMonadicApplyRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddAddFind.c b/src/bdd/cudd/cuddAddFind.c deleted file mode 100644 index 0469b014..00000000 --- a/src/bdd/cudd/cuddAddFind.c +++ /dev/null @@ -1,283 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddFind.c] - - PackageName [cudd] - - Synopsis [Functions to find maximum and minimum in an ADD and to - extract the i-th bit.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addFindMax() - <li> Cudd_addFindMin() - <li> Cudd_addIthBit() - </ul> - Static functions included in this module: - <ul> - <li> addDoIthBit() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddFind.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * addDoIthBit ARGS((DdManager *dd, DdNode *f, DdNode *index)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Finds the maximum discriminant of f.] - - Description [Returns a pointer to a constant ADD.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_addFindMax( - DdManager * dd, - DdNode * f) -{ - DdNode *t, *e, *res; - - statLine(dd); - if (cuddIsConstant(f)) { - return(f); - } - - res = cuddCacheLookup1(dd,Cudd_addFindMax,f); - if (res != NULL) { - return(res); - } - - t = Cudd_addFindMax(dd,cuddT(f)); - if (t == DD_PLUS_INFINITY(dd)) return(t); - - e = Cudd_addFindMax(dd,cuddE(f)); - - res = (cuddV(t) >= cuddV(e)) ? t : e; - - cuddCacheInsert1(dd,Cudd_addFindMax,f,res); - - return(res); - -} /* end of Cudd_addFindMax */ - - -/**Function******************************************************************** - - Synopsis [Finds the minimum discriminant of f.] - - Description [Returns a pointer to a constant ADD.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_addFindMin( - DdManager * dd, - DdNode * f) -{ - DdNode *t, *e, *res; - - statLine(dd); - if (cuddIsConstant(f)) { - return(f); - } - - res = cuddCacheLookup1(dd,Cudd_addFindMin,f); - if (res != NULL) { - return(res); - } - - t = Cudd_addFindMin(dd,cuddT(f)); - if (t == DD_MINUS_INFINITY(dd)) return(t); - - e = Cudd_addFindMin(dd,cuddE(f)); - - res = (cuddV(t) <= cuddV(e)) ? t : e; - - cuddCacheInsert1(dd,Cudd_addFindMin,f,res); - - return(res); - -} /* end of Cudd_addFindMin */ - - -/**Function******************************************************************** - - Synopsis [Extracts the i-th bit from an ADD.] - - Description [Produces an ADD from another ADD by replacing all - discriminants whose i-th bit is equal to 1 with 1, and all other - discriminants with 0. The i-th bit refers to the integer - representation of the leaf value. If the value is has a fractional - part, it is ignored. Repeated calls to this procedure allow one to - transform an integer-valued ADD into an array of ADDs, one for each - bit of the leaf values. Returns a pointer to the resulting ADD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddIthBit] - -******************************************************************************/ -DdNode * -Cudd_addIthBit( - DdManager * dd, - DdNode * f, - int bit) -{ - DdNode *res; - DdNode *index; - - /* Use a constant node to remember the bit, so that we can use the - ** global cache. - */ - index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit); - if (index == NULL) return(NULL); - cuddRef(index); - - do { - dd->reordered = 0; - res = addDoIthBit(dd, f, index); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd, index); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, index); - cuddDeref(res); - return(res); - -} /* end of Cudd_addIthBit */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addIthBit.] - - Description [Performs the recursive step for Cudd_addIthBit. - Returns a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -addDoIthBit( - DdManager * dd, - DdNode * f, - DdNode * index) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int mask, value; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - mask = 1 << ((int) cuddV(index)); - value = (int) cuddV(f); - return((value & mask) == 0 ? DD_ZERO(dd) : DD_ONE(dd)); - } - - /* Check cache. */ - res = cuddCacheLookup2(dd,addDoIthBit,f,index); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = addDoIthBit(dd,fv,index); - if (T == NULL) return(NULL); - cuddRef(T); - - E = addDoIthBit(dd,fvn,index); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert2(dd,addDoIthBit,f,index,res); - - return(res); - -} /* end of addDoIthBit */ - diff --git a/src/bdd/cudd/cuddAddInv.c b/src/bdd/cudd/cuddAddInv.c deleted file mode 100644 index fc4a340b..00000000 --- a/src/bdd/cudd/cuddAddInv.c +++ /dev/null @@ -1,172 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddInv.c] - - PackageName [cudd] - - Synopsis [Function to compute the scalar inverse of an ADD.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addScalarInverse() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddAddScalarInverseRecur() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddInv.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the scalar inverse of an ADD.] - - Description [Computes an n ADD where the discriminants are the - multiplicative inverses of the corresponding discriminants of the - argument ADD. Returns a pointer to the resulting ADD in case of - success. Returns NULL if any discriminants smaller than epsilon is - encountered.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_addScalarInverse( - DdManager * dd, - DdNode * f, - DdNode * epsilon) -{ - DdNode *res; - - if (!cuddIsConstant(epsilon)) { - (void) fprintf(dd->err,"Invalid epsilon\n"); - return(NULL); - } - do { - dd->reordered = 0; - res = cuddAddScalarInverseRecur(dd,f,epsilon); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addScalarInverse */ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of addScalarInverse.] - - Description [Returns a pointer to the resulting ADD in case of - success. Returns NULL if any discriminants smaller than epsilon is - encountered.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -cuddAddScalarInverseRecur( - DdManager * dd, - DdNode * f, - DdNode * epsilon) -{ - DdNode *t, *e, *res; - CUDD_VALUE_TYPE value; - - statLine(dd); - if (cuddIsConstant(f)) { - if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL); - value = 1.0 / cuddV(f); - res = cuddUniqueConst(dd,value); - return(res); - } - - res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon); - if (res != NULL) return(res); - - t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddRef(e); - - res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - - cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res); - - return(res); - -} /* end of cuddAddScalarInverseRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddAddIte.c b/src/bdd/cudd/cuddAddIte.c deleted file mode 100644 index 71f8070f..00000000 --- a/src/bdd/cudd/cuddAddIte.c +++ /dev/null @@ -1,613 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddIte.c] - - PackageName [cudd] - - Synopsis [ADD ITE function and satellites.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addIte() - <li> Cudd_addIteConstant() - <li> Cudd_addEvalConst() - <li> Cudd_addCmpl() - <li> Cudd_addLeq() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddAddIteRecur() - <li> cuddAddCmplRecur() - </ul> - Static procedures included in this module: - <ul> - <li> addVarToConst() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddIte.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void addVarToConst ARGS((DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements ITE(f,g,h).] - - Description [Implements ITE(f,g,h). This procedure assumes that f is - a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addIteConstant Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addIte( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddIteRecur(dd,f,g,h); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addIte */ - - -/**Function******************************************************************** - - Synopsis [Implements ITEconstant for ADDs.] - - Description [Implements ITEconstant for ADDs. f must be a 0-1 ADD. - Returns a pointer to the resulting ADD (which may or may not be - constant) or DD_NON_CONSTANT. No new nodes are created. This function - can be used, for instance, to check that g has a constant value - (specified by h) whenever f is 1. If the constant value is unknown, - then one should use Cudd_addEvalConst.] - - SideEffects [None] - - SeeAlso [Cudd_addIte Cudd_addEvalConst Cudd_bddIteConstant] - -******************************************************************************/ -DdNode * -Cudd_addIteConstant( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *one,*zero; - DdNode *Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*r,*t,*e; - unsigned int topf,topg,toph,v; - - statLine(dd); - /* Trivial cases. */ - if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */ - return(g); - } - if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ - return(h); - } - - /* From now on, f is known not to be a constant. */ - addVarToConst(f,&g,&h,one,zero); - - /* Check remaining one variable cases. */ - if (g == h) { /* ITE(F,G,G) = G */ - return(g); - } - if (cuddIsConstant(g) && cuddIsConstant(h)) { - return(DD_NON_CONSTANT); - } - - topf = cuddI(dd,f->index); - topg = cuddI(dd,g->index); - toph = cuddI(dd,h->index); - v = ddMin(topg,toph); - - /* ITE(F,G,H) = (x,G,H) (non constant) if F = (x,1,0), x < top(G,H). */ - if (topf < v && cuddIsConstant(cuddT(f)) && cuddIsConstant(cuddE(f))) { - return(DD_NON_CONSTANT); - } - - /* Check cache. */ - r = cuddConstantLookup(dd,DD_ADD_ITE_CONSTANT_TAG,f,g,h); - if (r != NULL) { - return(r); - } - - /* Compute cofactors. */ - if (topf <= v) { - v = ddMin(topf,v); /* v = top_var(F,G,H) */ - Fv = cuddT(f); Fnv = cuddE(f); - } else { - Fv = Fnv = f; - } - if (topg == v) { - Gv = cuddT(g); Gnv = cuddE(g); - } else { - Gv = Gnv = g; - } - if (toph == v) { - Hv = cuddT(h); Hnv = cuddE(h); - } else { - Hv = Hnv = h; - } - - /* Recursive step. */ - t = Cudd_addIteConstant(dd,Fv,Gv,Hv); - if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) { - cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - e = Cudd_addIteConstant(dd,Fnv,Gnv,Hnv); - if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) { - cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, t); - return(t); - -} /* end of Cudd_addIteConstant */ - - -/**Function******************************************************************** - - Synopsis [Checks whether ADD g is constant whenever ADD f is 1.] - - Description [Checks whether ADD g is constant whenever ADD f is 1. f - must be a 0-1 ADD. Returns a pointer to the resulting ADD (which may - or may not be constant) or DD_NON_CONSTANT. If f is identically 0, - the check is assumed to be successful, and the background value is - returned. No new nodes are created.] - - SideEffects [None] - - SeeAlso [Cudd_addIteConstant Cudd_addLeq] - -******************************************************************************/ -DdNode * -Cudd_addEvalConst( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *zero; - DdNode *Fv,*Fnv,*Gv,*Gnv,*r,*t,*e; - unsigned int topf,topg; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); -#endif - - statLine(dd); - /* Terminal cases. */ - if (f == DD_ONE(dd) || cuddIsConstant(g)) { - return(g); - } - if (f == (zero = DD_ZERO(dd))) { - return(dd->background); - } - -#ifdef DD_DEBUG - assert(!cuddIsConstant(f)); -#endif - /* From now on, f and g are known not to be constants. */ - - topf = cuddI(dd,f->index); - topg = cuddI(dd,g->index); - - /* Check cache. */ - r = cuddConstantLookup(dd,DD_ADD_EVAL_CONST_TAG,f,g,g); - if (r != NULL) { - return(r); - } - - /* Compute cofactors. */ - if (topf <= topg) { - Fv = cuddT(f); Fnv = cuddE(f); - } else { - Fv = Fnv = f; - } - if (topg <= topf) { - Gv = cuddT(g); Gnv = cuddE(g); - } else { - Gv = Gnv = g; - } - - /* Recursive step. */ - if (Fv != zero) { - t = Cudd_addEvalConst(dd,Fv,Gv); - if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) { - cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - if (Fnv != zero) { - e = Cudd_addEvalConst(dd,Fnv,Gnv); - if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) { - cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - } - cuddCacheInsert2(dd,Cudd_addEvalConst,f,g,t); - return(t); - } else { /* Fnv must be != zero */ - e = Cudd_addEvalConst(dd,Fnv,Gnv); - cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, e); - return(e); - } - -} /* end of Cudd_addEvalConst */ - - -/**Function******************************************************************** - - Synopsis [Computes the complement of an ADD a la C language.] - - Description [Computes the complement of an ADD a la C language: The - complement of 0 is 1 and the complement of everything else is 0. - Returns a pointer to the resulting ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addNegate] - -******************************************************************************/ -DdNode * -Cudd_addCmpl( - DdManager * dd, - DdNode * f) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddCmplRecur(dd,f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addCmpl */ - - -/**Function******************************************************************** - - Synopsis [Determines whether f is less than or equal to g.] - - Description [Returns 1 if f is less than or equal to g; 0 otherwise. - No new nodes are created. This procedure works for arbitrary ADDs. - For 0-1 ADDs Cudd_addEvalConst is more efficient.] - - SideEffects [None] - - SeeAlso [Cudd_addIteConstant Cudd_addEvalConst Cudd_bddLeq] - -******************************************************************************/ -int -Cudd_addLeq( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *tmp, *fv, *fvn, *gv, *gvn; - unsigned int topf, topg, res; - - /* Terminal cases. */ - if (f == g) return(1); - - statLine(dd); - if (cuddIsConstant(f)) { - if (cuddIsConstant(g)) return(cuddV(f) <= cuddV(g)); - if (f == DD_MINUS_INFINITY(dd)) return(1); - if (f == DD_PLUS_INFINITY(dd)) return(0); /* since f != g */ - } - if (g == DD_PLUS_INFINITY(dd)) return(1); - if (g == DD_MINUS_INFINITY(dd)) return(0); /* since f != g */ - - /* Check cache. */ - tmp = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, - DdNode *))Cudd_addLeq,f,g); - if (tmp != NULL) { - return(tmp == DD_ONE(dd)); - } - - /* Compute cofactors. One of f and g is not constant. */ - topf = cuddI(dd,f->index); - topg = cuddI(dd,g->index); - if (topf <= topg) { - fv = cuddT(f); fvn = cuddE(f); - } else { - fv = fvn = f; - } - if (topg <= topf) { - gv = cuddT(g); gvn = cuddE(g); - } else { - gv = gvn = g; - } - - res = Cudd_addLeq(dd,fvn,gvn) && Cudd_addLeq(dd,fv,gv); - - /* Store result in cache and return. */ - cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *)) - Cudd_addLeq,f,g,Cudd_NotCond(DD_ONE(dd),res==0)); - return(res); - -} /* end of Cudd_addLeq */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_addIte(f,g,h).] - - Description [Implements the recursive step of Cudd_addIte(f,g,h). - Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addIte] - -******************************************************************************/ -DdNode * -cuddAddIteRecur( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *one,*zero; - DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e; - unsigned int topf,topg,toph,v; - int index; - - statLine(dd); - /* Trivial cases. */ - - /* One variable cases. */ - if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */ - return(g); - } - if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ - return(h); - } - - /* From now on, f is known to not be a constant. */ - addVarToConst(f,&g,&h,one,zero); - - /* Check remaining one variable cases. */ - if (g == h) { /* ITE(F,G,G) = G */ - return(g); - } - - if (g == one) { /* ITE(F,1,0) = F */ - if (h == zero) return(f); - } - - topf = cuddI(dd,f->index); - topg = cuddI(dd,g->index); - toph = cuddI(dd,h->index); - v = ddMin(topg,toph); - - /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */ - if (topf < v && cuddT(f) == one && cuddE(f) == zero) { - r = cuddUniqueInter(dd,(int)f->index,g,h); - return(r); - } - if (topf < v && cuddT(f) == zero && cuddE(f) == one) { - r = cuddUniqueInter(dd,(int)f->index,h,g); - return(r); - } - - /* Check cache. */ - r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h); - if (r != NULL) { - return(r); - } - - /* Compute cofactors. */ - if (topf <= v) { - v = ddMin(topf,v); /* v = top_var(F,G,H) */ - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - } else { - Fv = Fnv = f; - } - if (topg == v) { - index = g->index; - Gv = cuddT(g); Gnv = cuddE(g); - } else { - Gv = Gnv = g; - } - if (toph == v) { - index = h->index; - Hv = cuddT(h); Hnv = cuddE(h); - } else { - Hv = Hnv = h; - } - - /* Recursive step. */ - t = cuddAddIteRecur(dd,Fv,Gv,Hv); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv); - if (e == NULL) { - Cudd_RecursiveDeref(dd,t); - return(NULL); - } - cuddRef(e); - - r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); - if (r == NULL) { - Cudd_RecursiveDeref(dd,t); - Cudd_RecursiveDeref(dd,e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r); - - return(r); - -} /* end of cuddAddIteRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addCmpl.] - - Description [Performs the recursive step of Cudd_addCmpl. Returns a - pointer to the resulting ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addCmpl] - -******************************************************************************/ -DdNode * -cuddAddCmplRecur( - DdManager * dd, - DdNode * f) -{ - DdNode *one,*zero; - DdNode *r,*Fv,*Fnv,*t,*e; - - statLine(dd); - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - if (cuddIsConstant(f)) { - if (f == zero) { - return(one); - } else { - return(zero); - } - } - r = cuddCacheLookup1(dd,Cudd_addCmpl,f); - if (r != NULL) { - return(r); - } - Fv = cuddT(f); - Fnv = cuddE(f); - t = cuddAddCmplRecur(dd,Fv); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddAddCmplRecur(dd,Fnv); - if (e == NULL) { - Cudd_RecursiveDeref(dd,t); - return(NULL); - } - cuddRef(e); - r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - cuddCacheInsert1(dd,Cudd_addCmpl,f,r); - return(r); - -} /* end of cuddAddCmplRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Replaces variables with constants if possible (part of - canonical form).] - - Description [] - - SideEffects [None] - -******************************************************************************/ -static void -addVarToConst( - DdNode * f, - DdNode ** gp, - DdNode ** hp, - DdNode * one, - DdNode * zero) -{ - DdNode *g = *gp; - DdNode *h = *hp; - - if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ - *gp = one; - } - - if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ - *hp = zero; - } - -} /* end of addVarToConst */ diff --git a/src/bdd/cudd/cuddAddNeg.c b/src/bdd/cudd/cuddAddNeg.c deleted file mode 100644 index bdb08ddc..00000000 --- a/src/bdd/cudd/cuddAddNeg.c +++ /dev/null @@ -1,262 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddNeg.c] - - PackageName [cudd] - - Synopsis [function to compute the negation of an ADD.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addNegate() - <li> Cudd_addRoundOff() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddAddNegateRecur() - <li> cuddAddRoundOffRecur() - </ul> ] - - Author [Fabio Somenzi, Balakrishna Kumthekar] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddNeg.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes the additive inverse of an ADD.] - - Description [Computes the additive inverse of an ADD. Returns a pointer - to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addCmpl] - -******************************************************************************/ -DdNode * -Cudd_addNegate( - DdManager * dd, - DdNode * f) -{ - DdNode *res; - - do { - res = cuddAddNegateRecur(dd,f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addNegate */ - - -/**Function******************************************************************** - - Synopsis [Rounds off the discriminants of an ADD.] - - Description [Rounds off the discriminants of an ADD. The discriminants are - rounded off to N digits after the decimal. Returns a pointer to the result - ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_addRoundOff( - DdManager * dd, - DdNode * f, - int N) -{ - DdNode *res; - double trunc = pow(10.0,(double)N); - - do { - res = cuddAddRoundOffRecur(dd,f,trunc); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addRoundOff */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_addNegate.] - - Description [Implements the recursive step of Cudd_addNegate. - Returns a pointer to the result.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -cuddAddNegateRecur( - DdManager * dd, - DdNode * f) -{ - DdNode *res, - *fv, *fvn, - *T, *E; - - statLine(dd); - /* Check terminal cases. */ - if (cuddIsConstant(f)) { - res = cuddUniqueConst(dd,-cuddV(f)); - return(res); - } - - /* Check cache */ - res = cuddCacheLookup1(dd,Cudd_addNegate,f); - if (res != NULL) return(res); - - /* Recursive Step */ - fv = cuddT(f); - fvn = cuddE(f); - T = cuddAddNegateRecur(dd,fv); - if (T == NULL) return(NULL); - cuddRef(T); - - E = cuddAddNegateRecur(dd,fvn); - if (E == NULL) { - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert1(dd,Cudd_addNegate,f,res); - - return(res); - -} /* end of cuddAddNegateRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_addRoundOff.] - - Description [Implements the recursive step of Cudd_addRoundOff. - Returns a pointer to the result.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -cuddAddRoundOffRecur( - DdManager * dd, - DdNode * f, - double trunc) -{ - - DdNode *res, *fv, *fvn, *T, *E; - double n; - DdNode *(*cacheOp)(DdManager *, DdNode *); - - statLine(dd); - if (cuddIsConstant(f)) { - n = ceil(cuddV(f)*trunc)/trunc; - res = cuddUniqueConst(dd,n); - return(res); - } - cacheOp = (DdNode *(*)(DdManager *, DdNode *)) Cudd_addRoundOff; - res = cuddCacheLookup1(dd,cacheOp,f); - if (res != NULL) { - return(res); - } - /* Recursive Step */ - fv = cuddT(f); - fvn = cuddE(f); - T = cuddAddRoundOffRecur(dd,fv,trunc); - if (T == NULL) { - return(NULL); - } - cuddRef(T); - E = cuddAddRoundOffRecur(dd,fvn,trunc); - if (E == NULL) { - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert1(dd,cacheOp,f,res); - return(res); - -} /* end of cuddAddRoundOffRecur */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddAddWalsh.c b/src/bdd/cudd/cuddAddWalsh.c deleted file mode 100644 index c6a67e34..00000000 --- a/src/bdd/cudd/cuddAddWalsh.c +++ /dev/null @@ -1,364 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddWalsh.c] - - PackageName [cudd] - - Synopsis [Functions that generate Walsh matrices and residue - functions in ADD form.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addWalsh() - <li> Cudd_addResidue() - </ul> - Static procedures included in this module: - <ul> - <li> addWalshInt() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddWalsh.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * addWalshInt ARGS((DdManager *dd, DdNode **x, DdNode **y, int n)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Generates a Walsh matrix in ADD form.] - - Description [Generates a Walsh matrix in ADD form. Returns a pointer - to the matrixi if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_addWalsh( - DdManager * dd, - DdNode ** x, - DdNode ** y, - int n) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = addWalshInt(dd, x, y, n); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addWalsh */ - - -/**Function******************************************************************** - - Synopsis [Builds an ADD for the residue modulo m of an n-bit - number.] - - Description [Builds an ADD for the residue modulo m of an n-bit - number. The modulus must be at least 2, and the number of bits at - least 1. Parameter options specifies whether the MSB should be on top - or the LSB; and whther the number whose residue is computed is in - two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT - specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB - specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's - complement residue. To request MSB on top and two's complement residue - simultaneously, one can OR the two macros: - CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC. - Cudd_addResidue returns a pointer to the resulting ADD if successful; - NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_addResidue( - DdManager * dd /* manager */, - int n /* number of bits */, - int m /* modulus */, - int options /* options */, - int top /* index of top variable */) -{ - int msbLsb; /* MSB on top (1) or LSB on top (0) */ - int tc; /* two's complement (1) or unsigned (0) */ - int i, j, k, t, residue, thisOne, previous, index; - DdNode **array[2], *var, *tmp, *res; - - /* Sanity check. */ - if (n < 1 && m < 2) return(NULL); - - msbLsb = options & CUDD_RESIDUE_MSB; - tc = options & CUDD_RESIDUE_TC; - - /* Allocate and initialize working arrays. */ - array[0] = ALLOC(DdNode *,m); - if (array[0] == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - array[1] = ALLOC(DdNode *,m); - if (array[1] == NULL) { - FREE(array[0]); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < m; i++) { - array[0][i] = array[1][i] = NULL; - } - - /* Initialize residues. */ - for (i = 0; i < m; i++) { - tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i); - if (tmp == NULL) { - for (j = 0; j < i; j++) { - Cudd_RecursiveDeref(dd,array[1][j]); - } - FREE(array[0]); - FREE(array[1]); - return(NULL); - } - cuddRef(tmp); - array[1][i] = tmp; - } - - /* Main iteration. */ - residue = 1; /* residue of 2**0 */ - for (k = 0; k < n; k++) { - /* Choose current and previous arrays. */ - thisOne = k & 1; - previous = thisOne ^ 1; - /* Build an ADD projection function. */ - if (msbLsb) { - index = top+n-k-1; - } else { - index = top+k; - } - var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd)); - if (var == NULL) { - for (j = 0; j < m; j++) { - Cudd_RecursiveDeref(dd,array[previous][j]); - } - FREE(array[0]); - FREE(array[1]); - return(NULL); - } - cuddRef(var); - for (i = 0; i < m; i ++) { - t = (i + residue) % m; - tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]); - if (tmp == NULL) { - for (j = 0; j < i; j++) { - Cudd_RecursiveDeref(dd,array[thisOne][j]); - } - for (j = 0; j < m; j++) { - Cudd_RecursiveDeref(dd,array[previous][j]); - } - FREE(array[0]); - FREE(array[1]); - return(NULL); - } - cuddRef(tmp); - array[thisOne][i] = tmp; - } - /* One layer completed. Free the other array for the next iteration. */ - for (i = 0; i < m; i++) { - Cudd_RecursiveDeref(dd,array[previous][i]); - } - Cudd_RecursiveDeref(dd,var); - /* Update residue of 2**k. */ - residue = (2 * residue) % m; - /* Adjust residue for MSB, if this is a two's complement number. */ - if (tc && (k == n - 1)) { - residue = (m - residue) % m; - } - } - - /* We are only interested in the 0-residue node of the top layer. */ - for (i = 1; i < m; i++) { - Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]); - } - res = array[(n - 1) & 1][0]; - - FREE(array[0]); - FREE(array[1]); - - cuddDeref(res); - return(res); - -} /* end of Cudd_addResidue */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_addWalsh.] - - Description [Generates a Walsh matrix in ADD form. Returns a pointer - to the matrixi if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -addWalshInt( - DdManager * dd, - DdNode ** x, - DdNode ** y, - int n) -{ - DdNode *one, *minusone; - DdNode *t, *u, *t1, *u1, *v, *w; - int i; - - one = DD_ONE(dd); - if (n == 0) return(one); - - /* Build bottom part of ADD outside loop */ - minusone = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) -1); - if (minusone == NULL) return(NULL); - cuddRef(minusone); - v = Cudd_addIte(dd, y[n-1], minusone, one); - if (v == NULL) { - Cudd_RecursiveDeref(dd, minusone); - return(NULL); - } - cuddRef(v); - u = Cudd_addIte(dd, x[n-1], v, one); - if (u == NULL) { - Cudd_RecursiveDeref(dd, minusone); - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - if (n>1) { - w = Cudd_addIte(dd, y[n-1], one, minusone); - if (w == NULL) { - Cudd_RecursiveDeref(dd, minusone); - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(w); - t = Cudd_addIte(dd, x[n-1], w, minusone); - if (t == NULL) { - Cudd_RecursiveDeref(dd, minusone); - Cudd_RecursiveDeref(dd, u); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(t); - Cudd_RecursiveDeref(dd, w); - } - cuddDeref(minusone); /* minusone is in the result; it won't die */ - - /* Loop to build the rest of the ADD */ - for (i=n-2; i>=0; i--) { - t1 = t; u1 = u; - v = Cudd_addIte(dd, y[i], t1, u1); - if (v == NULL) { - Cudd_RecursiveDeref(dd, u1); - Cudd_RecursiveDeref(dd, t1); - return(NULL); - } - cuddRef(v); - u = Cudd_addIte(dd, x[i], v, u1); - if (u == NULL) { - Cudd_RecursiveDeref(dd, u1); - Cudd_RecursiveDeref(dd, t1); - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - if (i>0) { - w = Cudd_addIte(dd, y[i], u1, t1); - if (u == NULL) { - Cudd_RecursiveDeref(dd, u1); - Cudd_RecursiveDeref(dd, t1); - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(w); - t = Cudd_addIte(dd, x[i], w, t1); - if (u == NULL) { - Cudd_RecursiveDeref(dd, u1); - Cudd_RecursiveDeref(dd, t1); - Cudd_RecursiveDeref(dd, u); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(t); - Cudd_RecursiveDeref(dd, w); - } - Cudd_RecursiveDeref(dd, u1); - Cudd_RecursiveDeref(dd, t1); - } - - cuddDeref(u); - return(u); - -} /* end of addWalshInt */ diff --git a/src/bdd/cudd/cuddAndAbs.c b/src/bdd/cudd/cuddAndAbs.c deleted file mode 100644 index 5ec47beb..00000000 --- a/src/bdd/cudd/cuddAndAbs.c +++ /dev/null @@ -1,306 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAndAbs.c] - - PackageName [cudd] - - Synopsis [Combined AND and existential abstraction for BDDs] - - Description [External procedures included in this module: - <ul> - <li> Cudd_bddAndAbstract() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddBddAndAbstractRecur() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAndAbs.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Takes the AND of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Takes the AND of two BDDs and simultaneously abstracts - the variables in cube. The variables are existentially abstracted. - Returns a pointer to the result is successful; NULL otherwise. - Cudd_bddAndAbstract implements the semiring matrix multiplication - algorithm for the boolean semiring.] - - SideEffects [None] - - SeeAlso [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd] - -******************************************************************************/ -DdNode * -Cudd_bddAndAbstract( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube) -{ - DdNode *res; - - do { - manager->reordered = 0; - res = cuddBddAndAbstractRecur(manager, f, g, cube); - } while (manager->reordered == 1); - return(res); - -} /* end of Cudd_bddAndAbstract */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Takes the AND of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Takes the AND of two BDDs and simultaneously abstracts - the variables in cube. The variables are existentially abstracted. - Returns a pointer to the result is successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -cuddBddAndAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube) -{ - DdNode *F, *ft, *fe, *G, *gt, *ge; - DdNode *one, *zero, *r, *t, *e; - unsigned int topf, topg, topcube, top, index; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); - if (f == one && g == one) return(one); - - if (cube == one) { - return(cuddBddAndRecur(manager, f, g)); - } - if (f == one || f == g) { - return(cuddBddExistAbstractRecur(manager, g, cube)); - } - if (g == one) { - return(cuddBddExistAbstractRecur(manager, f, cube)); - } - /* At this point f, g, and cube are not constant. */ - - if (f > g) { /* Try to increase cache efficiency. */ - DdNode *tmp = f; - f = g; - g = tmp; - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - F = Cudd_Regular(f); - G = Cudd_Regular(g); - topf = manager->perm[F->index]; - topg = manager->perm[G->index]; - top = ddMin(topf, topg); - topcube = manager->perm[cube->index]; - - while (topcube < top) { - cube = cuddT(cube); - if (cube == one) { - return(cuddBddAndRecur(manager, f, g)); - } - topcube = manager->perm[cube->index]; - } - /* Now, topcube >= top. */ - - /* Check cache. */ - if (F->ref != 1 || G->ref != 1) { - r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube); - if (r != NULL) { - return(r); - } - } - - if (topf == top) { - index = F->index; - ft = cuddT(F); - fe = cuddE(F); - if (Cudd_IsComplement(f)) { - ft = Cudd_Not(ft); - fe = Cudd_Not(fe); - } - } else { - index = G->index; - ft = fe = f; - } - - if (topg == top) { - gt = cuddT(G); - ge = cuddE(G); - if (Cudd_IsComplement(g)) { - gt = Cudd_Not(gt); - ge = Cudd_Not(ge); - } - } else { - gt = ge = g; - } - - if (topcube == top) { /* quantify */ - DdNode *Cube = cuddT(cube); - t = cuddBddAndAbstractRecur(manager, ft, gt, Cube); - if (t == NULL) return(NULL); - /* Special case: 1 OR anything = 1. Hence, no need to compute - ** the else branch if t is 1. Likewise t + t * anything == t. - ** Notice that t == fe implies that fe does not depend on the - ** variables in Cube. Likewise for t == ge. - */ - if (t == one || t == fe || t == ge) { - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, - f, g, cube, t); - return(t); - } - cuddRef(t); - /* Special case: t + !t * anything == t + anything. */ - if (t == Cudd_Not(fe)) { - e = cuddBddExistAbstractRecur(manager, ge, Cube); - } else if (t == Cudd_Not(ge)) { - e = cuddBddExistAbstractRecur(manager, fe, Cube); - } else { - e = cuddBddAndAbstractRecur(manager, fe, ge, Cube); - } - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - if (t == e) { - r = t; - cuddDeref(t); - } else { - cuddRef(e); - r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - cuddRef(r); - Cudd_DelayedDerefBdd(manager, t); - Cudd_DelayedDerefBdd(manager, e); - cuddDeref(r); - } - } else { - t = cuddBddAndAbstractRecur(manager, ft, gt, cube); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddBddAndAbstractRecur(manager, fe, ge, cube); - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - if (t == e) { - r = t; - cuddDeref(t); - } else { - cuddRef(e); - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager, (int) index, - Cudd_Not(t), Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - } - cuddDeref(e); - cuddDeref(t); - } - } - - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r); - return (r); - -} /* end of cuddBddAndAbstractRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddAnneal.c b/src/bdd/cudd/cuddAnneal.c deleted file mode 100644 index 3d8b56b9..00000000 --- a/src/bdd/cudd/cuddAnneal.c +++ /dev/null @@ -1,788 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAnneal.c] - - PackageName [cudd] - - Synopsis [Reordering of DDs based on simulated annealing] - - Description [Internal procedures included in this file: - <ul> - <li> cuddAnnealing() - </ul> - Static procedures included in this file: - <ul> - <li> stopping_criterion() - <li> random_generator() - <li> ddExchange() - <li> ddJumpingAux() - <li> ddJumpingUp() - <li> ddJumpingDown() - <li> siftBackwardProb() - <li> copyOrder() - <li> restoreOrder() - </ul> - ] - - SeeAlso [] - - Author [Jae-Young Jang, Jorgen Sivesind] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/* Annealing parameters */ -#define BETA 0.6 -#define ALPHA 0.90 -#define EXC_PROB 0.4 -#define JUMP_UP_PROB 0.36 -#define MAXGEN_RATIO 15.0 -#define STOP_TEMP 1.0 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAnneal.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -#ifdef DD_STATS -extern int ddTotalNumberSwapping; -extern int ddTotalNISwaps; -static int tosses; -static int acceptances; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int stopping_criterion ARGS((int c1, int c2, int c3, int c4, double temp)); -static double random_generator ARGS(()); -static int ddExchange ARGS((DdManager *table, int x, int y, double temp)); -static int ddJumpingAux ARGS((DdManager *table, int x, int x_low, int x_high, double temp)); -static Move * ddJumpingUp ARGS((DdManager *table, int x, int x_low, int initial_size)); -static Move * ddJumpingDown ARGS((DdManager *table, int x, int x_high, int initial_size)); -static int siftBackwardProb ARGS((DdManager *table, Move *moves, int size, double temp)); -static void copyOrder ARGS((DdManager *table, int *array, int lower, int upper)); -static int restoreOrder ARGS((DdManager *table, int *array, int lower, int upper)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Get new variable-order by simulated annealing algorithm.] - - Description [Get x, y by random selection. Choose either - exchange or jump randomly. In case of jump, choose between jump_up - and jump_down randomly. Do exchange or jump and get optimal case. - Loop until there is no improvement or temperature reaches - minimum. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddAnnealing( - DdManager * table, - int lower, - int upper) -{ - int nvars; - int size; - int x,y; - int result; - int c1, c2, c3, c4; - int BestCost; - int *BestOrder; - double NewTemp, temp; - double rand1; - int innerloop, maxGen; - int ecount, ucount, dcount; - - nvars = upper - lower + 1; - - result = cuddSifting(table,lower,upper); -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); -#endif - if (result == 0) return(0); - - size = table->keys - table->isolated; - - /* Keep track of the best order. */ - BestCost = size; - BestOrder = ALLOC(int,nvars); - if (BestOrder == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - copyOrder(table,BestOrder,lower,upper); - - temp = BETA * size; - maxGen = (int) (MAXGEN_RATIO * nvars); - - c1 = size + 10; - c2 = c1 + 10; - c3 = size; - c4 = c2 + 10; - ecount = ucount = dcount = 0; - - while (!stopping_criterion(c1, c2, c3, c4, temp)) { -#ifdef DD_STATS - (void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t", - temp,size,maxGen); - tosses = acceptances = 0; -#endif - for (innerloop = 0; innerloop < maxGen; innerloop++) { - /* Choose x, y randomly. */ - x = (int) Cudd_Random() % nvars; - do { - y = (int) Cudd_Random() % nvars; - } while (x == y); - x += lower; - y += lower; - if (x > y) { - int tmp = x; - x = y; - y = tmp; - } - - /* Choose move with roulette wheel. */ - rand1 = random_generator(); - if (rand1 < EXC_PROB) { - result = ddExchange(table,x,y,temp); /* exchange */ - ecount++; -#if 0 - (void) fprintf(table->out, - "Exchange of %d and %d: size = %d\n", - x,y,table->keys - table->isolated); -#endif - } else if (rand1 < EXC_PROB + JUMP_UP_PROB) { - result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */ - ucount++; -#if 0 - (void) fprintf(table->out, - "Jump up of %d to %d: size = %d\n", - y,x,table->keys - table->isolated); -#endif - } else { - result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */ - dcount++; -#if 0 - (void) fprintf(table->out, - "Jump down of %d to %d: size = %d\n", - x,y,table->keys - table->isolated); -#endif - } - - if (!result) { - FREE(BestOrder); - return(0); - } - - size = table->keys - table->isolated; /* keep current size */ - if (size < BestCost) { /* update best order */ - BestCost = size; - copyOrder(table,BestOrder,lower,upper); - } - } - c1 = c2; - c2 = c3; - c3 = c4; - c4 = size; - NewTemp = ALPHA * temp; - if (NewTemp >= 1.0) { - maxGen = (int)(log(NewTemp) / log(temp) * maxGen); - } - temp = NewTemp; /* control variable */ -#ifdef DD_STATS - (void) fprintf(table->out,"uphill = %d\taccepted = %d\n", - tosses,acceptances); - fflush(table->out); -#endif - } - - result = restoreOrder(table,BestOrder,lower,upper); - FREE(BestOrder); - if (!result) return(0); -#ifdef DD_STATS - fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount); - fprintf(table->out,"#:N_JUMPUP %8d : total jumps up\n",ucount); - fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount); -#endif - return(1); - -} /* end of cuddAnnealing */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Checks termination condition.] - - Description [If temperature is STOP_TEMP or there is no improvement - then terminates. Returns 1 if the termination criterion is met; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -stopping_criterion( - int c1, - int c2, - int c3, - int c4, - double temp) -{ - if (STOP_TEMP < temp) { - return(0); - } else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) { - return(1); - } else { - return(0); - } - -} /* end of stopping_criterion */ - - -/**Function******************************************************************** - - Synopsis [Random number generator.] - - Description [Returns a double precision value between 0.0 and 1.0.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static double -random_generator( - ) -{ - return((double)(Cudd_Random() / 2147483561.0)); - -} /* end of random_generator */ - - -/**Function******************************************************************** - - Synopsis [This function is for exchanging two variables, x and y.] - - Description [This is the same funcion as ddSwapping except for - comparison expression. Use probability function, exp(-size_change/temp).] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddExchange( - DdManager * table, - int x, - int y, - double temp) -{ - Move *move,*moves; - int tmp; - int x_ref,y_ref; - int x_next,y_next; - int size, result; - int initial_size, limit_size; - - x_ref = x; - y_ref = y; - - x_next = cuddNextHigh(table,x); - y_next = cuddNextLow(table,y); - moves = NULL; - initial_size = limit_size = table->keys - table->isolated; - - for (;;) { - if (x_next == y_next) { - size = cuddSwapInPlace(table,x,x_next); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - size = cuddSwapInPlace(table,y_next,y); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - size = cuddSwapInPlace(table,x,x_next); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; - x = y; - y = tmp; - } else if (x == y_next) { - size = cuddSwapInPlace(table,x,x_next); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - tmp = x; - x = y; - y = tmp; - } else { - size = cuddSwapInPlace(table,x,x_next); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - size = cuddSwapInPlace(table,y_next,y); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - x = x_next; - y = y_next; - } - - x_next = cuddNextHigh(table,x); - y_next = cuddNextLow(table,y); - if (x_next > y_ref) break; - - if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) { - break; - } else if (size < limit_size) { - limit_size = size; - } - } - - if (y_next>=x_ref) { - size = cuddSwapInPlace(table,y_next,y); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - } - - /* move backward and stop at best position or accept uphill move */ - result = siftBackwardProb(table,moves,initial_size,temp); - if (!result) goto ddExchangeOutOfMem; - - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(1); - -ddExchangeOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table,(DdNode *) moves); - moves = move; - } - return(0); - -} /* end of ddExchange */ - - -/**Function******************************************************************** - - Synopsis [Moves a variable to a specified position.] - - Description [If x==x_low, it executes jumping_down. If x==x_high, it - executes jumping_up. This funcion is similar to ddSiftingAux. Returns - 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddJumpingAux( - DdManager * table, - int x, - int x_low, - int x_high, - double temp) -{ - Move *move; - Move *moves; /* list of moves */ - int initial_size; - int result; - - initial_size = table->keys - table->isolated; - -#ifdef DD_DEBUG - assert(table->subtables[x].keys > 0); -#endif - - moves = NULL; - - if (cuddNextLow(table,x) < x_low) { - if (cuddNextHigh(table,x) > x_high) return(1); - moves = ddJumpingDown(table,x,x_high,initial_size); - /* after that point x --> x_high unless early termination */ - if (moves == NULL) goto ddJumpingAuxOutOfMem; - /* move backward and stop at best position or accept uphill move */ - result = siftBackwardProb(table,moves,initial_size,temp); - if (!result) goto ddJumpingAuxOutOfMem; - } else if (cuddNextHigh(table,x) > x_high) { - moves = ddJumpingUp(table,x,x_low,initial_size); - /* after that point x --> x_low unless early termination */ - if (moves == NULL) goto ddJumpingAuxOutOfMem; - /* move backward and stop at best position or accept uphill move */ - result = siftBackwardProb(table,moves,initial_size,temp); - if (!result) goto ddJumpingAuxOutOfMem; - } else { - (void) fprintf(table->err,"Unexpected condition in ddJumping\n"); - goto ddJumpingAuxOutOfMem; - } - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(1); - -ddJumpingAuxOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(0); - -} /* end of ddJumpingAux */ - - -/**Function******************************************************************** - - Synopsis [This function is for jumping up.] - - Description [This is a simplified version of ddSiftingUp. It does not - use lower bounding. Returns the set of moves in case of success; NULL - if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -ddJumpingUp( - DdManager * table, - int x, - int x_low, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - - moves = NULL; - y = cuddNextLow(table,x); - while (y >= x_low) { - size = cuddSwapInPlace(table,y,x); - if (size == 0) goto ddJumpingUpOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddJumpingUpOutOfMem; - move->x = y; - move->y = x; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > table->maxGrowth * (double) limit_size) { - break; - } else if (size < limit_size) { - limit_size = size; - } - x = y; - y = cuddNextLow(table,x); - } - return(moves); - -ddJumpingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(NULL); - -} /* end of ddJumpingUp */ - - -/**Function******************************************************************** - - Synopsis [This function is for jumping down.] - - Description [This is a simplified version of ddSiftingDown. It does not - use lower bounding. Returns the set of moves in case of success; NULL - if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -ddJumpingDown( - DdManager * table, - int x, - int x_high, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - - moves = NULL; - y = cuddNextHigh(table,x); - while (y <= x_high) { - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddJumpingDownOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddJumpingDownOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > table->maxGrowth * (double) limit_size) { - break; - } else if (size < limit_size) { - limit_size = size; - } - x = y; - y = cuddNextHigh(table,x); - } - return(moves); - -ddJumpingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(NULL); - -} /* end of ddJumpingDown */ - - -/**Function******************************************************************** - - Synopsis [Returns the DD to the best position encountered during - sifting if there was improvement.] - - Description [Otherwise, "tosses a coin" to decide whether to keep - the current configuration or return the DD to the original - one. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -siftBackwardProb( - DdManager * table, - Move * moves, - int size, - double temp) -{ - Move *move; - int res; - int best_size = size; - double coin, threshold; - - /* Look for best size during the last sifting */ - for (move = moves; move != NULL; move = move->next) { - if (move->size < best_size) { - best_size = move->size; - } - } - - /* If best_size equals size, the last sifting did not produce any - ** improvement. We now toss a coin to decide whether to retain - ** this change or not. - */ - if (best_size == size) { - coin = random_generator(); -#ifdef DD_STATS - tosses++; -#endif - threshold = exp(-((double)(table->keys - table->isolated - size))/temp); - if (coin < threshold) { -#ifdef DD_STATS - acceptances++; -#endif - return(1); - } - } - - /* Either there was improvement, or we have decided not to - ** accept the uphill move. Go to best position. - */ - res = table->keys - table->isolated; - for (move = moves; move != NULL; move = move->next) { - if (res == best_size) return(1); - res = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - - return(1); - -} /* end of sift_backward_prob */ - - -/**Function******************************************************************** - - Synopsis [Copies the current variable order to array.] - - Description [Copies the current variable order to array. - At the same time inverts the permutation.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -copyOrder( - DdManager * table, - int * array, - int lower, - int upper) -{ - int i; - int nvars; - - nvars = upper - lower + 1; - for (i = 0; i < nvars; i++) { - array[i] = table->invperm[i+lower]; - } - -} /* end of copyOrder */ - - -/**Function******************************************************************** - - Synopsis [Restores the variable order in array by a series of sifts up.] - - Description [Restores the variable order in array by a series of sifts up. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -restoreOrder( - DdManager * table, - int * array, - int lower, - int upper) -{ - int i, x, y, size; - int nvars = upper - lower + 1; - - for (i = 0; i < nvars; i++) { - x = table->perm[array[i]]; -#ifdef DD_DEBUG - assert(x >= lower && x <= upper); -#endif - y = cuddNextLow(table,x); - while (y >= i + lower) { - size = cuddSwapInPlace(table,y,x); - if (size == 0) return(0); - x = y; - y = cuddNextLow(table,x); - } - } - - return(1); - -} /* end of restoreOrder */ - diff --git a/src/bdd/cudd/cuddApa.c b/src/bdd/cudd/cuddApa.c deleted file mode 100644 index 47ab51e8..00000000 --- a/src/bdd/cudd/cuddApa.c +++ /dev/null @@ -1,930 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddApa.c] - - PackageName [cudd] - - Synopsis [Arbitrary precision arithmetic functions.] - - Description [External procedures included in this module: - <ul> - <li> - </ul> - Internal procedures included in this module: - <ul> - <li> () - </ul> - Static procedures included in this module: - <ul> - <li> () - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddApa.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -static DdNode *background, *zero; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdApaNumber cuddApaCountMintermAux ARGS((DdNode * node, int digits, DdApaNumber max, DdApaNumber min, st_table * table)); -static enum st_retval cuddApaStCountfree ARGS((char * key, char * value, char * arg)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Finds the number of digits for an arbitrary precision - integer.] - - Description [Finds the number of digits for an arbitrary precision - integer given the maximum number of binary digits. The number of - binary digits should be positive. Returns the number of digits if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_ApaNumberOfDigits( - int binaryDigits) -{ - int digits; - - digits = binaryDigits / DD_APA_BITS; - if ((digits * DD_APA_BITS) != binaryDigits) - digits++; - return(digits); - -} /* end of Cudd_ApaNumberOfDigits */ - - -/**Function******************************************************************** - - Synopsis [Allocates memory for an arbitrary precision integer.] - - Description [Allocates memory for an arbitrary precision - integer. Returns a pointer to the allocated memory if successful; - NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdApaNumber -Cudd_NewApaNumber( - int digits) -{ - return(ALLOC(DdApaDigit, digits)); - -} /* end of Cudd_NewApaNumber */ - - -/**Function******************************************************************** - - Synopsis [Makes a copy of an arbitrary precision integer.] - - Description [Makes a copy of an arbitrary precision integer.] - - SideEffects [Changes parameter <code>dest</code>.] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_ApaCopy( - int digits, - DdApaNumber source, - DdApaNumber dest) -{ - int i; - - for (i = 0; i < digits; i++) { - dest[i] = source[i]; - } - -} /* end of Cudd_ApaCopy */ - - -/**Function******************************************************************** - - Synopsis [Adds two arbitrary precision integers.] - - Description [Adds two arbitrary precision integers. Returns the - carry out of the most significant digit.] - - SideEffects [The result of the sum is stored in parameter <code>sum</code>.] - - SeeAlso [] - -******************************************************************************/ -DdApaDigit -Cudd_ApaAdd( - int digits, - DdApaNumber a, - DdApaNumber b, - DdApaNumber sum) -{ - int i; - DdApaDoubleDigit partial = 0; - - for (i = digits - 1; i >= 0; i--) { - partial = a[i] + b[i] + DD_MSDIGIT(partial); - sum[i] = (DdApaDigit) DD_LSDIGIT(partial); - } - return(DD_MSDIGIT(partial)); - -} /* end of Cudd_ApaAdd */ - - -/**Function******************************************************************** - - Synopsis [Subtracts two arbitrary precision integers.] - - Description [Subtracts two arbitrary precision integers. Returns the - borrow out of the most significant digit.] - - SideEffects [The result of the subtraction is stored in parameter - <code>diff</code>.] - - SeeAlso [] - -******************************************************************************/ -DdApaDigit -Cudd_ApaSubtract( - int digits, - DdApaNumber a, - DdApaNumber b, - DdApaNumber diff) -{ - int i; - DdApaDoubleDigit partial = DD_APA_BASE; - - for (i = digits - 1; i >= 0; i--) { - partial = a[i] - b[i] + DD_MSDIGIT(partial) + DD_APA_MASK; - diff[i] = (DdApaDigit) DD_LSDIGIT(partial); - } - return(DD_MSDIGIT(partial) - 1); - -} /* end of Cudd_ApaSubtract */ - - -/**Function******************************************************************** - - Synopsis [Divides an arbitrary precision integer by a digit.] - - Description [Divides an arbitrary precision integer by a digit.] - - SideEffects [The quotient is returned in parameter <code>quotient</code>.] - - SeeAlso [] - -******************************************************************************/ -DdApaDigit -Cudd_ApaShortDivision( - int digits, - DdApaNumber dividend, - DdApaDigit divisor, - DdApaNumber quotient) -{ - int i; - DdApaDigit remainder; - DdApaDoubleDigit partial; - - remainder = 0; - for (i = 0; i < digits; i++) { - partial = remainder * DD_APA_BASE + dividend[i]; - quotient[i] = (DdApaDigit) (partial/(DdApaDoubleDigit)divisor); - remainder = (DdApaDigit) (partial % divisor); - } - - return(remainder); - -} /* end of Cudd_ApaShortDivision */ - - -/**Function******************************************************************** - - Synopsis [Divides an arbitrary precision integer by an integer.] - - Description [Divides an arbitrary precision integer by a 32-bit - unsigned integer. Returns the remainder of the division. This - procedure relies on the assumption that the number of bits of a - DdApaDigit plus the number of bits of an unsigned int is less the - number of bits of the mantissa of a double. This guarantees that the - product of a DdApaDigit and an unsigned int can be represented - without loss of precision by a double. On machines where this - assumption is not satisfied, this procedure will malfunction.] - - SideEffects [The quotient is returned in parameter <code>quotient</code>.] - - SeeAlso [Cudd_ApaShortDivision] - -******************************************************************************/ -unsigned int -Cudd_ApaIntDivision( - int digits, - DdApaNumber dividend, - unsigned int divisor, - DdApaNumber quotient) -{ - int i; - double partial; - unsigned int remainder = 0; - double ddiv = (double) divisor; - - for (i = 0; i < digits; i++) { - partial = (double) remainder * DD_APA_BASE + dividend[i]; - quotient[i] = (DdApaDigit) (partial / ddiv); - remainder = (unsigned int) (partial - ((double)quotient[i] * ddiv)); - } - - return(remainder); - -} /* end of Cudd_ApaIntDivision */ - - -/**Function******************************************************************** - - Synopsis [Shifts right an arbitrary precision integer by one binary - place.] - - Description [Shifts right an arbitrary precision integer by one - binary place. The most significant binary digit of the result is - taken from parameter <code>in</code>.] - - SideEffects [The result is returned in parameter <code>b</code>.] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_ApaShiftRight( - int digits, - DdApaDigit in, - DdApaNumber a, - DdApaNumber b) -{ - int i; - - for (i = digits - 1; i > 0; i--) { - b[i] = (a[i] >> 1) | ((a[i-1] & 1) << (DD_APA_BITS - 1)); - } - b[0] = (a[0] >> 1) | (in << (DD_APA_BITS - 1)); - -} /* end of Cudd_ApaShiftRight */ - - -/**Function******************************************************************** - - Synopsis [Sets an arbitrary precision integer to a one-digit literal.] - - Description [Sets an arbitrary precision integer to a one-digit literal.] - - SideEffects [The result is returned in parameter <code>number</code>.] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_ApaSetToLiteral( - int digits, - DdApaNumber number, - DdApaDigit literal) -{ - int i; - - for (i = 0; i < digits - 1; i++) - number[i] = 0; - number[digits - 1] = literal; - -} /* end of Cudd_ApaSetToLiteral */ - - -/**Function******************************************************************** - - Synopsis [Sets an arbitrary precision integer to a power of two.] - - Description [Sets an arbitrary precision integer to a power of - two. If the power of two is too large to be represented, the number - is set to 0.] - - SideEffects [The result is returned in parameter <code>number</code>.] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_ApaPowerOfTwo( - int digits, - DdApaNumber number, - int power) -{ - int i; - int index; - - for (i = 0; i < digits; i++) - number[i] = 0; - i = digits - 1 - power / DD_APA_BITS; - if (i < 0) return; - index = power & (DD_APA_BITS - 1); - number[i] = 1 << index; - -} /* end of Cudd_ApaPowerOfTwo */ - - -/**Function******************************************************************** - - Synopsis [Compares two arbitrary precision integers.] - - Description [Compares two arbitrary precision integers. Returns 1 if - the first number is larger; 0 if they are equal; -1 if the second - number is larger.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_ApaCompare( - int digitsFirst, - DdApaNumber first, - int digitsSecond, - DdApaNumber second) -{ - int i; - int firstNZ, secondNZ; - - /* Find first non-zero in both numbers. */ - for (firstNZ = 0; firstNZ < digitsFirst; firstNZ++) - if (first[firstNZ] != 0) break; - for (secondNZ = 0; secondNZ < digitsSecond; secondNZ++) - if (second[secondNZ] != 0) break; - if (digitsFirst - firstNZ > digitsSecond - secondNZ) return(1); - else if (digitsFirst - firstNZ < digitsSecond - secondNZ) return(-1); - for (i = 0; i < digitsFirst - firstNZ; i++) { - if (first[firstNZ + i] > second[secondNZ + i]) return(1); - else if (first[firstNZ + i] < second[secondNZ + i]) return(-1); - } - return(0); - -} /* end of Cudd_ApaCompare */ - - -/**Function******************************************************************** - - Synopsis [Compares the ratios of two arbitrary precision integers to two - unsigned ints.] - - Description [Compares the ratios of two arbitrary precision integers - to two unsigned ints. Returns 1 if the first number is larger; 0 if - they are equal; -1 if the second number is larger.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_ApaCompareRatios( - int digitsFirst, - DdApaNumber firstNum, - unsigned int firstDen, - int digitsSecond, - DdApaNumber secondNum, - unsigned int secondDen) -{ - int result; - DdApaNumber first, second; - unsigned int firstRem, secondRem; - - first = Cudd_NewApaNumber(digitsFirst); - firstRem = Cudd_ApaIntDivision(digitsFirst,firstNum,firstDen,first); - second = Cudd_NewApaNumber(digitsSecond); - secondRem = Cudd_ApaIntDivision(digitsSecond,secondNum,secondDen,second); - result = Cudd_ApaCompare(digitsFirst,first,digitsSecond,second); - if (result == 0) { - if ((double)firstRem/firstDen > (double)secondRem/secondDen) - return(1); - else if ((double)firstRem/firstDen < (double)secondRem/secondDen) - return(-1); - } - return(result); - -} /* end of Cudd_ApaCompareRatios */ - - -/**Function******************************************************************** - - Synopsis [Prints an arbitrary precision integer in hexadecimal format.] - - Description [Prints an arbitrary precision integer in hexadecimal format. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ApaPrintDecimal Cudd_ApaPrintExponential] - -******************************************************************************/ -int -Cudd_ApaPrintHex( - FILE * fp, - int digits, - DdApaNumber number) -{ - int i, result; - - for (i = 0; i < digits; i++) { - result = fprintf(fp,DD_APA_HEXPRINT,number[i]); - if (result == EOF) - return(0); - } - return(1); - -} /* end of Cudd_ApaPrintHex */ - - -/**Function******************************************************************** - - Synopsis [Prints an arbitrary precision integer in decimal format.] - - Description [Prints an arbitrary precision integer in decimal format. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintExponential] - -******************************************************************************/ -int -Cudd_ApaPrintDecimal( - FILE * fp, - int digits, - DdApaNumber number) -{ - int i, result; - DdApaDigit remainder; - DdApaNumber work; - unsigned char *decimal; - int leadingzero; - int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1; - - work = Cudd_NewApaNumber(digits); - if (work == NULL) - return(0); - decimal = ALLOC(unsigned char, decimalDigits); - if (decimal == NULL) { - FREE(work); - return(0); - } - Cudd_ApaCopy(digits,number,work); - for (i = decimalDigits - 1; i >= 0; i--) { - remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work); - decimal[i] = remainder; - } - FREE(work); - - leadingzero = 1; - for (i = 0; i < decimalDigits; i++) { - leadingzero = leadingzero && (decimal[i] == 0); - if ((!leadingzero) || (i == (decimalDigits - 1))) { - result = fprintf(fp,"%1d",decimal[i]); - if (result == EOF) { - FREE(decimal); - return(0); - } - } - } - FREE(decimal); - return(1); - -} /* end of Cudd_ApaPrintDecimal */ - - -/**Function******************************************************************** - - Synopsis [Prints an arbitrary precision integer in exponential format.] - - Description [Prints an arbitrary precision integer in exponential format. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintDecimal] - -******************************************************************************/ -int -Cudd_ApaPrintExponential( - FILE * fp, - int digits, - DdApaNumber number, - int precision) -{ - int i, first, last, result; - DdApaDigit remainder; - DdApaNumber work; - unsigned char *decimal; - int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1; - - work = Cudd_NewApaNumber(digits); - if (work == NULL) - return(0); - decimal = ALLOC(unsigned char, decimalDigits); - if (decimal == NULL) { - FREE(work); - return(0); - } - Cudd_ApaCopy(digits,number,work); - first = decimalDigits - 1; - for (i = decimalDigits - 1; i >= 0; i--) { - remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work); - decimal[i] = remainder; - if (remainder != 0) first = i; /* keep track of MS non-zero */ - } - FREE(work); - last = ddMin(first + precision, decimalDigits); - - for (i = first; i < last; i++) { - result = fprintf(fp,"%s%1d",i == first+1 ? "." : "", decimal[i]); - if (result == EOF) { - FREE(decimal); - return(0); - } - } - FREE(decimal); - result = fprintf(fp,"e+%d",decimalDigits - first - 1); - if (result == EOF) { - return(0); - } - return(1); - -} /* end of Cudd_ApaPrintExponential */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms of a DD.] - - Description [Counts the number of minterms of a DD. The function is - assumed to depend on nvars variables. The minterm count is - represented as an arbitrary precision unsigned integer, to allow for - any number of variables CUDD supports. Returns a pointer to the - array representing the number of minterms of the function rooted at - node if successful; NULL otherwise.] - - SideEffects [The number of digits of the result is returned in - parameter <code>digits</code>.] - - SeeAlso [Cudd_CountMinterm] - -******************************************************************************/ -DdApaNumber -Cudd_ApaCountMinterm( - DdManager * manager, - DdNode * node, - int nvars, - int * digits) -{ - DdApaNumber max, min; - st_table *table; - DdApaNumber i,count; - - background = manager->background; - zero = Cudd_Not(manager->one); - - *digits = Cudd_ApaNumberOfDigits(nvars+1); - max = Cudd_NewApaNumber(*digits); - if (max == NULL) { - return(NULL); - } - Cudd_ApaPowerOfTwo(*digits,max,nvars); - min = Cudd_NewApaNumber(*digits); - if (min == NULL) { - FREE(max); - return(NULL); - } - Cudd_ApaSetToLiteral(*digits,min,0); - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) { - FREE(max); - FREE(min); - return(NULL); - } - i = cuddApaCountMintermAux(Cudd_Regular(node),*digits,max,min,table); - if (i == NULL) { - FREE(max); - FREE(min); - st_foreach(table, cuddApaStCountfree, NULL); - st_free_table(table); - return(NULL); - } - count = Cudd_NewApaNumber(*digits); - if (count == NULL) { - FREE(max); - FREE(min); - st_foreach(table, cuddApaStCountfree, NULL); - st_free_table(table); - if (Cudd_Regular(node)->ref == 1) FREE(i); - return(NULL); - } - if (Cudd_IsComplement(node)) { - (void) Cudd_ApaSubtract(*digits,max,i,count); - } else { - Cudd_ApaCopy(*digits,i,count); - } - FREE(max); - FREE(min); - st_foreach(table, cuddApaStCountfree, NULL); - st_free_table(table); - if (Cudd_Regular(node)->ref == 1) FREE(i); - return(count); - -} /* end of Cudd_ApaCountMinterm */ - - -/**Function******************************************************************** - - Synopsis [Prints the number of minterms of a BDD or ADD using - arbitrary precision arithmetic.] - - Description [Prints the number of minterms of a BDD or ADD using - arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ApaPrintMintermExp] - -******************************************************************************/ -int -Cudd_ApaPrintMinterm( - FILE * fp, - DdManager * dd, - DdNode * node, - int nvars) -{ - int digits; - int result; - DdApaNumber count; - - count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); - if (count == NULL) - return(0); - result = Cudd_ApaPrintDecimal(fp,digits,count); - FREE(count); - if (fprintf(fp,"\n") == EOF) { - return(0); - } - return(result); - -} /* end of Cudd_ApaPrintMinterm */ - - -/**Function******************************************************************** - - Synopsis [Prints the number of minterms of a BDD or ADD in exponential - format using arbitrary precision arithmetic.] - - Description [Prints the number of minterms of a BDD or ADD in - exponential format using arbitrary precision arithmetic. Parameter - precision controls the number of signficant digits printed. Returns - 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ApaPrintMinterm] - -******************************************************************************/ -int -Cudd_ApaPrintMintermExp( - FILE * fp, - DdManager * dd, - DdNode * node, - int nvars, - int precision) -{ - int digits; - int result; - DdApaNumber count; - - count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); - if (count == NULL) - return(0); - result = Cudd_ApaPrintExponential(fp,digits,count,precision); - FREE(count); - if (fprintf(fp,"\n") == EOF) { - return(0); - } - return(result); - -} /* end of Cudd_ApaPrintMintermExp */ - - -/**Function******************************************************************** - - Synopsis [Prints the density of a BDD or ADD using - arbitrary precision arithmetic.] - - Description [Prints the density of a BDD or ADD using - arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_ApaPrintDensity( - FILE * fp, - DdManager * dd, - DdNode * node, - int nvars) -{ - int digits; - int result; - DdApaNumber count,density; - unsigned int size, remainder, fractional; - - count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); - if (count == NULL) - return(0); - size = Cudd_DagSize(node); - density = Cudd_NewApaNumber(digits); - remainder = Cudd_ApaIntDivision(digits,count,size,density); - result = Cudd_ApaPrintDecimal(fp,digits,density); - FREE(count); - FREE(density); - fractional = (unsigned int)((double)remainder / size * 1000000); - if (fprintf(fp,".%u\n", fractional) == EOF) { - return(0); - } - return(result); - -} /* end of Cudd_ApaPrintDensity */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_ApaCountMinterm.] - - Description [Performs the recursive step of Cudd_ApaCountMinterm. - It is based on the following identity. Let |f| be the - number of minterms of f. Then: - <xmp> - |f| = (|f0|+|f1|)/2 - </xmp> - where f0 and f1 are the two cofactors of f. - Uses the identity <code>|f'| = max - |f|</code>. - The procedure expects the argument "node" to be a regular pointer, and - guarantees this condition is met in the recursive calls. - For efficiency, the result of a call is cached only if the node has - a reference count greater than 1. - Returns the number of minterms of the function rooted at node.] - - SideEffects [None] - -******************************************************************************/ -static DdApaNumber -cuddApaCountMintermAux( - DdNode * node, - int digits, - DdApaNumber max, - DdApaNumber min, - st_table * table) -{ - DdNode *Nt, *Ne; - DdApaNumber mint, mint1, mint2; - DdApaDigit carryout; - - if (cuddIsConstant(node)) { - if (node == background || node == zero) { - return(min); - } else { - return(max); - } - } - if (node->ref > 1 && st_lookup(table, (char *)node, (char **)&mint)) { - return(mint); - } - - Nt = cuddT(node); Ne = cuddE(node); - - mint1 = cuddApaCountMintermAux(Nt, digits, max, min, table); - if (mint1 == NULL) return(NULL); - mint2 = cuddApaCountMintermAux(Cudd_Regular(Ne), digits, max, min, table); - if (mint2 == NULL) { - if (Nt->ref == 1) FREE(mint1); - return(NULL); - } - mint = Cudd_NewApaNumber(digits); - if (mint == NULL) { - if (Nt->ref == 1) FREE(mint1); - if (Cudd_Regular(Ne)->ref == 1) FREE(mint2); - return(NULL); - } - if (Cudd_IsComplement(Ne)) { - (void) Cudd_ApaSubtract(digits,max,mint2,mint); - carryout = Cudd_ApaAdd(digits,mint1,mint,mint); - } else { - carryout = Cudd_ApaAdd(digits,mint1,mint2,mint); - } - Cudd_ApaShiftRight(digits,carryout,mint,mint); - /* If the refernce count of a child is 1, its minterm count - ** hasn't been stored in table. Therefore, it must be explicitly - ** freed here. */ - if (Nt->ref == 1) FREE(mint1); - if (Cudd_Regular(Ne)->ref == 1) FREE(mint2); - - if (node->ref > 1) { - if (st_insert(table, (char *)node, (char *)mint) == ST_OUT_OF_MEM) { - FREE(mint); - return(NULL); - } - } - return(mint); - -} /* end of cuddApaCountMintermAux */ - - -/**Function******************************************************************** - - Synopsis [Frees the memory used to store the minterm counts recorded - in the visited table.] - - Description [Frees the memory used to store the minterm counts - recorded in the visited table. Returns ST_CONTINUE.] - - SideEffects [None] - -******************************************************************************/ -static enum st_retval -cuddApaStCountfree( - char * key, - char * value, - char * arg) -{ - DdApaNumber d; - - d = (DdApaNumber) value; - FREE(d); - return(ST_CONTINUE); - -} /* end of cuddApaStCountfree */ - - diff --git a/src/bdd/cudd/cuddApprox.c b/src/bdd/cudd/cuddApprox.c deleted file mode 100644 index debcf48b..00000000 --- a/src/bdd/cudd/cuddApprox.c +++ /dev/null @@ -1,2192 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddApprox.c] - - PackageName [cudd] - - Synopsis [Procedures to approximate a given BDD.] - - Description [External procedures provided by this module: - <ul> - <li> Cudd_UnderApprox() - <li> Cudd_OverApprox() - <li> Cudd_RemapUnderApprox() - <li> Cudd_RemapOverApprox() - <li> Cudd_BiasedUnderApprox() - <li> Cudd_BiasedOverApprox() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddUnderApprox() - <li> cuddRemapUnderApprox() - <li> cuddBiasedUnderApprox() - </ul> - Static procedures included in this module: - <ul> - <li> gatherInfoAux() - <li> gatherInfo() - <li> computeSavings() - <li> UAmarkNodes() - <li> UAbuildSubset() - <li> updateRefs() - <li> RAmarkNodes() - <li> BAmarkNodes() - <li> RAbuildSubset() - </ul> - ] - - SeeAlso [cuddSubsetHB.c cuddSubsetSP.c cuddGenCof.c] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no - warranty about the suitability of this software for any - purpose. It is presented on an AS IS basis.] - -******************************************************************************/ - -#ifdef __STDC__ -#include <float.h> -#else -#define DBL_MAX_EXP 1024 -#endif -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define NOTHING 0 -#define REPLACE_T 1 -#define REPLACE_E 2 -#define REPLACE_N 3 -#define REPLACE_TT 4 -#define REPLACE_TE 5 - -#define DONT_CARE 0 -#define CARE 1 -#define TOTAL_CARE 2 -#define CARE_ERROR 3 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/* Data structure to store the information on each node. It keeps the -** number of minterms of the function rooted at this node in terms of -** the number of variables specified by the user; the number of -** minterms of the complement; the impact of the number of minterms of -** this function on the number of minterms of the root function; the -** reference count of the node from within the root function; the -** reference count of the node from an internal node; and the flag -** that says whether the node should be replaced and how. */ -typedef struct NodeData { - double mintermsP; /* minterms for the regular node */ - double mintermsN; /* minterms for the complemented node */ - int functionRef; /* references from within this function */ - char care; /* node intersects care set */ - char replace; /* replacement decision */ - short int parity; /* 1: even; 2: odd; 3: both */ - DdNode *resultP; /* result for even parity */ - DdNode *resultN; /* result for odd parity */ -} NodeData; - -typedef struct ApproxInfo { - DdNode *one; /* one constant */ - DdNode *zero; /* BDD zero constant */ - NodeData *page; /* per-node information */ - st_table *table; /* hash table to access the per-node info */ - int index; /* index of the current node */ - double max; /* max number of minterms */ - int size; /* how many nodes are left */ - double minterms; /* how many minterms are left */ -} ApproxInfo; - -/* Item of the queue used in the levelized traversal of the BDD. */ -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif -typedef struct GlobalQueueItem { - struct GlobalQueueItem *next; - struct GlobalQueueItem *cnext; - DdNode *node; - double impactP; - double impactN; -} GlobalQueueItem; - -typedef struct LocalQueueItem { - struct LocalQueueItem *next; - struct LocalQueueItem *cnext; - DdNode *node; - int localRef; -} LocalQueueItem; -#ifdef __osf__ -#pragma pointer_size restore -#endif - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddApprox.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void updateParity ARGS((DdNode *node, ApproxInfo *info, int newparity)); -static NodeData * gatherInfoAux ARGS((DdNode *node, ApproxInfo *info, int parity)); -static ApproxInfo * gatherInfo ARGS((DdManager *dd, DdNode *node, int numVars, int parity)); -static int computeSavings ARGS((DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue)); -static int updateRefs ARGS((DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue)); -static int UAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, int safe, double quality)); -static DdNode * UAbuildSubset ARGS((DdManager *dd, DdNode *node, ApproxInfo *info)); -static int RAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality)); -static int BAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality1, double quality0)); -static DdNode * RAbuildSubset ARGS((DdManager *dd, DdNode *node, ApproxInfo *info)); -static int BAapplyBias ARGS((DdManager *dd, DdNode *f, DdNode *b, ApproxInfo *info, DdHashTable *cache)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Extracts a dense subset from a BDD with Shiple's - underapproximation method.] - - Description [Extracts a dense subset from a BDD. This procedure uses - a variant of Tom Shiple's underapproximation method. The main - difference from the original method is that density is used as cost - function. Returns a pointer to the BDD of the subset if - successful. NULL if the procedure runs out of memory. The parameter - numVars is the maximum number of variables to be used in minterm - calculation. The optimal number should be as close as possible to - the size of the support of f. However, it is safe to pass the value - returned by Cudd_ReadSize for numVars when the number of variables - is under 1023. If numVars is larger than 1023, it will cause - overflow. If a 0 parameter is passed then the procedure will compute - a value which will avoid overflow but will cause underflow with 2046 - variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_UnderApprox( - DdManager * dd /* manager */, - DdNode * f /* function to be subset */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - int safe /* enforce safe approximation */, - double quality /* minimum improvement for accepted changes */) -{ - DdNode *subset; - - do { - dd->reordered = 0; - subset = cuddUnderApprox(dd, f, numVars, threshold, safe, quality); - } while (dd->reordered == 1); - - return(subset); - -} /* end of Cudd_UnderApprox */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense superset from a BDD with Shiple's - underapproximation method.] - - Description [Extracts a dense superset from a BDD. The procedure is - identical to the underapproximation procedure except for the fact that it - works on the complement of the given function. Extracting the subset - of the complement function is equivalent to extracting the superset - of the function. - Returns a pointer to the BDD of the superset if successful. NULL if - intermediate result causes the procedure to run out of memory. The - parameter numVars is the maximum number of variables to be used in - minterm calculation. The optimal number - should be as close as possible to the size of the support of f. - However, it is safe to pass the value returned by Cudd_ReadSize for - numVars when the number of variables is under 1023. If numVars is - larger than 1023, it will overflow. If a 0 parameter is passed then - the procedure will compute a value which will avoid overflow but - will cause underflow with 2046 variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_OverApprox( - DdManager * dd /* manager */, - DdNode * f /* function to be superset */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - int safe /* enforce safe approximation */, - double quality /* minimum improvement for accepted changes */) -{ - DdNode *subset, *g; - - g = Cudd_Not(f); - do { - dd->reordered = 0; - subset = cuddUnderApprox(dd, g, numVars, threshold, safe, quality); - } while (dd->reordered == 1); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_OverApprox */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense subset from a BDD with the remapping - underapproximation method.] - - Description [Extracts a dense subset from a BDD. This procedure uses - a remapping technique and density as the cost function. - Returns a pointer to the BDD of the subset if - successful. NULL if the procedure runs out of memory. The parameter - numVars is the maximum number of variables to be used in minterm - calculation. The optimal number should be as close as possible to - the size of the support of f. However, it is safe to pass the value - returned by Cudd_ReadSize for numVars when the number of variables - is under 1023. If numVars is larger than 1023, it will cause - overflow. If a 0 parameter is passed then the procedure will compute - a value which will avoid overflow but will cause underflow with 2046 - variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_RemapUnderApprox( - DdManager * dd /* manager */, - DdNode * f /* function to be subset */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - double quality /* minimum improvement for accepted changes */) -{ - DdNode *subset; - - do { - dd->reordered = 0; - subset = cuddRemapUnderApprox(dd, f, numVars, threshold, quality); - } while (dd->reordered == 1); - - return(subset); - -} /* end of Cudd_RemapUnderApprox */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense superset from a BDD with the remapping - underapproximation method.] - - Description [Extracts a dense superset from a BDD. The procedure is - identical to the underapproximation procedure except for the fact that it - works on the complement of the given function. Extracting the subset - of the complement function is equivalent to extracting the superset - of the function. - Returns a pointer to the BDD of the superset if successful. NULL if - intermediate result causes the procedure to run out of memory. The - parameter numVars is the maximum number of variables to be used in - minterm calculation. The optimal number - should be as close as possible to the size of the support of f. - However, it is safe to pass the value returned by Cudd_ReadSize for - numVars when the number of variables is under 1023. If numVars is - larger than 1023, it will overflow. If a 0 parameter is passed then - the procedure will compute a value which will avoid overflow but - will cause underflow with 2046 variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_RemapOverApprox( - DdManager * dd /* manager */, - DdNode * f /* function to be superset */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - double quality /* minimum improvement for accepted changes */) -{ - DdNode *subset, *g; - - g = Cudd_Not(f); - do { - dd->reordered = 0; - subset = cuddRemapUnderApprox(dd, g, numVars, threshold, quality); - } while (dd->reordered == 1); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_RemapOverApprox */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense subset from a BDD with the biased - underapproximation method.] - - Description [Extracts a dense subset from a BDD. This procedure uses - a biased remapping technique and density as the cost function. The bias - is a function. This procedure tries to approximate where the bias is 0 - and preserve the given function where the bias is 1. - Returns a pointer to the BDD of the subset if - successful. NULL if the procedure runs out of memory. The parameter - numVars is the maximum number of variables to be used in minterm - calculation. The optimal number should be as close as possible to - the size of the support of f. However, it is safe to pass the value - returned by Cudd_ReadSize for numVars when the number of variables - is under 1023. If numVars is larger than 1023, it will cause - overflow. If a 0 parameter is passed then the procedure will compute - a value which will avoid overflow but will cause underflow with 2046 - variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox - Cudd_RemapUnderApprox Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_BiasedUnderApprox( - DdManager *dd /* manager */, - DdNode *f /* function to be subset */, - DdNode *b /* bias function */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - double quality1 /* minimum improvement for accepted changes when b=1 */, - double quality0 /* minimum improvement for accepted changes when b=0 */) -{ - DdNode *subset; - - do { - dd->reordered = 0; - subset = cuddBiasedUnderApprox(dd, f, b, numVars, threshold, quality1, - quality0); - } while (dd->reordered == 1); - - return(subset); - -} /* end of Cudd_BiasedUnderApprox */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense superset from a BDD with the biased - underapproximation method.] - - Description [Extracts a dense superset from a BDD. The procedure is - identical to the underapproximation procedure except for the fact that it - works on the complement of the given function. Extracting the subset - of the complement function is equivalent to extracting the superset - of the function. - Returns a pointer to the BDD of the superset if successful. NULL if - intermediate result causes the procedure to run out of memory. The - parameter numVars is the maximum number of variables to be used in - minterm calculation. The optimal number - should be as close as possible to the size of the support of f. - However, it is safe to pass the value returned by Cudd_ReadSize for - numVars when the number of variables is under 1023. If numVars is - larger than 1023, it will overflow. If a 0 parameter is passed then - the procedure will compute a value which will avoid overflow but - will cause underflow with 2046 variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths - Cudd_RemapOverApprox Cudd_BiasedUnderApprox Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_BiasedOverApprox( - DdManager *dd /* manager */, - DdNode *f /* function to be superset */, - DdNode *b /* bias function */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - double quality1 /* minimum improvement for accepted changes when b=1*/, - double quality0 /* minimum improvement for accepted changes when b=0 */) -{ - DdNode *subset, *g; - - g = Cudd_Not(f); - do { - dd->reordered = 0; - subset = cuddBiasedUnderApprox(dd, g, b, numVars, threshold, quality1, - quality0); - } while (dd->reordered == 1); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_BiasedOverApprox */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Applies Tom Shiple's underappoximation algorithm.] - - Description [Applies Tom Shiple's underappoximation algorithm. Proceeds - in three phases: - <ul> - <li> collect information on each node in the BDD; this is done via DFS. - <li> traverse the BDD in top-down fashion and compute for each node - whether its elimination increases density. - <li> traverse the BDD via DFS and actually perform the elimination. - </ul> - Returns the approximated BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_UnderApprox] - -******************************************************************************/ -DdNode * -cuddUnderApprox( - DdManager * dd /* DD manager */, - DdNode * f /* current DD */, - int numVars /* maximum number of variables */, - int threshold /* threshold under which approximation stops */, - int safe /* enforce safe approximation */, - double quality /* minimum improvement for accepted changes */) -{ - ApproxInfo *info; - DdNode *subset; - int result; - - if (f == NULL) { - fprintf(dd->err, "Cannot subset, nil object\n"); - return(NULL); - } - - if (Cudd_IsConstant(f)) { - return(f); - } - - /* Create table where node data are accessible via a hash table. */ - info = gatherInfo(dd, f, numVars, safe); - if (info == NULL) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - /* Mark nodes that should be replaced by zero. */ - result = UAmarkNodes(dd, f, info, threshold, safe, quality); - if (result == 0) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - FREE(info->page); - st_free_table(info->table); - FREE(info); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - /* Build the result. */ - subset = UAbuildSubset(dd, f, info); -#if 1 - if (subset && info->size < Cudd_DagSize(subset)) - (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", - info->size, Cudd_DagSize(subset)); -#endif - FREE(info->page); - st_free_table(info->table); - FREE(info); - -#ifdef DD_DEBUG - if (subset != NULL) { - cuddRef(subset); -#if 0 - (void) Cudd_DebugCheck(dd); - (void) Cudd_CheckKeys(dd); -#endif - if (!Cudd_bddLeq(dd, subset, f)) { - (void) fprintf(dd->err, "Wrong subset\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - } - cuddDeref(subset); - } -#endif - return(subset); - -} /* end of cuddUnderApprox */ - - -/**Function******************************************************************** - - Synopsis [Applies the remapping underappoximation algorithm.] - - Description [Applies the remapping underappoximation algorithm. - Proceeds in three phases: - <ul> - <li> collect information on each node in the BDD; this is done via DFS. - <li> traverse the BDD in top-down fashion and compute for each node - whether remapping increases density. - <li> traverse the BDD via DFS and actually perform the elimination. - </ul> - Returns the approximated BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_RemapUnderApprox] - -******************************************************************************/ -DdNode * -cuddRemapUnderApprox( - DdManager * dd /* DD manager */, - DdNode * f /* current DD */, - int numVars /* maximum number of variables */, - int threshold /* threshold under which approximation stops */, - double quality /* minimum improvement for accepted changes */) -{ - ApproxInfo *info; - DdNode *subset; - int result; - - if (f == NULL) { - fprintf(dd->err, "Cannot subset, nil object\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - if (Cudd_IsConstant(f)) { - return(f); - } - - /* Create table where node data are accessible via a hash table. */ - info = gatherInfo(dd, f, numVars, TRUE); - if (info == NULL) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - /* Mark nodes that should be replaced by zero. */ - result = RAmarkNodes(dd, f, info, threshold, quality); - if (result == 0) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - FREE(info->page); - st_free_table(info->table); - FREE(info); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - /* Build the result. */ - subset = RAbuildSubset(dd, f, info); -#if 1 - if (subset && info->size < Cudd_DagSize(subset)) - (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", - info->size, Cudd_DagSize(subset)); -#endif - FREE(info->page); - st_free_table(info->table); - FREE(info); - -#ifdef DD_DEBUG - if (subset != NULL) { - cuddRef(subset); -#if 0 - (void) Cudd_DebugCheck(dd); - (void) Cudd_CheckKeys(dd); -#endif - if (!Cudd_bddLeq(dd, subset, f)) { - (void) fprintf(dd->err, "Wrong subset\n"); - } - cuddDeref(subset); - dd->errorCode = CUDD_INTERNAL_ERROR; - } -#endif - return(subset); - -} /* end of cuddRemapUnderApprox */ - - -/**Function******************************************************************** - - Synopsis [Applies the biased remapping underappoximation algorithm.] - - Description [Applies the biased remapping underappoximation algorithm. - Proceeds in three phases: - <ul> - <li> collect information on each node in the BDD; this is done via DFS. - <li> traverse the BDD in top-down fashion and compute for each node - whether remapping increases density. - <li> traverse the BDD via DFS and actually perform the elimination. - </ul> - Returns the approximated BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_BiasedUnderApprox] - -******************************************************************************/ -DdNode * -cuddBiasedUnderApprox( - DdManager *dd /* DD manager */, - DdNode *f /* current DD */, - DdNode *b /* bias function */, - int numVars /* maximum number of variables */, - int threshold /* threshold under which approximation stops */, - double quality1 /* minimum improvement for accepted changes when b=1 */, - double quality0 /* minimum improvement for accepted changes when b=1 */) -{ - ApproxInfo *info; - DdNode *subset; - int result; - DdHashTable *cache; - - if (f == NULL) { - fprintf(dd->err, "Cannot subset, nil object\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - if (Cudd_IsConstant(f)) { - return(f); - } - - /* Create table where node data are accessible via a hash table. */ - info = gatherInfo(dd, f, numVars, TRUE); - if (info == NULL) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - cache = cuddHashTableInit(dd,2,2); - result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache); - if (result == CARE_ERROR) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - cuddHashTableQuit(cache); - FREE(info->page); - st_free_table(info->table); - FREE(info); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - cuddHashTableQuit(cache); - - /* Mark nodes that should be replaced by zero. */ - result = BAmarkNodes(dd, f, info, threshold, quality1, quality0); - if (result == 0) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - FREE(info->page); - st_free_table(info->table); - FREE(info); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - /* Build the result. */ - subset = RAbuildSubset(dd, f, info); -#if 1 - if (subset && info->size < Cudd_DagSize(subset)) - (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", - info->size, Cudd_DagSize(subset)); -#endif - FREE(info->page); - st_free_table(info->table); - FREE(info); - -#ifdef DD_DEBUG - if (subset != NULL) { - cuddRef(subset); -#if 0 - (void) Cudd_DebugCheck(dd); - (void) Cudd_CheckKeys(dd); -#endif - if (!Cudd_bddLeq(dd, subset, f)) { - (void) fprintf(dd->err, "Wrong subset\n"); - } - cuddDeref(subset); - dd->errorCode = CUDD_INTERNAL_ERROR; - } -#endif - return(subset); - -} /* end of cuddBiasedUnderApprox */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Recursively update the parity of the paths reaching a node.] - - Description [Recursively update the parity of the paths reaching a node. - Assumes that node is regular and propagates the invariant.] - - SideEffects [None] - - SeeAlso [gatherInfoAux] - -******************************************************************************/ -static void -updateParity( - DdNode * node /* function to analyze */, - ApproxInfo * info /* info on BDD */, - int newparity /* new parity for node */) -{ - NodeData *infoN; - DdNode *E; - - if (!st_lookup(info->table, (char *)node, (char **)&infoN)) return; - if ((infoN->parity & newparity) != 0) return; - infoN->parity |= newparity; - if (Cudd_IsConstant(node)) return; - updateParity(cuddT(node),info,newparity); - E = cuddE(node); - if (Cudd_IsComplement(E)) { - updateParity(Cudd_Not(E),info,3-newparity); - } else { - updateParity(E,info,newparity); - } - return; - -} /* end of updateParity */ - - -/**Function******************************************************************** - - Synopsis [Recursively counts minterms and computes reference counts - of each node in the BDD.] - - Description [Recursively counts minterms and computes reference - counts of each node in the BDD. Similar to the cuddCountMintermAux - which recursively counts the number of minterms for the dag rooted - at each node in terms of the total number of variables (max). It assumes - that the node pointer passed to it is regular and it maintains the - invariant.] - - SideEffects [None] - - SeeAlso [gatherInfo] - -******************************************************************************/ -static NodeData * -gatherInfoAux( - DdNode * node /* function to analyze */, - ApproxInfo * info /* info on BDD */, - int parity /* gather parity information */) -{ - DdNode *N, *Nt, *Ne; - NodeData *infoN, *infoT, *infoE; - - N = Cudd_Regular(node); - - /* Check whether entry for this node exists. */ - if (st_lookup(info->table, (char *)N, (char **)&infoN)) { - if (parity) { - /* Update parity and propagate. */ - updateParity(N, info, 1 + (int) Cudd_IsComplement(node)); - } - return(infoN); - } - - /* Compute the cofactors. */ - Nt = Cudd_NotCond(cuddT(N), N != node); - Ne = Cudd_NotCond(cuddE(N), N != node); - - infoT = gatherInfoAux(Nt, info, parity); - if (infoT == NULL) return(NULL); - infoE = gatherInfoAux(Ne, info, parity); - if (infoE == NULL) return(NULL); - - infoT->functionRef++; - infoE->functionRef++; - - /* Point to the correct location in the page. */ - infoN = &(info->page[info->index++]); - infoN->parity |= 1 + (short) Cudd_IsComplement(node); - - infoN->mintermsP = infoT->mintermsP/2; - infoN->mintermsN = infoT->mintermsN/2; - if (Cudd_IsComplement(Ne) ^ Cudd_IsComplement(node)) { - infoN->mintermsP += infoE->mintermsN/2; - infoN->mintermsN += infoE->mintermsP/2; - } else { - infoN->mintermsP += infoE->mintermsP/2; - infoN->mintermsN += infoE->mintermsN/2; - } - - /* Insert entry for the node in the table. */ - if (st_insert(info->table,(char *)N, (char *)infoN) == ST_OUT_OF_MEM) { - return(NULL); - } - return(infoN); - -} /* end of gatherInfoAux */ - - -/**Function******************************************************************** - - Synopsis [Gathers information about each node.] - - Description [Counts minterms and computes reference counts of each - node in the BDD . The minterm count is separately computed for the - node and its complement. This is to avoid cancellation - errors. Returns a pointer to the data structure holding the - information gathered if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddUnderApprox gatherInfoAux] - -******************************************************************************/ -static ApproxInfo * -gatherInfo( - DdManager * dd /* manager */, - DdNode * node /* function to be analyzed */, - int numVars /* number of variables node depends on */, - int parity /* gather parity information */) -{ - ApproxInfo *info; - NodeData *infoTop; - - /* If user did not give numVars value, set it to the maximum - ** exponent that the pow function can take. The -1 is due to the - ** discrepancy in the value that pow takes and the value that - ** log gives. - */ - if (numVars == 0) { - numVars = DBL_MAX_EXP - 1; - } - - info = ALLOC(ApproxInfo,1); - if (info == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - info->max = pow(2.0,(double) numVars); - info->one = DD_ONE(dd); - info->zero = Cudd_Not(info->one); - info->size = Cudd_DagSize(node); - /* All the information gathered will be stored in a contiguous - ** piece of memory, which is allocated here. This can be done - ** efficiently because we have counted the number of nodes of the - ** BDD. info->index points to the next available entry in the array - ** that stores the per-node information. */ - info->page = ALLOC(NodeData,info->size); - if (info->page == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(info); - return(NULL); - } - memset(info->page, 0, info->size * sizeof(NodeData)); /* clear all page */ - info->table = st_init_table(st_ptrcmp,st_ptrhash); - if (info->table == NULL) { - FREE(info->page); - FREE(info); - return(NULL); - } - /* We visit the DAG in post-order DFS. Hence, the constant node is - ** in first position, and the root of the DAG is in last position. */ - - /* Info for the constant node: Initialize only fields different from 0. */ - if (st_insert(info->table, (char *)info->one, (char *)info->page) == ST_OUT_OF_MEM) { - FREE(info->page); - FREE(info); - st_free_table(info->table); - return(NULL); - } - info->page[0].mintermsP = info->max; - info->index = 1; - - infoTop = gatherInfoAux(node,info,parity); - if (infoTop == NULL) { - FREE(info->page); - st_free_table(info->table); - FREE(info); - return(NULL); - } - if (Cudd_IsComplement(node)) { - info->minterms = infoTop->mintermsN; - } else { - info->minterms = infoTop->mintermsP; - } - - infoTop->functionRef = 1; - return(info); - -} /* end of gatherInfo */ - - -/**Function******************************************************************** - - Synopsis [Counts the nodes that would be eliminated if a given node - were replaced by zero.] - - Description [Counts the nodes that would be eliminated if a given - node were replaced by zero. This procedure uses a queue passed by - the caller for efficiency: since the queue is left empty at the - endof the search, it can be reused as is by the next search. Returns - the count (always striclty positive) if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddUnderApprox] - -******************************************************************************/ -static int -computeSavings( - DdManager * dd, - DdNode * f, - DdNode * skip, - ApproxInfo * info, - DdLevelQueue * queue) -{ - NodeData *infoN; - LocalQueueItem *item; - DdNode *node; - int savings = 0; - - node = Cudd_Regular(f); - skip = Cudd_Regular(skip); - /* Insert the given node in the level queue. Its local reference - ** count is set equal to the function reference count so that the - ** search will continue from it when it is retrieved. */ - item = (LocalQueueItem *) - cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); - if (item == NULL) - return(0); - (void) st_lookup(info->table, (char *)node, (char **)&infoN); - item->localRef = infoN->functionRef; - - /* Process the queue. */ - while (queue->first != NULL) { - item = (LocalQueueItem *) queue->first; - node = item->node; - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); - if (node == skip) continue; - (void) st_lookup(info->table, (char *)node, (char **)&infoN); - if (item->localRef != infoN->functionRef) { - /* This node is shared. */ - continue; - } - savings++; - if (!cuddIsConstant(cuddT(node))) { - item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), - cuddI(dd,cuddT(node)->index)); - if (item == NULL) return(0); - item->localRef++; - } - if (!Cudd_IsConstant(cuddE(node))) { - item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), - cuddI(dd,Cudd_Regular(cuddE(node))->index)); - if (item == NULL) return(0); - item->localRef++; - } - } - -#ifdef DD_DEBUG - /* At the end of a local search the queue should be empty. */ - assert(queue->size == 0); -#endif - return(savings); - -} /* end of computeSavings */ - - -/**Function******************************************************************** - - Synopsis [Update function reference counts.] - - Description [Update function reference counts to account for replacement. - Returns the number of nodes saved if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [UAmarkNodes RAmarkNodes] - -******************************************************************************/ -static int -updateRefs( - DdManager * dd, - DdNode * f, - DdNode * skip, - ApproxInfo * info, - DdLevelQueue * queue) -{ - NodeData *infoN; - LocalQueueItem *item; - DdNode *node; - int savings = 0; - - node = Cudd_Regular(f); - /* Insert the given node in the level queue. Its function reference - ** count is set equal to 0 so that the search will continue from it - ** when it is retrieved. */ - item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); - if (item == NULL) - return(0); - (void) st_lookup(info->table, (char *)node, (char **)&infoN); - infoN->functionRef = 0; - - if (skip != NULL) { - /* Increase the function reference count of the node to be skipped - ** by 1 to account for the node pointing to it that will be created. */ - skip = Cudd_Regular(skip); - (void) st_lookup(info->table, (char *)skip, (char **)&infoN); - infoN->functionRef++; - } - - /* Process the queue. */ - while (queue->first != NULL) { - item = (LocalQueueItem *) queue->first; - node = item->node; - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); - (void) st_lookup(info->table, (char *)node, (char **)&infoN); - if (infoN->functionRef != 0) { - /* This node is shared or must be skipped. */ - continue; - } - savings++; - if (!cuddIsConstant(cuddT(node))) { - item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), - cuddI(dd,cuddT(node)->index)); - if (item == NULL) return(0); - (void) st_lookup(info->table, (char *)cuddT(node), - (char **)&infoN); - infoN->functionRef--; - } - if (!Cudd_IsConstant(cuddE(node))) { - item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), - cuddI(dd,Cudd_Regular(cuddE(node))->index)); - if (item == NULL) return(0); - (void) st_lookup(info->table, (char *)Cudd_Regular(cuddE(node)), - (char **)&infoN); - infoN->functionRef--; - } - } - -#ifdef DD_DEBUG - /* At the end of a local search the queue should be empty. */ - assert(queue->size == 0); -#endif - return(savings); - -} /* end of updateRefs */ - - -/**Function******************************************************************** - - Synopsis [Marks nodes for replacement by zero.] - - Description [Marks nodes for replacement by zero. Returns 1 if successful; - 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddUnderApprox] - -******************************************************************************/ -static int -UAmarkNodes( - DdManager * dd /* manager */, - DdNode * f /* function to be analyzed */, - ApproxInfo * info /* info on BDD */, - int threshold /* when to stop approximating */, - int safe /* enforce safe approximation */, - double quality /* minimum improvement for accepted changes */) -{ - DdLevelQueue *queue; - DdLevelQueue *localQueue; - NodeData *infoN; - GlobalQueueItem *item; - DdNode *node; - double numOnset; - double impactP, impactN; - int savings; - -#if 0 - (void) printf("initial size = %d initial minterms = %g\n", - info->size, info->minterms); -#endif - queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); - if (queue == NULL) { - return(0); - } - localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), - dd->initSlots); - if (localQueue == NULL) { - cuddLevelQueueQuit(queue); - return(0); - } - node = Cudd_Regular(f); - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); - if (item == NULL) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - if (Cudd_IsComplement(f)) { - item->impactP = 0.0; - item->impactN = 1.0; - } else { - item->impactP = 1.0; - item->impactN = 0.0; - } - while (queue->first != NULL) { - /* If the size of the subset is below the threshold, quit. */ - if (info->size <= threshold) - break; - item = (GlobalQueueItem *) queue->first; - node = item->node; - node = Cudd_Regular(node); - (void) st_lookup(info->table, (char *)node, (char **)&infoN); - if (safe && infoN->parity == 3) { - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); - continue; - } - impactP = item->impactP; - impactN = item->impactN; - numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; - savings = computeSavings(dd,node,NULL,info,localQueue); - if (savings == 0) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); -#if 0 - (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", - node, impactP, impactN, numOnset, savings); -#endif - if ((1 - numOnset / info->minterms) > - quality * (1 - (double) savings / info->size)) { - infoN->replace = TRUE; - info->size -= savings; - info->minterms -=numOnset; -#if 0 - (void) printf("replace: new size = %d new minterms = %g\n", - info->size, info->minterms); -#endif - savings -= updateRefs(dd,node,NULL,info,localQueue); - assert(savings == 0); - continue; - } - if (!cuddIsConstant(cuddT(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), - cuddI(dd,cuddT(node)->index)); - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - if (!Cudd_IsConstant(cuddE(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), - cuddI(dd,Cudd_Regular(cuddE(node))->index)); - if (Cudd_IsComplement(cuddE(node))) { - item->impactP += impactN/2.0; - item->impactN += impactP/2.0; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - } - - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(1); - -} /* end of UAmarkNodes */ - - -/**Function******************************************************************** - - Synopsis [Builds the subset BDD.] - - Description [Builds the subset BDD. Based on the info table, - replaces selected nodes by zero. Returns a pointer to the result if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddUnderApprox] - -******************************************************************************/ -static DdNode * -UAbuildSubset( - DdManager * dd /* DD manager */, - DdNode * node /* current node */, - ApproxInfo * info /* node info */) -{ - - DdNode *Nt, *Ne, *N, *t, *e, *r; - NodeData *infoN; - - if (Cudd_IsConstant(node)) - return(node); - - N = Cudd_Regular(node); - - if (st_lookup(info->table, (char *)N, (char **)&infoN)) { - if (infoN->replace == TRUE) { - return(info->zero); - } - if (N == node ) { - if (infoN->resultP != NULL) { - return(infoN->resultP); - } - } else { - if (infoN->resultN != NULL) { - return(infoN->resultN); - } - } - } else { - (void) fprintf(dd->err, - "Something is wrong, ought to be in info table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - - Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node)); - Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node)); - - t = UAbuildSubset(dd, Nt, info); - if (t == NULL) { - return(NULL); - } - cuddRef(t); - - e = UAbuildSubset(dd, Ne, info); - if (e == NULL) { - Cudd_RecursiveDeref(dd,t); - return(NULL); - } - cuddRef(e); - - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - - if (N == node) { - infoN->resultP = r; - } else { - infoN->resultN = r; - } - - return(r); - -} /* end of UAbuildSubset */ - - -/**Function******************************************************************** - - Synopsis [Marks nodes for remapping.] - - Description [Marks nodes for remapping. Returns 1 if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddRemapUnderApprox] - -******************************************************************************/ -static int -RAmarkNodes( - DdManager * dd /* manager */, - DdNode * f /* function to be analyzed */, - ApproxInfo * info /* info on BDD */, - int threshold /* when to stop approximating */, - double quality /* minimum improvement for accepted changes */) -{ - DdLevelQueue *queue; - DdLevelQueue *localQueue; - NodeData *infoN, *infoT, *infoE; - GlobalQueueItem *item; - DdNode *node, *T, *E; - DdNode *shared; /* grandchild shared by the two children of node */ - double numOnset; - double impact, impactP, impactN; - double minterms; - int savings; - int replace; - -#if 0 - (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n", - info->size, info->minterms); -#endif - queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); - if (queue == NULL) { - return(0); - } - localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), - dd->initSlots); - if (localQueue == NULL) { - cuddLevelQueueQuit(queue); - return(0); - } - /* Enqueue regular pointer to root and initialize impact. */ - node = Cudd_Regular(f); - item = (GlobalQueueItem *) - cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); - if (item == NULL) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - if (Cudd_IsComplement(f)) { - item->impactP = 0.0; - item->impactN = 1.0; - } else { - item->impactP = 1.0; - item->impactN = 0.0; - } - /* The nodes retrieved here are guaranteed to be non-terminal. - ** The initial node is not terminal because constant nodes are - ** dealt with in the calling procedure. Subsequent nodes are inserted - ** only if they are not terminal. */ - while (queue->first != NULL) { - /* If the size of the subset is below the threshold, quit. */ - if (info->size <= threshold) - break; - item = (GlobalQueueItem *) queue->first; - node = item->node; -#ifdef DD_DEBUG - assert(item->impactP >= 0 && item->impactP <= 1.0); - assert(item->impactN >= 0 && item->impactN <= 1.0); - assert(!Cudd_IsComplement(node)); - assert(!Cudd_IsConstant(node)); -#endif - if (!st_lookup(info->table, (char *)node, (char **)&infoN)) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } -#ifdef DD_DEBUG - assert(infoN->parity >= 1 && infoN->parity <= 3); -#endif - if (infoN->parity == 3) { - /* This node can be reached through paths of different parity. - ** It is not safe to replace it, because remapping will give - ** an incorrect result, while replacement by 0 may cause node - ** splitting. */ - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); - continue; - } - T = cuddT(node); - E = cuddE(node); - shared = NULL; - impactP = item->impactP; - impactN = item->impactN; - if (Cudd_bddLeq(dd,T,E)) { - /* Here we know that E is regular. */ -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(E)); -#endif - (void) st_lookup(info->table, (char *)T, (char **)&infoT); - (void) st_lookup(info->table, (char *)E, (char **)&infoE); - if (infoN->parity == 1) { - impact = impactP; - minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0; - if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { - savings = 1 + computeSavings(dd,E,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_E; - } else { -#ifdef DD_DEBUG - assert(infoN->parity == 2); -#endif - impact = impactN; - minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0; - if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { - savings = 1 + computeSavings(dd,T,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_T; - } - numOnset = impact * minterms; - } else if (Cudd_bddLeq(dd,E,T)) { - /* Here E may be complemented. */ - DdNode *Ereg = Cudd_Regular(E); - (void) st_lookup(info->table, (char *)T, (char **)&infoT); - (void) st_lookup(info->table, (char *)Ereg, (char **)&infoE); - if (infoN->parity == 1) { - impact = impactP; - minterms = infoT->mintermsP/2.0 - - ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0; - if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { - savings = 1 + computeSavings(dd,T,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_T; - } else { -#ifdef DD_DEBUG - assert(infoN->parity == 2); -#endif - impact = impactN; - minterms = ((E == Ereg) ? infoE->mintermsN : - infoE->mintermsP)/2.0 - infoT->mintermsN/2.0; - if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { - savings = 1 + computeSavings(dd,E,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_E; - } - numOnset = impact * minterms; - } else { - DdNode *Ereg = Cudd_Regular(E); - DdNode *TT = cuddT(T); - DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E)); - if (T->index == Ereg->index && TT == ET) { - shared = TT; - replace = REPLACE_TT; - } else { - DdNode *TE = cuddE(T); - DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E)); - if (T->index == Ereg->index && TE == EE) { - shared = TE; - replace = REPLACE_TE; - } else { - replace = REPLACE_N; - } - } - numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; - savings = computeSavings(dd,node,shared,info,localQueue); - if (shared != NULL) { - NodeData *infoS; - (void) st_lookup(info->table, (char *)Cudd_Regular(shared), - (char **)&infoS); - if (Cudd_IsComplement(shared)) { - numOnset -= (infoS->mintermsN * impactP + - infoS->mintermsP * impactN)/2.0; - } else { - numOnset -= (infoS->mintermsP * impactP + - infoS->mintermsN * impactN)/2.0; - } - savings--; - } - } - - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); -#if 0 - if (replace == REPLACE_T || replace == REPLACE_E) - (void) printf("node %p: impact = %g numOnset = %g savings %d\n", - node, impact, numOnset, savings); - else - (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", - node, impactP, impactN, numOnset, savings); -#endif - if ((1 - numOnset / info->minterms) > - quality * (1 - (double) savings / info->size)) { - infoN->replace = replace; - info->size -= savings; - info->minterms -=numOnset; -#if 0 - (void) printf("remap(%d): new size = %d new minterms = %g\n", - replace, info->size, info->minterms); -#endif - if (replace == REPLACE_N) { - savings -= updateRefs(dd,node,NULL,info,localQueue); - } else if (replace == REPLACE_T) { - savings -= updateRefs(dd,node,E,info,localQueue); - } else if (replace == REPLACE_E) { - savings -= updateRefs(dd,node,T,info,localQueue); - } else { -#ifdef DD_DEBUG - assert(replace == REPLACE_TT || replace == REPLACE_TE); -#endif - savings -= updateRefs(dd,node,shared,info,localQueue) - 1; - } - assert(savings == 0); - } else { - replace = NOTHING; - } - if (replace == REPLACE_N) continue; - if ((replace == REPLACE_E || replace == NOTHING) && - !cuddIsConstant(cuddT(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), - cuddI(dd,cuddT(node)->index)); - if (replace == REPLACE_E) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - if ((replace == REPLACE_T || replace == NOTHING) && - !Cudd_IsConstant(cuddE(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), - cuddI(dd,Cudd_Regular(cuddE(node))->index)); - if (Cudd_IsComplement(cuddE(node))) { - if (replace == REPLACE_T) { - item->impactP += impactN; - item->impactN += impactP; - } else { - item->impactP += impactN/2.0; - item->impactN += impactP/2.0; - } - } else { - if (replace == REPLACE_T) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - } - if ((replace == REPLACE_TT || replace == REPLACE_TE) && - !Cudd_IsConstant(shared)) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared), - cuddI(dd,Cudd_Regular(shared)->index)); - if (Cudd_IsComplement(shared)) { - if (replace == REPLACE_T) { - item->impactP += impactN; - item->impactN += impactP; - } else { - item->impactP += impactN/2.0; - item->impactN += impactP/2.0; - } - } else { - if (replace == REPLACE_T) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - } - } - - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(1); - -} /* end of RAmarkNodes */ - - -/**Function******************************************************************** - - Synopsis [Marks nodes for remapping.] - - Description [Marks nodes for remapping. Returns 1 if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddRemapUnderApprox] - -******************************************************************************/ -static int -BAmarkNodes( - DdManager *dd /* manager */, - DdNode *f /* function to be analyzed */, - ApproxInfo *info /* info on BDD */, - int threshold /* when to stop approximating */, - double quality1 /* minimum improvement for accepted changes when b=1 */, - double quality0 /* minimum improvement for accepted changes when b=0 */) -{ - DdLevelQueue *queue; - DdLevelQueue *localQueue; - NodeData *infoN, *infoT, *infoE; - GlobalQueueItem *item; - DdNode *node, *T, *E; - DdNode *shared; /* grandchild shared by the two children of node */ - double numOnset; - double impact, impactP, impactN; - double minterms; - double quality; - int savings; - int replace; - -#if 0 - (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n", - info->size, info->minterms); -#endif - queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); - if (queue == NULL) { - return(0); - } - localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), - dd->initSlots); - if (localQueue == NULL) { - cuddLevelQueueQuit(queue); - return(0); - } - /* Enqueue regular pointer to root and initialize impact. */ - node = Cudd_Regular(f); - item = (GlobalQueueItem *) - cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); - if (item == NULL) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - if (Cudd_IsComplement(f)) { - item->impactP = 0.0; - item->impactN = 1.0; - } else { - item->impactP = 1.0; - item->impactN = 0.0; - } - /* The nodes retrieved here are guaranteed to be non-terminal. - ** The initial node is not terminal because constant nodes are - ** dealt with in the calling procedure. Subsequent nodes are inserted - ** only if they are not terminal. */ - while (queue->first != NULL) { - /* If the size of the subset is below the threshold, quit. */ - if (info->size <= threshold) - break; - item = (GlobalQueueItem *) queue->first; - node = item->node; -#ifdef DD_DEBUG - assert(item->impactP >= 0 && item->impactP <= 1.0); - assert(item->impactN >= 0 && item->impactN <= 1.0); - assert(!Cudd_IsComplement(node)); - assert(!Cudd_IsConstant(node)); -#endif - if (!st_lookup(info->table, (char *)node, (char **)&infoN)) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - quality = infoN->care ? quality1 : quality0; -#ifdef DD_DEBUG - assert(infoN->parity >= 1 && infoN->parity <= 3); -#endif - if (infoN->parity == 3) { - /* This node can be reached through paths of different parity. - ** It is not safe to replace it, because remapping will give - ** an incorrect result, while replacement by 0 may cause node - ** splitting. */ - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); - continue; - } - T = cuddT(node); - E = cuddE(node); - shared = NULL; - impactP = item->impactP; - impactN = item->impactN; - if (Cudd_bddLeq(dd,T,E)) { - /* Here we know that E is regular. */ -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(E)); -#endif - (void) st_lookup(info->table, (char *)T, (char **)&infoT); - (void) st_lookup(info->table, (char *)E, (char **)&infoE); - if (infoN->parity == 1) { - impact = impactP; - minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0; - if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { - savings = 1 + computeSavings(dd,E,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_E; - } else { -#ifdef DD_DEBUG - assert(infoN->parity == 2); -#endif - impact = impactN; - minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0; - if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { - savings = 1 + computeSavings(dd,T,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_T; - } - numOnset = impact * minterms; - } else if (Cudd_bddLeq(dd,E,T)) { - /* Here E may be complemented. */ - DdNode *Ereg = Cudd_Regular(E); - (void) st_lookup(info->table, (char *)T, (char **)&infoT); - (void) st_lookup(info->table, (char *)Ereg, (char **)&infoE); - if (infoN->parity == 1) { - impact = impactP; - minterms = infoT->mintermsP/2.0 - - ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0; - if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { - savings = 1 + computeSavings(dd,T,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_T; - } else { -#ifdef DD_DEBUG - assert(infoN->parity == 2); -#endif - impact = impactN; - minterms = ((E == Ereg) ? infoE->mintermsN : - infoE->mintermsP)/2.0 - infoT->mintermsN/2.0; - if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { - savings = 1 + computeSavings(dd,E,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_E; - } - numOnset = impact * minterms; - } else { - DdNode *Ereg = Cudd_Regular(E); - DdNode *TT = cuddT(T); - DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E)); - if (T->index == Ereg->index && TT == ET) { - shared = TT; - replace = REPLACE_TT; - } else { - DdNode *TE = cuddE(T); - DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E)); - if (T->index == Ereg->index && TE == EE) { - shared = TE; - replace = REPLACE_TE; - } else { - replace = REPLACE_N; - } - } - numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; - savings = computeSavings(dd,node,shared,info,localQueue); - if (shared != NULL) { - NodeData *infoS; - (void) st_lookup(info->table, (char *)Cudd_Regular(shared), - (char **)&infoS); - if (Cudd_IsComplement(shared)) { - numOnset -= (infoS->mintermsN * impactP + - infoS->mintermsP * impactN)/2.0; - } else { - numOnset -= (infoS->mintermsP * impactP + - infoS->mintermsN * impactN)/2.0; - } - savings--; - } - } - - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); -#if 0 - if (replace == REPLACE_T || replace == REPLACE_E) - (void) printf("node %p: impact = %g numOnset = %g savings %d\n", - node, impact, numOnset, savings); - else - (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", - node, impactP, impactN, numOnset, savings); -#endif - if ((1 - numOnset / info->minterms) > - quality * (1 - (double) savings / info->size)) { - infoN->replace = replace; - info->size -= savings; - info->minterms -=numOnset; -#if 0 - (void) printf("remap(%d): new size = %d new minterms = %g\n", - replace, info->size, info->minterms); -#endif - if (replace == REPLACE_N) { - savings -= updateRefs(dd,node,NULL,info,localQueue); - } else if (replace == REPLACE_T) { - savings -= updateRefs(dd,node,E,info,localQueue); - } else if (replace == REPLACE_E) { - savings -= updateRefs(dd,node,T,info,localQueue); - } else { -#ifdef DD_DEBUG - assert(replace == REPLACE_TT || replace == REPLACE_TE); -#endif - savings -= updateRefs(dd,node,shared,info,localQueue) - 1; - } - assert(savings == 0); - } else { - replace = NOTHING; - } - if (replace == REPLACE_N) continue; - if ((replace == REPLACE_E || replace == NOTHING) && - !cuddIsConstant(cuddT(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), - cuddI(dd,cuddT(node)->index)); - if (replace == REPLACE_E) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - if ((replace == REPLACE_T || replace == NOTHING) && - !Cudd_IsConstant(cuddE(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), - cuddI(dd,Cudd_Regular(cuddE(node))->index)); - if (Cudd_IsComplement(cuddE(node))) { - if (replace == REPLACE_T) { - item->impactP += impactN; - item->impactN += impactP; - } else { - item->impactP += impactN/2.0; - item->impactN += impactP/2.0; - } - } else { - if (replace == REPLACE_T) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - } - if ((replace == REPLACE_TT || replace == REPLACE_TE) && - !Cudd_IsConstant(shared)) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared), - cuddI(dd,Cudd_Regular(shared)->index)); - if (Cudd_IsComplement(shared)) { - if (replace == REPLACE_T) { - item->impactP += impactN; - item->impactN += impactP; - } else { - item->impactP += impactN/2.0; - item->impactN += impactP/2.0; - } - } else { - if (replace == REPLACE_T) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - } - } - - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(1); - -} /* end of BAmarkNodes */ - - -/**Function******************************************************************** - - Synopsis [Builds the subset BDD for cuddRemapUnderApprox.] - - Description [Builds the subset BDDfor cuddRemapUnderApprox. Based - on the info table, performs remapping or replacement at selected - nodes. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [cuddRemapUnderApprox] - -******************************************************************************/ -static DdNode * -RAbuildSubset( - DdManager * dd /* DD manager */, - DdNode * node /* current node */, - ApproxInfo * info /* node info */) -{ - DdNode *Nt, *Ne, *N, *t, *e, *r; - NodeData *infoN; - - if (Cudd_IsConstant(node)) - return(node); - - N = Cudd_Regular(node); - - Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node)); - Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node)); - - if (st_lookup(info->table, (char *)N, (char **)&infoN)) { - if (N == node ) { - if (infoN->resultP != NULL) { - return(infoN->resultP); - } - } else { - if (infoN->resultN != NULL) { - return(infoN->resultN); - } - } - if (infoN->replace == REPLACE_T) { - r = RAbuildSubset(dd, Ne, info); - return(r); - } else if (infoN->replace == REPLACE_E) { - r = RAbuildSubset(dd, Nt, info); - return(r); - } else if (infoN->replace == REPLACE_N) { - return(info->zero); - } else if (infoN->replace == REPLACE_TT) { - DdNode *Ntt = Cudd_NotCond(cuddT(cuddT(N)), - Cudd_IsComplement(node)); - int index = cuddT(N)->index; - DdNode *e = info->zero; - DdNode *t = RAbuildSubset(dd, Ntt, info); - if (t == NULL) { - return(NULL); - } - cuddRef(t); - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - } - cuddDeref(t); - return(r); - } else if (infoN->replace == REPLACE_TE) { - DdNode *Nte = Cudd_NotCond(cuddE(cuddT(N)), - Cudd_IsComplement(node)); - int index = cuddT(N)->index; - DdNode *t = info->one; - DdNode *e = RAbuildSubset(dd, Nte, info); - if (e == NULL) { - return(NULL); - } - cuddRef(e); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - r =Cudd_Not(r); - cuddDeref(e); - return(r); - } - } else { - (void) fprintf(dd->err, - "Something is wrong, ought to be in info table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - - t = RAbuildSubset(dd, Nt, info); - if (t == NULL) { - return(NULL); - } - cuddRef(t); - - e = RAbuildSubset(dd, Ne, info); - if (e == NULL) { - Cudd_RecursiveDeref(dd,t); - return(NULL); - } - cuddRef(e); - - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - - if (N == node) { - infoN->resultP = r; - } else { - infoN->resultN = r; - } - - return(r); - -} /* end of RAbuildSubset */ - - -/**Function******************************************************************** - - Synopsis [Finds don't care nodes.] - - Description [Finds don't care nodes by traversing f and b in parallel. - Returns the care status of the visited f node if successful; CARE_ERROR - otherwise.] - - SideEffects [None] - - SeeAlso [cuddBiasedUnderApprox] - -******************************************************************************/ -static int -BAapplyBias( - DdManager *dd, - DdNode *f, - DdNode *b, - ApproxInfo *info, - DdHashTable *cache) -{ - DdNode *one, *zero, *res; - DdNode *Ft, *Fe, *B, *Bt, *Be; - unsigned int topf, topb; - NodeData *infoF; - int careT, careE; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - if (!st_lookup(info->table, (char *) f, (char **)&infoF)) - return(CARE_ERROR); - if (f == one) return(TOTAL_CARE); - if (b == zero) return(infoF->care); - if (infoF->care == TOTAL_CARE) return(TOTAL_CARE); - - if ((f->ref != 1 || Cudd_Regular(b)->ref != 1) && - (res = cuddHashTableLookup2(cache,f,b)) != NULL) { - if (res->ref == 0) { - cache->manager->dead++; - cache->manager->constants.dead++; - } - return(infoF->care); - } - - topf = dd->perm[f->index]; - B = Cudd_Regular(b); - topb = cuddI(dd,B->index); - if (topf <= topb) { - Ft = cuddT(f); Fe = cuddE(f); - } else { - Ft = Fe = f; - } - if (topb <= topf) { - /* We know that b is not constant because f is not. */ - Bt = cuddT(B); Be = cuddE(B); - if (Cudd_IsComplement(b)) { - Bt = Cudd_Not(Bt); - Be = Cudd_Not(Be); - } - } else { - Bt = Be = b; - } - - careT = BAapplyBias(dd, Ft, Bt, info, cache); - if (careT == CARE_ERROR) - return(CARE_ERROR); - careE = BAapplyBias(dd, Cudd_Regular(Fe), Be, info, cache); - if (careE == CARE_ERROR) - return(CARE_ERROR); - if (careT == TOTAL_CARE && careE == TOTAL_CARE) { - infoF->care = TOTAL_CARE; - } else { - infoF->care = CARE; - } - - if (f->ref != 1 || Cudd_Regular(b)->ref != 1) { - ptrint fanout = (ptrint) f->ref * Cudd_Regular(b)->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert2(cache,f,b,one,fanout)) { - return(CARE_ERROR); - } - } - return(infoF->care); - -} /* end of BAapplyBias */ diff --git a/src/bdd/cudd/cuddBddAbs.c b/src/bdd/cudd/cuddBddAbs.c deleted file mode 100644 index 9552464e..00000000 --- a/src/bdd/cudd/cuddBddAbs.c +++ /dev/null @@ -1,689 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddBddAbs.c] - - PackageName [cudd] - - Synopsis [Quantification functions for BDDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_bddExistAbstract() - <li> Cudd_bddXorExistAbstract() - <li> Cudd_bddUnivAbstract() - <li> Cudd_bddBooleanDiff() - <li> Cudd_bddVarIsDependent() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddBddExistAbstractRecur() - <li> cuddBddXorExistAbstractRecur() - <li> cuddBddBooleanDiffRecur() - </ul> - Static procedures included in this module: - <ul> - <li> bddCheckPositiveCube() - </ul> - ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddBddAbs.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int bddCheckPositiveCube ARGS((DdManager *manager, DdNode *cube)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Existentially abstracts all the variables in cube from f.] - - Description [Existentially abstracts all the variables in cube from f. - Returns the abstracted BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddUnivAbstract Cudd_addExistAbstract] - -******************************************************************************/ -DdNode * -Cudd_bddExistAbstract( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *res; - - if (bddCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err, - "Error: Can only abstract positive cubes\n"); - manager->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddBddExistAbstractRecur(manager, f, cube); - } while (manager->reordered == 1); - - return(res); - -} /* end of Cudd_bddExistAbstract */ - - -/**Function******************************************************************** - - Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Takes the exclusive OR of two BDDs and simultaneously abstracts - the variables in cube. The variables are existentially abstracted. Returns a - pointer to the result is successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddUnivAbstract Cudd_bddExistAbstract Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -Cudd_bddXorExistAbstract( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube) -{ - DdNode *res; - - if (bddCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err, - "Error: Can only abstract positive cubes\n"); - manager->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddBddXorExistAbstractRecur(manager, f, g, cube); - } while (manager->reordered == 1); - - return(res); - -} /* end of Cudd_bddXorExistAbstract */ - - -/**Function******************************************************************** - - Synopsis [Universally abstracts all the variables in cube from f.] - - Description [Universally abstracts all the variables in cube from f. - Returns the abstracted BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddExistAbstract Cudd_addUnivAbstract] - -******************************************************************************/ -DdNode * -Cudd_bddUnivAbstract( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *res; - - if (bddCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err, - "Error: Can only abstract positive cubes\n"); - manager->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube); - } while (manager->reordered == 1); - if (res != NULL) res = Cudd_Not(res); - - return(res); - -} /* end of Cudd_bddUnivAbstract */ - - -/**Function******************************************************************** - - Synopsis [Computes the boolean difference of f with respect to x.] - - Description [Computes the boolean difference of f with respect to the - variable with index x. Returns the BDD of the boolean difference if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_bddBooleanDiff( - DdManager * manager, - DdNode * f, - int x) -{ - DdNode *res, *var; - - /* If the variable is not currently in the manager, f cannot - ** depend on it. - */ - if (x >= manager->size) return(Cudd_Not(DD_ONE(manager))); - var = manager->vars[x]; - - do { - manager->reordered = 0; - res = cuddBddBooleanDiffRecur(manager, Cudd_Regular(f), var); - } while (manager->reordered == 1); - - return(res); - -} /* end of Cudd_bddBooleanDiff */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is dependent on others in a - function.] - - Description [Checks whether a variable is dependent on others in a - function. Returns 1 if the variable is dependent; 0 otherwise. No - new nodes are created.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_bddVarIsDependent( - DdManager *dd, /* manager */ - DdNode *f, /* function */ - DdNode *var /* variable */) -{ - DdNode *F, *res, *zero, *ft, *fe; - unsigned topf, level; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - int retval; - - zero = Cudd_Not(DD_ONE(dd)); - if (Cudd_IsConstant(f)) return(f == zero); - - /* From now on f is not constant. */ - F = Cudd_Regular(f); - topf = (unsigned) dd->perm[F->index]; - level = (unsigned) dd->perm[var->index]; - - /* Check terminal case. If topf > index of var, f does not depend on var. - ** Therefore, var is not dependent in f. */ - if (topf > level) { - return(0); - } - - cacheOp = - (DdNode *(*)(DdManager *, DdNode *, DdNode *)) Cudd_bddVarIsDependent; - res = cuddCacheLookup2(dd,cacheOp,f,var); - if (res != NULL) { - return(res != zero); - } - - /* Compute cofactors. */ - ft = Cudd_NotCond(cuddT(F), f != F); - fe = Cudd_NotCond(cuddE(F), f != F); - - if (topf == level) { - retval = Cudd_bddLeq(dd,ft,Cudd_Not(fe)); - } else { - retval = Cudd_bddVarIsDependent(dd,ft,var) && - Cudd_bddVarIsDependent(dd,fe,var); - } - - cuddCacheInsert2(dd,cacheOp,f,var,Cudd_NotCond(zero,retval)); - - return(retval); - -} /* Cudd_bddVarIsDependent */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive steps of Cudd_bddExistAbstract.] - - Description [Performs the recursive steps of Cudd_bddExistAbstract. - Returns the BDD obtained by abstracting the variables - of cube from f if successful; NULL otherwise. It is also used by - Cudd_bddUnivAbstract.] - - SideEffects [None] - - SeeAlso [Cudd_bddExistAbstract Cudd_bddUnivAbstract] - -******************************************************************************/ -DdNode * -cuddBddExistAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *F, *T, *E, *res, *res1, *res2, *one; - - statLine(manager); - one = DD_ONE(manager); - F = Cudd_Regular(f); - - /* Cube is guaranteed to be a cube at this point. */ - if (cube == one || F == one) { - return(f); - } - /* From now on, f and cube are non-constant. */ - - /* Abstract a variable that does not appear in f. */ - while (manager->perm[F->index] > manager->perm[cube->index]) { - cube = cuddT(cube); - if (cube == one) return(f); - } - - /* Check the cache. */ - if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) { - return(res); - } - - /* Compute the cofactors of f. */ - T = cuddT(F); E = cuddE(F); - if (f != F) { - T = Cudd_Not(T); E = Cudd_Not(E); - } - - /* If the two indices are the same, so are their levels. */ - if (F->index == cube->index) { - if (T == one || E == one || T == Cudd_Not(E)) { - return(one); - } - res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube)); - if (res1 == NULL) return(NULL); - if (res1 == one) { - if (F->ref != 1) - cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one); - return(one); - } - cuddRef(res1); - res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube)); - if (res2 == NULL) { - Cudd_IterDerefBdd(manager,res1); - return(NULL); - } - cuddRef(res2); - res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2)); - if (res == NULL) { - Cudd_IterDerefBdd(manager, res1); - Cudd_IterDerefBdd(manager, res2); - return(NULL); - } - res = Cudd_Not(res); - cuddRef(res); - Cudd_IterDerefBdd(manager, res1); - Cudd_IterDerefBdd(manager, res2); - if (F->ref != 1) - cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); - cuddDeref(res); - return(res); - } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */ - res1 = cuddBddExistAbstractRecur(manager, T, cube); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddBddExistAbstractRecur(manager, E, cube); - if (res2 == NULL) { - Cudd_IterDerefBdd(manager, res1); - return(NULL); - } - cuddRef(res2); - /* ITE takes care of possible complementation of res1 and of the - ** case in which res1 == res2. */ - res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2); - if (res == NULL) { - Cudd_IterDerefBdd(manager, res1); - Cudd_IterDerefBdd(manager, res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - if (F->ref != 1) - cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); - return(res); - } - -} /* end of cuddBddExistAbstractRecur */ - - -/**Function******************************************************************** - - Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Takes the exclusive OR of two BDDs and simultaneously abstracts - the variables in cube. The variables are existentially abstracted. Returns a - pointer to the result is successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -cuddBddXorExistAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube) -{ - DdNode *F, *fv, *fnv, *G, *gv, *gnv; - DdNode *one, *zero, *r, *t, *e, *Cube; - unsigned int topf, topg, topcube, top, index; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == g) { - return(zero); - } - if (f == Cudd_Not(g)) { - return(one); - } - if (cube == one) { - return(cuddBddXorRecur(manager, f, g)); - } - if (f == one) { - return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube)); - } - if (g == one) { - return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube)); - } - if (f == zero) { - return(cuddBddExistAbstractRecur(manager, g, cube)); - } - if (g == zero) { - return(cuddBddExistAbstractRecur(manager, f, cube)); - } - - /* At this point f, g, and cube are not constant. */ - - if (f > g) { /* Try to increase cache efficiency. */ - DdNode *tmp = f; - f = g; - g = tmp; - } - - /* Check cache. */ - r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube); - if (r != NULL) { - return(r); - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - F = Cudd_Regular(f); - topf = manager->perm[F->index]; - G = Cudd_Regular(g); - topg = manager->perm[G->index]; - top = ddMin(topf, topg); - topcube = manager->perm[cube->index]; - - if (topcube < top) { - return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube))); - } - /* Now, topcube >= top. */ - - if (topf == top) { - index = F->index; - fv = cuddT(F); - fnv = cuddE(F); - if (Cudd_IsComplement(f)) { - fv = Cudd_Not(fv); - fnv = Cudd_Not(fnv); - } - } else { - index = G->index; - fv = fnv = f; - } - - if (topg == top) { - gv = cuddT(G); - gnv = cuddE(G); - if (Cudd_IsComplement(g)) { - gv = Cudd_Not(gv); - gnv = Cudd_Not(gnv); - } - } else { - gv = gnv = g; - } - - if (topcube == top) { - Cube = cuddT(cube); - } else { - Cube = cube; - } - - t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube); - if (t == NULL) return(NULL); - - /* Special case: 1 OR anything = 1. Hence, no need to compute - ** the else branch if t is 1. - */ - if (t == one && topcube == top) { - cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one); - return(one); - } - cuddRef(t); - - e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube); - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - cuddRef(e); - - if (topcube == top) { /* abstract */ - r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - cuddRef(r); - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - cuddDeref(r); - } else if (t == e) { - r = t; - cuddDeref(t); - cuddDeref(e); - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - } - cuddDeref(e); - cuddDeref(t); - } - cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r); - return (r); - -} /* end of cuddBddXorExistAbstractRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive steps of Cudd_bddBoleanDiff.] - - Description [Performs the recursive steps of Cudd_bddBoleanDiff. - Returns the BDD obtained by XORing the cofactors of f with respect to - var if successful; NULL otherwise. Exploits the fact that dF/dx = - dF'/dx.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddBddBooleanDiffRecur( - DdManager * manager, - DdNode * f, - DdNode * var) -{ - DdNode *T, *E, *res, *res1, *res2; - - statLine(manager); - if (cuddI(manager,f->index) > manager->perm[var->index]) { - /* f does not depend on var. */ - return(Cudd_Not(DD_ONE(manager))); - } - - /* From now on, f is non-constant. */ - - /* If the two indices are the same, so are their levels. */ - if (f->index == var->index) { - res = cuddBddXorRecur(manager, cuddT(f), cuddE(f)); - return(res); - } - - /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */ - - /* Check the cache. */ - res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var); - if (res != NULL) { - return(res); - } - - /* Compute the cofactors of f. */ - T = cuddT(f); E = cuddE(f); - - res1 = cuddBddBooleanDiffRecur(manager, T, var); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var); - if (res2 == NULL) { - Cudd_IterDerefBdd(manager, res1); - return(NULL); - } - cuddRef(res2); - /* ITE takes care of possible complementation of res1 and of the - ** case in which res1 == res2. */ - res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2); - if (res == NULL) { - Cudd_IterDerefBdd(manager, res1); - Cudd_IterDerefBdd(manager, res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res); - return(res); - -} /* end of cuddBddBooleanDiffRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Checks whether cube is an BDD representing the product of - positive literals.] - - Description [Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -bddCheckPositiveCube( - DdManager * manager, - DdNode * cube) -{ - if (Cudd_IsComplement(cube)) return(0); - if (cube == DD_ONE(manager)) return(1); - if (cuddIsConstant(cube)) return(0); - if (cuddE(cube) == Cudd_Not(DD_ONE(manager))) { - return(bddCheckPositiveCube(manager, cuddT(cube))); - } - return(0); - -} /* end of bddCheckPositiveCube */ - diff --git a/src/bdd/cudd/cuddBddCorr.c b/src/bdd/cudd/cuddBddCorr.c deleted file mode 100644 index c99324a8..00000000 --- a/src/bdd/cudd/cuddBddCorr.c +++ /dev/null @@ -1,481 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddBddCorr.c] - - PackageName [cudd] - - Synopsis [Correlation between BDDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_bddCorrelation() - <li> Cudd_bddCorrelationWeights() - </ul> - Static procedures included in this module: - <ul> - <li> bddCorrelationAux() - <li> bddCorrelationWeightsAux() - <li> CorrelCompare() - <li> CorrelHash() - <li> CorrelCleanUp() - </ul> - ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct hashEntry { - DdNode *f; - DdNode *g; -} HashEntry; - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddBddCorr.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -#ifdef CORREL_STATS -static int num_calls; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static double bddCorrelationAux ARGS((DdManager *dd, DdNode *f, DdNode *g, st_table *table)); -static double bddCorrelationWeightsAux ARGS((DdManager *dd, DdNode *f, DdNode *g, double *prob, st_table *table)); -static int CorrelCompare ARGS((const char *key1, const char *key2)); -static int CorrelHash ARGS((char *key, int modulus)); -static enum st_retval CorrelCleanUp ARGS((char *key, char *value, char *arg)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the correlation of f and g.] - - Description [Computes the correlation of f and g. If f == g, their - correlation is 1. If f == g', their correlation is 0. Returns the - fraction of minterms in the ON-set of the EXNOR of f and g. If it - runs out of memory, returns (double)CUDD_OUT_OF_MEM.] - - SideEffects [None] - - SeeAlso [Cudd_bddCorrelationWeights] - -******************************************************************************/ -double -Cudd_bddCorrelation( - DdManager * manager, - DdNode * f, - DdNode * g) -{ - - st_table *table; - double correlation; - -#ifdef CORREL_STATS - num_calls = 0; -#endif - - table = st_init_table(CorrelCompare,CorrelHash); - if (table == NULL) return((double)CUDD_OUT_OF_MEM); - correlation = bddCorrelationAux(manager,f,g,table); - st_foreach(table, CorrelCleanUp, NIL(char)); - st_free_table(table); - return(correlation); - -} /* end of Cudd_bddCorrelation */ - - -/**Function******************************************************************** - - Synopsis [Computes the correlation of f and g for given input - probabilities.] - - Description [Computes the correlation of f and g for given input - probabilities. On input, prob\[i\] is supposed to contain the - probability of the i-th input variable to be 1. - If f == g, their correlation is 1. If f == g', their - correlation is 0. Returns the probability that f and g have the same - value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The - correlation of f and the constant one gives the probability of f.] - - SideEffects [None] - - SeeAlso [Cudd_bddCorrelation] - -******************************************************************************/ -double -Cudd_bddCorrelationWeights( - DdManager * manager, - DdNode * f, - DdNode * g, - double * prob) -{ - - st_table *table; - double correlation; - -#ifdef CORREL_STATS - num_calls = 0; -#endif - - table = st_init_table(CorrelCompare,CorrelHash); - if (table == NULL) return((double)CUDD_OUT_OF_MEM); - correlation = bddCorrelationWeightsAux(manager,f,g,prob,table); - st_foreach(table, CorrelCleanUp, NIL(char)); - st_free_table(table); - return(correlation); - -} /* end of Cudd_bddCorrelationWeights */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddCorrelation.] - - Description [Performs the recursive step of Cudd_bddCorrelation. - Returns the fraction of minterms in the ON-set of the EXNOR of f and - g.] - - SideEffects [None] - - SeeAlso [bddCorrelationWeightsAux] - -******************************************************************************/ -static double -bddCorrelationAux( - DdManager * dd, - DdNode * f, - DdNode * g, - st_table * table) -{ - DdNode *Fv, *Fnv, *G, *Gv, *Gnv; - double min, *pmin, min1, min2, *dummy; - HashEntry *entry; - unsigned int topF, topG; - - statLine(dd); -#ifdef CORREL_STATS - num_calls++; -#endif - - /* Terminal cases: only work for BDDs. */ - if (f == g) return(1.0); - if (f == Cudd_Not(g)) return(0.0); - - /* Standardize call using the following properties: - ** (f EXNOR g) = (g EXNOR f) - ** (f' EXNOR g') = (f EXNOR g). - */ - if (f > g) { - DdNode *tmp = f; - f = g; g = tmp; - } - if (Cudd_IsComplement(f)) { - f = Cudd_Not(f); - g = Cudd_Not(g); - } - /* From now on, f is regular. */ - - entry = ALLOC(HashEntry,1); - if (entry == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(CUDD_OUT_OF_MEM); - } - entry->f = f; entry->g = g; - - /* We do not use the fact that - ** correlation(f,g') = 1 - correlation(f,g) - ** to minimize the risk of cancellation. - */ - if (st_lookup(table, (char *)entry, (char **)&dummy)) { - min = *dummy; - FREE(entry); - return(min); - } - - G = Cudd_Regular(g); - topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); - if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } - if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } - - if (g != G) { - Gv = Cudd_Not(Gv); - Gnv = Cudd_Not(Gnv); - } - - min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0; - if (min1 == (double)CUDD_OUT_OF_MEM) { - FREE(entry); - return(CUDD_OUT_OF_MEM); - } - min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0; - if (min2 == (double)CUDD_OUT_OF_MEM) { - FREE(entry); - return(CUDD_OUT_OF_MEM); - } - min = (min1+min2); - - pmin = ALLOC(double,1); - if (pmin == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return((double)CUDD_OUT_OF_MEM); - } - *pmin = min; - - if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) { - FREE(entry); - FREE(pmin); - return((double)CUDD_OUT_OF_MEM); - } - return(min); - -} /* end of bddCorrelationAux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddCorrelationWeigths.] - - Description [] - - SideEffects [None] - - SeeAlso [bddCorrelationAux] - -******************************************************************************/ -static double -bddCorrelationWeightsAux( - DdManager * dd, - DdNode * f, - DdNode * g, - double * prob, - st_table * table) -{ - DdNode *Fv, *Fnv, *G, *Gv, *Gnv; - double min, *pmin, min1, min2, *dummy; - HashEntry *entry; - int topF, topG, index; - - statLine(dd); -#ifdef CORREL_STATS - num_calls++; -#endif - - /* Terminal cases: only work for BDDs. */ - if (f == g) return(1.0); - if (f == Cudd_Not(g)) return(0.0); - - /* Standardize call using the following properties: - ** (f EXNOR g) = (g EXNOR f) - ** (f' EXNOR g') = (f EXNOR g). - */ - if (f > g) { - DdNode *tmp = f; - f = g; g = tmp; - } - if (Cudd_IsComplement(f)) { - f = Cudd_Not(f); - g = Cudd_Not(g); - } - /* From now on, f is regular. */ - - entry = ALLOC(HashEntry,1); - if (entry == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return((double)CUDD_OUT_OF_MEM); - } - entry->f = f; entry->g = g; - - /* We do not use the fact that - ** correlation(f,g') = 1 - correlation(f,g) - ** to minimize the risk of cancellation. - */ - if (st_lookup(table, (char *)entry, (char **)&dummy)) { - min = *dummy; - FREE(entry); - return(min); - } - - G = Cudd_Regular(g); - topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); - if (topF <= topG) { - Fv = cuddT(f); Fnv = cuddE(f); - index = f->index; - } else { - Fv = Fnv = f; - index = G->index; - } - if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } - - if (g != G) { - Gv = Cudd_Not(Gv); - Gnv = Cudd_Not(Gnv); - } - - min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index]; - if (min1 == (double)CUDD_OUT_OF_MEM) { - FREE(entry); - return((double)CUDD_OUT_OF_MEM); - } - min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]); - if (min2 == (double)CUDD_OUT_OF_MEM) { - FREE(entry); - return((double)CUDD_OUT_OF_MEM); - } - min = (min1+min2); - - pmin = ALLOC(double,1); - if (pmin == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return((double)CUDD_OUT_OF_MEM); - } - *pmin = min; - - if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) { - FREE(entry); - FREE(pmin); - return((double)CUDD_OUT_OF_MEM); - } - return(min); - -} /* end of bddCorrelationWeightsAux */ - - -/**Function******************************************************************** - - Synopsis [Compares two hash table entries.] - - Description [Compares two hash table entries. Returns 0 if they are - identical; 1 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -CorrelCompare( - const char * key1, - const char * key2) -{ - HashEntry *entry1; - HashEntry *entry2; - - entry1 = (HashEntry *) key1; - entry2 = (HashEntry *) key2; - if (entry1->f != entry2->f || entry1->g != entry2->g) return(1); - - return(0); - -} /* end of CorrelCompare */ - - -/**Function******************************************************************** - - Synopsis [Hashes a hash table entry.] - - Description [Hashes a hash table entry. It is patterned after - st_strhash. Returns a value between 0 and modulus.] - - SideEffects [None] - -******************************************************************************/ -static int -CorrelHash( - char * key, - int modulus) -{ - HashEntry *entry; - int val = 0; - - entry = (HashEntry *) key; -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 - val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g)); -#else - val = ((int) entry->f)*997 + ((int) entry->g); -#endif - - return ((val < 0) ? -val : val) % modulus; - -} /* end of CorrelHash */ - - -/**Function******************************************************************** - - Synopsis [Frees memory associated with hash table.] - - Description [Frees memory associated with hash table. Returns - ST_CONTINUE.] - - SideEffects [None] - -******************************************************************************/ -static enum st_retval -CorrelCleanUp( - char * key, - char * value, - char * arg) -{ - double *d; - HashEntry *entry; - - entry = (HashEntry *) key; - FREE(entry); - d = (double *)value; - FREE(d); - return ST_CONTINUE; - -} /* end of CorrelCleanUp */ - diff --git a/src/bdd/cudd/cuddBddIte.c b/src/bdd/cudd/cuddBddIte.c deleted file mode 100644 index b44e40de..00000000 --- a/src/bdd/cudd/cuddBddIte.c +++ /dev/null @@ -1,1254 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddBddIte.c] - - PackageName [cudd] - - Synopsis [BDD ITE function and satellites.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_bddIte() - <li> Cudd_bddIteConstant() - <li> Cudd_bddIntersect() - <li> Cudd_bddAnd() - <li> Cudd_bddOr() - <li> Cudd_bddNand() - <li> Cudd_bddNor() - <li> Cudd_bddXor() - <li> Cudd_bddXnor() - <li> Cudd_bddLeq() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddBddIteRecur() - <li> cuddBddIntersectRecur() - <li> cuddBddAndRecur() - <li> cuddBddXorRecur() - </ul> - Static procedures included in this module: - <ul> - <li> bddVarToConst() - <li> bddVarToCanonical() - <li> bddVarToCanonicalSimple() - </ul>] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddBddIte.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void bddVarToConst ARGS((DdNode *f, DdNode **gp, DdNode **hp, DdNode *one)); -static int bddVarToCanonical ARGS((DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp)); -static int bddVarToCanonicalSimple ARGS((DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements ITE(f,g,h).] - - Description [Implements ITE(f,g,h). Returns a pointer to the - resulting BDD if successful; NULL if the intermediate result blows - up.] - - SideEffects [None] - - SeeAlso [Cudd_addIte Cudd_bddIteConstant Cudd_bddIntersect] - -******************************************************************************/ -DdNode * -Cudd_bddIte( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddIteRecur(dd,f,g,h); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddIte */ - - -/**Function******************************************************************** - - Synopsis [Implements ITEconstant(f,g,h).] - - Description [Implements ITEconstant(f,g,h). Returns a pointer to the - resulting BDD (which may or may not be constant) or DD_NON_CONSTANT. - No new nodes are created.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_bddIntersect Cudd_bddLeq Cudd_addIteConstant] - -******************************************************************************/ -DdNode * -Cudd_bddIteConstant( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e; - DdNode *one = DD_ONE(dd); - DdNode *zero = Cudd_Not(one); - int comple; - unsigned int topf, topg, toph, v; - - statLine(dd); - /* Trivial cases. */ - if (f == one) /* ITE(1,G,H) => G */ - return(g); - - if (f == zero) /* ITE(0,G,H) => H */ - return(h); - - /* f now not a constant. */ - bddVarToConst(f, &g, &h, one); /* possibly convert g or h */ - /* to constants */ - - if (g == h) /* ITE(F,G,G) => G */ - return(g); - - if (Cudd_IsConstant(g) && Cudd_IsConstant(h)) - return(DD_NON_CONSTANT); /* ITE(F,1,0) or ITE(F,0,1) */ - /* => DD_NON_CONSTANT */ - - if (g == Cudd_Not(h)) - return(DD_NON_CONSTANT); /* ITE(F,G,G') => DD_NON_CONSTANT */ - /* if F != G and F != G' */ - - comple = bddVarToCanonical(dd, &f, &g, &h, &topf, &topg, &toph); - - /* Cache lookup. */ - r = cuddConstantLookup(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h); - if (r != NULL) { - return(Cudd_NotCond(r,comple && r != DD_NON_CONSTANT)); - } - - v = ddMin(topg, toph); - - /* ITE(F,G,H) = (v,G,H) (non constant) if F = (v,1,0), v < top(G,H). */ - if (topf < v && cuddT(f) == one && cuddE(f) == zero) { - return(DD_NON_CONSTANT); - } - - /* Compute cofactors. */ - if (topf <= v) { - v = ddMin(topf, v); /* v = top_var(F,G,H) */ - Fv = cuddT(f); Fnv = cuddE(f); - } else { - Fv = Fnv = f; - } - - if (topg == v) { - Gv = cuddT(g); Gnv = cuddE(g); - } else { - Gv = Gnv = g; - } - - if (toph == v) { - H = Cudd_Regular(h); - Hv = cuddT(H); Hnv = cuddE(H); - if (Cudd_IsComplement(h)) { - Hv = Cudd_Not(Hv); - Hnv = Cudd_Not(Hnv); - } - } else { - Hv = Hnv = h; - } - - /* Recursion. */ - t = Cudd_bddIteConstant(dd, Fv, Gv, Hv); - if (t == DD_NON_CONSTANT || !Cudd_IsConstant(t)) { - cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - e = Cudd_bddIteConstant(dd, Fnv, Gnv, Hnv); - if (e == DD_NON_CONSTANT || !Cudd_IsConstant(e) || t != e) { - cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, t); - return(Cudd_NotCond(t,comple)); - -} /* end of Cudd_bddIteConstant */ - - -/**Function******************************************************************** - - Synopsis [Returns a function included in the intersection of f and g.] - - Description [Computes a function included in the intersection of f and - g. (That is, a witness that the intersection is not empty.) - Cudd_bddIntersect tries to build as few new nodes as possible. If the - only result of interest is whether f and g intersect, - Cudd_bddLeq should be used instead.] - - SideEffects [None] - - SeeAlso [Cudd_bddLeq Cudd_bddIteConstant] - -******************************************************************************/ -DdNode * -Cudd_bddIntersect( - DdManager * dd /* manager */, - DdNode * f /* first operand */, - DdNode * g /* second operand */) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddIntersectRecur(dd,f,g); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_bddIntersect */ - - -/**Function******************************************************************** - - Synopsis [Computes the conjunction of two BDDs f and g.] - - Description [Computes the conjunction of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect - Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Cudd_bddAnd( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddAndRecur(dd,f,g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddAnd */ - - -/**Function******************************************************************** - - Synopsis [Computes the disjunction of two BDDs f and g.] - - Description [Computes the disjunction of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddNand Cudd_bddNor - Cudd_bddXor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Cudd_bddOr( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g)); - } while (dd->reordered == 1); - res = Cudd_NotCond(res,res != NULL); - return(res); - -} /* end of Cudd_bddOr */ - - -/**Function******************************************************************** - - Synopsis [Computes the NAND of two BDDs f and g.] - - Description [Computes the NAND of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNor - Cudd_bddXor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Cudd_bddNand( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddAndRecur(dd,f,g); - } while (dd->reordered == 1); - res = Cudd_NotCond(res,res != NULL); - return(res); - -} /* end of Cudd_bddNand */ - - -/**Function******************************************************************** - - Synopsis [Computes the NOR of two BDDs f and g.] - - Description [Computes the NOR of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand - Cudd_bddXor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Cudd_bddNor( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g)); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddNor */ - - -/**Function******************************************************************** - - Synopsis [Computes the exclusive OR of two BDDs f and g.] - - Description [Computes the exclusive OR of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr - Cudd_bddNand Cudd_bddNor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Cudd_bddXor( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddXorRecur(dd,f,g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddXor */ - - -/**Function******************************************************************** - - Synopsis [Computes the exclusive NOR of two BDDs f and g.] - - Description [Computes the exclusive NOR of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr - Cudd_bddNand Cudd_bddNor Cudd_bddXor] - -******************************************************************************/ -DdNode * -Cudd_bddXnor( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddXorRecur(dd,f,Cudd_Not(g)); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddXnor */ - - -/**Function******************************************************************** - - Synopsis [Determines whether f is less than or equal to g.] - - Description [Returns 1 if f is less than or equal to g; 0 otherwise. - No new nodes are created.] - - SideEffects [None] - - SeeAlso [Cudd_bddIteConstant Cudd_addEvalConst] - -******************************************************************************/ -int -Cudd_bddLeq( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn; - unsigned int topf, topg, res; - - statLine(dd); - /* Terminal cases and normalization. */ - if (f == g) return(1); - - if (Cudd_IsComplement(g)) { - /* Special case: if f is regular and g is complemented, - ** f(1,...,1) = 1 > 0 = g(1,...,1). - */ - if (!Cudd_IsComplement(f)) return(0); - /* Both are complemented: Swap and complement because - ** f <= g <=> g' <= f' and we want the second argument to be regular. - */ - tmp = g; - g = Cudd_Not(f); - f = Cudd_Not(tmp); - } else if (Cudd_IsComplement(f) && g < f) { - tmp = g; - g = Cudd_Not(f); - f = Cudd_Not(tmp); - } - - /* Now g is regular and, if f is not regular, f < g. */ - one = DD_ONE(dd); - if (g == one) return(1); /* no need to test against zero */ - if (f == one) return(0); /* since at this point g != one */ - if (Cudd_Not(f) == g) return(0); /* because neither is constant */ - zero = Cudd_Not(one); - if (f == zero) return(1); - - /* Here neither f nor g is constant. */ - - /* Check cache. */ - tmp = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, - DdNode *))Cudd_bddLeq,f,g); - if (tmp != NULL) { - return(tmp == one); - } - - /* Compute cofactors. */ - F = Cudd_Regular(f); - topf = dd->perm[F->index]; - topg = dd->perm[g->index]; - if (topf <= topg) { - fv = cuddT(F); fvn = cuddE(F); - if (f != F) { - fv = Cudd_Not(fv); - fvn = Cudd_Not(fvn); - } - } else { - fv = fvn = f; - } - if (topg <= topf) { - gv = cuddT(g); gvn = cuddE(g); - } else { - gv = gvn = g; - } - - /* Recursive calls. Since we want to maximize the probability of - ** the special case f(1,...,1) > g(1,...,1), we consider the negative - ** cofactors first. Indeed, the complementation parity of the positive - ** cofactors is the same as the one of the parent functions. - */ - res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv); - - /* Store result in cache and return. */ - cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_bddLeq,f,g,(res ? one : zero)); - return(res); - -} /* end of Cudd_bddLeq */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddIte.] - - Description [Implements the recursive step of Cudd_bddIte. Returns a - pointer to the resulting BDD. NULL if the intermediate result blows - up or if reordering occurs.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddBddIteRecur( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *one, *zero, *res; - DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e; - unsigned int topf, topg, toph, v; - int index; - int comple; - - statLine(dd); - /* Terminal cases. */ - - /* One variable cases. */ - if (f == (one = DD_ONE(dd))) /* ITE(1,G,H) = G */ - return(g); - - if (f == (zero = Cudd_Not(one))) /* ITE(0,G,H) = H */ - return(h); - - /* From now on, f is known not to be a constant. */ - if (g == one || f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ - if (h == zero) { /* ITE(F,1,0) = F */ - return(f); - } else { - res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h)); - return(Cudd_NotCond(res,res != NULL)); - } - } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */ - if (h == one) { /* ITE(F,0,1) = !F */ - return(Cudd_Not(f)); - } else { - res = cuddBddAndRecur(dd,Cudd_Not(f),h); - return(res); - } - } - if (h == zero || f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ - res = cuddBddAndRecur(dd,f,g); - return(res); - } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */ - res = cuddBddAndRecur(dd,f,Cudd_Not(g)); - return(Cudd_NotCond(res,res != NULL)); - } - - /* Check remaining one variable case. */ - if (g == h) { /* ITE(F,G,G) = G */ - return(g); - } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */ - res = cuddBddXorRecur(dd,f,h); - return(res); - } - - /* From here, there are no constants. */ - comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph); - - /* f & g are now regular pointers */ - - v = ddMin(topg, toph); - - /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */ - if (topf < v && cuddT(f) == one && cuddE(f) == zero) { - r = cuddUniqueInter(dd, (int) f->index, g, h); - return(Cudd_NotCond(r,comple && r != NULL)); - } - - /* Check cache. */ - r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - /* Compute cofactors. */ - if (topf <= v) { - v = ddMin(topf, v); /* v = top_var(F,G,H) */ - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - } else { - Fv = Fnv = f; - } - if (topg == v) { - index = g->index; - Gv = cuddT(g); Gnv = cuddE(g); - } else { - Gv = Gnv = g; - } - if (toph == v) { - H = Cudd_Regular(h); - index = H->index; - Hv = cuddT(H); Hnv = cuddE(H); - if (Cudd_IsComplement(h)) { - Hv = Cudd_Not(Hv); - Hnv = Cudd_Not(Hnv); - } - } else { - Hv = Hnv = h; - } - - /* Recursive step. */ - t = cuddBddIteRecur(dd,Fv,Gv,Hv); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv); - if (e == NULL) { - Cudd_IterDerefBdd(dd,t); - return(NULL); - } - cuddRef(e); - - r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(dd,t); - Cudd_IterDerefBdd(dd,e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r); - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddIteRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddIntersect.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_bddIntersect] - -******************************************************************************/ -DdNode * -cuddBddIntersectRecur( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - DdNode *F, *G, *t, *e; - DdNode *fv, *fnv, *gv, *gnv; - DdNode *one, *zero; - unsigned int index, topf, topg; - - statLine(dd); - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); - if (f == g || g == one) return(f); - if (f == one) return(g); - - /* At this point f and g are not constant. */ - if (f > g) { DdNode *tmp = f; f = g; g = tmp; } - res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g); - if (res != NULL) return(res); - - /* Find splitting variable. Here we can skip the use of cuddI, - ** because the operands are known to be non-constant. - */ - F = Cudd_Regular(f); - topf = dd->perm[F->index]; - G = Cudd_Regular(g); - topg = dd->perm[G->index]; - - /* Compute cofactors. */ - if (topf <= topg) { - index = F->index; - fv = cuddT(F); - fnv = cuddE(F); - if (Cudd_IsComplement(f)) { - fv = Cudd_Not(fv); - fnv = Cudd_Not(fnv); - } - } else { - index = G->index; - fv = fnv = f; - } - - if (topg <= topf) { - gv = cuddT(G); - gnv = cuddE(G); - if (Cudd_IsComplement(g)) { - gv = Cudd_Not(gv); - gnv = Cudd_Not(gnv); - } - } else { - gv = gnv = g; - } - - /* Compute partial results. */ - t = cuddBddIntersectRecur(dd,fv,gv); - if (t == NULL) return(NULL); - cuddRef(t); - if (t != zero) { - e = zero; - } else { - e = cuddBddIntersectRecur(dd,fnv,gnv); - if (e == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - cuddRef(e); - - if (t == e) { /* both equal zero */ - res = t; - } else if (Cudd_IsComplement(t)) { - res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (res == NULL) { - Cudd_IterDerefBdd(dd, t); - Cudd_IterDerefBdd(dd, e); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = cuddUniqueInter(dd,(int)index,t,e); - if (res == NULL) { - Cudd_IterDerefBdd(dd, t); - Cudd_IterDerefBdd(dd, e); - return(NULL); - } - } - cuddDeref(e); - cuddDeref(t); - - cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res); - - return(res); - -} /* end of cuddBddIntersectRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddAnd.] - - Description [Implements the recursive step of Cudd_bddAnd by taking - the conjunction of two BDDs. Returns a pointer to the result is - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddAnd] - -******************************************************************************/ -DdNode * -cuddBddAndRecur( - DdManager * manager, - DdNode * f, - DdNode * g) -{ - DdNode *F, *fv, *fnv, *G, *gv, *gnv; - DdNode *one, *r, *t, *e; - unsigned int topf, topg, index; - - statLine(manager); - one = DD_ONE(manager); - - /* Terminal cases. */ - F = Cudd_Regular(f); - G = Cudd_Regular(g); - if (F == G) { - if (f == g) return(f); - else return(Cudd_Not(one)); - } - if (F == one) { - if (f == one) return(g); - else return(f); - } - if (G == one) { - if (g == one) return(f); - else return(g); - } - - /* At this point f and g are not constant. */ - if (f > g) { /* Try to increase cache efficiency. */ - DdNode *tmp = f; - f = g; - g = tmp; - F = Cudd_Regular(f); - G = Cudd_Regular(g); - } - - /* Check cache. */ - if (F->ref != 1 || G->ref != 1) { - r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g); - if (r != NULL) return(r); - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - topf = manager->perm[F->index]; - topg = manager->perm[G->index]; - - /* Compute cofactors. */ - if (topf <= topg) { - index = F->index; - fv = cuddT(F); - fnv = cuddE(F); - if (Cudd_IsComplement(f)) { - fv = Cudd_Not(fv); - fnv = Cudd_Not(fnv); - } - } else { - index = G->index; - fv = fnv = f; - } - - if (topg <= topf) { - gv = cuddT(G); - gnv = cuddE(G); - if (Cudd_IsComplement(g)) { - gv = Cudd_Not(gv); - gnv = Cudd_Not(gnv); - } - } else { - gv = gnv = g; - } - - t = cuddBddAndRecur(manager, fv, gv); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddBddAndRecur(manager, fnv, gnv); - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - } - } - cuddDeref(e); - cuddDeref(t); - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r); - return(r); - -} /* end of cuddBddAndRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddXor.] - - Description [Implements the recursive step of Cudd_bddXor by taking - the exclusive OR of two BDDs. Returns a pointer to the result is - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddXor] - -******************************************************************************/ -DdNode * -cuddBddXorRecur( - DdManager * manager, - DdNode * f, - DdNode * g) -{ - DdNode *fv, *fnv, *G, *gv, *gnv; - DdNode *one, *zero, *r, *t, *e; - unsigned int topf, topg, index; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == g) return(zero); - if (f == Cudd_Not(g)) return(one); - if (f > g) { /* Try to increase cache efficiency and simplify tests. */ - DdNode *tmp = f; - f = g; - g = tmp; - } - if (g == zero) return(f); - if (g == one) return(Cudd_Not(f)); - if (Cudd_IsComplement(f)) { - f = Cudd_Not(f); - g = Cudd_Not(g); - } - /* Now the first argument is regular. */ - if (f == one) return(Cudd_Not(g)); - - /* At this point f and g are not constant. */ - - /* Check cache. */ - r = cuddCacheLookup2(manager, Cudd_bddXor, f, g); - if (r != NULL) return(r); - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - topf = manager->perm[f->index]; - G = Cudd_Regular(g); - topg = manager->perm[G->index]; - - /* Compute cofactors. */ - if (topf <= topg) { - index = f->index; - fv = cuddT(f); - fnv = cuddE(f); - } else { - index = G->index; - fv = fnv = f; - } - - if (topg <= topf) { - gv = cuddT(G); - gnv = cuddE(G); - if (Cudd_IsComplement(g)) { - gv = Cudd_Not(gv); - gnv = Cudd_Not(gnv); - } - } else { - gv = gnv = g; - } - - t = cuddBddXorRecur(manager, fv, gv); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddBddXorRecur(manager, fnv, gnv); - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - } - } - cuddDeref(e); - cuddDeref(t); - cuddCacheInsert2(manager, Cudd_bddXor, f, g, r); - return(r); - -} /* end of cuddBddXorRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Replaces variables with constants if possible.] - - Description [This function performs part of the transformation to - standard form by replacing variables with constants if possible.] - - SideEffects [None] - - SeeAlso [bddVarToCanonical bddVarToCanonicalSimple] - -******************************************************************************/ -static void -bddVarToConst( - DdNode * f, - DdNode ** gp, - DdNode ** hp, - DdNode * one) -{ - DdNode *g = *gp; - DdNode *h = *hp; - - if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ - *gp = one; - } else if (f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */ - *gp = Cudd_Not(one); - } - if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ - *hp = Cudd_Not(one); - } else if (f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */ - *hp = one; - } - -} /* end of bddVarToConst */ - - -/**Function******************************************************************** - - Synopsis [Picks unique member from equiv expressions.] - - Description [Reduces 2 variable expressions to canonical form.] - - SideEffects [None] - - SeeAlso [bddVarToConst bddVarToCanonicalSimple] - -******************************************************************************/ -static int -bddVarToCanonical( - DdManager * dd, - DdNode ** fp, - DdNode ** gp, - DdNode ** hp, - unsigned int * topfp, - unsigned int * topgp, - unsigned int * tophp) -{ - register DdNode *F, *G, *H, *r, *f, *g, *h; - register unsigned int topf, topg, toph; - DdNode *one = dd->one; - int comple, change; - - f = *fp; - g = *gp; - h = *hp; - F = Cudd_Regular(f); - G = Cudd_Regular(g); - H = Cudd_Regular(h); - topf = cuddI(dd,F->index); - topg = cuddI(dd,G->index); - toph = cuddI(dd,H->index); - - change = 0; - - if (G == one) { /* ITE(F,c,H) */ - if ((topf > toph) || (topf == toph && f > h)) { - r = h; - h = f; - f = r; /* ITE(F,1,H) = ITE(H,1,F) */ - if (g != one) { /* g == zero */ - f = Cudd_Not(f); /* ITE(F,0,H) = ITE(!H,0,!F) */ - h = Cudd_Not(h); - } - change = 1; - } - } else if (H == one) { /* ITE(F,G,c) */ - if ((topf > topg) || (topf == topg && f > g)) { - r = g; - g = f; - f = r; /* ITE(F,G,0) = ITE(G,F,0) */ - if (h == one) { - f = Cudd_Not(f); /* ITE(F,G,1) = ITE(!G,!F,1) */ - g = Cudd_Not(g); - } - change = 1; - } - } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = ITE(G,F,!F) */ - if ((topf > topg) || (topf == topg && f > g)) { - r = f; - f = g; - g = r; - h = Cudd_Not(r); - change = 1; - } - } - /* adjust pointers so that the first 2 arguments to ITE are regular */ - if (Cudd_IsComplement(f) != 0) { /* ITE(!F,G,H) = ITE(F,H,G) */ - f = Cudd_Not(f); - r = g; - g = h; - h = r; - change = 1; - } - comple = 0; - if (Cudd_IsComplement(g) != 0) { /* ITE(F,!G,H) = !ITE(F,G,!H) */ - g = Cudd_Not(g); - h = Cudd_Not(h); - change = 1; - comple = 1; - } - if (change != 0) { - *fp = f; - *gp = g; - *hp = h; - } - *topfp = cuddI(dd,f->index); - *topgp = cuddI(dd,g->index); - *tophp = cuddI(dd,Cudd_Regular(h)->index); - - return(comple); - -} /* end of bddVarToCanonical */ - - -/**Function******************************************************************** - - Synopsis [Picks unique member from equiv expressions.] - - Description [Makes sure the first two pointers are regular. This - mat require the complementation of the result, which is signaled by - returning 1 instead of 0. This function is simpler than the general - case because it assumes that no two arguments are the same or - complementary, and no argument is constant.] - - SideEffects [None] - - SeeAlso [bddVarToConst bddVarToCanonical] - -******************************************************************************/ -static int -bddVarToCanonicalSimple( - DdManager * dd, - DdNode ** fp, - DdNode ** gp, - DdNode ** hp, - unsigned int * topfp, - unsigned int * topgp, - unsigned int * tophp) -{ - register DdNode *r, *f, *g, *h; - int comple, change; - - f = *fp; - g = *gp; - h = *hp; - - change = 0; - - /* adjust pointers so that the first 2 arguments to ITE are regular */ - if (Cudd_IsComplement(f)) { /* ITE(!F,G,H) = ITE(F,H,G) */ - f = Cudd_Not(f); - r = g; - g = h; - h = r; - change = 1; - } - comple = 0; - if (Cudd_IsComplement(g)) { /* ITE(F,!G,H) = !ITE(F,G,!H) */ - g = Cudd_Not(g); - h = Cudd_Not(h); - change = 1; - comple = 1; - } - if (change) { - *fp = f; - *gp = g; - *hp = h; - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - *topfp = dd->perm[f->index]; - *topgp = dd->perm[g->index]; - *tophp = dd->perm[Cudd_Regular(h)->index]; - - return(comple); - -} /* end of bddVarToCanonicalSimple */ - diff --git a/src/bdd/cudd/cuddBridge.c b/src/bdd/cudd/cuddBridge.c deleted file mode 100644 index ccc0893f..00000000 --- a/src/bdd/cudd/cuddBridge.c +++ /dev/null @@ -1,981 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddBridge.c] - - PackageName [cudd] - - Synopsis [Translation from BDD to ADD and vice versa and transfer between - different managers.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_addBddThreshold() - <li> Cudd_addBddStrictThreshold() - <li> Cudd_addBddInterval() - <li> Cudd_addBddIthBit() - <li> Cudd_BddToAdd() - <li> Cudd_addBddPattern() - <li> Cudd_bddTransfer() - </ul> - Internal procedures included in this file: - <ul> - <li> cuddBddTransfer() - <li> cuddAddBddDoPattern() - </ul> - Static procedures included in this file: - <ul> - <li> addBddDoThreshold() - <li> addBddDoStrictThreshold() - <li> addBddDoInterval() - <li> addBddDoIthBit() - <li> ddBddToAddRecur() - <li> cuddBddTransferRecur() - </ul> - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddBridge.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * addBddDoThreshold ARGS((DdManager *dd, DdNode *f, DdNode *val)); -static DdNode * addBddDoStrictThreshold ARGS((DdManager *dd, DdNode *f, DdNode *val)); -static DdNode * addBddDoInterval ARGS((DdManager *dd, DdNode *f, DdNode *l, DdNode *u)); -static DdNode * addBddDoIthBit ARGS((DdManager *dd, DdNode *f, DdNode *index)); -static DdNode * ddBddToAddRecur ARGS((DdManager *dd, DdNode *B)); -static DdNode * cuddBddTransferRecur ARGS((DdManager *ddS, DdManager *ddD, DdNode *f, st_table *table)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Converts an ADD to a BDD.] - - Description [Converts an ADD to a BDD by replacing all - discriminants greater than or equal to value with 1, and all other - discriminants with 0. Returns a pointer to the resulting BDD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd - Cudd_addBddStrictThreshold] - -******************************************************************************/ -DdNode * -Cudd_addBddThreshold( - DdManager * dd, - DdNode * f, - CUDD_VALUE_TYPE value) -{ - DdNode *res; - DdNode *val; - - val = cuddUniqueConst(dd,value); - if (val == NULL) return(NULL); - cuddRef(val); - - do { - dd->reordered = 0; - res = addBddDoThreshold(dd, f, val); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd, val); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, val); - cuddDeref(res); - return(res); - -} /* end of Cudd_addBddThreshold */ - - -/**Function******************************************************************** - - Synopsis [Converts an ADD to a BDD.] - - Description [Converts an ADD to a BDD by replacing all - discriminants STRICTLY greater than value with 1, and all other - discriminants with 0. Returns a pointer to the resulting BDD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd - Cudd_addBddThreshold] - -******************************************************************************/ -DdNode * -Cudd_addBddStrictThreshold( - DdManager * dd, - DdNode * f, - CUDD_VALUE_TYPE value) -{ - DdNode *res; - DdNode *val; - - val = cuddUniqueConst(dd,value); - if (val == NULL) return(NULL); - cuddRef(val); - - do { - dd->reordered = 0; - res = addBddDoStrictThreshold(dd, f, val); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd, val); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, val); - cuddDeref(res); - return(res); - -} /* end of Cudd_addBddStrictThreshold */ - - -/**Function******************************************************************** - - Synopsis [Converts an ADD to a BDD.] - - Description [Converts an ADD to a BDD by replacing all - discriminants greater than or equal to lower and less than or equal to - upper with 1, and all other discriminants with 0. Returns a pointer to - the resulting BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddThreshold Cudd_addBddStrictThreshold - Cudd_addBddPattern Cudd_BddToAdd] - -******************************************************************************/ -DdNode * -Cudd_addBddInterval( - DdManager * dd, - DdNode * f, - CUDD_VALUE_TYPE lower, - CUDD_VALUE_TYPE upper) -{ - DdNode *res; - DdNode *l; - DdNode *u; - - /* Create constant nodes for the interval bounds, so that we can use - ** the global cache. - */ - l = cuddUniqueConst(dd,lower); - if (l == NULL) return(NULL); - cuddRef(l); - u = cuddUniqueConst(dd,upper); - if (u == NULL) { - Cudd_RecursiveDeref(dd,l); - return(NULL); - } - cuddRef(u); - - do { - dd->reordered = 0; - res = addBddDoInterval(dd, f, l, u); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd, l); - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, l); - Cudd_RecursiveDeref(dd, u); - cuddDeref(res); - return(res); - -} /* end of Cudd_addBddInterval */ - - -/**Function******************************************************************** - - Synopsis [Converts an ADD to a BDD by extracting the i-th bit from - the leaves.] - - Description [Converts an ADD to a BDD by replacing all - discriminants whose i-th bit is equal to 1 with 1, and all other - discriminants with 0. The i-th bit refers to the integer - representation of the leaf value. If the value is has a fractional - part, it is ignored. Repeated calls to this procedure allow one to - transform an integer-valued ADD into an array of BDDs, one for each - bit of the leaf values. Returns a pointer to the resulting BDD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd] - -******************************************************************************/ -DdNode * -Cudd_addBddIthBit( - DdManager * dd, - DdNode * f, - int bit) -{ - DdNode *res; - DdNode *index; - - index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit); - if (index == NULL) return(NULL); - cuddRef(index); - - do { - dd->reordered = 0; - res = addBddDoIthBit(dd, f, index); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd, index); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, index); - cuddDeref(res); - return(res); - -} /* end of Cudd_addBddIthBit */ - - -/**Function******************************************************************** - - Synopsis [Converts a BDD to a 0-1 ADD.] - - Description [Converts a BDD to a 0-1 ADD. Returns a pointer to the - resulting ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddPattern Cudd_addBddThreshold Cudd_addBddInterval - Cudd_addBddStrictThreshold] - -******************************************************************************/ -DdNode * -Cudd_BddToAdd( - DdManager * dd, - DdNode * B) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = ddBddToAddRecur(dd, B); - } while (dd->reordered ==1); - return(res); - -} /* end of Cudd_BddToAdd */ - - -/**Function******************************************************************** - - Synopsis [Converts an ADD to a BDD.] - - Description [Converts an ADD to a BDD by replacing all - discriminants different from 0 with 1. Returns a pointer to the - resulting BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_BddToAdd Cudd_addBddThreshold Cudd_addBddInterval - Cudd_addBddStrictThreshold] - -******************************************************************************/ -DdNode * -Cudd_addBddPattern( - DdManager * dd, - DdNode * f) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddBddDoPattern(dd, f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addBddPattern */ - - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. The orders of the - variables in the two managers may be different. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_bddTransfer( - DdManager * ddSource, - DdManager * ddDestination, - DdNode * f) -{ - DdNode *res; - do { - ddDestination->reordered = 0; - res = cuddBddTransfer(ddSource, ddDestination, f); - } while (ddDestination->reordered == 1); - return(res); - -} /* end of Cudd_bddTransfer */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddTransfer] - -******************************************************************************/ -DdNode * -cuddBddTransfer( - DdManager * ddS, - DdManager * ddD, - DdNode * f) -{ - DdNode *res; - st_table *table = NULL; - st_generator *gen = NULL; - DdNode *key, *value; - - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) goto failure; - res = cuddBddTransferRecur(ddS, ddD, f, table); - if (res != NULL) cuddRef(res); - - /* Dereference all elements in the table and dispose of the table. - ** This must be done also if res is NULL to avoid leaks in case of - ** reordering. */ - gen = st_init_gen(table); - if (gen == NULL) goto failure; - while (st_gen(gen, (char **) &key, (char **) &value)) { - Cudd_RecursiveDeref(ddD, value); - } - st_free_gen(gen); gen = NULL; - st_free_table(table); table = NULL; - - if (res != NULL) cuddDeref(res); - return(res); - -failure: - if (table != NULL) st_free_table(table); - if (gen != NULL) st_free_gen(gen); - return(NULL); - -} /* end of cuddBddTransfer */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addBddPattern.] - - Description [Performs the recursive step for Cudd_addBddPattern. Returns a - pointer to the resulting BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddAddBddDoPattern( - DdManager * dd, - DdNode * f) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - return(Cudd_NotCond(DD_ONE(dd),f == DD_ZERO(dd))); - } - - /* Check cache. */ - res = cuddCacheLookup1(dd,Cudd_addBddPattern,f); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = cuddAddBddDoPattern(dd,fv); - if (T == NULL) return(NULL); - cuddRef(T); - - E = cuddAddBddDoPattern(dd,fvn); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - if (Cudd_IsComplement(T)) { - res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert1(dd,Cudd_addBddPattern,f,res); - - return(res); - -} /* end of cuddAddBddDoPattern */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addBddThreshold.] - - Description [Performs the recursive step for Cudd_addBddThreshold. - Returns a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [addBddDoStrictThreshold] - -******************************************************************************/ -static DdNode * -addBddDoThreshold( - DdManager * dd, - DdNode * f, - DdNode * val) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(val))); - } - - /* Check cache. */ - res = cuddCacheLookup2(dd,addBddDoThreshold,f,val); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = addBddDoThreshold(dd,fv,val); - if (T == NULL) return(NULL); - cuddRef(T); - - E = addBddDoThreshold(dd,fvn,val); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - if (Cudd_IsComplement(T)) { - res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert2(dd,addBddDoThreshold,f,val,res); - - return(res); - -} /* end of addBddDoThreshold */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addBddStrictThreshold.] - - Description [Performs the recursive step for Cudd_addBddStrictThreshold. - Returns a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [addBddDoThreshold] - -******************************************************************************/ -static DdNode * -addBddDoStrictThreshold( - DdManager * dd, - DdNode * f, - DdNode * val) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - return(Cudd_NotCond(DD_ONE(dd),cuddV(f) <= cuddV(val))); - } - - /* Check cache. */ - res = cuddCacheLookup2(dd,addBddDoStrictThreshold,f,val); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = addBddDoStrictThreshold(dd,fv,val); - if (T == NULL) return(NULL); - cuddRef(T); - - E = addBddDoStrictThreshold(dd,fvn,val); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - if (Cudd_IsComplement(T)) { - res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert2(dd,addBddDoStrictThreshold,f,val,res); - - return(res); - -} /* end of addBddDoStrictThreshold */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addBddInterval.] - - Description [Performs the recursive step for Cudd_addBddInterval. - Returns a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [addBddDoThreshold addBddDoStrictThreshold] - -******************************************************************************/ -static DdNode * -addBddDoInterval( - DdManager * dd, - DdNode * f, - DdNode * l, - DdNode * u) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(l) || cuddV(f) > cuddV(u))); - } - - /* Check cache. */ - res = cuddCacheLookup(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = addBddDoInterval(dd,fv,l,u); - if (T == NULL) return(NULL); - cuddRef(T); - - E = addBddDoInterval(dd,fvn,l,u); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - if (Cudd_IsComplement(T)) { - res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u,res); - - return(res); - -} /* end of addBddDoInterval */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addBddIthBit.] - - Description [Performs the recursive step for Cudd_addBddIthBit. - Returns a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -addBddDoIthBit( - DdManager * dd, - DdNode * f, - DdNode * index) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int mask, value; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - mask = 1 << ((int) cuddV(index)); - value = (int) cuddV(f); - return(Cudd_NotCond(DD_ONE(dd),(value & mask) == 0)); - } - - /* Check cache. */ - res = cuddCacheLookup2(dd,addBddDoIthBit,f,index); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = addBddDoIthBit(dd,fv,index); - if (T == NULL) return(NULL); - cuddRef(T); - - E = addBddDoIthBit(dd,fvn,index); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - if (Cudd_IsComplement(T)) { - res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert2(dd,addBddDoIthBit,f,index,res); - - return(res); - -} /* end of addBddDoIthBit */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_BddToAdd.] - - Description [Performs the recursive step for Cudd_BddToAdd. Returns a - pointer to the resulting ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -ddBddToAddRecur( - DdManager * dd, - DdNode * B) -{ - DdNode *one; - DdNode *res, *res1, *T, *E, *Bt, *Be; - int complement = 0; - - statLine(dd); - one = DD_ONE(dd); - - if (Cudd_IsConstant(B)) { - if (B == one) { - res = one; - } else { - res = DD_ZERO(dd); - } - return(res); - } - /* Check visited table */ - res = cuddCacheLookup1(dd,ddBddToAddRecur,B); - if (res != NULL) return(res); - - if (Cudd_IsComplement(B)) { - complement = 1; - Bt = cuddT(Cudd_Regular(B)); - Be = cuddE(Cudd_Regular(B)); - } else { - Bt = cuddT(B); - Be = cuddE(B); - } - - T = ddBddToAddRecur(dd, Bt); - if (T == NULL) return(NULL); - cuddRef(T); - - E = ddBddToAddRecur(dd, Be); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - - /* No need to check for T == E, because it is guaranteed not to happen. */ - res = cuddUniqueInter(dd, (int) Cudd_Regular(B)->index, T, E); - if (res == NULL) { - Cudd_RecursiveDeref(dd ,T); - Cudd_RecursiveDeref(dd ,E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - if (complement) { - cuddRef(res); - res1 = cuddAddCmplRecur(dd, res); - if (res1 == NULL) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - cuddRef(res1); - Cudd_RecursiveDeref(dd, res); - res = res1; - cuddDeref(res); - } - - /* Store result. */ - cuddCacheInsert1(dd,ddBddToAddRecur,B,res); - - return(res); - -} /* end of ddBddToAddRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddTransfer.] - - Description [Performs the recursive step of Cudd_bddTransfer. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddBddTransfer] - -******************************************************************************/ -static DdNode * -cuddBddTransferRecur( - DdManager * ddS, - DdManager * ddD, - DdNode * f, - st_table * table) -{ - DdNode *ft, *fe, *t, *e, *var, *res; - DdNode *one, *zero; - int index; - int comple = 0; - - statLine(ddD); - one = DD_ONE(ddD); - comple = Cudd_IsComplement(f); - - /* Trivial cases. */ - if (Cudd_IsConstant(f)) return(Cudd_NotCond(one, comple)); - - /* Make canonical to increase the utilization of the cache. */ - f = Cudd_NotCond(f,comple); - /* Now f is a regular pointer to a non-constant node. */ - - /* Check the cache. */ - if(st_lookup(table, (char *)f, (char **) &res)) - return(Cudd_NotCond(res,comple)); - - /* Recursive step. */ - index = f->index; - ft = cuddT(f); fe = cuddE(f); - - t = cuddBddTransferRecur(ddS, ddD, ft, table); - if (t == NULL) { - return(NULL); - } - cuddRef(t); - - e = cuddBddTransferRecur(ddS, ddD, fe, table); - if (e == NULL) { - Cudd_RecursiveDeref(ddD, t); - return(NULL); - } - cuddRef(e); - - zero = Cudd_Not(one); - var = cuddUniqueInter(ddD,index,one,zero); - if (var == NULL) { - Cudd_RecursiveDeref(ddD, t); - Cudd_RecursiveDeref(ddD, e); - return(NULL); - } - res = cuddBddIteRecur(ddD,var,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(ddD, t); - Cudd_RecursiveDeref(ddD, e); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(ddD, t); - Cudd_RecursiveDeref(ddD, e); - - if (st_add_direct(table, (char *) f, (char *) res) == ST_OUT_OF_MEM) { - Cudd_RecursiveDeref(ddD, res); - return(NULL); - } - return(Cudd_NotCond(res,comple)); - -} /* end of cuddBddTransferRecur */ - diff --git a/src/bdd/cudd/cuddCache.c b/src/bdd/cudd/cuddCache.c deleted file mode 100644 index d9e40921..00000000 --- a/src/bdd/cudd/cuddCache.c +++ /dev/null @@ -1,1023 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddCache.c] - - PackageName [cudd] - - Synopsis [Functions for cache insertion and lookup.] - - Description [Internal procedures included in this module: - <ul> - <li> cuddInitCache() - <li> cuddCacheInsert() - <li> cuddCacheInsert2() - <li> cuddCacheLookup() - <li> cuddCacheLookupZdd() - <li> cuddCacheLookup2() - <li> cuddCacheLookup2Zdd() - <li> cuddConstantLookup() - <li> cuddCacheProfile() - <li> cuddCacheResize() - <li> cuddCacheFlush() - <li> cuddComputeFloorLog2() - </ul> - Static procedures included in this module: - <ul> - </ul> ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#ifdef DD_CACHE_PROFILE -#define DD_HYSTO_BINS 8 -#endif - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddCache.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Initializes the computed table.] - - Description [Initializes the computed table. It is called by - Cudd_Init. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Init] - -******************************************************************************/ -int -cuddInitCache( - DdManager * unique /* unique table */, - unsigned int cacheSize /* initial size of the cache */, - unsigned int maxCacheSize /* cache size beyond which no resizing occurs */) -{ - int i; - unsigned int logSize; -#ifndef DD_CACHE_PROFILE - DdNodePtr *mem; - ptruint offset; -#endif - - /* Round cacheSize to largest power of 2 not greater than the requested - ** initial cache size. */ - logSize = cuddComputeFloorLog2(ddMax(cacheSize,unique->slots/2)); - cacheSize = 1 << logSize; - unique->acache = ALLOC(DdCache,cacheSize+1); - if (unique->acache == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - /* If the size of the cache entry is a power of 2, we want to - ** enforce alignment to that power of two. This happens when - ** DD_CACHE_PROFILE is not defined. */ -#ifdef DD_CACHE_PROFILE - unique->cache = unique->acache; - unique->memused += (cacheSize) * sizeof(DdCache); -#else - mem = (DdNodePtr *) unique->acache; - offset = (ptruint) mem & (sizeof(DdCache) - 1); - mem += (sizeof(DdCache) - offset) / sizeof(DdNodePtr); - unique->cache = (DdCache *) mem; - assert(((ptruint) unique->cache & (sizeof(DdCache) - 1)) == 0); - unique->memused += (cacheSize+1) * sizeof(DdCache); -#endif - unique->cacheSlots = cacheSize; - unique->cacheShift = sizeof(int) * 8 - logSize; - unique->maxCacheHard = maxCacheSize; - /* If cacheSlack is non-negative, we can resize. */ - unique->cacheSlack = (int) ddMin(maxCacheSize, - DD_MAX_CACHE_TO_SLOTS_RATIO*unique->slots) - - 2 * (int) cacheSize; - Cudd_SetMinHit(unique,DD_MIN_HIT); - /* Initialize to avoid division by 0 and immediate resizing. */ - unique->cacheMisses = (double) (int) (cacheSize * unique->minHit + 1); - unique->cacheHits = 0; - unique->totCachehits = 0; - /* The sum of cacheMisses and totCacheMisses is always correct, - ** even though cacheMisses is larger than it should for the reasons - ** explained above. */ - unique->totCacheMisses = -unique->cacheMisses; - unique->cachecollisions = 0; - unique->cacheinserts = 0; - unique->cacheLastInserts = 0; - unique->cachedeletions = 0; - - /* Initialize the cache */ - for (i = 0; (unsigned) i < cacheSize; i++) { - unique->cache[i].h = 0; /* unused slots */ - unique->cache[i].data = NULL; /* invalid entry */ -#ifdef DD_CACHE_PROFILE - unique->cache[i].count = 0; -#endif - } - - return(1); - -} /* end of cuddInitCache */ - - -/**Function******************************************************************** - - Synopsis [Inserts a result in the cache.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddCacheInsert2 cuddCacheInsert1] - -******************************************************************************/ -void -cuddCacheInsert( - DdManager * table, - ptruint op, - DdNode * f, - DdNode * g, - DdNode * h, - DdNode * data) -{ - int posn; - register DdCache *entry; - ptruint uf, ug, uh; - - uf = (ptruint) f | (op & 0xe); - ug = (ptruint) g | (op >> 4); - uh = (ptruint) h; - - posn = ddCHash2(uh,uf,ug,table->cacheShift); - entry = &table->cache[posn]; - - table->cachecollisions += entry->data != NULL; - table->cacheinserts++; - - entry->f = (DdNode *) uf; - entry->g = (DdNode *) ug; - entry->h = uh; - entry->data = data; -#ifdef DD_CACHE_PROFILE - entry->count++; -#endif - -} /* end of cuddCacheInsert */ - - -/**Function******************************************************************** - - Synopsis [Inserts a result in the cache for a function with two - operands.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddCacheInsert cuddCacheInsert1] - -******************************************************************************/ -void -cuddCacheInsert2( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *, DdNode *), - DdNode * f, - DdNode * g, - DdNode * data) -{ - int posn; - register DdCache *entry; - - posn = ddCHash2(op,f,g,table->cacheShift); - entry = &table->cache[posn]; - - if (entry->data != NULL) { - table->cachecollisions++; - } - table->cacheinserts++; - - entry->f = f; - entry->g = g; - entry->h = (ptruint) op; - entry->data = data; -#ifdef DD_CACHE_PROFILE - entry->count++; -#endif - -} /* end of cuddCacheInsert2 */ - - -/**Function******************************************************************** - - Synopsis [Inserts a result in the cache for a function with two - operands.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddCacheInsert cuddCacheInsert2] - -******************************************************************************/ -void -cuddCacheInsert1( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *), - DdNode * f, - DdNode * data) -{ - int posn; - register DdCache *entry; - - posn = ddCHash2(op,f,f,table->cacheShift); - entry = &table->cache[posn]; - - if (entry->data != NULL) { - table->cachecollisions++; - } - table->cacheinserts++; - - entry->f = f; - entry->g = f; - entry->h = (ptruint) op; - entry->data = data; -#ifdef DD_CACHE_PROFILE - entry->count++; -#endif - -} /* end of cuddCacheInsert1 */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f, - g, and h.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookup2 cuddCacheLookup1] - -******************************************************************************/ -DdNode * -cuddCacheLookup( - DdManager * table, - ptruint op, - DdNode * f, - DdNode * g, - DdNode * h) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - ptruint uf, ug, uh; - - uf = (ptruint) f | (op & 0xe); - ug = (ptruint) g | (op >> 4); - uh = (ptruint) h; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(uh,uf,ug,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && - en->h==uh) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaim(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookup */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f, - g, and h.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookup2Zdd cuddCacheLookup1Zdd] - -******************************************************************************/ -DdNode * -cuddCacheLookupZdd( - DdManager * table, - ptruint op, - DdNode * f, - DdNode * g, - DdNode * h) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - ptruint uf, ug, uh; - - uf = (ptruint) f | (op & 0xe); - ug = (ptruint) g | (op >> 4); - uh = (ptruint) h; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(uh,uf,ug,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && - en->h==uh) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaimZdd(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookupZdd */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f - and g.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookup cuddCacheLookup1] - -******************************************************************************/ -DdNode * -cuddCacheLookup2( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *, DdNode *), - DdNode * f, - DdNode * g) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(op,f,g,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaim(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookup2 */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookup cuddCacheLookup2] - -******************************************************************************/ -DdNode * -cuddCacheLookup1( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *), - DdNode * f) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(op,f,f,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==f && en->h==(ptruint)op) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaim(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookup1 */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f - and g.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookupZdd cuddCacheLookup1Zdd] - -******************************************************************************/ -DdNode * -cuddCacheLookup2Zdd( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *, DdNode *), - DdNode * f, - DdNode * g) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(op,f,g,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaimZdd(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookup2Zdd */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookupZdd cuddCacheLookup2Zdd] - -******************************************************************************/ -DdNode * -cuddCacheLookup1Zdd( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *), - DdNode * f) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(op,f,f,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==f && en->h==(ptruint)op) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaimZdd(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookup1Zdd */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f, - g, and h.] - - Description [Looks up in the cache for the result of op applied to f, - g, and h. Assumes that the calling procedure (e.g., - Cudd_bddIteConstant) is only interested in whether the result is - constant or not. Returns the result if found (possibly - DD_NON_CONSTANT); otherwise it returns NULL.] - - SideEffects [None] - - SeeAlso [cuddCacheLookup] - -******************************************************************************/ -DdNode * -cuddConstantLookup( - DdManager * table, - ptruint op, - DdNode * f, - DdNode * g, - DdNode * h) -{ - int posn; - DdCache *en,*cache; - ptruint uf, ug, uh; - - uf = (ptruint) f | (op & 0xe); - ug = (ptruint) g | (op >> 4); - uh = (ptruint) h; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - posn = ddCHash2(uh,uf,ug,table->cacheShift); - en = &cache[posn]; - - /* We do not reclaim here because the result should not be - * referenced, but only tested for being a constant. - */ - if (en->data != NULL && - en->f == (DdNodePtr)uf && en->g == (DdNodePtr)ug && en->h == uh) { - table->cacheHits++; - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddConstantLookup */ - - -/**Function******************************************************************** - - Synopsis [Computes and prints a profile of the cache usage.] - - Description [Computes and prints a profile of the cache usage. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddCacheProfile( - DdManager * table, - FILE * fp) -{ - DdCache *cache = table->cache; - int slots = table->cacheSlots; - int nzeroes = 0; - int i, retval; - double exUsed; - -#ifdef DD_CACHE_PROFILE - double count, mean, meansq, stddev, expected; - long max, min; - int imax, imin; - double *hystogramQ, *hystogramR; /* histograms by quotient and remainder */ - int nbins = DD_HYSTO_BINS; - int bin; - long thiscount; - double totalcount, exStddev; - - meansq = mean = expected = 0.0; - max = min = (long) cache[0].count; - imax = imin = 0; - totalcount = 0.0; - - hystogramQ = ALLOC(double, nbins); - if (hystogramQ == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - hystogramR = ALLOC(double, nbins); - if (hystogramR == NULL) { - FREE(hystogramQ); - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < nbins; i++) { - hystogramQ[i] = 0; - hystogramR[i] = 0; - } - - for (i = 0; i < slots; i++) { - thiscount = (long) cache[i].count; - if (thiscount > max) { - max = thiscount; - imax = i; - } - if (thiscount < min) { - min = thiscount; - imin = i; - } - if (thiscount == 0) { - nzeroes++; - } - count = (double) thiscount; - mean += count; - meansq += count * count; - totalcount += count; - expected += count * (double) i; - bin = (i * nbins) / slots; - hystogramQ[bin] += (double) thiscount; - bin = i % nbins; - hystogramR[bin] += (double) thiscount; - } - mean /= (double) slots; - meansq /= (double) slots; - - /* Compute the standard deviation from both the data and the - ** theoretical model for a random distribution. */ - stddev = sqrt(meansq - mean*mean); - exStddev = sqrt((1 - 1/(double) slots) * totalcount / (double) slots); - - retval = fprintf(fp,"Cache average accesses = %g\n", mean); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache access standard deviation = %g ", stddev); - if (retval == EOF) return(0); - retval = fprintf(fp,"(expected = %g)\n", exStddev); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin); - if (retval == EOF) return(0); - exUsed = 100.0 * (1.0 - exp(-totalcount / (double) slots)); - retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n", - 100.0 - (double) nzeroes * 100.0 / (double) slots, - exUsed); - if (retval == EOF) return(0); - - if (totalcount > 0) { - expected /= totalcount; - retval = fprintf(fp,"Cache access hystogram for %d bins", nbins); - if (retval == EOF) return(0); - retval = fprintf(fp," (expected bin value = %g)\nBy quotient:", - expected); - if (retval == EOF) return(0); - for (i = nbins - 1; i>=0; i--) { - retval = fprintf(fp," %.0f", hystogramQ[i]); - if (retval == EOF) return(0); - } - retval = fprintf(fp,"\nBy residue: "); - if (retval == EOF) return(0); - for (i = nbins - 1; i>=0; i--) { - retval = fprintf(fp," %.0f", hystogramR[i]); - if (retval == EOF) return(0); - } - retval = fprintf(fp,"\n"); - if (retval == EOF) return(0); - } - - FREE(hystogramQ); - FREE(hystogramR); -#else - for (i = 0; i < slots; i++) { - nzeroes += cache[i].h == 0; - } - exUsed = 100.0 * - (1.0 - exp(-(table->cacheinserts - table->cacheLastInserts) / - (double) slots)); - retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n", - 100.0 - (double) nzeroes * 100.0 / (double) slots, - exUsed); - if (retval == EOF) return(0); -#endif - return(1); - -} /* end of cuddCacheProfile */ - - -/**Function******************************************************************** - - Synopsis [Resizes the cache.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddCacheResize( - DdManager * table) -{ - DdCache *cache, *oldcache, *oldacache, *entry, *old; - int i; - int posn, shift; - unsigned int slots, oldslots; - double offset; - int moved = 0; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); -#ifndef DD_CACHE_PROFILE - ptruint misalignment; - DdNodePtr *mem; -#endif - - oldcache = table->cache; - oldacache = table->acache; - oldslots = table->cacheSlots; - slots = table->cacheSlots = oldslots << 1; - -#ifdef DD_VERBOSE - (void) fprintf(table->err,"Resizing the cache from %d to %d entries\n", - oldslots, slots); - (void) fprintf(table->err, - "\thits = %g\tmisses = %g\thit ratio = %5.3f\n", - table->cacheHits, table->cacheMisses, - table->cacheHits / (table->cacheHits + table->cacheMisses)); -#endif - - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - table->acache = cache = ALLOC(DdCache,slots+1); - MMoutOfMemory = saveHandler; - /* If we fail to allocate the new table we just give up. */ - if (cache == NULL) { -#ifdef DD_VERBOSE - (void) fprintf(table->err,"Resizing failed. Giving up.\n"); -#endif - table->cacheSlots = oldslots; - table->acache = oldacache; - /* Do not try to resize again. */ - table->maxCacheHard = oldslots - 1; - table->cacheSlack = - (oldslots + 1); - return; - } - /* If the size of the cache entry is a power of 2, we want to - ** enforce alignment to that power of two. This happens when - ** DD_CACHE_PROFILE is not defined. */ -#ifdef DD_CACHE_PROFILE - table->cache = cache; -#else - mem = (DdNodePtr *) cache; - misalignment = (ptruint) mem & (sizeof(DdCache) - 1); - mem += (sizeof(DdCache) - misalignment) / sizeof(DdNodePtr); - table->cache = cache = (DdCache *) mem; - assert(((ptruint) table->cache & (sizeof(DdCache) - 1)) == 0); -#endif - shift = --(table->cacheShift); - table->memused += (slots - oldslots) * sizeof(DdCache); - table->cacheSlack -= slots; /* need these many slots to double again */ - - /* Clear new cache. */ - for (i = 0; (unsigned) i < slots; i++) { - cache[i].data = NULL; - cache[i].h = 0; -#ifdef DD_CACHE_PROFILE - cache[i].count = 0; -#endif - } - - /* Copy from old cache to new one. */ - for (i = 0; (unsigned) i < oldslots; i++) { - old = &oldcache[i]; - if (old->data != NULL) { - posn = ddCHash2(old->h,old->f,old->g,shift); - entry = &cache[posn]; - entry->f = old->f; - entry->g = old->g; - entry->h = old->h; - entry->data = old->data; -#ifdef DD_CACHE_PROFILE - entry->count = 1; -#endif - moved++; - } - } - - FREE(oldacache); - - /* Reinitialize measurements so as to avoid division by 0 and - ** immediate resizing. - */ - offset = (double) (int) (slots * table->minHit + 1); - table->totCacheMisses += table->cacheMisses - offset; - table->cacheMisses = offset; - table->totCachehits += table->cacheHits; - table->cacheHits = 0; - table->cacheLastInserts = table->cacheinserts - (double) moved; - -} /* end of cuddCacheResize */ - - -/**Function******************************************************************** - - Synopsis [Flushes the cache.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddCacheFlush( - DdManager * table) -{ - int i, slots; - DdCache *cache; - - slots = table->cacheSlots; - cache = table->cache; - for (i = 0; i < slots; i++) { - table->cachedeletions += cache[i].data != NULL; - cache[i].data = NULL; - } - table->cacheLastInserts = table->cacheinserts; - - return; - -} /* end of cuddCacheFlush */ - - -/**Function******************************************************************** - - Synopsis [Returns the floor of the logarithm to the base 2.] - - Description [Returns the floor of the logarithm to the base 2. - The input value is assumed to be greater than 0.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddComputeFloorLog2( - unsigned int value) -{ - int floorLog = 0; -#ifdef DD_DEBUG - assert(value > 0); -#endif - while (value > 1) { - floorLog++; - value >>= 1; - } - return(floorLog); - -} /* end of cuddComputeFloorLog2 */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddCheck.c b/src/bdd/cudd/cuddCheck.c deleted file mode 100644 index aec8246d..00000000 --- a/src/bdd/cudd/cuddCheck.c +++ /dev/null @@ -1,851 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddCheck.c] - - PackageName [cudd] - - Synopsis [Functions to check consistency of data structures.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_DebugCheck() - <li> Cudd_CheckKeys() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddHeapProfile() - <li> cuddPrintNode() - <li> cuddPrintVarGroups() - </ul> - Static procedures included in this module: - <ul> - <li> debugFindParent() - </ul> - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddCheck.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void debugFindParent ARGS((DdManager *table, DdNode *node)); -#if 0 -static void debugCheckParent ARGS((DdManager *table, DdNode *node)); -#endif - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Checks for inconsistencies in the DD heap.] - - Description [Checks for inconsistencies in the DD heap: - <ul> - <li> node has illegal index - <li> live node has dead children - <li> node has illegal Then or Else pointers - <li> BDD/ADD node has identical children - <li> ZDD node has zero then child - <li> wrong number of total nodes - <li> wrong number of dead nodes - <li> ref count error at node - </ul> - Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is - not enough memory; 1 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_CheckKeys] - -******************************************************************************/ -int -Cudd_DebugCheck( - DdManager * table) -{ - unsigned int i; - int j,count; - int slots; - DdNodePtr *nodelist; - DdNode *f; - DdNode *sentinel = &(table->sentinel); - st_table *edgeTable; /* stores internal ref count for each node */ - st_generator *gen; - int flag = 0; - int totalNode; - int deadNode; - int index; - - - edgeTable = st_init_table(st_ptrcmp,st_ptrhash); - if (edgeTable == NULL) return(CUDD_OUT_OF_MEM); - - /* Check the BDD/ADD subtables. */ - for (i = 0; i < (unsigned) table->size; i++) { - index = table->invperm[i]; - if (i != (unsigned) table->perm[index]) { - (void) fprintf(table->err, - "Permutation corrupted: invperm[%d] = %d\t perm[%d] = %d\n", - i, index, index, table->perm[index]); - } - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - - totalNode = 0; - deadNode = 0; - for (j = 0; j < slots; j++) { /* for each subtable slot */ - f = nodelist[j]; - while (f != sentinel) { - totalNode++; - if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) { - if ((int) f->index != index) { - (void) fprintf(table->err, - "Error: node has illegal index\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if ((unsigned) cuddI(table,cuddT(f)->index) <= i || - (unsigned) cuddI(table,Cudd_Regular(cuddE(f))->index) - <= i) { - (void) fprintf(table->err, - "Error: node has illegal children\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if (Cudd_Regular(cuddT(f)) != cuddT(f)) { - (void) fprintf(table->err, - "Error: node has illegal form\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if (cuddT(f) == cuddE(f)) { - (void) fprintf(table->err, - "Error: node has identical children\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if (cuddT(f)->ref == 0 || Cudd_Regular(cuddE(f))->ref == 0) { - (void) fprintf(table->err, - "Error: live node has dead children\n"); - cuddPrintNode(f,table->err); - flag =1; - } - /* Increment the internal reference count for the - ** then child of the current node. - */ - if (st_lookup(edgeTable,(char *)cuddT(f),(char **)&count)) { - count++; - } else { - count = 1; - } - if (st_insert(edgeTable,(char *)cuddT(f), - (char *)(long)count) == ST_OUT_OF_MEM) { - st_free_table(edgeTable); - return(CUDD_OUT_OF_MEM); - } - - /* Increment the internal reference count for the - ** else child of the current node. - */ - if (st_lookup(edgeTable,(char *)Cudd_Regular(cuddE(f)),(char **)&count)) { - count++; - } else { - count = 1; - } - if (st_insert(edgeTable,(char *)Cudd_Regular(cuddE(f)), - (char *)(long)count) == ST_OUT_OF_MEM) { - st_free_table(edgeTable); - return(CUDD_OUT_OF_MEM); - } - } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) { - deadNode++; -#if 0 - debugCheckParent(table,f); -#endif - } else { - fprintf(table->err, - "Error: node has illegal Then or Else pointers\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - - f = f->next; - } /* for each element of the collision list */ - } /* for each subtable slot */ - - if ((unsigned) totalNode != table->subtables[i].keys) { - fprintf(table->err,"Error: wrong number of total nodes\n"); - flag = 1; - } - if ((unsigned) deadNode != table->subtables[i].dead) { - fprintf(table->err,"Error: wrong number of dead nodes\n"); - flag = 1; - } - } /* for each BDD/ADD subtable */ - - /* Check the ZDD subtables. */ - for (i = 0; i < (unsigned) table->sizeZ; i++) { - index = table->invpermZ[i]; - if (i != (unsigned) table->permZ[index]) { - (void) fprintf(table->err, - "Permutation corrupted: invpermZ[%d] = %d\t permZ[%d] = %d in ZDD\n", - i, index, index, table->permZ[index]); - } - nodelist = table->subtableZ[i].nodelist; - slots = table->subtableZ[i].slots; - - totalNode = 0; - deadNode = 0; - for (j = 0; j < slots; j++) { /* for each subtable slot */ - f = nodelist[j]; - while (f != NULL) { - totalNode++; - if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) { - if ((int) f->index != index) { - (void) fprintf(table->err, - "Error: ZDD node has illegal index\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if (Cudd_IsComplement(cuddT(f)) || - Cudd_IsComplement(cuddE(f))) { - (void) fprintf(table->err, - "Error: ZDD node has complemented children\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if ((unsigned) cuddIZ(table,cuddT(f)->index) <= i || - (unsigned) cuddIZ(table,cuddE(f)->index) <= i) { - (void) fprintf(table->err, - "Error: ZDD node has illegal children\n"); - cuddPrintNode(f,table->err); - cuddPrintNode(cuddT(f),table->err); - cuddPrintNode(cuddE(f),table->err); - flag = 1; - } - if (cuddT(f) == DD_ZERO(table)) { - (void) fprintf(table->err, - "Error: ZDD node has zero then child\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if (cuddT(f)->ref == 0 || cuddE(f)->ref == 0) { - (void) fprintf(table->err, - "Error: ZDD live node has dead children\n"); - cuddPrintNode(f,table->err); - flag =1; - } - /* Increment the internal reference count for the - ** then child of the current node. - */ - if (st_lookup(edgeTable,(char *)cuddT(f),(char **)&count)) { - count++; - } else { - count = 1; - } - if (st_insert(edgeTable,(char *)cuddT(f), - (char *)(long)count) == ST_OUT_OF_MEM) { - st_free_table(edgeTable); - return(CUDD_OUT_OF_MEM); - } - - /* Increment the internal reference count for the - ** else child of the current node. - */ - if (st_lookup(edgeTable,(char *)cuddE(f),(char **)&count)) { - count++; - } else { - count = 1; - } - if (st_insert(edgeTable,(char *)cuddE(f), - (char *)(long)count) == ST_OUT_OF_MEM) { - st_free_table(edgeTable); - table->errorCode = CUDD_MEMORY_OUT; - return(CUDD_OUT_OF_MEM); - } - } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) { - deadNode++; -#if 0 - debugCheckParent(table,f); -#endif - } else { - fprintf(table->err, - "Error: ZDD node has illegal Then or Else pointers\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - - f = f->next; - } /* for each element of the collision list */ - } /* for each subtable slot */ - - if ((unsigned) totalNode != table->subtableZ[i].keys) { - fprintf(table->err, - "Error: wrong number of total nodes in ZDD\n"); - flag = 1; - } - if ((unsigned) deadNode != table->subtableZ[i].dead) { - fprintf(table->err, - "Error: wrong number of dead nodes in ZDD\n"); - flag = 1; - } - } /* for each ZDD subtable */ - - /* Check the constant table. */ - nodelist = table->constants.nodelist; - slots = table->constants.slots; - - totalNode = 0; - deadNode = 0; - for (j = 0; j < slots; j++) { - f = nodelist[j]; - while (f != NULL) { - totalNode++; - if (f->ref != 0) { - if (f->index != CUDD_CONST_INDEX) { - fprintf(table->err,"Error: node has illegal index\n"); -#if SIZEOF_VOID_P == 8 - fprintf(table->err, - " node 0x%lx, id = %d, ref = %d, value = %g\n", - (unsigned long)f,f->index,f->ref,cuddV(f)); -#else - fprintf(table->err, - " node 0x%x, id = %d, ref = %d, value = %g\n", - (unsigned)f,f->index,f->ref,cuddV(f)); -#endif - flag = 1; - } - } else { - deadNode++; - } - f = f->next; - } - } - if ((unsigned) totalNode != table->constants.keys) { - (void) fprintf(table->err, - "Error: wrong number of total nodes in constants\n"); - flag = 1; - } - if ((unsigned) deadNode != table->constants.dead) { - (void) fprintf(table->err, - "Error: wrong number of dead nodes in constants\n"); - flag = 1; - } - gen = st_init_gen(edgeTable); - while (st_gen(gen,(char **)&f,(char **)&count)) { - if (count > (int)(f->ref) && f->ref != DD_MAXREF) { -#if SIZEOF_VOID_P == 8 - fprintf(table->err,"ref count error at node 0x%lx, count = %d, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n",(unsigned long)f,count,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f)); -#else - fprintf(table->err,"ref count error at node 0x%x, count = %d, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",(unsigned)f,count,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f)); -#endif - debugFindParent(table,f); - flag = 1; - } - } - st_free_gen(gen); - st_free_table(edgeTable); - - return (flag); - -} /* end of Cudd_DebugCheck */ - - -/**Function******************************************************************** - - Synopsis [Checks for several conditions that should not occur.] - - Description [Checks for the following conditions: - <ul> - <li>Wrong sizes of subtables. - <li>Wrong number of keys found in unique subtable. - <li>Wrong number of dead found in unique subtable. - <li>Wrong number of keys found in the constant table - <li>Wrong number of dead found in the constant table - <li>Wrong number of total slots found - <li>Wrong number of maximum keys found - <li>Wrong number of total dead found - </ul> - Reports the average length of non-empty lists. Returns the number of - subtables for which the number of keys is wrong.] - - SideEffects [None] - - SeeAlso [Cudd_DebugCheck] - -******************************************************************************/ -int -Cudd_CheckKeys( - DdManager * table) -{ - int size; - int i,j; - DdNodePtr *nodelist; - DdNode *node; - DdNode *sentinel = &(table->sentinel); - DdSubtable *subtable; - int keys; - int dead; - int count = 0; - int totalKeys = 0; - int totalSlots = 0; - int totalDead = 0; - int nonEmpty = 0; - unsigned int slots; - int logSlots; - int shift; - - size = table->size; - - for (i = 0; i < size; i++) { - subtable = &(table->subtables[i]); - nodelist = subtable->nodelist; - keys = subtable->keys; - dead = subtable->dead; - totalKeys += keys; - slots = subtable->slots; - shift = subtable->shift; - logSlots = sizeof(int) * 8 - shift; - if (((slots >> logSlots) << logSlots) != slots) { - (void) fprintf(table->err, - "Unique table %d is not the right power of 2\n", i); - (void) fprintf(table->err, - " slots = %u shift = %d\n", slots, shift); - } - totalSlots += slots; - totalDead += dead; - for (j = 0; (unsigned) j < slots; j++) { - node = nodelist[j]; - if (node != sentinel) { - nonEmpty++; - } - while (node != sentinel) { - keys--; - if (node->ref == 0) { - dead--; - } - node = node->next; - } - } - if (keys != 0) { - (void) fprintf(table->err, "Wrong number of keys found \ -in unique table %d (difference=%d)\n", i, keys); - count++; - } - if (dead != 0) { - (void) fprintf(table->err, "Wrong number of dead found \ -in unique table no. %d (difference=%d)\n", i, dead); - } - } /* for each BDD/ADD subtable */ - - /* Check the ZDD subtables. */ - size = table->sizeZ; - - for (i = 0; i < size; i++) { - subtable = &(table->subtableZ[i]); - nodelist = subtable->nodelist; - keys = subtable->keys; - dead = subtable->dead; - totalKeys += keys; - totalSlots += subtable->slots; - totalDead += dead; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - if (node != NULL) { - nonEmpty++; - } - while (node != NULL) { - keys--; - if (node->ref == 0) { - dead--; - } - node = node->next; - } - } - if (keys != 0) { - (void) fprintf(table->err, "Wrong number of keys found \ -in ZDD unique table no. %d (difference=%d)\n", i, keys); - count++; - } - if (dead != 0) { - (void) fprintf(table->err, "Wrong number of dead found \ -in ZDD unique table no. %d (difference=%d)\n", i, dead); - } - } /* for each ZDD subtable */ - - /* Check the constant table. */ - subtable = &(table->constants); - nodelist = subtable->nodelist; - keys = subtable->keys; - dead = subtable->dead; - totalKeys += keys; - totalSlots += subtable->slots; - totalDead += dead; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - if (node != NULL) { - nonEmpty++; - } - while (node != NULL) { - keys--; - if (node->ref == 0) { - dead--; - } - node = node->next; - } - } - if (keys != 0) { - (void) fprintf(table->err, "Wrong number of keys found \ -in the constant table (difference=%d)\n", keys); - count++; - } - if (dead != 0) { - (void) fprintf(table->err, "Wrong number of dead found \ -in the constant table (difference=%d)\n", dead); - } - if ((unsigned) totalKeys != table->keys + table->keysZ) { - (void) fprintf(table->err, "Wrong number of total keys found \ -(difference=%d)\n", totalKeys-table->keys); - } - if ((unsigned) totalSlots != table->slots) { - (void) fprintf(table->err, "Wrong number of total slots found \ -(difference=%d)\n", totalSlots-table->slots); - } - if (table->minDead != (unsigned) (table->gcFrac * table->slots)) { - (void) fprintf(table->err, "Wrong number of minimum dead found \ -(%d vs. %d)\n", table->minDead, - (unsigned) (table->gcFrac * (double) table->slots)); - } - if ((unsigned) totalDead != table->dead + table->deadZ) { - (void) fprintf(table->err, "Wrong number of total dead found \ -(difference=%d)\n", totalDead-table->dead); - } - (void)printf("Average length of non-empty lists = %g\n", - (double) table->keys / (double) nonEmpty); - - return(count); - -} /* end of Cudd_CheckKeys */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints information about the heap.] - - Description [Prints to the manager's stdout the number of live nodes for each - level of the DD heap that contains at least one live node. It also - prints a summary containing: - <ul> - <li> total number of tables; - <li> number of tables with live nodes; - <li> table with the largest number of live nodes; - <li> number of nodes in that table. - </ul> - If more than one table contains the maximum number of live nodes, - only the one of lowest index is reported. Returns 1 in case of success - and 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddHeapProfile( - DdManager * dd) -{ - int ntables = dd->size; - DdSubtable *subtables = dd->subtables; - int i, /* loop index */ - nodes, /* live nodes in i-th layer */ - retval, /* return value of fprintf */ - largest = -1, /* index of the table with most live nodes */ - maxnodes = -1, /* maximum number of live nodes in a table */ - nonempty = 0; /* number of tables with live nodes */ - - /* Print header. */ -#if SIZEOF_VOID_P == 8 - retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n", - (unsigned long) dd); -#else - retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n", - (unsigned) dd); -#endif - if (retval == EOF) return 0; - - /* Print number of live nodes for each nonempty table. */ - for (i=0; i<ntables; i++) { - nodes = subtables[i].keys - subtables[i].dead; - if (nodes) { - nonempty++; - retval = fprintf(dd->out,"%5d: %5d nodes\n", i, nodes); - if (retval == EOF) return 0; - if (nodes > maxnodes) { - maxnodes = nodes; - largest = i; - } - } - } - - nodes = dd->constants.keys - dd->constants.dead; - if (nodes) { - nonempty++; - retval = fprintf(dd->out,"const: %5d nodes\n", nodes); - if (retval == EOF) return 0; - if (nodes > maxnodes) { - maxnodes = nodes; - largest = CUDD_CONST_INDEX; - } - } - - /* Print summary. */ - retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ", - ntables+1, nonempty, largest); - if (retval == EOF) return 0; - retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes); - if (retval == EOF) return 0; - - return(1); - -} /* end of cuddHeapProfile */ - - -/**Function******************************************************************** - - Synopsis [Prints out information on a node.] - - Description [Prints out information on a node.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddPrintNode( - DdNode * f, - FILE *fp) -{ - f = Cudd_Regular(f); -#if SIZEOF_VOID_P == 8 - (void) fprintf(fp," node 0x%lx, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n",(unsigned long)f,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f)); -#else - (void) fprintf(fp," node 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",(unsigned)f,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f)); -#endif - -} /* end of cuddPrintNode */ - - - -/**Function******************************************************************** - - Synopsis [Prints the variable groups as a parenthesized list.] - - Description [Prints the variable groups as a parenthesized list. - For each group the level range that it represents is printed. After - each group, the group's flags are printed, preceded by a `|'. For - each flag (except MTR_TERMINAL) a character is printed. - <ul> - <li>F: MTR_FIXED - <li>N: MTR_NEWNODE - <li>S: MTR_SOFT - </ul> - The second argument, silent, if different from 0, causes - Cudd_PrintVarGroups to only check the syntax of the group tree.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddPrintVarGroups( - DdManager * dd /* manager */, - MtrNode * root /* root of the group tree */, - int zdd /* 0: BDD; 1: ZDD */, - int silent /* flag to check tree syntax only */) -{ - MtrNode *node; - int level; - - assert(root != NULL); - assert(root->younger == NULL || root->younger->elder == root); - assert(root->elder == NULL || root->elder->younger == root); - if (zdd) { - level = dd->permZ[root->index]; - } else { - level = dd->perm[root->index]; - } - if (!silent) (void) printf("(%d",level); - if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) { - if (!silent) (void) printf(","); - } else { - node = root->child; - while (node != NULL) { - assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size)); - assert(node->parent == root); - cuddPrintVarGroups(dd,node,zdd,silent); - node = node->younger; - } - } - if (!silent) { - (void) printf("%d", level + root->size - 1); - if (root->flags != MTR_DEFAULT) { - (void) printf("|"); - if (MTR_TEST(root,MTR_FIXED)) (void) printf("F"); - if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N"); - if (MTR_TEST(root,MTR_SOFT)) (void) printf("S"); - } - (void) printf(")"); - if (root->parent == NULL) (void) printf("\n"); - } - assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0); - return; - -} /* end of cuddPrintVarGroups */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Searches the subtables above node for its parents.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -debugFindParent( - DdManager * table, - DdNode * node) -{ - int i,j; - int slots; - DdNodePtr *nodelist; - DdNode *f; - - for (i = 0; i < cuddI(table,node->index); i++) { - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - - for (j=0;j<slots;j++) { - f = nodelist[j]; - while (f != NULL) { - if (cuddT(f) == node || Cudd_Regular(cuddE(f)) == node) { -#if SIZEOF_VOID_P == 8 - (void) fprintf(table->out,"parent is at 0x%lx, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n", - (unsigned long)f,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f)); -#else - (void) fprintf(table->out,"parent is at 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n", - (unsigned)f,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f)); -#endif - } - f = f->next; - } - } - } - -} /* end of debugFindParent */ - - -#if 0 -/**Function******************************************************************** - - Synopsis [Reports an error if a (dead) node has a non-dead parent.] - - Description [Searches all the subtables above node. Very expensive. - The same check is now implemented more efficiently in ddDebugCheck.] - - SideEffects [None] - - SeeAlso [debugFindParent] - -******************************************************************************/ -static void -debugCheckParent( - DdManager * table, - DdNode * node) -{ - int i,j; - int slots; - DdNode **nodelist,*f; - - for (i = 0; i < cuddI(table,node->index); i++) { - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - - for (j=0;j<slots;j++) { - f = nodelist[j]; - while (f != NULL) { - if ((Cudd_Regular(cuddE(f)) == node || cuddT(f) == node) && f->ref != 0) { - (void) fprintf(table->err, - "error with zero ref count\n"); - (void) fprintf(table->err,"parent is 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",f,f->index,f->ref,cuddT(f),cuddE(f)); - (void) fprintf(table->err,"child is 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",node,node->index,node->ref,cuddT(node),cuddE(node)); - } - f = f->next; - } - } - } -} -#endif diff --git a/src/bdd/cudd/cuddClip.c b/src/bdd/cudd/cuddClip.c deleted file mode 100644 index 4da296ef..00000000 --- a/src/bdd/cudd/cuddClip.c +++ /dev/null @@ -1,531 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddClip.c] - - PackageName [cudd] - - Synopsis [Clipping functions.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_bddClippingAnd() - <li> Cudd_bddClippingAndAbstract() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddBddClippingAnd() - <li> cuddBddClippingAndAbstract() - </ul> - Static procedures included in this module: - <ul> - <li> cuddBddClippingAndRecur() - <li> cuddBddClipAndAbsRecur() - </ul> - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddClip.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * cuddBddClippingAndRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, int distance, int direction)); -static DdNode * cuddBddClipAndAbsRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube, int distance, int direction)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Approximates the conjunction of two BDDs f and g.] - - Description [Approximates the conjunction of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddAnd] - -******************************************************************************/ -DdNode * -Cudd_bddClippingAnd( - DdManager * dd /* manager */, - DdNode * f /* first conjunct */, - DdNode * g /* second conjunct */, - int maxDepth /* maximum recursion depth */, - int direction /* under (0) or over (1) approximation */) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddClippingAnd(dd,f,g,maxDepth,direction); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddClippingAnd */ - - -/**Function******************************************************************** - - Synopsis [Approximates the conjunction of two BDDs f and g and - simultaneously abstracts the variables in cube.] - - Description [Approximates the conjunction of two BDDs f and g and - simultaneously abstracts the variables in cube. The variables are - existentially abstracted. Returns a pointer to the resulting BDD if - successful; NULL if the intermediate result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddAndAbstract Cudd_bddClippingAnd] - -******************************************************************************/ -DdNode * -Cudd_bddClippingAndAbstract( - DdManager * dd /* manager */, - DdNode * f /* first conjunct */, - DdNode * g /* second conjunct */, - DdNode * cube /* cube of variables to be abstracted */, - int maxDepth /* maximum recursion depth */, - int direction /* under (0) or over (1) approximation */) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddClippingAndAbstract(dd,f,g,cube,maxDepth,direction); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddClippingAndAbstract */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Approximates the conjunction of two BDDs f and g.] - - Description [Approximates the conjunction of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddClippingAnd] - -******************************************************************************/ -DdNode * -cuddBddClippingAnd( - DdManager * dd /* manager */, - DdNode * f /* first conjunct */, - DdNode * g /* second conjunct */, - int maxDepth /* maximum recursion depth */, - int direction /* under (0) or over (1) approximation */) -{ - DdNode *res; - - res = cuddBddClippingAndRecur(dd,f,g,maxDepth,direction); - - return(res); - -} /* end of cuddBddClippingAnd */ - - -/**Function******************************************************************** - - Synopsis [Approximates the conjunction of two BDDs f and g and - simultaneously abstracts the variables in cube.] - - Description [Approximates the conjunction of two BDDs f and g and - simultaneously abstracts the variables in cube. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddClippingAndAbstract] - -******************************************************************************/ -DdNode * -cuddBddClippingAndAbstract( - DdManager * dd /* manager */, - DdNode * f /* first conjunct */, - DdNode * g /* second conjunct */, - DdNode * cube /* cube of variables to be abstracted */, - int maxDepth /* maximum recursion depth */, - int direction /* under (0) or over (1) approximation */) -{ - DdNode *res; - - res = cuddBddClipAndAbsRecur(dd,f,g,cube,maxDepth,direction); - - return(res); - -} /* end of cuddBddClippingAndAbstract */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddClippingAnd.] - - Description [Implements the recursive step of Cudd_bddClippingAnd by taking - the conjunction of two BDDs. Returns a pointer to the result is - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddBddClippingAnd] - -******************************************************************************/ -static DdNode * -cuddBddClippingAndRecur( - DdManager * manager, - DdNode * f, - DdNode * g, - int distance, - int direction) -{ - DdNode *F, *ft, *fe, *G, *gt, *ge; - DdNode *one, *zero, *r, *t, *e; - unsigned int topf, topg, index; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); - if (f == g || g == one) return(f); - if (f == one) return(g); - if (distance == 0) { - /* One last attempt at returning the right result. We sort of - ** cheat by calling Cudd_bddLeq. */ - if (Cudd_bddLeq(manager,f,g)) return(f); - if (Cudd_bddLeq(manager,g,f)) return(g); - if (direction == 1) { - if (Cudd_bddLeq(manager,f,Cudd_Not(g)) || - Cudd_bddLeq(manager,g,Cudd_Not(f))) return(zero); - } - return(Cudd_NotCond(one,(direction == 0))); - } - - /* At this point f and g are not constant. */ - distance--; - - /* Check cache. Try to increase cache efficiency by sorting the - ** pointers. */ - if (f > g) { - DdNode *tmp = f; - f = g; g = tmp; - } - F = Cudd_Regular(f); - G = Cudd_Regular(g); - cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) - (direction ? Cudd_bddClippingAnd : cuddBddClippingAnd); - if (F->ref != 1 || G->ref != 1) { - r = cuddCacheLookup2(manager, cacheOp, f, g); - if (r != NULL) return(r); - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - topf = manager->perm[F->index]; - topg = manager->perm[G->index]; - - /* Compute cofactors. */ - if (topf <= topg) { - index = F->index; - ft = cuddT(F); - fe = cuddE(F); - if (Cudd_IsComplement(f)) { - ft = Cudd_Not(ft); - fe = Cudd_Not(fe); - } - } else { - index = G->index; - ft = fe = f; - } - - if (topg <= topf) { - gt = cuddT(G); - ge = cuddE(G); - if (Cudd_IsComplement(g)) { - gt = Cudd_Not(gt); - ge = Cudd_Not(ge); - } - } else { - gt = ge = g; - } - - t = cuddBddClippingAndRecur(manager, ft, gt, distance, direction); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddBddClippingAndRecur(manager, fe, ge, distance, direction); - if (e == NULL) { - Cudd_RecursiveDeref(manager, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - return(NULL); - } - } - } - cuddDeref(e); - cuddDeref(t); - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert2(manager, cacheOp, f, g, r); - return(r); - -} /* end of cuddBddClippingAndRecur */ - - -/**Function******************************************************************** - - Synopsis [Approximates the AND of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Approximates the AND of two BDDs and simultaneously - abstracts the variables in cube. The variables are existentially - abstracted. Returns a pointer to the result is successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddClippingAndAbstract] - -******************************************************************************/ -static DdNode * -cuddBddClipAndAbsRecur( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube, - int distance, - int direction) -{ - DdNode *F, *ft, *fe, *G, *gt, *ge; - DdNode *one, *zero, *r, *t, *e, *Cube; - unsigned int topf, topg, topcube, top, index; - ptruint cacheTag; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); - if (f == one && g == one) return(one); - if (cube == one) { - return(cuddBddClippingAndRecur(manager, f, g, distance, direction)); - } - if (f == one || f == g) { - return (cuddBddExistAbstractRecur(manager, g, cube)); - } - if (g == one) { - return (cuddBddExistAbstractRecur(manager, f, cube)); - } - if (distance == 0) return(Cudd_NotCond(one,(direction == 0))); - - /* At this point f, g, and cube are not constant. */ - distance--; - - /* Check cache. */ - if (f > g) { /* Try to increase cache efficiency. */ - DdNode *tmp = f; - f = g; g = tmp; - } - F = Cudd_Regular(f); - G = Cudd_Regular(g); - cacheTag = direction ? DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG : - DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG; - if (F->ref != 1 || G->ref != 1) { - r = cuddCacheLookup(manager, cacheTag, - f, g, cube); - if (r != NULL) { - return(r); - } - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - topf = manager->perm[F->index]; - topg = manager->perm[G->index]; - top = ddMin(topf, topg); - topcube = manager->perm[cube->index]; - - if (topcube < top) { - return(cuddBddClipAndAbsRecur(manager, f, g, cuddT(cube), - distance, direction)); - } - /* Now, topcube >= top. */ - - if (topf == top) { - index = F->index; - ft = cuddT(F); - fe = cuddE(F); - if (Cudd_IsComplement(f)) { - ft = Cudd_Not(ft); - fe = Cudd_Not(fe); - } - } else { - index = G->index; - ft = fe = f; - } - - if (topg == top) { - gt = cuddT(G); - ge = cuddE(G); - if (Cudd_IsComplement(g)) { - gt = Cudd_Not(gt); - ge = Cudd_Not(ge); - } - } else { - gt = ge = g; - } - - if (topcube == top) { - Cube = cuddT(cube); - } else { - Cube = cube; - } - - t = cuddBddClipAndAbsRecur(manager, ft, gt, Cube, distance, direction); - if (t == NULL) return(NULL); - - /* Special case: 1 OR anything = 1. Hence, no need to compute - ** the else branch if t is 1. - */ - if (t == one && topcube == top) { - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert(manager, cacheTag, f, g, cube, one); - return(one); - } - cuddRef(t); - - e = cuddBddClipAndAbsRecur(manager, fe, ge, Cube, distance, direction); - if (e == NULL) { - Cudd_RecursiveDeref(manager, t); - return(NULL); - } - cuddRef(e); - - if (topcube == top) { /* abstract */ - r = cuddBddClippingAndRecur(manager, Cudd_Not(t), Cudd_Not(e), - distance, (direction == 0)); - if (r == NULL) { - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - return(NULL); - } - r = Cudd_Not(r); - cuddRef(r); - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - cuddDeref(r); - } else if (t == e) { - r = t; - cuddDeref(t); - cuddDeref(e); - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - return(NULL); - } - } - cuddDeref(e); - cuddDeref(t); - } - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert(manager, cacheTag, f, g, cube, r); - return (r); - -} /* end of cuddBddClipAndAbsRecur */ - diff --git a/src/bdd/cudd/cuddCof.c b/src/bdd/cudd/cuddCof.c deleted file mode 100644 index f79e3f91..00000000 --- a/src/bdd/cudd/cuddCof.c +++ /dev/null @@ -1,300 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddCof.c] - - PackageName [cudd] - - Synopsis [Cofactoring functions.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_Cofactor() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddGetBranches() - <li> cuddCheckCube() - <li> cuddCofactorRecur() - </ul> - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddCof.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the cofactor of f with respect to g.] - - Description [Computes the cofactor of f with respect to g; g must be - the BDD or the ADD of a cube. Returns a pointer to the cofactor if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain Cudd_bddRestrict] - -******************************************************************************/ -DdNode * -Cudd_Cofactor( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res,*zero; - - zero = Cudd_Not(DD_ONE(dd)); - if (g == zero || g == DD_ZERO(dd)) { - (void) fprintf(dd->err,"Cudd_Cofactor: Invalid restriction 1\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - do { - dd->reordered = 0; - res = cuddCofactorRecur(dd,f,g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_Cofactor */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the children of g.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddGetBranches( - DdNode * g, - DdNode ** g1, - DdNode ** g0) -{ - DdNode *G = Cudd_Regular(g); - - *g1 = cuddT(G); - *g0 = cuddE(G); - if (Cudd_IsComplement(g)) { - *g1 = Cudd_Not(*g1); - *g0 = Cudd_Not(*g0); - } - -} /* end of cuddGetBranches */ - - -/**Function******************************************************************** - - Synopsis [Checks whether g is the BDD of a cube.] - - Description [Checks whether g is the BDD of a cube. Returns 1 in case - of success; 0 otherwise. The constant 1 is a valid cube, but all other - constant functions cause cuddCheckCube to return 0.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddCheckCube( - DdManager * dd, - DdNode * g) -{ - DdNode *g1,*g0,*one,*zero; - - one = DD_ONE(dd); - if (g == one) return(1); - if (Cudd_IsConstant(g)) return(0); - - zero = Cudd_Not(one); - cuddGetBranches(g,&g1,&g0); - - if (g0 == zero) { - return(cuddCheckCube(dd, g1)); - } - if (g1 == zero) { - return(cuddCheckCube(dd, g0)); - } - return(0); - -} /* end of cuddCheckCube */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_Cofactor.] - - Description [Performs the recursive step of Cudd_Cofactor. Returns a - pointer to the cofactor if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Cofactor] - -******************************************************************************/ -DdNode * -cuddCofactorRecur( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r; - unsigned int topf,topg; - int comple; - - statLine(dd); - F = Cudd_Regular(f); - if (cuddIsConstant(F)) return(f); - - one = DD_ONE(dd); - - /* The invariant g != 0 is true on entry to this procedure and is - ** recursively maintained by it. Therefore it suffices to test g - ** against one to make sure it is not constant. - */ - if (g == one) return(f); - /* From now on, f and g are known not to be constants. */ - - comple = f != F; - r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - topf = dd->perm[F->index]; - G = Cudd_Regular(g); - topg = dd->perm[G->index]; - - /* We take the cofactors of F because we are going to rely on - ** the fact that the cofactors of the complement are the complements - ** of the cofactors to better utilize the cache. Variable comple - ** remembers whether we have to complement the result or not. - */ - if (topf <= topg) { - f1 = cuddT(F); f0 = cuddE(F); - } else { - f1 = f0 = F; - } - if (topg <= topf) { - g1 = cuddT(G); g0 = cuddE(G); - if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); } - } else { - g1 = g0 = g; - } - - zero = Cudd_Not(one); - if (topf >= topg) { - if (g0 == zero || g0 == DD_ZERO(dd)) { - r = cuddCofactorRecur(dd, f1, g1); - } else if (g1 == zero || g1 == DD_ZERO(dd)) { - r = cuddCofactorRecur(dd, f0, g0); - } else { - (void) fprintf(dd->out, - "Cudd_Cofactor: Invalid restriction 2\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - if (r == NULL) return(NULL); - } else /* if (topf < topg) */ { - t = cuddCofactorRecur(dd, f1, g); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddCofactorRecur(dd, f0, g); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e)); - if (r != NULL) - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(dd,(int)F->index,t,e); - } - if (r == NULL) { - Cudd_RecursiveDeref(dd ,e); - Cudd_RecursiveDeref(dd ,t); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r); - - return(Cudd_NotCond(r,comple)); - -} /* end of cuddCofactorRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddCompose.c b/src/bdd/cudd/cuddCompose.c deleted file mode 100644 index 8c858051..00000000 --- a/src/bdd/cudd/cuddCompose.c +++ /dev/null @@ -1,1722 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddCompose.c] - - PackageName [cudd] - - Synopsis [Functional composition and variable permutation of DDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_bddCompose() - <li> Cudd_addCompose() - <li> Cudd_addPermute() - <li> Cudd_addSwapVariables() - <li> Cudd_bddPermute() - <li> Cudd_bddVarMap() - <li> Cudd_SetVarMap() - <li> Cudd_bddSwapVariables() - <li> Cudd_bddAdjPermuteX() - <li> Cudd_addVectorCompose() - <li> Cudd_addGeneralVectorCompose() - <li> Cudd_addNonSimCompose() - <li> Cudd_bddVectorCompose() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddBddComposeRecur() - <li> cuddAddComposeRecur() - </ul> - Static procedures included in this module: - <ul> - <li> cuddAddPermuteRecur() - <li> cuddBddPermuteRecur() - <li> cuddBddVarMapRecur() - <li> cuddAddVectorComposeRecur() - <li> cuddAddGeneralVectorComposeRecur() - <li> cuddAddNonSimComposeRecur() - <li> cuddBddVectorComposeRecur() - <li> ddIsIthAddVar() - <li> ddIsIthAddVarPair() - </ul> - The permutation functions use a local cache because the results to - be remembered depend on the permutation being applied. Since the - permutation is just an array, it cannot be stored in the global - cache. There are different procedured for BDDs and ADDs. This is - because bddPermuteRecur uses cuddBddIteRecur. If this were changed, - the procedures could be merged.] - - Author [Fabio Somenzi and Kavita Ravi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddCompose.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -#ifdef DD_DEBUG -static int addPermuteRecurHits; -static int bddPermuteRecurHits; -static int bddVectorComposeHits; -static int addVectorComposeHits; - -static int addGeneralVectorComposeHits; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * cuddAddPermuteRecur ARGS((DdManager *manager, DdHashTable *table, DdNode *node, int *permut)); -static DdNode * cuddBddPermuteRecur ARGS((DdManager *manager, DdHashTable *table, DdNode *node, int *permut)); -static DdNode * cuddBddVarMapRecur ARGS((DdManager *manager, DdNode *f)); -static DdNode * cuddAddVectorComposeRecur ARGS((DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest)); -static DdNode * cuddAddNonSimComposeRecur ARGS((DdManager *dd, DdNode *f, DdNode **vector, DdNode *key, DdNode *cube, int lastsub)); -static DdNode * cuddBddVectorComposeRecur ARGS((DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest)); -DD_INLINE static int ddIsIthAddVar ARGS((DdManager *dd, DdNode *f, unsigned int i)); - -static DdNode * cuddAddGeneralVectorComposeRecur ARGS((DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vectorOn, DdNode **vectorOff, int deepest)); -DD_INLINE static int ddIsIthAddVarPair ARGS((DdManager *dd, DdNode *f, DdNode *g, unsigned int i)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Substitutes g for x_v in the BDD for f.] - - Description [Substitutes g for x_v in the BDD for f. v is the index of the - variable to be substituted. Cudd_bddCompose passes the corresponding - projection function to the recursive procedure, so that the cache may - be used. Returns the composed BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addCompose] - -******************************************************************************/ -DdNode * -Cudd_bddCompose( - DdManager * dd, - DdNode * f, - DdNode * g, - int v) -{ - DdNode *proj, *res; - - /* Sanity check. */ - if (v < 0 || v > dd->size) return(NULL); - - proj = dd->vars[v]; - do { - dd->reordered = 0; - res = cuddBddComposeRecur(dd,f,g,proj); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddCompose */ - - -/**Function******************************************************************** - - Synopsis [Substitutes g for x_v in the ADD for f.] - - Description [Substitutes g for x_v in the ADD for f. v is the index of the - variable to be substituted. g must be a 0-1 ADD. Cudd_bddCompose passes - the corresponding projection function to the recursive procedure, so - that the cache may be used. Returns the composed ADD if successful; - NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddCompose] - -******************************************************************************/ -DdNode * -Cudd_addCompose( - DdManager * dd, - DdNode * f, - DdNode * g, - int v) -{ - DdNode *proj, *res; - - /* Sanity check. */ - if (v < 0 || v > dd->size) return(NULL); - - proj = dd->vars[v]; - do { - dd->reordered = 0; - res = cuddAddComposeRecur(dd,f,g,proj); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addCompose */ - - -/**Function******************************************************************** - - Synopsis [Permutes the variables of an ADD.] - - Description [Given a permutation in array permut, creates a new ADD - with permuted variables. There should be an entry in array permut - for each variable in the manager. The i-th entry of permut holds the - index of the variable that is to substitute the i-th - variable. Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute Cudd_addSwapVariables] - -******************************************************************************/ -DdNode * -Cudd_addPermute( - DdManager * manager, - DdNode * node, - int * permut) -{ - DdHashTable *table; - DdNode *res; - - do { - manager->reordered = 0; - table = cuddHashTableInit(manager,1,2); - if (table == NULL) return(NULL); - /* Recursively solve the problem. */ - res = cuddAddPermuteRecur(manager,table,node,permut); - if (res != NULL) cuddRef(res); - /* Dispose of local cache. */ - cuddHashTableQuit(table); - } while (manager->reordered == 1); - - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_addPermute */ - - -/**Function******************************************************************** - - Synopsis [Swaps two sets of variables of the same size (x and y) in - the ADD f.] - - Description [Swaps two sets of variables of the same size (x and y) in - the ADD f. The size is given by n. The two sets of variables are - assumed to be disjoint. Returns a pointer to the resulting ADD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] - -******************************************************************************/ -DdNode * -Cudd_addSwapVariables( - DdManager * dd, - DdNode * f, - DdNode ** x, - DdNode ** y, - int n) -{ - DdNode *swapped; - int i, j, k; - int *permut; - - permut = ALLOC(int,dd->size); - if (permut == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < dd->size; i++) permut[i] = i; - for (i = 0; i < n; i++) { - j = x[i]->index; - k = y[i]->index; - permut[j] = k; - permut[k] = j; - } - - swapped = Cudd_addPermute(dd,f,permut); - FREE(permut); - - return(swapped); - -} /* end of Cudd_addSwapVariables */ - - -/**Function******************************************************************** - - Synopsis [Permutes the variables of a BDD.] - - Description [Given a permutation in array permut, creates a new BDD - with permuted variables. There should be an entry in array permut - for each variable in the manager. The i-th entry of permut holds the - index of the variable that is to substitute the i-th variable. - Returns a pointer to the resulting BDD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] - -******************************************************************************/ -DdNode * -Cudd_bddPermute( - DdManager * manager, - DdNode * node, - int * permut) -{ - DdHashTable *table; - DdNode *res; - - do { - manager->reordered = 0; - table = cuddHashTableInit(manager,1,2); - if (table == NULL) return(NULL); - res = cuddBddPermuteRecur(manager,table,node,permut); - if (res != NULL) cuddRef(res); - /* Dispose of local cache. */ - cuddHashTableQuit(table); - - } while (manager->reordered == 1); - - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_bddPermute */ - - -/**Function******************************************************************** - - Synopsis [Remaps the variables of a BDD using the default variable map.] - - Description [Remaps the variables of a BDD using the default - variable map. A typical use of this function is to swap two sets of - variables. The variable map must be registered with Cudd_SetVarMap. - Returns a pointer to the resulting BDD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables Cudd_SetVarMap] - -******************************************************************************/ -DdNode * -Cudd_bddVarMap( - DdManager * manager /* DD manager */, - DdNode * f /* function in which to remap variables */) -{ - DdNode *res; - - if (manager->map == NULL) return(NULL); - do { - manager->reordered = 0; - res = cuddBddVarMapRecur(manager, f); - } while (manager->reordered == 1); - - return(res); - -} /* end of Cudd_bddVarMap */ - - -/**Function******************************************************************** - - Synopsis [Registers a variable mapping with the manager.] - - Description [Registers with the manager a variable mapping described - by two sets of variables. This variable mapping is then used by - functions like Cudd_bddVarMap. This function is convenient for - those applications that perform the same mapping several times. - However, if several different permutations are used, it may be more - efficient not to rely on the registered mapping, because changing - mapping causes the cache to be cleared. (The initial setting, - however, does not clear the cache.) The two sets of variables (x and - y) must have the same size (x and y). The size is given by n. The - two sets of variables are normally disjoint, but this restriction is - not imposeded by the function. When new variables are created, the - map is automatically extended (each new variable maps to - itself). The typical use, however, is to wait until all variables - are created, and then create the map. Returns 1 if the mapping is - successfully registered with the manager; 0 otherwise.] - - SideEffects [Modifies the manager. May clear the cache.] - - SeeAlso [Cudd_bddVarMap Cudd_bddPermute Cudd_bddSwapVariables] - -******************************************************************************/ -int -Cudd_SetVarMap ( - DdManager *manager /* DD manager */, - DdNode **x /* first array of variables */, - DdNode **y /* second array of variables */, - int n /* length of both arrays */) -{ - int i; - - if (manager->map != NULL) { - cuddCacheFlush(manager); - } else { - manager->map = ALLOC(int,manager->maxSize); - if (manager->map == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return(0); - } - manager->memused += sizeof(int) * manager->maxSize; - } - /* Initialize the map to the identity. */ - for (i = 0; i < manager->size; i++) { - manager->map[i] = i; - } - /* Create the map. */ - for (i = 0; i < n; i++) { - manager->map[x[i]->index] = y[i]->index; - manager->map[y[i]->index] = x[i]->index; - } - return(1); - -} /* end of Cudd_SetVarMap */ - - -/**Function******************************************************************** - - Synopsis [Swaps two sets of variables of the same size (x and y) in - the BDD f.] - - Description [Swaps two sets of variables of the same size (x and y) - in the BDD f. The size is given by n. The two sets of variables are - assumed to be disjoint. Returns a pointer to the resulting BDD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute Cudd_addSwapVariables] - -******************************************************************************/ -DdNode * -Cudd_bddSwapVariables( - DdManager * dd, - DdNode * f, - DdNode ** x, - DdNode ** y, - int n) -{ - DdNode *swapped; - int i, j, k; - int *permut; - - permut = ALLOC(int,dd->size); - if (permut == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < dd->size; i++) permut[i] = i; - for (i = 0; i < n; i++) { - j = x[i]->index; - k = y[i]->index; - permut[j] = k; - permut[k] = j; - } - - swapped = Cudd_bddPermute(dd,f,permut); - FREE(permut); - - return(swapped); - -} /* end of Cudd_bddSwapVariables */ - - -/**Function******************************************************************** - - Synopsis [Rearranges a set of variables in the BDD B.] - - Description [Rearranges a set of variables in the BDD B. The size of - the set is given by n. This procedure is intended for the - `randomization' of the priority functions. Returns a pointer to the - BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables - Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_PrioritySelect] - -******************************************************************************/ -DdNode * -Cudd_bddAdjPermuteX( - DdManager * dd, - DdNode * B, - DdNode ** x, - int n) -{ - DdNode *swapped; - int i, j, k; - int *permut; - - permut = ALLOC(int,dd->size); - if (permut == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < dd->size; i++) permut[i] = i; - for (i = 0; i < n-2; i += 3) { - j = x[i]->index; - k = x[i+1]->index; - permut[j] = k; - permut[k] = j; - } - - swapped = Cudd_bddPermute(dd,B,permut); - FREE(permut); - - return(swapped); - -} /* end of Cudd_bddAdjPermuteX */ - - -/**Function******************************************************************** - - Synopsis [Composes an ADD with a vector of 0-1 ADDs.] - - Description [Given a vector of 0-1 ADDs, creates a new ADD by - substituting the 0-1 ADDs for the variables of the ADD f. There - should be an entry in vector for each variable in the manager. - If no substitution is sought for a given variable, the corresponding - projection function should be specified in the vector. - This function implements simultaneous composition. - Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addNonSimCompose Cudd_addPermute Cudd_addCompose - Cudd_bddVectorCompose] - -******************************************************************************/ -DdNode * -Cudd_addVectorCompose( - DdManager * dd, - DdNode * f, - DdNode ** vector) -{ - DdHashTable *table; - DdNode *res; - int deepest; - int i; - - do { - dd->reordered = 0; - /* Initialize local cache. */ - table = cuddHashTableInit(dd,1,2); - if (table == NULL) return(NULL); - - /* Find deepest real substitution. */ - for (deepest = dd->size - 1; deepest >= 0; deepest--) { - i = dd->invperm[deepest]; - if (!ddIsIthAddVar(dd,vector[i],i)) { - break; - } - } - - /* Recursively solve the problem. */ - res = cuddAddVectorComposeRecur(dd,table,f,vector,deepest); - if (res != NULL) cuddRef(res); - - /* Dispose of local cache. */ - cuddHashTableQuit(table); - } while (dd->reordered == 1); - - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_addVectorCompose */ - - -/**Function******************************************************************** - - Synopsis [Composes an ADD with a vector of ADDs.] - - Description [Given a vector of ADDs, creates a new ADD by substituting the - ADDs for the variables of the ADD f. vectorOn contains ADDs to be substituted - for the x_v and vectorOff the ADDs to be substituted for x_v'. There should - be an entry in vector for each variable in the manager. If no substitution - is sought for a given variable, the corresponding projection function should - be specified in the vector. This function implements simultaneous - composition. Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addVectorCompose Cudd_addNonSimCompose Cudd_addPermute - Cudd_addCompose Cudd_bddVectorCompose] - -******************************************************************************/ -DdNode * -Cudd_addGeneralVectorCompose( - DdManager * dd, - DdNode * f, - DdNode ** vectorOn, - DdNode ** vectorOff) -{ - DdHashTable *table; - DdNode *res; - int deepest; - int i; - - do { - dd->reordered = 0; - /* Initialize local cache. */ - table = cuddHashTableInit(dd,1,2); - if (table == NULL) return(NULL); - - /* Find deepest real substitution. */ - for (deepest = dd->size - 1; deepest >= 0; deepest--) { - i = dd->invperm[deepest]; - if (!ddIsIthAddVarPair(dd,vectorOn[i],vectorOff[i],i)) { - break; - } - } - - /* Recursively solve the problem. */ - res = cuddAddGeneralVectorComposeRecur(dd,table,f,vectorOn, - vectorOff,deepest); - if (res != NULL) cuddRef(res); - - /* Dispose of local cache. */ - cuddHashTableQuit(table); - } while (dd->reordered == 1); - - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_addGeneralVectorCompose */ - - -/**Function******************************************************************** - - Synopsis [Composes an ADD with a vector of 0-1 ADDs.] - - Description [Given a vector of 0-1 ADDs, creates a new ADD by - substituting the 0-1 ADDs for the variables of the ADD f. There - should be an entry in vector for each variable in the manager. - This function implements non-simultaneous composition. If any of the - functions being composed depends on any of the variables being - substituted, then the result depends on the order of composition, - which in turn depends on the variable order: The variables farther from - the roots in the order are substituted first. - Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addVectorCompose Cudd_addPermute Cudd_addCompose] - -******************************************************************************/ -DdNode * -Cudd_addNonSimCompose( - DdManager * dd, - DdNode * f, - DdNode ** vector) -{ - DdNode *cube, *key, *var, *tmp, *piece; - DdNode *res; - int i, lastsub; - - /* The cache entry for this function is composed of three parts: - ** f itself, the replacement relation, and the cube of the - ** variables being substituted. - ** The replacement relation is the product of the terms (yi EXNOR gi). - ** This apporach allows us to use the global cache for this function, - ** with great savings in memory with respect to using arrays for the - ** cache entries. - ** First we build replacement relation and cube of substituted - ** variables from the vector specifying the desired composition. - */ - key = DD_ONE(dd); - cuddRef(key); - cube = DD_ONE(dd); - cuddRef(cube); - for (i = (int) dd->size - 1; i >= 0; i--) { - if (ddIsIthAddVar(dd,vector[i],(unsigned int)i)) { - continue; - } - var = Cudd_addIthVar(dd,i); - if (var == NULL) { - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(var); - /* Update cube. */ - tmp = Cudd_addApply(dd,Cudd_addTimes,var,cube); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,cube); - Cudd_RecursiveDeref(dd,var); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,cube); - cube = tmp; - /* Update replacement relation. */ - piece = Cudd_addApply(dd,Cudd_addXnor,var,vector[i]); - if (piece == NULL) { - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,var); - return(NULL); - } - cuddRef(piece); - Cudd_RecursiveDeref(dd,var); - tmp = Cudd_addApply(dd,Cudd_addTimes,key,piece); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,piece); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,piece); - key = tmp; - } - - /* Now try composition, until no reordering occurs. */ - do { - /* Find real substitution with largest index. */ - for (lastsub = dd->size - 1; lastsub >= 0; lastsub--) { - if (!ddIsIthAddVar(dd,vector[lastsub],(unsigned int)lastsub)) { - break; - } - } - - /* Recursively solve the problem. */ - dd->reordered = 0; - res = cuddAddNonSimComposeRecur(dd,f,vector,key,cube,lastsub+1); - if (res != NULL) cuddRef(res); - - } while (dd->reordered == 1); - - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,cube); - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_addNonSimCompose */ - - -/**Function******************************************************************** - - Synopsis [Composes a BDD with a vector of BDDs.] - - Description [Given a vector of BDDs, creates a new BDD by - substituting the BDDs for the variables of the BDD f. There - should be an entry in vector for each variable in the manager. - If no substitution is sought for a given variable, the corresponding - projection function should be specified in the vector. - This function implements simultaneous composition. - Returns a pointer to the resulting BDD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute Cudd_bddCompose Cudd_addVectorCompose] - -******************************************************************************/ -DdNode * -Cudd_bddVectorCompose( - DdManager * dd, - DdNode * f, - DdNode ** vector) -{ - DdHashTable *table; - DdNode *res; - int deepest; - int i; - - do { - dd->reordered = 0; - /* Initialize local cache. */ - table = cuddHashTableInit(dd,1,2); - if (table == NULL) return(NULL); - - /* Find deepest real substitution. */ - for (deepest = dd->size - 1; deepest >= 0; deepest--) { - i = dd->invperm[deepest]; - if (vector[i] != dd->vars[i]) { - break; - } - } - - /* Recursively solve the problem. */ - res = cuddBddVectorComposeRecur(dd,table,f,vector, deepest); - if (res != NULL) cuddRef(res); - - /* Dispose of local cache. */ - cuddHashTableQuit(table); - } while (dd->reordered == 1); - - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_bddVectorCompose */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddCompose.] - - Description [Performs the recursive step of Cudd_bddCompose. - Exploits the fact that the composition of f' with g - produces the complement of the composition of f with g to better - utilize the cache. Returns the composed BDD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddCompose] - -******************************************************************************/ -DdNode * -cuddBddComposeRecur( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * proj) -{ - DdNode *F, *G, *f1, *f0, *g1, *g0, *r, *t, *e; - unsigned int v, topf, topg, topindex; - int comple; - - statLine(dd); - v = dd->perm[proj->index]; - F = Cudd_Regular(f); - topf = cuddI(dd,F->index); - - /* Terminal case. Subsumes the test for constant f. */ - if (topf > v) return(f); - - /* We solve the problem for a regular pointer, and then complement - ** the result if the pointer was originally complemented. - */ - comple = Cudd_IsComplement(f); - - /* Check cache. */ - r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - if (topf == v) { - /* Compose. */ - f1 = cuddT(F); - f0 = cuddE(F); - r = cuddBddIteRecur(dd, g, f1, f0); - if (r == NULL) return(NULL); - } else { - /* Compute cofactors of f and g. Remember the index of the top - ** variable. - */ - G = Cudd_Regular(g); - topg = cuddI(dd,G->index); - if (topf > topg) { - topindex = G->index; - f1 = f0 = F; - } else { - topindex = F->index; - f1 = cuddT(F); - f0 = cuddE(F); - } - if (topg > topf) { - g1 = g0 = g; - } else { - g1 = cuddT(G); - g0 = cuddE(G); - if (g != G) { - g1 = Cudd_Not(g1); - g0 = Cudd_Not(g0); - } - } - /* Recursive step. */ - t = cuddBddComposeRecur(dd, f1, g1, proj); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddBddComposeRecur(dd, f0, g0, proj); - if (e == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - cuddRef(e); - - r = cuddBddIteRecur(dd, dd->vars[topindex], t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, t); - Cudd_IterDerefBdd(dd, e); - return(NULL); - } - cuddRef(r); - Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */ - Cudd_IterDerefBdd(dd, e); - cuddDeref(r); - } - - cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r); - - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddComposeRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addCompose.] - - Description [Performs the recursive step of Cudd_addCompose. - Returns the composed BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addCompose] - -******************************************************************************/ -DdNode * -cuddAddComposeRecur( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * proj) -{ - DdNode *f1, *f0, *g1, *g0, *r, *t, *e; - unsigned int v, topf, topg, topindex; - - statLine(dd); - v = dd->perm[proj->index]; - topf = cuddI(dd,f->index); - - /* Terminal case. Subsumes the test for constant f. */ - if (topf > v) return(f); - - /* Check cache. */ - r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj); - if (r != NULL) { - return(r); - } - - if (topf == v) { - /* Compose. */ - f1 = cuddT(f); - f0 = cuddE(f); - r = cuddAddIteRecur(dd, g, f1, f0); - if (r == NULL) return(NULL); - } else { - /* Compute cofactors of f and g. Remember the index of the top - ** variable. - */ - topg = cuddI(dd,g->index); - if (topf > topg) { - topindex = g->index; - f1 = f0 = f; - } else { - topindex = f->index; - f1 = cuddT(f); - f0 = cuddE(f); - } - if (topg > topf) { - g1 = g0 = g; - } else { - g1 = cuddT(g); - g0 = cuddE(g); - } - /* Recursive step. */ - t = cuddAddComposeRecur(dd, f1, g1, proj); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddAddComposeRecur(dd, f0, g0, proj); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else { - r = cuddUniqueInter(dd, (int) topindex, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r); - - return(r); - -} /* end of cuddAddComposeRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_addPermute.] - - Description [ Recursively puts the ADD in the order given in the - array permut. Checks for trivial cases to terminate recursion, then - splits on the children of this node. Once the solutions for the - children are obtained, it puts into the current position the node - from the rest of the ADD that should be here. Then returns this ADD. - The key here is that the node being visited is NOT put in its proper - place by this instance, but rather is switched when its proper - position is reached in the recursion tree.<p> - The DdNode * that is returned is the same ADD as passed in as node, - but in the new order.] - - SideEffects [None] - - SeeAlso [Cudd_addPermute cuddBddPermuteRecur] - -******************************************************************************/ -static DdNode * -cuddAddPermuteRecur( - DdManager * manager /* DD manager */, - DdHashTable * table /* computed table */, - DdNode * node /* ADD to be reordered */, - int * permut /* permutation array */) -{ - DdNode *T,*E; - DdNode *res,*var; - int index; - - statLine(manager); - /* Check for terminal case of constant node. */ - if (cuddIsConstant(node)) { - return(node); - } - - /* If problem already solved, look up answer and return. */ - if (node->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) { -#ifdef DD_DEBUG - addPermuteRecurHits++; -#endif - return(res); - } - - /* Split and recur on children of this node. */ - T = cuddAddPermuteRecur(manager,table,cuddT(node),permut); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddAddPermuteRecur(manager,table,cuddE(node),permut); - if (E == NULL) { - Cudd_RecursiveDeref(manager, T); - return(NULL); - } - cuddRef(E); - - /* Move variable that should be in this position to this position - ** by creating a single var ADD for that variable, and calling - ** cuddAddIteRecur with the T and E we just created. - */ - index = permut[node->index]; - var = cuddUniqueInter(manager,index,DD_ONE(manager),DD_ZERO(manager)); - if (var == NULL) return(NULL); - cuddRef(var); - res = cuddAddIteRecur(manager,var,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(manager,var); - Cudd_RecursiveDeref(manager, T); - Cudd_RecursiveDeref(manager, E); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,var); - Cudd_RecursiveDeref(manager, T); - Cudd_RecursiveDeref(manager, E); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if (node->ref != 1) { - ptrint fanout = (ptrint) node->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert1(table,node,res,fanout)) { - Cudd_RecursiveDeref(manager, res); - return(NULL); - } - } - cuddDeref(res); - return(res); - -} /* end of cuddAddPermuteRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddPermute.] - - Description [ Recursively puts the BDD in the order given in the array permut. - Checks for trivial cases to terminate recursion, then splits on the - children of this node. Once the solutions for the children are - obtained, it puts into the current position the node from the rest of - the BDD that should be here. Then returns this BDD. - The key here is that the node being visited is NOT put in its proper - place by this instance, but rather is switched when its proper position - is reached in the recursion tree.<p> - The DdNode * that is returned is the same BDD as passed in as node, - but in the new order.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute cuddAddPermuteRecur] - -******************************************************************************/ -static DdNode * -cuddBddPermuteRecur( - DdManager * manager /* DD manager */, - DdHashTable * table /* computed table */, - DdNode * node /* BDD to be reordered */, - int * permut /* permutation array */) -{ - DdNode *N,*T,*E; - DdNode *res; - int index; - - statLine(manager); - N = Cudd_Regular(node); - - /* Check for terminal case of constant node. */ - if (cuddIsConstant(N)) { - return(node); - } - - /* If problem already solved, look up answer and return. */ - if (N->ref != 1 && (res = cuddHashTableLookup1(table,N)) != NULL) { -#ifdef DD_DEBUG - bddPermuteRecurHits++; -#endif - return(Cudd_NotCond(res,N != node)); - } - - /* Split and recur on children of this node. */ - T = cuddBddPermuteRecur(manager,table,cuddT(N),permut); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddBddPermuteRecur(manager,table,cuddE(N),permut); - if (E == NULL) { - Cudd_IterDerefBdd(manager, T); - return(NULL); - } - cuddRef(E); - - /* Move variable that should be in this position to this position - ** by retrieving the single var BDD for that variable, and calling - ** cuddBddIteRecur with the T and E we just created. - */ - index = permut[N->index]; - res = cuddBddIteRecur(manager,manager->vars[index],T,E); - if (res == NULL) { - Cudd_IterDerefBdd(manager, T); - Cudd_IterDerefBdd(manager, E); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(manager, T); - Cudd_IterDerefBdd(manager, E); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if (N->ref != 1) { - ptrint fanout = (ptrint) N->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert1(table,N,res,fanout)) { - Cudd_IterDerefBdd(manager, res); - return(NULL); - } - } - cuddDeref(res); - return(Cudd_NotCond(res,N != node)); - -} /* end of cuddBddPermuteRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddVarMap.] - - Description [Implements the recursive step of Cudd_bddVarMap. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddVarMap] - -******************************************************************************/ -static DdNode * -cuddBddVarMapRecur( - DdManager *manager /* DD manager */, - DdNode *f /* BDD to be remapped */) -{ - DdNode *F, *T, *E; - DdNode *res; - int index; - - statLine(manager); - F = Cudd_Regular(f); - - /* Check for terminal case of constant node. */ - if (cuddIsConstant(F)) { - return(f); - } - - /* If problem already solved, look up answer and return. */ - if (F->ref != 1 && - (res = cuddCacheLookup1(manager,Cudd_bddVarMap,F)) != NULL) { - return(Cudd_NotCond(res,F != f)); - } - - /* Split and recur on children of this node. */ - T = cuddBddVarMapRecur(manager,cuddT(F)); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddBddVarMapRecur(manager,cuddE(F)); - if (E == NULL) { - Cudd_IterDerefBdd(manager, T); - return(NULL); - } - cuddRef(E); - - /* Move variable that should be in this position to this position - ** by retrieving the single var BDD for that variable, and calling - ** cuddBddIteRecur with the T and E we just created. - */ - index = manager->map[F->index]; - res = cuddBddIteRecur(manager,manager->vars[index],T,E); - if (res == NULL) { - Cudd_IterDerefBdd(manager, T); - Cudd_IterDerefBdd(manager, E); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(manager, T); - Cudd_IterDerefBdd(manager, E); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if (F->ref != 1) { - cuddCacheInsert1(manager,Cudd_bddVarMap,F,res); - } - cuddDeref(res); - return(Cudd_NotCond(res,F != f)); - -} /* end of cuddBddVarMapRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addVectorCompose.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -cuddAddVectorComposeRecur( - DdManager * dd /* DD manager */, - DdHashTable * table /* computed table */, - DdNode * f /* ADD in which to compose */, - DdNode ** vector /* functions to substitute */, - int deepest /* depth of deepest substitution */) -{ - DdNode *T,*E; - DdNode *res; - - statLine(dd); - /* If we are past the deepest substitution, return f. */ - if (cuddI(dd,f->index) > deepest) { - return(f); - } - - if ((res = cuddHashTableLookup1(table,f)) != NULL) { -#ifdef DD_DEBUG - addVectorComposeHits++; -#endif - return(res); - } - - /* Split and recur on children of this node. */ - T = cuddAddVectorComposeRecur(dd,table,cuddT(f),vector,deepest); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddAddVectorComposeRecur(dd,table,cuddE(f),vector,deepest); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - - /* Retrieve the 0-1 ADD for the current top variable and call - ** cuddAddIteRecur with the T and E we just created. - */ - res = cuddAddIteRecur(dd,vector[f->index],T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again - */ - if (f->ref != 1) { - ptrint fanout = (ptrint) f->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert1(table,f,res,fanout)) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - } - cuddDeref(res); - return(res); - -} /* end of cuddAddVectorComposeRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addGeneralVectorCompose.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -cuddAddGeneralVectorComposeRecur( - DdManager * dd /* DD manager */, - DdHashTable * table /* computed table */, - DdNode * f /* ADD in which to compose */, - DdNode ** vectorOn /* functions to substitute for x_i */, - DdNode ** vectorOff /* functions to substitute for x_i' */, - int deepest /* depth of deepest substitution */) -{ - DdNode *T,*E,*t,*e; - DdNode *res; - - /* If we are past the deepest substitution, return f. */ - if (cuddI(dd,f->index) > deepest) { - return(f); - } - - if ((res = cuddHashTableLookup1(table,f)) != NULL) { -#ifdef DD_DEBUG - addGeneralVectorComposeHits++; -#endif - return(res); - } - - /* Split and recur on children of this node. */ - T = cuddAddGeneralVectorComposeRecur(dd,table,cuddT(f), - vectorOn,vectorOff,deepest); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddAddGeneralVectorComposeRecur(dd,table,cuddE(f), - vectorOn,vectorOff,deepest); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - - /* Retrieve the compose ADDs for the current top variable and call - ** cuddAddApplyRecur with the T and E we just created. - */ - t = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOn[f->index],T); - if (t == NULL) { - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - return(NULL); - } - cuddRef(t); - e = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOff[f->index],E); - if (e == NULL) { - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - Cudd_RecursiveDeref(dd,t); - return(NULL); - } - cuddRef(e); - res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - Cudd_RecursiveDeref(dd,t); - Cudd_RecursiveDeref(dd,e); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - Cudd_RecursiveDeref(dd,t); - Cudd_RecursiveDeref(dd,e); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again - */ - if (f->ref != 1) { - ptrint fanout = (ptrint) f->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert1(table,f,res,fanout)) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - } - cuddDeref(res); - return(res); - -} /* end of cuddAddGeneralVectorComposeRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addNonSimCompose.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -cuddAddNonSimComposeRecur( - DdManager * dd, - DdNode * f, - DdNode ** vector, - DdNode * key, - DdNode * cube, - int lastsub) -{ - DdNode *f1, *f0, *key1, *key0, *cube1, *var; - DdNode *T,*E; - DdNode *r; - unsigned int top, topf, topk, topc; - unsigned int index; - int i; - DdNode **vect1; - DdNode **vect0; - - statLine(dd); - /* If we are past the deepest substitution, return f. */ - if (cube == DD_ONE(dd) || cuddIsConstant(f)) { - return(f); - } - - /* If problem already solved, look up answer and return. */ - r = cuddCacheLookup(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube); - if (r != NULL) { - return(r); - } - - /* Find top variable. we just need to look at f, key, and cube, - ** because all the varibles in the gi are in key. - */ - topf = cuddI(dd,f->index); - topk = cuddI(dd,key->index); - top = ddMin(topf,topk); - topc = cuddI(dd,cube->index); - top = ddMin(top,topc); - index = dd->invperm[top]; - - /* Compute the cofactors. */ - if (topf == top) { - f1 = cuddT(f); - f0 = cuddE(f); - } else { - f1 = f0 = f; - } - if (topc == top) { - cube1 = cuddT(cube); - /* We want to eliminate vector[index] from key. Otherwise - ** cache performance is severely affected. Hence we - ** existentially quantify the variable with index "index" from key. - */ - var = Cudd_addIthVar(dd, (int) index); - if (var == NULL) { - return(NULL); - } - cuddRef(var); - key1 = cuddAddExistAbstractRecur(dd, key, var); - if (key1 == NULL) { - Cudd_RecursiveDeref(dd,var); - return(NULL); - } - cuddRef(key1); - Cudd_RecursiveDeref(dd,var); - key0 = key1; - } else { - cube1 = cube; - if (topk == top) { - key1 = cuddT(key); - key0 = cuddE(key); - } else { - key1 = key0 = key; - } - cuddRef(key1); - } - - /* Allocate two new vectors for the cofactors of vector. */ - vect1 = ALLOC(DdNode *,lastsub); - if (vect1 == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd,key1); - return(NULL); - } - vect0 = ALLOC(DdNode *,lastsub); - if (vect0 == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd,key1); - FREE(vect1); - return(NULL); - } - - /* Cofactor the gi. Eliminate vect1[index] and vect0[index], because - ** we do not need them. - */ - for (i = 0; i < lastsub; i++) { - DdNode *gi = vector[i]; - if (gi == NULL) { - vect1[i] = vect0[i] = NULL; - } else if (gi->index == index) { - vect1[i] = cuddT(gi); - vect0[i] = cuddE(gi); - } else { - vect1[i] = vect0[i] = gi; - } - } - vect1[index] = vect0[index] = NULL; - - /* Recur on children. */ - T = cuddAddNonSimComposeRecur(dd,f1,vect1,key1,cube1,lastsub); - FREE(vect1); - if (T == NULL) { - Cudd_RecursiveDeref(dd,key1); - FREE(vect0); - return(NULL); - } - cuddRef(T); - E = cuddAddNonSimComposeRecur(dd,f0,vect0,key0,cube1,lastsub); - FREE(vect0); - if (E == NULL) { - Cudd_RecursiveDeref(dd,key1); - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - Cudd_RecursiveDeref(dd,key1); - - /* Retrieve the 0-1 ADD for the current top variable from vector, - ** and call cuddAddIteRecur with the T and E we just created. - */ - r = cuddAddIteRecur(dd,vector[index],T,E); - if (r == NULL) { - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - cuddDeref(r); - - /* Store answer to trim recursion. */ - cuddCacheInsert(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube,r); - - return(r); - -} /* end of cuddAddNonSimComposeRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddVectorCompose.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -cuddBddVectorComposeRecur( - DdManager * dd /* DD manager */, - DdHashTable * table /* computed table */, - DdNode * f /* BDD in which to compose */, - DdNode ** vector /* functions to be composed */, - int deepest /* depth of the deepest substitution */) -{ - DdNode *F,*T,*E; - DdNode *res; - - statLine(dd); - F = Cudd_Regular(f); - - /* If we are past the deepest substitution, return f. */ - if (cuddI(dd,F->index) > deepest) { - return(f); - } - - /* If problem already solved, look up answer and return. */ - if ((res = cuddHashTableLookup1(table,F)) != NULL) { -#ifdef DD_DEBUG - bddVectorComposeHits++; -#endif - return(Cudd_NotCond(res,F != f)); - } - - /* Split and recur on children of this node. */ - T = cuddBddVectorComposeRecur(dd,table,cuddT(F),vector, deepest); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddBddVectorComposeRecur(dd,table,cuddE(F),vector, deepest); - if (E == NULL) { - Cudd_IterDerefBdd(dd, T); - return(NULL); - } - cuddRef(E); - - /* Call cuddBddIteRecur with the BDD that replaces the current top - ** variable and the T and E we just created. - */ - res = cuddBddIteRecur(dd,vector[F->index],T,E); - if (res == NULL) { - Cudd_IterDerefBdd(dd, T); - Cudd_IterDerefBdd(dd, E); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(dd, T); - Cudd_IterDerefBdd(dd, E); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if (F->ref != 1) { - ptrint fanout = (ptrint) F->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert1(table,F,res,fanout)) { - Cudd_IterDerefBdd(dd, res); - return(NULL); - } - } - cuddDeref(res); - return(Cudd_NotCond(res,F != f)); - -} /* end of cuddBddVectorComposeRecur */ - - -/**Function******************************************************************** - - Synopsis [Comparison of a function to the i-th ADD variable.] - - Description [Comparison of a function to the i-th ADD variable. Returns 1 if - the function is the i-th ADD variable; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DD_INLINE -static int -ddIsIthAddVar( - DdManager * dd, - DdNode * f, - unsigned int i) -{ - return(f->index == i && cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd)); - -} /* end of ddIsIthAddVar */ - - -/**Function******************************************************************** - - Synopsis [Comparison of a pair of functions to the i-th ADD variable.] - - Description [Comparison of a pair of functions to the i-th ADD - variable. Returns 1 if the functions are the i-th ADD variable and its - complement; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DD_INLINE -static int -ddIsIthAddVarPair( - DdManager * dd, - DdNode * f, - DdNode * g, - unsigned int i) -{ - return(f->index == i && g->index == i && - cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd) && - cuddT(g) == DD_ZERO(dd) && cuddE(g) == DD_ONE(dd)); - -} /* end of ddIsIthAddVarPair */ diff --git a/src/bdd/cudd/cuddDecomp.c b/src/bdd/cudd/cuddDecomp.c deleted file mode 100644 index 4fde7392..00000000 --- a/src/bdd/cudd/cuddDecomp.c +++ /dev/null @@ -1,2150 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddDecomp.c] - - PackageName [cudd] - - Synopsis [Functions for BDD decomposition.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_bddApproxConjDecomp() - <li> Cudd_bddApproxDisjDecomp() - <li> Cudd_bddIterConjDecomp() - <li> Cudd_bddIterDisjDecomp() - <li> Cudd_bddGenConjDecomp() - <li> Cudd_bddGenDisjDecomp() - <li> Cudd_bddVarConjDecomp() - <li> Cudd_bddVarDisjDecomp() - </ul> - Static procedures included in this module: - <ul> - <li> cuddConjunctsAux() - <li> CreateBotDist() - <li> BuildConjuncts() - <li> ConjunctsFree() - </ul>] - - Author [Kavita Ravi, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ -#define DEPTH 5 -#define THRESHOLD 10 -#define NONE 0 -#define PAIR_ST 1 -#define PAIR_CR 2 -#define G_ST 3 -#define G_CR 4 -#define H_ST 5 -#define H_CR 6 -#define BOTH_G 7 -#define BOTH_H 8 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ -typedef struct Conjuncts { - DdNode *g; - DdNode *h; -} Conjuncts; - -typedef struct NodeStat { - int distance; - int localRef; -} NodeStat; - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddDecomp.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -static DdNode *one, *zero; -long lastTimeG; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -#define FactorsNotStored(factors) ((int)((long)(factors) & 01)) - -#define FactorsComplement(factors) ((Conjuncts *)((long)(factors) | 01)) - -#define FactorsUncomplement(factors) ((Conjuncts *)((long)(factors) ^ 01)) - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static NodeStat * CreateBotDist ARGS((DdNode * node, st_table * distanceTable)); -static double CountMinterms ARGS((DdNode * node, double max, st_table * mintermTable, FILE *fp)); -static void ConjunctsFree ARGS((DdManager * dd, Conjuncts * factors)); -static int PairInTables ARGS((DdNode * g, DdNode * h, st_table * ghTable)); -static Conjuncts * CheckTablesCacheAndReturn ARGS((DdNode * node, DdNode * g, DdNode * h, st_table * ghTable, st_table * cacheTable)); -static Conjuncts * PickOnePair ARGS((DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st_table * ghTable, st_table * cacheTable)); -static Conjuncts * CheckInTables ARGS((DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st_table * ghTable, st_table * cacheTable, int * outOfMem)); -static Conjuncts * ZeroCase ARGS((DdManager * dd, DdNode * node, Conjuncts * factorsNv, st_table * ghTable, st_table * cacheTable, int switched)); -static Conjuncts * BuildConjuncts ARGS((DdManager * dd, DdNode * node, st_table * distanceTable, st_table * cacheTable, int approxDistance, int maxLocalRef, st_table * ghTable, st_table * mintermTable)); -static int cuddConjunctsAux ARGS((DdManager * dd, DdNode * f, DdNode ** c1, DdNode ** c2)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs two-way conjunctive decomposition of a BDD.] - - Description [Performs two-way conjunctive decomposition of a - BDD. This procedure owes its name to the use of supersetting to - obtain an initial factor of the given function. Returns the number - of conjuncts produced, that is, 2 if successful; 1 if no meaningful - decomposition was found; 0 otherwise. The conjuncts produced by this - procedure tend to be imbalanced.] - - SideEffects [The factors are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the conjuncts are already - referenced. If the function returns 0, the array for the conjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddApproxDisjDecomp Cudd_bddIterConjDecomp - Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox - Cudd_bddSqueeze Cudd_bddLICompaction] - -******************************************************************************/ -int -Cudd_bddApproxConjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** conjuncts /* address of the first factor */) -{ - DdNode *superset1, *superset2, *glocal, *hlocal; - int nvars = Cudd_SupportSize(dd,f); - - /* Find a tentative first factor by overapproximation and minimization. */ - superset1 = Cudd_RemapOverApprox(dd,f,nvars,0,1.0); - if (superset1 == NULL) return(0); - cuddRef(superset1); - superset2 = Cudd_bddSqueeze(dd,f,superset1); - if (superset2 == NULL) { - Cudd_RecursiveDeref(dd,superset1); - return(0); - } - cuddRef(superset2); - Cudd_RecursiveDeref(dd,superset1); - - /* Compute the second factor by minimization. */ - hlocal = Cudd_bddLICompaction(dd,f,superset2); - if (hlocal == NULL) { - Cudd_RecursiveDeref(dd,superset2); - return(0); - } - cuddRef(hlocal); - - /* Refine the first factor by minimization. If h turns out to be f, this - ** step guarantees that g will be 1. */ - glocal = Cudd_bddLICompaction(dd,superset2,hlocal); - if (glocal == NULL) { - Cudd_RecursiveDeref(dd,superset2); - Cudd_RecursiveDeref(dd,hlocal); - return(0); - } - cuddRef(glocal); - Cudd_RecursiveDeref(dd,superset2); - - if (glocal != DD_ONE(dd)) { - if (hlocal != DD_ONE(dd)) { - *conjuncts = ALLOC(DdNode *,2); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - (*conjuncts)[1] = hlocal; - return(2); - } else { - Cudd_RecursiveDeref(dd,hlocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - return(1); - } - } else { - Cudd_RecursiveDeref(dd,glocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = hlocal; - return(1); - } - -} /* end of Cudd_bddApproxConjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way disjunctive decomposition of a BDD.] - - Description [Performs two-way disjunctive decomposition of a BDD. - Returns the number of disjuncts produced, that is, 2 if successful; - 1 if no meaningful decomposition was found; 0 otherwise. The - disjuncts produced by this procedure tend to be imbalanced.] - - SideEffects [The two disjuncts are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the disjuncts are already - referenced. If the function returns 0, the array for the disjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddApproxConjDecomp Cudd_bddIterDisjDecomp - Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp] - -******************************************************************************/ -int -Cudd_bddApproxDisjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** disjuncts /* address of the array of the disjuncts */) -{ - int result, i; - - result = Cudd_bddApproxConjDecomp(dd,Cudd_Not(f),disjuncts); - for (i = 0; i < result; i++) { - (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); - } - return(result); - -} /* end of Cudd_bddApproxDisjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way conjunctive decomposition of a BDD.] - - Description [Performs two-way conjunctive decomposition of a - BDD. This procedure owes its name to the iterated use of - supersetting to obtain a factor of the given function. Returns the - number of conjuncts produced, that is, 2 if successful; 1 if no - meaningful decomposition was found; 0 otherwise. The conjuncts - produced by this procedure tend to be imbalanced.] - - SideEffects [The factors are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the conjuncts are already - referenced. If the function returns 0, the array for the conjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddIterDisjDecomp Cudd_bddApproxConjDecomp - Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox - Cudd_bddSqueeze Cudd_bddLICompaction] - -******************************************************************************/ -int -Cudd_bddIterConjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** conjuncts /* address of the array of conjuncts */) -{ - DdNode *superset1, *superset2, *old[2], *res[2]; - int sizeOld, sizeNew; - int nvars = Cudd_SupportSize(dd,f); - - old[0] = DD_ONE(dd); - cuddRef(old[0]); - old[1] = f; - cuddRef(old[1]); - sizeOld = Cudd_SharingSize(old,2); - - do { - /* Find a tentative first factor by overapproximation and - ** minimization. */ - superset1 = Cudd_RemapOverApprox(dd,old[1],nvars,0,1.0); - if (superset1 == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - return(0); - } - cuddRef(superset1); - superset2 = Cudd_bddSqueeze(dd,old[1],superset1); - if (superset2 == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - Cudd_RecursiveDeref(dd,superset1); - return(0); - } - cuddRef(superset2); - Cudd_RecursiveDeref(dd,superset1); - res[0] = Cudd_bddAnd(dd,old[0],superset2); - if (res[0] == NULL) { - Cudd_RecursiveDeref(dd,superset2); - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - return(0); - } - cuddRef(res[0]); - Cudd_RecursiveDeref(dd,superset2); - if (res[0] == old[0]) { - Cudd_RecursiveDeref(dd,res[0]); - break; /* avoid infinite loop */ - } - - /* Compute the second factor by minimization. */ - res[1] = Cudd_bddLICompaction(dd,old[1],res[0]); - if (res[1] == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - return(0); - } - cuddRef(res[1]); - - sizeNew = Cudd_SharingSize(res,2); - if (sizeNew <= sizeOld) { - Cudd_RecursiveDeref(dd,old[0]); - old[0] = res[0]; - Cudd_RecursiveDeref(dd,old[1]); - old[1] = res[1]; - sizeOld = sizeNew; - } else { - Cudd_RecursiveDeref(dd,res[0]); - Cudd_RecursiveDeref(dd,res[1]); - break; - } - - } while (1); - - /* Refine the first factor by minimization. If h turns out to - ** be f, this step guarantees that g will be 1. */ - superset1 = Cudd_bddLICompaction(dd,old[0],old[1]); - if (superset1 == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - return(0); - } - cuddRef(superset1); - Cudd_RecursiveDeref(dd,old[0]); - old[0] = superset1; - - if (old[0] != DD_ONE(dd)) { - if (old[1] != DD_ONE(dd)) { - *conjuncts = ALLOC(DdNode *,2); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = old[0]; - (*conjuncts)[1] = old[1]; - return(2); - } else { - Cudd_RecursiveDeref(dd,old[1]); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = old[0]; - return(1); - } - } else { - Cudd_RecursiveDeref(dd,old[0]); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,old[1]); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = old[1]; - return(1); - } - -} /* end of Cudd_bddIterConjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way disjunctive decomposition of a BDD.] - - Description [Performs two-way disjunctive decomposition of a BDD. - Returns the number of disjuncts produced, that is, 2 if successful; - 1 if no meaningful decomposition was found; 0 otherwise. The - disjuncts produced by this procedure tend to be imbalanced.] - - SideEffects [The two disjuncts are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the disjuncts are already - referenced. If the function returns 0, the array for the disjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddIterConjDecomp Cudd_bddApproxDisjDecomp - Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp] - -******************************************************************************/ -int -Cudd_bddIterDisjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** disjuncts /* address of the array of the disjuncts */) -{ - int result, i; - - result = Cudd_bddIterConjDecomp(dd,Cudd_Not(f),disjuncts); - for (i = 0; i < result; i++) { - (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); - } - return(result); - -} /* end of Cudd_bddIterDisjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way conjunctive decomposition of a BDD.] - - Description [Performs two-way conjunctive decomposition of a - BDD. This procedure owes its name to the fact tht it generalizes the - decomposition based on the cofactors with respect to one - variable. Returns the number of conjuncts produced, that is, 2 if - successful; 1 if no meaningful decomposition was found; 0 - otherwise. The conjuncts produced by this procedure tend to be - balanced.] - - SideEffects [The two factors are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the conjuncts are already - referenced. If the function returns 0, the array for the conjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddGenDisjDecomp Cudd_bddApproxConjDecomp - Cudd_bddIterConjDecomp Cudd_bddVarConjDecomp] - -******************************************************************************/ -int -Cudd_bddGenConjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** conjuncts /* address of the array of conjuncts */) -{ - int result; - DdNode *glocal, *hlocal; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - do { - dd->reordered = 0; - result = cuddConjunctsAux(dd, f, &glocal, &hlocal); - } while (dd->reordered == 1); - - if (result == 0) { - return(0); - } - - if (glocal != one) { - if (hlocal != one) { - *conjuncts = ALLOC(DdNode *,2); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - (*conjuncts)[1] = hlocal; - return(2); - } else { - Cudd_RecursiveDeref(dd,hlocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - return(1); - } - } else { - Cudd_RecursiveDeref(dd,glocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = hlocal; - return(1); - } - -} /* end of Cudd_bddGenConjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way disjunctive decomposition of a BDD.] - - Description [Performs two-way disjunctive decomposition of a BDD. - Returns the number of disjuncts produced, that is, 2 if successful; - 1 if no meaningful decomposition was found; 0 otherwise. The - disjuncts produced by this procedure tend to be balanced.] - - SideEffects [The two disjuncts are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the disjuncts are already - referenced. If the function returns 0, the array for the disjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddGenConjDecomp Cudd_bddApproxDisjDecomp - Cudd_bddIterDisjDecomp Cudd_bddVarDisjDecomp] - -******************************************************************************/ -int -Cudd_bddGenDisjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** disjuncts /* address of the array of the disjuncts */) -{ - int result, i; - - result = Cudd_bddGenConjDecomp(dd,Cudd_Not(f),disjuncts); - for (i = 0; i < result; i++) { - (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); - } - return(result); - -} /* end of Cudd_bddGenDisjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way conjunctive decomposition of a BDD.] - - Description [Conjunctively decomposes one BDD according to a - variable. If <code>f</code> is the function of the BDD and - <code>x</code> is the variable, the decomposition is - <code>(f+x)(f+x')</code>. The variable is chosen so as to balance - the sizes of the two conjuncts and to keep them small. Returns the - number of conjuncts produced, that is, 2 if successful; 1 if no - meaningful decomposition was found; 0 otherwise.] - - SideEffects [The two factors are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the conjuncts are already - referenced. If the function returns 0, the array for the conjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddVarDisjDecomp Cudd_bddGenConjDecomp - Cudd_bddApproxConjDecomp Cudd_bddIterConjDecomp] - -*****************************************************************************/ -int -Cudd_bddVarConjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** conjuncts /* address of the array of conjuncts */) -{ - int best; - int min; - DdNode *support, *scan, *var, *glocal, *hlocal; - - /* Find best cofactoring variable. */ - support = Cudd_Support(dd,f); - if (support == NULL) return(0); - if (Cudd_IsConstant(support)) { - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = f; - cuddRef((*conjuncts)[0]); - return(1); - } - cuddRef(support); - min = 1000000000; - best = -1; - scan = support; - while (!Cudd_IsConstant(scan)) { - int i = scan->index; - int est1 = Cudd_EstimateCofactor(dd,f,i,1); - int est0 = Cudd_EstimateCofactor(dd,f,i,0); - /* Minimize the size of the larger of the two cofactors. */ - int est = (est1 > est0) ? est1 : est0; - if (est < min) { - min = est; - best = i; - } - scan = cuddT(scan); - } -#ifdef DD_DEBUG - assert(best >= 0 && best < dd->size); -#endif - Cudd_RecursiveDeref(dd,support); - - var = Cudd_bddIthVar(dd,best); - glocal = Cudd_bddOr(dd,f,var); - if (glocal == NULL) { - return(0); - } - cuddRef(glocal); - hlocal = Cudd_bddOr(dd,f,Cudd_Not(var)); - if (hlocal == NULL) { - Cudd_RecursiveDeref(dd,glocal); - return(0); - } - cuddRef(hlocal); - - if (glocal != DD_ONE(dd)) { - if (hlocal != DD_ONE(dd)) { - *conjuncts = ALLOC(DdNode *,2); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - (*conjuncts)[1] = hlocal; - return(2); - } else { - Cudd_RecursiveDeref(dd,hlocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - return(1); - } - } else { - Cudd_RecursiveDeref(dd,glocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = hlocal; - return(1); - } - -} /* end of Cudd_bddVarConjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way disjunctive decomposition of a BDD.] - - Description [Performs two-way disjunctive decomposition of a BDD - according to a variable. If <code>f</code> is the function of the - BDD and <code>x</code> is the variable, the decomposition is - <code>f*x + f*x'</code>. The variable is chosen so as to balance - the sizes of the two disjuncts and to keep them small. Returns the - number of disjuncts produced, that is, 2 if successful; 1 if no - meaningful decomposition was found; 0 otherwise.] - - SideEffects [The two disjuncts are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the disjuncts are already - referenced. If the function returns 0, the array for the disjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddVarConjDecomp Cudd_bddApproxDisjDecomp - Cudd_bddIterDisjDecomp Cudd_bddGenDisjDecomp] - -******************************************************************************/ -int -Cudd_bddVarDisjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** disjuncts /* address of the array of the disjuncts */) -{ - int result, i; - - result = Cudd_bddVarConjDecomp(dd,Cudd_Not(f),disjuncts); - for (i = 0; i < result; i++) { - (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); - } - return(result); - -} /* end of Cudd_bddVarDisjDecomp */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Get longest distance of node from constant.] - - Description [Get longest distance of node from constant. Returns the - distance of the root from the constant if successful; CUDD_OUT_OF_MEM - otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static NodeStat * -CreateBotDist( - DdNode * node, - st_table * distanceTable) -{ - DdNode *N, *Nv, *Nnv; - int distance, distanceNv, distanceNnv; - NodeStat *nodeStat, *nodeStatNv, *nodeStatNnv; - -#if 0 - if (Cudd_IsConstant(node)) { - return(0); - } -#endif - - /* Return the entry in the table if found. */ - N = Cudd_Regular(node); - if (st_lookup(distanceTable, (char *)N, (char **)&nodeStat)) { - nodeStat->localRef++; - return(nodeStat); - } - - Nv = cuddT(N); - Nnv = cuddE(N); - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - /* Recur on the children. */ - nodeStatNv = CreateBotDist(Nv, distanceTable); - if (nodeStatNv == NULL) return(NULL); - distanceNv = nodeStatNv->distance; - - nodeStatNnv = CreateBotDist(Nnv, distanceTable); - if (nodeStatNnv == NULL) return(NULL); - distanceNnv = nodeStatNnv->distance; - /* Store max distance from constant; note sometimes this distance - ** may be to 0. - */ - distance = (distanceNv > distanceNnv) ? (distanceNv+1) : (distanceNnv + 1); - - nodeStat = ALLOC(NodeStat, 1); - if (nodeStat == NULL) { - return(0); - } - nodeStat->distance = distance; - nodeStat->localRef = 1; - - if (st_insert(distanceTable, (char *)N, (char *)nodeStat) == - ST_OUT_OF_MEM) { - return(0); - - } - return(nodeStat); - -} /* end of CreateBotDist */ - - -/**Function******************************************************************** - - Synopsis [Count the number of minterms of each node ina a BDD and - store it in a hash table.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static double -CountMinterms( - DdNode * node, - double max, - st_table * mintermTable, - FILE *fp) -{ - DdNode *N, *Nv, *Nnv; - double min, minNv, minNnv; - double *dummy; - - N = Cudd_Regular(node); - - if (cuddIsConstant(N)) { - if (node == zero) { - return(0); - } else { - return(max); - } - } - - /* Return the entry in the table if found. */ - if (st_lookup(mintermTable, (char *)node, (char **)&dummy)) { - min = *dummy; - return(min); - } - - Nv = cuddT(N); - Nnv = cuddE(N); - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - /* Recur on the children. */ - minNv = CountMinterms(Nv, max, mintermTable, fp); - if (minNv == -1.0) return(-1.0); - minNnv = CountMinterms(Nnv, max, mintermTable, fp); - if (minNnv == -1.0) return(-1.0); - min = minNv / 2.0 + minNnv / 2.0; - /* store - */ - - dummy = ALLOC(double, 1); - if (dummy == NULL) return(-1.0); - *dummy = min; - if (st_insert(mintermTable, (char *)node, (char *)dummy) == ST_OUT_OF_MEM) { - (void) fprintf(fp, "st table insert failed\n"); - } - return(min); - -} /* end of CountMinterms */ - - -/**Function******************************************************************** - - Synopsis [Free factors structure] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -ConjunctsFree( - DdManager * dd, - Conjuncts * factors) -{ - Cudd_RecursiveDeref(dd, factors->g); - Cudd_RecursiveDeref(dd, factors->h); - FREE(factors); - return; - -} /* end of ConjunctsFree */ - - -/**Function******************************************************************** - - Synopsis [Check whether the given pair is in the tables.] - - Description [.Check whether the given pair is in the tables. gTable - and hTable are combined. - absence in both is indicated by 0, - presence in gTable is indicated by 1, - presence in hTable by 2 and - presence in both by 3. - The values returned by this function are PAIR_ST, - PAIR_CR, G_ST, G_CR, H_ST, H_CR, BOTH_G, BOTH_H, NONE. - PAIR_ST implies g in gTable and h in hTable - PAIR_CR implies g in hTable and h in gTable - G_ST implies g in gTable and h not in any table - G_CR implies g in hTable and h not in any table - H_ST implies h in hTable and g not in any table - H_CR implies h in gTable and g not in any table - BOTH_G implies both in gTable - BOTH_H implies both in hTable - NONE implies none in table; ] - - SideEffects [] - - SeeAlso [CheckTablesCacheAndReturn CheckInTables] - -******************************************************************************/ -static int -PairInTables( - DdNode * g, - DdNode * h, - st_table * ghTable) -{ - int valueG, valueH, gPresent, hPresent; - - valueG = valueH = gPresent = hPresent = 0; - - gPresent = st_lookup_int(ghTable, (char *)Cudd_Regular(g), &valueG); - hPresent = st_lookup_int(ghTable, (char *)Cudd_Regular(h), &valueH); - - if (!gPresent && !hPresent) return(NONE); - - if (!hPresent) { - if (valueG & 1) return(G_ST); - if (valueG & 2) return(G_CR); - } - if (!gPresent) { - if (valueH & 1) return(H_CR); - if (valueH & 2) return(H_ST); - } - /* both in tables */ - if ((valueG & 1) && (valueH & 2)) return(PAIR_ST); - if ((valueG & 2) && (valueH & 1)) return(PAIR_CR); - - if (valueG & 1) { - return(BOTH_G); - } else { - return(BOTH_H); - } - -} /* end of PairInTables */ - - -/**Function******************************************************************** - - Synopsis [Check the tables for the existence of pair and return one - combination, cache the result.] - - Description [Check the tables for the existence of pair and return - one combination, cache the result. The assumption is that one of the - conjuncts is already in the tables.] - - SideEffects [g and h referenced for the cache] - - SeeAlso [ZeroCase] - -******************************************************************************/ -static Conjuncts * -CheckTablesCacheAndReturn( - DdNode * node, - DdNode * g, - DdNode * h, - st_table * ghTable, - st_table * cacheTable) -{ - int pairValue; - int value; - Conjuncts *factors; - - value = 0; - /* check tables */ - pairValue = PairInTables(g, h, ghTable); - assert(pairValue != NONE); - /* if both dont exist in table, we know one exists(either g or h). - * Therefore store the other and proceed - */ - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) return(NULL); - if ((pairValue == BOTH_H) || (pairValue == H_ST)) { - if (g != one) { - value = 0; - if (st_lookup_int(ghTable, (char *)Cudd_Regular(g), &value)) { - value |= 1; - } else { - value = 1; - } - if (st_insert(ghTable, (char *)Cudd_Regular(g), - (char *)(long)value) == ST_OUT_OF_MEM) { - return(NULL); - } - } - factors->g = g; - factors->h = h; - } else if ((pairValue == BOTH_G) || (pairValue == G_ST)) { - if (h != one) { - value = 0; - if (st_lookup_int(ghTable, (char *)Cudd_Regular(h), &value)) { - value |= 2; - } else { - value = 2; - } - if (st_insert(ghTable, (char *)Cudd_Regular(h), - (char *)(long)value) == ST_OUT_OF_MEM) { - return(NULL); - } - } - factors->g = g; - factors->h = h; - } else if (pairValue == H_CR) { - if (g != one) { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(g), - (char *)(long)value) == ST_OUT_OF_MEM) { - return(NULL); - } - } - factors->g = h; - factors->h = g; - } else if (pairValue == G_CR) { - if (h != one) { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(h), - (char *)(long)value) == ST_OUT_OF_MEM) { - return(NULL); - } - } - factors->g = h; - factors->h = g; - } else if (pairValue == PAIR_CR) { - /* pair exists in table */ - factors->g = h; - factors->h = g; - } else if (pairValue == PAIR_ST) { - factors->g = g; - factors->h = h; - } - - /* cache the result for this node */ - if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - - return(factors); - -} /* end of CheckTablesCacheAndReturn */ - -/**Function******************************************************************** - - Synopsis [Check the tables for the existence of pair and return one - combination, store in cache.] - - Description [Check the tables for the existence of pair and return - one combination, store in cache. The pair that has more pointers to - it is picked. An approximation of the number of local pointers is - made by taking the reference count of the pairs sent. ] - - SideEffects [] - - SeeAlso [ZeroCase BuildConjuncts] - -******************************************************************************/ -static Conjuncts * -PickOnePair( - DdNode * node, - DdNode * g1, - DdNode * h1, - DdNode * g2, - DdNode * h2, - st_table * ghTable, - st_table * cacheTable) -{ - int value; - Conjuncts *factors; - int oneRef, twoRef; - - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) return(NULL); - - /* count the number of pointers to pair 2 */ - if (h2 == one) { - twoRef = (Cudd_Regular(g2))->ref; - } else if (g2 == one) { - twoRef = (Cudd_Regular(h2))->ref; - } else { - twoRef = ((Cudd_Regular(g2))->ref + (Cudd_Regular(h2))->ref)/2; - } - - /* count the number of pointers to pair 1 */ - if (h1 == one) { - oneRef = (Cudd_Regular(g1))->ref; - } else if (g1 == one) { - oneRef = (Cudd_Regular(h1))->ref; - } else { - oneRef = ((Cudd_Regular(g1))->ref + (Cudd_Regular(h1))->ref)/2; - } - - /* pick the pair with higher reference count */ - if (oneRef >= twoRef) { - factors->g = g1; - factors->h = h1; - } else { - factors->g = g2; - factors->h = h2; - } - - /* - * Store computed factors in respective tables to encourage - * recombination. - */ - if (factors->g != one) { - /* insert g in htable */ - value = 0; - if (st_lookup_int(ghTable, (char *)Cudd_Regular(factors->g), &value)) { - if (value == 2) { - value |= 1; - if (st_insert(ghTable, (char *)Cudd_Regular(factors->g), - (char *)(long)value) == ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - } - } else { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(factors->g), - (char *)(long)value) == ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - } - } - - if (factors->h != one) { - /* insert h in htable */ - value = 0; - if (st_lookup_int(ghTable, (char *)Cudd_Regular(factors->h), &value)) { - if (value == 1) { - value |= 2; - if (st_insert(ghTable, (char *)Cudd_Regular(factors->h), - (char *)(long)value) == ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - } - } else { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(factors->h), - (char *)(long)value) == ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - } - } - - /* Store factors in cache table for later use. */ - if (st_insert(cacheTable, (char *)node, (char *)factors) == - ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - - return(factors); - -} /* end of PickOnePair */ - - -/**Function******************************************************************** - - Synopsis [Check if the two pairs exist in the table, If any of the - conjuncts do exist, store in the cache and return the corresponding pair.] - - Description [Check if the two pairs exist in the table. If any of - the conjuncts do exist, store in the cache and return the - corresponding pair.] - - SideEffects [] - - SeeAlso [ZeroCase BuildConjuncts] - -******************************************************************************/ -static Conjuncts * -CheckInTables( - DdNode * node, - DdNode * g1, - DdNode * h1, - DdNode * g2, - DdNode * h2, - st_table * ghTable, - st_table * cacheTable, - int * outOfMem) -{ - int pairValue1, pairValue2; - Conjuncts *factors; - int value; - - *outOfMem = 0; - - /* check existence of pair in table */ - pairValue1 = PairInTables(g1, h1, ghTable); - pairValue2 = PairInTables(g2, h2, ghTable); - - /* if none of the 4 exist in the gh tables, return NULL */ - if ((pairValue1 == NONE) && (pairValue2 == NONE)) { - return NULL; - } - - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) { - *outOfMem = 1; - return NULL; - } - - /* pairs that already exist in the table get preference. */ - if (pairValue1 == PAIR_ST) { - factors->g = g1; - factors->h = h1; - } else if (pairValue2 == PAIR_ST) { - factors->g = g2; - factors->h = h2; - } else if (pairValue1 == PAIR_CR) { - factors->g = h1; - factors->h = g1; - } else if (pairValue2 == PAIR_CR) { - factors->g = h2; - factors->h = g2; - } else if (pairValue1 == G_ST) { - /* g exists in the table, h is not found in either table */ - factors->g = g1; - factors->h = h1; - if (h1 != one) { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(h1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue1 == BOTH_G) { - /* g and h are found in the g table */ - factors->g = g1; - factors->h = h1; - if (h1 != one) { - value = 3; - if (st_insert(ghTable, (char *)Cudd_Regular(h1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue1 == H_ST) { - /* h exists in the table, g is not found in either table */ - factors->g = g1; - factors->h = h1; - if (g1 != one) { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(g1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue1 == BOTH_H) { - /* g and h are found in the h table */ - factors->g = g1; - factors->h = h1; - if (g1 != one) { - value = 3; - if (st_insert(ghTable, (char *)Cudd_Regular(g1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == G_ST) { - /* g exists in the table, h is not found in either table */ - factors->g = g2; - factors->h = h2; - if (h2 != one) { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(h2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == BOTH_G) { - /* g and h are found in the g table */ - factors->g = g2; - factors->h = h2; - if (h2 != one) { - value = 3; - if (st_insert(ghTable, (char *)Cudd_Regular(h2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == H_ST) { - /* h exists in the table, g is not found in either table */ - factors->g = g2; - factors->h = h2; - if (g2 != one) { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(g2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == BOTH_H) { - /* g and h are found in the h table */ - factors->g = g2; - factors->h = h2; - if (g2 != one) { - value = 3; - if (st_insert(ghTable, (char *)Cudd_Regular(g2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue1 == G_CR) { - /* g found in h table and h in none */ - factors->g = h1; - factors->h = g1; - if (h1 != one) { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(h1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue1 == H_CR) { - /* h found in g table and g in none */ - factors->g = h1; - factors->h = g1; - if (g1 != one) { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(g1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == G_CR) { - /* g found in h table and h in none */ - factors->g = h2; - factors->h = g2; - if (h2 != one) { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(h2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == H_CR) { - /* h found in g table and g in none */ - factors->g = h2; - factors->h = g2; - if (g2 != one) { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(g2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } - - /* Store factors in cache table for later use. */ - if (st_insert(cacheTable, (char *)node, (char *)factors) == - ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - return factors; -} /* end of CheckInTables */ - - - -/**Function******************************************************************** - - Synopsis [If one child is zero, do explicitly what Restrict does or better] - - Description [If one child is zero, do explicitly what Restrict does or better. - First separate a variable and its child in the base case. In case of a cube - times a function, separate the cube and function. As a last resort, look in - tables.] - - SideEffects [Frees the BDDs in factorsNv. factorsNv itself is not freed - because it is freed above.] - - SeeAlso [BuildConjuncts] - -******************************************************************************/ -static Conjuncts * -ZeroCase( - DdManager * dd, - DdNode * node, - Conjuncts * factorsNv, - st_table * ghTable, - st_table * cacheTable, - int switched) -{ - int topid; - DdNode *g, *h, *g1, *g2, *h1, *h2, *x, *N, *G, *H, *Gv, *Gnv; - DdNode *Hv, *Hnv; - int value; - int outOfMem; - Conjuncts *factors; - - /* get var at this node */ - N = Cudd_Regular(node); - topid = N->index; - x = dd->vars[topid]; - x = (switched) ? Cudd_Not(x): x; - cuddRef(x); - - /* Seprate variable and child */ - if (factorsNv->g == one) { - Cudd_RecursiveDeref(dd, factorsNv->g); - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, x); - return(NULL); - } - factors->g = x; - factors->h = factorsNv->h; - /* cache the result*/ - if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, x); - FREE(factors); - return NULL; - } - - /* store x in g table, the other node is already in the table */ - if (st_lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) { - value |= 1; - } else { - value = 1; - } - if (st_insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - return NULL; - } - return(factors); - } - - /* Seprate variable and child */ - if (factorsNv->h == one) { - Cudd_RecursiveDeref(dd, factorsNv->h); - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, x); - return(NULL); - } - factors->g = factorsNv->g; - factors->h = x; - /* cache the result. */ - if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, x); - FREE(factors); - return(NULL); - } - /* store x in h table, the other node is already in the table */ - if (st_lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) { - value |= 2; - } else { - value = 2; - } - if (st_insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - return NULL; - } - return(factors); - } - - G = Cudd_Regular(factorsNv->g); - Gv = cuddT(G); - Gnv = cuddE(G); - Gv = Cudd_NotCond(Gv, Cudd_IsComplement(node)); - Gnv = Cudd_NotCond(Gnv, Cudd_IsComplement(node)); - /* if the child below is a variable */ - if ((Gv == zero) || (Gnv == zero)) { - h = factorsNv->h; - g = cuddBddAndRecur(dd, x, factorsNv->g); - if (g != NULL) cuddRef(g); - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, x); - if (g == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->h); - return NULL; - } - /* CheckTablesCacheAndReturn responsible for allocating - * factors structure., g,h referenced for cache store the - */ - factors = CheckTablesCacheAndReturn(node, - g, - h, - ghTable, - cacheTable); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g); - Cudd_RecursiveDeref(dd, h); - } - return(factors); - } - - H = Cudd_Regular(factorsNv->h); - Hv = cuddT(H); - Hnv = cuddE(H); - Hv = Cudd_NotCond(Hv, Cudd_IsComplement(node)); - Hnv = Cudd_NotCond(Hnv, Cudd_IsComplement(node)); - /* if the child below is a variable */ - if ((Hv == zero) || (Hnv == zero)) { - g = factorsNv->g; - h = cuddBddAndRecur(dd, x, factorsNv->h); - if (h!= NULL) cuddRef(h); - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, x); - if (h == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - return NULL; - } - /* CheckTablesCacheAndReturn responsible for allocating - * factors structure.g,h referenced for table store - */ - factors = CheckTablesCacheAndReturn(node, - g, - h, - ghTable, - cacheTable); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g); - Cudd_RecursiveDeref(dd, h); - } - return(factors); - } - - /* build g1 = x*g; h1 = h */ - /* build g2 = g; h2 = x*h */ - Cudd_RecursiveDeref(dd, x); - h1 = factorsNv->h; - g1 = cuddBddAndRecur(dd, x, factorsNv->g); - if (g1 != NULL) cuddRef(g1); - if (g1 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNv->h); - return NULL; - } - - g2 = factorsNv->g; - h2 = cuddBddAndRecur(dd, x, factorsNv->h); - if (h2 != NULL) cuddRef(h2); - if (h2 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNv->g); - return NULL; - } - - /* check whether any pair is in tables */ - factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem); - if (outOfMem) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - return NULL; - } - if (factors != NULL) { - if ((factors->g == g1) || (factors->g == h1)) { - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - } - return factors; - } - - /* check for each pair in tables and choose one */ - factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - /* now free what was created and not used */ - if ((factors->g == g1) || (factors->g == h1)) { - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - } - } - - return(factors); -} /* end of ZeroCase */ - - -/**Function******************************************************************** - - Synopsis [Builds the conjuncts recursively, bottom up.] - - Description [Builds the conjuncts recursively, bottom up. Constants - are returned as (f, f). The cache is checked for previously computed - result. The decomposition points are determined by the local - reference count of this node and the longest distance from the - constant. At the decomposition point, the factors returned are (f, - 1). Recur on the two children. The order is determined by the - heavier branch. Combine the factors of the two children and pick the - one that already occurs in the gh table. Occurence in g is indicated - by value 1, occurence in h by 2, occurence in both 3.] - - SideEffects [] - - SeeAlso [cuddConjunctsAux] - -******************************************************************************/ -static Conjuncts * -BuildConjuncts( - DdManager * dd, - DdNode * node, - st_table * distanceTable, - st_table * cacheTable, - int approxDistance, - int maxLocalRef, - st_table * ghTable, - st_table * mintermTable) -{ - int topid, distance; - Conjuncts *factorsNv, *factorsNnv, *factors; - Conjuncts *dummy; - DdNode *N, *Nv, *Nnv, *temp, *g1, *g2, *h1, *h2, *topv; - double minNv = 0.0, minNnv = 0.0; - double *doubleDummy; - int switched =0; - int outOfMem; - int freeNv = 0, freeNnv = 0, freeTemp; - NodeStat *nodeStat; - int value; - - /* if f is constant, return (f,f) */ - if (Cudd_IsConstant(node)) { - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - factors->g = node; - factors->h = node; - return(FactorsComplement(factors)); - } - - /* If result (a pair of conjuncts) in cache, return the factors. */ - if (st_lookup(cacheTable, (char *)node, (char **)&dummy)) { - factors = dummy; - return(factors); - } - - /* check distance and local reference count of this node */ - N = Cudd_Regular(node); - if (!st_lookup(distanceTable, (char *)N, (char **)&nodeStat)) { - (void) fprintf(dd->err, "Not in table, Something wrong\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - distance = nodeStat->distance; - - /* at or below decomposition point, return (f, 1) */ - if (((nodeStat->localRef > maxLocalRef*2/3) && - (distance < approxDistance*2/3)) || - (distance <= approxDistance/4)) { - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - /* alternate assigning (f,1) */ - value = 0; - if (st_lookup_int(ghTable, (char *)Cudd_Regular(node), &value)) { - if (value == 3) { - if (!lastTimeG) { - factors->g = node; - factors->h = one; - lastTimeG = 1; - } else { - factors->g = one; - factors->h = node; - lastTimeG = 0; - } - } else if (value == 1) { - factors->g = node; - factors->h = one; - } else { - factors->g = one; - factors->h = node; - } - } else if (!lastTimeG) { - factors->g = node; - factors->h = one; - lastTimeG = 1; - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(factors); - return NULL; - } - } else { - factors->g = one; - factors->h = node; - lastTimeG = 0; - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(factors); - return NULL; - } - } - return(FactorsComplement(factors)); - } - - /* get the children and recur */ - Nv = cuddT(N); - Nnv = cuddE(N); - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - /* Choose which subproblem to solve first based on the number of - * minterms. We go first where there are more minterms. - */ - if (!Cudd_IsConstant(Nv)) { - if (!st_lookup(mintermTable, (char *)Nv, (char **)&doubleDummy)) { - (void) fprintf(dd->err, "Not in table: Something wrong\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - minNv = *doubleDummy; - } - - if (!Cudd_IsConstant(Nnv)) { - if (!st_lookup(mintermTable, (char *)Nnv, (char **)&doubleDummy)) { - (void) fprintf(dd->err, "Not in table: Something wrong\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - minNnv = *doubleDummy; - } - - if (minNv < minNnv) { - temp = Nv; - Nv = Nnv; - Nnv = temp; - switched = 1; - } - - /* build gt, ht recursively */ - if (Nv != zero) { - factorsNv = BuildConjuncts(dd, Nv, distanceTable, - cacheTable, approxDistance, maxLocalRef, - ghTable, mintermTable); - if (factorsNv == NULL) return(NULL); - freeNv = FactorsNotStored(factorsNv); - factorsNv = (freeNv) ? FactorsUncomplement(factorsNv) : factorsNv; - cuddRef(factorsNv->g); - cuddRef(factorsNv->h); - - /* Deal with the zero case */ - if (Nnv == zero) { - /* is responsible for freeing factorsNv */ - factors = ZeroCase(dd, node, factorsNv, ghTable, - cacheTable, switched); - if (freeNv) FREE(factorsNv); - return(factors); - } - } - - /* build ge, he recursively */ - if (Nnv != zero) { - factorsNnv = BuildConjuncts(dd, Nnv, distanceTable, - cacheTable, approxDistance, maxLocalRef, - ghTable, mintermTable); - if (factorsNnv == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNv->h); - if (freeNv) FREE(factorsNv); - return(NULL); - } - freeNnv = FactorsNotStored(factorsNnv); - factorsNnv = (freeNnv) ? FactorsUncomplement(factorsNnv) : factorsNnv; - cuddRef(factorsNnv->g); - cuddRef(factorsNnv->h); - - /* Deal with the zero case */ - if (Nv == zero) { - /* is responsible for freeing factorsNv */ - factors = ZeroCase(dd, node, factorsNnv, ghTable, - cacheTable, switched); - if (freeNnv) FREE(factorsNnv); - return(factors); - } - } - - /* construct the 2 pairs */ - /* g1 = x*gt + x'*ge; h1 = x*ht + x'*he; */ - /* g2 = x*gt + x'*he; h2 = x*ht + x'*ge */ - if (switched) { - factors = factorsNnv; - factorsNnv = factorsNv; - factorsNv = factors; - freeTemp = freeNv; - freeNv = freeNnv; - freeNnv = freeTemp; - } - - /* Build the factors for this node. */ - topid = N->index; - topv = dd->vars[topid]; - - g1 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->g); - if (g1 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNnv->g); - Cudd_RecursiveDeref(dd, factorsNnv->h); - if (freeNv) FREE(factorsNv); - if (freeNnv) FREE(factorsNnv); - return(NULL); - } - - cuddRef(g1); - - h1 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->h); - if (h1 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNnv->g); - Cudd_RecursiveDeref(dd, factorsNnv->h); - Cudd_RecursiveDeref(dd, g1); - if (freeNv) FREE(factorsNv); - if (freeNnv) FREE(factorsNnv); - return(NULL); - } - - cuddRef(h1); - - g2 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->h); - if (g2 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNnv->g); - Cudd_RecursiveDeref(dd, factorsNnv->h); - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - if (freeNv) FREE(factorsNv); - if (freeNnv) FREE(factorsNnv); - return(NULL); - } - cuddRef(g2); - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNnv->h); - - h2 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->g); - if (h2 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNnv->g); - Cudd_RecursiveDeref(dd, factorsNnv->h); - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - Cudd_RecursiveDeref(dd, g2); - if (freeNv) FREE(factorsNv); - if (freeNnv) FREE(factorsNnv); - return(NULL); - } - cuddRef(h2); - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNnv->g); - if (freeNv) FREE(factorsNv); - if (freeNnv) FREE(factorsNnv); - - /* check for each pair in tables and choose one */ - factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem); - if (outOfMem) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - return(NULL); - } - if (factors != NULL) { - if ((factors->g == g1) || (factors->g == h1)) { - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - } - return(factors); - } - - /* if not in tables, pick one pair */ - factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - /* now free what was created and not used */ - if ((factors->g == g1) || (factors->g == h1)) { - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - } - } - - return(factors); - -} /* end of BuildConjuncts */ - - -/**Function******************************************************************** - - Synopsis [Procedure to compute two conjunctive factors of f and place in *c1 and *c2.] - - Description [Procedure to compute two conjunctive factors of f and - place in *c1 and *c2. Sets up the required data - table of distances - from the constant and local reference count. Also minterm table. ] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -static int -cuddConjunctsAux( - DdManager * dd, - DdNode * f, - DdNode ** c1, - DdNode ** c2) -{ - st_table *distanceTable = NULL; - st_table *cacheTable = NULL; - st_table *mintermTable = NULL; - st_table *ghTable = NULL; - st_generator *stGen; - char *key, *value; - Conjuncts *factors; - int distance, approxDistance; - double max, minterms; - int freeFactors; - NodeStat *nodeStat; - int maxLocalRef; - - /* initialize */ - *c1 = NULL; - *c2 = NULL; - - /* initialize distances table */ - distanceTable = st_init_table(st_ptrcmp,st_ptrhash); - if (distanceTable == NULL) goto outOfMem; - - /* make the entry for the constant */ - nodeStat = ALLOC(NodeStat, 1); - if (nodeStat == NULL) goto outOfMem; - nodeStat->distance = 0; - nodeStat->localRef = 1; - if (st_insert(distanceTable, (char *)one, (char *)nodeStat) == ST_OUT_OF_MEM) { - goto outOfMem; - } - - /* Count node distances from constant. */ - nodeStat = CreateBotDist(f, distanceTable); - if (nodeStat == NULL) goto outOfMem; - - /* set the distance for the decomposition points */ - approxDistance = (DEPTH < nodeStat->distance) ? nodeStat->distance : DEPTH; - distance = nodeStat->distance; - - if (distance < approxDistance) { - /* Too small to bother. */ - *c1 = f; - *c2 = DD_ONE(dd); - cuddRef(*c1); cuddRef(*c2); - stGen = st_init_gen(distanceTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - FREE(value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(distanceTable); - return(1); - } - - /* record the maximum local reference count */ - maxLocalRef = 0; - stGen = st_init_gen(distanceTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - nodeStat = (NodeStat *)value; - maxLocalRef = (nodeStat->localRef > maxLocalRef) ? - nodeStat->localRef : maxLocalRef; - } - st_free_gen(stGen); stGen = NULL; - - - /* Count minterms for each node. */ - max = pow(2.0, (double)Cudd_SupportSize(dd,f)); /* potential overflow */ - mintermTable = st_init_table(st_ptrcmp,st_ptrhash); - if (mintermTable == NULL) goto outOfMem; - minterms = CountMinterms(f, max, mintermTable, dd->err); - if (minterms == -1.0) goto outOfMem; - - lastTimeG = Cudd_Random() & 1; - cacheTable = st_init_table(st_ptrcmp, st_ptrhash); - if (cacheTable == NULL) goto outOfMem; - ghTable = st_init_table(st_ptrcmp, st_ptrhash); - if (ghTable == NULL) goto outOfMem; - - /* Build conjuncts. */ - factors = BuildConjuncts(dd, f, distanceTable, cacheTable, - approxDistance, maxLocalRef, ghTable, mintermTable); - if (factors == NULL) goto outOfMem; - - /* free up tables */ - stGen = st_init_gen(distanceTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - FREE(value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(distanceTable); distanceTable = NULL; - st_free_table(ghTable); ghTable = NULL; - - stGen = st_init_gen(mintermTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - FREE(value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(mintermTable); mintermTable = NULL; - - freeFactors = FactorsNotStored(factors); - factors = (freeFactors) ? FactorsUncomplement(factors) : factors; - if (factors != NULL) { - *c1 = factors->g; - *c2 = factors->h; - cuddRef(*c1); - cuddRef(*c2); - if (freeFactors) FREE(factors); - -#if 0 - if ((*c1 == f) && (!Cudd_IsConstant(f))) { - assert(*c2 == one); - } - if ((*c2 == f) && (!Cudd_IsConstant(f))) { - assert(*c1 == one); - } - - if ((*c1 != one) && (!Cudd_IsConstant(f))) { - assert(!Cudd_bddLeq(dd, *c2, *c1)); - } - if ((*c2 != one) && (!Cudd_IsConstant(f))) { - assert(!Cudd_bddLeq(dd, *c1, *c2)); - } -#endif - } - - stGen = st_init_gen(cacheTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - ConjunctsFree(dd, (Conjuncts *)value); - } - st_free_gen(stGen); stGen = NULL; - - st_free_table(cacheTable); cacheTable = NULL; - - return(1); - -outOfMem: - if (distanceTable != NULL) { - stGen = st_init_gen(distanceTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - FREE(value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(distanceTable); distanceTable = NULL; - } - if (mintermTable != NULL) { - stGen = st_init_gen(mintermTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - FREE(value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(mintermTable); mintermTable = NULL; - } - if (ghTable != NULL) st_free_table(ghTable); - if (cacheTable != NULL) { - stGen = st_init_gen(cacheTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - ConjunctsFree(dd, (Conjuncts *)value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(cacheTable); cacheTable = NULL; - } - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - -} /* end of cuddConjunctsAux */ diff --git a/src/bdd/cudd/cuddEssent.c b/src/bdd/cudd/cuddEssent.c deleted file mode 100644 index db4b8b49..00000000 --- a/src/bdd/cudd/cuddEssent.c +++ /dev/null @@ -1,279 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddEssent.c] - - PackageName [cudd] - - Synopsis [Functions for the detection of essential variables.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_FindEssential() - <li> Cudd_bddIsVarEssential() - </ul> - Static procedures included in this module: - <ul> - <li> ddFindEssentialRecur() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddEssent.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * ddFindEssentialRecur ARGS((DdManager *dd, DdNode *f)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Finds the essential variables of a DD.] - - Description [Returns the cube of the essential variables. A positive - literal means that the variable must be set to 1 for the function to be - 1. A negative literal means that the variable must be set to 0 for the - function to be 1. Returns a pointer to the cube BDD if successful; - NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddIsVarEssential] - -******************************************************************************/ -DdNode * -Cudd_FindEssential( - DdManager * dd, - DdNode * f) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = ddFindEssentialRecur(dd,f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_FindEssential */ - - -/**Function******************************************************************** - - Synopsis [Determines whether a given variable is essential with a - given phase in a BDD.] - - Description [Determines whether a given variable is essential with a - given phase in a BDD. Uses Cudd_bddIteConstant. Returns 1 if phase == 1 - and f-->x_id, or if phase == 0 and f-->x_id'.] - - SideEffects [None] - - SeeAlso [Cudd_FindEssential] - -******************************************************************************/ -int -Cudd_bddIsVarEssential( - DdManager * manager, - DdNode * f, - int id, - int phase) -{ - DdNode *var; - int res; - DdNode *one, *zero; - - one = DD_ONE(manager); - zero = Cudd_Not(one); - - var = cuddUniqueInter(manager, id, one, zero); - - var = Cudd_NotCond(var,phase == 0); - - res = Cudd_bddIteConstant(manager, Cudd_Not(f), one, var) == one; - - return(res); - -} /* end of Cudd_bddIsVarEssential */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_FindEssential.] - - Description [Implements the recursive step of Cudd_FindEssential. - Returns a pointer to the cube BDD if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -ddFindEssentialRecur( - DdManager * dd, - DdNode * f) -{ - DdNode *T, *E, *F; - DdNode *essT, *essE, *res; - int index; - DdNode *one, *lzero, *azero; - - one = DD_ONE(dd); - F = Cudd_Regular(f); - /* If f is constant the set of essential variables is empty. */ - if (cuddIsConstant(F)) return(one); - - res = cuddCacheLookup1(dd,Cudd_FindEssential,f); - if (res != NULL) { - return(res); - } - - lzero = Cudd_Not(one); - azero = DD_ZERO(dd); - /* Find cofactors: here f is non-constant. */ - T = cuddT(F); - E = cuddE(F); - if (Cudd_IsComplement(f)) { - T = Cudd_Not(T); E = Cudd_Not(E); - } - - index = F->index; - if (Cudd_IsConstant(T) && T != lzero && T != azero) { - /* if E is zero, index is essential, otherwise there are no - ** essentials, because index is not essential and no other variable - ** can be, since setting index = 1 makes the function constant and - ** different from 0. - */ - if (E == lzero || E == azero) { - res = dd->vars[index]; - } else { - res = one; - } - } else if (T == lzero || T == azero) { - if (Cudd_IsConstant(E)) { /* E cannot be zero here */ - res = Cudd_Not(dd->vars[index]); - } else { /* E == non-constant */ - /* find essentials in the else branch */ - essE = ddFindEssentialRecur(dd,E); - if (essE == NULL) { - return(NULL); - } - cuddRef(essE); - - /* add index to the set with negative phase */ - res = cuddUniqueInter(dd,index,one,Cudd_Not(essE)); - if (res == NULL) { - Cudd_RecursiveDeref(dd,essE); - return(NULL); - } - res = Cudd_Not(res); - cuddDeref(essE); - } - } else { /* T == non-const */ - if (E == lzero || E == azero) { - /* find essentials in the then branch */ - essT = ddFindEssentialRecur(dd,T); - if (essT == NULL) { - return(NULL); - } - cuddRef(essT); - - /* add index to the set with positive phase */ - /* use And because essT may be complemented */ - res = cuddBddAndRecur(dd,dd->vars[index],essT); - if (res == NULL) { - Cudd_RecursiveDeref(dd,essT); - return(NULL); - } - cuddDeref(essT); - } else if (!Cudd_IsConstant(E)) { - /* if E is a non-zero constant there are no essentials - ** because T is non-constant. - */ - essT = ddFindEssentialRecur(dd,T); - if (essT == NULL) { - return(NULL); - } - if (essT == one) { - res = one; - } else { - cuddRef(essT); - essE = ddFindEssentialRecur(dd,E); - if (essE == NULL) { - Cudd_RecursiveDeref(dd,essT); - return(NULL); - } - cuddRef(essE); - - /* res = intersection(essT, essE) */ - res = cuddBddLiteralSetIntersectionRecur(dd,essT,essE); - if (res == NULL) { - Cudd_RecursiveDeref(dd,essT); - Cudd_RecursiveDeref(dd,essE); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd,essT); - Cudd_RecursiveDeref(dd,essE); - cuddDeref(res); - } - } else { /* E is a non-zero constant */ - res = one; - } - } - - cuddCacheInsert1(dd,Cudd_FindEssential, f, res); - return(res); - -} /* end of ddFindEssentialRecur */ - diff --git a/src/bdd/cudd/cuddExact.c b/src/bdd/cudd/cuddExact.c deleted file mode 100644 index 6852be68..00000000 --- a/src/bdd/cudd/cuddExact.c +++ /dev/null @@ -1,1004 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddExact.c] - - PackageName [cudd] - - Synopsis [Functions for exact variable reordering.] - - Description [External procedures included in this file: - <ul> - </ul> - Internal procedures included in this module: - <ul> - <li> cuddExact() - </ul> - Static procedures included in this module: - <ul> - <li> getMaxBinomial() - <li> gcd() - <li> getMatrix() - <li> freeMatrix() - <li> getLevelKeys() - <li> ddShuffle() - <li> ddSiftUp() - <li> updateUB() - <li> ddCountRoots() - <li> ddClearGlobal() - <li> computeLB() - <li> updateEntry() - <li> pushDown() - <li> initSymmInfo() - </ul>] - - Author [Cheng Hua, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddExact.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -#ifdef DD_STATS -static int ddTotalShuffles; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int getMaxBinomial ARGS((int n)); -static int gcd ARGS((int x, int y)); -static DdHalfWord ** getMatrix ARGS((int rows, int cols)); -static void freeMatrix ARGS((DdHalfWord **matrix)); -static int getLevelKeys ARGS((DdManager *table, int l)); -static int ddShuffle ARGS((DdManager *table, DdHalfWord *permutation, int lower, int upper)); -static int ddSiftUp ARGS((DdManager *table, int x, int xLow)); -static int updateUB ARGS((DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper)); -static int ddCountRoots ARGS((DdManager *table, int lower, int upper)); -static void ddClearGlobal ARGS((DdManager *table, int lower, int maxlevel)); -static int computeLB ARGS((DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level)); -static int updateEntry ARGS((DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper)); -static void pushDown ARGS((DdHalfWord *order, int j, int level)); -static DdHalfWord * initSymmInfo ARGS((DdManager *table, int lower, int upper)); -static int checkSymmInfo ARGS((DdManager *table, DdHalfWord *symmInfo, int index, int level)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Exact variable ordering algorithm.] - - Description [Exact variable ordering algorithm. Finds an optimum - order for the variables between lower and upper. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddExact( - DdManager * table, - int lower, - int upper) -{ - int k, i, j; - int maxBinomial, oldSubsets, newSubsets; - int subsetCost; - int size; /* number of variables to be reordered */ - int unused, nvars, level, result; - int upperBound, lowerBound, cost; - int roots; - char *mask = NULL; - DdHalfWord *symmInfo = NULL; - DdHalfWord **newOrder = NULL; - DdHalfWord **oldOrder = NULL; - int *newCost = NULL; - int *oldCost = NULL; - DdHalfWord **tmpOrder; - int *tmpCost; - DdHalfWord *bestOrder = NULL; - DdHalfWord *order; -#ifdef DD_STATS - int ddTotalSubsets; -#endif - - /* Restrict the range to be reordered by excluding unused variables - ** at the two ends. */ - while (table->subtables[lower].keys == 1 && - table->vars[table->invperm[lower]]->ref == 1 && - lower < upper) - lower++; - while (table->subtables[upper].keys == 1 && - table->vars[table->invperm[upper]]->ref == 1 && - lower < upper) - upper--; - if (lower == upper) return(1); /* trivial problem */ - - /* Apply symmetric sifting to get a good upper bound and to extract - ** symmetry information. */ - result = cuddSymmSiftingConv(table,lower,upper); - if (result == 0) goto cuddExactOutOfMem; - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - ddTotalShuffles = 0; - ddTotalSubsets = 0; -#endif - - /* Initialization. */ - nvars = table->size; - size = upper - lower + 1; - /* Count unused variable among those to be reordered. This is only - ** used to compute maxBinomial. */ - unused = 0; - for (i = lower + 1; i < upper; i++) { - if (table->subtables[i].keys == 1 && - table->vars[table->invperm[i]]->ref == 1) - unused++; - } - - /* Find the maximum number of subsets we may have to store. */ - maxBinomial = getMaxBinomial(size - unused); - if (maxBinomial == -1) goto cuddExactOutOfMem; - - newOrder = getMatrix(maxBinomial, size); - if (newOrder == NULL) goto cuddExactOutOfMem; - - newCost = ALLOC(int, maxBinomial); - if (newCost == NULL) goto cuddExactOutOfMem; - - oldOrder = getMatrix(maxBinomial, size); - if (oldOrder == NULL) goto cuddExactOutOfMem; - - oldCost = ALLOC(int, maxBinomial); - if (oldCost == NULL) goto cuddExactOutOfMem; - - bestOrder = ALLOC(DdHalfWord, size); - if (bestOrder == NULL) goto cuddExactOutOfMem; - - mask = ALLOC(char, nvars); - if (mask == NULL) goto cuddExactOutOfMem; - - symmInfo = initSymmInfo(table, lower, upper); - if (symmInfo == NULL) goto cuddExactOutOfMem; - - roots = ddCountRoots(table, lower, upper); - - /* Initialize the old order matrix for the empty subset and the best - ** order to the current order. The cost for the empty subset includes - ** the cost of the levels between upper and the constants. These levels - ** are not going to change. Hence, we count them only once. - */ - oldSubsets = 1; - for (i = 0; i < size; i++) { - oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower]; - } - subsetCost = table->constants.keys; - for (i = upper + 1; i < nvars; i++) - subsetCost += getLevelKeys(table,i); - oldCost[0] = subsetCost; - /* The upper bound is initialized to the current size of the BDDs. */ - upperBound = table->keys - table->isolated; - - /* Now consider subsets of increasing size. */ - for (k = 1; k <= size; k++) { -#if DD_STATS - (void) fprintf(table->out,"Processing subsets of size %d\n", k); - fflush(table->out); -#endif - newSubsets = 0; - level = size - k; /* offset of first bottom variable */ - - for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */ - order = oldOrder[i]; - cost = oldCost[i]; - lowerBound = computeLB(table, order, roots, cost, lower, upper, - level); - if (lowerBound >= upperBound) - continue; - /* Impose new order. */ - result = ddShuffle(table, order, lower, upper); - if (result == 0) goto cuddExactOutOfMem; - upperBound = updateUB(table,upperBound,bestOrder,lower,upper); - /* For each top bottom variable. */ - for (j = level; j >= 0; j--) { - /* Skip unused variables. */ - if (table->subtables[j+lower-1].keys == 1 && - table->vars[table->invperm[j+lower-1]]->ref == 1) continue; - /* Find cost under this order. */ - subsetCost = cost + getLevelKeys(table, lower + level); - newSubsets = updateEntry(table, order, level, subsetCost, - newOrder, newCost, newSubsets, mask, - lower, upper); - if (j == 0) - break; - if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0) - continue; - pushDown(order,j-1,level); - /* Impose new order. */ - result = ddShuffle(table, order, lower, upper); - if (result == 0) goto cuddExactOutOfMem; - upperBound = updateUB(table,upperBound,bestOrder,lower,upper); - } /* for each bottom variable */ - } /* for each subset of size k */ - - /* New orders become old orders in preparation for next iteration. */ - tmpOrder = oldOrder; tmpCost = oldCost; - oldOrder = newOrder; oldCost = newCost; - newOrder = tmpOrder; newCost = tmpCost; -#ifdef DD_STATS - ddTotalSubsets += newSubsets; -#endif - oldSubsets = newSubsets; - } - result = ddShuffle(table, bestOrder, lower, upper); - if (result == 0) goto cuddExactOutOfMem; -#ifdef DD_STATS -#ifdef DD_VERBOSE - (void) fprintf(table->out,"\n"); -#endif - (void) fprintf(table->out,"#:S_EXACT %8d: total subsets\n", - ddTotalSubsets); - (void) fprintf(table->out,"#:H_EXACT %8d: total shuffles", - ddTotalShuffles); -#endif - - freeMatrix(newOrder); - freeMatrix(oldOrder); - FREE(bestOrder); - FREE(oldCost); - FREE(newCost); - FREE(symmInfo); - FREE(mask); - return(1); - -cuddExactOutOfMem: - - if (newOrder != NULL) freeMatrix(newOrder); - if (oldOrder != NULL) freeMatrix(oldOrder); - if (bestOrder != NULL) FREE(bestOrder); - if (oldCost != NULL) FREE(oldCost); - if (newCost != NULL) FREE(newCost); - if (symmInfo != NULL) FREE(symmInfo); - if (mask != NULL) FREE(mask); - table->errorCode = CUDD_MEMORY_OUT; - return(0); - -} /* end of cuddExact */ - - -/**Function******************************************************************** - - Synopsis [Returns the maximum value of (n choose k) for a given n.] - - Description [Computes the maximum value of (n choose k) for a given - n. The maximum value occurs for k = n/2 when n is even, or k = - (n-1)/2 when n is odd. The algorithm used in this procedure is - quite inefficient, but it avoids intermediate overflow problems. - Returns the computed value if successful; -1 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -getMaxBinomial( - int n) -{ - int *numerator; - int i, j, k, y, g, result; - - k = (n & ~1) >> 1; - - numerator = ALLOC(int,k); - if (numerator == NULL) return(-1); - - for (i = 0; i < k; i++) - numerator[i] = n - i; - - for (i = k; i > 1; i--) { - y = i; - for (j = 0; j < k; j++) { - if (numerator[j] == 1) continue; - g = gcd(numerator[j], y); - if (g != 1) { - numerator[j] /= g; - if (y == g) break; - y /= g; - } - } - } - - result = 1; - for (i = 0; i < k; i++) - result *= numerator[i]; - - FREE(numerator); - return(result); - -} /* end of getMaxBinomial */ - - -/**Function******************************************************************** - - Synopsis [Returns the gcd of two integers.] - - Description [Returns the gcd of two integers. Uses the binary GCD - algorithm described in Cormen, Leiserson, and Rivest.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -gcd( - int x, - int y) -{ - int a; - int b; - int lsbMask; - - /* GCD(n,0) = n. */ - if (x == 0) return(y); - if (y == 0) return(x); - - a = x; b = y; lsbMask = 1; - - /* Here both a and b are != 0. The iteration maintains this invariant. - ** Hence, we only need to check for when they become equal. - */ - while (a != b) { - if (a & lsbMask) { - if (b & lsbMask) { /* both odd */ - if (a < b) { - b = (b - a) >> 1; - } else { - a = (a - b) >> 1; - } - } else { /* a odd, b even */ - b >>= 1; - } - } else { - if (b & lsbMask) { /* a even, b odd */ - a >>= 1; - } else { /* both even */ - lsbMask <<= 1; - } - } - } - - return(a); - -} /* end of gcd */ - - -/**Function******************************************************************** - - Synopsis [Allocates a two-dimensional matrix of ints.] - - Description [Allocates a two-dimensional matrix of ints. - Returns the pointer to the matrix if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [freeMatrix] - -******************************************************************************/ -static DdHalfWord ** -getMatrix( - int rows /* number of rows */, - int cols /* number of columns */) -{ - DdHalfWord **matrix; - int i; - - if (cols*rows == 0) return(NULL); - matrix = ALLOC(DdHalfWord *, rows); - if (matrix == NULL) return(NULL); - matrix[0] = ALLOC(DdHalfWord, cols*rows); - if (matrix[0] == NULL) return(NULL); - for (i = 1; i < rows; i++) { - matrix[i] = matrix[i-1] + cols; - } - return(matrix); - -} /* end of getMatrix */ - - -/**Function******************************************************************** - - Synopsis [Frees a two-dimensional matrix allocated by getMatrix.] - - Description [] - - SideEffects [None] - - SeeAlso [getMatrix] - -******************************************************************************/ -static void -freeMatrix( - DdHalfWord ** matrix) -{ - FREE(matrix[0]); - FREE(matrix); - return; - -} /* end of freeMatrix */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of nodes at one level of a unique table.] - - Description [Returns the number of nodes at one level of a unique table. - The projection function, if isolated, is not counted.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -getLevelKeys( - DdManager * table, - int l) -{ - int isolated; - int x; /* x is an index */ - - x = table->invperm[l]; - isolated = table->vars[x]->ref == 1; - - return(table->subtables[l].keys - isolated); - -} /* end of getLevelKeys */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables according to a given permutation.] - - Description [Reorders variables according to a given permutation. - The i-th permutation array contains the index of the variable that - should be brought to the i-th level. ddShuffle assumes that no - dead nodes are present and that the interaction matrix is properly - initialized. The reordering is achieved by a series of upward sifts. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddShuffle( - DdManager * table, - DdHalfWord * permutation, - int lower, - int upper) -{ - DdHalfWord index; - int level; - int position; - int numvars; - int result; -#ifdef DD_STATS - long localTime; - int initialSize; -#ifdef DD_VERBOSE - int finalSize; -#endif - int previousSize; -#endif - -#ifdef DD_STATS - localTime = util_cpu_time(); - initialSize = table->keys - table->isolated; -#endif - - numvars = table->size; - -#if 0 - (void) fprintf(table->out,"%d:", ddTotalShuffles); - for (level = 0; level < numvars; level++) { - (void) fprintf(table->out," %d", table->invperm[level]); - } - (void) fprintf(table->out,"\n"); -#endif - - for (level = 0; level <= upper - lower; level++) { - index = permutation[level]; - position = table->perm[index]; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddSiftUp(table,position,level+lower); - if (!result) return(0); - } - -#ifdef DD_STATS - ddTotalShuffles++; -#ifdef DD_VERBOSE - finalSize = table->keys - table->isolated; - if (finalSize < initialSize) { - (void) fprintf(table->out,"-"); - } else if (finalSize > initialSize) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - if ((ddTotalShuffles & 63) == 0) (void) fprintf(table->out,"\n"); - fflush(table->out); -#endif -#endif - - return(1); - -} /* end of ddShuffle */ - - -/**Function******************************************************************** - - Synopsis [Moves one variable up.] - - Description [Takes a variable from position x and sifts it up to - position xLow; xLow should be less than or equal to x. - Returns 1 if successful; 0 otherwise] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddSiftUp( - DdManager * table, - int x, - int xLow) -{ - int y; - int size; - - y = cuddNextLow(table,x); - while (y >= xLow) { - size = cuddSwapInPlace(table,y,x); - if (size == 0) { - return(0); - } - x = y; - y = cuddNextLow(table,x); - } - return(1); - -} /* end of ddSiftUp */ - - -/**Function******************************************************************** - - Synopsis [Updates the upper bound and saves the best order seen so far.] - - Description [Updates the upper bound and saves the best order seen so far. - Returns the current value of the upper bound.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -updateUB( - DdManager * table, - int oldBound, - DdHalfWord * bestOrder, - int lower, - int upper) -{ - int i; - int newBound = table->keys - table->isolated; - - if (newBound < oldBound) { -#ifdef DD_STATS - (void) fprintf(table->out,"New upper bound = %d\n", newBound); - fflush(table->out); -#endif - for (i = lower; i <= upper; i++) - bestOrder[i-lower] = (DdHalfWord) table->invperm[i]; - return(newBound); - } else { - return(oldBound); - } - -} /* end of updateUB */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of roots.] - - Description [Counts the number of roots at the levels between lower and - upper. The computation is based on breadth-first search. - A node is a root if it is not reachable from any previously visited node. - (All the nodes at level lower are therefore considered roots.) - The visited flag uses the LSB of the next pointer. Returns the root - count. The roots that are constant nodes are always ignored.] - - SideEffects [None] - - SeeAlso [ddClearGlobal] - -******************************************************************************/ -static int -ddCountRoots( - DdManager * table, - int lower, - int upper) -{ - int i,j; - DdNode *f; - DdNodePtr *nodelist; - DdNode *sentinel = &(table->sentinel); - int slots; - int roots = 0; - int maxlevel = lower; - - for (i = lower; i <= upper; 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)) { - if (f != table->vars[f->index]) { - roots++; - } - } - if (!Cudd_IsConstant(cuddT(f))) { - cuddT(f)->next = Cudd_Complement(cuddT(f)->next); - if (table->perm[cuddT(f)->index] > maxlevel) - maxlevel = table->perm[cuddT(f)->index]; - } - if (!Cudd_IsConstant(cuddE(f))) { - Cudd_Regular(cuddE(f))->next = - Cudd_Complement(Cudd_Regular(cuddE(f))->next); - if (table->perm[Cudd_Regular(cuddE(f))->index] > maxlevel) - maxlevel = table->perm[Cudd_Regular(cuddE(f))->index]; - } - f = Cudd_Regular(f->next); - } - } - } - ddClearGlobal(table, lower, maxlevel); - - return(roots); - -} /* end of ddCountRoots */ - - -/**Function******************************************************************** - - Synopsis [Scans the DD and clears the LSB of the next pointers.] - - Description [Scans the DD and clears the LSB of the next pointers. - The LSB of the next pointers are used as markers to tell whether a - node was reached. Once the roots are counted, these flags are - reset.] - - SideEffects [None] - - SeeAlso [ddCountRoots] - -******************************************************************************/ -static void -ddClearGlobal( - DdManager * table, - int lower, - int maxlevel) -{ - int i,j; - DdNode *f; - DdNodePtr *nodelist; - DdNode *sentinel = &(table->sentinel); - int slots; - - for (i = lower; i <= maxlevel; 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 */ - - -/**Function******************************************************************** - - Synopsis [Computes a lower bound on the size of a BDD.] - - Description [Computes a lower bound on the size of a BDD from the - following factors: - <ul> - <li> size of the lower part of it; - <li> size of the part of the upper part not subjected to reordering; - <li> number of roots in the part of the BDD subjected to reordering; - <li> variable in the support of the roots in the upper part of the - BDD subjected to reordering. - <ul/>] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -computeLB( - DdManager * table /* manager */, - DdHalfWord * order /* optimal order for the subset */, - int roots /* roots between lower and upper */, - int cost /* minimum cost for the subset */, - int lower /* lower level to be reordered */, - int upper /* upper level to be reordered */, - int level /* offset for the current top bottom var */ - ) -{ - int i; - int lb = cost; - int lb1 = 0; - int lb2; - int support; - DdHalfWord ref; - - /* The levels not involved in reordering are not going to change. - ** Add their sizes to the lower bound. - */ - for (i = 0; i < lower; i++) { - lb += getLevelKeys(table,i); - } - /* If a variable is in the support, then there is going - ** to be at least one node labeled by that variable. - */ - for (i = lower; i <= lower+level; i++) { - support = table->subtables[i].keys > 1 || - table->vars[order[i-lower]]->ref > 1; - lb1 += support; - } - - /* Estimate the number of nodes required to connect the roots to - ** the nodes in the bottom part. */ - if (lower+level+1 < table->size) { - if (lower+level < upper) - ref = table->vars[order[level+1]]->ref; - else - ref = table->vars[table->invperm[upper+1]]->ref; - lb2 = table->subtables[lower+level+1].keys - - (ref > (DdHalfWord) 1) - roots; - } else { - lb2 = 0; - } - - lb += lb1 > lb2 ? lb1 : lb2; - - return(lb); - -} /* end of computeLB */ - - -/**Function******************************************************************** - - Synopsis [Updates entry for a subset.] - - Description [Updates entry for a subset. Finds the subset, if it exists. - If the new order for the subset has lower cost, or if the subset did not - exist, it stores the new order and cost. Returns the number of subsets - currently in the table.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -updateEntry( - DdManager * table, - DdHalfWord * order, - int level, - int cost, - DdHalfWord ** orders, - int * costs, - int subsets, - char * mask, - int lower, - int upper) -{ - int i, j; - int size = upper - lower + 1; - - /* Build a mask that says what variables are in this subset. */ - for (i = lower; i <= upper; i++) - mask[table->invperm[i]] = 0; - for (i = level; i < size; i++) - mask[order[i]] = 1; - - /* Check each subset until a match is found or all subsets are examined. */ - for (i = 0; i < subsets; i++) { - DdHalfWord *subset = orders[i]; - for (j = level; j < size; j++) { - if (mask[subset[j]] == 0) - break; - } - if (j == size) /* no mismatches: success */ - break; - } - if (i == subsets || cost < costs[i]) { /* add or replace */ - for (j = 0; j < size; j++) - orders[i][j] = order[j]; - costs[i] = cost; - subsets += (i == subsets); - } - return(subsets); - -} /* end of updateEntry */ - - -/**Function******************************************************************** - - Synopsis [Pushes a variable in the order down to position "level."] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -pushDown( - DdHalfWord * order, - int j, - int level) -{ - int i; - DdHalfWord tmp; - - tmp = order[j]; - for (i = j; i < level; i++) { - order[i] = order[i+1]; - } - order[level] = tmp; - return; - -} /* end of pushDown */ - - -/**Function******************************************************************** - - Synopsis [Gathers symmetry information.] - - Description [Translates the symmetry information stored in the next - field of each subtable from level to indices. This procedure is called - immediately after symmetric sifting, so that the next fields are correct. - By translating this informaton in terms of indices, we make it independent - of subsequent reorderings. The format used is that of the next fields: - a circular list where each variable points to the next variable in the - same symmetry group. Only the entries between lower and upper are - considered. The procedure returns a pointer to an array - holding the symmetry information if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [checkSymmInfo] - -******************************************************************************/ -static DdHalfWord * -initSymmInfo( - DdManager * table, - int lower, - int upper) -{ - int level, index, next, nextindex; - DdHalfWord *symmInfo; - - symmInfo = ALLOC(DdHalfWord, table->size); - if (symmInfo == NULL) return(NULL); - - for (level = lower; level <= upper; level++) { - index = table->invperm[level]; - next = table->subtables[level].next; - nextindex = table->invperm[next]; - symmInfo[index] = nextindex; - } - return(symmInfo); - -} /* end of initSymmInfo */ - - -/**Function******************************************************************** - - Synopsis [Check symmetry condition.] - - Description [Returns 1 if a variable is the one with the highest index - among those belonging to a symmetry group that are in the top part of - the BDD. The top part is given by level.] - - SideEffects [None] - - SeeAlso [initSymmInfo] - -******************************************************************************/ -static int -checkSymmInfo( - DdManager * table, - DdHalfWord * symmInfo, - int index, - int level) -{ - int i; - - i = symmInfo[index]; - while (i != index) { - if (index < i && table->perm[i] <= level) - return(0); - i = symmInfo[i]; - } - return(1); - -} /* end of checkSymmInfo */ - diff --git a/src/bdd/cudd/cuddExport.c b/src/bdd/cudd/cuddExport.c deleted file mode 100644 index d148be42..00000000 --- a/src/bdd/cudd/cuddExport.c +++ /dev/null @@ -1,1289 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddExport.c] - - PackageName [cudd] - - Synopsis [Export functions.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_DumpBlif() - <li> Cudd_DumpBlifBody() - <li> Cudd_DumpDot() - <li> Cudd_DumpDaVinci() - <li> Cudd_DumpDDcal() - <li> Cudd_DumpFactoredForm() - </ul> - Internal procedures included in this module: - <ul> - </ul> - Static procedures included in this module: - <ul> - <li> ddDoDumpBlif() - <li> ddDoDumpDaVinci() - <li> ddDoDumpDDcal() - <li> ddDoDumpFactoredForm() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddExport.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddDoDumpBlif ARGS((DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names)); -static int ddDoDumpDaVinci ARGS((DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, long mask)); -static int ddDoDumpDDcal ARGS((DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, long mask)); -static int ddDoDumpFactoredForm ARGS((DdManager *dd, DdNode *f, FILE *fp, char **names)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Writes a blif file representing the argument BDDs.] - - Description [Writes a blif file representing the argument BDDs as a - network of multiplexers. One multiplexer is written for each BDD - node. It returns 1 in case of success; 0 otherwise (e.g., - out-of-memory, file system full, or an ADD with constants different - from 0 and 1). Cudd_DumpBlif does not close the file: This is the - caller responsibility. Cudd_DumpBlif 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.] - - SideEffects [None] - - SeeAlso [Cudd_DumpBlifBody Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal - Cudd_DumpDaVinci Cudd_DumpFactoredForm] - -******************************************************************************/ -int -Cudd_DumpBlif( - 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) */, - char * mname /* model name (or NULL) */, - FILE * fp /* pointer to the dump file */) -{ - DdNode *support = NULL; - DdNode *scan; - int *sorted = NULL; - int nvars = dd->size; - int retval; - int i; - - /* 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. */ - support = Cudd_VectorSupport(dd,f,n); - 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 */ - - /* Write the header (.model .inputs .outputs). */ - if (mname == NULL) { - retval = fprintf(fp,".model DD\n.inputs"); - } else { - retval = fprintf(fp,".model %s\n.inputs",mname); - } - if (retval == EOF) return(0); - - /* Write the input list by scanning the support array. */ - for (i = 0; i < nvars; i++) { - if (sorted[i]) { - if (inames == NULL) { - retval = fprintf(fp," %d", i); - } else { - retval = fprintf(fp," %s", inames[i]); - } - if (retval == EOF) goto failure; - } - } - FREE(sorted); - sorted = NULL; - - /* Write the .output line. */ - retval = fprintf(fp,"\n.outputs"); - 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; - } - retval = fprintf(fp,"\n"); - if (retval == EOF) goto failure; - - retval = Cudd_DumpBlifBody(dd, n, f, inames, onames, fp); - if (retval == 0) goto failure; - - /* Write trailer and return. */ - retval = fprintf(fp,".end\n"); - if (retval == EOF) goto failure; - - return(1); - -failure: - if (sorted != NULL) FREE(sorted); - if (support != NULL) Cudd_RecursiveDeref(dd,support); - return(0); - -} /* end of Cudd_DumpBlif */ - - -/**Function******************************************************************** - - Synopsis [Writes a blif body representing the argument BDDs.] - - Description [Writes a blif body representing the argument BDDs as a - network of multiplexers. One multiplexer is written for each BDD - node. It returns 1 in case of success; 0 otherwise (e.g., - out-of-memory, file system full, or an ADD with constants different - from 0 and 1). Cudd_DumpBlif does not close the file: This is the - caller responsibility. Cudd_DumpBlif 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. This function prints out only - .names part.] - - SideEffects [None] - - SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal - Cudd_DumpDaVinci Cudd_DumpFactoredForm] - -******************************************************************************/ -int -Cudd_DumpBlifBody( - 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 */) -{ - st_table *visited = NULL; - int retval; - int i; - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - if (visited == NULL) goto failure; - - /* Call the function that really gets the job done. */ - for (i = 0; i < n; i++) { - retval = ddDoDumpBlif(dd,Cudd_Regular(f[i]),fp,visited,inames); - if (retval == 0) goto failure; - } - - /* To account for the possible complement on the root, - ** we put either a buffer or an inverter at the output of - ** the multiplexer representing the top node. - */ - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp, -#if SIZEOF_VOID_P == 8 - ".names %lx f%d\n", (unsigned long) f[i] / (unsigned long) sizeof(DdNode), i); -#else - ".names %x f%d\n", (unsigned) f[i] / (unsigned) sizeof(DdNode), i); -#endif - } else { - retval = fprintf(fp, -#if SIZEOF_VOID_P == 8 - ".names %lx %s\n", (unsigned long) f[i] / (unsigned long) sizeof(DdNode), onames[i]); -#else - ".names %x %s\n", (unsigned) f[i] / (unsigned) sizeof(DdNode), onames[i]); -#endif - } - if (retval == EOF) goto failure; - if (Cudd_IsComplement(f[i])) { - retval = fprintf(fp,"0 1\n"); - } else { - retval = fprintf(fp,"1 1\n"); - } - if (retval == EOF) goto failure; - } - - st_free_table(visited); - return(1); - -failure: - if (visited != NULL) st_free_table(visited); - return(0); - -} /* end of Cudd_DumpBlifBody */ - - -/**Function******************************************************************** - - Synopsis [Writes a dot file representing the argument DDs.] - - Description [Writes a file representing the argument DDs 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_DumpDot does not close the file: This is the caller - responsibility. Cudd_DumpDot 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_DumpDot uses the following convention to draw arcs: - <ul> - <li> solid line: THEN arcs; - <li> dotted line: complement arcs; - <li> dashed line: regular ELSE arcs. - </ul> - The dot options are chosen so that the drawing fits on a letter-size - sheet. - ] - - SideEffects [None] - - SeeAlso [Cudd_DumpBlif Cudd_PrintDebug Cudd_DumpDDcal - Cudd_DumpDaVinci Cudd_DumpFactoredForm] - -******************************************************************************/ -int -Cudd_DumpDot( - 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->size; - st_table *visited = NULL; - st_generator *gen = NULL; - 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. */ - support = Cudd_VectorSupport(dd,f,n); - 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(Cudd_Regular(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) Cudd_Regular(f[0]); - diff = 0; - gen = st_init_gen(visited); - if (gen == NULL) goto failure; - while (st_gen(gen, (char **) &scan, NULL)) { - diff |= refAddr ^ (long) scan; - } - st_free_gen(gen); gen = NULL; - - /* 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 \"DD\" {\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->invperm[i]]) { - if (inames == NULL || inames[dd->invperm[i]] == NULL) { - retval = fprintf(fp,"\" %d \" -> ", dd->invperm[i]); - } else { - retval = fprintf(fp,"\" %s \" -> ", inames[dd->invperm[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->invperm[i]]) { - retval = fprintf(fp,"{ rank = same; "); - if (retval == EOF) goto failure; - if (inames == NULL || inames[dd->invperm[i]] == NULL) { - retval = fprintf(fp,"\" %d \";\n", dd->invperm[i]); - } else { - retval = fprintf(fp,"\" %s \";\n", inames[dd->invperm[i]]); - } - if (retval == EOF) goto failure; - nodelist = dd->subtables[i].nodelist; - slots = dd->subtables[i].slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (st_is_member(visited,(char *) scan)) { - retval = fprintf(fp,"\"%lx\";\n", (mask & (long) 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,"\"%lx\";\n", (mask & (long) 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; - /* Account for the possible complement on the root. */ - if (Cudd_IsComplement(f[i])) { - retval = fprintf(fp," -> \"%lx\" [style = dotted];\n", - (mask & (long) f[i]) / sizeof(DdNode)); - } else { - retval = fprintf(fp," -> \"%lx\" [style = solid];\n", - (mask & (long) f[i]) / sizeof(DdNode)); - } - if (retval == EOF) goto failure; - } - - /* Edges from internal nodes. */ - for (i = 0; i < nvars; i++) { - if (sorted[dd->invperm[i]]) { - nodelist = dd->subtables[i].nodelist; - slots = dd->subtables[i].slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (st_is_member(visited,(char *) scan)) { - retval = fprintf(fp, - "\"%lx\" -> \"%lx\";\n", - (mask & (long) scan) / sizeof(DdNode), - (mask & (long) cuddT(scan)) / sizeof(DdNode)); - if (retval == EOF) goto failure; - if (Cudd_IsComplement(cuddE(scan))) { - retval = fprintf(fp, - "\"%lx\" -> \"%lx\" [style = dotted];\n", - (mask & (long) scan) / sizeof(DdNode), - (mask & (long) cuddE(scan)) / sizeof(DdNode)); - } else { - retval = fprintf(fp, - "\"%lx\" -> \"%lx\" [style = dashed];\n", - (mask & (long) scan) / sizeof(DdNode), - (mask & (long) 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,"\"%lx\" [label = \"%g\"];\n", - (mask & (long) 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 (support != NULL) Cudd_RecursiveDeref(dd,support); - if (visited != NULL) st_free_table(visited); - return(0); - -} /* end of Cudd_DumpDot */ - - -/**Function******************************************************************** - - Synopsis [Writes a daVinci file representing the argument BDDs.] - - Description [Writes a daVinci file representing the argument BDDs. - It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or - file system full). Cudd_DumpDaVinci does not close the file: This - is the caller responsibility. Cudd_DumpDaVinci 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.] - - SideEffects [None] - - SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDDcal - Cudd_DumpFactoredForm] - -******************************************************************************/ -int -Cudd_DumpDaVinci( - 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; - st_table *visited = NULL; - int retval; - int i; - st_generator *gen; - long refAddr, diff, mask; - - /* 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(Cudd_Regular(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) Cudd_Regular(f[0]); - diff = 0; - gen = st_init_gen(visited); - while (st_gen(gen, (char **) &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; - } - st_free_table(visited); - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - if (visited == NULL) goto failure; - - retval = fprintf(fp, "["); - if (retval == EOF) goto failure; - /* Call the function that really gets the job done. */ - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp, - "l(\"f%d\",n(\"root\",[a(\"OBJECT\",\"f%d\")],", - i,i); - } else { - retval = fprintf(fp, - "l(\"%s\",n(\"root\",[a(\"OBJECT\",\"%s\")],", - onames[i], onames[i]); - } - if (retval == EOF) goto failure; - retval = fprintf(fp, "[e(\"edge\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],", - Cudd_IsComplement(f[i]) ? "red" : "blue"); - if (retval == EOF) goto failure; - retval = ddDoDumpDaVinci(dd,Cudd_Regular(f[i]),fp,visited,inames,mask); - if (retval == 0) goto failure; - retval = fprintf(fp, ")]))%s", i == n-1 ? "" : ","); - if (retval == EOF) goto failure; - } - - /* Write trailer and return. */ - retval = fprintf(fp, "]\n"); - if (retval == EOF) goto failure; - - st_free_table(visited); - return(1); - -failure: - if (support != NULL) Cudd_RecursiveDeref(dd,support); - if (visited != NULL) st_free_table(visited); - return(0); - -} /* end of Cudd_DumpDaVinci */ - - -/**Function******************************************************************** - - Synopsis [Writes a DDcal file representing the argument BDDs.] - - Description [Writes a DDcal file representing the argument BDDs. - It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or - file system full). Cudd_DumpDDcal does not close the file: This - is the caller responsibility. Cudd_DumpDDcal 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.] - - SideEffects [None] - - SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci - Cudd_DumpFactoredForm] - -******************************************************************************/ -int -Cudd_DumpDDcal( - 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->size; - st_table *visited = NULL; - int retval; - int i; - st_generator *gen; - long refAddr, diff, mask; - - /* 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(Cudd_Regular(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) Cudd_Regular(f[0]); - diff = 0; - gen = st_init_gen(visited); - while (st_gen(gen, (char **) &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; - } - st_free_table(visited); - - /* 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. */ - support = Cudd_VectorSupport(dd,f,n); - 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 */ - for (i = 0; i < nvars; i++) { - if (sorted[dd->invperm[i]]) { - if (inames == NULL || inames[dd->invperm[i]] == NULL) { - retval = fprintf(fp,"v%d", dd->invperm[i]); - } else { - retval = fprintf(fp,"%s", inames[dd->invperm[i]]); - } - if (retval == EOF) goto failure; - } - retval = fprintf(fp,"%s", i == nvars - 1 ? "\n" : " * "); - if (retval == EOF) goto failure; - } - FREE(sorted); - sorted = NULL; - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - if (visited == NULL) goto failure; - - /* Call the function that really gets the job done. */ - for (i = 0; i < n; i++) { - retval = ddDoDumpDDcal(dd,Cudd_Regular(f[i]),fp,visited,inames,mask); - if (retval == 0) goto failure; - if (onames == NULL) { - retval = fprintf(fp, "f%d = ", i); - } else { - retval = fprintf(fp, "%s = ", onames[i]); - } - if (retval == EOF) goto failure; - retval = fprintf(fp, "n%lx%s\n", - ((long) f[i] & mask) / sizeof(DdNode), - Cudd_IsComplement(f[i]) ? "'" : ""); - if (retval == EOF) goto failure; - } - - /* Write trailer and return. */ - retval = fprintf(fp, "["); - 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]); - } - retval = fprintf(fp, "%s", i == n-1 ? "" : " "); - if (retval == EOF) goto failure; - } - retval = fprintf(fp, "]\n"); - if (retval == EOF) goto failure; - - st_free_table(visited); - return(1); - -failure: - if (sorted != NULL) FREE(sorted); - if (support != NULL) Cudd_RecursiveDeref(dd,support); - if (visited != NULL) st_free_table(visited); - return(0); - -} /* end of Cudd_DumpDDcal */ - - -/**Function******************************************************************** - - Synopsis [Writes factored forms representing the argument BDDs.] - - Description [Writes factored forms representing the argument BDDs. - The format of the factored form is the one used in the genlib files - for technology mapping in sis. It returns 1 in case of success; 0 - otherwise (e.g., file system full). Cudd_DumpFactoredForm does not - close the file: This is the caller responsibility. Caution must be - exercised because a factored form may be exponentially larger than - the argument BDD. If the argument inames is non-null, it is assumed - to hold the pointers to the names of the inputs. Similarly for - onames.] - - SideEffects [None] - - SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci - Cudd_DumpDDcal] - -******************************************************************************/ -int -Cudd_DumpFactoredForm( - 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 */) -{ - int retval; - int i; - - /* Call the function that really gets the job done. */ - 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) return(0); - if (f[i] == DD_ONE(dd)) { - retval = fprintf(fp, "CONST1"); - if (retval == EOF) return(0); - } else if (f[i] == Cudd_Not(DD_ONE(dd)) || f[i] == DD_ZERO(dd)) { - retval = fprintf(fp, "CONST0"); - if (retval == EOF) return(0); - } else { - retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? "!(" : ""); - if (retval == EOF) return(0); - retval = ddDoDumpFactoredForm(dd,Cudd_Regular(f[i]),fp,inames); - if (retval == 0) return(0); - retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? ")" : ""); - if (retval == EOF) return(0); - } - retval = fprintf(fp, "%s", i == n-1 ? "" : "\n"); - if (retval == EOF) return(0); - } - - return(1); - -} /* end of Cudd_DumpFactoredForm */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_DumpBlif.] - - Description [Performs the recursive step of Cudd_DumpBlif. Traverses - the BDD f and writes a multiplexer-network description to the file - pointed by fp in blif format. f is assumed to be a regular pointer - and ddDoDumpBlif guarantees this assumption in the recursive calls.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddDoDumpBlif( - DdManager * dd, - DdNode * f, - FILE * fp, - st_table * visited, - char ** names) -{ - DdNode *T, *E; - int retval; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); -#endif - - /* If already visited, nothing to do. */ - if (st_is_member(visited, (char *) f) == 1) - return(1); - - /* Check for abnormal condition that should never happen. */ - if (f == NULL) - return(0); - - /* Mark node as visited. */ - if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) - return(0); - - /* Check for special case: If constant node, generate constant 1. */ - if (f == DD_ONE(dd)) { -#if SIZEOF_VOID_P == 8 - retval = fprintf(fp, ".names %lx\n1\n",(unsigned long) f / (unsigned long) sizeof(DdNode)); -#else - retval = fprintf(fp, ".names %x\n1\n",(unsigned) f / (unsigned) sizeof(DdNode)); -#endif - if (retval == EOF) { - return(0); - } else { - return(1); - } - } - - /* Check whether this is an ADD. We deal with 0-1 ADDs, but not - ** with the general case. - */ - if (f == DD_ZERO(dd)) { -#if SIZEOF_VOID_P == 8 - retval = fprintf(fp, ".names %lx\n",(unsigned long) f / (unsigned long) sizeof(DdNode)); -#else - retval = fprintf(fp, ".names %x\n",(unsigned) f / (unsigned) sizeof(DdNode)); -#endif - if (retval == EOF) { - return(0); - } else { - return(1); - } - } - if (cuddIsConstant(f)) - return(0); - - /* Recursive calls. */ - T = cuddT(f); - retval = ddDoDumpBlif(dd,T,fp,visited,names); - if (retval != 1) return(retval); - E = Cudd_Regular(cuddE(f)); - retval = ddDoDumpBlif(dd,E,fp,visited,names); - if (retval != 1) return(retval); - - /* Write multiplexer taking complement arc into account. */ - if (names != NULL) { - retval = fprintf(fp,".names %s", names[f->index]); - } else { - retval = fprintf(fp,".names %d", f->index); - } - if (retval == EOF) - return(0); - -#if SIZEOF_VOID_P == 8 - if (Cudd_IsComplement(cuddE(f))) { - retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-0 1\n", - (unsigned long) T / (unsigned long) sizeof(DdNode), - (unsigned long) E / (unsigned long) sizeof(DdNode), - (unsigned long) f / (unsigned long) sizeof(DdNode)); - } else { - retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-1 1\n", - (unsigned long) T / (unsigned long) sizeof(DdNode), - (unsigned long) E / (unsigned long) sizeof(DdNode), - (unsigned long) f / (unsigned long) sizeof(DdNode)); - } -#else - if (Cudd_IsComplement(cuddE(f))) { - retval = fprintf(fp," %x %x %x\n11- 1\n0-0 1\n", - (unsigned) T / (unsigned) sizeof(DdNode), - (unsigned) E / (unsigned) sizeof(DdNode), - (unsigned) f / (unsigned) sizeof(DdNode)); - } else { - retval = fprintf(fp," %x %x %x\n11- 1\n0-1 1\n", - (unsigned) T / (unsigned) sizeof(DdNode), - (unsigned) E / (unsigned) sizeof(DdNode), - (unsigned) f / (unsigned) sizeof(DdNode)); - } -#endif - if (retval == EOF) { - return(0); - } else { - return(1); - } - -} /* end of ddDoDumpBlif */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_DumpDaVinci.] - - Description [Performs the recursive step of Cudd_DumpDaVinci. Traverses - the BDD f and writes a term expression to the file - pointed by fp in daVinci format. f is assumed to be a regular pointer - and ddDoDumpDaVinci guarantees this assumption in the recursive calls.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddDoDumpDaVinci( - DdManager * dd, - DdNode * f, - FILE * fp, - st_table * visited, - char ** names, - long mask) -{ - DdNode *T, *E; - int retval; - long id; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); -#endif - - id = ((long) f & mask) / sizeof(DdNode); - - /* If already visited, insert a reference. */ - if (st_is_member(visited, (char *) f) == 1) { - retval = fprintf(fp,"r(\"%lx\")", id); - if (retval == EOF) { - return(0); - } else { - return(1); - } - } - - /* Check for abnormal condition that should never happen. */ - if (f == NULL) - return(0); - - /* Mark node as visited. */ - if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) - return(0); - - /* Check for special case: If constant node, generate constant 1. */ - if (Cudd_IsConstant(f)) { - retval = fprintf(fp, "l(\"%lx\",n(\"constant\",[a(\"OBJECT\",\"%g\")],[]))", id, cuddV(f)); - if (retval == EOF) { - return(0); - } else { - return(1); - } - } - - /* Recursive calls. */ - if (names != NULL) { - retval = fprintf(fp, - "l(\"%lx\",n(\"internal\",[a(\"OBJECT\",\"%s\"),", - id, names[f->index]); - } else { - retval = fprintf(fp, - "l(\"%lx\",n(\"internal\",[a(\"OBJECT\",\"%d\"),", - id, f->index); - } - retval = fprintf(fp, "a(\"_GO\",\"ellipse\")],[e(\"then\",[a(\"EDGECOLOR\",\"blue\"),a(\"_DIR\",\"none\")],"); - if (retval == EOF) return(0); - T = cuddT(f); - retval = ddDoDumpDaVinci(dd,T,fp,visited,names,mask); - if (retval != 1) return(retval); - retval = fprintf(fp, "),e(\"else\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],", - Cudd_IsComplement(cuddE(f)) ? "red" : "green"); - if (retval == EOF) return(0); - E = Cudd_Regular(cuddE(f)); - retval = ddDoDumpDaVinci(dd,E,fp,visited,names,mask); - if (retval != 1) return(retval); - - retval = fprintf(fp,")]))"); - if (retval == EOF) { - return(0); - } else { - return(1); - } - -} /* end of ddDoDumpDaVinci */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_DumpDDcal.] - - Description [Performs the recursive step of Cudd_DumpDDcal. Traverses - the BDD f and writes a line for each node to the file - pointed by fp in DDcal format. f is assumed to be a regular pointer - and ddDoDumpDDcal guarantees this assumption in the recursive calls.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddDoDumpDDcal( - DdManager * dd, - DdNode * f, - FILE * fp, - st_table * visited, - char ** names, - long mask) -{ - DdNode *T, *E; - int retval; - long id, idT, idE; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); -#endif - - id = ((long) f & mask) / sizeof(DdNode); - - /* If already visited, do nothing. */ - if (st_is_member(visited, (char *) f) == 1) { - return(1); - } - - /* Check for abnormal condition that should never happen. */ - if (f == NULL) - return(0); - - /* Mark node as visited. */ - if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) - return(0); - - /* Check for special case: If constant node, assign constant. */ - if (Cudd_IsConstant(f)) { - if (f != DD_ONE(dd) && f != DD_ZERO(dd)) - return(0); - retval = fprintf(fp, "n%lx = %g\n", id, cuddV(f)); - if (retval == EOF) { - return(0); - } else { - return(1); - } - } - - /* Recursive calls. */ - T = cuddT(f); - retval = ddDoDumpDDcal(dd,T,fp,visited,names,mask); - if (retval != 1) return(retval); - E = Cudd_Regular(cuddE(f)); - retval = ddDoDumpDDcal(dd,E,fp,visited,names,mask); - if (retval != 1) return(retval); - idT = ((long) T & mask) / sizeof(DdNode); - idE = ((long) E & mask) / sizeof(DdNode); - if (names != NULL) { - retval = fprintf(fp, "n%lx = %s * n%lx + %s' * n%lx%s\n", - id, names[f->index], idT, names[f->index], - idE, Cudd_IsComplement(cuddE(f)) ? "'" : ""); - } else { - retval = fprintf(fp, "n%lx = v%d * n%lx + v%d' * n%lx%s\n", - id, f->index, idT, f->index, - idE, Cudd_IsComplement(cuddE(f)) ? "'" : ""); - } - if (retval == EOF) { - return(0); - } else { - return(1); - } - -} /* end of ddDoDumpDDcal */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_DumpFactoredForm.] - - Description [Performs the recursive step of - Cudd_DumpFactoredForm. Traverses the BDD f and writes a factored - form for each node to the file pointed by fp in terms of the - factored forms of the children. Constants are propagated, and - absorption is applied. f is assumed to be a regular pointer and - ddDoDumpFActoredForm guarantees this assumption in the recursive - calls.] - - SideEffects [None] - - SeeAlso [Cudd_DumpFactoredForm] - -******************************************************************************/ -static int -ddDoDumpFactoredForm( - DdManager * dd, - DdNode * f, - FILE * fp, - char ** names) -{ - DdNode *T, *E; - int retval; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); - assert(!Cudd_IsConstant(f)); -#endif - - /* Check for abnormal condition that should never happen. */ - if (f == NULL) - return(0); - - /* Recursive calls. */ - T = cuddT(f); - E = cuddE(f); - if (T != DD_ZERO(dd)) { - if (E != DD_ONE(dd)) { - if (names != NULL) { - retval = fprintf(fp, "%s", names[f->index]); - } else { - retval = fprintf(fp, "x%d", f->index); - } - if (retval == EOF) return(0); - } - if (T != DD_ONE(dd)) { - retval = fprintf(fp, "%s(", E != DD_ONE(dd) ? " * " : ""); - if (retval == EOF) return(0); - retval = ddDoDumpFactoredForm(dd,T,fp,names); - if (retval != 1) return(retval); - retval = fprintf(fp, ")"); - if (retval == EOF) return(0); - } - if (E == Cudd_Not(DD_ONE(dd)) || E == DD_ZERO(dd)) return(1); - retval = fprintf(fp, " + "); - if (retval == EOF) return(0); - } - E = Cudd_Regular(E); - if (T != DD_ONE(dd)) { - if (names != NULL) { - retval = fprintf(fp, "!%s", names[f->index]); - } else { - retval = fprintf(fp, "!x%d", f->index); - } - if (retval == EOF) return(0); - } - if (E != DD_ONE(dd)) { - retval = fprintf(fp, "%s%s(", T != DD_ONE(dd) ? " * " : "", - E != cuddE(f) ? "!" : ""); - if (retval == EOF) return(0); - retval = ddDoDumpFactoredForm(dd,E,fp,names); - if (retval != 1) return(retval); - retval = fprintf(fp, ")"); - if (retval == EOF) return(0); - } - return(1); - -} /* end of ddDoDumpFactoredForm */ - diff --git a/src/bdd/cudd/cuddGenCof.c b/src/bdd/cudd/cuddGenCof.c deleted file mode 100644 index 142ee27e..00000000 --- a/src/bdd/cudd/cuddGenCof.c +++ /dev/null @@ -1,1968 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddGenCof.c] - - PackageName [cudd] - - Synopsis [Generalized cofactors for BDDs and ADDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_bddConstrain() - <li> Cudd_bddRestrict() - <li> Cudd_addConstrain() - <li> Cudd_bddConstrainDecomp() - <li> Cudd_addRestrict() - <li> Cudd_bddCharToVect() - <li> Cudd_bddLICompaction() - <li> Cudd_bddSqueeze() - <li> Cudd_SubsetCompress() - <li> Cudd_SupersetCompress() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddBddConstrainRecur() - <li> cuddBddRestrictRecur() - <li> cuddAddConstrainRecur() - <li> cuddAddRestrictRecur() - <li> cuddBddLICompaction() - </ul> - Static procedures included in this module: - <ul> - <li> cuddBddConstrainDecomp() - <li> cuddBddCharToVect() - <li> cuddBddLICMarkEdges() - <li> cuddBddLICBuildResult() - <li> cuddBddSqueeze() - </ul> - ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/* Codes for edge markings in Cudd_bddLICompaction. The codes are defined -** so that they can be bitwise ORed to implement the code priority scheme. -*/ -#define DD_LIC_DC 0 -#define DD_LIC_1 1 -#define DD_LIC_0 2 -#define DD_LIC_NL 3 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/* Key for the cache used in the edge marking phase. */ -typedef struct MarkCacheKey { - DdNode *f; - DdNode *c; -} MarkCacheKey; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddGenCof.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int cuddBddConstrainDecomp ARGS((DdManager *dd, DdNode *f, DdNode **decomp)); -static DdNode * cuddBddCharToVect ARGS((DdManager *dd, DdNode *f, DdNode *x)); -static int cuddBddLICMarkEdges ARGS((DdManager *dd, DdNode *f, DdNode *c, st_table *table, st_table *cache)); -static DdNode * cuddBddLICBuildResult ARGS((DdManager *dd, DdNode *f, st_table *cache, st_table *table)); -static int MarkCacheHash ARGS((char *ptr, int modulus)); -static int MarkCacheCompare ARGS((const char *ptr1, const char *ptr2)); -static enum st_retval MarkCacheCleanUp ARGS((char *key, char *value, char *arg)); -static DdNode * cuddBddSqueeze ARGS((DdManager *dd, DdNode *l, DdNode *u)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes f constrain c.] - - Description [Computes f constrain c (f @ c). - Uses a canonical form: (f' @ c) = ( f @ c)'. (Note: this is not true - for c.) List of special cases: - <ul> - <li> f @ 0 = 0 - <li> f @ 1 = f - <li> 0 @ c = 0 - <li> 1 @ c = 1 - <li> f @ f = 1 - <li> f @ f'= 0 - </ul> - Returns a pointer to the result if successful; NULL otherwise. Note that if - F=(f1,...,fn) and reordering takes place while computing F @ c, then the - image restriction property (Img(F,c) = Img(F @ c)) is lost.] - - SideEffects [None] - - SeeAlso [Cudd_bddRestrict Cudd_addConstrain] - -******************************************************************************/ -DdNode * -Cudd_bddConstrain( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddConstrainRecur(dd,f,c); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddConstrain */ - - -/**Function******************************************************************** - - Synopsis [BDD restrict according to Coudert and Madre's algorithm - (ICCAD90).] - - Description [BDD restrict according to Coudert and Madre's algorithm - (ICCAD90). Returns the restricted BDD if successful; otherwise NULL. - If application of restrict results in a BDD larger than the input - BDD, the input BDD is returned.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain Cudd_addRestrict] - -******************************************************************************/ -DdNode * -Cudd_bddRestrict( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *suppF, *suppC, *commonSupport; - DdNode *cplus, *res; - int retval; - int sizeF, sizeRes; - - /* Check terminal cases here to avoid computing supports in trivial cases. - ** This also allows us notto check later for the case c == 0, in which - ** there is no common support. */ - if (c == Cudd_Not(DD_ONE(dd))) return(Cudd_Not(DD_ONE(dd))); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(DD_ONE(dd)); - if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd))); - - /* Check if supports intersect. */ - retval = Cudd_ClassifySupport(dd,f,c,&commonSupport,&suppF,&suppC); - if (retval == 0) { - return(NULL); - } - cuddRef(commonSupport); cuddRef(suppF); cuddRef(suppC); - Cudd_IterDerefBdd(dd,suppF); - - if (commonSupport == DD_ONE(dd)) { - Cudd_IterDerefBdd(dd,commonSupport); - Cudd_IterDerefBdd(dd,suppC); - return(f); - } - Cudd_IterDerefBdd(dd,commonSupport); - - /* Abstract from c the variables that do not appear in f. */ - cplus = Cudd_bddExistAbstract(dd, c, suppC); - if (cplus == NULL) { - Cudd_IterDerefBdd(dd,suppC); - return(NULL); - } - cuddRef(cplus); - Cudd_IterDerefBdd(dd,suppC); - - do { - dd->reordered = 0; - res = cuddBddRestrictRecur(dd, f, cplus); - } while (dd->reordered == 1); - if (res == NULL) { - Cudd_IterDerefBdd(dd,cplus); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(dd,cplus); - /* Make restric safe by returning the smaller of the input and the - ** result. */ - sizeF = Cudd_DagSize(f); - sizeRes = Cudd_DagSize(res); - if (sizeF <= sizeRes) { - Cudd_IterDerefBdd(dd, res); - return(f); - } else { - cuddDeref(res); - return(res); - } - -} /* end of Cudd_bddRestrict */ - - -/**Function******************************************************************** - - Synopsis [Computes f constrain c for ADDs.] - - Description [Computes f constrain c (f @ c), for f an ADD and c a 0-1 - ADD. List of special cases: - <ul> - <li> F @ 0 = 0 - <li> F @ 1 = F - <li> 0 @ c = 0 - <li> 1 @ c = 1 - <li> F @ F = 1 - </ul> - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain] - -******************************************************************************/ -DdNode * -Cudd_addConstrain( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddConstrainRecur(dd,f,c); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addConstrain */ - - -/**Function******************************************************************** - - Synopsis [BDD conjunctive decomposition as in McMillan's CAV96 paper.] - - Description [BDD conjunctive decomposition as in McMillan's CAV96 - paper. The decomposition is canonical only for a given variable - order. If canonicity is required, variable ordering must be disabled - after the decomposition has been computed. Returns an array with one - entry for each BDD variable in the manager if successful; otherwise - NULL. The components of the solution have their reference counts - already incremented (unlike the results of most other functions in - the package.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain Cudd_bddExistAbstract] - -******************************************************************************/ -DdNode ** -Cudd_bddConstrainDecomp( - DdManager * dd, - DdNode * f) -{ - DdNode **decomp; - int res; - int i; - - /* Create an initialize decomposition array. */ - decomp = ALLOC(DdNode *,dd->size); - if (decomp == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < dd->size; i++) { - decomp[i] = NULL; - } - do { - dd->reordered = 0; - /* Clean up the decomposition array in case reordering took place. */ - for (i = 0; i < dd->size; i++) { - if (decomp[i] != NULL) { - Cudd_IterDerefBdd(dd, decomp[i]); - decomp[i] = NULL; - } - } - res = cuddBddConstrainDecomp(dd,f,decomp); - } while (dd->reordered == 1); - if (res == 0) { - FREE(decomp); - return(NULL); - } - /* Missing components are constant ones. */ - for (i = 0; i < dd->size; i++) { - if (decomp[i] == NULL) { - decomp[i] = DD_ONE(dd); - cuddRef(decomp[i]); - } - } - return(decomp); - -} /* end of Cudd_bddConstrainDecomp */ - - -/**Function******************************************************************** - - Synopsis [ADD restrict according to Coudert and Madre's algorithm - (ICCAD90).] - - Description [ADD restrict according to Coudert and Madre's algorithm - (ICCAD90). Returns the restricted ADD if successful; otherwise NULL. - If application of restrict results in an ADD larger than the input - ADD, the input ADD is returned.] - - SideEffects [None] - - SeeAlso [Cudd_addConstrain Cudd_bddRestrict] - -******************************************************************************/ -DdNode * -Cudd_addRestrict( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *supp_f, *supp_c; - DdNode *res, *commonSupport; - int intersection; - int sizeF, sizeRes; - - /* Check if supports intersect. */ - supp_f = Cudd_Support(dd, f); - if (supp_f == NULL) { - return(NULL); - } - cuddRef(supp_f); - supp_c = Cudd_Support(dd, c); - if (supp_c == NULL) { - Cudd_RecursiveDeref(dd,supp_f); - return(NULL); - } - cuddRef(supp_c); - commonSupport = Cudd_bddLiteralSetIntersection(dd, supp_f, supp_c); - if (commonSupport == NULL) { - Cudd_RecursiveDeref(dd,supp_f); - Cudd_RecursiveDeref(dd,supp_c); - return(NULL); - } - cuddRef(commonSupport); - Cudd_RecursiveDeref(dd,supp_f); - Cudd_RecursiveDeref(dd,supp_c); - intersection = commonSupport != DD_ONE(dd); - Cudd_RecursiveDeref(dd,commonSupport); - - if (intersection) { - do { - dd->reordered = 0; - res = cuddAddRestrictRecur(dd, f, c); - } while (dd->reordered == 1); - sizeF = Cudd_DagSize(f); - sizeRes = Cudd_DagSize(res); - if (sizeF <= sizeRes) { - cuddRef(res); - Cudd_RecursiveDeref(dd, res); - return(f); - } else { - return(res); - } - } else { - return(f); - } - -} /* end of Cudd_addRestrict */ - - -/**Function******************************************************************** - - Synopsis [Computes a vector whose image equals a non-zero function.] - - Description [Computes a vector of BDDs whose image equals a non-zero - function. - The result depends on the variable order. The i-th component of the vector - depends only on the first i variables in the order. Each BDD in the vector - is not larger than the BDD of the given characteristic function. This - function is based on the description of char-to-vect in "Verification of - Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C. - Berthet and J. C. Madre. - Returns a pointer to an array containing the result if successful; NULL - otherwise. The size of the array equals the number of variables in the - manager. The components of the solution have their reference counts - already incremented (unlike the results of most other functions in - the package.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain] - -******************************************************************************/ -DdNode ** -Cudd_bddCharToVect( - DdManager * dd, - DdNode * f) -{ - int i, j; - DdNode **vect; - DdNode *res = NULL; - - if (f == Cudd_Not(DD_ONE(dd))) return(NULL); - - vect = ALLOC(DdNode *, dd->size); - if (vect == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - do { - dd->reordered = 0; - for (i = 0; i < dd->size; i++) { - res = cuddBddCharToVect(dd,f,dd->vars[dd->invperm[i]]); - if (res == NULL) { - /* Clean up the vector array in case reordering took place. */ - for (j = 0; j < i; j++) { - Cudd_IterDerefBdd(dd, vect[dd->invperm[j]]); - } - break; - } - cuddRef(res); - vect[dd->invperm[i]] = res; - } - } while (dd->reordered == 1); - if (res == NULL) { - FREE(vect); - return(NULL); - } - return(vect); - -} /* end of Cudd_bddCharToVect */ - - -/**Function******************************************************************** - - Synopsis [Performs safe minimization of a BDD.] - - Description [Performs safe minimization of a BDD. Given the BDD - <code>f</code> of a function to be minimized and a BDD - <code>c</code> representing the care set, Cudd_bddLICompaction - produces the BDD of a function that agrees with <code>f</code> - wherever <code>c</code> is 1. Safe minimization means that the size - of the result is guaranteed not to exceed the size of - <code>f</code>. This function is based on the DAC97 paper by Hong et - al.. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddRestrict] - -******************************************************************************/ -DdNode * -Cudd_bddLICompaction( - DdManager * dd /* manager */, - DdNode * f /* function to be minimized */, - DdNode * c /* constraint (care set) */) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddLICompaction(dd,f,c); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddLICompaction */ - - -/**Function******************************************************************** - - Synopsis [Finds a small BDD in a function interval.] - - Description [Finds a small BDD in a function interval. Given BDDs - <code>l</code> and <code>u</code>, representing the lower bound and - upper bound of a function interval, Cudd_bddSqueeze produces the BDD - of a function within the interval with a small BDD. Returns a - pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction] - -******************************************************************************/ -DdNode * -Cudd_bddSqueeze( - DdManager * dd /* manager */, - DdNode * l /* lower bound */, - DdNode * u /* upper bound */) -{ - DdNode *res; - int sizeRes, sizeL, sizeU; - - do { - dd->reordered = 0; - res = cuddBddSqueeze(dd,l,u); - } while (dd->reordered == 1); - if (res == NULL) return(NULL); - /* We now compare the result with the bounds and return the smallest. - ** We first compare to u, so that in case l == 0 and u == 1, we return - ** 0 as in other minimization algorithms. */ - sizeRes = Cudd_DagSize(res); - sizeU = Cudd_DagSize(u); - if (sizeU <= sizeRes) { - cuddRef(res); - Cudd_IterDerefBdd(dd,res); - res = u; - sizeRes = sizeU; - } - sizeL = Cudd_DagSize(l); - if (sizeL <= sizeRes) { - cuddRef(res); - Cudd_IterDerefBdd(dd,res); - res = l; - sizeRes = sizeL; - } - return(res); - -} /* end of Cudd_bddSqueeze */ - - -/**Function******************************************************************** - - Synopsis [Finds a small BDD that agrees with <code>f</code> over - <code>c</code>.] - - Description [Finds a small BDD that agrees with <code>f</code> over - <code>c</code>. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction Cudd_bddSqueeze] - -******************************************************************************/ -DdNode * -Cudd_bddMinimize( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *cplus, *res; - - if (c == Cudd_Not(DD_ONE(dd))) return(c); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(DD_ONE(dd)); - if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd))); - - cplus = Cudd_RemapOverApprox(dd,c,0,0,1.0); - if (cplus == NULL) return(NULL); - cuddRef(cplus); - res = Cudd_bddLICompaction(dd,f,cplus); - if (res == NULL) { - Cudd_IterDerefBdd(dd,cplus); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(dd,cplus); - cuddDeref(res); - return(res); - -} /* end of Cudd_bddMinimize */ - - -/**Function******************************************************************** - - Synopsis [Find a dense subset of BDD <code>f</code>.] - - Description [Finds a dense subset of BDD <code>f</code>. Density is - the ratio of number of minterms to number of nodes. Uses several - techniques in series. It is more expensive than other subsetting - procedures, but often produces better results. See - Cudd_SubsetShortPaths for a description of the threshold and nvars - parameters. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetRemap Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch - Cudd_bddSqueeze] - -******************************************************************************/ -DdNode * -Cudd_SubsetCompress( - DdManager * dd /* manager */, - DdNode * f /* BDD whose subset is sought */, - int nvars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the subset */) -{ - DdNode *res, *tmp1, *tmp2; - - tmp1 = Cudd_SubsetShortPaths(dd, f, nvars, threshold, 0); - if (tmp1 == NULL) return(NULL); - cuddRef(tmp1); - tmp2 = Cudd_RemapUnderApprox(dd,tmp1,nvars,0,1.0); - if (tmp2 == NULL) { - Cudd_IterDerefBdd(dd,tmp1); - return(NULL); - } - cuddRef(tmp2); - Cudd_IterDerefBdd(dd,tmp1); - res = Cudd_bddSqueeze(dd,tmp2,f); - if (res == NULL) { - Cudd_IterDerefBdd(dd,tmp2); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(dd,tmp2); - cuddDeref(res); - return(res); - -} /* end of Cudd_SubsetCompress */ - - -/**Function******************************************************************** - - Synopsis [Find a dense superset of BDD <code>f</code>.] - - Description [Finds a dense superset of BDD <code>f</code>. Density is - the ratio of number of minterms to number of nodes. Uses several - techniques in series. It is more expensive than other supersetting - procedures, but often produces better results. See - Cudd_SupersetShortPaths for a description of the threshold and nvars - parameters. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetCompress Cudd_SupersetRemap Cudd_SupersetShortPaths - Cudd_SupersetHeavyBranch Cudd_bddSqueeze] - -******************************************************************************/ -DdNode * -Cudd_SupersetCompress( - DdManager * dd /* manager */, - DdNode * f /* BDD whose superset is sought */, - int nvars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the superset */) -{ - DdNode *subset; - - subset = Cudd_SubsetCompress(dd, Cudd_Not(f),nvars,threshold); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_SupersetCompress */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddConstrain.] - - Description [Performs the recursive step of Cudd_bddConstrain. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain] - -******************************************************************************/ -DdNode * -cuddBddConstrainRecur( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r; - DdNode *one, *zero; - unsigned int topf, topc; - int index; - int comple = 0; - - statLine(dd); - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Trivial cases. */ - if (c == one) return(f); - if (c == zero) return(zero); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(one); - if (f == Cudd_Not(c)) return(zero); - - /* Make canonical to increase the utilization of the cache. */ - if (Cudd_IsComplement(f)) { - f = Cudd_Not(f); - comple = 1; - } - /* Now f is a regular pointer to a non-constant node; c is also - ** non-constant, but may be complemented. - */ - - /* Check the cache. */ - r = cuddCacheLookup2(dd, Cudd_bddConstrain, f, c); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - /* Recursive step. */ - topf = dd->perm[f->index]; - topc = dd->perm[Cudd_Regular(c)->index]; - if (topf <= topc) { - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - } else { - index = Cudd_Regular(c)->index; - Fv = Fnv = f; - } - if (topc <= topf) { - Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); - if (Cudd_IsComplement(c)) { - Cv = Cudd_Not(Cv); - Cnv = Cudd_Not(Cnv); - } - } else { - Cv = Cnv = c; - } - - if (!Cudd_IsConstant(Cv)) { - t = cuddBddConstrainRecur(dd, Fv, Cv); - if (t == NULL) - return(NULL); - } else if (Cv == one) { - t = Fv; - } else { /* Cv == zero: return Fnv @ Cnv */ - if (Cnv == one) { - r = Fnv; - } else { - r = cuddBddConstrainRecur(dd, Fnv, Cnv); - if (r == NULL) - return(NULL); - } - return(Cudd_NotCond(r,comple)); - } - cuddRef(t); - - if (!Cudd_IsConstant(Cnv)) { - e = cuddBddConstrainRecur(dd, Fnv, Cnv); - if (e == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } else if (Cnv == one) { - e = Fnv; - } else { /* Cnv == zero: return Fv @ Cv previously computed */ - cuddDeref(t); - return(Cudd_NotCond(t,comple)); - } - cuddRef(e); - - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert2(dd, Cudd_bddConstrain, f, c, r); - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddConstrainRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddRestrict.] - - Description [Performs the recursive step of Cudd_bddRestrict. - Returns the restricted BDD if successful; otherwise NULL.] - - SideEffects [None] - - SeeAlso [Cudd_bddRestrict] - -******************************************************************************/ -DdNode * -cuddBddRestrictRecur( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero; - unsigned int topf, topc; - int index; - int comple = 0; - - statLine(dd); - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Trivial cases */ - if (c == one) return(f); - if (c == zero) return(zero); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(one); - if (f == Cudd_Not(c)) return(zero); - - /* Make canonical to increase the utilization of the cache. */ - if (Cudd_IsComplement(f)) { - f = Cudd_Not(f); - comple = 1; - } - /* Now f is a regular pointer to a non-constant node; c is also - ** non-constant, but may be complemented. - */ - - /* Check the cache. */ - r = cuddCacheLookup2(dd, Cudd_bddRestrict, f, c); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - topf = dd->perm[f->index]; - topc = dd->perm[Cudd_Regular(c)->index]; - - if (topc < topf) { /* abstract top variable from c */ - DdNode *d, *s1, *s2; - - /* Find complements of cofactors of c. */ - if (Cudd_IsComplement(c)) { - s1 = cuddT(Cudd_Regular(c)); - s2 = cuddE(Cudd_Regular(c)); - } else { - s1 = Cudd_Not(cuddT(c)); - s2 = Cudd_Not(cuddE(c)); - } - /* Take the OR by applying DeMorgan. */ - d = cuddBddAndRecur(dd, s1, s2); - if (d == NULL) return(NULL); - d = Cudd_Not(d); - cuddRef(d); - r = cuddBddRestrictRecur(dd, f, d); - if (r == NULL) { - Cudd_IterDerefBdd(dd, d); - return(NULL); - } - cuddRef(r); - Cudd_IterDerefBdd(dd, d); - cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r); - cuddDeref(r); - return(Cudd_NotCond(r,comple)); - } - - /* Recursive step. Here topf <= topc. */ - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - if (topc == topf) { - Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); - if (Cudd_IsComplement(c)) { - Cv = Cudd_Not(Cv); - Cnv = Cudd_Not(Cnv); - } - } else { - Cv = Cnv = c; - } - - if (!Cudd_IsConstant(Cv)) { - t = cuddBddRestrictRecur(dd, Fv, Cv); - if (t == NULL) return(NULL); - } else if (Cv == one) { - t = Fv; - } else { /* Cv == zero: return(Fnv @ Cnv) */ - if (Cnv == one) { - r = Fnv; - } else { - r = cuddBddRestrictRecur(dd, Fnv, Cnv); - if (r == NULL) return(NULL); - } - return(Cudd_NotCond(r,comple)); - } - cuddRef(t); - - if (!Cudd_IsConstant(Cnv)) { - e = cuddBddRestrictRecur(dd, Fnv, Cnv); - if (e == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } else if (Cnv == one) { - e = Fnv; - } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ - cuddDeref(t); - return(Cudd_NotCond(t,comple)); - } - cuddRef(e); - - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r); - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddRestrictRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addConstrain.] - - Description [Performs the recursive step of Cudd_addConstrain. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addConstrain] - -******************************************************************************/ -DdNode * -cuddAddConstrainRecur( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r; - DdNode *one, *zero; - unsigned int topf, topc; - int index; - - statLine(dd); - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - /* Trivial cases. */ - if (c == one) return(f); - if (c == zero) return(zero); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(one); - - /* Now f and c are non-constant. */ - - /* Check the cache. */ - r = cuddCacheLookup2(dd, Cudd_addConstrain, f, c); - if (r != NULL) { - return(r); - } - - /* Recursive step. */ - topf = dd->perm[f->index]; - topc = dd->perm[c->index]; - if (topf <= topc) { - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - } else { - index = c->index; - Fv = Fnv = f; - } - if (topc <= topf) { - Cv = cuddT(c); Cnv = cuddE(c); - } else { - Cv = Cnv = c; - } - - if (!Cudd_IsConstant(Cv)) { - t = cuddAddConstrainRecur(dd, Fv, Cv); - if (t == NULL) - return(NULL); - } else if (Cv == one) { - t = Fv; - } else { /* Cv == zero: return Fnv @ Cnv */ - if (Cnv == one) { - r = Fnv; - } else { - r = cuddAddConstrainRecur(dd, Fnv, Cnv); - if (r == NULL) - return(NULL); - } - return(r); - } - cuddRef(t); - - if (!Cudd_IsConstant(Cnv)) { - e = cuddAddConstrainRecur(dd, Fnv, Cnv); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - } else if (Cnv == one) { - e = Fnv; - } else { /* Cnv == zero: return Fv @ Cv previously computed */ - cuddDeref(t); - return(t); - } - cuddRef(e); - - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert2(dd, Cudd_addConstrain, f, c, r); - return(r); - -} /* end of cuddAddConstrainRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addRestrict.] - - Description [Performs the recursive step of Cudd_addRestrict. - Returns the restricted ADD if successful; otherwise NULL.] - - SideEffects [None] - - SeeAlso [Cudd_addRestrict] - -******************************************************************************/ -DdNode * -cuddAddRestrictRecur( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero; - unsigned int topf, topc; - int index; - - statLine(dd); - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - /* Trivial cases */ - if (c == one) return(f); - if (c == zero) return(zero); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(one); - - /* Now f and c are non-constant. */ - - /* Check the cache. */ - r = cuddCacheLookup2(dd, Cudd_addRestrict, f, c); - if (r != NULL) { - return(r); - } - - topf = dd->perm[f->index]; - topc = dd->perm[c->index]; - - if (topc < topf) { /* abstract top variable from c */ - DdNode *d, *s1, *s2; - - /* Find cofactors of c. */ - s1 = cuddT(c); - s2 = cuddE(c); - /* Take the OR by applying DeMorgan. */ - d = cuddAddApplyRecur(dd, Cudd_addOr, s1, s2); - if (d == NULL) return(NULL); - cuddRef(d); - r = cuddAddRestrictRecur(dd, f, d); - if (r == NULL) { - Cudd_RecursiveDeref(dd, d); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDeref(dd, d); - cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r); - cuddDeref(r); - return(r); - } - - /* Recursive step. Here topf <= topc. */ - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - if (topc == topf) { - Cv = cuddT(c); Cnv = cuddE(c); - } else { - Cv = Cnv = c; - } - - if (!Cudd_IsConstant(Cv)) { - t = cuddAddRestrictRecur(dd, Fv, Cv); - if (t == NULL) return(NULL); - } else if (Cv == one) { - t = Fv; - } else { /* Cv == zero: return(Fnv @ Cnv) */ - if (Cnv == one) { - r = Fnv; - } else { - r = cuddAddRestrictRecur(dd, Fnv, Cnv); - if (r == NULL) return(NULL); - } - return(r); - } - cuddRef(t); - - if (!Cudd_IsConstant(Cnv)) { - e = cuddAddRestrictRecur(dd, Fnv, Cnv); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - } else if (Cnv == one) { - e = Fnv; - } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ - cuddDeref(t); - return(t); - } - cuddRef(e); - - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r); - return(r); - -} /* end of cuddAddRestrictRecur */ - - - -/**Function******************************************************************** - - Synopsis [Performs safe minimization of a BDD.] - - Description [Performs safe minimization of a BDD. Given the BDD - <code>f</code> of a function to be minimized and a BDD - <code>c</code> representing the care set, Cudd_bddLICompaction - produces the BDD of a function that agrees with <code>f</code> - wherever <code>c</code> is 1. Safe minimization means that the size - of the result is guaranteed not to exceed the size of - <code>f</code>. This function is based on the DAC97 paper by Hong et - al.. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction] - -******************************************************************************/ -DdNode * -cuddBddLICompaction( - DdManager * dd /* manager */, - DdNode * f /* function to be minimized */, - DdNode * c /* constraint (care set) */) -{ - st_table *marktable, *markcache, *buildcache; - DdNode *res, *zero; - - zero = Cudd_Not(DD_ONE(dd)); - if (c == zero) return(zero); - - /* We need to use local caches for both steps of this operation. - ** The results of the edge marking step are only valid as long as the - ** edge markings themselves are available. However, the edge markings - ** are lost at the end of one invocation of Cudd_bddLICompaction. - ** Hence, the cache entries for the edge marking step must be - ** invalidated at the end of this function. - ** For the result of the building step we argue as follows. The result - ** for a node and a given constrain depends on the BDD in which the node - ** appears. Hence, the same node and constrain may give different results - ** in successive invocations. - */ - marktable = st_init_table(st_ptrcmp,st_ptrhash); - if (marktable == NULL) { - return(NULL); - } - markcache = st_init_table(MarkCacheCompare,MarkCacheHash); - if (markcache == NULL) { - st_free_table(marktable); - return(NULL); - } - if (cuddBddLICMarkEdges(dd,f,c,marktable,markcache) == CUDD_OUT_OF_MEM) { - st_foreach(markcache, MarkCacheCleanUp, NULL); - st_free_table(marktable); - st_free_table(markcache); - return(NULL); - } - st_foreach(markcache, MarkCacheCleanUp, NULL); - st_free_table(markcache); - buildcache = st_init_table(st_ptrcmp,st_ptrhash); - if (buildcache == NULL) { - st_free_table(marktable); - return(NULL); - } - res = cuddBddLICBuildResult(dd,f,buildcache,marktable); - st_free_table(buildcache); - st_free_table(marktable); - return(res); - -} /* end of cuddBddLICompaction */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddConstrainDecomp.] - - Description [Performs the recursive step of Cudd_bddConstrainDecomp. - Returns f super (i) if successful; otherwise NULL.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrainDecomp] - -******************************************************************************/ -static int -cuddBddConstrainDecomp( - DdManager * dd, - DdNode * f, - DdNode ** decomp) -{ - DdNode *F, *fv, *fvn; - DdNode *fAbs; - DdNode *result; - int ok; - - if (Cudd_IsConstant(f)) return(1); - /* Compute complements of cofactors. */ - F = Cudd_Regular(f); - fv = cuddT(F); - fvn = cuddE(F); - if (F == f) { - fv = Cudd_Not(fv); - fvn = Cudd_Not(fvn); - } - /* Compute abstraction of top variable. */ - fAbs = cuddBddAndRecur(dd, fv, fvn); - if (fAbs == NULL) { - return(0); - } - cuddRef(fAbs); - fAbs = Cudd_Not(fAbs); - /* Recursively find the next abstraction and the components of the - ** decomposition. */ - ok = cuddBddConstrainDecomp(dd, fAbs, decomp); - if (ok == 0) { - Cudd_IterDerefBdd(dd,fAbs); - return(0); - } - /* Compute the component of the decomposition corresponding to the - ** top variable and store it in the decomposition array. */ - result = cuddBddConstrainRecur(dd, f, fAbs); - if (result == NULL) { - Cudd_IterDerefBdd(dd,fAbs); - return(0); - } - cuddRef(result); - decomp[F->index] = result; - Cudd_IterDerefBdd(dd, fAbs); - return(1); - -} /* end of cuddBddConstrainDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddCharToVect.] - - Description [Performs the recursive step of Cudd_bddCharToVect. - This function maintains the invariant that f is non-zero. - Returns the i-th component of the vector if successful; otherwise NULL.] - - SideEffects [None] - - SeeAlso [Cudd_bddCharToVect] - -******************************************************************************/ -static DdNode * -cuddBddCharToVect( - DdManager * dd, - DdNode * f, - DdNode * x) -{ - unsigned int topf; - unsigned int level; - int comple; - - DdNode *one, *zero, *res, *F, *fT, *fE, *T, *E; - - statLine(dd); - /* Check the cache. */ - res = cuddCacheLookup2(dd, cuddBddCharToVect, f, x); - if (res != NULL) { - return(res); - } - - F = Cudd_Regular(f); - - topf = cuddI(dd,F->index); - level = dd->perm[x->index]; - - if (topf > level) return(x); - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - comple = F != f; - fT = Cudd_NotCond(cuddT(F),comple); - fE = Cudd_NotCond(cuddE(F),comple); - - if (topf == level) { - if (fT == zero) return(zero); - if (fE == zero) return(one); - return(x); - } - - /* Here topf < level. */ - if (fT == zero) return(cuddBddCharToVect(dd, fE, x)); - if (fE == zero) return(cuddBddCharToVect(dd, fT, x)); - - T = cuddBddCharToVect(dd, fT, x); - if (T == NULL) { - return(NULL); - } - cuddRef(T); - E = cuddBddCharToVect(dd, fE, x); - if (E == NULL) { - Cudd_IterDerefBdd(dd,T); - return(NULL); - } - cuddRef(E); - res = cuddBddIteRecur(dd, dd->vars[F->index], T, E); - if (res == NULL) { - Cudd_IterDerefBdd(dd,T); - Cudd_IterDerefBdd(dd,E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - cuddCacheInsert2(dd, cuddBddCharToVect, f, x, res); - return(res); - -} /* end of cuddBddCharToVect */ - - -/**Function******************************************************************** - - Synopsis [Performs the edge marking step of Cudd_bddLICompaction.] - - Description [Performs the edge marking step of Cudd_bddLICompaction. - Returns the LUB of the markings of the two outgoing edges of <code>f</code> - if successful; otherwise CUDD_OUT_OF_MEM.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction cuddBddLICBuildResult] - -******************************************************************************/ -static int -cuddBddLICMarkEdges( - DdManager * dd, - DdNode * f, - DdNode * c, - st_table * table, - st_table * cache) -{ - DdNode *Fv, *Fnv, *Cv, *Cnv; - DdNode *one, *zero; - unsigned int topf, topc; - int index; - int comple; - int resT, resE, res, retval; - char **slot; - MarkCacheKey *key; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (c == zero) return(DD_LIC_DC); - if (f == one) return(DD_LIC_1); - if (f == zero) return(DD_LIC_0); - - /* Make canonical to increase the utilization of the cache. */ - comple = Cudd_IsComplement(f); - f = Cudd_Regular(f); - /* Now f is a regular pointer to a non-constant node; c may be - ** constant, or it may be complemented. - */ - - /* Check the cache. */ - key = ALLOC(MarkCacheKey, 1); - if (key == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(CUDD_OUT_OF_MEM); - } - key->f = f; key->c = c; - if (st_lookup(cache, (char *)key, (char **)&res)) { - FREE(key); - if (comple) { - if (res == DD_LIC_0) res = DD_LIC_1; - else if (res == DD_LIC_1) res = DD_LIC_0; - } - return(res); - } - - /* Recursive step. */ - topf = dd->perm[f->index]; - topc = cuddI(dd,Cudd_Regular(c)->index); - if (topf <= topc) { - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - } else { - index = Cudd_Regular(c)->index; - Fv = Fnv = f; - } - if (topc <= topf) { - /* We know that c is not constant because f is not. */ - Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); - if (Cudd_IsComplement(c)) { - Cv = Cudd_Not(Cv); - Cnv = Cudd_Not(Cnv); - } - } else { - Cv = Cnv = c; - } - - resT = cuddBddLICMarkEdges(dd, Fv, Cv, table, cache); - if (resT == CUDD_OUT_OF_MEM) { - FREE(key); - return(CUDD_OUT_OF_MEM); - } - resE = cuddBddLICMarkEdges(dd, Fnv, Cnv, table, cache); - if (resE == CUDD_OUT_OF_MEM) { - FREE(key); - return(CUDD_OUT_OF_MEM); - } - - /* Update edge markings. */ - if (topf <= topc) { - retval = st_find_or_add(table, (char *)f, (char ***)&slot); - if (retval == 0) { - *slot = (char *) (ptrint)((resT << 2) | resE); - } else if (retval == 1) { - *slot = (char *) (ptrint)((int)((ptrint) *slot) | (resT << 2) | resE); - } else { - FREE(key); - return(CUDD_OUT_OF_MEM); - } - } - - /* Cache result. */ - res = resT | resE; - if (st_insert(cache, (char *)key, (char *)(ptrint)res) == ST_OUT_OF_MEM) { - FREE(key); - return(CUDD_OUT_OF_MEM); - } - - /* Take into account possible complementation. */ - if (comple) { - if (res == DD_LIC_0) res = DD_LIC_1; - else if (res == DD_LIC_1) res = DD_LIC_0; - } - return(res); - -} /* end of cuddBddLICMarkEdges */ - - -/**Function******************************************************************** - - Synopsis [Builds the result of Cudd_bddLICompaction.] - - Description [Builds the results of Cudd_bddLICompaction. - Returns a pointer to the minimized BDD if successful; otherwise NULL.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction cuddBddLICMarkEdges] - -******************************************************************************/ -static DdNode * -cuddBddLICBuildResult( - DdManager * dd, - DdNode * f, - st_table * cache, - st_table * table) -{ - DdNode *Fv, *Fnv, *r, *t, *e; - DdNode *one, *zero; - unsigned int topf; - int index; - int comple; - int markT, markE, markings; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - if (Cudd_IsConstant(f)) return(f); - /* Make canonical to increase the utilization of the cache. */ - comple = Cudd_IsComplement(f); - f = Cudd_Regular(f); - - /* Check the cache. */ - if (st_lookup(cache, (char *)f, (char **)&r)) { - return(Cudd_NotCond(r,comple)); - } - - /* Retrieve the edge markings. */ - if (st_lookup(table, (char *)f, (char **)&markings) == 0) - return(NULL); - markT = markings >> 2; - markE = markings & 3; - - topf = dd->perm[f->index]; - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - - if (markT == DD_LIC_NL) { - t = cuddBddLICBuildResult(dd,Fv,cache,table); - if (t == NULL) { - return(NULL); - } - } else if (markT == DD_LIC_1) { - t = one; - } else { - t = zero; - } - cuddRef(t); - if (markE == DD_LIC_NL) { - e = cuddBddLICBuildResult(dd,Fnv,cache,table); - if (e == NULL) { - Cudd_IterDerefBdd(dd,t); - return(NULL); - } - } else if (markE == DD_LIC_1) { - e = one; - } else { - e = zero; - } - cuddRef(e); - - if (markT == DD_LIC_DC && markE != DD_LIC_DC) { - r = e; - } else if (markT != DD_LIC_DC && markE == DD_LIC_DC) { - r = t; - } else { - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - } - cuddDeref(t); - cuddDeref(e); - - if (st_insert(cache, (char *)f, (char *)r) == ST_OUT_OF_MEM) { - cuddRef(r); - Cudd_IterDerefBdd(dd,r); - return(NULL); - } - - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddLICBuildResult */ - - -/**Function******************************************************************** - - Synopsis [Hash function for the computed table of cuddBddLICMarkEdges.] - - Description [Hash function for the computed table of - cuddBddLICMarkEdges. Returns the bucket number.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction] - -******************************************************************************/ -static int -MarkCacheHash( - char * ptr, - int modulus) -{ - int val = 0; - MarkCacheKey *entry; - - entry = (MarkCacheKey *) ptr; - - val = (int) (ptrint) entry->f; - val = val * 997 + (int) (ptrint) entry->c; - - return ((val < 0) ? -val : val) % modulus; - -} /* end of MarkCacheHash */ - - -/**Function******************************************************************** - - Synopsis [Comparison function for the computed table of - cuddBddLICMarkEdges.] - - Description [Comparison function for the computed table of - cuddBddLICMarkEdges. Returns 0 if the two nodes of the key are equal; 1 - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction] - -******************************************************************************/ -static int -MarkCacheCompare( - const char * ptr1, - const char * ptr2) -{ - MarkCacheKey *entry1, *entry2; - - entry1 = (MarkCacheKey *) ptr1; - entry2 = (MarkCacheKey *) ptr2; - - return((entry1->f != entry2->f) || (entry1->c != entry2->c)); - -} /* end of MarkCacheCompare */ - - - -/**Function******************************************************************** - - Synopsis [Frees memory associated with computed table of - cuddBddLICMarkEdges.] - - Description [Frees memory associated with computed table of - cuddBddLICMarkEdges. Returns ST_CONTINUE.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction] - -******************************************************************************/ -static enum st_retval -MarkCacheCleanUp( - char * key, - char * value, - char * arg) -{ - MarkCacheKey *entry; - - entry = (MarkCacheKey *) key; - FREE(entry); - return ST_CONTINUE; - -} /* end of MarkCacheCleanUp */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddSqueeze.] - - Description [Performs the recursive step of Cudd_bddSqueeze. This - procedure exploits the fact that if we complement and swap the - bounds of the interval we obtain a valid solution by taking the - complement of the solution to the original problem. Therefore, we - can enforce the condition that the upper bound is always regular. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddSqueeze] - -******************************************************************************/ -static DdNode * -cuddBddSqueeze( - DdManager * dd, - DdNode * l, - DdNode * u) -{ - DdNode *one, *zero, *r, *lt, *le, *ut, *ue, *t, *e; -#if 0 - DdNode *ar; -#endif - int comple = 0; - unsigned int topu, topl; - int index; - - statLine(dd); - if (l == u) { - return(l); - } - one = DD_ONE(dd); - zero = Cudd_Not(one); - /* The only case when l == zero && u == one is at the top level, - ** where returning either one or zero is OK. In all other cases - ** the procedure will detect such a case and will perform - ** remapping. Therefore the order in which we test l and u at this - ** point is immaterial. */ - if (l == zero) return(l); - if (u == one) return(u); - - /* Make canonical to increase the utilization of the cache. */ - if (Cudd_IsComplement(u)) { - DdNode *temp; - temp = Cudd_Not(l); - l = Cudd_Not(u); - u = temp; - comple = 1; - } - /* At this point u is regular and non-constant; l is non-constant, but - ** may be complemented. */ - - /* Here we could check the relative sizes. */ - - /* Check the cache. */ - r = cuddCacheLookup2(dd, Cudd_bddSqueeze, l, u); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - /* Recursive step. */ - topu = dd->perm[u->index]; - topl = dd->perm[Cudd_Regular(l)->index]; - if (topu <= topl) { - index = u->index; - ut = cuddT(u); ue = cuddE(u); - } else { - index = Cudd_Regular(l)->index; - ut = ue = u; - } - if (topl <= topu) { - lt = cuddT(Cudd_Regular(l)); le = cuddE(Cudd_Regular(l)); - if (Cudd_IsComplement(l)) { - lt = Cudd_Not(lt); - le = Cudd_Not(le); - } - } else { - lt = le = l; - } - - /* If one interval is contained in the other, use the smaller - ** interval. This corresponds to one-sided matching. */ - if ((lt == zero || Cudd_bddLeq(dd,lt,le)) && - (ut == one || Cudd_bddLeq(dd,ue,ut))) { /* remap */ - r = cuddBddSqueeze(dd, le, ue); - if (r == NULL) - return(NULL); - return(Cudd_NotCond(r,comple)); - } else if ((le == zero || Cudd_bddLeq(dd,le,lt)) && - (ue == one || Cudd_bddLeq(dd,ut,ue))) { /* remap */ - r = cuddBddSqueeze(dd, lt, ut); - if (r == NULL) - return(NULL); - return(Cudd_NotCond(r,comple)); - } else if ((le == zero || Cudd_bddLeq(dd,le,Cudd_Not(ut))) && - (ue == one || Cudd_bddLeq(dd,Cudd_Not(lt),ue))) { /* c-remap */ - t = cuddBddSqueeze(dd, lt, ut); - cuddRef(t); - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(dd, index, Cudd_Not(t), t); - if (r == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(dd, index, t, Cudd_Not(t)); - if (r == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - cuddDeref(t); - if (r == NULL) - return(NULL); - cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); - return(Cudd_NotCond(r,comple)); - } else if ((lt == zero || Cudd_bddLeq(dd,lt,Cudd_Not(ue))) && - (ut == one || Cudd_bddLeq(dd,Cudd_Not(le),ut))) { /* c-remap */ - e = cuddBddSqueeze(dd, le, ue); - cuddRef(e); - if (Cudd_IsComplement(e)) { - r = cuddUniqueInter(dd, index, Cudd_Not(e), e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - return(NULL); - } - } else { - r = cuddUniqueInter(dd, index, e, Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - return(NULL); - } - r = Cudd_Not(r); - } - cuddDeref(e); - if (r == NULL) - return(NULL); - cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); - return(Cudd_NotCond(r,comple)); - } - -#if 0 - /* If the two intervals intersect, take a solution from - ** the intersection of the intervals. This guarantees that the - ** splitting variable will not appear in the result. - ** This approach corresponds to two-sided matching, and is very - ** expensive. */ - if (Cudd_bddLeq(dd,lt,ue) && Cudd_bddLeq(dd,le,ut)) { - DdNode *au, *al; - au = cuddBddAndRecur(dd,ut,ue); - if (au == NULL) - return(NULL); - cuddRef(au); - al = cuddBddAndRecur(dd,Cudd_Not(lt),Cudd_Not(le)); - if (al == NULL) { - Cudd_IterDerefBdd(dd,au); - return(NULL); - } - cuddRef(al); - al = Cudd_Not(al); - ar = cuddBddSqueeze(dd, al, au); - if (ar == NULL) { - Cudd_IterDerefBdd(dd,au); - Cudd_IterDerefBdd(dd,al); - return(NULL); - } - cuddRef(ar); - Cudd_IterDerefBdd(dd,au); - Cudd_IterDerefBdd(dd,al); - } else { - ar = NULL; - } -#endif - - t = cuddBddSqueeze(dd, lt, ut); - if (t == NULL) { - return(NULL); - } - cuddRef(t); - e = cuddBddSqueeze(dd, le, ue); - if (e == NULL) { - Cudd_IterDerefBdd(dd,t); - return(NULL); - } - cuddRef(e); - - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - -#if 0 - /* Check whether there is a result obtained by abstraction and whether - ** it is better than the one obtained by recursion. */ - cuddRef(r); - if (ar != NULL) { - if (Cudd_DagSize(ar) <= Cudd_DagSize(r)) { - Cudd_IterDerefBdd(dd, r); - r = ar; - } else { - Cudd_IterDerefBdd(dd, ar); - } - } - cuddDeref(r); -#endif - - cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddSqueeze */ diff --git a/src/bdd/cudd/cuddGenetic.c b/src/bdd/cudd/cuddGenetic.c deleted file mode 100644 index 9fe03dad..00000000 --- a/src/bdd/cudd/cuddGenetic.c +++ /dev/null @@ -1,921 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddGenetic.c] - - PackageName [cudd] - - Synopsis [Genetic algorithm for variable reordering.] - - Description [Internal procedures included in this file: - <ul> - <li> cuddGa() - </ul> - Static procedures included in this module: - <ul> - <li> make_random() - <li> sift_up() - <li> build_dd() - <li> largest() - <li> rand_int() - <li> array_hash() - <li> array_compare() - <li> find_best() - <li> find_average_fitness() - <li> PMX() - <li> roulette() - </ul> - - The genetic algorithm implemented here is as follows. We start with - the current DD order. We sift this order and use this as the - reference DD. We only keep 1 DD around for the entire process and - simply rearrange the order of this DD, storing the various orders - and their corresponding DD sizes. We generate more random orders to - build an initial population. This initial population is 3 times the - number of variables, with a maximum of 120. Each random order is - built (from the reference DD) and its size stored. Each random - order is also sifted to keep the DD sizes fairly small. Then a - crossover is performed between two orders (picked randomly) and the - two resulting DDs are built and sifted. For each new order, if its - size is smaller than any DD in the population, it is inserted into - the population and the DD with the largest number of nodes is thrown - out. The crossover process happens up to 50 times, and at this point - the DD in the population with the smallest size is chosen as the - result. This DD must then be built from the reference DD.] - - SeeAlso [] - - Author [Curt Musfeldt, Alan Shuler, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddGenetic.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -static int popsize; /* the size of the population */ -static int numvars; /* the number of input variables in the ckt. */ -/* storedd stores the population orders and sizes. This table has two -** extra rows and one extras column. The two extra rows are used for the -** offspring produced by a crossover. Each row stores one order and its -** size. The order is stored by storing the indices of variables in the -** order in which they appear in the order. The table is in reality a -** one-dimensional array which is accessed via a macro to give the illusion -** it is a two-dimensional structure. -*/ -static int *storedd; -static st_table *computed; /* hash table to identify existing orders */ -static int *repeat; /* how many times an order is present */ -static int large; /* stores the index of the population with - ** the largest number of nodes in the DD */ -static int result; -static int cross; /* the number of crossovers to perform */ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/* macro used to access the population table as if it were a -** two-dimensional structure. -*/ -#define STOREDD(i,j) storedd[(i)*(numvars+1)+(j)] - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int make_random ARGS((DdManager *table, int lower)); -static int sift_up ARGS((DdManager *table, int x, int x_low)); -static int build_dd ARGS((DdManager *table, int num, int lower, int upper)); -static int largest ARGS(()); -static int rand_int ARGS((int a)); -static int array_hash ARGS((char *array, int modulus)); -static int array_compare ARGS((const char *array1, const char *array2)); -static int find_best ARGS(()); -static double find_average_fitness ARGS(()); -static int PMX ARGS((int maxvar)); -static int roulette ARGS((int *p1, int *p2)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Genetic algorithm for DD reordering.] - - Description [Genetic algorithm for DD reordering. - The two children of a crossover will be stored in - storedd[popsize] and storedd[popsize+1] --- the last two slots in the - storedd array. (This will make comparisons and replacement easy.) - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddGa( - DdManager * table /* manager */, - int lower /* lowest level to be reordered */, - int upper /* highest level to be reorderded */) -{ - int i,n,m; /* dummy/loop vars */ - int index; - double average_fitness; - int small; /* index of smallest DD in population */ - - /* Do an initial sifting to produce at least one reasonable individual. */ - if (!cuddSifting(table,lower,upper)) return(0); - - /* Get the initial values. */ - numvars = upper - lower + 1; /* number of variables to be reordered */ - if (table->populationSize == 0) { - popsize = 3 * numvars; /* population size is 3 times # of vars */ - if (popsize > 120) { - popsize = 120; /* Maximum population size is 120 */ - } - } else { - popsize = table->populationSize; /* user specified value */ - } - if (popsize < 4) popsize = 4; /* enforce minimum population size */ - - /* Allocate population table. */ - storedd = ALLOC(int,(popsize+2)*(numvars+1)); - if (storedd == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - - /* Initialize the computed table. This table is made up of two data - ** structures: A hash table with the key given by the order, which says - ** if a given order is present in the population; and the repeat - ** vector, which says how many copies of a given order are stored in - ** the population table. If there are multiple copies of an order, only - ** one has a repeat count greater than 1. This copy is the one pointed - ** by the computed table. - */ - repeat = ALLOC(int,popsize); - if (repeat == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - FREE(storedd); - return(0); - } - for (i = 0; i < popsize; i++) { - repeat[i] = 0; - } - computed = st_init_table(array_compare,array_hash); - if (computed == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - FREE(storedd); - FREE(repeat); - return(0); - } - - /* Copy the current DD and its size to the population table. */ - for (i = 0; i < numvars; i++) { - STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */ - } - STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */ - - /* Store the initial order in the computed table. */ - if (st_insert(computed,(char *)storedd,(char *) 0) == ST_OUT_OF_MEM) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - repeat[0]++; - - /* Insert the reverse order as second element of the population. */ - for (i = 0; i < numvars; i++) { - STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */ - } - - /* Now create the random orders. make_random fills the population - ** table with random permutations. The successive loop builds and sifts - ** the DDs for the reverse order and each random permutation, and stores - ** the results in the computed table. - */ - if (!make_random(table,lower)) { - table->errorCode = CUDD_MEMORY_OUT; - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - for (i = 1; i < popsize; i++) { - result = build_dd(table,i,lower,upper); /* build and sift order */ - if (!result) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - if (st_lookup(computed,(char *)&STOREDD(i,0),(char **)&index)) { - repeat[index]++; - } else { - if (st_insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) == - ST_OUT_OF_MEM) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - repeat[i]++; - } - } - -#if 0 -#ifdef DD_STATS - /* Print the initial population. */ - (void) fprintf(table->out,"Initial population after sifting\n"); - for (m = 0; m < popsize; m++) { - for (i = 0; i < numvars; i++) { - (void) fprintf(table->out," %2d",STOREDD(m,i)); - } - (void) fprintf(table->out," : %3d (%d)\n", - STOREDD(m,numvars),repeat[m]); - } -#endif -#endif - - small = find_best(); - average_fitness = find_average_fitness(); -#ifdef DD_STATS - (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); -#endif - - /* Decide how many crossovers should be tried. */ - if (table->numberXovers == 0) { - cross = 3*numvars; - if (cross > 60) { /* do a maximum of 50 crossovers */ - cross = 60; - } - } else { - cross = table->numberXovers; /* use user specified value */ - } - - /* Perform the crossovers to get the best order. */ - for (m = 0; m < cross; m++) { - if (!PMX(table->size)) { /* perform one crossover */ - table->errorCode = CUDD_MEMORY_OUT; - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - /* The offsprings are left in the last two entries of the - ** population table. These are now considered in turn. - */ - for (i = popsize; i <= popsize+1; i++) { - result = build_dd(table,i,lower,upper); /* build and sift child */ - if (!result) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - large = largest(); /* find the largest DD in population */ - - /* If the new child is smaller than the largest DD in the current - ** population, enter it into the population in place of the - ** largest DD. - */ - if (STOREDD(i,numvars) < STOREDD(large,numvars)) { - /* Look up the largest DD in the computed table. - ** Decrease its repetition count. If the repetition count - ** goes to 0, remove the largest DD from the computed table. - */ - result = st_lookup(computed,(char *)&STOREDD(large,0),(char - **)&index); - if (!result) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - repeat[index]--; - if (repeat[index] == 0) { - int *pointer = &STOREDD(index,0); - result = st_delete(computed, (char **)&pointer,NULL); - if (!result) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - } - /* Copy the new individual to the entry of the - ** population table just made available and update the - ** computed table. - */ - for (n = 0; n <= numvars; n++) { - STOREDD(large,n) = STOREDD(i,n); - } - if (st_lookup(computed,(char *)&STOREDD(large,0),(char - **)&index)) { - repeat[index]++; - } else { - if (st_insert(computed,(char *)&STOREDD(large,0), - (char *)(long)large) == ST_OUT_OF_MEM) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - repeat[large]++; - } - } - } - } - - /* Find the smallest DD in the population and build it; - ** that will be the result. - */ - small = find_best(); - - /* Print stats on the final population. */ -#ifdef DD_STATS - average_fitness = find_average_fitness(); - (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); -#endif - - /* Clean up, build the result DD, and return. */ - st_free_table(computed); - computed = NULL; - result = build_dd(table,small,lower,upper); - FREE(storedd); - FREE(repeat); - return(result); - -} /* end of cuddGa */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Generates the random sequences for the initial population.] - - Description [Generates the random sequences for the initial population. - The sequences are permutations of the indices between lower and - upper in the current order.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -make_random( - DdManager * table, - int lower) -{ - int i,j; /* loop variables */ - int *used; /* is a number already in a permutation */ - int next; /* next random number without repetitions */ - - used = ALLOC(int,numvars); - if (used == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } -#if 0 -#ifdef DD_STATS - (void) fprintf(table->out,"Initial population before sifting\n"); - for (i = 0; i < 2; i++) { - for (j = 0; j < numvars; j++) { - (void) fprintf(table->out," %2d",STOREDD(i,j)); - } - (void) fprintf(table->out,"\n"); - } -#endif -#endif - for (i = 2; i < popsize; i++) { - for (j = 0; j < numvars; j++) { - used[j] = 0; - } - /* Generate a permutation of {0...numvars-1} and use it to - ** permute the variables in the layesr from lower to upper. - */ - for (j = 0; j < numvars; j++) { - do { - next = rand_int(numvars-1); - } while (used[next] != 0); - used[next] = 1; - STOREDD(i,j) = table->invperm[next+lower]; - } -#if 0 -#ifdef DD_STATS - /* Print the order just generated. */ - for (j = 0; j < numvars; j++) { - (void) fprintf(table->out," %2d",STOREDD(i,j)); - } - (void) fprintf(table->out,"\n"); -#endif -#endif - } - FREE(used); - return(1); - -} /* end of make_random */ - - -/**Function******************************************************************** - - Synopsis [Moves one variable up.] - - Description [Takes a variable from position x and sifts it up to - position x_low; x_low should be less than x. Returns 1 if successful; - 0 otherwise] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -sift_up( - DdManager * table, - int x, - int x_low) -{ - int y; - int size; - - y = cuddNextLow(table,x); - while (y >= x_low) { - size = cuddSwapInPlace(table,y,x); - if (size == 0) { - return(0); - } - x = y; - y = cuddNextLow(table,x); - } - return(1); - -} /* end of sift_up */ - - -/**Function******************************************************************** - - Synopsis [Builds a DD from a given order.] - - Description [Builds a DD from a given order. This procedure also - sifts the final order and inserts into the array the size in nodes - of the result. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -build_dd( - DdManager * table, - int num /* the index of the individual to be built */, - int lower, - int upper) -{ - int i,j; /* loop vars */ - int position; - int index; - int limit; /* how large the DD for this order can grow */ - int size; - - /* Check the computed table. If the order already exists, it - ** suffices to copy the size from the existing entry. - */ - if (computed && st_lookup(computed,(char *)&STOREDD(num,0),(char **)&index)) { - STOREDD(num,numvars) = STOREDD(index,numvars); -#ifdef DD_STATS - (void) fprintf(table->out,"\nCache hit for index %d", index); -#endif - return(1); - } - - /* Stop if the DD grows 20 times larges than the reference size. */ - limit = 20 * STOREDD(0,numvars); - - /* Sift up the variables so as to build the desired permutation. - ** First the variable that has to be on top is sifted to the top. - ** Then the variable that has to occupy the secon position is sifted - ** up to the second position, and so on. - */ - for (j = 0; j < numvars; j++) { - i = STOREDD(num,j); - position = table->perm[i]; - result = sift_up(table,position,j+lower); - if (!result) return(0); - size = table->keys - table->isolated; - if (size > limit) break; - } - - /* Sift the DD just built. */ -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); -#endif - result = cuddSifting(table,lower,upper); - if (!result) return(0); - - /* Copy order and size to table. */ - for (j = 0; j < numvars; j++) { - STOREDD(num,j) = table->invperm[lower+j]; - } - STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */ - return(1); - -} /* end of build_dd */ - - -/**Function******************************************************************** - - Synopsis [Finds the largest DD in the population.] - - Description [Finds the largest DD in the population. If an order is - repeated, it avoids choosing the copy that is in the computed table - (it has repeat[i] > 1).] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -largest( - ) -{ - int i; /* loop var */ - int big; /* temporary holder to return result */ - - big = 0; - while (repeat[big] > 1) big++; - for (i = big + 1; i < popsize; i++) { - if (STOREDD(i,numvars) >= STOREDD(big,numvars) && repeat[i] <= 1) { - big = i; - } - } - return(big); - -} /* end of largest */ - - -/**Function******************************************************************** - - Synopsis [Generates a random number between 0 and the integer a.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -rand_int( - int a) -{ - return(Cudd_Random() % (a+1)); - -} /* end of rand_int */ - - -/**Function******************************************************************** - - Synopsis [Hash function for the computed table.] - - Description [Hash function for the computed table. Returns the bucket - number.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -array_hash( - char * array, - int modulus) -{ - int val = 0; - int i; - int *intarray; - - intarray = (int *) array; - - for (i = 0; i < numvars; i++) { - val = val * 997 + intarray[i]; - } - - return ((val < 0) ? -val : val) % modulus; - -} /* end of array_hash */ - - -/**Function******************************************************************** - - Synopsis [Comparison function for the computed table.] - - Description [Comparison function for the computed table. Returns 0 if - the two arrays are equal; 1 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -array_compare( - const char * array1, - const char * array2) -{ - int i; - int *intarray1, *intarray2; - - intarray1 = (int *) array1; - intarray2 = (int *) array2; - - for (i = 0; i < numvars; i++) { - if (intarray1[i] != intarray2[i]) return(1); - } - return(0); - -} /* end of array_compare */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of the fittest individual.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -find_best( - ) -{ - int i,small; - - small = 0; - for (i = 1; i < popsize; i++) { - if (STOREDD(i,numvars) < STOREDD(small,numvars)) { - small = i; - } - } - return(small); - -} /* end of find_best */ - - -/**Function******************************************************************** - - Synopsis [Returns the average fitness of the population.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static double -find_average_fitness( - ) -{ - int i; - int total_fitness = 0; - double average_fitness; - - for (i = 0; i < popsize; i++) { - total_fitness += STOREDD(i,numvars); - } - average_fitness = (double) total_fitness / (double) popsize; - return(average_fitness); - -} /* end of find_average_fitness */ - - -/**Function******************************************************************** - - Synopsis [Performs the crossover between two parents.] - - Description [Performs the crossover between two randomly chosen - parents, and creates two children, x1 and x2. Uses the Partially - Matched Crossover operator.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -PMX( - int maxvar) -{ - int cut1,cut2; /* the two cut positions (random) */ - int mom,dad; /* the two randomly chosen parents */ - int *inv1; /* inverse permutations for repair algo */ - int *inv2; - int i; /* loop vars */ - int u,v; /* aux vars */ - - inv1 = ALLOC(int,maxvar); - if (inv1 == NULL) { - return(0); - } - inv2 = ALLOC(int,maxvar); - if (inv2 == NULL) { - FREE(inv1); - return(0); - } - - /* Choose two orders from the population using roulette wheel. */ - if (!roulette(&mom,&dad)) { - FREE(inv1); - FREE(inv2); - return(0); - } - - /* Choose two random cut positions. A cut in position i means that - ** the cut immediately precedes position i. If cut1 < cut2, we - ** exchange the middle of the two orderings; otherwise, we - ** exchange the beginnings and the ends. - */ - cut1 = rand_int(numvars-1); - do { - cut2 = rand_int(numvars-1); - } while (cut1 == cut2); - -#if 0 - /* Print out the parents. */ - (void) fprintf(table->out, - "Crossover of %d (mom) and %d (dad) between %d and %d\n", - mom,dad,cut1,cut2); - for (i = 0; i < numvars; i++) { - if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); - (void) fprintf(table->out,"%2d ",STOREDD(mom,i)); - } - (void) fprintf(table->out,"\n"); - for (i = 0; i < numvars; i++) { - if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); - (void) fprintf(table->out,"%2d ",STOREDD(dad,i)); - } - (void) fprintf(table->out,"\n"); -#endif - - /* Initialize the inverse permutations: -1 means yet undetermined. */ - for (i = 0; i < maxvar; i++) { - inv1[i] = -1; - inv2[i] = -1; - } - - /* Copy the portions whithin the cuts. */ - for (i = cut1; i != cut2; i = (i == numvars-1) ? 0 : i+1) { - STOREDD(popsize,i) = STOREDD(dad,i); - inv1[STOREDD(popsize,i)] = i; - STOREDD(popsize+1,i) = STOREDD(mom,i); - inv2[STOREDD(popsize+1,i)] = i; - } - - /* Now apply the repair algorithm outside the cuts. */ - for (i = cut2; i != cut1; i = (i == numvars-1 ) ? 0 : i+1) { - v = i; - do { - u = STOREDD(mom,v); - v = inv1[u]; - } while (v != -1); - STOREDD(popsize,i) = u; - inv1[u] = i; - v = i; - do { - u = STOREDD(dad,v); - v = inv2[u]; - } while (v != -1); - STOREDD(popsize+1,i) = u; - inv2[u] = i; - } - -#if 0 - /* Print the results of crossover. */ - for (i = 0; i < numvars; i++) { - if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); - (void) fprintf(table->out,"%2d ",STOREDD(popsize,i)); - } - (void) fprintf(table->out,"\n"); - for (i = 0; i < numvars; i++) { - if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); - (void) fprintf(table->out,"%2d ",STOREDD(popsize+1,i)); - } - (void) fprintf(table->out,"\n"); -#endif - - FREE(inv1); - FREE(inv2); - return(1); - -} /* end of PMX */ - - -/**Function******************************************************************** - - Synopsis [Selects two parents with the roulette wheel method.] - - Description [Selects two distinct parents with the roulette wheel method.] - - SideEffects [The indices of the selected parents are returned as side - effects.] - - SeeAlso [] - -******************************************************************************/ -static int -roulette( - int * p1, - int * p2) -{ - double *wheel; - double spin; - int i; - - wheel = ALLOC(double,popsize); - if (wheel == NULL) { - return(0); - } - - /* The fitness of an individual is the reciprocal of its size. */ - wheel[0] = 1.0 / (double) STOREDD(0,numvars); - - for (i = 1; i < popsize; i++) { - wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars); - } - - /* Get a random number between 0 and wheel[popsize-1] (that is, - ** the sum of all fitness values. 2147483561 is the largest number - ** returned by Cudd_Random. - */ - spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0; - - /* Find the lucky element by scanning the wheel. */ - for (i = 0; i < popsize; i++) { - if (spin <= wheel[i]) break; - } - *p1 = i; - - /* Repeat the process for the second parent, making sure it is - ** distinct from the first. - */ - do { - spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0; - for (i = 0; i < popsize; i++) { - if (spin <= wheel[i]) break; - } - } while (i == *p1); - *p2 = i; - - FREE(wheel); - return(1); - -} /* end of roulette */ - diff --git a/src/bdd/cudd/cuddGroup.c b/src/bdd/cudd/cuddGroup.c deleted file mode 100644 index 81c05d2c..00000000 --- a/src/bdd/cudd/cuddGroup.c +++ /dev/null @@ -1,2142 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddGroup.c] - - PackageName [cudd] - - Synopsis [Functions for group sifting.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_MakeTreeNode() - </ul> - Internal procedures included in this file: - <ul> - <li> cuddTreeSifting() - </ul> - Static procedures included in this module: - <ul> - <li> ddTreeSiftingAux() - <li> ddCountInternalMtrNodes() - <li> ddReorderChildren() - <li> ddFindNodeHiLo() - <li> ddUniqueCompareGroup() - <li> ddGroupSifting() - <li> ddCreateGroup() - <li> ddGroupSiftingAux() - <li> ddGroupSiftingUp() - <li> ddGroupSiftingDown() - <li> ddGroupMove() - <li> ddGroupMoveBackward() - <li> ddGroupSiftingBackward() - <li> ddMergeGroups() - <li> ddDissolveGroup() - <li> ddNoCheck() - <li> ddSecDiffCheck() - <li> ddExtSymmCheck() - <li> ddVarGroupCheck() - <li> ddSetVarHandled() - <li> ddResetVarHandled() - <li> ddIsVarHandled() - </ul>] - - Author [Shipra Panda, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/* Constants for lazy sifting */ -#define DD_NORMAL_SIFT 0 -#define DD_LAZY_SIFT 1 - -/* Constants for sifting up and down */ -#define DD_SIFT_DOWN 0 -#define DD_SIFT_UP 1 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddGroup.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -static int *entry; -extern int ddTotalNumberSwapping; -#ifdef DD_STATS -extern int ddTotalNISwaps; -static int extsymmcalls; -static int extsymm; -static int secdiffcalls; -static int secdiff; -static int secdiffmisfire; -#endif -#ifdef DD_DEBUG -static int pr = 0; /* flag to enable printing while debugging */ - /* by depositing a 1 into it */ -#endif -static int originalSize; -static int originalLevel; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddTreeSiftingAux ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); -#ifdef DD_STATS -static int ddCountInternalMtrNodes ARGS((DdManager *table, MtrNode *treenode)); -#endif -static int ddReorderChildren ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); -static void ddFindNodeHiLo ARGS((DdManager *table, MtrNode *treenode, int *lower, int *upper)); -static int ddUniqueCompareGroup ARGS((int *ptrX, int *ptrY)); -static int ddGroupSifting ARGS((DdManager *table, int lower, int upper, int (*checkFunction)(DdManager *, int, int), int lazyFlag)); -static void ddCreateGroup ARGS((DdManager *table, int x, int y)); -static int ddGroupSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh, int (*checkFunction)(DdManager *, int, int), int lazyFlag)); -static int ddGroupSiftingUp ARGS((DdManager *table, int y, int xLow, int (*checkFunction)(DdManager *, int, int), Move **moves)); -static int ddGroupSiftingDown ARGS((DdManager *table, int x, int xHigh, int (*checkFunction)(DdManager *, int, int), Move **moves)); -static int ddGroupMove ARGS((DdManager *table, int x, int y, Move **moves)); -static int ddGroupMoveBackward ARGS((DdManager *table, int x, int y)); -static int ddGroupSiftingBackward ARGS((DdManager *table, Move *moves, int size, int upFlag, int lazyFlag)); -static void ddMergeGroups ARGS((DdManager *table, MtrNode *treenode, int low, int high)); -static void ddDissolveGroup ARGS((DdManager *table, int x, int y)); -static int ddNoCheck ARGS((DdManager *table, int x, int y)); -static int ddSecDiffCheck ARGS((DdManager *table, int x, int y)); -static int ddExtSymmCheck ARGS((DdManager *table, int x, int y)); -static int ddVarGroupCheck ARGS((DdManager * table, int x, int y)); -static int ddSetVarHandled ARGS((DdManager *dd, int index)); -static int ddResetVarHandled ARGS((DdManager *dd, int index)); -static int ddIsVarHandled ARGS((DdManager *dd, int index)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Creates a new variable group.] - - Description [Creates a new variable group. The group starts at - variable and contains size variables. The parameter low is the index - of the first variable. If the variable already exists, its current - position in the order is known to the manager. If the variable does - not exist yet, the position is assumed to be the same as the index. - The group tree is created if it does not exist yet. - Returns a pointer to the group if successful; NULL otherwise.] - - SideEffects [The variable tree is changed.] - - SeeAlso [Cudd_MakeZddTreeNode] - -******************************************************************************/ -MtrNode * -Cudd_MakeTreeNode( - DdManager * dd /* manager */, - unsigned int low /* index of the first group variable */, - unsigned int size /* number of variables in the group */, - unsigned int type /* MTR_DEFAULT or MTR_FIXED */) -{ - MtrNode *group; - MtrNode *tree; - unsigned int level; - - /* If the variable does not exist yet, the position is assumed to be - ** the same as the index. Therefore, applications that rely on - ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new - ** variables have to create the variables before they group them. - */ - level = (low < (unsigned int) dd->size) ? dd->perm[low] : low; - - if (level + size - 1> (int) MTR_MAXHIGH) - return(NULL); - - /* If the tree does not exist yet, create it. */ - tree = dd->tree; - if (tree == NULL) { - dd->tree = tree = Mtr_InitGroupTree(0, dd->size); - if (tree == NULL) - return(NULL); - tree->index = dd->invperm[0]; - } - - /* Extend the upper bound of the tree if necessary. This allows the - ** application to create groups even before the variables are created. - */ - tree->size = ddMax(tree->size, ddMax(level + size, (unsigned) dd->size)); - - /* Create the group. */ - group = Mtr_MakeGroup(tree, level, size, type); - if (group == NULL) - return(NULL); - - /* Initialize the index field to the index of the variable currently - ** in position low. This field will be updated by the reordering - ** procedure to provide a handle to the group once it has been moved. - */ - group->index = (MtrHalfWord) low; - - return(group); - -} /* end of Cudd_MakeTreeNode */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Tree sifting algorithm.] - - Description [Tree sifting algorithm. Assumes that a tree representing - a group hierarchy is passed as a parameter. It then reorders each - group in postorder fashion by calling ddTreeSiftingAux. Assumes that - no dead nodes are present. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddTreeSifting( - DdManager * table /* DD table */, - Cudd_ReorderingType method /* reordering method for the groups of leaves */) -{ - int i; - int nvars; - int result; - int tempTree; - - /* If no tree is provided we create a temporary one in which all - ** variables are in a single group. After reordering this tree is - ** destroyed. - */ - tempTree = table->tree == NULL; - if (tempTree) { - table->tree = Mtr_InitGroupTree(0,table->size); - table->tree->index = table->invperm[0]; - } - nvars = table->size; - -#ifdef DD_DEBUG - if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:"); - Mtr_PrintGroups(table->tree,pr <= 0); -#endif - -#ifdef DD_STATS - extsymmcalls = 0; - extsymm = 0; - secdiffcalls = 0; - secdiff = 0; - secdiffmisfire = 0; - - (void) fprintf(table->out,"\n"); - if (!tempTree) - (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", - ddCountInternalMtrNodes(table,table->tree)); -#endif - - /* Initialize the group of each subtable to itself. Initially - ** there are no groups. Groups are created according to the tree - ** structure in postorder fashion. - */ - for (i = 0; i < nvars; i++) - table->subtables[i].next = i; - - - /* Reorder. */ - result = ddTreeSiftingAux(table, table->tree, method); - -#ifdef DD_STATS /* print stats */ - if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && - (table->groupcheck == CUDD_GROUP_CHECK7 || - table->groupcheck == CUDD_GROUP_CHECK5)) { - (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); - (void) fprintf(table->out,"extsymm = %d",extsymm); - } - if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && - table->groupcheck == CUDD_GROUP_CHECK7) { - (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); - (void) fprintf(table->out,"secdiff = %d\n",secdiff); - (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); - } -#endif - - if (tempTree) - Cudd_FreeTree(table); - return(result); - -} /* end of cuddTreeSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Visits the group tree and reorders each group.] - - Description [Recursively visits the group tree and reorders each - group in postorder fashion. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddTreeSiftingAux( - DdManager * table, - MtrNode * treenode, - Cudd_ReorderingType method) -{ - MtrNode *auxnode; - int res; - Cudd_AggregationType saveCheck; - -#ifdef DD_DEBUG - Mtr_PrintGroups(treenode,1); -#endif - - auxnode = treenode; - while (auxnode != NULL) { - if (auxnode->child != NULL) { - if (!ddTreeSiftingAux(table, auxnode->child, method)) - return(0); - saveCheck = table->groupcheck; - table->groupcheck = CUDD_NO_CHECK; - if (method != CUDD_REORDER_LAZY_SIFT) - res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT); - else - res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT); - table->groupcheck = saveCheck; - - if (res == 0) - return(0); - } else if (auxnode->size > 1) { - if (!ddReorderChildren(table, auxnode, method)) - return(0); - } - auxnode = auxnode->younger; - } - - return(1); - -} /* end of ddTreeSiftingAux */ - - -#ifdef DD_STATS -/**Function******************************************************************** - - Synopsis [Counts the number of internal nodes of the group tree.] - - Description [Counts the number of internal nodes of the group tree. - Returns the count.] - - SideEffects [None] - -******************************************************************************/ -static int -ddCountInternalMtrNodes( - DdManager * table, - MtrNode * treenode) -{ - MtrNode *auxnode; - int count,nodeCount; - - - nodeCount = 0; - auxnode = treenode; - while (auxnode != NULL) { - if (!(MTR_TEST(auxnode,MTR_TERMINAL))) { - nodeCount++; - count = ddCountInternalMtrNodes(table,auxnode->child); - nodeCount += count; - } - auxnode = auxnode->younger; - } - - return(nodeCount); - -} /* end of ddCountInternalMtrNodes */ -#endif - - -/**Function******************************************************************** - - Synopsis [Reorders the children of a group tree node according to - the options.] - - Description [Reorders the children of a group tree node according to - the options. After reordering puts all the variables in the group - and/or its descendents in a single group. This allows hierarchical - reordering. If the variables in the group do not exist yet, simply - does nothing. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddReorderChildren( - DdManager * table, - MtrNode * treenode, - Cudd_ReorderingType method) -{ - int lower; - int upper; - int result; - unsigned int initialSize; - - ddFindNodeHiLo(table,treenode,&lower,&upper); - /* If upper == -1 these variables do not exist yet. */ - if (upper == -1) - return(1); - - if (treenode->flags == MTR_FIXED) { - result = 1; - } else { -#ifdef DD_STATS - (void) fprintf(table->out," "); -#endif - switch (method) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - result = cuddSwapping(table,lower,upper,method); - break; - case CUDD_REORDER_SIFT: - result = cuddSifting(table,lower,upper); - break; - case CUDD_REORDER_SIFT_CONVERGE: - do { - initialSize = table->keys - table->isolated; - result = cuddSifting(table,lower,upper); - if (initialSize <= table->keys - table->isolated) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - case CUDD_REORDER_SYMM_SIFT: - result = cuddSymmSifting(table,lower,upper); - break; - case CUDD_REORDER_SYMM_SIFT_CONV: - result = cuddSymmSiftingConv(table,lower,upper); - break; - case CUDD_REORDER_GROUP_SIFT: - if (table->groupcheck == CUDD_NO_CHECK) { - result = ddGroupSifting(table,lower,upper,ddNoCheck, - DD_NORMAL_SIFT); - } else if (table->groupcheck == CUDD_GROUP_CHECK5) { - result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, - DD_NORMAL_SIFT); - } else if (table->groupcheck == CUDD_GROUP_CHECK7) { - result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, - DD_NORMAL_SIFT); - } else { - (void) fprintf(table->err, - "Unknown group ckecking method\n"); - result = 0; - } - break; - case CUDD_REORDER_GROUP_SIFT_CONV: - do { - initialSize = table->keys - table->isolated; - if (table->groupcheck == CUDD_NO_CHECK) { - result = ddGroupSifting(table,lower,upper,ddNoCheck, - DD_NORMAL_SIFT); - } else if (table->groupcheck == CUDD_GROUP_CHECK5) { - result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, - DD_NORMAL_SIFT); - } else if (table->groupcheck == CUDD_GROUP_CHECK7) { - result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, - DD_NORMAL_SIFT); - } else { - (void) fprintf(table->err, - "Unknown group ckecking method\n"); - result = 0; - } -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); -#endif - result = cuddWindowReorder(table,lower,upper, - CUDD_REORDER_WINDOW4); - if (initialSize <= table->keys - table->isolated) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - case CUDD_REORDER_WINDOW2: - case CUDD_REORDER_WINDOW3: - case CUDD_REORDER_WINDOW4: - case CUDD_REORDER_WINDOW2_CONV: - case CUDD_REORDER_WINDOW3_CONV: - case CUDD_REORDER_WINDOW4_CONV: - result = cuddWindowReorder(table,lower,upper,method); - break; - case CUDD_REORDER_ANNEALING: - result = cuddAnnealing(table,lower,upper); - break; - case CUDD_REORDER_GENETIC: - result = cuddGa(table,lower,upper); - break; - case CUDD_REORDER_LINEAR: - result = cuddLinearAndSifting(table,lower,upper); - break; - case CUDD_REORDER_LINEAR_CONVERGE: - do { - initialSize = table->keys - table->isolated; - result = cuddLinearAndSifting(table,lower,upper); - if (initialSize <= table->keys - table->isolated) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - case CUDD_REORDER_EXACT: - result = cuddExact(table,lower,upper); - break; - case CUDD_REORDER_LAZY_SIFT: - result = ddGroupSifting(table,lower,upper,ddVarGroupCheck, - DD_LAZY_SIFT); - break; - default: - return(0); - } - } - - /* Create a single group for all the variables that were sifted, - ** so that they will be treated as a single block by successive - ** invocations of ddGroupSifting. - */ - ddMergeGroups(table,treenode,lower,upper); - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:"); -#endif - - return(result); - -} /* end of ddReorderChildren */ - - -/**Function******************************************************************** - - Synopsis [Finds the lower and upper bounds of the group represented - by treenode.] - - Description [Finds the lower and upper bounds of the group - represented by treenode. From the index and size fields we need to - derive the current positions, and find maximum and minimum.] - - SideEffects [The bounds are returned as side effects.] - - SeeAlso [] - -******************************************************************************/ -static void -ddFindNodeHiLo( - DdManager * table, - MtrNode * treenode, - int * lower, - int * upper) -{ - int low; - int high; - - /* Check whether no variables in this group already exist. - ** If so, return immediately. The calling procedure will know from - ** the values of upper that no reordering is needed. - */ - if ((int) treenode->low >= table->size) { - *lower = table->size; - *upper = -1; - return; - } - - *lower = low = (unsigned int) table->perm[treenode->index]; - high = (int) (low + treenode->size - 1); - - if (high >= table->size) { - /* This is the case of a partially existing group. The aim is to - ** reorder as many variables as safely possible. If the tree - ** node is terminal, we just reorder the subset of the group - ** that is currently in existence. If the group has - ** subgroups, then we only reorder those subgroups that are - ** fully instantiated. This way we avoid breaking up a group. - */ - MtrNode *auxnode = treenode->child; - if (auxnode == NULL) { - *upper = (unsigned int) table->size - 1; - } else { - /* Search the subgroup that strands the table->size line. - ** If the first group starts at 0 and goes past table->size - ** upper will get -1, thus correctly signaling that no reordering - ** should take place. - */ - while (auxnode != NULL) { - int thisLower = table->perm[auxnode->low]; - int thisUpper = thisLower + auxnode->size - 1; - if (thisUpper >= table->size && thisLower < table->size) - *upper = (unsigned int) thisLower - 1; - auxnode = auxnode->younger; - } - } - } else { - /* Normal case: All the variables of the group exist. */ - *upper = (unsigned int) high; - } - -#ifdef DD_DEBUG - /* Make sure that all variables in group are contiguous. */ - assert(treenode->size >= *upper - *lower + 1); -#endif - - return; - -} /* end of ddFindNodeHiLo */ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the variables - according to the number of keys in the subtables. Returns the - difference in number of keys between the two variables being - compared.] - - SideEffects [None] - -******************************************************************************/ -static int -ddUniqueCompareGroup( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of ddUniqueCompareGroup */ - - -/**Function******************************************************************** - - Synopsis [Sifts from treenode->low to treenode->high.] - - Description [Sifts from treenode->low to treenode->high. If - croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the - end of the initial sifting. If a group is created, it is then sifted - again. After sifting one variable, the group that contains it is - dissolved. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupSifting( - DdManager * table, - int lower, - int upper, - int (*checkFunction)(DdManager *, int, int), - int lazyFlag) -{ - int *var; - int i,j,x,xInit; - int nvars; - int classes; - int result; - int *sifted; - int merged; - int dissolve; -#ifdef DD_STATS - unsigned previousSize; -#endif - int xindex; - - nvars = table->size; - - /* Order variables to sift. */ - entry = NULL; - sifted = NULL; - var = ALLOC(int,nvars); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddGroupSiftingOutOfMem; - } - entry = ALLOC(int,nvars); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddGroupSiftingOutOfMem; - } - sifted = ALLOC(int,nvars); - if (sifted == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddGroupSiftingOutOfMem; - } - - /* Here we consider only one representative for each group. */ - for (i = 0, classes = 0; i < nvars; i++) { - sifted[i] = 0; - x = table->perm[i]; - if ((unsigned) x >= table->subtables[x].next) { - entry[i] = table->subtables[x].keys; - var[classes] = i; - classes++; - } - } - - qsort((void *)var,classes,sizeof(int), - (int (*)(const void *, const void *)) ddUniqueCompareGroup); - - if (lazyFlag) { - for (i = 0; i < nvars; i ++) { - ddResetVarHandled(table, i); - } - } - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - xindex = var[i]; - if (sifted[xindex] == 1) /* variable already sifted as part of group */ - continue; - x = table->perm[xindex]; /* find current level of this variable */ - - if (x < lower || x > upper || table->subtables[x].bindVar == 1) - continue; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif -#ifdef DD_DEBUG - /* x is bottom of group */ - assert((unsigned) x >= table->subtables[x].next); -#endif - if ((unsigned) x == table->subtables[x].next) { - dissolve = 1; - result = ddGroupSiftingAux(table,x,lower,upper,checkFunction, - lazyFlag); - } else { - dissolve = 0; - result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag); - } - if (!result) goto ddGroupSiftingOutOfMem; - - /* check for aggregation */ - merged = 0; - if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) { - x = table->perm[xindex]; /* find current level */ - if ((unsigned) x == table->subtables[x].next) { /* not part of a group */ - if (x != upper && sifted[table->invperm[x+1]] == 0 && - (unsigned) x+1 == table->subtables[x+1].next) { - if (ddSecDiffCheck(table,x,x+1)) { - merged =1; - ddCreateGroup(table,x,x+1); - } - } - if (x != lower && sifted[table->invperm[x-1]] == 0 && - (unsigned) x-1 == table->subtables[x-1].next) { - if (ddSecDiffCheck(table,x-1,x)) { - merged =1; - ddCreateGroup(table,x-1,x); - } - } - } - } - - if (merged) { /* a group was created */ - /* move x to bottom of group */ - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - /* sift */ - result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag); - if (!result) goto ddGroupSiftingOutOfMem; -#ifdef DD_STATS - if (table->keys < previousSize + table->isolated) { - (void) fprintf(table->out,"_"); - } else if (table->keys > previousSize + table->isolated) { - (void) fprintf(table->out,"^"); - } else { - (void) fprintf(table->out,"*"); - } - fflush(table->out); - } else { - if (table->keys < previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > previousSize + table->isolated) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - /* Mark variables in the group just sifted. */ - x = table->perm[xindex]; - if ((unsigned) x != table->subtables[x].next) { - xInit = x; - do { - j = table->invperm[x]; - sifted[j] = 1; - x = table->subtables[x].next; - } while (x != xInit); - - /* Dissolve the group if it was created. */ - if (lazyFlag == 0 && dissolve) { - do { - j = table->subtables[x].next; - table->subtables[x].next = x; - x = j; - } while (x != xInit); - } - } - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:"); -#endif - - if (lazyFlag) ddSetVarHandled(table, xindex); - } /* for */ - - FREE(sifted); - FREE(var); - FREE(entry); - - return(1); - -ddGroupSiftingOutOfMem: - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - if (sifted != NULL) FREE(sifted); - - return(0); - -} /* end of ddGroupSifting */ - - -/**Function******************************************************************** - - Synopsis [Creates a group encompassing variables from x to y in the - DD table.] - - Description [Creates a group encompassing variables from x to y in the - DD table. In the current implementation it must be y == x+1. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static void -ddCreateGroup( - DdManager * table, - int x, - int y) -{ - int gybot; - -#ifdef DD_DEBUG - assert(y == x+1); -#endif - - /* Find bottom of second group. */ - gybot = y; - while ((unsigned) gybot < table->subtables[gybot].next) - gybot = table->subtables[gybot].next; - - /* Link groups. */ - table->subtables[x].next = y; - table->subtables[gybot].next = x; - - return; - -} /* ddCreateGroup */ - - -/**Function******************************************************************** - - Synopsis [Sifts one variable up and down until it has taken all - positions. Checks for aggregation.] - - Description [Sifts one variable up and down until it has taken all - positions. Checks for aggregation. There may be at most two sweeps, - even if the group grows. Assumes that x is either an isolated - variable, or it is the bottom of a group. All groups may not have - been found. The variable being moved is returned to the best position - seen during sifting. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh, - int (*checkFunction)(DdManager *, int, int), - int lazyFlag) -{ - Move *move; - Move *moves; /* list of moves */ - int initialSize; - int result; - int y; - int topbot; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out, - "ddGroupSiftingAux from %d to %d\n",xLow,xHigh); - assert((unsigned) x >= table->subtables[x].next); /* x is bottom of group */ -#endif - - initialSize = table->keys - table->isolated; - moves = NULL; - - originalSize = initialSize; /* for lazy sifting */ - - /* If we have a singleton, we check for aggregation in both - ** directions before we sift. - */ - if ((unsigned) x == table->subtables[x].next) { - /* Will go down first, unless x == xHigh: - ** Look for aggregation above x. - */ - for (y = x; y > xLow; y--) { - if (!checkFunction(table,y-1,y)) - break; - topbot = table->subtables[y-1].next; /* find top of y-1's group */ - table->subtables[y-1].next = y; - table->subtables[x].next = topbot; /* x is bottom of group so its */ - /* next is top of y-1's group */ - y = topbot + 1; /* add 1 for y--; new y is top of group */ - } - /* Will go up first unless x == xlow: - ** Look for aggregation below x. - */ - for (y = x; y < xHigh; y++) { - if (!checkFunction(table,y,y+1)) - break; - /* find bottom of y+1's group */ - topbot = y + 1; - while ((unsigned) topbot < table->subtables[topbot].next) { - topbot = table->subtables[topbot].next; - } - table->subtables[topbot].next = table->subtables[y].next; - table->subtables[y].next = y + 1; - y = topbot - 1; /* subtract 1 for y++; new y is bottom of group */ - } - } - - /* Now x may be in the middle of a group. - ** Find bottom of x's group. - */ - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - - originalLevel = x; /* for lazy sifting */ - - if (x == xLow) { /* Sift down */ -#ifdef DD_DEBUG - /* x must be a singleton */ - assert((unsigned) x == table->subtables[x].next); -#endif - if (x == xHigh) return(1); /* just one variable */ - - if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - /* move backward and stop at best position */ - result = ddGroupSiftingBackward(table,moves,initialSize, - DD_SIFT_DOWN,lazyFlag); -#ifdef DD_DEBUG - assert(table->keys - table->isolated <= (unsigned) initialSize); -#endif - if (!result) goto ddGroupSiftingAuxOutOfMem; - - } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ -#ifdef DD_DEBUG - /* x is bottom of group */ - assert((unsigned) x >= table->subtables[x].next); -#endif - /* Find top of x's group */ - x = table->subtables[x].next; - - if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - /* at this point x == xLow, unless early term */ - - /* move backward and stop at best position */ - result = ddGroupSiftingBackward(table,moves,initialSize, - DD_SIFT_UP,lazyFlag); -#ifdef DD_DEBUG - assert(table->keys - table->isolated <= (unsigned) initialSize); -#endif - if (!result) goto ddGroupSiftingAuxOutOfMem; - - } else if (x - xLow > xHigh - x) { /* must go down first: shorter */ - if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - /* Find top of group */ - if (moves) { - x = moves->y; - } - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - x = table->subtables[x].next; -#ifdef DD_DEBUG - /* x should be the top of a group */ - assert((unsigned) x <= table->subtables[x].next); -#endif - - if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - - /* move backward and stop at best position */ - result = ddGroupSiftingBackward(table,moves,initialSize, - DD_SIFT_UP,lazyFlag); -#ifdef DD_DEBUG - assert(table->keys - table->isolated <= (unsigned) initialSize); -#endif - if (!result) goto ddGroupSiftingAuxOutOfMem; - - } else { /* moving up first: shorter */ - /* Find top of x's group */ - x = table->subtables[x].next; - - if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - if (moves) { - x = moves->x; - } - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; -#ifdef DD_DEBUG - /* x is bottom of a group */ - assert((unsigned) x >= table->subtables[x].next); -#endif - - if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - - /* move backward and stop at best position */ - result = ddGroupSiftingBackward(table,moves,initialSize, - DD_SIFT_DOWN,lazyFlag); -#ifdef DD_DEBUG - assert(table->keys - table->isolated <= (unsigned) initialSize); -#endif - if (!result) goto ddGroupSiftingAuxOutOfMem; - } - - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(1); - -ddGroupSiftingAuxOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(0); - -} /* end of ddGroupSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts up a variable until either it reaches position xLow - or the size of the DD heap increases too much.] - - Description [Sifts up a variable until either it reaches position - xLow or the size of the DD heap increases too much. Assumes that y is - the top of a group (or a singleton). Checks y for aggregation to the - adjacent variables. Records all the moves that are appended to the - list of moves received as input and returned as a side effect. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupSiftingUp( - DdManager * table, - int y, - int xLow, - int (*checkFunction)(DdManager *, int, int), - Move ** moves) -{ - Move *move; - int x; - int size; - int i; - int gxtop,gybot; - int limitSize; - int xindex, yindex; - int zindex; - int z; - int isolated; - int L; /* lower bound on DD size */ -#ifdef DD_DEBUG - int checkL; -#endif - - yindex = table->invperm[y]; - - /* Initialize the lower bound. - ** The part of the DD below the bottom of y's group will not change. - ** The part of the DD above y that does not interact with any - ** variable of y's group will not change. - ** The rest may vanish in the best case, except for - ** the nodes at level xLow, which will not vanish, regardless. - ** What we use here is not really a lower bound, because we ignore - ** the interactions with all variables except y. - */ - limitSize = L = table->keys - table->isolated; - gybot = y; - while ((unsigned) gybot < table->subtables[gybot].next) - gybot = table->subtables[gybot].next; - for (z = xLow + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - L -= table->subtables[z].keys - isolated; - } - } - - originalLevel = y; /* for lazy sifting */ - - x = cuddNextLow(table,y); - while (x >= xLow && L <= limitSize) { -#ifdef DD_DEBUG - gybot = y; - while ((unsigned) gybot < table->subtables[gybot].next) - gybot = table->subtables[gybot].next; - checkL = table->keys - table->isolated; - for (z = xLow + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - checkL -= table->subtables[z].keys - isolated; - } - } - if (pr > 0 && L != checkL) { - (void) fprintf(table->out, - "Inaccurate lower bound: L = %d checkL = %d\n", - L, checkL); - } -#endif - gxtop = table->subtables[x].next; - if (checkFunction(table,x,y)) { - /* Group found, attach groups */ - table->subtables[x].next = y; - i = table->subtables[y].next; - while (table->subtables[i].next != (unsigned) y) - i = table->subtables[i].next; - table->subtables[i].next = gxtop; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddGroupSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_NEWNODE; - move->size = table->keys - table->isolated; - move->next = *moves; - *moves = move; - } else if (table->subtables[x].next == (unsigned) x && - table->subtables[y].next == (unsigned) y) { - /* x and y are self groups */ - xindex = table->invperm[x]; - size = cuddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtables[x].next == (unsigned) x); - assert(table->subtables[y].next == (unsigned) y); -#endif - if (size == 0) goto ddGroupSiftingUpOutOfMem; - /* Update the lower bound. */ - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L += table->subtables[y].keys - isolated; - } - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddGroupSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_DEFAULT; - move->size = size; - move->next = *moves; - *moves = move; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out, - "ddGroupSiftingUp (2 single groups):\n"); -#endif - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } else { /* Group move */ - size = ddGroupMove(table,x,y,moves); - if (size == 0) goto ddGroupSiftingUpOutOfMem; - /* Update the lower bound. */ - z = (*moves)->y; - do { - zindex = table->invperm[z]; - if (cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - L += table->subtables[z].keys - isolated; - } - z = table->subtables[z].next; - } while (z != (int) (*moves)->y); - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } - y = gxtop; - x = cuddNextLow(table,y); - } - - return(1); - -ddGroupSiftingUpOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - return(0); - -} /* end of ddGroupSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts down a variable until it reaches position xHigh.] - - Description [Sifts down a variable until it reaches position xHigh. - Assumes that x is the bottom of a group (or a singleton). Records - all the moves. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupSiftingDown( - DdManager * table, - int x, - int xHigh, - int (*checkFunction)(DdManager *, int, int), - Move ** moves) -{ - Move *move; - int y; - int size; - int limitSize; - int gxtop,gybot; - int R; /* upper bound on node decrease */ - int xindex, yindex; - int isolated, allVars; - int z; - int zindex; -#ifdef DD_DEBUG - int checkR; -#endif - - /* If the group consists of simple variables, there is no point in - ** sifting it down. This check is redundant if the projection functions - ** do not have external references, because the computation of the - ** lower bound takes care of the problem. It is necessary otherwise to - ** prevent the sifting down of simple variables. */ - y = x; - allVars = 1; - do { - if (table->subtables[y].keys != 1) { - allVars = 0; - break; - } - y = table->subtables[y].next; - } while (table->subtables[y].next != (unsigned) x); - if (allVars) - return(1); - - /* Initialize R. */ - xindex = table->invperm[x]; - gxtop = table->subtables[x].next; - limitSize = size = table->keys - table->isolated; - R = 0; - for (z = xHigh; z > gxtop; z--) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R += table->subtables[z].keys - isolated; - } - } - - originalLevel = x; /* for lazy sifting */ - - y = cuddNextHigh(table,x); - while (y <= xHigh && size - R < limitSize) { -#ifdef DD_DEBUG - gxtop = table->subtables[x].next; - checkR = 0; - for (z = xHigh; z > gxtop; z--) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - checkR += table->subtables[z].keys - isolated; - } - } - assert(R >= checkR); -#endif - /* Find bottom of y group. */ - gybot = table->subtables[y].next; - while (table->subtables[gybot].next != (unsigned) y) - gybot = table->subtables[gybot].next; - - if (checkFunction(table,x,y)) { - /* Group found: attach groups and record move. */ - gxtop = table->subtables[x].next; - table->subtables[x].next = y; - table->subtables[gybot].next = gxtop; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddGroupSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_NEWNODE; - move->size = table->keys - table->isolated; - move->next = *moves; - *moves = move; - } else if (table->subtables[x].next == (unsigned) x && - table->subtables[y].next == (unsigned) y) { - /* x and y are self groups */ - /* Update upper bound on node decrease. */ - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R -= table->subtables[y].keys - isolated; - } - size = cuddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtables[x].next == (unsigned) x); - assert(table->subtables[y].next == (unsigned) y); -#endif - if (size == 0) goto ddGroupSiftingDownOutOfMem; - - /* Record move. */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddGroupSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_DEFAULT; - move->size = size; - move->next = *moves; - *moves = move; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out, - "ddGroupSiftingDown (2 single groups):\n"); -#endif - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - - x = y; - y = cuddNextHigh(table,x); - } else { /* Group move */ - /* Update upper bound on node decrease: first phase. */ - gxtop = table->subtables[x].next; - z = gxtop + 1; - do { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R -= table->subtables[z].keys - isolated; - } - z++; - } while (z <= gybot); - size = ddGroupMove(table,x,y,moves); - if (size == 0) goto ddGroupSiftingDownOutOfMem; - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - - /* Update upper bound on node decrease: second phase. */ - gxtop = table->subtables[gybot].next; - for (z = gxtop + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R += table->subtables[z].keys - isolated; - } - } - } - x = gybot; - y = cuddNextHigh(table,x); - } - - return(1); - -ddGroupSiftingDownOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - - return(0); - -} /* end of ddGroupSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Swaps two groups and records the move.] - - Description [Swaps two groups and records the move. Returns the - number of keys in the DD table in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupMove( - DdManager * table, - int x, - int y, - Move ** moves) -{ - Move *move; - int size; - int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - int swapx,swapy; -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - int initialSize,bestSize; -#endif - -#if DD_DEBUG - /* We assume that x < y */ - assert(x < y); -#endif - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtables[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtables[ybot].next) - ybot = table->subtables[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - initialSize = bestSize = table->keys - table->isolated; -#endif - /* Sift the variables of the second group up through the first group */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddGroupMoveOutOfMem; -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (size < bestSize) - bestSize = size; -#endif - swapx = x; swapy = y; - y = x; - x = cuddNextLow(table,y); - } - y = ytop + i; - x = cuddNextLow(table,y); - } -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if ((bestSize < initialSize) && (bestSize < size)) - (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size); -#endif - - /* fix groups */ - y = xtop; /* ytop is now where xtop used to be */ - for (i = 0; i < ysize - 1; i++) { - table->subtables[y].next = cuddNextHigh(table,y); - y = cuddNextHigh(table,y); - } - table->subtables[y].next = xtop; /* y is bottom of its group, join */ - /* it to top of its group */ - x = cuddNextHigh(table,y); - newxtop = x; - for (i = 0; i < xsize - 1; i++) { - table->subtables[x].next = cuddNextHigh(table,x); - x = cuddNextHigh(table,x); - } - table->subtables[x].next = newxtop; /* x is bottom of its group, join */ - /* it to top of its group */ -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n"); -#endif - - /* Store group move */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddGroupMoveOutOfMem; - move->x = swapx; - move->y = swapy; - move->flags = MTR_DEFAULT; - move->size = table->keys - table->isolated; - move->next = *moves; - *moves = move; - - return(table->keys - table->isolated); - -ddGroupMoveOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - return(0); - -} /* end of ddGroupMove */ - - -/**Function******************************************************************** - - Synopsis [Undoes the swap two groups.] - - Description [Undoes the swap two groups. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupMoveBackward( - DdManager * table, - int x, - int y) -{ - int size; - int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - - -#if DD_DEBUG - /* We assume that x < y */ - assert(x < y); -#endif - - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtables[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtables[ybot].next) - ybot = table->subtables[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - - /* Sift the variables of the second group up through the first group */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddSwapInPlace(table,x,y); - if (size == 0) - return(0); - y = x; - x = cuddNextLow(table,y); - } - y = ytop + i; - x = cuddNextLow(table,y); - } - - /* fix groups */ - y = xtop; - for (i = 0; i < ysize - 1; i++) { - table->subtables[y].next = cuddNextHigh(table,y); - y = cuddNextHigh(table,y); - } - table->subtables[y].next = xtop; /* y is bottom of its group, join */ - /* to its top */ - x = cuddNextHigh(table,y); - newxtop = x; - for (i = 0; i < xsize - 1; i++) { - table->subtables[x].next = cuddNextHigh(table,x); - x = cuddNextHigh(table,x); - } - table->subtables[x].next = newxtop; /* x is bottom of its group, join */ - /* to its top */ -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n"); -#endif - - return(1); - -} /* end of ddGroupMoveBackward */ - - -/**Function******************************************************************** - - Synopsis [Determines the best position for a variables and returns - it there.] - - Description [Determines the best position for a variables and returns - it there. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupSiftingBackward( - DdManager * table, - Move * moves, - int size, - int upFlag, - int lazyFlag) -{ - Move *move; - int res; - Move *end_move; - int diff, tmp_diff; - int index, pairlev; - - if (lazyFlag) { - end_move = NULL; - - /* Find the minimum size, and the earliest position at which it - ** was achieved. */ - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - end_move = move; - } else if (move->size == size) { - if (end_move == NULL) end_move = move; - } - } - - /* Find among the moves that give minimum size the one that - ** minimizes the distance from the corresponding variable. */ - if (moves != NULL) { - diff = Cudd_ReadSize(table) + 1; - index = (upFlag == 1) ? - table->invperm[moves->x] : table->invperm[moves->y]; - pairlev = table->perm[Cudd_bddReadPairIndex(table, index)]; - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) { - if (upFlag == 1) { - tmp_diff = (move->x > pairlev) ? - move->x - pairlev : pairlev - move->x; - } else { - tmp_diff = (move->y > pairlev) ? - move->y - pairlev : pairlev - move->y; - } - if (tmp_diff < diff) { - diff = tmp_diff; - end_move = move; - } - } - } - } - } else { - /* Find the minimum size. */ - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - } - - /* In case of lazy sifting, end_move identifies the position at - ** which we want to stop. Otherwise, we stop as soon as we meet - ** the minimum size. */ - for (move = moves; move != NULL; move = move->next) { - if (lazyFlag) { - if (move == end_move) return(1); - } else { - if (move->size == size) return(1); - } - if ((table->subtables[move->x].next == move->x) && - (table->subtables[move->y].next == move->y)) { - res = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n"); - assert(table->subtables[move->x].next == move->x); - assert(table->subtables[move->y].next == move->y); -#endif - } else { /* Group move necessary */ - if (move->flags == MTR_NEWNODE) { - ddDissolveGroup(table,(int)move->x,(int)move->y); - } else { - res = ddGroupMoveBackward(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - } - - } - - return(1); - -} /* end of ddGroupSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Merges groups in the DD table.] - - Description [Creates a single group from low to high and adjusts the - index field of the tree node.] - - SideEffects [None] - -******************************************************************************/ -static void -ddMergeGroups( - DdManager * table, - MtrNode * treenode, - int low, - int high) -{ - int i; - MtrNode *auxnode; - int saveindex; - int newindex; - - /* Merge all variables from low to high in one group, unless - ** this is the topmost group. In such a case we do not merge lest - ** we lose the symmetry information. */ - if (treenode != table->tree) { - for (i = low; i < high; i++) - table->subtables[i].next = i+1; - table->subtables[high].next = low; - } - - /* Adjust the index fields of the tree nodes. If a node is the - ** first child of its parent, then the parent may also need adjustment. */ - saveindex = treenode->index; - newindex = table->invperm[low]; - auxnode = treenode; - do { - auxnode->index = newindex; - if (auxnode->parent == NULL || - (int) auxnode->parent->index != saveindex) - break; - auxnode = auxnode->parent; - } while (1); - return; - -} /* end of ddMergeGroups */ - - -/**Function******************************************************************** - - Synopsis [Dissolves a group in the DD table.] - - Description [x and y are variables in a group to be cut in two. The cut - is to pass between x and y.] - - SideEffects [None] - -******************************************************************************/ -static void -ddDissolveGroup( - DdManager * table, - int x, - int y) -{ - int topx; - int boty; - - /* find top and bottom of the two groups */ - boty = y; - while ((unsigned) boty < table->subtables[boty].next) - boty = table->subtables[boty].next; - - topx = table->subtables[boty].next; - - table->subtables[boty].next = y; - table->subtables[x].next = topx; - - return; - -} /* end of ddDissolveGroup */ - - -/**Function******************************************************************** - - Synopsis [Pretends to check two variables for aggregation.] - - Description [Pretends to check two variables for aggregation. Always - returns 0.] - - SideEffects [None] - -******************************************************************************/ -static int -ddNoCheck( - DdManager * table, - int x, - int y) -{ - return(0); - -} /* end of ddNoCheck */ - - -/**Function******************************************************************** - - Synopsis [Checks two variables for aggregation.] - - Description [Checks two variables for aggregation. The check is based - on the second difference of the number of nodes as a function of the - layer. If the second difference is lower than a given threshold - (typically negative) then the two variables should be aggregated. - Returns 1 if the two variables pass the test; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSecDiffCheck( - DdManager * table, - int x, - int y) -{ - double Nx,Nx_1; - double Sx; - double threshold; - int xindex,yindex; - - if (x==0) return(0); - -#ifdef DD_STATS - secdiffcalls++; -#endif - Nx = (double) table->subtables[x].keys; - Nx_1 = (double) table->subtables[x-1].keys; - Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1); - - threshold = table->recomb / 100.0; - if (Sx < threshold) { - xindex = table->invperm[x]; - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - (void) fprintf(table->out, - "Second difference for %d = %g Pos(%d)\n", - table->invperm[x],Sx,x); -#endif -#ifdef DD_STATS - secdiff++; -#endif - return(1); - } else { -#ifdef DD_STATS - secdiffmisfire++; -#endif - return(0); - } - - } - return(0); - -} /* end of ddSecDiffCheck */ - - -/**Function******************************************************************** - - Synopsis [Checks for extended symmetry of x and y.] - - Description [Checks for extended symmetry of x and y. Returns 1 in - case of extended symmetry; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddExtSymmCheck( - DdManager * table, - int x, - int y) -{ - DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; - DdNode *one; - int comple; /* f0 is complemented */ - int notproj; /* f is not a projection function */ - int arccount; /* number of arcs from layer x to layer y */ - int TotalRefCount; /* total reference count of layer y minus 1 */ - int counter; /* number of nodes of layer x that are allowed */ - /* to violate extended symmetry conditions */ - int arccounter; /* number of arcs into layer y that are allowed */ - /* to come from layers other than x */ - int i; - int xindex; - int yindex; - int res; - int slots; - DdNodePtr *list; - DdNode *sentinel = &(table->sentinel); - - xindex = table->invperm[x]; - yindex = table->invperm[y]; - - /* If the two variables do not interact, we do not want to merge them. */ - if (!cuddTestInteract(table,xindex,yindex)) - return(0); - -#ifdef DD_DEBUG - /* Checks that x and y do not contain just the projection functions. - ** With the test on interaction, these test become redundant, - ** because an isolated projection function does not interact with - ** any other variable. - */ - if (table->subtables[x].keys == 1) { - assert(table->vars[xindex]->ref != 1); - } - if (table->subtables[y].keys == 1) { - assert(table->vars[yindex]->ref != 1); - } -#endif - -#ifdef DD_STATS - extsymmcalls++; -#endif - - arccount = 0; - counter = (int) (table->subtables[x].keys * - (table->symmviolation/100.0) + 0.5); - one = DD_ONE(table); - - slots = table->subtables[x].slots; - list = table->subtables[x].nodelist; - for (i = 0; i < slots; i++) { - f = list[i]; - while (f != sentinel) { - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); - f0 = Cudd_Regular(cuddE(f)); - comple = Cudd_IsComplement(cuddE(f)); - notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1; - if (f1->index == yindex) { - arccount++; - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - if ((int) f0->index != yindex) { - /* If f is an isolated projection function it is - ** allowed to bypass layer y. - */ - if (notproj) { - if (counter == 0) - return(0); - counter--; /* f bypasses layer y */ - } - } - f11 = f10 = f1; - } - if ((int) f0->index == yindex) { - arccount++; - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = f00 = f0; - } - if (comple) { - f01 = Cudd_Not(f01); - f00 = Cudd_Not(f00); - } - - /* Unless we are looking at a projection function - ** without external references except the one from the - ** table, we insist that f01 == f10 or f11 == f00 - */ - if (notproj) { - if (f01 != f10 && f11 != f00) { - if (counter == 0) - return(0); - counter--; - } - } - - f = f->next; - } /* while */ - } /* for */ - - /* Calculate the total reference counts of y */ - TotalRefCount = -1; /* -1 for projection function */ - slots = table->subtables[y].slots; - list = table->subtables[y].nodelist; - for (i = 0; i < slots; i++) { - f = list[i]; - while (f != sentinel) { - TotalRefCount += f->ref; - f = f->next; - } - } - - arccounter = (int) (table->subtables[y].keys * - (table->arcviolation/100.0) + 0.5); - res = arccount >= TotalRefCount - arccounter; - -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (res) { - (void) fprintf(table->out, - "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n", - xindex,yindex,x,y); - } -#endif - -#ifdef DD_STATS - if (res) - extsymm++; -#endif - return(res); - -} /* end ddExtSymmCheck */ - - -/**Function******************************************************************** - - Synopsis [Checks for grouping of x and y.] - - Description [Checks for grouping of x and y. Returns 1 in - case of grouping; 0 otherwise. This function is used for lazy sifting.] - - SideEffects [None] - -******************************************************************************/ -static int -ddVarGroupCheck( - DdManager * table, - int x, - int y) -{ - int xindex = table->invperm[x]; - int yindex = table->invperm[y]; - - if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0); - - if (Cudd_bddReadPairIndex(table, xindex) == yindex) { - if (ddIsVarHandled(table, xindex) || - ddIsVarHandled(table, yindex)) { - if (Cudd_bddIsVarToBeGrouped(table, xindex) || - Cudd_bddIsVarToBeGrouped(table, yindex) ) { - if (table->keys - table->isolated <= originalSize) { - return(1); - } - } - } - } - - return(0); - -} /* end of ddVarGroupCheck */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable to already handled.] - - Description [Sets a variable to already handled. This function is used - for lazy sifting.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static int -ddSetVarHandled( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].varHandled = 1; - return(1); - -} /* end of ddSetVarHandled */ - - -/**Function******************************************************************** - - Synopsis [Resets a variable to be processed.] - - Description [Resets a variable to be processed. This function is used - for lazy sifting.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static int -ddResetVarHandled( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].varHandled = 0; - return(1); - -} /* end of ddResetVarHandled */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variables is already handled.] - - Description [Checks whether a variables is already handled. This - function is used for lazy sifting.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static int -ddIsVarHandled( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(-1); - return dd->subtables[dd->perm[index]].varHandled; - -} /* end of ddIsVarHandled */ diff --git a/src/bdd/cudd/cuddHarwell.c b/src/bdd/cudd/cuddHarwell.c deleted file mode 100644 index 063f1922..00000000 --- a/src/bdd/cudd/cuddHarwell.c +++ /dev/null @@ -1,541 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddHarwell.c] - - PackageName [cudd] - - Synopsis [Function to read a matrix in Harwell format.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addHarwell() - </ul> - ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddHarwell.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Reads in a matrix in the format of the Harwell-Boeing - benchmark suite.] - - Description [Reads in a matrix in the format of the Harwell-Boeing - benchmark suite. The variables are ordered as follows: - <blockquote> - x\[0\] y\[0\] x\[1\] y\[1\] ... - </blockquote> - 0 is the most significant bit. On input, nx and ny hold the numbers - of row and column variables already in existence. On output, they - hold the numbers of row and column variables actually used by the - matrix. m and n are set to the numbers of rows and columns of the - matrix. Their values on input are immaterial. Returns 1 on - success; 0 otherwise. The ADD for the sparse matrix is returned in - E, and its reference count is > 0.] - - SideEffects [None] - - SeeAlso [Cudd_addRead Cudd_bddRead] - -******************************************************************************/ -int -Cudd_addHarwell( - FILE * fp /* pointer to the input file */, - DdManager * dd /* DD manager */, - DdNode ** E /* characteristic function of the graph */, - DdNode *** x /* array of row variables */, - DdNode *** y /* array of column variables */, - DdNode *** xn /* array of complemented row variables */, - DdNode *** yn_ /* array of complemented column variables */, - int * nx /* number or row variables */, - int * ny /* number or column variables */, - int * m /* number of rows */, - int * n /* number of columns */, - int bx /* first index of row variables */, - int sx /* step of row variables */, - int by /* first index of column variables */, - int sy /* step of column variables */, - int pr /* verbosity level */) -{ - DdNode *one, *zero; - DdNode *w; - DdNode *cubex, *cubey, *minterm1; - int u, v, err, i, j, nv; - double val; - DdNode **lx, **ly, **lxn, **lyn; /* local copies of x, y, xn, yn_ */ - int lnx, lny; /* local copies of nx and ny */ - char title[73], key[9], mxtype[4], rhstyp[4]; - int totcrd, ptrcrd, indcrd, valcrd, rhscrd, - nrow, ncol, nnzero, neltvl, - nrhs, nrhsix; - int *colptr, *rowind; -#if 0 - int nguess, nexact; - int *rhsptr, *rhsind; -#endif - - if (*nx < 0 || *ny < 0) return(0); - - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - /* Read the header */ - err = fscanf(fp, "%72c %8c", title, key); - if (err == EOF) { - return(0); - } else if (err != 2) { - return(0); - } - title[72] = (char) 0; - key[8] = (char) 0; - - err = fscanf(fp, "%d %d %d %d %d", &totcrd, &ptrcrd, &indcrd, - &valcrd, &rhscrd); - if (err == EOF) { - return(0); - } else if (err != 5) { - return(0); - } - - err = fscanf(fp, "%3s %d %d %d %d", mxtype, &nrow, &ncol, - &nnzero, &neltvl); - if (err == EOF) { - return(0); - } else if (err != 5) { - return(0); - } - - /* Skip FORTRAN formats */ - if (rhscrd == 0) { - err = fscanf(fp, "%*s %*s %*s \n"); - } else { - err = fscanf(fp, "%*s %*s %*s %*s \n"); - } - if (err == EOF) { - return(0); - } else if (err != 0) { - return(0); - } - - /* Print out some stuff if requested to be verbose */ - if (pr>0) { - (void) fprintf(dd->out,"%s: type %s, %d rows, %d columns, %d entries\n", key, - mxtype, nrow, ncol, nnzero); - if (pr>1) (void) fprintf(dd->out,"%s\n", title); - } - - /* Check matrix type */ - if (mxtype[0] != 'R' || mxtype[1] != 'U' || mxtype[2] != 'A') { - (void) fprintf(dd->err,"%s: Illegal matrix type: %s\n", - key, mxtype); - return(0); - } - if (neltvl != 0) return(0); - - /* Read optional 5-th line */ - if (rhscrd != 0) { - err = fscanf(fp, "%3c %d %d", rhstyp, &nrhs, &nrhsix); - if (err == EOF) { - return(0); - } else if (err != 3) { - return(0); - } - rhstyp[3] = (char) 0; - if (rhstyp[0] != 'F') { - (void) fprintf(dd->err, - "%s: Sparse right-hand side not yet supported\n", key); - return(0); - } - if (pr>0) (void) fprintf(dd->out,"%d right-hand side(s)\n", nrhs); - } else { - nrhs = 0; - } - - /* Compute the number of variables */ - - /* row and column numbers start from 0 */ - u = nrow - 1; - for (i=0; u > 0; i++) { - u >>= 1; - } - lnx = i; - if (nrhs == 0) { - v = ncol - 1; - } else { - v = 2* (ddMax(ncol, nrhs) - 1); - } - for (i=0; v > 0; i++) { - v >>= 1; - } - lny = i; - - /* Allocate or reallocate arrays for variables as needed */ - if (*nx == 0) { - if (lnx > 0) { - *x = lx = ALLOC(DdNode *,lnx); - if (lx == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *xn = lxn = ALLOC(DdNode *,lnx); - if (lxn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } else { - *x = *xn = NULL; - } - } else if (lnx > *nx) { - *x = lx = REALLOC(DdNode *, *x, lnx); - if (lx == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *xn = lxn = REALLOC(DdNode *, *xn, lnx); - if (lxn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } else { - lx = *x; - lxn = *xn; - } - if (*ny == 0) { - if (lny >0) { - *y = ly = ALLOC(DdNode *,lny); - if (ly == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *yn_ = lyn = ALLOC(DdNode *,lny); - if (lyn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } else { - *y = *yn_ = NULL; - } - } else if (lny > *ny) { - *y = ly = REALLOC(DdNode *, *y, lny); - if (ly == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *yn_ = lyn = REALLOC(DdNode *, *yn_, lny); - if (lyn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } else { - ly = *y; - lyn = *yn_; - } - - /* Create new variables as needed */ - for (i= *nx,nv=bx+(*nx)*sx; i < lnx; i++,nv+=sx) { - do { - dd->reordered = 0; - lx[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (lx[i] == NULL) return(0); - cuddRef(lx[i]); - do { - dd->reordered = 0; - lxn[i] = cuddUniqueInter(dd, nv, zero, one); - } while (dd->reordered == 1); - if (lxn[i] == NULL) return(0); - cuddRef(lxn[i]); - } - for (i= *ny,nv=by+(*ny)*sy; i < lny; i++,nv+=sy) { - do { - dd->reordered = 0; - ly[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (ly[i] == NULL) return(0); - cuddRef(ly[i]); - do { - dd->reordered = 0; - lyn[i] = cuddUniqueInter(dd, nv, zero, one); - } while (dd->reordered == 1); - if (lyn[i] == NULL) return(0); - cuddRef(lyn[i]); - } - - /* Update matrix parameters */ - *nx = lnx; - *ny = lny; - *m = nrow; - if (nrhs == 0) { - *n = ncol; - } else { - *n = (1 << (lny - 1)) + nrhs; - } - - /* Read structure data */ - colptr = ALLOC(int, ncol+1); - if (colptr == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - rowind = ALLOC(int, nnzero); - if (rowind == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - - for (i=0; i<ncol+1; i++) { - err = fscanf(fp, " %d ", &u); - if (err == EOF){ - FREE(colptr); - FREE(rowind); - return(0); - } else if (err != 1) { - FREE(colptr); - FREE(rowind); - return(0); - } - colptr[i] = u - 1; - } - if (colptr[0] != 0) { - (void) fprintf(dd->err,"%s: Unexpected colptr[0] (%d)\n", - key,colptr[0]); - FREE(colptr); - FREE(rowind); - return(0); - } - for (i=0; i<nnzero; i++) { - err = fscanf(fp, " %d ", &u); - if (err == EOF){ - FREE(colptr); - FREE(rowind); - return(0); - } else if (err != 1) { - FREE(colptr); - FREE(rowind); - return(0); - } - rowind[i] = u - 1; - } - - *E = zero; cuddRef(*E); - - for (j=0; j<ncol; j++) { - v = j; - cubey = one; cuddRef(cubey); - for (nv = lny - 1; nv>=0; nv--) { - if (v & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - FREE(colptr); - FREE(rowind); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, cubey); - cubey = w; - v >>= 1; - } - for (i=colptr[j]; i<colptr[j+1]; i++) { - u = rowind[i]; - err = fscanf(fp, " %lf ", &val); - if (err == EOF || err != 1){ - Cudd_RecursiveDeref(dd, cubey); - FREE(colptr); - FREE(rowind); - return(0); - } - /* Create new Constant node if necessary */ - cubex = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) val); - if (cubex == NULL) { - Cudd_RecursiveDeref(dd, cubey); - FREE(colptr); - FREE(rowind); - return(0); - } - cuddRef(cubex); - - for (nv = lnx - 1; nv>=0; nv--) { - if (u & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - Cudd_RecursiveDeref(dd, cubex); - FREE(colptr); - FREE(rowind); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, cubex); - cubex = w; - u >>= 1; - } - minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex); - if (minterm1 == NULL) { - Cudd_RecursiveDeref(dd, cubey); - Cudd_RecursiveDeref(dd, cubex); - FREE(colptr); - FREE(rowind); - return(0); - } - cuddRef(minterm1); - Cudd_RecursiveDeref(dd, cubex); - w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1); - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - FREE(colptr); - FREE(rowind); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - Cudd_RecursiveDeref(dd, *E); - *E = w; - } - Cudd_RecursiveDeref(dd, cubey); - } - FREE(colptr); - FREE(rowind); - - /* Read right-hand sides */ - for (j=0; j<nrhs; j++) { - v = j + (1<< (lny-1)); - cubey = one; cuddRef(cubey); - for (nv = lny - 1; nv>=0; nv--) { - if (v & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, cubey); - cubey = w; - v >>= 1; - } - for (i=0; i<nrow; i++) { - u = i; - err = fscanf(fp, " %lf ", &val); - if (err == EOF || err != 1){ - Cudd_RecursiveDeref(dd, cubey); - return(0); - } - /* Create new Constant node if necessary */ - if (val == (double) 0.0) continue; - cubex = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) val); - if (cubex == NULL) { - Cudd_RecursiveDeref(dd, cubey); - return(0); - } - cuddRef(cubex); - - for (nv = lnx - 1; nv>=0; nv--) { - if (u & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - Cudd_RecursiveDeref(dd, cubex); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, cubex); - cubex = w; - u >>= 1; - } - minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex); - if (minterm1 == NULL) { - Cudd_RecursiveDeref(dd, cubey); - Cudd_RecursiveDeref(dd, cubex); - return(0); - } - cuddRef(minterm1); - Cudd_RecursiveDeref(dd, cubex); - w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1); - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - Cudd_RecursiveDeref(dd, *E); - *E = w; - } - Cudd_RecursiveDeref(dd, cubey); - } - - return(1); - -} /* end of Cudd_addHarwell */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddInit.c b/src/bdd/cudd/cuddInit.c deleted file mode 100644 index 8e06a425..00000000 --- a/src/bdd/cudd/cuddInit.c +++ /dev/null @@ -1,283 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddInit.c] - - PackageName [cudd] - - Synopsis [Functions to initialize and shut down the DD manager.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_Init() - <li> Cudd_Quit() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddZddInitUniv() - <li> cuddZddFreeUniv() - </ul> - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#define CUDD_MAIN -#include "cuddInt.h" -#undef CUDD_MAIN - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddInit.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Creates a new DD manager.] - - Description [Creates a new DD manager, initializes the table, the - basic constants and the projection functions. If maxMemory is 0, - Cudd_Init decides suitable values for the maximum size of the cache - and for the limit for fast unique table growth based on the available - memory. Returns a pointer to the manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Quit] - -******************************************************************************/ -DdManager * -Cudd_Init( - unsigned int numVars /* initial number of BDD variables (i.e., subtables) */, - unsigned int numVarsZ /* initial number of ZDD variables (i.e., subtables) */, - unsigned int numSlots /* initial size of the unique tables */, - unsigned int cacheSize /* initial size of the cache */, - unsigned long maxMemory /* target maximum memory occupation */) -{ - DdManager *unique; - int i,result; - DdNode *one, *zero; - unsigned int maxCacheSize; - unsigned int looseUpTo; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - if (maxMemory == 0) { - maxMemory = getSoftDataLimit(); - } - looseUpTo = (unsigned int) ((maxMemory / sizeof(DdNode)) / - DD_MAX_LOOSE_FRACTION); - unique = cuddInitTable(numVars,numVarsZ,numSlots,looseUpTo); - unique->maxmem = (unsigned) maxMemory / 10 * 9; - if (unique == NULL) return(NULL); - maxCacheSize = (unsigned int) ((maxMemory / sizeof(DdCache)) / - DD_MAX_CACHE_FRACTION); - result = cuddInitCache(unique,cacheSize,maxCacheSize); - if (result == 0) return(NULL); - - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - unique->stash = ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4); - MMoutOfMemory = saveHandler; - if (unique->stash == NULL) { - (void) fprintf(unique->err,"Unable to set aside memory\n"); - } - - /* Initialize constants. */ - unique->one = cuddUniqueConst(unique,1.0); - if (unique->one == NULL) return(0); - cuddRef(unique->one); - unique->zero = cuddUniqueConst(unique,0.0); - if (unique->zero == NULL) return(0); - cuddRef(unique->zero); -#ifdef HAVE_IEEE_754 - if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 || - DD_PLUS_INF_VAL != DD_PLUS_INF_VAL / 3) { - (void) fprintf(unique->err,"Warning: Crippled infinite values\n"); - (void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n"); - } -#endif - unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL); - if (unique->plusinfinity == NULL) return(0); - cuddRef(unique->plusinfinity); - unique->minusinfinity = cuddUniqueConst(unique,DD_MINUS_INF_VAL); - if (unique->minusinfinity == NULL) return(0); - cuddRef(unique->minusinfinity); - unique->background = unique->zero; - - /* The logical zero is different from the CUDD_VALUE_TYPE zero! */ - one = unique->one; - zero = Cudd_Not(one); - /* Create the projection functions. */ - unique->vars = ALLOC(DdNodePtr,unique->maxSize); - if (unique->vars == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < unique->size; i++) { - unique->vars[i] = cuddUniqueInter(unique,i,one,zero); - if (unique->vars[i] == NULL) return(0); - cuddRef(unique->vars[i]); - } - - if (unique->sizeZ) - cuddZddInitUniv(unique); - - unique->memused += sizeof(DdNode *) * unique->maxSize; - - return(unique); - -} /* end of Cudd_Init */ - - -/**Function******************************************************************** - - Synopsis [Deletes resources associated with a DD manager.] - - Description [Deletes resources associated with a DD manager and - resets the global statistical counters. (Otherwise, another manaqger - subsequently created would inherit the stats of this one.)] - - SideEffects [None] - - SeeAlso [Cudd_Init] - -******************************************************************************/ -void -Cudd_Quit( - DdManager * unique) -{ - if (unique->stash != NULL) FREE(unique->stash); - cuddFreeTable(unique); - -} /* end of Cudd_Quit */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Initializes the ZDD universe.] - - Description [Initializes the ZDD universe. Returns 1 if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddZddFreeUniv] - -******************************************************************************/ -int -cuddZddInitUniv( - DdManager * zdd) -{ - DdNode *p, *res; - int i; - - zdd->univ = ALLOC(DdNodePtr, zdd->sizeZ); - if (zdd->univ == NULL) { - zdd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - - res = DD_ONE(zdd); - cuddRef(res); - for (i = zdd->sizeZ - 1; i >= 0; i--) { - unsigned int index = zdd->invpermZ[i]; - p = res; - res = cuddUniqueInterZdd(zdd, index, p, p); - if (res == NULL) { - Cudd_RecursiveDerefZdd(zdd,p); - FREE(zdd->univ); - return(0); - } - cuddRef(res); - cuddDeref(p); - zdd->univ[i] = res; - } - -#ifdef DD_VERBOSE - cuddZddP(zdd, zdd->univ[0]); -#endif - - return(1); - -} /* end of cuddZddInitUniv */ - - -/**Function******************************************************************** - - Synopsis [Frees the ZDD universe.] - - Description [Frees the ZDD universe.] - - SideEffects [None] - - SeeAlso [cuddZddInitUniv] - -******************************************************************************/ -void -cuddZddFreeUniv( - DdManager * zdd) -{ - if (zdd->univ) { - Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]); - FREE(zdd->univ); - } - -} /* end of cuddZddFreeUniv */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddInt.h b/src/bdd/cudd/cuddInt.h deleted file mode 100644 index a5d0cf16..00000000 --- a/src/bdd/cudd/cuddInt.h +++ /dev/null @@ -1,1133 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [cuddInt.h] - - PackageName [cudd] - - Synopsis [Internal data structures of the CUDD package.] - - Description [] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: cuddInt.h,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $] - -******************************************************************************/ - -#ifndef _CUDDINT -#define _CUDDINT - - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - -#ifdef DD_MIS -#include "array.h" -#include "list.h" -#include "st.h" -#include "espresso.h" -#include "node.h" -#ifdef SIS -#include "graph.h" -#include "astg.h" -#endif -#include "network.h" -#endif - -#include <math.h> -#include "cudd.h" -#include "st.h" - -#if defined(__GNUC__) -# define DD_INLINE __inline__ -# if (__GNUC__ >2 || __GNUC_MINOR__ >=7) -# define DD_UNUSED __attribute__ ((__unused__)) -# else -# define DD_UNUSED -# endif -#else -# if defined(__cplusplus) -# define DD_INLINE inline -# else -# define DD_INLINE -# endif -# define DD_UNUSED -#endif - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_MAXREF ((DdHalfWord) ~0) - -#define DD_DEFAULT_RESIZE 10 /* how many extra variables */ - /* should be added when resizing */ -#define DD_MEM_CHUNK 1022 - -/* These definitions work for CUDD_VALUE_TYPE == double */ -#define DD_ONE_VAL (1.0) -#define DD_ZERO_VAL (0.0) -#define DD_EPSILON (1.0e-12) - -/* The definitions of +/- infinity in terms of HUGE_VAL work on -** the DECstations and on many other combinations of OS/compiler. -*/ -#ifdef HAVE_IEEE_754 -# define DD_PLUS_INF_VAL (HUGE_VAL) -#else -# define DD_PLUS_INF_VAL (10e301) -# define DD_CRI_HI_MARK (10e150) -# define DD_CRI_LO_MARK (-(DD_CRI_HI_MARK)) -#endif -#define DD_MINUS_INF_VAL (-(DD_PLUS_INF_VAL)) - -#define DD_NON_CONSTANT ((DdNode *) 1) /* for Cudd_bddIteConstant */ - -/* Unique table and cache management constants. */ -#define DD_MAX_SUBTABLE_DENSITY 4 /* tells when to resize a subtable */ -/* gc when this percent are dead (measured w.r.t. slots, not keys) -** The first limit (LO) applies normally. The second limit applies when -** the package believes more space for the unique table (i.e., more dead -** nodes) would improve performance, and the unique table is not already -** too large. The third limit applies when memory is low. -*/ -#define DD_GC_FRAC_LO DD_MAX_SUBTABLE_DENSITY * 0.25 -#define DD_GC_FRAC_HI DD_MAX_SUBTABLE_DENSITY * 1.0 -#define DD_GC_FRAC_MIN 0.2 -#define DD_MIN_HIT 30 /* resize cache when hit ratio - above this percentage (default) */ -#define DD_MAX_LOOSE_FRACTION 5 /* 1 / (max fraction of memory used for - unique table in fast growth mode) */ -#define DD_MAX_CACHE_FRACTION 3 /* 1 / (max fraction of memory used for - computed table if resizing enabled) */ -#define DD_STASH_FRACTION 64 /* 1 / (fraction of memory set - aside for emergencies) */ -#define DD_MAX_CACHE_TO_SLOTS_RATIO 4 /* used to limit the cache size */ - -/* Variable ordering default parameter values. */ -#define DD_SIFT_MAX_VAR 1000 -#define DD_SIFT_MAX_SWAPS 2000000 -#define DD_DEFAULT_RECOMB 0 -#define DD_MAX_REORDER_GROWTH 1.2 -#define DD_FIRST_REORDER 4004 /* 4 for the constants */ -#define DD_DYN_RATIO 2 /* when to dynamically reorder */ - -/* Primes for cache hash functions. */ -#define DD_P1 12582917 -#define DD_P2 4256249 -#define DD_P3 741457 -#define DD_P4 1618033999 - -/* Cache tags for 3-operand operators. These tags are stored in the -** least significant bits of the cache operand pointers according to -** the following scheme. The tag consists of two hex digits. Both digits -** must be even, so that they do not interfere with complementation bits. -** The least significant one is stored in Bits 3:1 of the f operand in the -** cache entry. Bit 1 is always 1, so that we can differentiate -** three-operand operations from one- and two-operand operations. -** Therefore, the least significant digit is one of {2,6,a,e}. The most -** significant digit occupies Bits 3:1 of the g operand in the cache -** entry. It can by any even digit between 0 and e. This gives a total -** of 5 bits for the tag proper, which means a maximum of 32 three-operand -** operations. */ -#define DD_ADD_ITE_TAG 0x02 -#define DD_BDD_AND_ABSTRACT_TAG 0x06 -#define DD_BDD_XOR_EXIST_ABSTRACT_TAG 0x0a -#define DD_BDD_ITE_TAG 0x0e -#define DD_ADD_BDD_DO_INTERVAL_TAG 0x22 -#define DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG 0x26 -#define DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG 0x2a -#define DD_BDD_COMPOSE_RECUR_TAG 0x2e -#define DD_ADD_COMPOSE_RECUR_TAG 0x42 -#define DD_ADD_NON_SIM_COMPOSE_TAG 0x46 -#define DD_EQUIV_DC_TAG 0x4a -#define DD_ZDD_ITE_TAG 0x4e -#define DD_ADD_ITE_CONSTANT_TAG 0x62 -#define DD_ADD_EVAL_CONST_TAG 0x66 -#define DD_BDD_ITE_CONSTANT_TAG 0x6a -#define DD_ADD_OUT_SUM_TAG 0x6e -#define DD_BDD_LEQ_UNLESS_TAG 0x82 -#define DD_ADD_TRIANGLE_TAG 0x86 - -/* Generator constants. */ -#define CUDD_GEN_CUBES 0 -#define CUDD_GEN_NODES 1 -#define CUDD_GEN_ZDD_PATHS 2 -#define CUDD_GEN_EMPTY 0 -#define CUDD_GEN_NONEMPTY 1 - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -struct DdGen { - DdManager *manager; - int type; - int status; - union { - struct { - int *cube; - CUDD_VALUE_TYPE value; - } cubes; - struct { - st_table *visited; - st_generator *stGen; - } nodes; - } gen; - struct { - int sp; - DdNode **stack; - } stack; - DdNode *node; -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/* Hooks in CUDD are functions that the application registers with the -** manager so that they are called at appropriate times. The functions -** are passed the manager as argument; they should return 1 if -** successful and 0 otherwise. -*/ -typedef struct DdHook { /* hook list element */ - int (*f) ARGS((DdManager *, char *, void *)); /* function to be called */ - struct DdHook *next; /* next element in the list */ -} DdHook; - -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -typedef long ptrint; -typedef unsigned long ptruint; -#else -typedef int ptrint; -typedef unsigned int ptruint; -#endif - -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - -typedef DdNode *DdNodePtr; - -/* Generic local cache item. */ -typedef struct DdLocalCacheItem { - DdNode *value; -#ifdef DD_CACHE_PROFILE - ptrint count; -#endif - DdNode *key[1]; -} DdLocalCacheItem; - -/* Local cache. */ -typedef struct DdLocalCache { - DdLocalCacheItem *item; - unsigned int itemsize; - unsigned int keysize; - unsigned int slots; - int shift; - double lookUps; - double minHit; - double hits; - unsigned int maxslots; - DdManager *manager; - struct DdLocalCache *next; -} DdLocalCache; - -/* Generic hash item. */ -typedef struct DdHashItem { - struct DdHashItem *next; - ptrint count; - DdNode *value; - DdNode *key[1]; -} DdHashItem; - -/* Local hash table */ -typedef struct DdHashTable { - unsigned int keysize; - unsigned int itemsize; - DdHashItem **bucket; - DdHashItem *nextFree; - DdHashItem **memoryList; - unsigned int numBuckets; - int shift; - unsigned int size; - unsigned int maxsize; - DdManager *manager; -} DdHashTable; - -typedef struct DdCache { - DdNode *f,*g; /* DDs */ - ptruint h; /* either operator or DD */ - DdNode *data; /* already constructed DD */ -#ifdef DD_CACHE_PROFILE - ptrint count; -#endif -} DdCache; - -typedef struct DdSubtable { /* subtable for one index */ - DdNode **nodelist; /* hash table */ - int shift; /* shift for hash function */ - unsigned int slots; /* size of the hash table */ - unsigned int keys; /* number of nodes stored in this table */ - unsigned int maxKeys; /* slots * DD_MAX_SUBTABLE_DENSITY */ - unsigned int dead; /* number of dead nodes in this table */ - unsigned int next; /* index of next variable in group */ - int bindVar; /* flag to bind this variable to its level */ - /* Fields for lazy sifting. */ - Cudd_VariableType varType; /* variable type (ps, ns, pi) */ - int pairIndex; /* corresponding variable index (ps <-> ns) */ - int varHandled; /* flag: 1 means variable is already handled */ - Cudd_LazyGroupType varToBeGrouped; /* tells what grouping to apply */ -} DdSubtable; - -struct DdManager { /* specialized DD symbol table */ - /* Constants */ - DdNode sentinel; /* for collision lists */ - DdNode *one; /* constant 1 */ - DdNode *zero; /* constant 0 */ - DdNode *plusinfinity; /* plus infinity */ - DdNode *minusinfinity; /* minus infinity */ - DdNode *background; /* background value */ - /* Computed Table */ - DdCache *acache; /* address of allocated memory for cache */ - DdCache *cache; /* the cache-based computed table */ - unsigned int cacheSlots; /* total number of cache entries */ - int cacheShift; /* shift value for cache hash function */ - double cacheMisses; /* number of cache misses (since resizing) */ - double cacheHits; /* number of cache hits (since resizing) */ - double minHit; /* hit percentage above which to resize */ - int cacheSlack; /* slots still available for resizing */ - unsigned int maxCacheHard; /* hard limit for cache size */ - /* Unique Table */ - int size; /* number of unique subtables */ - int sizeZ; /* for ZDD */ - int maxSize; /* max number of subtables before resizing */ - int maxSizeZ; /* for ZDD */ - DdSubtable *subtables; /* array of unique subtables */ - DdSubtable *subtableZ; /* for ZDD */ - DdSubtable constants; /* unique subtable for the constants */ - unsigned int slots; /* total number of hash buckets */ - unsigned int keys; /* total number of BDD and ADD nodes */ - unsigned int keysZ; /* total number of ZDD nodes */ - unsigned int dead; /* total number of dead BDD and ADD nodes */ - unsigned int deadZ; /* total number of dead ZDD nodes */ - unsigned int maxLive; /* maximum number of live nodes */ - unsigned int minDead; /* do not GC if fewer than these dead */ - double gcFrac; /* gc when this fraction is dead */ - int gcEnabled; /* gc is enabled */ - unsigned int looseUpTo; /* slow growth beyond this limit */ - /* (measured w.r.t. slots, not keys) */ - unsigned int initSlots; /* initial size of a subtable */ - DdNode **stack; /* stack for iterative procedures */ - double allocated; /* number of nodes allocated */ - /* (not during reordering) */ - double reclaimed; /* number of nodes brought back from the dead */ - int isolated; /* isolated projection functions */ - int *perm; /* current variable perm. (index to level) */ - int *permZ; /* for ZDD */ - int *invperm; /* current inv. var. perm. (level to index) */ - int *invpermZ; /* for ZDD */ - DdNode **vars; /* projection functions */ - int *map; /* variable map for fast swap */ - DdNode **univ; /* ZDD 1 for each variable */ - int linearSize; /* number of rows and columns of linear */ - long *interact; /* interacting variable matrix */ - long *linear; /* linear transform matrix */ - /* Memory Management */ - DdNode **memoryList; /* memory manager for symbol table */ - DdNode *nextFree; /* list of free nodes */ - char *stash; /* memory reserve */ -#ifndef DD_NO_DEATH_ROW - DdNode **deathRow; /* queue for dereferencing */ - int deathRowDepth; /* number of slots in the queue */ - int nextDead; /* index in the queue */ - unsigned deadMask; /* mask for circular index update */ -#endif - /* General Parameters */ - CUDD_VALUE_TYPE epsilon; /* tolerance on comparisons */ - /* Dynamic Reordering Parameters */ - int reordered; /* flag set at the end of reordering */ - int reorderings; /* number of calls to Cudd_ReduceHeap */ - int siftMaxVar; /* maximum number of vars sifted */ - int siftMaxSwap; /* maximum number of swaps per sifting */ - double maxGrowth; /* maximum growth during reordering */ - double maxGrowthAlt; /* alternate maximum growth for reordering */ - int reordCycle; /* how often to apply alternate threshold */ - int autoDyn; /* automatic dynamic reordering flag (BDD) */ - int autoDynZ; /* automatic dynamic reordering flag (ZDD) */ - Cudd_ReorderingType autoMethod; /* default reordering method */ - Cudd_ReorderingType autoMethodZ; /* default reordering method (ZDD) */ - int realign; /* realign ZDD order after BDD reordering */ - int realignZ; /* realign BDD order after ZDD reordering */ - unsigned int nextDyn; /* reorder if this size is reached */ - unsigned int countDead; /* if 0, count deads to trigger reordering */ - MtrNode *tree; /* Variable group tree (BDD) */ - MtrNode *treeZ; /* Variable group tree (ZDD) */ - Cudd_AggregationType groupcheck; /* Used during group sifting */ - int recomb; /* Used during group sifting */ - int symmviolation; /* Used during group sifting */ - int arcviolation; /* Used during group sifting */ - int populationSize; /* population size for GA */ - int numberXovers; /* number of crossovers for GA */ - DdLocalCache *localCaches; /* local caches currently in existence */ -#ifdef __osf__ -#pragma pointer_size restore -#endif - char *hooks; /* application-specific field (used by vis) */ - DdHook *preGCHook; /* hooks to be called before GC */ - DdHook *postGCHook; /* hooks to be called after GC */ - DdHook *preReorderingHook; /* hooks to be called before reordering */ - DdHook *postReorderingHook; /* hooks to be called after reordering */ - FILE *out; /* stdout for this manager */ - FILE *err; /* stderr for this manager */ -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - Cudd_ErrorType errorCode; /* info on last error */ - /* Statistical counters. */ - long memused; /* total memory allocated for the manager */ - long maxmem; /* target maximum memory */ - long maxmemhard; /* hard limit for maximum memory */ - int garbageCollections; /* number of garbage collections */ - long GCTime; /* total time spent in garbage collection */ - long reordTime; /* total time spent in reordering */ - double totCachehits; /* total number of cache hits */ - double totCacheMisses; /* total number of cache misses */ - double cachecollisions; /* number of cache collisions */ - double cacheinserts; /* number of cache insertions */ - double cacheLastInserts; /* insertions at the last cache resizing */ - double cachedeletions; /* number of deletions during garbage coll. */ -#ifdef DD_STATS - double nodesFreed; /* number of nodes returned to the free list */ - double nodesDropped; /* number of nodes killed by dereferencing */ -#endif - unsigned int peakLiveNodes; /* maximum number of live nodes */ -#ifdef DD_UNIQUE_PROFILE - double uniqueLookUps; /* number of unique table lookups */ - double uniqueLinks; /* total distance traveled in coll. chains */ -#endif -#ifdef DD_COUNT - double recursiveCalls; /* number of recursive calls */ -#ifdef DD_STATS - double nextSample; /* when to write next line of stats */ -#endif - double swapSteps; /* number of elementary reordering steps */ -#endif -#ifdef DD_MIS - /* mis/verif compatibility fields */ - array_t *iton; /* maps ids in ddNode to node_t */ - array_t *order; /* copy of order_list */ - lsHandle handle; /* where it is in network BDD list */ - network_t *network; - st_table *local_order; /* for local BDDs */ - int nvars; /* variables used so far */ - int threshold; /* for pseudo var threshold value*/ -#endif -}; - -typedef struct Move { - DdHalfWord x; - DdHalfWord y; - unsigned int flags; - int size; - struct Move *next; -} Move; - -/* Generic level queue item. */ -typedef struct DdQueueItem { - struct DdQueueItem *next; - struct DdQueueItem *cnext; - void *key; -} DdQueueItem; - -/* Level queue. */ -typedef struct DdLevelQueue { - void *first; - DdQueueItem **last; - DdQueueItem *freelist; - DdQueueItem **buckets; - int levels; - int itemsize; - int size; - int maxsize; - int numBuckets; - int shift; -} DdLevelQueue; - -#ifdef __osf__ -#pragma pointer_size restore -#endif - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**Macro*********************************************************************** - - Synopsis [Adds node to the head of the free list.] - - Description [Adds node to the head of the free list. Does not - deallocate memory chunks that become free. This function is also - used by the dynamic reordering functions.] - - SideEffects [None] - - SeeAlso [cuddAllocNode cuddDynamicAllocNode] - -******************************************************************************/ -#define cuddDeallocNode(unique,node) \ - (node)->next = (unique)->nextFree; \ - (unique)->nextFree = node; - - -/**Macro*********************************************************************** - - Synopsis [Increases the reference count of a node, if it is not - saturated.] - - Description [Increases the reference count of a node, if it is not - saturated. This being a macro, it is faster than Cudd_Ref, but it - cannot be used in constructs like cuddRef(a = b()).] - - SideEffects [none] - - SeeAlso [Cudd_Ref] - -******************************************************************************/ -#define cuddRef(n) cuddSatInc(Cudd_Regular(n)->ref) - - -/**Macro*********************************************************************** - - Synopsis [Decreases the reference count of a node, if it is not - saturated.] - - Description [Decreases the reference count of node. It is primarily - used in recursive procedures to decrease the ref count of a result - node before returning it. This accomplishes the goal of removing the - protection applied by a previous cuddRef. This being a macro, it is - faster than Cudd_Deref, but it cannot be used in constructs like - cuddDeref(a = b()).] - - SideEffects [none] - - SeeAlso [Cudd_Deref] - -******************************************************************************/ -#define cuddDeref(n) cuddSatDec(Cudd_Regular(n)->ref) - - -/**Macro*********************************************************************** - - Synopsis [Returns 1 if the node is a constant node.] - - Description [Returns 1 if the node is a constant node (rather than an - internal node). All constant nodes have the same index - (CUDD_CONST_INDEX). The pointer passed to cuddIsConstant must be regular.] - - SideEffects [none] - - SeeAlso [Cudd_IsConstant] - -******************************************************************************/ -#define cuddIsConstant(node) ((node)->index == CUDD_CONST_INDEX) - - -/**Macro*********************************************************************** - - Synopsis [Returns the then child of an internal node.] - - Description [Returns the then child of an internal node. If - <code>node</code> is a constant node, the result is unpredictable. - The pointer passed to cuddT must be regular.] - - SideEffects [none] - - SeeAlso [Cudd_T] - -******************************************************************************/ -#define cuddT(node) ((node)->type.kids.T) - - -/**Macro*********************************************************************** - - Synopsis [Returns the else child of an internal node.] - - Description [Returns the else child of an internal node. If - <code>node</code> is a constant node, the result is unpredictable. - The pointer passed to cuddE must be regular.] - - SideEffects [none] - - SeeAlso [Cudd_E] - -******************************************************************************/ -#define cuddE(node) ((node)->type.kids.E) - - -/**Macro*********************************************************************** - - Synopsis [Returns the value of a constant node.] - - Description [Returns the value of a constant node. If - <code>node</code> is an internal node, the result is unpredictable. - The pointer passed to cuddV must be regular.] - - SideEffects [none] - - SeeAlso [Cudd_V] - -******************************************************************************/ -#define cuddV(node) ((node)->type.value) - - -/**Macro*********************************************************************** - - Synopsis [Finds the current position of variable index in the - order.] - - Description [Finds the current position of variable index in the - order. This macro duplicates the functionality of Cudd_ReadPerm, - but it does not check for out-of-bounds indices and it is more - efficient.] - - SideEffects [none] - - SeeAlso [Cudd_ReadPerm] - -******************************************************************************/ -#define cuddI(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->perm[(index)]) - - -/**Macro*********************************************************************** - - Synopsis [Finds the current position of ZDD variable index in the - order.] - - Description [Finds the current position of ZDD variable index in the - order. This macro duplicates the functionality of Cudd_ReadPermZdd, - but it does not check for out-of-bounds indices and it is more - efficient.] - - SideEffects [none] - - SeeAlso [Cudd_ReadPermZdd] - -******************************************************************************/ -#define cuddIZ(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->permZ[(index)]) - - -/**Macro*********************************************************************** - - Synopsis [Hash function for the unique table.] - - Description [] - - SideEffects [none] - - SeeAlso [ddCHash ddCHash2] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define ddHash(f,g,s) \ -((((unsigned)(unsigned long)(f) * DD_P1 + \ - (unsigned)(unsigned long)(g)) * DD_P2) >> (s)) -#else -#define ddHash(f,g,s) \ -((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Hash function for the cache.] - - Description [] - - SideEffects [none] - - SeeAlso [ddHash ddCHash2] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define ddCHash(o,f,g,h,s) \ -((((((unsigned)(unsigned long)(f) + (unsigned)(unsigned long)(o)) * DD_P1 + \ - (unsigned)(unsigned long)(g)) * DD_P2 + \ - (unsigned)(unsigned long)(h)) * DD_P3) >> (s)) -#else -#define ddCHash(o,f,g,h,s) \ -((((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2 + \ - (unsigned)(h)) * DD_P3) >> (s)) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Hash function for the cache for functions with two - operands.] - - Description [] - - SideEffects [none] - - SeeAlso [ddHash ddCHash] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define ddCHash2(o,f,g,s) \ -(((((unsigned)(unsigned long)(f) + (unsigned)(unsigned long)(o)) * DD_P1 + \ - (unsigned)(unsigned long)(g)) * DD_P2) >> (s)) -#else -#define ddCHash2(o,f,g,s) \ -(((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Clears the 4 least significant bits of a pointer.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -#define cuddClean(p) ((DdNode *)((ptruint)(p) & ~0xf)) - - -/**Macro*********************************************************************** - - Synopsis [Computes the minimum of two numbers.] - - Description [] - - SideEffects [none] - - SeeAlso [ddMax] - -******************************************************************************/ -#define ddMin(x,y) (((y) < (x)) ? (y) : (x)) - - -/**Macro*********************************************************************** - - Synopsis [Computes the maximum of two numbers.] - - Description [] - - SideEffects [none] - - SeeAlso [ddMin] - -******************************************************************************/ -#define ddMax(x,y) (((y) > (x)) ? (y) : (x)) - - -/**Macro*********************************************************************** - - Synopsis [Computes the absolute value of a number.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -#define ddAbs(x) (((x)<0) ? -(x) : (x)) - - -/**Macro*********************************************************************** - - Synopsis [Returns 1 if the absolute value of the difference of the two - arguments x and y is less than e.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -#define ddEqualVal(x,y,e) (ddAbs((x)-(y))<(e)) - - -/**Macro*********************************************************************** - - Synopsis [Saturating increment operator.] - - Description [] - - SideEffects [none] - - SeeAlso [cuddSatDec] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define cuddSatInc(x) ((x)++) -#else -#define cuddSatInc(x) ((x) += (x) != (DdHalfWord)DD_MAXREF) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Saturating decrement operator.] - - Description [] - - SideEffects [none] - - SeeAlso [cuddSatInc] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define cuddSatDec(x) ((x)--) -#else -#define cuddSatDec(x) ((x) -= (x) != (DdHalfWord)DD_MAXREF) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Returns the constant 1 node.] - - Description [] - - SideEffects [none] - - SeeAlso [DD_ZERO DD_PLUS_INFINITY DD_MINUS_INFINITY] - -******************************************************************************/ -#define DD_ONE(dd) ((dd)->one) - - -/**Macro*********************************************************************** - - Synopsis [Returns the arithmetic 0 constant node.] - - Description [Returns the arithmetic 0 constant node. This is different - from the logical zero. The latter is obtained by - Cudd_Not(DD_ONE(dd)).] - - SideEffects [none] - - SeeAlso [DD_ONE Cudd_Not DD_PLUS_INFINITY DD_MINUS_INFINITY] - -******************************************************************************/ -#define DD_ZERO(dd) ((dd)->zero) - - -/**Macro*********************************************************************** - - Synopsis [Returns the plus infinity constant node.] - - Description [] - - SideEffects [none] - - SeeAlso [DD_ONE DD_ZERO DD_MINUS_INFINITY] - -******************************************************************************/ -#define DD_PLUS_INFINITY(dd) ((dd)->plusinfinity) - - -/**Macro*********************************************************************** - - Synopsis [Returns the minus infinity constant node.] - - Description [] - - SideEffects [none] - - SeeAlso [DD_ONE DD_ZERO DD_PLUS_INFINITY] - -******************************************************************************/ -#define DD_MINUS_INFINITY(dd) ((dd)->minusinfinity) - - -/**Macro*********************************************************************** - - Synopsis [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.] - - Description [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL. - Furthermore, if x <= DD_MINUS_INF_VAL/2, x is set to - DD_MINUS_INF_VAL. Similarly, if DD_PLUS_INF_VAL/2 <= x, x is set to - DD_PLUS_INF_VAL. Normally this macro is a NOOP. However, if - HAVE_IEEE_754 is not defined, it makes sure that a value does not - get larger than infinity in absolute value, and once it gets to - infinity, stays there. If the value overflows before this macro is - applied, no recovery is possible.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -#ifdef HAVE_IEEE_754 -#define cuddAdjust(x) -#else -#define cuddAdjust(x) ((x) = ((x) >= DD_CRI_HI_MARK) ? DD_PLUS_INF_VAL : (((x) <= DD_CRI_LO_MARK) ? DD_MINUS_INF_VAL : (x))) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Extract the least significant digit of a double digit.] - - Description [Extract the least significant digit of a double digit. Used - in the manipulation of arbitrary precision integers.] - - SideEffects [None] - - SeeAlso [DD_MSDIGIT] - -******************************************************************************/ -#define DD_LSDIGIT(x) ((x) & DD_APA_MASK) - - -/**Macro*********************************************************************** - - Synopsis [Extract the most significant digit of a double digit.] - - Description [Extract the most significant digit of a double digit. Used - in the manipulation of arbitrary precision integers.] - - SideEffects [None] - - SeeAlso [DD_LSDIGIT] - -******************************************************************************/ -#define DD_MSDIGIT(x) ((x) >> DD_APA_BITS) - - -/**Macro*********************************************************************** - - Synopsis [Outputs a line of stats.] - - Description [Outputs a line of stats if DD_COUNT and DD_STATS are - defined. Increments the number of recursive calls if DD_COUNT is - defined.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -#ifdef DD_COUNT -#ifdef DD_STATS -#define statLine(dd) dd->recursiveCalls++; \ -if (dd->recursiveCalls == dd->nextSample) {(void) fprintf(dd->err, \ -"@%.0f: %u nodes %u live %.0f dropped %.0f reclaimed\n", dd->recursiveCalls, \ -dd->keys, dd->keys - dd->dead, dd->nodesDropped, dd->reclaimed); \ -dd->nextSample += 250000;} -#else -#define statLine(dd) dd->recursiveCalls++; -#endif -#else -#define statLine(dd) -#endif - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - -EXTERN DdNode * cuddAddExistAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * cuddAddUnivAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * cuddAddOrAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * cuddAddApplyRecur ARGS((DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g)); -EXTERN DdNode * cuddAddMonadicApplyRecur ARGS((DdManager * dd, DdNode * (*op)(DdManager *, DdNode *), DdNode * f)); -EXTERN DdNode * cuddAddScalarInverseRecur ARGS((DdManager *dd, DdNode *f, DdNode *epsilon)); -EXTERN DdNode * cuddAddIteRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddAddCmplRecur ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * cuddAddNegateRecur ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * cuddAddRoundOffRecur ARGS((DdManager *dd, DdNode *f, double trunc)); -EXTERN DdNode * cuddUnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality)); -EXTERN DdNode * cuddRemapUnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, double quality)); -EXTERN DdNode * cuddBiasedUnderApprox ARGS((DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0)); -EXTERN DdNode * cuddBddAndAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); -EXTERN int cuddAnnealing ARGS((DdManager *table, int lower, int upper)); -EXTERN DdNode * cuddBddExistAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * cuddBddXorExistAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); -EXTERN DdNode * cuddBddBooleanDiffRecur ARGS((DdManager *manager, DdNode *f, DdNode *var)); -EXTERN DdNode * cuddBddIteRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddBddIntersectRecur ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddBddAndRecur ARGS((DdManager *manager, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddBddXorRecur ARGS((DdManager *manager, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddBddTransfer ARGS((DdManager *ddS, DdManager *ddD, DdNode *f)); -EXTERN DdNode * cuddAddBddDoPattern ARGS((DdManager *dd, DdNode *f)); -EXTERN int cuddInitCache ARGS((DdManager *unique, unsigned int cacheSize, unsigned int maxCacheSize)); -EXTERN void cuddCacheInsert ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h, DdNode *data)); -EXTERN void cuddCacheInsert2 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g, DdNode *data)); -EXTERN void cuddCacheInsert1 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f, DdNode *data)); -EXTERN DdNode * cuddCacheLookup ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddCacheLookupZdd ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddCacheLookup2 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g)); -EXTERN DdNode * cuddCacheLookup1 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f)); -EXTERN DdNode * cuddCacheLookup2Zdd ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g)); -EXTERN DdNode * cuddCacheLookup1Zdd ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f)); -EXTERN DdNode * cuddConstantLookup ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)); -EXTERN int cuddCacheProfile ARGS((DdManager *table, FILE *fp)); -EXTERN void cuddCacheResize ARGS((DdManager *table)); -EXTERN void cuddCacheFlush ARGS((DdManager *table)); -EXTERN int cuddComputeFloorLog2 ARGS((unsigned int value)); -EXTERN int cuddHeapProfile ARGS((DdManager *dd)); -EXTERN void cuddPrintNode ARGS((DdNode *f, FILE *fp)); -EXTERN void cuddPrintVarGroups ARGS((DdManager * dd, MtrNode * root, int zdd, int silent)); -EXTERN DdNode * cuddBddClippingAnd ARGS((DdManager *dd, DdNode *f, DdNode *g, int maxDepth, int direction)); -EXTERN DdNode * cuddBddClippingAndAbstract ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *cube, int maxDepth, int direction)); -EXTERN void cuddGetBranches ARGS((DdNode *g, DdNode **g1, DdNode **g0)); -EXTERN int cuddCheckCube ARGS((DdManager *dd, DdNode *g)); -EXTERN DdNode * cuddCofactorRecur ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddBddComposeRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *proj)); -EXTERN DdNode * cuddAddComposeRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *proj)); -EXTERN int cuddExact ARGS((DdManager *table, int lower, int upper)); -EXTERN DdNode * cuddBddConstrainRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * cuddBddRestrictRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * cuddAddConstrainRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * cuddAddRestrictRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * cuddBddLICompaction ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN int cuddGa ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddTreeSifting ARGS((DdManager *table, Cudd_ReorderingType method)); -EXTERN int cuddZddInitUniv ARGS((DdManager *zdd)); -EXTERN void cuddZddFreeUniv ARGS((DdManager *zdd)); -EXTERN void cuddSetInteract ARGS((DdManager *table, int x, int y)); -EXTERN int cuddTestInteract ARGS((DdManager *table, int x, int y)); -EXTERN int cuddInitInteract ARGS((DdManager *table)); -EXTERN DdLocalCache * cuddLocalCacheInit ARGS((DdManager *manager, unsigned int keySize, unsigned int cacheSize, unsigned int maxCacheSize)); -EXTERN void cuddLocalCacheQuit ARGS((DdLocalCache *cache)); -EXTERN void cuddLocalCacheInsert ARGS((DdLocalCache *cache, DdNodePtr *key, DdNode *value)); -EXTERN DdNode * cuddLocalCacheLookup ARGS((DdLocalCache *cache, DdNodePtr *key)); -EXTERN void cuddLocalCacheClearDead ARGS((DdManager *manager)); -EXTERN int cuddIsInDeathRow ARGS((DdManager *dd, DdNode *f)); -EXTERN int cuddTimesInDeathRow ARGS((DdManager *dd, DdNode *f)); -EXTERN void cuddLocalCacheClearAll ARGS((DdManager *manager)); -#ifdef DD_CACHE_PROFILE -EXTERN int cuddLocalCacheProfile ARGS((DdLocalCache *cache)); -#endif -EXTERN DdHashTable * cuddHashTableInit ARGS((DdManager *manager, unsigned int keySize, unsigned int initSize)); -EXTERN void cuddHashTableQuit ARGS((DdHashTable *hash)); -EXTERN int cuddHashTableInsert ARGS((DdHashTable *hash, DdNodePtr *key, DdNode *value, ptrint count)); -EXTERN DdNode * cuddHashTableLookup ARGS((DdHashTable *hash, DdNodePtr *key)); -EXTERN int cuddHashTableInsert1 ARGS((DdHashTable *hash, DdNode *f, DdNode *value, ptrint count)); -EXTERN DdNode * cuddHashTableLookup1 ARGS((DdHashTable *hash, DdNode *f)); -EXTERN int cuddHashTableInsert2 ARGS((DdHashTable *hash, DdNode *f, DdNode *g, DdNode *value, ptrint count)); -EXTERN DdNode * cuddHashTableLookup2 ARGS((DdHashTable *hash, DdNode *f, DdNode *g)); -EXTERN int cuddHashTableInsert3 ARGS((DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h, DdNode *value, ptrint count)); -EXTERN DdNode * cuddHashTableLookup3 ARGS((DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdLevelQueue * cuddLevelQueueInit ARGS((int levels, int itemSize, int numBuckets)); -EXTERN void cuddLevelQueueQuit ARGS((DdLevelQueue *queue)); -EXTERN void * cuddLevelQueueEnqueue ARGS((DdLevelQueue *queue, void *key, int level)); -EXTERN void cuddLevelQueueDequeue ARGS((DdLevelQueue *queue, int level)); -EXTERN int cuddLinearAndSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN DdNode * cuddBddLiteralSetIntersectionRecur ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddCProjectionRecur ARGS((DdManager *dd, DdNode *R, DdNode *Y, DdNode *Ysupp)); -EXTERN DdNode * cuddBddClosestCube ARGS((DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE bound)); -EXTERN void cuddReclaim ARGS((DdManager *table, DdNode *n)); -EXTERN void cuddReclaimZdd ARGS((DdManager *table, DdNode *n)); -EXTERN void cuddClearDeathRow ARGS((DdManager *table)); -EXTERN void cuddShrinkDeathRow ARGS((DdManager *table)); -EXTERN DdNode * cuddDynamicAllocNode ARGS((DdManager *table)); -EXTERN int cuddSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddSwapping ARGS((DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)); -EXTERN int cuddNextHigh ARGS((DdManager *table, int x)); -EXTERN int cuddNextLow ARGS((DdManager *table, int x)); -EXTERN int cuddSwapInPlace ARGS((DdManager *table, int x, int y)); -EXTERN int cuddBddAlignToZdd ARGS((DdManager *table)); -EXTERN DdNode * cuddBddMakePrime ARGS((DdManager *dd, DdNode *cube, DdNode *f)); -EXTERN DdNode * cuddSolveEqnRecur ARGS((DdManager *bdd, DdNode *F, DdNode *Y, DdNode **G, int n, int *yIndex, int i)); -EXTERN DdNode * cuddVerifySol ARGS((DdManager *bdd, DdNode *F, DdNode **G, int *yIndex, int n)); -#ifdef ST_INCLUDED -EXTERN DdNode* cuddSplitSetRecur ARGS((DdManager *manager, st_table *mtable, int *varSeen, DdNode *p, double n, double max, int index)); -#endif -EXTERN DdNode * cuddSubsetHeavyBranch ARGS((DdManager *dd, DdNode *f, int numVars, int threshold)); -EXTERN DdNode * cuddSubsetShortPaths ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)); -EXTERN int cuddSymmCheck ARGS((DdManager *table, int x, int y)); -EXTERN int cuddSymmSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddSymmSiftingConv ARGS((DdManager *table, int lower, int upper)); -EXTERN DdNode * cuddAllocNode ARGS((DdManager *unique)); -EXTERN DdManager * cuddInitTable ARGS((unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int looseUpTo)); -EXTERN void cuddFreeTable ARGS((DdManager *unique)); -EXTERN int cuddGarbageCollect ARGS((DdManager *unique, int clearCache)); -EXTERN int cuddGarbageCollectZdd ARGS((DdManager *unique, int clearCache)); -EXTERN DdNode * cuddZddGetNode ARGS((DdManager *zdd, int id, DdNode *T, DdNode *E)); -EXTERN DdNode * cuddZddGetNodeIVO ARGS((DdManager *dd, int index, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddUniqueInter ARGS((DdManager *unique, int index, DdNode *T, DdNode *E)); -EXTERN DdNode * cuddUniqueInterIVO ARGS((DdManager *unique, int index, DdNode *T, DdNode *E)); -EXTERN DdNode * cuddUniqueInterZdd ARGS((DdManager *unique, int index, DdNode *T, DdNode *E)); -EXTERN DdNode * cuddUniqueConst ARGS((DdManager *unique, CUDD_VALUE_TYPE value)); -EXTERN void cuddRehash ARGS((DdManager *unique, int i)); -EXTERN void cuddShrinkSubtable ARGS((DdManager *unique, int i)); -EXTERN int cuddInsertSubtables ARGS((DdManager *unique, int n, int level)); -EXTERN int cuddDestroySubtables ARGS((DdManager *unique, int n)); -EXTERN int cuddResizeTableZdd ARGS((DdManager *unique, int index)); -EXTERN void cuddSlowTableGrowth ARGS((DdManager *unique)); -EXTERN int cuddP ARGS((DdManager *dd, DdNode *f)); -#ifdef ST_INCLUDED -EXTERN enum st_retval cuddStCountfree ARGS((char *key, char *value, char *arg)); -EXTERN int cuddCollectNodes ARGS((DdNode *f, st_table *visited)); -#endif -EXTERN int cuddWindowReorder ARGS((DdManager *table, int low, int high, Cudd_ReorderingType submethod)); -EXTERN DdNode * cuddZddProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddZddUnateProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddZddWeakDiv ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddZddWeakDivF ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddZddDivide ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddZddDivideF ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN int cuddZddGetCofactors3 ARGS((DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0, DdNode **fd)); -EXTERN int cuddZddGetCofactors2 ARGS((DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0)); -EXTERN DdNode * cuddZddComplement ARGS((DdManager *dd, DdNode *node)); -EXTERN int cuddZddGetPosVarIndex(DdManager * dd, int index); -EXTERN int cuddZddGetNegVarIndex(DdManager * dd, int index); -EXTERN int cuddZddGetPosVarLevel(DdManager * dd, int index); -EXTERN int cuddZddGetNegVarLevel(DdManager * dd, int index); -EXTERN int cuddZddTreeSifting ARGS((DdManager *table, Cudd_ReorderingType method)); -EXTERN DdNode * cuddZddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U, DdNode **zdd_I)); -EXTERN DdNode * cuddBddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U)); -EXTERN DdNode * cuddMakeBddFromZddCover ARGS((DdManager *dd, DdNode *node)); -EXTERN int cuddZddLinearSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddZddAlignToBdd ARGS((DdManager *table)); -EXTERN int cuddZddNextHigh ARGS((DdManager *table, int x)); -EXTERN int cuddZddNextLow ARGS((DdManager *table, int x)); -EXTERN int cuddZddUniqueCompare ARGS((int *ptr_x, int *ptr_y)); -EXTERN int cuddZddSwapInPlace ARGS((DdManager *table, int x, int y)); -EXTERN int cuddZddSwapping ARGS((DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)); -EXTERN int cuddZddSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN DdNode * cuddZddIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddZddUnion ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); -EXTERN DdNode * cuddZddIntersect ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); -EXTERN DdNode * cuddZddDiff ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); -EXTERN DdNode * cuddZddChangeAux ARGS((DdManager *zdd, DdNode *P, DdNode *zvar)); -EXTERN DdNode * cuddZddSubset1 ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN DdNode * cuddZddSubset0 ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN DdNode * cuddZddChange ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN int cuddZddSymmCheck ARGS((DdManager *table, int x, int y)); -EXTERN int cuddZddSymmSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddZddSymmSiftingConv ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddZddP ARGS((DdManager *zdd, DdNode *f)); - -/**AutomaticEnd***************************************************************/ - -#endif /* _CUDDINT */ diff --git a/src/bdd/cudd/cuddInteract.c b/src/bdd/cudd/cuddInteract.c deleted file mode 100644 index 96613639..00000000 --- a/src/bdd/cudd/cuddInteract.c +++ /dev/null @@ -1,402 +0,0 @@ -/**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 - intercat, but that for a given variable order have no arc connecting - their layers when they are adjacent.] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.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.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void ddSuppInteract ARGS((DdNode *f, int *support)); -static void ddClearLocal ARGS((DdNode *f)); -static void ddUpdateInteract ARGS((DdManager *table, int *support)); -static void ddClearGlobal ARGS((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,k; - int words; - long *interact; - int *support; - DdNode *f; - DdNode *sentinel = &(table->sentinel); - DdNodePtr *nodelist; - int slots; - int n = 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(int,n); - if (support == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - FREE(interact); - return(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)) { - for (k = 0; k < n; k++) { - support[k] = 0; - } - 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, - int * 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 [None] - - SeeAlso [] - -******************************************************************************/ -static void -ddUpdateInteract( - DdManager * table, - int * support) -{ - int i,j; - int n = table->size; - - for (i = 0; i < n-1; i++) { - if (support[i] == 1) { - for (j = i+1; j < n; j++) { - if (support[j] == 1) { - cuddSetInteract(table,i,j); - } - } - } - } - -} /* 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 */ - diff --git a/src/bdd/cudd/cuddLCache.c b/src/bdd/cudd/cuddLCache.c deleted file mode 100644 index 8bd37ba0..00000000 --- a/src/bdd/cudd/cuddLCache.c +++ /dev/null @@ -1,1428 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddLCache.c] - - PackageName [cudd] - - Synopsis [Functions for local caches.] - - Description [Internal procedures included in this module: - <ul> - <li> cuddLocalCacheInit() - <li> cuddLocalCacheQuit() - <li> cuddLocalCacheInsert() - <li> cuddLocalCacheLookup() - <li> cuddLocalCacheClearDead() - <li> cuddLocalCacheClearAll() - <li> cuddLocalCacheProfile() - <li> cuddHashTableInit() - <li> cuddHashTableQuit() - <li> cuddHashTableInsert() - <li> cuddHashTableLookup() - <li> cuddHashTableInsert2() - <li> cuddHashTableLookup2() - <li> cuddHashTableInsert3() - <li> cuddHashTableLookup3() - </ul> - Static procedures included in this module: - <ul> - <li> cuddLocalCacheResize() - <li> ddLCHash() - <li> cuddLocalCacheAddToList() - <li> cuddLocalCacheRemoveFromList() - <li> cuddHashTableResize() - <li> cuddHashTableAlloc() - </ul> ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_MAX_HASHTABLE_DENSITY 2 /* tells when to resize a table */ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddLCache.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**Macro*********************************************************************** - - Synopsis [Computes hash function for keys of two operands.] - - Description [] - - SideEffects [None] - - SeeAlso [ddLCHash3 ddLCHash] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define ddLCHash2(f,g,shift) \ -((((unsigned)(unsigned long)(f) * DD_P1 + \ - (unsigned)(unsigned long)(g)) * DD_P2) >> (shift)) -#else -#define ddLCHash2(f,g,shift) \ -((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (shift)) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Computes hash function for keys of three operands.] - - Description [] - - SideEffects [None] - - SeeAlso [ddLCHash2 ddLCHash] - -******************************************************************************/ -#define ddLCHash3(f,g,h,shift) ddCHash2(f,g,h,shift) - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void cuddLocalCacheResize ARGS((DdLocalCache *cache)); -DD_INLINE static unsigned int ddLCHash ARGS((DdNodePtr *key, unsigned int keysize, int shift)); -static void cuddLocalCacheAddToList ARGS((DdLocalCache *cache)); -static void cuddLocalCacheRemoveFromList ARGS((DdLocalCache *cache)); -static int cuddHashTableResize ARGS((DdHashTable *hash)); -DD_INLINE static DdHashItem * cuddHashTableAlloc ARGS((DdHashTable *hash)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Initializes a local computed table.] - - Description [Initializes a computed table. Returns a pointer the - the new local cache in case of success; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddInitCache] - -******************************************************************************/ -DdLocalCache * -cuddLocalCacheInit( - DdManager * manager /* manager */, - unsigned int keySize /* size of the key (number of operands) */, - unsigned int cacheSize /* Initial size of the cache */, - unsigned int maxCacheSize /* Size of the cache beyond which no resizing occurs */) -{ - DdLocalCache *cache; - int logSize; - - cache = ALLOC(DdLocalCache,1); - if (cache == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - cache->manager = manager; - cache->keysize = keySize; - cache->itemsize = (keySize + 1) * sizeof(DdNode *); -#ifdef DD_CACHE_PROFILE - cache->itemsize += sizeof(ptrint); -#endif - logSize = cuddComputeFloorLog2(ddMax(cacheSize,manager->slots/2)); - cacheSize = 1 << logSize; - cache->item = (DdLocalCacheItem *) - ALLOC(char, cacheSize * cache->itemsize); - if (cache->item == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - FREE(cache); - return(NULL); - } - cache->slots = cacheSize; - cache->shift = sizeof(int) * 8 - logSize; - cache->maxslots = ddMin(maxCacheSize,manager->slots); - cache->minHit = manager->minHit; - /* Initialize to avoid division by 0 and immediate resizing. */ - cache->lookUps = (double) (int) (cacheSize * cache->minHit + 1); - cache->hits = 0; - manager->memused += cacheSize * cache->itemsize + sizeof(DdLocalCache); - - /* Initialize the cache. */ - memset(cache->item, 0, cacheSize * cache->itemsize); - - /* Add to manager's list of local caches for GC. */ - cuddLocalCacheAddToList(cache); - - return(cache); - -} /* end of cuddLocalCacheInit */ - - -/**Function******************************************************************** - - Synopsis [Shuts down a local computed table.] - - Description [Initializes the computed table. It is called by - Cudd_Init. Returns a pointer the the new local cache in case of - success; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddLocalCacheInit] - -******************************************************************************/ -void -cuddLocalCacheQuit( - DdLocalCache * cache /* cache to be shut down */) -{ - cache->manager->memused -= - cache->slots * cache->itemsize + sizeof(DdLocalCache); - cuddLocalCacheRemoveFromList(cache); - FREE(cache->item); - FREE(cache); - - return; - -} /* end of cuddLocalCacheQuit */ - - -/**Function******************************************************************** - - Synopsis [Inserts a result in a local cache.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddLocalCacheInsert( - DdLocalCache * cache, - DdNodePtr * key, - DdNode * value) -{ - unsigned int posn; - DdLocalCacheItem *entry; - - posn = ddLCHash(key,cache->keysize,cache->shift); - entry = (DdLocalCacheItem *) ((char *) cache->item + - posn * cache->itemsize); - memcpy(entry->key,key,cache->keysize * sizeof(DdNode *)); - entry->value = value; -#ifdef DD_CACHE_PROFILE - entry->count++; -#endif - -} /* end of cuddLocalCacheInsert */ - - -/**Function******************************************************************** - - Synopsis [Looks up in a local cache.] - - Description [Looks up in a local cache. Returns the result if found; - it returns NULL if no result is found.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddLocalCacheLookup( - DdLocalCache * cache, - DdNodePtr * key) -{ - unsigned int posn; - DdLocalCacheItem *entry; - DdNode *value; - - cache->lookUps++; - posn = ddLCHash(key,cache->keysize,cache->shift); - entry = (DdLocalCacheItem *) ((char *) cache->item + - posn * cache->itemsize); - if (entry->value != NULL && - memcmp(key,entry->key,cache->keysize*sizeof(DdNode *)) == 0) { - cache->hits++; - value = Cudd_Regular(entry->value); - if (value->ref == 0) { - cuddReclaim(cache->manager,value); - } - return(entry->value); - } - - /* Cache miss: decide whether to resize */ - - if (cache->slots < cache->maxslots && - cache->hits > cache->lookUps * cache->minHit) { - cuddLocalCacheResize(cache); - } - - return(NULL); - -} /* end of cuddLocalCacheLookup */ - - -/**Function******************************************************************** - - Synopsis [Clears the dead entries of the local caches of a manager.] - - Description [Clears the dead entries of the local caches of a manager. - Used during garbage collection.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddLocalCacheClearDead( - DdManager * manager) -{ - DdLocalCache *cache = manager->localCaches; - unsigned int keysize; - unsigned int itemsize; - unsigned int slots; - DdLocalCacheItem *item; - DdNodePtr *key; - unsigned int i, j; - - while (cache != NULL) { - keysize = cache->keysize; - itemsize = cache->itemsize; - slots = cache->slots; - item = cache->item; - for (i = 0; i < slots; i++) { - if (item->value != NULL && Cudd_Regular(item->value)->ref == 0) { - item->value = NULL; - } else { - key = item->key; - for (j = 0; j < keysize; j++) { - if (Cudd_Regular(key[j])->ref == 0) { - item->value = NULL; - break; - } - } - } - item = (DdLocalCacheItem *) ((char *) item + itemsize); - } - cache = cache->next; - } - return; - -} /* end of cuddLocalCacheClearDead */ - - -/**Function******************************************************************** - - Synopsis [Clears the local caches of a manager.] - - Description [Clears the local caches of a manager. - Used before reordering.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddLocalCacheClearAll( - DdManager * manager) -{ - DdLocalCache *cache = manager->localCaches; - - while (cache != NULL) { - memset(cache->item, 0, cache->slots * cache->itemsize); - cache = cache->next; - } - return; - -} /* end of cuddLocalCacheClearAll */ - - -#ifdef DD_CACHE_PROFILE - -#define DD_HYSTO_BINS 8 - -/**Function******************************************************************** - - Synopsis [Computes and prints a profile of a local cache usage.] - - Description [Computes and prints a profile of a local cache usage. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddLocalCacheProfile( - DdLocalCache * cache) -{ - double count, mean, meansq, stddev, expected; - long max, min; - int imax, imin; - int i, retval, slots; - long *hystogram; - int nbins = DD_HYSTO_BINS; - int bin; - long thiscount; - double totalcount; - int nzeroes; - DdLocalCacheItem *entry; - FILE *fp = cache->manager->out; - - slots = cache->slots; - - meansq = mean = expected = 0.0; - max = min = (long) cache->item[0].count; - imax = imin = nzeroes = 0; - totalcount = 0.0; - - hystogram = ALLOC(long, nbins); - if (hystogram == NULL) { - return(0); - } - for (i = 0; i < nbins; i++) { - hystogram[i] = 0; - } - - for (i = 0; i < slots; i++) { - entry = (DdLocalCacheItem *) ((char *) cache->item + - i * cache->itemsize); - thiscount = (long) entry->count; - if (thiscount > max) { - max = thiscount; - imax = i; - } - if (thiscount < min) { - min = thiscount; - imin = i; - } - if (thiscount == 0) { - nzeroes++; - } - count = (double) thiscount; - mean += count; - meansq += count * count; - totalcount += count; - expected += count * (double) i; - bin = (i * nbins) / slots; - hystogram[bin] += thiscount; - } - mean /= (double) slots; - meansq /= (double) slots; - stddev = sqrt(meansq - mean*mean); - - retval = fprintf(fp,"Cache stats: slots = %d average = %g ", slots, mean); - if (retval == EOF) return(0); - retval = fprintf(fp,"standard deviation = %g\n", stddev); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache unused slots = %d\n", nzeroes); - if (retval == EOF) return(0); - - if (totalcount) { - expected /= totalcount; - retval = fprintf(fp,"Cache access hystogram for %d bins", nbins); - if (retval == EOF) return(0); - retval = fprintf(fp," (expected bin value = %g)\n# ", expected); - if (retval == EOF) return(0); - for (i = nbins - 1; i>=0; i--) { - retval = fprintf(fp,"%ld ", hystogram[i]); - if (retval == EOF) return(0); - } - retval = fprintf(fp,"\n"); - if (retval == EOF) return(0); - } - - FREE(hystogram); - return(1); - -} /* end of cuddLocalCacheProfile */ -#endif - - -/**Function******************************************************************** - - Synopsis [Initializes a hash table.] - - Description [Initializes a hash table. Returns a pointer to the new - table if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddHashTableQuit] - -******************************************************************************/ -DdHashTable * -cuddHashTableInit( - DdManager * manager, - unsigned int keySize, - unsigned int initSize) -{ - DdHashTable *hash; - int logSize; - -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - hash = ALLOC(DdHashTable, 1); - if (hash == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - hash->keysize = keySize; - hash->manager = manager; - hash->memoryList = NULL; - hash->nextFree = NULL; - hash->itemsize = (keySize + 1) * sizeof(DdNode *) + - sizeof(ptrint) + sizeof(DdHashItem *); - /* We have to guarantee that the shift be < 32. */ - if (initSize < 2) initSize = 2; - logSize = cuddComputeFloorLog2(initSize); - hash->numBuckets = 1 << logSize; - hash->shift = sizeof(int) * 8 - logSize; - hash->bucket = ALLOC(DdHashItem *, hash->numBuckets); - if (hash->bucket == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - FREE(hash); - return(NULL); - } - memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *)); - hash->size = 0; - hash->maxsize = hash->numBuckets * DD_MAX_HASHTABLE_DENSITY; -#ifdef __osf__ -#pragma pointer_size restore -#endif - return(hash); - -} /* end of cuddHashTableInit */ - - -/**Function******************************************************************** - - Synopsis [Shuts down a hash table.] - - Description [Shuts down a hash table, dereferencing all the values.] - - SideEffects [None] - - SeeAlso [cuddHashTableInit] - -******************************************************************************/ -void -cuddHashTableQuit( - DdHashTable * hash) -{ -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - unsigned int i; - DdManager *dd = hash->manager; - DdHashItem *bucket; - DdHashItem **memlist, **nextmem; - unsigned int numBuckets = hash->numBuckets; - - for (i = 0; i < numBuckets; i++) { - bucket = hash->bucket[i]; - while (bucket != NULL) { - Cudd_RecursiveDeref(dd, bucket->value); - bucket = bucket->next; - } - } - - memlist = hash->memoryList; - while (memlist != NULL) { - nextmem = (DdHashItem **) memlist[0]; - FREE(memlist); - memlist = nextmem; - } - - FREE(hash->bucket); - FREE(hash); -#ifdef __osf__ -#pragma pointer_size restore -#endif - - return; - -} /* end of cuddHashTableQuit */ - - -/**Function******************************************************************** - - Synopsis [Inserts an item in a hash table.] - - Description [Inserts an item in a hash table when the key has more than - three pointers. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [[cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableInsert3 - cuddHashTableLookup] - -******************************************************************************/ -int -cuddHashTableInsert( - DdHashTable * hash, - DdNodePtr * key, - DdNode * value, - ptrint count) -{ - int result; - unsigned int posn; - DdHashItem *item; - unsigned int i; - -#ifdef DD_DEBUG - assert(hash->keysize > 3); -#endif - - if (hash->size > hash->maxsize) { - result = cuddHashTableResize(hash); - if (result == 0) return(0); - } - item = cuddHashTableAlloc(hash); - if (item == NULL) return(0); - hash->size++; - item->value = value; - cuddRef(value); - item->count = count; - for (i = 0; i < hash->keysize; i++) { - item->key[i] = key[i]; - } - posn = ddLCHash(key,hash->keysize,hash->shift); - item->next = hash->bucket[posn]; - hash->bucket[posn] = item; - - return(1); - -} /* end of cuddHashTableInsert */ - - -/**Function******************************************************************** - - Synopsis [Looks up a key in a hash table.] - - Description [Looks up a key consisting of more than three pointers - in a hash table. Returns the value associated to the key if there - is an entry for the given key in the table; NULL otherwise. If the - entry is present, its reference counter is decremented if not - saturated. If the counter reaches 0, the value of the entry is - dereferenced, and the entry is returned to the free list.] - - SideEffects [None] - - SeeAlso [cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableLookup3 - cuddHashTableInsert] - -******************************************************************************/ -DdNode * -cuddHashTableLookup( - DdHashTable * hash, - DdNodePtr * key) -{ - unsigned int posn; - DdHashItem *item, *prev; - unsigned int i, keysize; - -#ifdef DD_DEBUG - assert(hash->keysize > 3); -#endif - - posn = ddLCHash(key,hash->keysize,hash->shift); - item = hash->bucket[posn]; - prev = NULL; - - keysize = hash->keysize; - while (item != NULL) { - DdNodePtr *key2 = item->key; - int equal = 1; - for (i = 0; i < keysize; i++) { - if (key[i] != key2[i]) { - equal = 0; - break; - } - } - if (equal) { - DdNode *value = item->value; - cuddSatDec(item->count); - if (item->count == 0) { - cuddDeref(value); - if (prev == NULL) { - hash->bucket[posn] = item->next; - } else { - prev->next = item->next; - } - item->next = hash->nextFree; - hash->nextFree = item; - hash->size--; - } - return(value); - } - prev = item; - item = item->next; - } - return(NULL); - -} /* end of cuddHashTableLookup */ - - -/**Function******************************************************************** - - Synopsis [Inserts an item in a hash table.] - - Description [Inserts an item in a hash table when the key is one pointer. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddHashTableInsert cuddHashTableInsert2 cuddHashTableInsert3 - cuddHashTableLookup1] - -******************************************************************************/ -int -cuddHashTableInsert1( - DdHashTable * hash, - DdNode * f, - DdNode * value, - ptrint count) -{ - int result; - unsigned int posn; - DdHashItem *item; - -#ifdef DD_DEBUG - assert(hash->keysize == 1); -#endif - - if (hash->size > hash->maxsize) { - result = cuddHashTableResize(hash); - if (result == 0) return(0); - } - item = cuddHashTableAlloc(hash); - if (item == NULL) return(0); - hash->size++; - item->value = value; - cuddRef(value); - item->count = count; - item->key[0] = f; - posn = ddLCHash2(f,f,hash->shift); - item->next = hash->bucket[posn]; - hash->bucket[posn] = item; - - return(1); - -} /* end of cuddHashTableInsert1 */ - - -/**Function******************************************************************** - - Synopsis [Looks up a key consisting of one pointer in a hash table.] - - Description [Looks up a key consisting of one pointer in a hash table. - Returns the value associated to the key if there is an entry for the given - key in the table; NULL otherwise. If the entry is present, its reference - counter is decremented if not saturated. If the counter reaches 0, the - value of the entry is dereferenced, and the entry is returned to the free - list.] - - SideEffects [None] - - SeeAlso [cuddHashTableLookup cuddHashTableLookup2 cuddHashTableLookup3 - cuddHashTableInsert1] - -******************************************************************************/ -DdNode * -cuddHashTableLookup1( - DdHashTable * hash, - DdNode * f) -{ - unsigned int posn; - DdHashItem *item, *prev; - -#ifdef DD_DEBUG - assert(hash->keysize == 1); -#endif - - posn = ddLCHash2(f,f,hash->shift); - item = hash->bucket[posn]; - prev = NULL; - - while (item != NULL) { - DdNodePtr *key = item->key; - if (f == key[0]) { - DdNode *value = item->value; - cuddSatDec(item->count); - if (item->count == 0) { - cuddDeref(value); - if (prev == NULL) { - hash->bucket[posn] = item->next; - } else { - prev->next = item->next; - } - item->next = hash->nextFree; - hash->nextFree = item; - hash->size--; - } - return(value); - } - prev = item; - item = item->next; - } - return(NULL); - -} /* end of cuddHashTableLookup1 */ - - -/**Function******************************************************************** - - Synopsis [Inserts an item in a hash table.] - - Description [Inserts an item in a hash table when the key is - composed of two pointers. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert3 - cuddHashTableLookup2] - -******************************************************************************/ -int -cuddHashTableInsert2( - DdHashTable * hash, - DdNode * f, - DdNode * g, - DdNode * value, - ptrint count) -{ - int result; - unsigned int posn; - DdHashItem *item; - -#ifdef DD_DEBUG - assert(hash->keysize == 2); -#endif - - if (hash->size > hash->maxsize) { - result = cuddHashTableResize(hash); - if (result == 0) return(0); - } - item = cuddHashTableAlloc(hash); - if (item == NULL) return(0); - hash->size++; - item->value = value; - cuddRef(value); - item->count = count; - item->key[0] = f; - item->key[1] = g; - posn = ddLCHash2(f,g,hash->shift); - item->next = hash->bucket[posn]; - hash->bucket[posn] = item; - - return(1); - -} /* end of cuddHashTableInsert2 */ - - -/**Function******************************************************************** - - Synopsis [Looks up a key consisting of two pointers in a hash table.] - - Description [Looks up a key consisting of two pointer in a hash table. - Returns the value associated to the key if there is an entry for the given - key in the table; NULL otherwise. If the entry is present, its reference - counter is decremented if not saturated. If the counter reaches 0, the - value of the entry is dereferenced, and the entry is returned to the free - list.] - - SideEffects [None] - - SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup3 - cuddHashTableInsert2] - -******************************************************************************/ -DdNode * -cuddHashTableLookup2( - DdHashTable * hash, - DdNode * f, - DdNode * g) -{ - unsigned int posn; - DdHashItem *item, *prev; - -#ifdef DD_DEBUG - assert(hash->keysize == 2); -#endif - - posn = ddLCHash2(f,g,hash->shift); - item = hash->bucket[posn]; - prev = NULL; - - while (item != NULL) { - DdNodePtr *key = item->key; - if ((f == key[0]) && (g == key[1])) { - DdNode *value = item->value; - cuddSatDec(item->count); - if (item->count == 0) { - cuddDeref(value); - if (prev == NULL) { - hash->bucket[posn] = item->next; - } else { - prev->next = item->next; - } - item->next = hash->nextFree; - hash->nextFree = item; - hash->size--; - } - return(value); - } - prev = item; - item = item->next; - } - return(NULL); - -} /* end of cuddHashTableLookup2 */ - - -/**Function******************************************************************** - - Synopsis [Inserts an item in a hash table.] - - Description [Inserts an item in a hash table when the key is - composed of three pointers. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert2 - cuddHashTableLookup3] - -******************************************************************************/ -int -cuddHashTableInsert3( - DdHashTable * hash, - DdNode * f, - DdNode * g, - DdNode * h, - DdNode * value, - ptrint count) -{ - int result; - unsigned int posn; - DdHashItem *item; - -#ifdef DD_DEBUG - assert(hash->keysize == 3); -#endif - - if (hash->size > hash->maxsize) { - result = cuddHashTableResize(hash); - if (result == 0) return(0); - } - item = cuddHashTableAlloc(hash); - if (item == NULL) return(0); - hash->size++; - item->value = value; - cuddRef(value); - item->count = count; - item->key[0] = f; - item->key[1] = g; - item->key[2] = h; - posn = ddLCHash3(f,g,h,hash->shift); - item->next = hash->bucket[posn]; - hash->bucket[posn] = item; - - return(1); - -} /* end of cuddHashTableInsert3 */ - - -/**Function******************************************************************** - - Synopsis [Looks up a key consisting of three pointers in a hash table.] - - Description [Looks up a key consisting of three pointers in a hash table. - Returns the value associated to the key if there is an entry for the given - key in the table; NULL otherwise. If the entry is present, its reference - counter is decremented if not saturated. If the counter reaches 0, the - value of the entry is dereferenced, and the entry is returned to the free - list.] - - SideEffects [None] - - SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup2 - cuddHashTableInsert3] - -******************************************************************************/ -DdNode * -cuddHashTableLookup3( - DdHashTable * hash, - DdNode * f, - DdNode * g, - DdNode * h) -{ - unsigned int posn; - DdHashItem *item, *prev; - -#ifdef DD_DEBUG - assert(hash->keysize == 3); -#endif - - posn = ddLCHash3(f,g,h,hash->shift); - item = hash->bucket[posn]; - prev = NULL; - - while (item != NULL) { - DdNodePtr *key = item->key; - if ((f == key[0]) && (g == key[1]) && (h == key[2])) { - DdNode *value = item->value; - cuddSatDec(item->count); - if (item->count == 0) { - cuddDeref(value); - if (prev == NULL) { - hash->bucket[posn] = item->next; - } else { - prev->next = item->next; - } - item->next = hash->nextFree; - hash->nextFree = item; - hash->size--; - } - return(value); - } - prev = item; - item = item->next; - } - return(NULL); - -} /* end of cuddHashTableLookup3 */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Resizes a local cache.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -cuddLocalCacheResize( - DdLocalCache * cache) -{ - DdLocalCacheItem *item, *olditem, *entry, *old; - int i, shift; - unsigned int posn; - unsigned int slots, oldslots; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - olditem = cache->item; - oldslots = cache->slots; - slots = cache->slots = oldslots << 1; - -#ifdef DD_VERBOSE - (void) fprintf(cache->manager->err, - "Resizing local cache from %d to %d entries\n", - oldslots, slots); - (void) fprintf(cache->manager->err, - "\thits = %.0f\tlookups = %.0f\thit ratio = %5.3f\n", - cache->hits, cache->lookUps, cache->hits / cache->lookUps); -#endif - - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - cache->item = item = - (DdLocalCacheItem *) ALLOC(char, slots * cache->itemsize); - MMoutOfMemory = saveHandler; - /* If we fail to allocate the new table we just give up. */ - if (item == NULL) { -#ifdef DD_VERBOSE - (void) fprintf(cache->manager->err,"Resizing failed. Giving up.\n"); -#endif - cache->slots = oldslots; - cache->item = olditem; - /* Do not try to resize again. */ - cache->maxslots = oldslots - 1; - return; - } - shift = --(cache->shift); - cache->manager->memused += (slots - oldslots) * cache->itemsize; - - /* Clear new cache. */ - memset(item, 0, slots * cache->itemsize); - - /* Copy from old cache to new one. */ - for (i = 0; (unsigned) i < oldslots; i++) { - old = (DdLocalCacheItem *) ((char *) olditem + i * cache->itemsize); - if (old->value != NULL) { - posn = ddLCHash(old->key,cache->keysize,slots); - entry = (DdLocalCacheItem *) ((char *) item + - posn * cache->itemsize); - memcpy(entry->key,old->key,cache->keysize*sizeof(DdNode *)); - entry->value = old->value; - } - } - - FREE(olditem); - - /* Reinitialize measurements so as to avoid division by 0 and - ** immediate resizing. - */ - cache->lookUps = (double) (int) (slots * cache->minHit + 1); - cache->hits = 0; - -} /* end of cuddLocalCacheResize */ - - -/**Function******************************************************************** - - Synopsis [Computes the hash value for a local cache.] - - Description [Computes the hash value for a local cache. Returns the - bucket index.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DD_INLINE -static unsigned int -ddLCHash( - DdNodePtr * key, - unsigned int keysize, - int shift) -{ - unsigned int val = (unsigned int) (ptrint) key[0]; - unsigned int i; - - for (i = 1; i < keysize; i++) { - val = val * DD_P1 + (int) (ptrint) key[i]; - } - - return(val >> shift); - -} /* end of ddLCHash */ - - -/**Function******************************************************************** - - Synopsis [Inserts a local cache in the manager list.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -cuddLocalCacheAddToList( - DdLocalCache * cache) -{ - DdManager *manager = cache->manager; - - cache->next = manager->localCaches; - manager->localCaches = cache; - return; - -} /* end of cuddLocalCacheAddToList */ - - -/**Function******************************************************************** - - Synopsis [Removes a local cache from the manager list.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -cuddLocalCacheRemoveFromList( - DdLocalCache * cache) -{ - DdManager *manager = cache->manager; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - DdLocalCache **prevCache, *nextCache; -#ifdef __osf__ -#pragma pointer_size restore -#endif - - prevCache = &(manager->localCaches); - nextCache = manager->localCaches; - - while (nextCache != NULL) { - if (nextCache == cache) { - *prevCache = nextCache->next; - return; - } - prevCache = &(nextCache->next); - nextCache = nextCache->next; - } - return; /* should never get here */ - -} /* end of cuddLocalCacheRemoveFromList */ - - -/**Function******************************************************************** - - Synopsis [Resizes a hash table.] - - Description [Resizes a hash table. Returns 1 if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddHashTableInsert] - -******************************************************************************/ -static int -cuddHashTableResize( - DdHashTable * hash) -{ - int j; - unsigned int posn; - DdHashItem *item; - DdHashItem *next; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - DdNode **key; - int numBuckets; - DdHashItem **buckets; - DdHashItem **oldBuckets = hash->bucket; -#ifdef __osf__ -#pragma pointer_size restore -#endif - int shift; - int oldNumBuckets = hash->numBuckets; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - /* Compute the new size of the table. */ - numBuckets = oldNumBuckets << 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - buckets = ALLOC(DdHashItem *, numBuckets); - MMoutOfMemory = saveHandler; - if (buckets == NULL) { - hash->maxsize <<= 1; - return(1); - } - - hash->bucket = buckets; - hash->numBuckets = numBuckets; - shift = --(hash->shift); - hash->maxsize <<= 1; - memset(buckets, 0, numBuckets * sizeof(DdHashItem *)); -#ifdef __osf__ -#pragma pointer_size restore -#endif - if (hash->keysize == 1) { - for (j = 0; j < oldNumBuckets; j++) { - item = oldBuckets[j]; - while (item != NULL) { - next = item->next; - key = item->key; - posn = ddLCHash2(key[0], key[0], shift); - item->next = buckets[posn]; - buckets[posn] = item; - item = next; - } - } - } else if (hash->keysize == 2) { - for (j = 0; j < oldNumBuckets; j++) { - item = oldBuckets[j]; - while (item != NULL) { - next = item->next; - key = item->key; - posn = ddLCHash2(key[0], key[1], shift); - item->next = buckets[posn]; - buckets[posn] = item; - item = next; - } - } - } else if (hash->keysize == 3) { - for (j = 0; j < oldNumBuckets; j++) { - item = oldBuckets[j]; - while (item != NULL) { - next = item->next; - key = item->key; - posn = ddLCHash3(key[0], key[1], key[2], shift); - item->next = buckets[posn]; - buckets[posn] = item; - item = next; - } - } - } else { - for (j = 0; j < oldNumBuckets; j++) { - item = oldBuckets[j]; - while (item != NULL) { - next = item->next; - posn = ddLCHash(item->key, hash->keysize, shift); - item->next = buckets[posn]; - buckets[posn] = item; - item = next; - } - } - } - FREE(oldBuckets); - return(1); - -} /* end of cuddHashTableResize */ - - -/**Function******************************************************************** - - Synopsis [Fast storage allocation for items in a hash table.] - - Description [Fast storage allocation for items in a hash table. The - first 4 bytes of a chunk contain a pointer to the next block; the - rest contains DD_MEM_CHUNK spaces for hash items. Returns a pointer to - a new item if successful; NULL is memory is full.] - - SideEffects [None] - - SeeAlso [cuddAllocNode cuddDynamicAllocNode] - -******************************************************************************/ -DD_INLINE -static DdHashItem * -cuddHashTableAlloc( - DdHashTable * hash) -{ - int i; - unsigned int itemsize = hash->itemsize; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - DdHashItem **mem, *thisOne, *next, *item; - - if (hash->nextFree == NULL) { - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); - MMoutOfMemory = saveHandler; -#ifdef __osf__ -#pragma pointer_size restore -#endif - if (mem == NULL) { - if (hash->manager->stash != NULL) { - FREE(hash->manager->stash); - hash->manager->stash = NULL; - /* Inhibit resizing of tables. */ - hash->manager->maxCacheHard = hash->manager->cacheSlots - 1; - hash->manager->cacheSlack = -(hash->manager->cacheSlots + 1); - for (i = 0; i < hash->manager->size; i++) { - hash->manager->subtables[i].maxKeys <<= 2; - } - hash->manager->gcFrac = 0.2; - hash->manager->minDead = - (unsigned) (0.2 * (double) hash->manager->slots); -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); -#ifdef __osf__ -#pragma pointer_size restore -#endif - } - if (mem == NULL) { - (*MMoutOfMemory)((DD_MEM_CHUNK + 1) * itemsize); - hash->manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - } - - mem[0] = (DdHashItem *) hash->memoryList; - hash->memoryList = mem; - - thisOne = (DdHashItem *) ((char *) mem + itemsize); - hash->nextFree = thisOne; - for (i = 1; i < DD_MEM_CHUNK; i++) { - next = (DdHashItem *) ((char *) thisOne + itemsize); - thisOne->next = next; - thisOne = next; - } - - thisOne->next = NULL; - - } - item = hash->nextFree; - hash->nextFree = item->next; - return(item); - -} /* end of cuddHashTableAlloc */ diff --git a/src/bdd/cudd/cuddLevelQ.c b/src/bdd/cudd/cuddLevelQ.c deleted file mode 100644 index 3cc8e8d8..00000000 --- a/src/bdd/cudd/cuddLevelQ.c +++ /dev/null @@ -1,533 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddLevelQ.c] - - PackageName [cudd] - - Synopsis [Procedure to manage level queues.] - - Description [The functions in this file allow an application to - easily manipulate a queue where nodes are prioritized by level. The - emphasis is on efficiency. Therefore, the queue items can have - variable size. If the application does not need to attach - information to the nodes, it can declare the queue items to be of - type DdQueueItem. Otherwise, it can declare them to be of a - structure type such that the first three fields are data - pointers. The third pointer points to the node. The first two - pointers are used by the level queue functions. The remaining fields - are initialized to 0 when a new item is created, and are then left - to the exclusive use of the application. On the DEC Alphas the three - pointers must be 32-bit pointers when CUDD is compiled with 32-bit - pointers. The level queue functions make sure that each node - appears at most once in the queue. They do so by keeping a hash - table where the node is used as key. Queue items are recycled via a - free list for efficiency. - - Internal procedures provided by this module: - <ul> - <li> cuddLevelQueueInit() - <li> cuddLevelQueueQuit() - <li> cuddLevelQueueEnqueue() - <li> cuddLevelQueueDequeue() - </ul> - Static procedures included in this module: - <ul> - <li> hashLookup() - <li> hashInsert() - <li> hashDelete() - <li> hashResize() - </ul> - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no - warranty about the suitability of this software for any - purpose. It is presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddLevelQ.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**Macro*********************************************************************** - - Synopsis [Hash function for the table of a level queue.] - - Description [Hash function for the table of a level queue.] - - SideEffects [None] - - SeeAlso [hashInsert hashLookup hashDelete] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define lqHash(key,shift) \ -(((unsigned)(unsigned long)(key) * DD_P1) >> (shift)) -#else -#define lqHash(key,shift) \ -(((unsigned)(key) * DD_P1) >> (shift)) -#endif - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdQueueItem * hashLookup ARGS((DdLevelQueue *queue, void *key)); -static int hashInsert ARGS((DdLevelQueue *queue, DdQueueItem *item)); -static void hashDelete ARGS((DdLevelQueue *queue, DdQueueItem *item)); -static int hashResize ARGS((DdLevelQueue *queue)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Initializes a level queue.] - - Description [Initializes a level queue. A level queue is a queue - where inserts are based on the levels of the nodes. Within each - level the policy is FIFO. Level queues are useful in traversing a - BDD top-down. Queue items are kept in a free list when dequeued for - efficiency. Returns a pointer to the new queue if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueQuit cuddLevelQueueEnqueue cuddLevelQueueDequeue] - -******************************************************************************/ -DdLevelQueue * -cuddLevelQueueInit( - int levels /* number of levels */, - int itemSize /* size of the item */, - int numBuckets /* initial number of hash buckets */) -{ - DdLevelQueue *queue; - int logSize; - - queue = ALLOC(DdLevelQueue,1); - if (queue == NULL) - return(NULL); -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - /* Keep pointers to the insertion points for all levels. */ - queue->last = ALLOC(DdQueueItem *, levels); -#ifdef __osf__ -#pragma pointer_size restore -#endif - if (queue->last == NULL) { - FREE(queue); - return(NULL); - } - /* Use a hash table to test for uniqueness. */ - if (numBuckets < 2) numBuckets = 2; - logSize = cuddComputeFloorLog2(numBuckets); - queue->numBuckets = 1 << logSize; - queue->shift = sizeof(int) * 8 - logSize; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - queue->buckets = ALLOC(DdQueueItem *, queue->numBuckets); -#ifdef __osf__ -#pragma pointer_size restore -#endif - if (queue->buckets == NULL) { - FREE(queue->last); - FREE(queue); - return(NULL); - } -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - memset(queue->last, 0, levels * sizeof(DdQueueItem *)); - memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *)); -#ifdef __osf__ -#pragma pointer_size restore -#endif - queue->first = NULL; - queue->freelist = NULL; - queue->levels = levels; - queue->itemsize = itemSize; - queue->size = 0; - queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY; - return(queue); - -} /* end of cuddLevelQueueInit */ - - -/**Function******************************************************************** - - Synopsis [Shuts down a level queue.] - - Description [Shuts down a level queue and releases all the - associated memory.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueInit] - -******************************************************************************/ -void -cuddLevelQueueQuit( - DdLevelQueue * queue) -{ - DdQueueItem *item; - - while (queue->freelist != NULL) { - item = queue->freelist; - queue->freelist = item->next; - FREE(item); - } - while (queue->first != NULL) { - item = (DdQueueItem *) queue->first; - queue->first = item->next; - FREE(item); - } - FREE(queue->buckets); - FREE(queue->last); - FREE(queue); - return; - -} /* end of cuddLevelQueueQuit */ - - -/**Function******************************************************************** - - Synopsis [Inserts a new key in a level queue.] - - Description [Inserts a new key in a level queue. A new entry is - created in the queue only if the node is not already - enqueued. Returns a pointer to the queue item if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueInit cuddLevelQueueDequeue] - -******************************************************************************/ -void * -cuddLevelQueueEnqueue( - DdLevelQueue * queue /* level queue */, - void * key /* key to be enqueued */, - int level /* level at which to insert */) -{ - int plevel; - DdQueueItem *item; - -#ifdef DD_DEBUG - assert(level < queue->levels); -#endif - /* Check whether entry for this node exists. */ - item = hashLookup(queue,key); - if (item != NULL) return(item); - - /* Get a free item from either the free list or the memory manager. */ - if (queue->freelist == NULL) { - item = (DdQueueItem *) ALLOC(char, queue->itemsize); - if (item == NULL) - return(NULL); - } else { - item = queue->freelist; - queue->freelist = item->next; - } - /* Initialize. */ - memset(item, 0, queue->itemsize); - item->key = key; - /* Update stats. */ - queue->size++; - - if (queue->last[level]) { - /* There are already items for this level in the queue. */ - item->next = queue->last[level]->next; - queue->last[level]->next = item; - } else { - /* There are no items at the current level. Look for the first - ** non-empty level preceeding this one. */ - plevel = level; - while (plevel != 0 && queue->last[plevel] == NULL) - plevel--; - if (queue->last[plevel] == NULL) { - /* No element precedes this one in the queue. */ - item->next = (DdQueueItem *) queue->first; - queue->first = item; - } else { - item->next = queue->last[plevel]->next; - queue->last[plevel]->next = item; - } - } - queue->last[level] = item; - - /* Insert entry for the key in the hash table. */ - if (hashInsert(queue,item) == 0) { - return(NULL); - } - return(item); - -} /* end of cuddLevelQueueEnqueue */ - - -/**Function******************************************************************** - - Synopsis [Remove an item from the front of a level queue.] - - Description [Remove an item from the front of a level queue.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueEnqueue] - -******************************************************************************/ -void -cuddLevelQueueDequeue( - DdLevelQueue * queue, - int level) -{ - DdQueueItem *item = (DdQueueItem *) queue->first; - - /* Delete from the hash table. */ - hashDelete(queue,item); - - /* Since we delete from the front, if this is the last item for - ** its level, there are no other items for the same level. */ - if (queue->last[level] == item) - queue->last[level] = NULL; - - queue->first = item->next; - /* Put item on the free list. */ - item->next = queue->freelist; - queue->freelist = item; - /* Update stats. */ - queue->size--; - return; - -} /* end of cuddLevelQueueDequeue */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Looks up a key in the hash table of a level queue.] - - Description [Looks up a key in the hash table of a level queue. Returns - a pointer to the item with the given key if the key is found; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueEnqueue hashInsert] - -******************************************************************************/ -static DdQueueItem * -hashLookup( - DdLevelQueue * queue, - void * key) -{ - int posn; - DdQueueItem *item; - - posn = lqHash(key,queue->shift); - item = queue->buckets[posn]; - - while (item != NULL) { - if (item->key == key) { - return(item); - } - item = item->cnext; - } - return(NULL); - -} /* end of hashLookup */ - - -/**Function******************************************************************** - - Synopsis [Inserts an item in the hash table of a level queue.] - - Description [Inserts an item in the hash table of a level queue. Returns - 1 if successful; 0 otherwise. No check is performed to see if an item with - the same key is already in the hash table.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueEnqueue] - -******************************************************************************/ -static int -hashInsert( - DdLevelQueue * queue, - DdQueueItem * item) -{ - int result; - int posn; - - if (queue->size > queue->maxsize) { - result = hashResize(queue); - if (result == 0) return(0); - } - - posn = lqHash(item->key,queue->shift); - item->cnext = queue->buckets[posn]; - queue->buckets[posn] = item; - - return(1); - -} /* end of hashInsert */ - - -/**Function******************************************************************** - - Synopsis [Removes an item from the hash table of a level queue.] - - Description [Removes an item from the hash table of a level queue. - Nothing is done if the item is not in the table.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueDequeue hashInsert] - -******************************************************************************/ -static void -hashDelete( - DdLevelQueue * queue, - DdQueueItem * item) -{ - int posn; - DdQueueItem *prevItem; - - posn = lqHash(item->key,queue->shift); - prevItem = queue->buckets[posn]; - - if (prevItem == NULL) return; - if (prevItem == item) { - queue->buckets[posn] = prevItem->cnext; - return; - } - - while (prevItem->cnext != NULL) { - if (prevItem->cnext == item) { - prevItem->cnext = item->cnext; - return; - } - prevItem = prevItem->cnext; - } - return; - -} /* end of hashDelete */ - - -/**Function******************************************************************** - - Synopsis [Resizes the hash table of a level queue.] - - Description [Resizes the hash table of a level queue. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [hashInsert] - -******************************************************************************/ -static int -hashResize( - DdLevelQueue * queue) -{ - int j; - int posn; - DdQueueItem *item; - DdQueueItem *next; - int numBuckets; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - DdQueueItem **buckets; - DdQueueItem **oldBuckets = queue->buckets; -#ifdef __osf__ -#pragma pointer_size restore -#endif - int shift; - int oldNumBuckets = queue->numBuckets; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - /* Compute the new size of the subtable. */ - numBuckets = oldNumBuckets << 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - buckets = queue->buckets = ALLOC(DdQueueItem *, numBuckets); - if (buckets == NULL) { - queue->maxsize <<= 1; - return(1); - } - - queue->numBuckets = numBuckets; - shift = --(queue->shift); - queue->maxsize <<= 1; - memset(buckets, 0, numBuckets * sizeof(DdQueueItem *)); -#ifdef __osf__ -#pragma pointer_size restore -#endif - for (j = 0; j < oldNumBuckets; j++) { - item = oldBuckets[j]; - while (item != NULL) { - next = item->cnext; - posn = lqHash(item->key, shift); - item->cnext = buckets[posn]; - buckets[posn] = item; - item = next; - } - } - FREE(oldBuckets); - return(1); - -} /* end of hashResize */ diff --git a/src/bdd/cudd/cuddLinear.c b/src/bdd/cudd/cuddLinear.c deleted file mode 100644 index 7f6b3678..00000000 --- a/src/bdd/cudd/cuddLinear.c +++ /dev/null @@ -1,1333 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddLinear.c] - - PackageName [cudd] - - Synopsis [Functions for DD reduction by linear transformations.] - - Description [ Internal procedures included in this module: - <ul> - <li> cuddLinearAndSifting() - </ul> - Static procedures included in this module: - <ul> - <li> ddLinearUniqueCompare() - <li> ddLinearAndSiftingAux() - <li> ddLinearAndSiftingUp() - <li> ddLinearAndSiftingDown() - <li> ddLinearAndSiftingBackward() - <li> ddUndoMoves() - <li> ddUpdateInteractionMatrix() - <li> cuddLinearInPlace() - <li> cuddInitLinear() - <li> cuddResizeLinear() - <li> cuddXorLinear() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define CUDD_SWAP_MOVE 0 -#define CUDD_LINEAR_TRANSFORM_MOVE 1 -#define CUDD_INVERSE_TRANSFORM_MOVE 2 -#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: cuddLinear.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -static int *entry; - -#ifdef DD_STATS -extern int ddTotalNumberSwapping; -extern int ddTotalNISwaps; -static int ddTotalNumberLinearTr; -#endif - -#ifdef DD_DEBUG -static int zero = 0; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddLinearUniqueCompare ARGS((int *ptrX, int *ptrY)); -static int ddLinearAndSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static Move * ddLinearAndSiftingUp ARGS((DdManager *table, int y, int xLow, Move *prevMoves)); -static Move * ddLinearAndSiftingDown ARGS((DdManager *table, int x, int xHigh, Move *prevMoves)); -static int ddLinearAndSiftingBackward ARGS((DdManager *table, int size, Move *moves)); -static Move* ddUndoMoves ARGS((DdManager *table, Move *moves)); -static int cuddLinearInPlace ARGS((DdManager *table, int x, int y)); -static void ddUpdateInteractionMatrix ARGS((DdManager *table, int xindex, int yindex)); -static int cuddInitLinear ARGS((DdManager *table)); -static int cuddResizeLinear ARGS((DdManager *table)); -static void cuddXorLinear ARGS((DdManager *table, int x, int y)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints the linear transform matrix.] - - Description [Prints the linear transform matrix. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_PrintLinear( - DdManager * table) -{ - int i,j,k; - int retval; - int nvars = table->linearSize; - int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; - long word; - - for (i = 0; i < nvars; i++) { - for (j = 0; j < wordsPerRow; j++) { - word = table->linear[i*wordsPerRow + j]; - for (k = 0; k < BPL; k++) { - retval = fprintf(table->out,"%ld",word & 1); - if (retval == 0) return(0); - word >>= 1; - } - } - retval = fprintf(table->out,"\n"); - if (retval == 0) return(0); - } - return(1); - -} /* end of Cudd_PrintLinear */ - - -/**Function******************************************************************** - - Synopsis [Reads an entry of the linear transform matrix.] - - Description [Reads an entry of the linear transform matrix.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_ReadLinear( - DdManager * table /* CUDD manager */, - int x /* row index */, - int y /* column index */) -{ - int nvars = table->size; - int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; - long word; - int bit; - int result; - - assert(table->size == table->linearSize); - - word = wordsPerRow * x + (y >> LOGBPL); - bit = y & (BPL-1); - result = (int) ((table->linear[word] >> bit) & 1); - return(result); - -} /* end of Cudd_ReadLinear */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [BDD reduction based on combination of sifting and linear - transformations.] - - Description [BDD reduction based on combination of sifting and linear - transformations. Assumes that no dead nodes are present. - <ol> - <li> Order all the variables according to the number of entries - in each unique table. - <li> Sift the variable up and down, remembering each time the - total size of the DD heap. At each position, linear transformation - of the two adjacent variables is tried and is accepted if it reduces - the size of the DD. - <li> Select the best permutation. - <li> Repeat 3 and 4 for all variables. - </ol> - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddLinearAndSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; -#ifdef DD_STATS - int previousSize; -#endif - -#ifdef DD_STATS - ddTotalNumberLinearTr = 0; -#endif - - size = table->size; - - var = NULL; - entry = NULL; - if (table->linear == NULL) { - result = cuddInitLinear(table); - if (result == 0) goto cuddLinearAndSiftingOutOfMem; -#if 0 - (void) fprintf(table->out,"\n"); - result = Cudd_PrintLinear(table); - if (result == 0) goto cuddLinearAndSiftingOutOfMem; -#endif - } else if (table->size != table->linearSize) { - result = cuddResizeLinear(table); - if (result == 0) goto cuddLinearAndSiftingOutOfMem; -#if 0 - (void) fprintf(table->out,"\n"); - result = Cudd_PrintLinear(table); - if (result == 0) goto cuddLinearAndSiftingOutOfMem; -#endif - } - - /* Find order in which to sift variables. */ - entry = ALLOC(int,size); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddLinearAndSiftingOutOfMem; - } - var = ALLOC(int,size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddLinearAndSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->perm[i]; - entry[i] = table->subtables[x].keys; - var[i] = i; - } - - qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddLinearUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { - x = table->perm[var[i]]; - if (x < lower || x > upper) continue; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddLinearAndSiftingAux(table,x,lower,upper); - if (!result) goto cuddLinearAndSiftingOutOfMem; -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"+"); /* should never happen */ - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif -#ifdef DD_DEBUG - (void) Cudd_DebugCheck(table); -#endif - } - - FREE(var); - FREE(entry); - -#ifdef DD_STATS - (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.", - ddTotalNumberLinearTr); -#endif - - return(1); - -cuddLinearAndSiftingOutOfMem: - - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddLinearAndSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the - variables according to the number of keys in the subtables. - Returns the difference in number of keys between the two - variables being compared.] - - SideEffects [None] - -******************************************************************************/ -static int -ddLinearUniqueCompare( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of ddLinearUniqueCompare */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. At each step a linear transformation is tried, and, if it - decreases the size of the DD, it is accepted. Finds the best position - and does the required changes. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddLinearAndSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - - Move *move; - Move *moveUp; /* list of up moves */ - Move *moveDown; /* list of down moves */ - int initialSize; - int result; - - initialSize = table->keys - table->isolated; - - moveDown = NULL; - moveUp = NULL; - - if (x == xLow) { - moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); - /* At this point x --> xHigh unless bounding occurred. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddLinearAndSiftingBackward(table,initialSize,moveDown); - if (!result) goto ddLinearAndSiftingAuxOutOfMem; - - } else if (x == xHigh) { - moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); - /* At this point x --> xLow unless bounding occurred. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddLinearAndSiftingBackward(table,initialSize,moveUp); - if (!result) goto ddLinearAndSiftingAuxOutOfMem; - - } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ - moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); - /* At this point x --> xHigh unless bounding occurred. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - moveUp = ddUndoMoves(table,moveDown); -#ifdef DD_DEBUG - assert(moveUp == NULL || moveUp->x == x); -#endif - moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp); - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddLinearAndSiftingBackward(table,initialSize,moveUp); - if (!result) goto ddLinearAndSiftingAuxOutOfMem; - - } else { /* must go up first: shorter */ - moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); - /* At this point x --> xLow unless bounding occurred. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - moveDown = ddUndoMoves(table,moveUp); -#ifdef DD_DEBUG - assert(moveDown == NULL || moveDown->y == x); -#endif - moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown); - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddLinearAndSiftingBackward(table,initialSize,moveDown); - if (!result) goto ddLinearAndSiftingAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - - return(1); - -ddLinearAndSiftingAuxOutOfMem: - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - - return(0); - -} /* end of ddLinearAndSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable up and applies linear transformations.] - - Description [Sifts a variable up and applies linear transformations. - Moves y up until either it reaches the bound (xLow) or the size of - the DD heap increases too much. Returns the set of moves in case of - success; NULL if memory is full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddLinearAndSiftingUp( - DdManager * table, - int y, - int xLow, - Move * prevMoves) -{ - Move *moves; - Move *move; - int x; - int size, newsize; - int limitSize; - int xindex, yindex; - int isolated; - int L; /* lower bound on DD size */ -#ifdef DD_DEBUG - int checkL; - int z; - int zindex; -#endif - - moves = prevMoves; - yindex = table->invperm[y]; - - /* Initialize the lower bound. - ** The part of the DD below y will not change. - ** The part of the DD above y that does not interact with y will not - ** change. The rest may vanish in the best case, except for - ** the nodes at level xLow, which will not vanish, regardless. - */ - limitSize = L = table->keys - table->isolated; - for (x = xLow + 1; x < y; x++) { - xindex = table->invperm[x]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L -= table->subtables[x].keys - isolated; - } - } - isolated = table->vars[yindex]->ref == 1; - L -= table->subtables[y].keys - isolated; - - x = cuddNextLow(table,y); - while (x >= xLow && L <= limitSize) { - xindex = table->invperm[x]; -#ifdef DD_DEBUG - checkL = table->keys - table->isolated; - for (z = xLow + 1; z < y; z++) { - zindex = table->invperm[z]; - if (cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - checkL -= table->subtables[z].keys - isolated; - } - } - isolated = table->vars[yindex]->ref == 1; - checkL -= table->subtables[y].keys - isolated; - if (L != checkL) { - (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L); - } -#endif - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddLinearAndSiftingUpOutOfMem; - newsize = cuddLinearInPlace(table,x,y); - if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddLinearAndSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->next = moves; - moves = move; - move->flags = CUDD_SWAP_MOVE; - if (newsize >= size) { - /* Undo transformation. The transformation we apply is - ** its own inverse. Hence, we just apply the transformation - ** again. - */ - newsize = cuddLinearInPlace(table,x,y); - if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; -#ifdef DD_DEBUG - if (newsize != size) { - (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); - } -#endif - } else if (cuddTestInteract(table,xindex,yindex)) { - size = newsize; - move->flags = CUDD_LINEAR_TRANSFORM_MOVE; - ddUpdateInteractionMatrix(table,xindex,yindex); - } - move->size = size; - /* Update the lower bound. */ - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L += table->subtables[y].keys - isolated; - } - if ((double) size > (double) limitSize * table->maxGrowth) break; - if (size < limitSize) limitSize = size; - y = x; - x = cuddNextLow(table,y); - } - return(moves); - -ddLinearAndSiftingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of ddLinearAndSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable down and applies linear transformations.] - - Description [Sifts a variable down and applies linear - transformations. Moves x down until either it reaches the bound - (xHigh) or the size of the DD heap increases too much. Returns the - set of moves in case of success; NULL if memory is full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddLinearAndSiftingDown( - DdManager * table, - int x, - int xHigh, - Move * prevMoves) -{ - Move *moves; - Move *move; - int y; - int size, newsize; - int R; /* upper bound on node decrease */ - int limitSize; - int xindex, yindex; - int isolated; -#ifdef DD_DEBUG - int checkR; - int z; - int zindex; -#endif - - moves = prevMoves; - /* Initialize R */ - xindex = table->invperm[x]; - limitSize = size = table->keys - table->isolated; - R = 0; - for (y = xHigh; y > x; y--) { - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R += table->subtables[y].keys - isolated; - } - } - - y = cuddNextHigh(table,x); - while (y <= xHigh && size - R < limitSize) { -#ifdef DD_DEBUG - checkR = 0; - for (z = xHigh; z > x; z--) { - zindex = table->invperm[z]; - if (cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - checkR += table->subtables[z].keys - isolated; - } - } - if (R != checkR) { - (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R); - } -#endif - /* Update upper bound on node decrease. */ - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R -= table->subtables[y].keys - isolated; - } - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddLinearAndSiftingDownOutOfMem; - newsize = cuddLinearInPlace(table,x,y); - if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddLinearAndSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->next = moves; - moves = move; - move->flags = CUDD_SWAP_MOVE; - if (newsize >= size) { - /* Undo transformation. The transformation we apply is - ** its own inverse. Hence, we just apply the transformation - ** again. - */ - newsize = cuddLinearInPlace(table,x,y); - if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; - if (newsize != size) { - (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); - } - } else if (cuddTestInteract(table,xindex,yindex)) { - size = newsize; - move->flags = CUDD_LINEAR_TRANSFORM_MOVE; - ddUpdateInteractionMatrix(table,xindex,yindex); - } - move->size = size; - if ((double) size > (double) limitSize * table->maxGrowth) break; - if (size < limitSize) limitSize = size; - x = y; - y = cuddNextHigh(table,x); - } - return(moves); - -ddLinearAndSiftingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of ddLinearAndSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the DD heap to the order - giving the minimum size.] - - Description [Given a set of moves, returns the DD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddLinearAndSiftingBackward( - DdManager * table, - int size, - Move * moves) -{ - Move *move; - int res; - - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { - res = cuddLinearInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - res = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { - res = cuddLinearInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - } - - return(1); - -} /* end of ddLinearAndSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the DD heap to the order - in effect before the moves.] - - Description [Given a set of moves, returns the DD heap to the - order in effect before the moves. Returns 1 in case of success; - 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static Move* -ddUndoMoves( - DdManager * table, - Move * moves) -{ - Move *invmoves = NULL; - Move *move; - Move *invmove; - int size; - - for (move = moves; move != NULL; move = move->next) { - invmove = (Move *) cuddDynamicAllocNode(table); - if (invmove == NULL) goto ddUndoMovesOutOfMem; - invmove->x = move->x; - invmove->y = move->y; - invmove->next = invmoves; - invmoves = invmove; - if (move->flags == CUDD_SWAP_MOVE) { - invmove->flags = CUDD_SWAP_MOVE; - size = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto ddUndoMovesOutOfMem; - } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { - invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; - size = cuddLinearInPlace(table,(int)move->x,(int)move->y); - if (!size) goto ddUndoMovesOutOfMem; - size = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto ddUndoMovesOutOfMem; - } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ -#ifdef DD_DEBUG - (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); -#endif - invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; - size = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto ddUndoMovesOutOfMem; - size = cuddLinearInPlace(table,(int)move->x,(int)move->y); - if (!size) goto ddUndoMovesOutOfMem; - } - invmove->size = size; - } - - return(invmoves); - -ddUndoMovesOutOfMem: - while (invmoves != NULL) { - move = invmoves->next; - cuddDeallocNode(table, (DdNode *) invmoves); - invmoves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of ddUndoMoves */ - - -/**Function******************************************************************** - - Synopsis [Linearly combines two adjacent variables.] - - Description [Linearly combines two adjacent variables. Specifically, - replaces the top variable with the exclusive nor of the two variables. - It assumes that no dead nodes are present on entry to this - procedure. The procedure then guarantees that no dead nodes will be - present when it terminates. cuddLinearInPlace assumes that x < - y. Returns the number of keys in the table if successful; 0 - otherwise.] - - SideEffects [The two subtables corrresponding to variables x and y are - modified. The global counters of the unique table are also affected.] - - SeeAlso [cuddSwapInPlace] - -******************************************************************************/ -static int -cuddLinearInPlace( - DdManager * table, - int x, - int y) -{ - DdNodePtr *xlist, *ylist; - int xindex, yindex; - int xslots, yslots; - int xshift, yshift; - int oldxkeys, oldykeys; - int newxkeys, newykeys; - int comple, newcomplement; - int i; - int posn; - int isolated; - DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; - DdNode *g,*next,*last; - DdNodePtr *previousP; - DdNode *tmp; - DdNode *sentinel = &(table->sentinel); -#if DD_DEBUG - int count, idcheck; -#endif - -#ifdef DD_DEBUG - assert(x < y); - assert(cuddNextHigh(table,x) == y); - assert(table->subtables[x].keys != 0); - assert(table->subtables[y].keys != 0); - assert(table->subtables[x].dead == 0); - assert(table->subtables[y].dead == 0); -#endif - - xindex = table->invperm[x]; - yindex = table->invperm[y]; - - if (cuddTestInteract(table,xindex,yindex)) { -#ifdef DD_STATS - ddTotalNumberLinearTr++; -#endif - /* Get parameters of x subtable. */ - xlist = table->subtables[x].nodelist; - oldxkeys = table->subtables[x].keys; - xslots = table->subtables[x].slots; - xshift = table->subtables[x].shift; - - /* Get parameters of y subtable. */ - ylist = table->subtables[y].nodelist; - oldykeys = table->subtables[y].keys; - yslots = table->subtables[y].slots; - yshift = table->subtables[y].shift; - - newxkeys = 0; - newykeys = oldykeys; - - /* Check whether the two projection functions involved in this - ** swap are isolated. At the end, we'll be able to tell how many - ** isolated projection functions are there by checking only these - ** two functions again. This is done to eliminate the isolated - ** projection functions from the node count. - */ - isolated = - ((table->vars[xindex]->ref == 1) + - (table->vars[yindex]->ref == 1)); - - /* The nodes in the x layer are put in a chain. - ** The chain is handled as a FIFO; g points to the beginning and - ** last points to the end. - */ - g = NULL; - for (i = 0; i < xslots; i++) { - f = xlist[i]; - if (f == sentinel) continue; - xlist[i] = sentinel; - if (g == NULL) { - g = f; - } else { - last->next = f; - } - while ((next = f->next) != sentinel) { - f = next; - } /* while there are elements in the collision chain */ - last = f; - } /* for each slot of the x subtable */ - last->next = NULL; - -#ifdef DD_COUNT - table->swapSteps += oldxkeys; -#endif - /* Take care of the x nodes that must be re-expressed. - ** They form a linked list pointed by g. - */ - f = g; - while (f != NULL) { - next = f->next; - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(f1))); -#endif - if ((int) f1->index == yindex) { - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - f11 = f10 = f1; - } -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(f11))); -#endif - f0 = cuddE(f); - comple = Cudd_IsComplement(f0); - f0 = Cudd_Regular(f0); - if ((int) f0->index == yindex) { - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = f00 = f0; - } - if (comple) { - f01 = Cudd_Not(f01); - f00 = Cudd_Not(f00); - } - /* Decrease ref count of f1. */ - cuddSatDec(f1->ref); - /* Create the new T child. */ - if (f11 == f00) { - newf1 = f11; - cuddSatInc(newf1->ref); - } else { - /* Check ylist for triple (yindex,f11,f00). */ - posn = ddHash(f11, f00, yshift); - /* For each element newf1 in collision list ylist[posn]. */ - previousP = &(ylist[posn]); - newf1 = *previousP; - while (f11 < cuddT(newf1)) { - previousP = &(newf1->next); - newf1 = *previousP; - } - while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) { - previousP = &(newf1->next); - newf1 = *previousP; - } - if (cuddT(newf1) == f11 && cuddE(newf1) == f00) { - cuddSatInc(newf1->ref); - } else { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto cuddLinearOutOfMem; - newf1->index = yindex; newf1->ref = 1; - cuddT(newf1) = f11; - cuddE(newf1) = f00; - /* Insert newf1 in the collision list ylist[posn]; - ** increase the ref counts of f11 and f00. - */ - newykeys++; - newf1->next = *previousP; - *previousP = newf1; - cuddSatInc(f11->ref); - tmp = Cudd_Regular(f00); - cuddSatInc(tmp->ref); - } - } - cuddT(f) = newf1; -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(newf1))); -#endif - - /* Do the same for f0, keeping complement dots into account. */ - /* decrease ref count of f0 */ - tmp = Cudd_Regular(f0); - cuddSatDec(tmp->ref); - /* create the new E child */ - if (f01 == f10) { - newf0 = f01; - tmp = Cudd_Regular(newf0); - cuddSatInc(tmp->ref); - } else { - /* make sure f01 is regular */ - newcomplement = Cudd_IsComplement(f01); - if (newcomplement) { - f01 = Cudd_Not(f01); - f10 = Cudd_Not(f10); - } - /* Check ylist for triple (yindex,f01,f10). */ - posn = ddHash(f01, f10, yshift); - /* For each element newf0 in collision list ylist[posn]. */ - previousP = &(ylist[posn]); - newf0 = *previousP; - while (f01 < cuddT(newf0)) { - previousP = &(newf0->next); - newf0 = *previousP; - } - while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) { - previousP = &(newf0->next); - newf0 = *previousP; - } - if (cuddT(newf0) == f01 && cuddE(newf0) == f10) { - cuddSatInc(newf0->ref); - } else { /* no match */ - newf0 = cuddDynamicAllocNode(table); - if (newf0 == NULL) - goto cuddLinearOutOfMem; - newf0->index = yindex; newf0->ref = 1; - cuddT(newf0) = f01; - cuddE(newf0) = f10; - /* Insert newf0 in the collision list ylist[posn]; - ** increase the ref counts of f01 and f10. - */ - newykeys++; - newf0->next = *previousP; - *previousP = newf0; - cuddSatInc(f01->ref); - tmp = Cudd_Regular(f10); - cuddSatInc(tmp->ref); - } - if (newcomplement) { - newf0 = Cudd_Not(newf0); - } - } - cuddE(f) = newf0; - - /* Re-insert the modified f in xlist. - ** The modified f does not already exists in xlist. - ** (Because of the uniqueness of the cofactors.) - */ - posn = ddHash(newf1, newf0, xshift); - newxkeys++; - previousP = &(xlist[posn]); - tmp = *previousP; - while (newf1 < cuddT(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - f->next = *previousP; - *previousP = f; - f = next; - } /* while f != NULL */ - - /* GC the y layer. */ - - /* For each node f in ylist. */ - for (i = 0; i < yslots; i++) { - previousP = &(ylist[i]); - f = *previousP; - while (f != sentinel) { - next = f->next; - if (f->ref == 0) { - tmp = cuddT(f); - cuddSatDec(tmp->ref); - tmp = Cudd_Regular(cuddE(f)); - cuddSatDec(tmp->ref); - cuddDeallocNode(table,f); - newykeys--; - } else { - *previousP = f; - previousP = &(f->next); - } - f = next; - } /* while f */ - *previousP = sentinel; - } /* for every collision list */ - -#if DD_DEBUG -#if 0 - (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y); -#endif - count = 0; - idcheck = 0; - for (i = 0; i < yslots; i++) { - f = ylist[i]; - while (f != sentinel) { - count++; - if (f->index != (DdHalfWord) yindex) - idcheck++; - f = f->next; - } - } - if (count != newykeys) { - fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count); - } - if (idcheck != 0) - fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck); - count = 0; - idcheck = 0; - for (i = 0; i < xslots; i++) { - f = xlist[i]; - while (f != sentinel) { - count++; - if (f->index != (DdHalfWord) xindex) - idcheck++; - f = f->next; - } - } - if (count != newxkeys || newxkeys != oldxkeys) { - fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count); - } - if (idcheck != 0) - fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck); -#endif - - isolated += (table->vars[xindex]->ref == 1) + - (table->vars[yindex]->ref == 1); - table->isolated += isolated; - - /* Set the appropriate fields in table. */ - table->subtables[y].keys = newykeys; - - /* Here we should update the linear combination table - ** to record that x <- x EXNOR y. This is done by complementing - ** the (x,y) entry of the table. - */ - - table->keys += newykeys - oldykeys; - - cuddXorLinear(table,xindex,yindex); - } - -#ifdef DD_DEBUG - if (zero) { - (void) Cudd_DebugCheck(table); - } -#endif - - return(table->keys - table->isolated); - -cuddLinearOutOfMem: - (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n"); - - return (0); - -} /* end of cuddLinearInPlace */ - - -/**Function******************************************************************** - - Synopsis [Updates the interaction matrix.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static void -ddUpdateInteractionMatrix( - DdManager * table, - int xindex, - int yindex) -{ - int i; - for (i = 0; i < yindex; i++) { - if (i != xindex && cuddTestInteract(table,i,yindex)) { - if (i < xindex) { - cuddSetInteract(table,i,xindex); - } else { - cuddSetInteract(table,xindex,i); - } - } - } - for (i = yindex+1; i < table->size; i++) { - if (i != xindex && cuddTestInteract(table,yindex,i)) { - if (i < xindex) { - cuddSetInteract(table,i,xindex); - } else { - cuddSetInteract(table,xindex,i); - } - } - } - -} /* end of ddUpdateInteractionMatrix */ - - -/**Function******************************************************************** - - Synopsis [Initializes the linear transform matrix.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static int -cuddInitLinear( - DdManager * table) -{ - int words; - int wordsPerRow; - int nvars; - int word; - int bit; - int i; - long *linear; - - nvars = table->size; - wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; - words = wordsPerRow * nvars; - table->linear = linear = ALLOC(long,words); - if (linear == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - table->memused += words * sizeof(long); - table->linearSize = nvars; - for (i = 0; i < words; i++) linear[i] = 0; - for (i = 0; i < nvars; i++) { - word = wordsPerRow * i + (i >> LOGBPL); - bit = i & (BPL-1); - linear[word] = 1 << bit; - } - return(1); - -} /* end of cuddInitLinear */ - - -/**Function******************************************************************** - - Synopsis [Resizes the linear transform matrix.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static int -cuddResizeLinear( - DdManager * table) -{ - int words,oldWords; - int wordsPerRow,oldWordsPerRow; - int nvars,oldNvars; - int word,oldWord; - int bit; - int i,j; - long *linear,*oldLinear; - - oldNvars = table->linearSize; - oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1; - oldWords = oldWordsPerRow * oldNvars; - oldLinear = table->linear; - - nvars = table->size; - wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; - words = wordsPerRow * nvars; - table->linear = linear = ALLOC(long,words); - if (linear == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - table->memused += (words - oldWords) * sizeof(long); - for (i = 0; i < words; i++) linear[i] = 0; - - /* Copy old matrix. */ - for (i = 0; i < oldNvars; i++) { - for (j = 0; j < oldWordsPerRow; j++) { - oldWord = oldWordsPerRow * i + j; - word = wordsPerRow * i + j; - linear[word] = oldLinear[oldWord]; - } - } - FREE(oldLinear); - - /* Add elements to the diagonal. */ - for (i = oldNvars; i < nvars; i++) { - word = wordsPerRow * i + (i >> LOGBPL); - bit = i & (BPL-1); - linear[word] = 1 << bit; - } - table->linearSize = nvars; - - return(1); - -} /* end of cuddResizeLinear */ - - -/**Function******************************************************************** - - Synopsis [XORs two rows of the linear transform matrix.] - - Description [XORs two rows of the linear transform matrix and replaces - the first row with the result.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static void -cuddXorLinear( - DdManager * table, - int x, - int y) -{ - int i; - int nvars = table->size; - int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; - int xstart = wordsPerRow * x; - int ystart = wordsPerRow * y; - long *linear = table->linear; - - for (i = 0; i < wordsPerRow; i++) { - linear[xstart+i] ^= linear[ystart+i]; - } - -} /* end of cuddXorLinear */ - diff --git a/src/bdd/cudd/cuddLiteral.c b/src/bdd/cudd/cuddLiteral.c deleted file mode 100644 index 43740690..00000000 --- a/src/bdd/cudd/cuddLiteral.c +++ /dev/null @@ -1,237 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddLiteral.c] - - PackageName [cudd] - - Synopsis [Functions for manipulation of literal sets represented by - BDDs.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_bddLiteralSetIntersection() - </ul> - Internal procedures included in this file: - <ul> - <li> cuddBddLiteralSetIntersectionRecur() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddLiteral.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the intesection of two sets of literals - represented as BDDs.] - - Description [Computes the intesection of two sets of literals - represented as BDDs. Each set is represented as a cube of the - literals in the set. The empty set is represented by the constant 1. - No variable can be simultaneously present in both phases in a set. - Returns a pointer to the BDD representing the intersected sets, if - successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_bddLiteralSetIntersection( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddLiteralSetIntersectionRecur(dd,f,g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddLiteralSetIntersection */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of - Cudd_bddLiteralSetIntersection.] - - Description [Performs the recursive step of - Cudd_bddLiteralSetIntersection. Scans the cubes for common variables, - and checks whether they agree in phase. Returns a pointer to the - resulting cube if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -cuddBddLiteralSetIntersectionRecur( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res, *tmp; - DdNode *F, *G; - DdNode *fc, *gc; - DdNode *one; - DdNode *zero; - unsigned int topf, topg, comple; - int phasef, phaseg; - - statLine(dd); - if (f == g) return(f); - - F = Cudd_Regular(f); - G = Cudd_Regular(g); - one = DD_ONE(dd); - - /* Here f != g. If F == G, then f and g are complementary. - ** Since they are two cubes, this case only occurs when f == v, - ** g == v', and v is a variable or its complement. - */ - if (F == G) return(one); - - zero = Cudd_Not(one); - topf = cuddI(dd,F->index); - topg = cuddI(dd,G->index); - /* Look for a variable common to both cubes. If there are none, this - ** loop will stop when the constant node is reached in both cubes. - */ - while (topf != topg) { - if (topf < topg) { /* move down on f */ - comple = f != F; - f = cuddT(F); - if (comple) f = Cudd_Not(f); - if (f == zero) { - f = cuddE(F); - if (comple) f = Cudd_Not(f); - } - F = Cudd_Regular(f); - topf = cuddI(dd,F->index); - } else if (topg < topf) { - comple = g != G; - g = cuddT(G); - if (comple) g = Cudd_Not(g); - if (g == zero) { - g = cuddE(G); - if (comple) g = Cudd_Not(g); - } - G = Cudd_Regular(g); - topg = cuddI(dd,G->index); - } - } - - /* At this point, f == one <=> g == 1. It suffices to test one of them. */ - if (f == one) return(one); - - res = cuddCacheLookup2(dd,Cudd_bddLiteralSetIntersection,f,g); - if (res != NULL) { - return(res); - } - - /* Here f and g are both non constant and have the same top variable. */ - comple = f != F; - fc = cuddT(F); - phasef = 1; - if (comple) fc = Cudd_Not(fc); - if (fc == zero) { - fc = cuddE(F); - phasef = 0; - if (comple) fc = Cudd_Not(fc); - } - comple = g != G; - gc = cuddT(G); - phaseg = 1; - if (comple) gc = Cudd_Not(gc); - if (gc == zero) { - gc = cuddE(G); - phaseg = 0; - if (comple) gc = Cudd_Not(gc); - } - - tmp = cuddBddLiteralSetIntersectionRecur(dd,fc,gc); - if (tmp == NULL) { - return(NULL); - } - - if (phasef != phaseg) { - res = tmp; - } else { - cuddRef(tmp); - if (phasef == 0) { - res = cuddBddAndRecur(dd,Cudd_Not(dd->vars[F->index]),tmp); - } else { - res = cuddBddAndRecur(dd,dd->vars[F->index],tmp); - } - if (res == NULL) { - Cudd_RecursiveDeref(dd,tmp); - return(NULL); - } - cuddDeref(tmp); /* Just cuddDeref, because it is included in result */ - } - - cuddCacheInsert2(dd,Cudd_bddLiteralSetIntersection,f,g,res); - - return(res); - -} /* end of cuddBddLiteralSetIntersectionRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddMatMult.c b/src/bdd/cudd/cuddMatMult.c deleted file mode 100644 index 345e7921..00000000 --- a/src/bdd/cudd/cuddMatMult.c +++ /dev/null @@ -1,680 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddMatMult.c] - - PackageName [cudd] - - Synopsis [Matrix multiplication functions.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addMatrixMultiply() - <li> Cudd_addTimesPlus() - <li> Cudd_addTriangle() - <li> Cudd_addOuterSum() - </ul> - Static procedures included in this module: - <ul> - <li> addMMRecur() - <li> addTriangleRecur() - <li> cuddAddOuterSumRecur() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddMatMult.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * addMMRecur ARGS((DdManager *dd, DdNode *A, DdNode *B, int topP, int *vars)); -static DdNode * addTriangleRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, int *vars, DdNode *cube)); -static DdNode * cuddAddOuterSumRecur ARGS((DdManager *dd, DdNode *M, DdNode *r, DdNode *c)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Calculates the product of two matrices represented as - ADDs.] - - Description [Calculates the product of two matrices, A and B, - represented as ADDs. This procedure implements the quasiring multiplication - algorithm. A is assumed to depend on variables x (rows) and z - (columns). B is assumed to depend on variables z (rows) and y - (columns). The product of A and B then depends on x (rows) and y - (columns). Only the z variables have to be explicitly identified; - they are the "summation" variables. Returns a pointer to the - result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addTimesPlus Cudd_addTriangle Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -Cudd_addMatrixMultiply( - DdManager * dd, - DdNode * A, - DdNode * B, - DdNode ** z, - int nz) -{ - int i, nvars, *vars; - DdNode *res; - - /* Array vars says what variables are "summation" variables. */ - nvars = dd->size; - vars = ALLOC(int,nvars); - if (vars == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < nvars; i++) { - vars[i] = 0; - } - for (i = 0; i < nz; i++) { - vars[z[i]->index] = 1; - } - - do { - dd->reordered = 0; - res = addMMRecur(dd,A,B,-1,vars); - } while (dd->reordered == 1); - FREE(vars); - return(res); - -} /* end of Cudd_addMatrixMultiply */ - - -/**Function******************************************************************** - - Synopsis [Calculates the product of two matrices represented as - ADDs.] - - Description [Calculates the product of two matrices, A and B, - represented as ADDs, using the CMU matrix by matrix multiplication - procedure by Clarke et al.. Matrix A has x's as row variables and z's - as column variables, while matrix B has z's as row variables and y's - as column variables. Returns the pointer to the result if successful; - NULL otherwise. The resulting matrix has x's as row variables and y's - as column variables.] - - SideEffects [None] - - SeeAlso [Cudd_addMatrixMultiply] - -******************************************************************************/ -DdNode * -Cudd_addTimesPlus( - DdManager * dd, - DdNode * A, - DdNode * B, - DdNode ** z, - int nz) -{ - DdNode *w, *cube, *tmp, *res; - int i; - tmp = Cudd_addApply(dd,Cudd_addTimes,A,B); - if (tmp == NULL) return(NULL); - Cudd_Ref(tmp); - Cudd_Ref(cube = DD_ONE(dd)); - for (i = nz-1; i >= 0; i--) { - w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd)); - if (w == NULL) { - Cudd_RecursiveDeref(dd,tmp); - return(NULL); - } - Cudd_Ref(w); - Cudd_RecursiveDeref(dd,cube); - cube = w; - } - res = Cudd_addExistAbstract(dd,tmp,cube); - if (res == NULL) { - Cudd_RecursiveDeref(dd,tmp); - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - Cudd_Ref(res); - Cudd_RecursiveDeref(dd,cube); - Cudd_RecursiveDeref(dd,tmp); - Cudd_Deref(res); - return(res); - -} /* end of Cudd_addTimesPlus */ - - -/**Function******************************************************************** - - Synopsis [Performs the triangulation step for the shortest path - computation.] - - Description [Implements the semiring multiplication algorithm used in - the triangulation step for the shortest path computation. f - is assumed to depend on variables x (rows) and z (columns). g is - assumed to depend on variables z (rows) and y (columns). The product - of f and g then depends on x (rows) and y (columns). Only the z - variables have to be explicitly identified; they are the - "abstraction" variables. Returns a pointer to the result if - successful; NULL otherwise. ] - - SideEffects [None] - - SeeAlso [Cudd_addMatrixMultiply Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -Cudd_addTriangle( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode ** z, - int nz) -{ - int i, nvars, *vars; - DdNode *res, *cube; - - nvars = dd->size; - vars = ALLOC(int, nvars); - if (vars == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < nvars; i++) vars[i] = -1; - for (i = 0; i < nz; i++) vars[z[i]->index] = i; - cube = Cudd_addComputeCube(dd, z, NULL, nz); - if (cube == NULL) { - FREE(vars); - return(NULL); - } - cuddRef(cube); - - do { - dd->reordered = 0; - res = addTriangleRecur(dd, f, g, vars, cube); - } while (dd->reordered == 1); - if (res != NULL) cuddRef(res); - Cudd_RecursiveDeref(dd,cube); - if (res != NULL) cuddDeref(res); - FREE(vars); - return(res); - -} /* end of Cudd_addTriangle */ - - -/**Function******************************************************************** - - Synopsis [Takes the minimum of a matrix and the outer sum of two vectors.] - - Description [Takes the pointwise minimum of a matrix and the outer - sum of two vectors. This procedure is used in the Floyd-Warshall - all-pair shortest path algorithm. Returns a pointer to the result if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_addOuterSum( - DdManager *dd, - DdNode *M, - DdNode *r, - DdNode *c) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddOuterSumRecur(dd, M, r, c); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addOuterSum */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addMatrixMultiply.] - - Description [Performs the recursive step of Cudd_addMatrixMultiply. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -addMMRecur( - DdManager * dd, - DdNode * A, - DdNode * B, - int topP, - int * vars) -{ - DdNode *zero, - *At, /* positive cofactor of first operand */ - *Ae, /* negative cofactor of first operand */ - *Bt, /* positive cofactor of second operand */ - *Be, /* negative cofactor of second operand */ - *t, /* positive cofactor of result */ - *e, /* negative cofactor of result */ - *scaled, /* scaled result */ - *add_scale, /* ADD representing the scaling factor */ - *res; - int i; /* loop index */ - double scale; /* scaling factor */ - int index; /* index of the top variable */ - CUDD_VALUE_TYPE value; - unsigned int topA, topB, topV; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - - statLine(dd); - zero = DD_ZERO(dd); - - if (A == zero || B == zero) { - return(zero); - } - - if (cuddIsConstant(A) && cuddIsConstant(B)) { - /* Compute the scaling factor. It is 2^k, where k is the - ** number of summation variables below the current variable. - ** Indeed, these constants represent blocks of 2^k identical - ** constant values in both A and B. - */ - value = cuddV(A) * cuddV(B); - for (i = 0; i < dd->size; i++) { - if (vars[i]) { - if (dd->perm[i] > topP) { - value *= (CUDD_VALUE_TYPE) 2; - } - } - } - res = cuddUniqueConst(dd, value); - return(res); - } - - /* Standardize to increase cache efficiency. Clearly, A*B != B*A - ** in matrix multiplication. However, which matrix is which is - ** determined by the variables appearing in the ADDs and not by - ** which one is passed as first argument. - */ - if (A > B) { - DdNode *tmp = A; - A = B; - B = tmp; - } - - topA = cuddI(dd,A->index); topB = cuddI(dd,B->index); - topV = ddMin(topA,topB); - - cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) addMMRecur; - res = cuddCacheLookup2(dd,cacheOp,A,B); - if (res != NULL) { - /* If the result is 0, there is no need to normalize. - ** Otherwise we count the number of z variables between - ** the current depth and the top of the ADDs. These are - ** the missing variables that determine the size of the - ** constant blocks. - */ - if (res == zero) return(res); - scale = 1.0; - for (i = 0; i < dd->size; i++) { - if (vars[i]) { - if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { - scale *= 2; - } - } - } - if (scale > 1.0) { - cuddRef(res); - add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); - if (add_scale == NULL) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - cuddRef(add_scale); - scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); - if (scaled == NULL) { - Cudd_RecursiveDeref(dd, add_scale); - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - cuddRef(scaled); - Cudd_RecursiveDeref(dd, add_scale); - Cudd_RecursiveDeref(dd, res); - res = scaled; - cuddDeref(res); - } - return(res); - } - - /* compute the cofactors */ - if (topV == topA) { - At = cuddT(A); - Ae = cuddE(A); - } else { - At = Ae = A; - } - if (topV == topB) { - Bt = cuddT(B); - Be = cuddE(B); - } else { - Bt = Be = B; - } - - t = addMMRecur(dd, At, Bt, (int)topV, vars); - if (t == NULL) return(NULL); - cuddRef(t); - e = addMMRecur(dd, Ae, Be, (int)topV, vars); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddRef(e); - - index = dd->invperm[topV]; - if (vars[index] == 0) { - /* We have split on either the rows of A or the columns - ** of B. We just need to connect the two subresults, - ** which correspond to two submatrices of the result. - */ - res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - cuddRef(res); - cuddDeref(t); - cuddDeref(e); - } else { - /* we have simultaneously split on the columns of A and - ** the rows of B. The two subresults must be added. - */ - res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - } - - cuddCacheInsert2(dd,cacheOp,A,B,res); - - /* We have computed (and stored in the computed table) a minimal - ** result; that is, a result that assumes no summation variables - ** between the current depth of the recursion and its top - ** variable. We now take into account the z variables by properly - ** scaling the result. - */ - if (res != zero) { - scale = 1.0; - for (i = 0; i < dd->size; i++) { - if (vars[i]) { - if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { - scale *= 2; - } - } - } - if (scale > 1.0) { - add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); - if (add_scale == NULL) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - cuddRef(add_scale); - scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); - if (scaled == NULL) { - Cudd_RecursiveDeref(dd, res); - Cudd_RecursiveDeref(dd, add_scale); - return(NULL); - } - cuddRef(scaled); - Cudd_RecursiveDeref(dd, add_scale); - Cudd_RecursiveDeref(dd, res); - res = scaled; - } - } - cuddDeref(res); - return(res); - -} /* end of addMMRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addTriangle.] - - Description [Performs the recursive step of Cudd_addTriangle. Returns - a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -addTriangleRecur( - DdManager * dd, - DdNode * f, - DdNode * g, - int * vars, - DdNode *cube) -{ - DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res; - CUDD_VALUE_TYPE value; - int top, topf, topg, index; - - statLine(dd); - if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) { - return(DD_PLUS_INFINITY(dd)); - } - - if (cuddIsConstant(f) && cuddIsConstant(g)) { - value = cuddV(f) + cuddV(g); - res = cuddUniqueConst(dd, value); - return(res); - } - if (f < g) { - DdNode *tmp = f; - f = g; - g = tmp; - } - - if (f->ref != 1 || g->ref != 1) { - res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube); - if (res != NULL) { - return(res); - } - } - - topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); - top = ddMin(topf,topg); - - if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} - if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} - - t = addTriangleRecur(dd, fv, gv, vars, cube); - if (t == NULL) return(NULL); - cuddRef(t); - e = addTriangleRecur(dd, fvn, gvn, vars, cube); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddRef(e); - - index = dd->invperm[top]; - if (vars[index] < 0) { - res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } else { - res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - cuddDeref(res); - } - - if (f->ref != 1 || g->ref != 1) { - cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res); - } - - return(res); - -} /* end of addTriangleRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addOuterSum.] - - Description [Performs the recursive step of Cudd_addOuterSum. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -cuddAddOuterSumRecur( - DdManager *dd, - DdNode *M, - DdNode *r, - DdNode *c) -{ - DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re; - int topM, topc, topr; - int v, index; - - statLine(dd); - /* Check special cases. */ - if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); - - if (cuddIsConstant(c) && cuddIsConstant(r)) { - R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r)); - cuddRef(R); - if (cuddIsConstant(M)) { - if (cuddV(R) <= cuddV(M)) { - cuddDeref(R); - return(R); - } else { - Cudd_RecursiveDeref(dd,R); - return(M); - } - } else { - P = Cudd_addApply(dd,Cudd_addMinimum,R,M); - cuddRef(P); - Cudd_RecursiveDeref(dd,R); - cuddDeref(P); - return(P); - } - } - - /* Check the cache. */ - R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c); - if (R != NULL) return(R); - - topM = cuddI(dd,M->index); topr = cuddI(dd,r->index); - topc = cuddI(dd,c->index); - v = ddMin(topM,ddMin(topr,topc)); - - /* Compute cofactors. */ - if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; } - if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; } - if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; } - - /* Recursively solve. */ - Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct); - if (Rt == NULL) return(NULL); - cuddRef(Rt); - Re = cuddAddOuterSumRecur(dd,Me,re,ce); - if (Re == NULL) { - Cudd_RecursiveDeref(dd, Rt); - return(NULL); - } - cuddRef(Re); - index = dd->invperm[v]; - R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re); - if (R == NULL) { - Cudd_RecursiveDeref(dd, Rt); - Cudd_RecursiveDeref(dd, Re); - return(NULL); - } - cuddDeref(Rt); - cuddDeref(Re); - - /* Store the result in the cache. */ - cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R); - - return(R); - -} /* end of cuddAddOuterSumRecur */ diff --git a/src/bdd/cudd/cuddPriority.c b/src/bdd/cudd/cuddPriority.c deleted file mode 100644 index 788fc712..00000000 --- a/src/bdd/cudd/cuddPriority.c +++ /dev/null @@ -1,1475 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddPriority.c] - - PackageName [cudd] - - Synopsis [Priority functions.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_PrioritySelect() - <li> Cudd_Xgty() - <li> Cudd_Xeqy() - <li> Cudd_addXeqy() - <li> Cudd_Dxygtdxz() - <li> Cudd_Dxygtdyz() - <li> Cudd_CProjection() - <li> Cudd_addHamming() - <li> Cudd_MinHammingDist() - <li> Cudd_bddClosestCube() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddCProjectionRecur() - <li> cuddBddClosestCube() - </ul> - Static procedures included in this module: - <ul> - <li> cuddMinHammingDistRecur() - <li> separateCube() - <li> createResult() - </ul> - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddPriority.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ -static int cuddMinHammingDistRecur ARGS((DdNode * f, int *minterm, DdHashTable * table, int upperBound)); -static DdNode * separateCube ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE *distance)); -static DdNode * createResult ARGS((DdManager *dd, unsigned int index, unsigned int phase, DdNode *cube, CUDD_VALUE_TYPE distance)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Selects pairs from R using a priority function.] - - Description [Selects pairs from a relation R(x,y) (given as a BDD) - in such a way that a given x appears in one pair only. Uses a - priority function to determine which y should be paired to a given x. - Cudd_PrioritySelect returns a pointer to - the selected function if successful; NULL otherwise. - Three of the arguments--x, y, and z--are vectors of BDD variables. - The first two are the variables on which R depends. The third vectore - is a vector of auxiliary variables, used during the computation. This - vector is optional. If a NULL value is passed instead, - Cudd_PrioritySelect will create the working variables on the fly. - The sizes of x and y (and z if it is not NULL) should equal n. - The priority function Pi can be passed as a BDD, or can be built by - Cudd_PrioritySelect. If NULL is passed instead of a DdNode *, - parameter Pifunc is used by Cudd_PrioritySelect to build a BDD for the - priority function. (Pifunc is a pointer to a C function.) If Pi is not - NULL, then Pifunc is ignored. Pifunc should have the same interface as - the standard priority functions (e.g., Cudd_Dxygtdxz). - Cudd_PrioritySelect and Cudd_CProjection can sometimes be used - interchangeably. Specifically, calling Cudd_PrioritySelect with - Cudd_Xgty as Pifunc produces the same result as calling - Cudd_CProjection with the all-zero minterm as reference minterm. - However, depending on the application, one or the other may be - preferable: - <ul> - <li> When extracting representatives from an equivalence relation, - Cudd_CProjection has the advantage of nor requiring the auxiliary - variables. - <li> When computing matchings in general bipartite graphs, - Cudd_PrioritySelect normally obtains better results because it can use - more powerful matching schemes (e.g., Cudd_Dxygtdxz). - </ul> - ] - - SideEffects [If called with z == NULL, will create new variables in - the manager.] - - SeeAlso [Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_Xgty - Cudd_bddAdjPermuteX Cudd_CProjection] - -******************************************************************************/ -DdNode * -Cudd_PrioritySelect( - DdManager * dd /* manager */, - DdNode * R /* BDD of the relation */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */, - DdNode ** z /* array of z variables (optional: may be NULL) */, - DdNode * Pi /* BDD of the priority function (optional: may be NULL) */, - int n /* size of x, y, and z */, - DdNode * (*Pifunc)(DdManager *, int, DdNode **, DdNode **, DdNode **) /* function used to build Pi if it is NULL */) -{ - DdNode *res = NULL; - DdNode *zcube = NULL; - DdNode *Rxz, *Q; - int createdZ = 0; - int createdPi = 0; - int i; - - /* Create z variables if needed. */ - if (z == NULL) { - if (Pi != NULL) return(NULL); - z = ALLOC(DdNode *,n); - if (z == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - createdZ = 1; - for (i = 0; i < n; i++) { - if (dd->size >= (int) CUDD_MAXINDEX - 1) goto endgame; - z[i] = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one)); - if (z[i] == NULL) goto endgame; - } - } - - /* Create priority function BDD if needed. */ - if (Pi == NULL) { - Pi = Pifunc(dd,n,x,y,z); - if (Pi == NULL) goto endgame; - createdPi = 1; - cuddRef(Pi); - } - - /* Initialize abstraction cube. */ - zcube = DD_ONE(dd); - cuddRef(zcube); - for (i = n - 1; i >= 0; i--) { - DdNode *tmpp; - tmpp = Cudd_bddAnd(dd,z[i],zcube); - if (tmpp == NULL) goto endgame; - cuddRef(tmpp); - Cudd_RecursiveDeref(dd,zcube); - zcube = tmpp; - } - - /* Compute subset of (x,y) pairs. */ - Rxz = Cudd_bddSwapVariables(dd,R,y,z,n); - if (Rxz == NULL) goto endgame; - cuddRef(Rxz); - Q = Cudd_bddAndAbstract(dd,Rxz,Pi,zcube); - if (Q == NULL) { - Cudd_RecursiveDeref(dd,Rxz); - goto endgame; - } - cuddRef(Q); - Cudd_RecursiveDeref(dd,Rxz); - res = Cudd_bddAnd(dd,R,Cudd_Not(Q)); - if (res == NULL) { - Cudd_RecursiveDeref(dd,Q); - goto endgame; - } - cuddRef(res); - Cudd_RecursiveDeref(dd,Q); - -endgame: - if (zcube != NULL) Cudd_RecursiveDeref(dd,zcube); - if (createdZ) { - FREE(z); - } - if (createdPi) { - Cudd_RecursiveDeref(dd,Pi); - } - if (res != NULL) cuddDeref(res); - return(res); - -} /* Cudd_PrioritySelect */ - - -/**Function******************************************************************** - - Synopsis [Generates a BDD for the function x > y.] - - Description [This function generates a BDD for the function x > y. - Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and - y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. - The BDD is built bottom-up. - It has 3*N-1 internal nodes, if the variables are ordered as follows: - x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. - Argument z is not used by Cudd_Xgty: it is included to make it - call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz.] - - SideEffects [None] - - SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Dxygtdyz] - -******************************************************************************/ -DdNode * -Cudd_Xgty( - DdManager * dd /* DD manager */, - int N /* number of x and y variables */, - DdNode ** z /* array of z variables: unused */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */) -{ - DdNode *u, *v, *w; - int i; - - /* Build bottom part of BDD outside loop. */ - u = Cudd_bddAnd(dd, x[N-1], Cudd_Not(y[N-1])); - if (u == NULL) return(NULL); - cuddRef(u); - - /* Loop to build the rest of the BDD. */ - for (i = N-2; i >= 0; i--) { - v = Cudd_bddAnd(dd, y[i], Cudd_Not(u)); - if (v == NULL) { - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(v); - w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u); - if (w == NULL) { - Cudd_RecursiveDeref(dd, u); - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, u); - u = Cudd_bddIte(dd, x[i], Cudd_Not(v), w); - if (u == NULL) { - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - - } - cuddDeref(u); - return(u); - -} /* end of Cudd_Xgty */ - - -/**Function******************************************************************** - - Synopsis [Generates a BDD for the function x==y.] - - Description [This function generates a BDD for the function x==y. - Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and - y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. - The BDD is built bottom-up. - It has 3*N-1 internal nodes, if the variables are ordered as follows: - x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ] - - SideEffects [None] - - SeeAlso [Cudd_addXeqy] - -******************************************************************************/ -DdNode * -Cudd_Xeqy( - DdManager * dd /* DD manager */, - int N /* number of x and y variables */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */) -{ - DdNode *u, *v, *w; - int i; - - /* Build bottom part of BDD outside loop. */ - u = Cudd_bddIte(dd, x[N-1], y[N-1], Cudd_Not(y[N-1])); - if (u == NULL) return(NULL); - cuddRef(u); - - /* Loop to build the rest of the BDD. */ - for (i = N-2; i >= 0; i--) { - v = Cudd_bddAnd(dd, y[i], u); - if (v == NULL) { - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(v); - w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u); - if (w == NULL) { - Cudd_RecursiveDeref(dd, u); - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, u); - u = Cudd_bddIte(dd, x[i], v, w); - if (u == NULL) { - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - } - cuddDeref(u); - return(u); - -} /* end of Cudd_Xeqy */ - - -/**Function******************************************************************** - - Synopsis [Generates an ADD for the function x==y.] - - Description [This function generates an ADD for the function x==y. - Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and - y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. - The ADD is built bottom-up. - It has 3*N-1 internal nodes, if the variables are ordered as follows: - x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ] - - SideEffects [None] - - SeeAlso [Cudd_Xeqy] - -******************************************************************************/ -DdNode * -Cudd_addXeqy( - DdManager * dd /* DD manager */, - int N /* number of x and y variables */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */) -{ - DdNode *one, *zero; - DdNode *u, *v, *w; - int i; - - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - /* Build bottom part of ADD outside loop. */ - v = Cudd_addIte(dd, y[N-1], one, zero); - if (v == NULL) return(NULL); - cuddRef(v); - w = Cudd_addIte(dd, y[N-1], zero, one); - if (w == NULL) { - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(w); - u = Cudd_addIte(dd, x[N-1], v, w); - if (w == NULL) { - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - - /* Loop to build the rest of the ADD. */ - for (i = N-2; i >= 0; i--) { - v = Cudd_addIte(dd, y[i], u, zero); - if (v == NULL) { - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(v); - w = Cudd_addIte(dd, y[i], zero, u); - if (w == NULL) { - Cudd_RecursiveDeref(dd, u); - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, u); - u = Cudd_addIte(dd, x[i], v, w); - if (w == NULL) { - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - } - cuddDeref(u); - return(u); - -} /* end of Cudd_addXeqy */ - - -/**Function******************************************************************** - - Synopsis [Generates a BDD for the function d(x,y) > d(x,z).] - - Description [This function generates a BDD for the function d(x,y) - > d(x,z); - x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\], - y\[0\] y\[1\] ... y\[N-1\], and z\[0\] z\[1\] ... z\[N-1\], - with 0 the most significant bit. - The distance d(x,y) is defined as: - \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}). - The BDD is built bottom-up. - It has 7*N-3 internal nodes, if the variables are ordered as follows: - x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ] - - SideEffects [None] - - SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdyz Cudd_Xgty Cudd_bddAdjPermuteX] - -******************************************************************************/ -DdNode * -Cudd_Dxygtdxz( - DdManager * dd /* DD manager */, - int N /* number of x, y, and z variables */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */, - DdNode ** z /* array of z variables */) -{ - DdNode *one, *zero; - DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1; - int i; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Build bottom part of BDD outside loop. */ - y1_ = Cudd_bddIte(dd, y[N-1], one, Cudd_Not(z[N-1])); - if (y1_ == NULL) return(NULL); - cuddRef(y1_); - y2 = Cudd_bddIte(dd, y[N-1], z[N-1], one); - if (y2 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - return(NULL); - } - cuddRef(y2); - x1 = Cudd_bddIte(dd, x[N-1], y1_, y2); - if (x1 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - return(NULL); - } - cuddRef(x1); - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - - /* Loop to build the rest of the BDD. */ - for (i = N-2; i >= 0; i--) { - z1 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1)); - if (z1 == NULL) { - Cudd_RecursiveDeref(dd, x1); - return(NULL); - } - cuddRef(z1); - z2 = Cudd_bddIte(dd, z[i], x1, one); - if (z2 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - return(NULL); - } - cuddRef(z2); - z3 = Cudd_bddIte(dd, z[i], one, x1); - if (z3 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - return(NULL); - } - cuddRef(z3); - z4 = Cudd_bddIte(dd, z[i], x1, zero); - if (z4 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - return(NULL); - } - cuddRef(z4); - Cudd_RecursiveDeref(dd, x1); - y1_ = Cudd_bddIte(dd, y[i], z2, Cudd_Not(z1)); - if (y1_ == NULL) { - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - return(NULL); - } - cuddRef(y1_); - y2 = Cudd_bddIte(dd, y[i], z4, z3); - if (y2 == NULL) { - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - Cudd_RecursiveDeref(dd, y1_); - return(NULL); - } - cuddRef(y2); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - x1 = Cudd_bddIte(dd, x[i], y1_, y2); - if (x1 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - return(NULL); - } - cuddRef(x1); - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - } - cuddDeref(x1); - return(Cudd_Not(x1)); - -} /* end of Cudd_Dxygtdxz */ - - -/**Function******************************************************************** - - Synopsis [Generates a BDD for the function d(x,y) > d(y,z).] - - Description [This function generates a BDD for the function d(x,y) - > d(y,z); - x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\], - y\[0\] y\[1\] ... y\[N-1\], and z\[0\] z\[1\] ... z\[N-1\], - with 0 the most significant bit. - The distance d(x,y) is defined as: - \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}). - The BDD is built bottom-up. - It has 7*N-3 internal nodes, if the variables are ordered as follows: - x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ] - - SideEffects [None] - - SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Xgty Cudd_bddAdjPermuteX] - -******************************************************************************/ -DdNode * -Cudd_Dxygtdyz( - DdManager * dd /* DD manager */, - int N /* number of x, y, and z variables */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */, - DdNode ** z /* array of z variables */) -{ - DdNode *one, *zero; - DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1; - int i; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Build bottom part of BDD outside loop. */ - y1_ = Cudd_bddIte(dd, y[N-1], one, z[N-1]); - if (y1_ == NULL) return(NULL); - cuddRef(y1_); - y2 = Cudd_bddIte(dd, y[N-1], z[N-1], zero); - if (y2 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - return(NULL); - } - cuddRef(y2); - x1 = Cudd_bddIte(dd, x[N-1], y1_, Cudd_Not(y2)); - if (x1 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - return(NULL); - } - cuddRef(x1); - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - - /* Loop to build the rest of the BDD. */ - for (i = N-2; i >= 0; i--) { - z1 = Cudd_bddIte(dd, z[i], x1, zero); - if (z1 == NULL) { - Cudd_RecursiveDeref(dd, x1); - return(NULL); - } - cuddRef(z1); - z2 = Cudd_bddIte(dd, z[i], x1, one); - if (z2 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - return(NULL); - } - cuddRef(z2); - z3 = Cudd_bddIte(dd, z[i], one, x1); - if (z3 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - return(NULL); - } - cuddRef(z3); - z4 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1)); - if (z4 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - return(NULL); - } - cuddRef(z4); - Cudd_RecursiveDeref(dd, x1); - y1_ = Cudd_bddIte(dd, y[i], z2, z1); - if (y1_ == NULL) { - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - return(NULL); - } - cuddRef(y1_); - y2 = Cudd_bddIte(dd, y[i], z4, Cudd_Not(z3)); - if (y2 == NULL) { - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - Cudd_RecursiveDeref(dd, y1_); - return(NULL); - } - cuddRef(y2); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - x1 = Cudd_bddIte(dd, x[i], y1_, Cudd_Not(y2)); - if (x1 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - return(NULL); - } - cuddRef(x1); - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - } - cuddDeref(x1); - return(Cudd_Not(x1)); - -} /* end of Cudd_Dxygtdyz */ - - -/**Function******************************************************************** - - Synopsis [Computes the compatible projection of R w.r.t. cube Y.] - - Description [Computes the compatible projection of relation R with - respect to cube Y. Returns a pointer to the c-projection if - successful; NULL otherwise. For a comparison between Cudd_CProjection - and Cudd_PrioritySelect, see the documentation of the latter.] - - SideEffects [None] - - SeeAlso [Cudd_PrioritySelect] - -******************************************************************************/ -DdNode * -Cudd_CProjection( - DdManager * dd, - DdNode * R, - DdNode * Y) -{ - DdNode *res; - DdNode *support; - - if (cuddCheckCube(dd,Y) == 0) { - (void) fprintf(dd->err, - "Error: The third argument of Cudd_CProjection should be a cube\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - /* Compute the support of Y, which is used by the abstraction step - ** in cuddCProjectionRecur. - */ - support = Cudd_Support(dd,Y); - if (support == NULL) return(NULL); - cuddRef(support); - - do { - dd->reordered = 0; - res = cuddCProjectionRecur(dd,R,Y,support); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd,support); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd,support); - cuddDeref(res); - - return(res); - -} /* end of Cudd_CProjection */ - - -/**Function******************************************************************** - - Synopsis [Computes the Hamming distance ADD.] - - Description [Computes the Hamming distance ADD. Returns an ADD that - gives the Hamming distance between its two arguments if successful; - NULL otherwise. The two vectors xVars and yVars identify the variables - that form the two arguments.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_addHamming( - DdManager * dd, - DdNode ** xVars, - DdNode ** yVars, - int nVars) -{ - DdNode *result,*tempBdd; - DdNode *tempAdd,*temp; - int i; - - result = DD_ZERO(dd); - cuddRef(result); - - for (i = 0; i < nVars; i++) { - tempBdd = Cudd_bddIte(dd,xVars[i],Cudd_Not(yVars[i]),yVars[i]); - if (tempBdd == NULL) { - Cudd_RecursiveDeref(dd,result); - return(NULL); - } - cuddRef(tempBdd); - tempAdd = Cudd_BddToAdd(dd,tempBdd); - if (tempAdd == NULL) { - Cudd_RecursiveDeref(dd,tempBdd); - Cudd_RecursiveDeref(dd,result); - return(NULL); - } - cuddRef(tempAdd); - Cudd_RecursiveDeref(dd,tempBdd); - temp = Cudd_addApply(dd,Cudd_addPlus,tempAdd,result); - if (temp == NULL) { - Cudd_RecursiveDeref(dd,tempAdd); - Cudd_RecursiveDeref(dd,result); - return(NULL); - } - cuddRef(temp); - Cudd_RecursiveDeref(dd,tempAdd); - Cudd_RecursiveDeref(dd,result); - result = temp; - } - - cuddDeref(result); - return(result); - -} /* end of Cudd_addHamming */ - - -/**Function******************************************************************** - - Synopsis [Returns the minimum Hamming distance between f and minterm.] - - Description [Returns the minimum Hamming distance between the - minterms of a function f and a reference minterm. The function is - given as a BDD; the minterm is given as an array of integers, one - for each variable in the manager. Returns the minimum distance if - it is less than the upper bound; the upper bound if the minimum - distance is at least as large; CUDD_OUT_OF_MEM in case of failure.] - - SideEffects [None] - - SeeAlso [Cudd_addHamming Cudd_bddClosestCube] - -******************************************************************************/ -int -Cudd_MinHammingDist( - DdManager *dd /* DD manager */, - DdNode *f /* function to examine */, - int *minterm /* reference minterm */, - int upperBound /* distance above which an approximate answer is OK */) -{ - DdHashTable *table; - CUDD_VALUE_TYPE epsilon; - int res; - - table = cuddHashTableInit(dd,1,2); - if (table == NULL) { - return(CUDD_OUT_OF_MEM); - } - epsilon = Cudd_ReadEpsilon(dd); - Cudd_SetEpsilon(dd,(CUDD_VALUE_TYPE)0.0); - res = cuddMinHammingDistRecur(f,minterm,table,upperBound); - cuddHashTableQuit(table); - Cudd_SetEpsilon(dd,epsilon); - - return(res); - -} /* end of Cudd_MinHammingDist */ - - -/**Function******************************************************************** - - Synopsis [Finds a cube of f at minimum Hamming distance from g.] - - Description [Finds a cube of f at minimum Hamming distance from the - minterms of g. All the minterms of the cube are at the minimum - distance. If the distance is 0, the cube belongs to the - intersection of f and g. Returns the cube if successful; NULL - otherwise.] - - SideEffects [The distance is returned as a side effect.] - - SeeAlso [Cudd_MinHammingDist] - -******************************************************************************/ -DdNode * -Cudd_bddClosestCube( - DdManager *dd, - DdNode * f, - DdNode *g, - int *distance) -{ - DdNode *res, *acube; - CUDD_VALUE_TYPE rdist; - - /* Compute the cube and distance as a single ADD. */ - do { - dd->reordered = 0; - res = cuddBddClosestCube(dd,f,g,CUDD_CONST_INDEX + 1.0); - } while (dd->reordered == 1); - if (res == NULL) return(NULL); - cuddRef(res); - - /* Unpack distance and cube. */ - do { - dd->reordered = 0; - acube = separateCube(dd, res, &rdist); - } while (dd->reordered == 1); - if (acube == NULL) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - cuddRef(acube); - Cudd_RecursiveDeref(dd, res); - - /* Convert cube from ADD to BDD. */ - do { - dd->reordered = 0; - res = cuddAddBddDoPattern(dd, acube); - } while (dd->reordered == 1); - if (res == NULL) { - Cudd_RecursiveDeref(dd, acube); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, acube); - - *distance = (int) rdist; - cuddDeref(res); - return(res); - -} /* end of Cudd_bddClosestCube */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CProjection.] - - Description [Performs the recursive step of Cudd_CProjection. Returns - the projection if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_CProjection] - -******************************************************************************/ -DdNode * -cuddCProjectionRecur( - DdManager * dd, - DdNode * R, - DdNode * Y, - DdNode * Ysupp) -{ - DdNode *res, *res1, *res2, *resA; - DdNode *r, *y, *RT, *RE, *YT, *YE, *Yrest, *Ra, *Ran, *Gamma, *Alpha; - unsigned int topR, topY, top, index; - DdNode *one = DD_ONE(dd); - - statLine(dd); - if (Y == one) return(R); - -#ifdef DD_DEBUG - assert(!Cudd_IsConstant(Y)); -#endif - - if (R == Cudd_Not(one)) return(R); - - res = cuddCacheLookup2(dd, Cudd_CProjection, R, Y); - if (res != NULL) return(res); - - r = Cudd_Regular(R); - topR = cuddI(dd,r->index); - y = Cudd_Regular(Y); - topY = cuddI(dd,y->index); - - top = ddMin(topR, topY); - - /* Compute the cofactors of R */ - if (topR == top) { - index = r->index; - RT = cuddT(r); - RE = cuddE(r); - if (r != R) { - RT = Cudd_Not(RT); RE = Cudd_Not(RE); - } - } else { - RT = RE = R; - } - - if (topY > top) { - /* Y does not depend on the current top variable. - ** We just need to compute the results on the two cofactors of R - ** and make them the children of a node labeled r->index. - */ - res1 = cuddCProjectionRecur(dd,RT,Y,Ysupp); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddCProjectionRecur(dd,RE,Y,Ysupp); - if (res2 == NULL) { - Cudd_RecursiveDeref(dd,res1); - return(NULL); - } - cuddRef(res2); - res = cuddBddIteRecur(dd, dd->vars[index], res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,res2); - return(NULL); - } - /* If we have reached this point, res1 and res2 are now - ** incorporated in res. cuddDeref is therefore sufficient. - */ - cuddDeref(res1); - cuddDeref(res2); - } else { - /* Compute the cofactors of Y */ - index = y->index; - YT = cuddT(y); - YE = cuddE(y); - if (y != Y) { - YT = Cudd_Not(YT); YE = Cudd_Not(YE); - } - if (YT == Cudd_Not(one)) { - Alpha = Cudd_Not(dd->vars[index]); - Yrest = YE; - Ra = RE; - Ran = RT; - } else { - Alpha = dd->vars[index]; - Yrest = YT; - Ra = RT; - Ran = RE; - } - Gamma = cuddBddExistAbstractRecur(dd,Ra,cuddT(Ysupp)); - if (Gamma == NULL) return(NULL); - if (Gamma == one) { - res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res = cuddBddAndRecur(dd, Alpha, res1); - if (res == NULL) { - Cudd_RecursiveDeref(dd,res1); - return(NULL); - } - cuddDeref(res1); - } else if (Gamma == Cudd_Not(one)) { - res1 = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res = cuddBddAndRecur(dd, Cudd_Not(Alpha), res1); - if (res == NULL) { - Cudd_RecursiveDeref(dd,res1); - return(NULL); - } - cuddDeref(res1); - } else { - cuddRef(Gamma); - resA = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); - if (resA == NULL) { - Cudd_RecursiveDeref(dd,Gamma); - return(NULL); - } - cuddRef(resA); - res2 = cuddBddAndRecur(dd, Cudd_Not(Gamma), resA); - if (res2 == NULL) { - Cudd_RecursiveDeref(dd,Gamma); - Cudd_RecursiveDeref(dd,resA); - return(NULL); - } - cuddRef(res2); - Cudd_RecursiveDeref(dd,Gamma); - Cudd_RecursiveDeref(dd,resA); - res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); - if (res1 == NULL) { - Cudd_RecursiveDeref(dd,res2); - return(NULL); - } - cuddRef(res1); - res = cuddBddIteRecur(dd, Alpha, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - } - } - - cuddCacheInsert2(dd,Cudd_CProjection,R,Y,res); - - return(res); - -} /* end of cuddCProjectionRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddClosestCube.] - - Description [Performs the recursive step of Cudd_bddClosestCube. - Returns the cube if succesful; NULL otherwise. The procedure uses a - four-way recursion to examine all four combinations of cofactors of - f and g. The most interesting feature of this function is the - scheme used for caching the results in the global computed table. - Since we have a cube and a distance, we combine them to form an ADD. - The combination replaces the zero child of the top node of the cube - with the negative of the distance. (The use of the negative is to - avoid ambiguity with 1.) The degenerate cases (zero and one) are - treated specially because the distance is known (0 for one, and - infinity for zero).] - - SideEffects [None] - - SeeAlso [Cudd_bddClosestCube] - -******************************************************************************/ -DdNode * -cuddBddClosestCube( - DdManager *dd, - DdNode *f, - DdNode *g, - CUDD_VALUE_TYPE bound) -{ - DdNode *res, *F, *G, *ft, *fe, *gt, *ge, *tt, *ee; - DdNode *ctt, *cee, *cte, *cet; - CUDD_VALUE_TYPE minD, dtt, dee, dte, det; - DdNode *one = DD_ONE(dd); - DdNode *lzero = Cudd_Not(one); - DdNode *azero = DD_ZERO(dd); - unsigned int topf, topg, index; - - statLine(dd); - if (bound < (f == Cudd_Not(g))) return(azero); - /* Terminal cases. */ - if (g == lzero || f == lzero) return(azero); - if (f == one && g == one) return(one); - - /* Check cache. */ - F = Cudd_Regular(f); - G = Cudd_Regular(g); - if (F->ref != 1 || G->ref != 1) { - res = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, - DdNode *)) Cudd_bddClosestCube, f, g); - if (res != NULL) return(res); - } - - topf = cuddI(dd,F->index); - topg = cuddI(dd,G->index); - - /* Compute cofactors. */ - if (topf <= topg) { - index = F->index; - ft = cuddT(F); - fe = cuddE(F); - if (Cudd_IsComplement(f)) { - ft = Cudd_Not(ft); - fe = Cudd_Not(fe); - } - } else { - index = G->index; - ft = fe = f; - } - - if (topg <= topf) { - gt = cuddT(G); - ge = cuddE(G); - if (Cudd_IsComplement(g)) { - gt = Cudd_Not(gt); - ge = Cudd_Not(ge); - } - } else { - gt = ge = g; - } - - tt = cuddBddClosestCube(dd,ft,gt,bound); - if (tt == NULL) return(NULL); - cuddRef(tt); - ctt = separateCube(dd,tt,&dtt); - if (ctt == NULL) { - Cudd_RecursiveDeref(dd, tt); - return(NULL); - } - cuddRef(ctt); - Cudd_RecursiveDeref(dd, tt); - minD = dtt; - bound = ddMin(bound,minD); - - ee = cuddBddClosestCube(dd,fe,ge,bound); - if (ee == NULL) { - Cudd_RecursiveDeref(dd, ctt); - return(NULL); - } - cuddRef(ee); - cee = separateCube(dd,ee,&dee); - if (cee == NULL) { - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, ee); - return(NULL); - } - cuddRef(cee); - Cudd_RecursiveDeref(dd, ee); - minD = ddMin(dtt, dee); - bound = ddMin(bound,minD-1); - - if (minD > 0 && topf == topg) { - DdNode *te = cuddBddClosestCube(dd,ft,ge,bound-1); - if (te == NULL) { - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, cee); - return(NULL); - } - cuddRef(te); - cte = separateCube(dd,te,&dte); - if (cte == NULL) { - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, cee); - Cudd_RecursiveDeref(dd, te); - return(NULL); - } - cuddRef(cte); - Cudd_RecursiveDeref(dd, te); - dte += 1.0; - minD = ddMin(minD, dte); - } else { - cte = azero; - cuddRef(cte); - dte = CUDD_CONST_INDEX + 1.0; - } - bound = ddMin(bound,minD-1); - - if (minD > 0 && topf == topg) { - DdNode *et = cuddBddClosestCube(dd,fe,gt,bound-1); - if (et == NULL) { - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, cee); - Cudd_RecursiveDeref(dd, cte); - return(NULL); - } - cuddRef(et); - cet = separateCube(dd,et,&det); - if (cet == NULL) { - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, cee); - Cudd_RecursiveDeref(dd, cte); - Cudd_RecursiveDeref(dd, et); - return(NULL); - } - cuddRef(cet); - Cudd_RecursiveDeref(dd, et); - det += 1.0; - minD = ddMin(minD, det); - } else { - cet = azero; - cuddRef(cet); - det = CUDD_CONST_INDEX + 1.0; - } - - if (minD == dtt) { - if (dtt == dee && ctt == cee) { - res = createResult(dd,CUDD_CONST_INDEX,1,ctt,dtt); - } else { - res = createResult(dd,index,1,ctt,dtt); - } - } else if (minD == dee) { - res = createResult(dd,index,0,cee,dee); - } else if (minD == dte) { - res = createResult(dd,index,(topf <= topg),cte,dte); - } else { - res = createResult(dd,index,(topf > topg),cet,det); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, cee); - Cudd_RecursiveDeref(dd, cte); - Cudd_RecursiveDeref(dd, cet); - - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, - DdNode *)) Cudd_bddClosestCube, f, g, res); - - cuddDeref(res); - return(res); - -} /* end of cuddBddClosestCube */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_MinHammingDist.] - - Description [Performs the recursive step of Cudd_MinHammingDist. - It is based on the following identity. Let H(f) be the - minimum Hamming distance of the minterms of f from the reference - minterm. Then: - <xmp> - H(f) = min(H(f0)+h0,H(f1)+h1) - </xmp> - where f0 and f1 are the two cofactors of f with respect to its top - variable; h0 is 1 if the minterm assigns 1 to the top variable of f; - h1 is 1 if the minterm assigns 0 to the top variable of f. - The upper bound on the distance is used to bound the depth of the - recursion. - Returns the minimum distance unless it exceeds the upper bound or - computation fails.] - - SideEffects [None] - - SeeAlso [Cudd_MinHammingDist] - -******************************************************************************/ -static int -cuddMinHammingDistRecur( - DdNode * f, - int *minterm, - DdHashTable * table, - int upperBound) -{ - DdNode *F, *Ft, *Fe; - double h, hT, hE; - DdNode *zero, *res; - DdManager *dd = table->manager; - - statLine(dd); - if (upperBound == 0) return(0); - - F = Cudd_Regular(f); - - if (cuddIsConstant(F)) { - zero = Cudd_Not(DD_ONE(dd)); - if (f == dd->background || f == zero) { - return(upperBound); - } else { - return(0); - } - } - if ((res = cuddHashTableLookup1(table,f)) != NULL) { - h = cuddV(res); - if (res->ref == 0) { - dd->dead++; - dd->constants.dead++; - } - return((int) h); - } - - Ft = cuddT(F); Fe = cuddE(F); - if (Cudd_IsComplement(f)) { - Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe); - } - if (minterm[F->index] == 0) { - DdNode *temp = Ft; - Ft = Fe; Fe = temp; - } - - hT = cuddMinHammingDistRecur(Ft,minterm,table,upperBound); - if (hT == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); - if (hT == 0) { - hE = upperBound; - } else { - hE = cuddMinHammingDistRecur(Fe,minterm,table,upperBound - 1); - if (hE == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); - } - h = ddMin(hT, hE + 1); - - if (F->ref != 1) { - ptrint fanout = (ptrint) F->ref; - cuddSatDec(fanout); - res = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) h); - if (!cuddHashTableInsert1(table,f,res,fanout)) { - cuddRef(res); Cudd_RecursiveDeref(dd, res); - return(CUDD_OUT_OF_MEM); - } - } - - return((int) h); - -} /* end of cuddMinHammingDistRecur */ - - -/**Function******************************************************************** - - Synopsis [Separates cube from distance.] - - Description [Separates cube from distance. Returns the cube if - successful; NULL otherwise.] - - SideEffects [The distance is returned as a side effect.] - - SeeAlso [cuddBddClosestCube createResult] - -******************************************************************************/ -static DdNode * -separateCube( - DdManager *dd, - DdNode *f, - CUDD_VALUE_TYPE *distance) -{ - DdNode *cube, *t; - - /* One and zero are special cases because the distance is implied. */ - if (Cudd_IsConstant(f)) { - *distance = (f == DD_ONE(dd)) ? 0.0 : - (1.0 + (CUDD_VALUE_TYPE) CUDD_CONST_INDEX); - return(f); - } - - /* Find out which branch points to the distance and replace the top - ** node with one pointing to zero instead. */ - t = cuddT(f); - if (Cudd_IsConstant(t) && cuddV(t) <= 0) { -#ifdef DD_DEBUG - assert(!Cudd_IsConstant(cuddE(f)) || cuddE(f) == DD_ONE(dd)); -#endif - *distance = -cuddV(t); - cube = cuddUniqueInter(dd, f->index, DD_ZERO(dd), cuddE(f)); - } else { -#ifdef DD_DEBUG - assert(!Cudd_IsConstant(t) || t == DD_ONE(dd)); -#endif - *distance = -cuddV(cuddE(f)); - cube = cuddUniqueInter(dd, f->index, t, DD_ZERO(dd)); - } - - return(cube); - -} /* end of separateCube */ - - -/**Function******************************************************************** - - Synopsis [Builds a result for cache storage.] - - Description [Builds a result for cache storage. Returns a pointer - to the resulting ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddBddClosestCube separateCube] - -******************************************************************************/ -static DdNode * -createResult( - DdManager *dd, - unsigned int index, - unsigned int phase, - DdNode *cube, - CUDD_VALUE_TYPE distance) -{ - DdNode *res, *constant; - - /* Special case. The cube is either one or zero, and we do not - ** add any variables. Hence, the result is also one or zero, - ** and the distance remains implied by teh value of the constant. */ - if (index == CUDD_CONST_INDEX && Cudd_IsConstant(cube)) return(cube); - - constant = cuddUniqueConst(dd,-distance); - if (constant == NULL) return(NULL); - cuddRef(constant); - - if (index == CUDD_CONST_INDEX) { - /* Replace the top node. */ - if (cuddT(cube) == DD_ZERO(dd)) { - res = cuddUniqueInter(dd,cube->index,constant,cuddE(cube)); - } else { - res = cuddUniqueInter(dd,cube->index,cuddT(cube),constant); - } - } else { - /* Add a new top node. */ -#ifdef DD_DEBUG - assert(cuddI(dd,index) < cuddI(dd,cube->index)); -#endif - if (phase) { - res = cuddUniqueInter(dd,index,cube,constant); - } else { - res = cuddUniqueInter(dd,index,constant,cube); - } - } - if (res == NULL) { - Cudd_RecursiveDeref(dd, constant); - return(NULL); - } - cuddDeref(constant); /* safe because constant is part of res */ - - return(res); - -} /* end of createResult */ diff --git a/src/bdd/cudd/cuddRead.c b/src/bdd/cudd/cuddRead.c deleted file mode 100644 index 2c4a86d8..00000000 --- a/src/bdd/cudd/cuddRead.c +++ /dev/null @@ -1,490 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddRead.c] - - PackageName [cudd] - - Synopsis [Functions to read in a matrix] - - Description [External procedures included in this module: - <ul> - <li> Cudd_addRead() - <li> Cudd_bddRead() - </ul>] - - SeeAlso [cudd_addHarwell.c] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddRead.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Reads in a sparse matrix.] - - Description [Reads in a sparse matrix specified in a simple format. - The first line of the input contains the numbers of rows and columns. - The remaining lines contain the elements of the matrix, one per line. - Given a background value - (specified by the background field of the manager), only the values - different from it are explicitly listed. Each foreground element is - described by two integers, i.e., the row and column number, and a - real number, i.e., the value.<p> - Cudd_addRead produces an ADD that depends on two sets of variables: x - and y. The x variables (x\[0\] ... x\[nx-1\]) encode the row index and - the y variables (y\[0\] ... y\[ny-1\]) encode the column index. - x\[0\] and y\[0\] are the most significant bits in the indices. - The variables may already exist or may be created by the function. - The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.<p> - On input, nx and ny hold the numbers - of row and column variables already in existence. On output, they - hold the numbers of row and column variables actually used by the - matrix. When Cudd_addRead creates the variable arrays, - the index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy. - When some variables already exist Cudd_addRead expects the indices - of the existing x variables to be bx+i*sx, and the indices of the - existing y variables to be by+i*sy.<p> - m and n are set to the numbers of rows and columns of the - matrix. Their values on input are immaterial. - The ADD for the - sparse matrix is returned in E, and its reference count is > 0. - Cudd_addRead returns 1 in case of success; 0 otherwise.] - - SideEffects [nx and ny are set to the numbers of row and column - variables. m and n are set to the numbers of rows and columns. x and y - are possibly extended to represent the array of row and column - variables. Similarly for xn and yn_, which hold on return from - Cudd_addRead the complements of the row and column variables.] - - SeeAlso [Cudd_addHarwell Cudd_bddRead] - -******************************************************************************/ -int -Cudd_addRead( - FILE * fp /* input file pointer */, - DdManager * dd /* DD manager */, - DdNode ** E /* characteristic function of the graph */, - DdNode *** x /* array of row variables */, - DdNode *** y /* array of column variables */, - DdNode *** xn /* array of complemented row variables */, - DdNode *** yn_ /* array of complemented column variables */, - int * nx /* number or row variables */, - int * ny /* number or column variables */, - int * m /* number of rows */, - int * n /* number of columns */, - int bx /* first index of row variables */, - int sx /* step of row variables */, - int by /* first index of column variables */, - int sy /* step of column variables */) -{ - DdNode *one, *zero; - DdNode *w, *neW; - DdNode *minterm1; - int u, v, err, i, nv; - int lnx, lny; - CUDD_VALUE_TYPE val; - DdNode **lx, **ly, **lxn, **lyn; - - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - err = fscanf(fp, "%d %d", &u, &v); - if (err == EOF) { - return(0); - } else if (err != 2) { - return(0); - } - - *m = u; - /* Compute the number of x variables. */ - lx = *x; lxn = *xn; - u--; /* row and column numbers start from 0 */ - for (lnx=0; u > 0; lnx++) { - u >>= 1; - } - /* Here we rely on the fact that REALLOC of a null pointer is - ** translates to an ALLOC. - */ - if (lnx > *nx) { - *x = lx = REALLOC(DdNode *, *x, lnx); - if (lx == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *xn = lxn = REALLOC(DdNode *, *xn, lnx); - if (lxn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } - - *n = v; - /* Compute the number of y variables. */ - ly = *y; lyn = *yn_; - v--; /* row and column numbers start from 0 */ - for (lny=0; v > 0; lny++) { - v >>= 1; - } - /* Here we rely on the fact that REALLOC of a null pointer is - ** translates to an ALLOC. - */ - if (lny > *ny) { - *y = ly = REALLOC(DdNode *, *y, lny); - if (ly == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *yn_ = lyn = REALLOC(DdNode *, *yn_, lny); - if (lyn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } - - /* Create all new variables. */ - for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) { - do { - dd->reordered = 0; - lx[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (lx[i] == NULL) return(0); - cuddRef(lx[i]); - do { - dd->reordered = 0; - lxn[i] = cuddUniqueInter(dd, nv, zero, one); - } while (dd->reordered == 1); - if (lxn[i] == NULL) return(0); - cuddRef(lxn[i]); - } - for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) { - do { - dd->reordered = 0; - ly[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (ly[i] == NULL) return(0); - cuddRef(ly[i]); - do { - dd->reordered = 0; - lyn[i] = cuddUniqueInter(dd, nv, zero, one); - } while (dd->reordered == 1); - if (lyn[i] == NULL) return(0); - cuddRef(lyn[i]); - } - *nx = lnx; - *ny = lny; - - *E = dd->background; /* this call will never cause reordering */ - cuddRef(*E); - - while (! feof(fp)) { - err = fscanf(fp, "%d %d %lf", &u, &v, &val); - if (err == EOF) { - break; - } else if (err != 3) { - return(0); - } else if (u >= *m || v >= *n || u < 0 || v < 0) { - return(0); - } - - minterm1 = one; cuddRef(minterm1); - - /* Build minterm1 corresponding to this arc */ - for (i = lnx - 1; i>=0; i--) { - if (u & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lx[i]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lxn[i]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - minterm1 = w; - u >>= 1; - } - for (i = lny - 1; i>=0; i--) { - if (v & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, minterm1, ly[i]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lyn[i]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - minterm1 = w; - v >>= 1; - } - /* Create new constant node if necessary. - ** This call will never cause reordering. - */ - neW = cuddUniqueConst(dd, val); - if (neW == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - cuddRef(neW); - - w = Cudd_addIte(dd, minterm1, neW, *E); - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - Cudd_RecursiveDeref(dd, neW); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - Cudd_RecursiveDeref(dd, neW); - Cudd_RecursiveDeref(dd, *E); - *E = w; - } - return(1); - -} /* end of Cudd_addRead */ - - -/**Function******************************************************************** - - Synopsis [Reads in a graph (without labels) given as a list of arcs.] - - Description [Reads in a graph (without labels) given as an adjacency - matrix. The first line of the input contains the numbers of rows and - columns of the adjacency matrix. The remaining lines contain the arcs - of the graph, one per line. Each arc is described by two integers, - i.e., the row and column number, or the indices of the two endpoints. - Cudd_bddRead produces a BDD that depends on two sets of variables: x - and y. The x variables (x\[0\] ... x\[nx-1\]) encode - the row index and the y variables (y\[0\] ... y\[ny-1\]) encode the - column index. x\[0\] and y\[0\] are the most significant bits in the - indices. - The variables may already exist or may be created by the function. - The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.<p> - On input, nx and ny hold the numbers of row and column variables already - in existence. On output, they hold the numbers of row and column - variables actually used by the matrix. When Cudd_bddRead creates the - variable arrays, the index of x\[i\] is bx+i*sx, and the index of - y\[i\] is by+i*sy. When some variables already exist, Cudd_bddRead - expects the indices of the existing x variables to be bx+i*sx, and the - indices of the existing y variables to be by+i*sy.<p> - m and n are set to the numbers of rows and columns of the - matrix. Their values on input are immaterial. The BDD for the graph - is returned in E, and its reference count is > 0. Cudd_bddRead returns - 1 in case of success; 0 otherwise.] - - SideEffects [nx and ny are set to the numbers of row and column - variables. m and n are set to the numbers of rows and columns. x and y - are possibly extended to represent the array of row and column - variables.] - - SeeAlso [Cudd_addHarwell Cudd_addRead] - -******************************************************************************/ -int -Cudd_bddRead( - FILE * fp /* input file pointer */, - DdManager * dd /* DD manager */, - DdNode ** E /* characteristic function of the graph */, - DdNode *** x /* array of row variables */, - DdNode *** y /* array of column variables */, - int * nx /* number or row variables */, - int * ny /* number or column variables */, - int * m /* number of rows */, - int * n /* number of columns */, - int bx /* first index of row variables */, - int sx /* step of row variables */, - int by /* first index of column variables */, - int sy /* step of column variables */) -{ - DdNode *one, *zero; - DdNode *w; - DdNode *minterm1; - int u, v, err, i, nv; - int lnx, lny; - DdNode **lx, **ly; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - err = fscanf(fp, "%d %d", &u, &v); - if (err == EOF) { - return(0); - } else if (err != 2) { - return(0); - } - - *m = u; - /* Compute the number of x variables. */ - lx = *x; - u--; /* row and column numbers start from 0 */ - for (lnx=0; u > 0; lnx++) { - u >>= 1; - } - if (lnx > *nx) { - *x = lx = REALLOC(DdNode *, *x, lnx); - if (lx == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } - - *n = v; - /* Compute the number of y variables. */ - ly = *y; - v--; /* row and column numbers start from 0 */ - for (lny=0; v > 0; lny++) { - v >>= 1; - } - if (lny > *ny) { - *y = ly = REALLOC(DdNode *, *y, lny); - if (ly == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } - - /* Create all new variables. */ - for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) { - do { - dd->reordered = 0; - lx[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (lx[i] == NULL) return(0); - cuddRef(lx[i]); - } - for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) { - do { - dd->reordered = 0; - ly[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (ly[i] == NULL) return(0); - cuddRef(ly[i]); - } - *nx = lnx; - *ny = lny; - - *E = zero; /* this call will never cause reordering */ - cuddRef(*E); - - while (! feof(fp)) { - err = fscanf(fp, "%d %d", &u, &v); - if (err == EOF) { - break; - } else if (err != 2) { - return(0); - } else if (u >= *m || v >= *n || u < 0 || v < 0) { - return(0); - } - - minterm1 = one; cuddRef(minterm1); - - /* Build minterm1 corresponding to this arc. */ - for (i = lnx - 1; i>=0; i--) { - if (u & 1) { - w = Cudd_bddAnd(dd, minterm1, lx[i]); - } else { - w = Cudd_bddAnd(dd, minterm1, Cudd_Not(lx[i])); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd,minterm1); - minterm1 = w; - u >>= 1; - } - for (i = lny - 1; i>=0; i--) { - if (v & 1) { - w = Cudd_bddAnd(dd, minterm1, ly[i]); - } else { - w = Cudd_bddAnd(dd, minterm1, Cudd_Not(ly[i])); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - minterm1 = w; - v >>= 1; - } - - w = Cudd_bddAnd(dd, Cudd_Not(minterm1), Cudd_Not(*E)); - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - w = Cudd_Not(w); - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - Cudd_RecursiveDeref(dd, *E); - *E = w; - } - return(1); - -} /* end of Cudd_bddRead */ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddRef.c b/src/bdd/cudd/cuddRef.c deleted file mode 100644 index a9241f3d..00000000 --- a/src/bdd/cudd/cuddRef.c +++ /dev/null @@ -1,781 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddRef.c] - - PackageName [cudd] - - Synopsis [Functions that manipulate the reference counts.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_Ref() - <li> Cudd_RecursiveDeref() - <li> Cudd_IterDerefBdd() - <li> Cudd_DelayedDerefBdd() - <li> Cudd_RecursiveDerefZdd() - <li> Cudd_Deref() - <li> Cudd_CheckZeroRef() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddReclaim() - <li> cuddReclaimZdd() - <li> cuddClearDeathRow() - <li> cuddShrinkDeathRow() - <li> cuddIsInDeathRow() - <li> cuddTimesInDeathRow() - </ul> - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddRef.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Increases the reference count of a node, if it is not - saturated.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_RecursiveDeref Cudd_Deref] - -******************************************************************************/ -void -Cudd_Ref( - DdNode * n) -{ - - n = Cudd_Regular(n); - - cuddSatInc(n->ref); - -} /* end of Cudd_Ref */ - - -/**Function******************************************************************** - - Synopsis [Decreases the reference count of node n.] - - Description [Decreases the reference count of node n. If n dies, - recursively decreases the reference counts of its children. It is - used to dispose of a DD that is no longer needed.] - - SideEffects [None] - - SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDerefZdd] - -******************************************************************************/ -void -Cudd_RecursiveDeref( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack = table->stack; - int SP = 1; - - unsigned int live = table->keys - table->dead; - if (live > table->peakLiveNodes) { - table->peakLiveNodes = live; - } - - N = Cudd_Regular(n); - - do { -#ifdef DD_DEBUG - assert(N->ref != 0); -#endif - - if (N->ref == 1) { - N->ref = 0; - table->dead++; -#ifdef DD_STATS - table->nodesDropped++; -#endif - if (cuddIsConstant(N)) { - table->constants.dead++; - N = stack[--SP]; - } else { - ord = table->perm[N->index]; - stack[SP++] = Cudd_Regular(cuddE(N)); - table->subtables[ord].dead++; - N = cuddT(N); - } - } else { - cuddSatDec(N->ref); - N = stack[--SP]; - } - } while (SP != 0); - -} /* end of Cudd_RecursiveDeref */ - - -/**Function******************************************************************** - - Synopsis [Decreases the reference count of BDD node n.] - - Description [Decreases the reference count of node n. If n dies, - recursively decreases the reference counts of its children. It is - used to dispose of a BDD that is no longer needed. It is more - efficient than Cudd_RecursiveDeref, but it cannot be used on - ADDs. The greater efficiency comes from being able to assume that no - constant node will ever die as a result of a call to this - procedure.] - - SideEffects [None] - - SeeAlso [Cudd_RecursiveDeref Cudd_DelayedDerefBdd] - -******************************************************************************/ -void -Cudd_IterDerefBdd( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack = table->stack; - int SP = 1; - - unsigned int live = table->keys - table->dead; - if (live > table->peakLiveNodes) { - table->peakLiveNodes = live; - } - - N = Cudd_Regular(n); - - do { -#ifdef DD_DEBUG - assert(N->ref != 0); -#endif - - if (N->ref == 1) { - N->ref = 0; - table->dead++; -#ifdef DD_STATS - table->nodesDropped++; -#endif - ord = table->perm[N->index]; - stack[SP++] = Cudd_Regular(cuddE(N)); - table->subtables[ord].dead++; - N = cuddT(N); - } else { - cuddSatDec(N->ref); - N = stack[--SP]; - } - } while (SP != 0); - -} /* end of Cudd_IterDerefBdd */ - - -/**Function******************************************************************** - - Synopsis [Decreases the reference count of BDD node n.] - - Description [Enqueues node n for later dereferencing. If the queue - is full decreases the reference count of the oldest node N to make - room for n. If N dies, recursively decreases the reference counts of - its children. It is used to dispose of a BDD that is currently not - needed, but may be useful again in the near future. The dereferencing - proper is done as in Cudd_IterDerefBdd.] - - SideEffects [None] - - SeeAlso [Cudd_RecursiveDeref Cudd_IterDerefBdd] - -******************************************************************************/ -void -Cudd_DelayedDerefBdd( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack; - int SP; - - unsigned int live = table->keys - table->dead; - if (live > table->peakLiveNodes) { - table->peakLiveNodes = live; - } - - n = Cudd_Regular(n); -#ifdef DD_DEBUG - assert(n->ref != 0); -#endif - -#ifdef DD_NO_DEATH_ROW - N = n; -#else - if (cuddIsConstant(n) || n->ref > 1) { -#ifdef DD_DEBUG - assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table))); -#endif - cuddSatDec(n->ref); - return; - } - - N = table->deathRow[table->nextDead]; - - if (N != NULL) { -#endif -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(N)); -#endif - stack = table->stack; - SP = 1; - do { -#ifdef DD_DEBUG - assert(N->ref != 0); -#endif - if (N->ref == 1) { - N->ref = 0; - table->dead++; -#ifdef DD_STATS - table->nodesDropped++; -#endif - ord = table->perm[N->index]; - stack[SP++] = Cudd_Regular(cuddE(N)); - table->subtables[ord].dead++; - N = cuddT(N); - } else { - cuddSatDec(N->ref); - N = stack[--SP]; - } - } while (SP != 0); -#ifndef DD_NO_DEATH_ROW - } - table->deathRow[table->nextDead] = n; - - /* Udate insertion point. */ - table->nextDead++; - table->nextDead &= table->deadMask; -#if 0 - if (table->nextDead == table->deathRowDepth) { - if (table->deathRowDepth < table->looseUpTo / 2) { - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long) = MMoutOfMemory; - DdNodePtr *newRow; - MMoutOfMemory = Cudd_OutOfMem; - newRow = REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth); - MMoutOfMemory = saveHandler; - if (newRow == NULL) { - table->nextDead = 0; - } else { - int i; - table->memused += table->deathRowDepth; - i = table->deathRowDepth; - table->deathRowDepth <<= 1; - for (; i < table->deathRowDepth; i++) { - newRow[i] = NULL; - } - table->deadMask = table->deathRowDepth - 1; - table->deathRow = newRow; - } - } else { - table->nextDead = 0; - } - } -#endif -#endif - -} /* end of Cudd_DelayedDerefBdd */ - - -/**Function******************************************************************** - - Synopsis [Decreases the reference count of ZDD node n.] - - Description [Decreases the reference count of ZDD node n. If n dies, - recursively decreases the reference counts of its children. It is - used to dispose of a ZDD that is no longer needed.] - - SideEffects [None] - - SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref] - -******************************************************************************/ -void -Cudd_RecursiveDerefZdd( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack = table->stack; - int SP = 1; - - N = n; - - do { -#ifdef DD_DEBUG - assert(N->ref != 0); -#endif - - cuddSatDec(N->ref); - - if (N->ref == 0) { - table->deadZ++; -#ifdef DD_STATS - table->nodesDropped++; -#endif -#ifdef DD_DEBUG - assert(!cuddIsConstant(N)); -#endif - ord = table->permZ[N->index]; - stack[SP++] = cuddE(N); - table->subtableZ[ord].dead++; - N = cuddT(N); - } else { - N = stack[--SP]; - } - } while (SP != 0); - -} /* end of Cudd_RecursiveDerefZdd */ - - -/**Function******************************************************************** - - Synopsis [Decreases the reference count of node.] - - Description [Decreases the reference count of node. It is primarily - used in recursive procedures to decrease the ref count of a result - node before returning it. This accomplishes the goal of removing the - protection applied by a previous Cudd_Ref.] - - SideEffects [None] - - SeeAlso [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref] - -******************************************************************************/ -void -Cudd_Deref( - DdNode * node) -{ - node = Cudd_Regular(node); - cuddSatDec(node->ref); - -} /* end of Cudd_Deref */ - - -/**Function******************************************************************** - - Synopsis [Checks the unique table for nodes with non-zero reference - counts.] - - Description [Checks the unique table for nodes with non-zero - reference counts. It is normally called before Cudd_Quit to make sure - that there are no memory leaks due to missing Cudd_RecursiveDeref's. - Takes into account that reference counts may saturate and that the - basic constants and the projection functions are referenced by the - manager. Returns the number of nodes with non-zero reference count. - (Except for the cases mentioned above.)] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_CheckZeroRef( - DdManager * manager) -{ - int size; - int i, j; - int remain; /* the expected number of remaining references to one */ - DdNodePtr *nodelist; - DdNode *node; - DdNode *sentinel = &(manager->sentinel); - DdSubtable *subtable; - int count = 0; - int index; - -#ifndef DD_NO_DEATH_ROW - cuddClearDeathRow(manager); -#endif - - /* First look at the BDD/ADD subtables. */ - remain = 1; /* reference from the manager */ - size = manager->size; - remain += 2 * size; /* reference from the BDD projection functions */ - - for (i = 0; i < size; i++) { - subtable = &(manager->subtables[i]); - nodelist = subtable->nodelist; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - while (node != sentinel) { - if (node->ref != 0 && node->ref != DD_MAXREF) { - index = (int) node->index; - if (node != manager->vars[index]) { - count++; - } else { - if (node->ref != 1) { - count++; - } - } - } - node = node->next; - } - } - } - - /* Then look at the ZDD subtables. */ - size = manager->sizeZ; - if (size) /* references from ZDD universe */ - remain += 2; - - for (i = 0; i < size; i++) { - subtable = &(manager->subtableZ[i]); - nodelist = subtable->nodelist; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - while (node != NULL) { - if (node->ref != 0 && node->ref != DD_MAXREF) { - index = (int) node->index; - if (node == manager->univ[manager->permZ[index]]) { - if (node->ref > 2) { - count++; - } - } else { - count++; - } - } - node = node->next; - } - } - } - - /* Now examine the constant table. Plusinfinity, minusinfinity, and - ** zero are referenced by the manager. One is referenced by the - ** manager, by the ZDD universe, and by all projection functions. - ** All other nodes should have no references. - */ - nodelist = manager->constants.nodelist; - for (j = 0; (unsigned) j < manager->constants.slots; j++) { - node = nodelist[j]; - while (node != NULL) { - if (node->ref != 0 && node->ref != DD_MAXREF) { - if (node == manager->one) { - if ((int) node->ref != remain) { - count++; - } - } else if (node == manager->zero || - node == manager->plusinfinity || - node == manager->minusinfinity) { - if (node->ref != 1) { - count++; - } - } else { - count++; - } - } - node = node->next; - } - } - return(count); - -} /* end of Cudd_CheckZeroRef */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Brings children of a dead node back.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddReclaimZdd] - -******************************************************************************/ -void -cuddReclaim( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack = table->stack; - int SP = 1; - double initialDead = table->dead; - - N = Cudd_Regular(n); - -#ifdef DD_DEBUG - assert(N->ref == 0); -#endif - - do { - if (N->ref == 0) { - N->ref = 1; - table->dead--; - if (cuddIsConstant(N)) { - table->constants.dead--; - N = stack[--SP]; - } else { - ord = table->perm[N->index]; - stack[SP++] = Cudd_Regular(cuddE(N)); - table->subtables[ord].dead--; - N = cuddT(N); - } - } else { - cuddSatInc(N->ref); - N = stack[--SP]; - } - } while (SP != 0); - - N = Cudd_Regular(n); - cuddSatDec(N->ref); - table->reclaimed += initialDead - table->dead; - -} /* end of cuddReclaim */ - - -/**Function******************************************************************** - - Synopsis [Brings children of a dead ZDD node back.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddReclaim] - -******************************************************************************/ -void -cuddReclaimZdd( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack = table->stack; - int SP = 1; - - N = n; - -#ifdef DD_DEBUG - assert(N->ref == 0); -#endif - - do { - cuddSatInc(N->ref); - - if (N->ref == 1) { - table->deadZ--; - table->reclaimed++; -#ifdef DD_DEBUG - assert(!cuddIsConstant(N)); -#endif - ord = table->permZ[N->index]; - stack[SP++] = cuddE(N); - table->subtableZ[ord].dead--; - N = cuddT(N); - } else { - N = stack[--SP]; - } - } while (SP != 0); - - cuddSatDec(n->ref); - -} /* end of cuddReclaimZdd */ - - -/**Function******************************************************************** - - Synopsis [Shrinks the death row.] - - Description [Shrinks the death row by a factor of four.] - - SideEffects [None] - - SeeAlso [cuddClearDeathRow] - -******************************************************************************/ -void -cuddShrinkDeathRow( - DdManager *table) -{ -#ifndef DD_NO_DEATH_ROW - int i; - - if (table->deathRowDepth > 3) { - for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) { - if (table->deathRow[i] == NULL) break; - Cudd_IterDerefBdd(table,table->deathRow[i]); - table->deathRow[i] = NULL; - } - table->deathRowDepth /= 4; - table->deadMask = table->deathRowDepth - 2; - if ((unsigned) table->nextDead > table->deadMask) { - table->nextDead = 0; - } - table->deathRow = REALLOC(DdNodePtr, table->deathRow, - table->deathRowDepth); - } -#endif - -} /* end of cuddShrinkDeathRow */ - - -/**Function******************************************************************** - - Synopsis [Clears the death row.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef - cuddGarbageCollect] - -******************************************************************************/ -void -cuddClearDeathRow( - DdManager *table) -{ -#ifndef DD_NO_DEATH_ROW - int i; - - for (i = 0; i < table->deathRowDepth; i++) { - if (table->deathRow[i] == NULL) break; - Cudd_IterDerefBdd(table,table->deathRow[i]); - table->deathRow[i] = NULL; - } -#ifdef DD_DEBUG - for (; i < table->deathRowDepth; i++) { - assert(table->deathRow[i] == NULL); - } -#endif - table->nextDead = 0; -#endif - -} /* end of cuddClearDeathRow */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a node is in the death row.] - - Description [Checks whether a node is in the death row. Returns the - position of the first occurrence if the node is present; -1 - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow] - -******************************************************************************/ -int -cuddIsInDeathRow( - DdManager *dd, - DdNode *f) -{ -#ifndef DD_NO_DEATH_ROW - int i; - - for (i = 0; i < dd->deathRowDepth; i++) { - if (f == dd->deathRow[i]) { - return(i); - } - } -#endif - - return(-1); - -} /* end of cuddIsInDeathRow */ - - -/**Function******************************************************************** - - Synopsis [Counts how many times a node is in the death row.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow] - -******************************************************************************/ -int -cuddTimesInDeathRow( - DdManager *dd, - DdNode *f) -{ - int count = 0; -#ifndef DD_NO_DEATH_ROW - int i; - - for (i = 0; i < dd->deathRowDepth; i++) { - count += f == dd->deathRow[i]; - } -#endif - - return(count); - -} /* end of cuddTimesInDeathRow */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddReorder.c b/src/bdd/cudd/cuddReorder.c deleted file mode 100644 index 1387196f..00000000 --- a/src/bdd/cudd/cuddReorder.c +++ /dev/null @@ -1,2090 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddReorder.c] - - PackageName [cudd] - - Synopsis [Functions for dynamic variable reordering.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_ReduceHeap() - <li> Cudd_ShuffleHeap() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddDynamicAllocNode() - <li> cuddSifting() - <li> cuddSwapping() - <li> cuddNextHigh() - <li> cuddNextLow() - <li> cuddSwapInPlace() - <li> cuddBddAlignToZdd() - </ul> - Static procedures included in this module: - <ul> - <li> ddUniqueCompare() - <li> ddSwapAny() - <li> ddSiftingAux() - <li> ddSiftingUp() - <li> ddSiftingDown() - <li> ddSiftingBackward() - <li> ddReorderPreprocess() - <li> ddReorderPostprocess() - <li> ddShuffle() - <li> ddSiftUp() - <li> bddFixTree() - </ul>] - - Author [Shipra Panda, Bernard Plessier, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_MAX_SUBTABLE_SPARSITY 8 -#define DD_SHRINK_FACTOR 2 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static int *entry; - -int ddTotalNumberSwapping; -#ifdef DD_STATS -int ddTotalNISwaps; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddUniqueCompare ARGS((int *ptrX, int *ptrY)); -static Move * ddSwapAny ARGS((DdManager *table, int x, int y)); -static int ddSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static Move * ddSiftingUp ARGS((DdManager *table, int y, int xLow)); -static Move * ddSiftingDown ARGS((DdManager *table, int x, int xHigh)); -static int ddSiftingBackward ARGS((DdManager *table, int size, Move *moves)); -static int ddReorderPreprocess ARGS((DdManager *table)); -static int ddReorderPostprocess ARGS((DdManager *table)); -static int ddShuffle ARGS((DdManager *table, int *permutation)); -static int ddSiftUp ARGS((DdManager *table, int x, int xLow)); -static void bddFixTree ARGS((DdManager *table, MtrNode *treenode)); -static int ddUpdateMtrTree ARGS((DdManager *table, MtrNode *treenode, int *perm, int *invperm)); -static int ddCheckPermuation ARGS((DdManager *table, MtrNode *treenode, int *perm, int *invperm)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Main dynamic reordering routine.] - - Description [Main dynamic reordering routine. - Calls one of the possible reordering procedures: - <ul> - <li>Swapping - <li>Sifting - <li>Symmetric Sifting - <li>Group Sifting - <li>Window Permutation - <li>Simulated Annealing - <li>Genetic Algorithm - <li>Dynamic Programming (exact) - </ul> - - For sifting, symmetric sifting, group sifting, and window - permutation it is possible to request reordering to convergence.<p> - - The core of all methods is the reordering procedure - cuddSwapInPlace() which swaps two adjacent variables and is based - on Rudell's paper. - Returns 1 in case of success; 0 otherwise. In the case of symmetric - sifting (with and without convergence) returns 1 plus the number of - symmetric variables, in case of success.] - - SideEffects [Changes the variable order for all diagrams and clears - the cache.] - -******************************************************************************/ -int -Cudd_ReduceHeap( - DdManager * table /* DD manager */, - Cudd_ReorderingType heuristic /* method used for reordering */, - int minsize /* bound below which no reordering occurs */) -{ - DdHook *hook; - int result; - unsigned int nextDyn; -#ifdef DD_STATS - unsigned int initialSize; - unsigned int finalSize; -#endif - long localTime; - - /* Don't reorder if there are too many dead nodes. */ - if (table->keys - table->dead < (unsigned) minsize) - return(1); - - if (heuristic == CUDD_REORDER_SAME) { - heuristic = table->autoMethod; - } - if (heuristic == CUDD_REORDER_NONE) { - return(1); - } - - /* This call to Cudd_ReduceHeap does initiate reordering. Therefore - ** we count it. - */ - table->reorderings++; - - localTime = util_cpu_time(); - - /* Run the hook functions. */ - hook = table->preReorderingHook; - while (hook != NULL) { - int res = (hook->f)(table, "BDD", (void *)heuristic); - if (res == 0) return(0); - hook = hook->next; - } - - if (!ddReorderPreprocess(table)) return(0); - ddTotalNumberSwapping = 0; - - if (table->keys > table->peakLiveNodes) { - table->peakLiveNodes = table->keys; - } -#ifdef DD_STATS - initialSize = table->keys - table->isolated; - ddTotalNISwaps = 0; - - switch(heuristic) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - (void) fprintf(table->out,"#:I_RANDOM "); - break; - case CUDD_REORDER_SIFT: - case CUDD_REORDER_SIFT_CONVERGE: - case CUDD_REORDER_SYMM_SIFT: - case CUDD_REORDER_SYMM_SIFT_CONV: - case CUDD_REORDER_GROUP_SIFT: - case CUDD_REORDER_GROUP_SIFT_CONV: - (void) fprintf(table->out,"#:I_SIFTING "); - break; - case CUDD_REORDER_WINDOW2: - case CUDD_REORDER_WINDOW3: - case CUDD_REORDER_WINDOW4: - case CUDD_REORDER_WINDOW2_CONV: - case CUDD_REORDER_WINDOW3_CONV: - case CUDD_REORDER_WINDOW4_CONV: - (void) fprintf(table->out,"#:I_WINDOW "); - break; - case CUDD_REORDER_ANNEALING: - (void) fprintf(table->out,"#:I_ANNEAL "); - break; - case CUDD_REORDER_GENETIC: - (void) fprintf(table->out,"#:I_GENETIC "); - break; - case CUDD_REORDER_LINEAR: - case CUDD_REORDER_LINEAR_CONVERGE: - (void) fprintf(table->out,"#:I_LINSIFT "); - break; - case CUDD_REORDER_EXACT: - (void) fprintf(table->out,"#:I_EXACT "); - break; - default: - return(0); - } - (void) fprintf(table->out,"%8d: initial size",initialSize); -#endif - - /* See if we should use alternate threshold for maximum growth. */ - if (table->reordCycle && table->reorderings % table->reordCycle == 0) { - double saveGrowth = table->maxGrowth; - table->maxGrowth = table->maxGrowthAlt; - result = cuddTreeSifting(table,heuristic); - table->maxGrowth = saveGrowth; - } else { - result = cuddTreeSifting(table,heuristic); - } - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - finalSize = table->keys - table->isolated; - (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); - (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", - ((double)(util_cpu_time() - localTime)/1000.0)); - (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", - ddTotalNumberSwapping); - (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps); -#endif - - if (result == 0) - return(0); - - if (!ddReorderPostprocess(table)) - return(0); - - if (table->realign) { - if (!cuddZddAlignToBdd(table)) - return(0); - } - - nextDyn = (table->keys - table->constants.keys + 1) * - DD_DYN_RATIO + table->constants.keys; - if (table->reorderings < 20 || nextDyn > table->nextDyn) - table->nextDyn = nextDyn; - else - table->nextDyn += 20; - table->reordered = 1; - - /* Run hook functions. */ - hook = table->postReorderingHook; - while (hook != NULL) { - int res = (hook->f)(table, "BDD", (void *)localTime); - if (res == 0) return(0); - hook = hook->next; - } - /* Update cumulative reordering time. */ - table->reordTime += util_cpu_time() - localTime; - - return(result); - -} /* end of Cudd_ReduceHeap */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables according to given permutation.] - - Description [Reorders variables according to given permutation. - The i-th entry of the permutation array contains the index of the variable - that should be brought to the i-th level. The size of the array should be - equal or greater to the number of variables currently in use. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [Changes the variable order for all diagrams and clears - the cache.] - - SeeAlso [Cudd_ReduceHeap] - -******************************************************************************/ -int -Cudd_ShuffleHeap( - DdManager * table /* DD manager */, - int * permutation /* required variable permutation */) -{ - - int result; - int i; - int identity = 1; - int *perm; - - /* Don't waste time in case of identity permutation. */ - for (i = 0; i < table->size; i++) { - if (permutation[i] != table->invperm[i]) { - identity = 0; - break; - } - } - if (identity == 1) { - return(1); - } - if (!ddReorderPreprocess(table)) return(0); - if (table->keys > table->peakLiveNodes) { - table->peakLiveNodes = table->keys; - } - - perm = ALLOC(int, table->size); - for (i = 0; i < table->size; i++) - perm[permutation[i]] = i; - if (!ddCheckPermuation(table,table->tree,perm,permutation)) { - FREE(perm); - return(0); - } - if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) { - FREE(perm); - return(0); - } - FREE(perm); - - result = ddShuffle(table,permutation); - - if (!ddReorderPostprocess(table)) return(0); - - return(result); - -} /* end of Cudd_ShuffleHeap */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Dynamically allocates a Node.] - - Description [Dynamically allocates a Node. This procedure is similar - to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage - collection, because during reordering there are no dead nodes. - Returns a pointer to a new node if successful; NULL is memory is - full.] - - SideEffects [None] - - SeeAlso [cuddAllocNode] - -******************************************************************************/ -DdNode * -cuddDynamicAllocNode( - DdManager * table) -{ - int i; - DdNodePtr *mem; - DdNode *list, *node; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - if (table->nextFree == NULL) { /* free list is empty */ - /* Try to allocate a new block. */ - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1); - MMoutOfMemory = saveHandler; - if (mem == NULL && table->stash != NULL) { - FREE(table->stash); - table->stash = NULL; - /* Inhibit resizing of tables. */ - table->maxCacheHard = table->cacheSlots - 1; - table->cacheSlack = -(table->cacheSlots + 1); - for (i = 0; i < table->size; i++) { - table->subtables[i].maxKeys <<= 2; - } - mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); - } - if (mem == NULL) { - /* Out of luck. Call the default handler to do - ** whatever it specifies for a failed malloc. If this - ** handler returns, then set error code, print - ** warning, and return. */ - (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); - table->errorCode = CUDD_MEMORY_OUT; -#ifdef DD_VERBOSE - (void) fprintf(table->err, - "cuddDynamicAllocNode: out of memory"); - (void) fprintf(table->err,"Memory in use = %ld\n", - table->memused); -#endif - return(NULL); - } else { /* successful allocation; slice memory */ - unsigned long offset; - table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); - mem[0] = (DdNode *) table->memoryList; - table->memoryList = mem; - - /* Here we rely on the fact that the size of a DdNode is a - ** power of 2 and a multiple of the size of a pointer. - ** If we align one node, all the others will be aligned - ** as well. */ - offset = (unsigned long) mem & (sizeof(DdNode) - 1); - mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); -#ifdef DD_DEBUG - assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0); -#endif - list = (DdNode *) mem; - - i = 1; - do { - list[i - 1].next = &list[i]; - } while (++i < DD_MEM_CHUNK); - - list[DD_MEM_CHUNK - 1].next = NULL; - - table->nextFree = &list[0]; - } - } /* if free list empty */ - - node = table->nextFree; - table->nextFree = node->next; - return (node); - -} /* end of cuddDynamicAllocNode */ - - -/**Function******************************************************************** - - Synopsis [Implementation of Rudell's sifting algorithm.] - - Description [Implementation of Rudell's sifting algorithm. - Assumes that no dead nodes are present. - <ol> - <li> Order all the variables according to the number of entries - in each unique table. - <li> Sift the variable up and down, remembering each time the - total size of the DD heap. - <li> Select the best permutation. - <li> Repeat 3 and 4 for all variables. - </ol> - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; -#ifdef DD_STATS - int previousSize; -#endif - - size = table->size; - - /* Find order in which to sift variables. */ - var = NULL; - entry = ALLOC(int,size); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddSiftingOutOfMem; - } - var = ALLOC(int,size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->perm[i]; - entry[i] = table->subtables[x].keys; - var[i] = i; - } - - qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->perm[var[i]]; - - if (x < lower || x > upper || table->subtables[x].bindVar == 1) - continue; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddSiftingAux(table, x, lower, upper); - if (!result) goto cuddSiftingOutOfMem; -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"+"); /* should never happen */ - (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - FREE(var); - FREE(entry); - - return(1); - -cuddSiftingOutOfMem: - - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddSifting */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.] - - Description [Implementation of Plessier's algorithm that reorders - variables by a sequence of (non-adjacent) swaps. - <ol> - <li> Select two variables (RANDOM or HEURISTIC). - <li> Permute these variables. - <li> If the nodes have decreased accept the permutation. - <li> Otherwise reconstruct the original heap. - <li> Loop. - </ol> - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddSwapping( - DdManager * table, - int lower, - int upper, - Cudd_ReorderingType heuristic) -{ - int i, j; - int max, keys; - int nvars; - int x, y; - int iterate; - int previousSize; - Move *moves, *move; - int pivot; - int modulo; - int result; - -#ifdef DD_DEBUG - /* Sanity check */ - assert(lower >= 0 && upper < table->size && lower <= upper); -#endif - - nvars = upper - lower + 1; - iterate = nvars; - - for (i = 0; i < iterate; i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { - max = -1; - for (j = lower; j <= upper; j++) { - if ((keys = table->subtables[j].keys) > max) { - max = keys; - pivot = j; - } - } - - modulo = upper - pivot; - if (modulo == 0) { - y = pivot; - } else{ - y = pivot + 1 + ((int) Cudd_Random() % modulo); - } - - modulo = pivot - lower - 1; - if (modulo < 1) { - x = lower; - } else{ - do { - x = (int) Cudd_Random() % modulo; - } while (x == y); - } - } else { - x = ((int) Cudd_Random() % nvars) + lower; - do { - y = ((int) Cudd_Random() % nvars) + lower; - } while (x == y); - } - previousSize = table->keys - table->isolated; - moves = ddSwapAny(table,x,y); - if (moves == NULL) goto cuddSwappingOutOfMem; - result = ddSiftingBackward(table,previousSize,moves); - if (!result) goto cuddSwappingOutOfMem; - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif -#if 0 - (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n", - table->keys - table->isolated); -#endif - } - - return(1); - -cuddSwappingOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(0); - -} /* end of cuddSwapping */ - - -/**Function******************************************************************** - - Synopsis [Finds the next subtable with a larger index.] - - Description [Finds the next subtable with a larger index. Returns the - index.] - - SideEffects [None] - - SeeAlso [cuddNextLow] - -******************************************************************************/ -int -cuddNextHigh( - DdManager * table, - int x) -{ - return(x+1); - -} /* end of cuddNextHigh */ - - -/**Function******************************************************************** - - Synopsis [Finds the next subtable with a smaller index.] - - Description [Finds the next subtable with a smaller index. Returns the - index.] - - SideEffects [None] - - SeeAlso [cuddNextHigh] - -******************************************************************************/ -int -cuddNextLow( - DdManager * table, - int x) -{ - return(x-1); - -} /* end of cuddNextLow */ - - -/**Function******************************************************************** - - Synopsis [Swaps two adjacent variables.] - - Description [Swaps two adjacent variables. It assumes that no dead - nodes are present on entry to this procedure. The procedure then - guarantees that no dead nodes will be present when it terminates. - cuddSwapInPlace assumes that x < y. Returns the number of keys in - the table if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddSwapInPlace( - DdManager * table, - int x, - int y) -{ - DdNodePtr *xlist, *ylist; - int xindex, yindex; - int xslots, yslots; - int xshift, yshift; - int oldxkeys, oldykeys; - int newxkeys, newykeys; - int comple, newcomplement; - int i; - Cudd_VariableType varType; - Cudd_LazyGroupType groupType; - int posn; - int isolated; - DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; - DdNode *g,*next; - DdNodePtr *previousP; - DdNode *tmp; - DdNode *sentinel = &(table->sentinel); - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - -#if DD_DEBUG - int count,idcheck; -#endif - -#ifdef DD_DEBUG - assert(x < y); - assert(cuddNextHigh(table,x) == y); - assert(table->subtables[x].keys != 0); - assert(table->subtables[y].keys != 0); - assert(table->subtables[x].dead == 0); - assert(table->subtables[y].dead == 0); -#endif - - ddTotalNumberSwapping++; - - /* Get parameters of x subtable. */ - xindex = table->invperm[x]; - xlist = table->subtables[x].nodelist; - oldxkeys = table->subtables[x].keys; - xslots = table->subtables[x].slots; - xshift = table->subtables[x].shift; - - /* Get parameters of y subtable. */ - yindex = table->invperm[y]; - ylist = table->subtables[y].nodelist; - oldykeys = table->subtables[y].keys; - yslots = table->subtables[y].slots; - yshift = table->subtables[y].shift; - - if (!cuddTestInteract(table,xindex,yindex)) { -#ifdef DD_STATS - ddTotalNISwaps++; -#endif - newxkeys = oldxkeys; - newykeys = oldykeys; - } else { - newxkeys = 0; - newykeys = oldykeys; - - /* Check whether the two projection functions involved in this - ** swap are isolated. At the end, we'll be able to tell how many - ** isolated projection functions are there by checking only these - ** two functions again. This is done to eliminate the isolated - ** projection functions from the node count. - */ - isolated = - ((table->vars[xindex]->ref == 1) + - (table->vars[yindex]->ref == 1)); - - /* The nodes in the x layer that do not depend on - ** y will stay there; the others are put in a chain. - ** The chain is handled as a LIFO; g points to the beginning. - */ - g = NULL; - if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) && - oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) { - for (i = 0; i < xslots; i++) { - previousP = &(xlist[i]); - f = *previousP; - while (f != sentinel) { - next = f->next; - f1 = cuddT(f); f0 = cuddE(f); - if (f1->index != (DdHalfWord) yindex && - Cudd_Regular(f0)->index != (DdHalfWord) yindex) { - /* stays */ - newxkeys++; - *previousP = f; - previousP = &(f->next); - } else { - f->index = yindex; - f->next = g; - g = f; - } - f = next; - } /* while there are elements in the collision chain */ - *previousP = sentinel; - } /* for each slot of the x subtable */ - } else { /* resize xlist */ - DdNode *h = NULL; - DdNodePtr *newxlist; - unsigned int newxslots; - int newxshift; - /* Empty current xlist. Nodes that stay go to list h; - ** nodes that move go to list g. */ - for (i = 0; i < xslots; i++) { - f = xlist[i]; - while (f != sentinel) { - next = f->next; - f1 = cuddT(f); f0 = cuddE(f); - if (f1->index != (DdHalfWord) yindex && - Cudd_Regular(f0)->index != (DdHalfWord) yindex) { - /* stays */ - f->next = h; - h = f; - newxkeys++; - } else { - f->index = yindex; - f->next = g; - g = f; - } - f = next; - } /* while there are elements in the collision chain */ - } /* for each slot of the x subtable */ - /* Decide size of new subtable. */ - if (oldxkeys > DD_MAX_SUBTABLE_DENSITY * xslots) { - newxshift = xshift - 1; - newxslots = xslots << 1; - } else { - newxshift = xshift + 1; - newxslots = xslots >> 1; - } - /* Try to allocate new table. Be ready to back off. */ - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - newxlist = ALLOC(DdNodePtr, newxslots); - MMoutOfMemory = saveHandler; - if (newxlist == NULL) { - (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i); - newxlist = xlist; - newxslots = xslots; - newxshift = xshift; - } else { - table->slots += (newxslots - xslots); - table->minDead = (unsigned) - (table->gcFrac * (double) table->slots); - table->cacheSlack = (int) - ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO - * table->slots) - 2 * (int) table->cacheSlots; - table->memused += (newxslots - xslots) * sizeof(DdNodePtr); - FREE(xlist); - xslots = newxslots; - xshift = newxshift; - xlist = newxlist; - } - /* Initialize new subtable. */ - for (i = 0; i < xslots; i++) { - xlist[i] = sentinel; - } - /* Move nodes that were parked in list h to their new home. */ - f = h; - while (f != NULL) { - next = f->next; - f1 = cuddT(f); - f0 = cuddE(f); - /* Check xlist for pair (f11,f01). */ - posn = ddHash(f1, f0, xshift); - /* For each element tmp in collision list xlist[posn]. */ - previousP = &(xlist[posn]); - tmp = *previousP; - while (f1 < cuddT(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - f->next = *previousP; - *previousP = f; - f = next; - } - } - -#ifdef DD_COUNT - table->swapSteps += oldxkeys - newxkeys; -#endif - /* Take care of the x nodes that must be re-expressed. - ** They form a linked list pointed by g. Their index has been - ** already changed to yindex. - */ - f = g; - while (f != NULL) { - next = f->next; - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(f1))); -#endif - if ((int) f1->index == yindex) { - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - f11 = f10 = f1; - } -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(f11))); -#endif - f0 = cuddE(f); - comple = Cudd_IsComplement(f0); - f0 = Cudd_Regular(f0); - if ((int) f0->index == yindex) { - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = f00 = f0; - } - if (comple) { - f01 = Cudd_Not(f01); - f00 = Cudd_Not(f00); - } - /* Decrease ref count of f1. */ - cuddSatDec(f1->ref); - /* Create the new T child. */ - if (f11 == f01) { - newf1 = f11; - cuddSatInc(newf1->ref); - } else { - /* Check xlist for triple (xindex,f11,f01). */ - posn = ddHash(f11, f01, xshift); - /* For each element newf1 in collision list xlist[posn]. */ - previousP = &(xlist[posn]); - newf1 = *previousP; - while (f11 < cuddT(newf1)) { - previousP = &(newf1->next); - newf1 = *previousP; - } - while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) { - previousP = &(newf1->next); - newf1 = *previousP; - } - if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { - cuddSatInc(newf1->ref); - } else { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto cuddSwapOutOfMem; - newf1->index = xindex; newf1->ref = 1; - cuddT(newf1) = f11; - cuddE(newf1) = f01; - /* Insert newf1 in the collision list xlist[posn]; - ** increase the ref counts of f11 and f01. - */ - newxkeys++; - newf1->next = *previousP; - *previousP = newf1; - cuddSatInc(f11->ref); - tmp = Cudd_Regular(f01); - cuddSatInc(tmp->ref); - } - } - cuddT(f) = newf1; -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(newf1))); -#endif - - /* Do the same for f0, keeping complement dots into account. */ - /* Decrease ref count of f0. */ - tmp = Cudd_Regular(f0); - cuddSatDec(tmp->ref); - /* Create the new E child. */ - if (f10 == f00) { - newf0 = f00; - tmp = Cudd_Regular(newf0); - cuddSatInc(tmp->ref); - } else { - /* make sure f10 is regular */ - newcomplement = Cudd_IsComplement(f10); - if (newcomplement) { - f10 = Cudd_Not(f10); - f00 = Cudd_Not(f00); - } - /* Check xlist for triple (xindex,f10,f00). */ - posn = ddHash(f10, f00, xshift); - /* For each element newf0 in collision list xlist[posn]. */ - previousP = &(xlist[posn]); - newf0 = *previousP; - while (f10 < cuddT(newf0)) { - previousP = &(newf0->next); - newf0 = *previousP; - } - while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) { - previousP = &(newf0->next); - newf0 = *previousP; - } - if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { - cuddSatInc(newf0->ref); - } else { /* no match */ - newf0 = cuddDynamicAllocNode(table); - if (newf0 == NULL) - goto cuddSwapOutOfMem; - newf0->index = xindex; newf0->ref = 1; - cuddT(newf0) = f10; - cuddE(newf0) = f00; - /* Insert newf0 in the collision list xlist[posn]; - ** increase the ref counts of f10 and f00. - */ - newxkeys++; - newf0->next = *previousP; - *previousP = newf0; - cuddSatInc(f10->ref); - tmp = Cudd_Regular(f00); - cuddSatInc(tmp->ref); - } - if (newcomplement) { - newf0 = Cudd_Not(newf0); - } - } - cuddE(f) = newf0; - - /* Insert the modified f in ylist. - ** The modified f does not already exists in ylist. - ** (Because of the uniqueness of the cofactors.) - */ - posn = ddHash(newf1, newf0, yshift); - newykeys++; - previousP = &(ylist[posn]); - tmp = *previousP; - while (newf1 < cuddT(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - f->next = *previousP; - *previousP = f; - f = next; - } /* while f != NULL */ - - /* GC the y layer. */ - - /* For each node f in ylist. */ - for (i = 0; i < yslots; i++) { - previousP = &(ylist[i]); - f = *previousP; - while (f != sentinel) { - next = f->next; - if (f->ref == 0) { - tmp = cuddT(f); - cuddSatDec(tmp->ref); - tmp = Cudd_Regular(cuddE(f)); - cuddSatDec(tmp->ref); - cuddDeallocNode(table,f); - newykeys--; - } else { - *previousP = f; - previousP = &(f->next); - } - f = next; - } /* while f */ - *previousP = sentinel; - } /* for i */ - -#if DD_DEBUG -#if 0 - (void) fprintf(table->out,"Swapping %d and %d\n",x,y); -#endif - count = 0; - idcheck = 0; - for (i = 0; i < yslots; i++) { - f = ylist[i]; - while (f != sentinel) { - count++; - if (f->index != (DdHalfWord) yindex) - idcheck++; - f = f->next; - } - } - if (count != newykeys) { - (void) fprintf(table->out, - "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n", - oldykeys,newykeys,count); - } - if (idcheck != 0) - (void) fprintf(table->out, - "Error in id's of ylist\twrong id's = %d\n", - idcheck); - count = 0; - idcheck = 0; - for (i = 0; i < xslots; i++) { - f = xlist[i]; - while (f != sentinel) { - count++; - if (f->index != (DdHalfWord) xindex) - idcheck++; - f = f->next; - } - } - if (count != newxkeys) { - (void) fprintf(table->out, - "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n", - oldxkeys,newxkeys,count); - } - if (idcheck != 0) - (void) fprintf(table->out, - "Error in id's of xlist\twrong id's = %d\n", - idcheck); -#endif - - isolated += (table->vars[xindex]->ref == 1) + - (table->vars[yindex]->ref == 1); - table->isolated += isolated; - } - - /* Set the appropriate fields in table. */ - table->subtables[x].nodelist = ylist; - table->subtables[x].slots = yslots; - table->subtables[x].shift = yshift; - table->subtables[x].keys = newykeys; - table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; - i = table->subtables[x].bindVar; - table->subtables[x].bindVar = table->subtables[y].bindVar; - table->subtables[y].bindVar = i; - /* Adjust filds for lazy sifting. */ - varType = table->subtables[x].varType; - table->subtables[x].varType = table->subtables[y].varType; - table->subtables[y].varType = varType; - i = table->subtables[x].pairIndex; - table->subtables[x].pairIndex = table->subtables[y].pairIndex; - table->subtables[y].pairIndex = i; - i = table->subtables[x].varHandled; - table->subtables[x].varHandled = table->subtables[y].varHandled; - table->subtables[y].varHandled = i; - groupType = table->subtables[x].varToBeGrouped; - table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped; - table->subtables[y].varToBeGrouped = groupType; - - table->subtables[y].nodelist = xlist; - table->subtables[y].slots = xslots; - table->subtables[y].shift = xshift; - table->subtables[y].keys = newxkeys; - table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; - - table->perm[xindex] = y; table->perm[yindex] = x; - table->invperm[x] = yindex; table->invperm[y] = xindex; - - table->keys += newxkeys + newykeys - oldxkeys - oldykeys; - - return(table->keys - table->isolated); - -cuddSwapOutOfMem: - (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n"); - - return (0); - -} /* end of cuddSwapInPlace */ - - -/**Function******************************************************************** - - Synopsis [Reorders BDD variables according to the order of the ZDD - variables.] - - Description [Reorders BDD variables according to the order of the - ZDD variables. This function can be called at the end of ZDD - reordering to insure that the order of the BDD variables is - consistent with the order of the ZDD variables. The number of ZDD - variables must be a multiple of the number of BDD variables. Let - <code>M</code> be the ratio of the two numbers. cuddBddAlignToZdd - then considers the ZDD variables from <code>M*i</code> to - <code>(M+1)*i-1</code> as corresponding to BDD variable - <code>i</code>. This function should be normally called from - Cudd_zddReduceHeap, which clears the cache. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [Changes the BDD variable order for all diagrams and performs - garbage collection of the BDD unique table.] - - SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap] - -******************************************************************************/ -int -cuddBddAlignToZdd( - DdManager * table /* DD manager */) -{ - int *invperm; /* permutation array */ - int M; /* ratio of ZDD variables to BDD variables */ - int i; /* loop index */ - int result; /* return value */ - - /* We assume that a ratio of 0 is OK. */ - if (table->size == 0) - return(1); - - M = table->sizeZ / table->size; - /* Check whether the number of ZDD variables is a multiple of the - ** number of BDD variables. - */ - if (M * table->size != table->sizeZ) - return(0); - /* Create and initialize the inverse permutation array. */ - invperm = ALLOC(int,table->size); - if (invperm == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < table->sizeZ; i += M) { - int indexZ = table->invpermZ[i]; - int index = indexZ / M; - invperm[i / M] = index; - } - /* Eliminate dead nodes. Do not scan the cache again, because we - ** assume that Cudd_zddReduceHeap has already cleared it. - */ - cuddGarbageCollect(table,0); - - /* Initialize number of isolated projection functions. */ - table->isolated = 0; - for (i = 0; i < table->size; i++) { - if (table->vars[i]->ref == 1) table->isolated++; - } - - /* Initialize the interaction matrix. */ - result = cuddInitInteract(table); - if (result == 0) return(0); - - result = ddShuffle(table, invperm); - FREE(invperm); - /* Free interaction matrix. */ - FREE(table->interact); - /* Fix the BDD variable group tree. */ - bddFixTree(table,table->tree); - return(result); - -} /* end of cuddBddAlignToZdd */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the - variables according to the number of keys in the subtables. - Returns the difference in number of keys between the two - variables being compared.] - - SideEffects [None] - -******************************************************************************/ -static int -ddUniqueCompare( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of ddUniqueCompare */ - - -/**Function******************************************************************** - - Synopsis [Swaps any two variables.] - - Description [Swaps any two variables. Returns the set of moves.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddSwapAny( - DdManager * table, - int x, - int y) -{ - Move *move, *moves; - int xRef,yRef; - int xNext,yNext; - int size; - int limitSize; - int tmp; - - if (x >y) { - tmp = x; x = y; y = tmp; - } - - xRef = x; yRef = y; - - xNext = cuddNextHigh(table,x); - yNext = cuddNextLow(table,y); - moves = NULL; - limitSize = table->keys - table->isolated; - - for (;;) { - if ( xNext == yNext) { - size = cuddSwapInPlace(table,x,xNext); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = x; - move->y = xNext; - move->size = size; - move->next = moves; - moves = move; - - size = cuddSwapInPlace(table,yNext,y); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = yNext; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - size = cuddSwapInPlace(table,x,xNext); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = x; - move->y = xNext; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; x = y; y = tmp; - - } else if (x == yNext) { - - size = cuddSwapInPlace(table,x,xNext); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = x; - move->y = xNext; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; x = y; y = tmp; - - } else { - size = cuddSwapInPlace(table,x,xNext); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = x; - move->y = xNext; - move->size = size; - move->next = moves; - moves = move; - - size = cuddSwapInPlace(table,yNext,y); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = yNext; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - x = xNext; - y = yNext; - } - - xNext = cuddNextHigh(table,x); - yNext = cuddNextLow(table,y); - if (xNext > yRef) break; - - if ((double) size > table->maxGrowth * (double) limitSize) break; - if (size < limitSize) limitSize = size; - } - if (yNext>=xRef) { - size = cuddSwapInPlace(table,yNext,y); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = yNext; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - } - - return(moves); - -ddSwapAnyOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(NULL); - -} /* end of ddSwapAny */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - - Move *move; - Move *moveUp; /* list of up moves */ - Move *moveDown; /* list of down moves */ - int initialSize; - int result; - - initialSize = table->keys - table->isolated; - - moveDown = NULL; - moveUp = NULL; - - if (x == xLow) { - moveDown = ddSiftingDown(table,x,xHigh); - /* At this point x --> xHigh unless bounding occurred. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddSiftingBackward(table,initialSize,moveDown); - if (!result) goto ddSiftingAuxOutOfMem; - - } else if (x == xHigh) { - moveUp = ddSiftingUp(table,x,xLow); - /* At this point x --> xLow unless bounding occurred. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddSiftingBackward(table,initialSize,moveUp); - if (!result) goto ddSiftingAuxOutOfMem; - - } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ - moveDown = ddSiftingDown(table,x,xHigh); - /* At this point x --> xHigh unless bounding occurred. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - if (moveDown != NULL) { - x = moveDown->y; - } - moveUp = ddSiftingUp(table,x,xLow); - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - /* Move backward and stop at best position */ - result = ddSiftingBackward(table,initialSize,moveUp); - if (!result) goto ddSiftingAuxOutOfMem; - - } else { /* must go up first: shorter */ - moveUp = ddSiftingUp(table,x,xLow); - /* At this point x --> xLow unless bounding occurred. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - if (moveUp != NULL) { - x = moveUp->x; - } - moveDown = ddSiftingDown(table,x,xHigh); - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddSiftingBackward(table,initialSize,moveDown); - if (!result) goto ddSiftingAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - - return(1); - -ddSiftingAuxOutOfMem: - if (moveDown != (Move *) CUDD_OUT_OF_MEM) { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - } - if (moveUp != (Move *) CUDD_OUT_OF_MEM) { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - } - - return(0); - -} /* end of ddSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable up.] - - Description [Sifts a variable up. Moves y up until either it reaches - the bound (xLow) or the size of the DD heap increases too much. - Returns the set of moves in case of success; NULL if memory is full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddSiftingUp( - DdManager * table, - int y, - int xLow) -{ - Move *moves; - Move *move; - int x; - int size; - int limitSize; - int xindex, yindex; - int isolated; - int L; /* lower bound on DD size */ -#ifdef DD_DEBUG - int checkL; - int z; - int zindex; -#endif - - moves = NULL; - yindex = table->invperm[y]; - - /* Initialize the lower bound. - ** The part of the DD below y will not change. - ** The part of the DD above y that does not interact with y will not - ** change. The rest may vanish in the best case, except for - ** the nodes at level xLow, which will not vanish, regardless. - */ - limitSize = L = table->keys - table->isolated; - for (x = xLow + 1; x < y; x++) { - xindex = table->invperm[x]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L -= table->subtables[x].keys - isolated; - } - } - isolated = table->vars[yindex]->ref == 1; - L -= table->subtables[y].keys - isolated; - - x = cuddNextLow(table,y); - while (x >= xLow && L <= limitSize) { - xindex = table->invperm[x]; -#ifdef DD_DEBUG - checkL = table->keys - table->isolated; - for (z = xLow + 1; z < y; z++) { - zindex = table->invperm[z]; - if (cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - checkL -= table->subtables[z].keys - isolated; - } - } - isolated = table->vars[yindex]->ref == 1; - checkL -= table->subtables[y].keys - isolated; - assert(L == checkL); -#endif - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddSiftingUpOutOfMem; - /* Update the lower bound. */ - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L += table->subtables[y].keys - isolated; - } - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > (double) limitSize * table->maxGrowth) break; - if (size < limitSize) limitSize = size; - y = x; - x = cuddNextLow(table,y); - } - return(moves); - -ddSiftingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of ddSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable down.] - - Description [Sifts a variable down. Moves x down until either it - reaches the bound (xHigh) or the size of the DD heap increases too - much. Returns the set of moves in case of success; NULL if memory is - full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddSiftingDown( - DdManager * table, - int x, - int xHigh) -{ - Move *moves; - Move *move; - int y; - int size; - int R; /* upper bound on node decrease */ - int limitSize; - int xindex, yindex; - int isolated; -#ifdef DD_DEBUG - int checkR; - int z; - int zindex; -#endif - - moves = NULL; - /* Initialize R */ - xindex = table->invperm[x]; - limitSize = size = table->keys - table->isolated; - R = 0; - for (y = xHigh; y > x; y--) { - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R += table->subtables[y].keys - isolated; - } - } - - y = cuddNextHigh(table,x); - while (y <= xHigh && size - R < limitSize) { -#ifdef DD_DEBUG - checkR = 0; - for (z = xHigh; z > x; z--) { - zindex = table->invperm[z]; - if (cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - checkR += table->subtables[z].keys - isolated; - } - } - assert(R == checkR); -#endif - /* Update upper bound on node decrease. */ - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R -= table->subtables[y].keys - isolated; - } - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddSiftingDownOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > (double) limitSize * table->maxGrowth) break; - if (size < limitSize) limitSize = size; - x = y; - y = cuddNextHigh(table,x); - } - return(moves); - -ddSiftingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of ddSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the DD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the DD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSiftingBackward( - DdManager * table, - int size, - Move * moves) -{ - Move *move; - int res; - - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - res = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - - return(1); - -} /* end of ddSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Prepares the DD heap for dynamic reordering.] - - Description [Prepares the DD heap for dynamic reordering. Does - garbage collection, to guarantee that there are no dead nodes; - clears the cache, which is invalidated by dynamic reordering; initializes - the number of isolated projection functions; and initializes the - interaction matrix. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddReorderPreprocess( - DdManager * table) -{ - int i; - int res; - - /* Clear the cache. */ - cuddCacheFlush(table); - cuddLocalCacheClearAll(table); - - /* Eliminate dead nodes. Do not scan the cache again. */ - cuddGarbageCollect(table,0); - - /* Initialize number of isolated projection functions. */ - table->isolated = 0; - for (i = 0; i < table->size; i++) { - if (table->vars[i]->ref == 1) table->isolated++; - } - - /* Initialize the interaction matrix. */ - res = cuddInitInteract(table); - if (res == 0) return(0); - - return(1); - -} /* end of ddReorderPreprocess */ - - -/**Function******************************************************************** - - Synopsis [Cleans up at the end of reordering.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -static int -ddReorderPostprocess( - DdManager * table) -{ - -#ifdef DD_VERBOSE - (void) fflush(table->out); -#endif - - /* Free interaction matrix. */ - FREE(table->interact); - - return(1); - -} /* end of ddReorderPostprocess */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables according to a given permutation.] - - Description [Reorders variables according to a given permutation. - The i-th permutation array contains the index of the variable that - should be brought to the i-th level. ddShuffle assumes that no - dead nodes are present and that the interaction matrix is properly - initialized. The reordering is achieved by a series of upward sifts. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddShuffle( - DdManager * table, - int * permutation) -{ - int index; - int level; - int position; - int numvars; - int result; -#ifdef DD_STATS - long localTime; - int initialSize; - int finalSize; - int previousSize; -#endif - - ddTotalNumberSwapping = 0; -#ifdef DD_STATS - localTime = util_cpu_time(); - initialSize = table->keys - table->isolated; - (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", - initialSize); - ddTotalNISwaps = 0; -#endif - - numvars = table->size; - - for (level = 0; level < numvars; level++) { - index = permutation[level]; - position = table->perm[index]; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddSiftUp(table,position,level); - if (!result) return(0); -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - finalSize = table->keys - table->isolated; - (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); - (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", - ((double)(util_cpu_time() - localTime)/1000.0)); - (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", - ddTotalNumberSwapping); - (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps); -#endif - - return(1); - -} /* end of ddShuffle */ - - -/**Function******************************************************************** - - Synopsis [Moves one variable up.] - - Description [Takes a variable from position x and sifts it up to - position xLow; xLow should be less than or equal to x. - Returns 1 if successful; 0 otherwise] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddSiftUp( - DdManager * table, - int x, - int xLow) -{ - int y; - int size; - - y = cuddNextLow(table,x); - while (y >= xLow) { - size = cuddSwapInPlace(table,y,x); - if (size == 0) { - return(0); - } - x = y; - y = cuddNextLow(table,x); - } - return(1); - -} /* end of ddSiftUp */ - - -/**Function******************************************************************** - - Synopsis [Fixes the BDD variable group tree after a shuffle.] - - Description [Fixes the BDD variable group tree after a - shuffle. Assumes that the order of the variables in a terminal node - has not been changed.] - - SideEffects [Changes the BDD variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static void -bddFixTree( - DdManager * table, - MtrNode * treenode) -{ - if (treenode == NULL) return; - treenode->low = ((int) treenode->index < table->size) ? - table->perm[treenode->index] : treenode->index; - if (treenode->child != NULL) { - bddFixTree(table, treenode->child); - } - if (treenode->younger != NULL) - bddFixTree(table, treenode->younger); - if (treenode->parent != NULL && treenode->low < treenode->parent->low) { - treenode->parent->low = treenode->low; - treenode->parent->index = treenode->index; - } - return; - -} /* end of bddFixTree */ - - -/**Function******************************************************************** - - Synopsis [Updates the BDD variable group tree before a shuffle.] - - Description [Updates the BDD variable group tree before a shuffle. - Returns 1 if successful; 0 otherwise.] - - SideEffects [Changes the BDD variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static int -ddUpdateMtrTree( - DdManager * table, - MtrNode * treenode, - int * perm, - int * invperm) -{ - int i, size, index, level; - int minLevel, maxLevel, minIndex; - - if (treenode == NULL) return(1); - - /* i : level */ - for (i = treenode->low; i < treenode->low + treenode->size; i++) { - index = table->invperm[i]; - level = perm[index]; - if (level < minLevel) { - minLevel = level; - minIndex = index; - } - if (level > maxLevel) - maxLevel = level; - } - size = maxLevel - minLevel + 1; - if (size == treenode->size) { - treenode->low = minLevel; - treenode->index = minIndex; - } else - return(0); - - if (treenode->child != NULL) { - if (!ddUpdateMtrTree(table, treenode->child, perm, invperm)) - return(0); - } - if (treenode->younger != NULL) { - if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm)) - return(0); - } - return(1); -} - - -/**Function******************************************************************** - - Synopsis [Checks the BDD variable group tree before a shuffle.] - - Description [Checks the BDD variable group tree before a shuffle. - Returns 1 if successful; 0 otherwise.] - - SideEffects [Changes the BDD variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static int -ddCheckPermuation( - DdManager * table, - MtrNode * treenode, - int * perm, - int * invperm) -{ - int i, size, index, level; - int minLevel, maxLevel; - - if (treenode == NULL) return(1); - - minLevel = table->size; - maxLevel = 0; - /* i : level */ - for (i = treenode->low; i < treenode->low + treenode->size; i++) { - index = table->invperm[i]; - level = perm[index]; - if (level < minLevel) - minLevel = level; - if (level > maxLevel) - maxLevel = level; - } - size = maxLevel - minLevel + 1; - if (size != treenode->size) - return(0); - - if (treenode->child != NULL) { - if (!ddCheckPermuation(table, treenode->child, perm, invperm)) - return(0); - } - if (treenode->younger != NULL) { - if (!ddCheckPermuation(table, treenode->younger, perm, invperm)) - return(0); - } - return(1); -} diff --git a/src/bdd/cudd/cuddSat.c b/src/bdd/cudd/cuddSat.c deleted file mode 100644 index 1755a1c1..00000000 --- a/src/bdd/cudd/cuddSat.c +++ /dev/null @@ -1,1305 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSat.c] - - PackageName [cudd] - - Synopsis [Functions for the solution of satisfiability related - problems.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_Eval() - <li> Cudd_ShortestPath() - <li> Cudd_LargestCube() - <li> Cudd_ShortestLength() - <li> Cudd_Decreasing() - <li> Cudd_Increasing() - <li> Cudd_EquivDC() - <li> Cudd_bddLeqUnless() - <li> Cudd_EqualSupNorm() - <li> Cudd_bddMakePrime() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddBddMakePrime() - </ul> - Static procedures included in this module: - <ul> - <li> freePathPair() - <li> getShortest() - <li> getPath() - <li> getLargest() - <li> getCube() - </ul>] - - Author [Seh-Woong Jeong, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_BIGGY 1000000 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct cuddPathPair { - int pos; - int neg; -} cuddPathPair; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static DdNode *one, *zero; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -#define WEIGHT(weight, col) ((weight) == NULL ? 1 : weight[col]) - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static enum st_retval freePathPair ARGS((char *key, char *value, char *arg)); -static cuddPathPair getShortest ARGS((DdNode *root, int *cost, int *support, st_table *visited)); -static DdNode * getPath ARGS((DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost)); -static cuddPathPair getLargest ARGS((DdNode *root, st_table *visited)); -static DdNode * getCube ARGS((DdManager *manager, st_table *visited, DdNode *f, int cost)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Returns the value of a DD for a given variable assignment.] - - Description [Finds the value of a DD for a given variable - assignment. The variable assignment is passed in an array of int's, - that should specify a zero or a one for each variable in the support - of the function. Returns a pointer to a constant node. No new nodes - are produced.] - - SideEffects [None] - - SeeAlso [Cudd_bddLeq Cudd_addEvalConst] - -******************************************************************************/ -DdNode * -Cudd_Eval( - DdManager * dd, - DdNode * f, - int * inputs) -{ - int comple; - DdNode *ptr; - - comple = Cudd_IsComplement(f); - ptr = Cudd_Regular(f); - - while (!cuddIsConstant(ptr)) { - if (inputs[ptr->index] == 1) { - ptr = cuddT(ptr); - } else { - comple ^= Cudd_IsComplement(cuddE(ptr)); - ptr = Cudd_Regular(cuddE(ptr)); - } - } - return(Cudd_NotCond(ptr,comple)); - -} /* end of Cudd_Eval */ - - -/**Function******************************************************************** - - Synopsis [Finds a shortest path in a DD.] - - Description [Finds a shortest path in a DD. f is the DD we want to - get the shortest path for; weight\[i\] is the weight of the THEN arc - coming from the node whose index is i. If weight is NULL, then unit - weights are assumed for all THEN arcs. All ELSE arcs have 0 weight. - If non-NULL, both weight and support should point to arrays with at - least as many entries as there are variables in the manager. - Returns the shortest path as the BDD of a cube.] - - SideEffects [support contains on return the true support of f. - If support is NULL on entry, then Cudd_ShortestPath does not compute - the true support info. length contains the length of the path.] - - SeeAlso [Cudd_ShortestLength Cudd_LargestCube] - -******************************************************************************/ -DdNode * -Cudd_ShortestPath( - DdManager * manager, - DdNode * f, - int * weight, - int * support, - int * length) -{ - register DdNode *F; - st_table *visited; - DdNode *sol; - cuddPathPair *rootPair; - int complement, cost; - int i; - - one = DD_ONE(manager); - zero = DD_ZERO(manager); - - /* Initialize support. */ - if (support) { - for (i = 0; i < manager->size; i++) { - support[i] = 0; - } - } - - if (f == Cudd_Not(one) || f == zero) { - *length = DD_BIGGY; - return(Cudd_Not(one)); - } - /* From this point on, a path exists. */ - - /* Initialize visited table. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - - /* Now get the length of the shortest path(s) from f to 1. */ - (void) getShortest(f, weight, support, visited); - - complement = Cudd_IsComplement(f); - - F = Cudd_Regular(f); - - st_lookup(visited, (char *)F, (char **)&rootPair); - - if (complement) { - cost = rootPair->neg; - } else { - cost = rootPair->pos; - } - - /* Recover an actual shortest path. */ - do { - manager->reordered = 0; - sol = getPath(manager,visited,f,weight,cost); - } while (manager->reordered == 1); - - st_foreach(visited, freePathPair, NULL); - st_free_table(visited); - - *length = cost; - return(sol); - -} /* end of Cudd_ShortestPath */ - - -/**Function******************************************************************** - - Synopsis [Finds a largest cube in a DD.] - - Description [Finds a largest cube in a DD. f is the DD we want to - get the largest cube for. The problem is translated into the one of - finding a shortest path in f, when both THEN and ELSE arcs are assumed to - have unit length. This yields a largest cube in the disjoint cover - corresponding to the DD. Therefore, it is not necessarily the largest - implicant of f. Returns the largest cube as a BDD.] - - SideEffects [The number of literals of the cube is returned in length.] - - SeeAlso [Cudd_ShortestPath] - -******************************************************************************/ -DdNode * -Cudd_LargestCube( - DdManager * manager, - DdNode * f, - int * length) -{ - register DdNode *F; - st_table *visited; - DdNode *sol; - cuddPathPair *rootPair; - int complement, cost; - - one = DD_ONE(manager); - zero = DD_ZERO(manager); - - if (f == Cudd_Not(one) || f == zero) { - *length = DD_BIGGY; - return(Cudd_Not(one)); - } - /* From this point on, a path exists. */ - - /* Initialize visited table. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - - /* Now get the length of the shortest path(s) from f to 1. */ - (void) getLargest(f, visited); - - complement = Cudd_IsComplement(f); - - F = Cudd_Regular(f); - - st_lookup(visited, (char *)F, (char **)&rootPair); - - if (complement) { - cost = rootPair->neg; - } else { - cost = rootPair->pos; - } - - /* Recover an actual shortest path. */ - do { - manager->reordered = 0; - sol = getCube(manager,visited,f,cost); - } while (manager->reordered == 1); - - st_foreach(visited, freePathPair, NULL); - st_free_table(visited); - - *length = cost; - return(sol); - -} /* end of Cudd_LargestCube */ - - -/**Function******************************************************************** - - Synopsis [Find the length of the shortest path(s) in a DD.] - - Description [Find the length of the shortest path(s) in a DD. f is - the DD we want to get the shortest path for; weight\[i\] is the - weight of the THEN edge coming from the node whose index is i. All - ELSE edges have 0 weight. Returns the length of the shortest - path(s) if successful; CUDD_OUT_OF_MEM otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ShortestPath] - -******************************************************************************/ -int -Cudd_ShortestLength( - DdManager * manager, - DdNode * f, - int * weight) -{ - register DdNode *F; - st_table *visited; - cuddPathPair *my_pair; - int complement, cost; - - one = DD_ONE(manager); - zero = DD_ZERO(manager); - - if (f == Cudd_Not(one) || f == zero) { - return(DD_BIGGY); - } - - /* From this point on, a path exists. */ - /* Initialize visited table and support. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - - /* Now get the length of the shortest path(s) from f to 1. */ - (void) getShortest(f, weight, NULL, visited); - - complement = Cudd_IsComplement(f); - - F = Cudd_Regular(f); - - st_lookup(visited, (char *)F, (char **)&my_pair); - - if (complement) { - cost = my_pair->neg; - } else { - cost = my_pair->pos; - } - - st_foreach(visited, freePathPair, NULL); - st_free_table(visited); - - return(cost); - -} /* end of Cudd_ShortestLength */ - - -/**Function******************************************************************** - - Synopsis [Determines whether a BDD is negative unate in a - variable.] - - Description [Determines whether the function represented by BDD f is - negative unate (monotonic decreasing) in variable i. Returns the - constant one is f is unate and the (logical) constant zero if it is not. - This function does not generate any new nodes.] - - SideEffects [None] - - SeeAlso [Cudd_Increasing] - -******************************************************************************/ -DdNode * -Cudd_Decreasing( - DdManager * dd, - DdNode * f, - int i) -{ - unsigned int topf, level; - DdNode *F, *fv, *fvn, *res; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - - statLine(dd); -#ifdef DD_DEBUG - assert(0 <= i && i < dd->size); -#endif - - F = Cudd_Regular(f); - topf = cuddI(dd,F->index); - - /* Check terminal case. If topf > i, f does not depend on var. - ** Therefore, f is unate in i. - */ - level = (unsigned) dd->perm[i]; - if (topf > level) { - return(DD_ONE(dd)); - } - - /* From now on, f is not constant. */ - - /* Check cache. */ - cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) Cudd_Decreasing; - res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]); - if (res != NULL) { - return(res); - } - - /* Compute cofactors. */ - fv = cuddT(F); fvn = cuddE(F); - if (F != f) { - fv = Cudd_Not(fv); - fvn = Cudd_Not(fvn); - } - - if (topf == (unsigned) level) { - /* Special case: if fv is regular, fv(1,...,1) = 1; - ** If in addition fvn is complemented, fvn(1,...,1) = 0. - ** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not - ** monotonic decreasing in i. - */ - if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) { - return(Cudd_Not(DD_ONE(dd))); - } - res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd)); - } else { - res = Cudd_Decreasing(dd,fv,i); - if (res == DD_ONE(dd)) { - res = Cudd_Decreasing(dd,fvn,i); - } - } - - cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res); - return(res); - -} /* end of Cudd_Decreasing */ - - -/**Function******************************************************************** - - Synopsis [Determines whether a BDD is positive unate in a - variable.] - - Description [Determines whether the function represented by BDD f is - positive unate (monotonic decreasing) in variable i. It is based on - Cudd_Decreasing and the fact that f is monotonic increasing in i if - and only if its complement is monotonic decreasing in i.] - - SideEffects [None] - - SeeAlso [Cudd_Decreasing] - -******************************************************************************/ -DdNode * -Cudd_Increasing( - DdManager * dd, - DdNode * f, - int i) -{ - return(Cudd_Decreasing(dd,Cudd_Not(f),i)); - -} /* end of Cudd_Increasing */ - - -/**Function******************************************************************** - - Synopsis [Tells whether F and G are identical wherever D is 0.] - - Description [Tells whether F and G are identical wherever D is 0. F - and G are either two ADDs or two BDDs. D is either a 0-1 ADD or a - BDD. The function returns 1 if F and G are equivalent, and 0 - otherwise. No new nodes are created.] - - SideEffects [None] - - SeeAlso [Cudd_bddLeqUnless] - -******************************************************************************/ -int -Cudd_EquivDC( - DdManager * dd, - DdNode * F, - DdNode * G, - DdNode * D) -{ - DdNode *tmp, *One, *Gr, *Dr; - DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn; - int res; - unsigned int flevel, glevel, dlevel, top; - - One = DD_ONE(dd); - - statLine(dd); - /* Check terminal cases. */ - if (D == One || F == G) return(1); - if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0); - - /* From now on, D is non-constant. */ - - /* Normalize call to increase cache efficiency. */ - if (F > G) { - tmp = F; - F = G; - G = tmp; - } - if (Cudd_IsComplement(F)) { - F = Cudd_Not(F); - G = Cudd_Not(G); - } - - /* From now on, F is regular. */ - - /* Check cache. */ - tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D); - if (tmp != NULL) return(tmp == One); - - /* Find splitting variable. */ - flevel = cuddI(dd,F->index); - Gr = Cudd_Regular(G); - glevel = cuddI(dd,Gr->index); - top = ddMin(flevel,glevel); - Dr = Cudd_Regular(D); - dlevel = dd->perm[Dr->index]; - top = ddMin(top,dlevel); - - /* Compute cofactors. */ - if (top == flevel) { - Fv = cuddT(F); - Fvn = cuddE(F); - } else { - Fv = Fvn = F; - } - if (top == glevel) { - Gv = cuddT(Gr); - Gvn = cuddE(Gr); - if (G != Gr) { - Gv = Cudd_Not(Gv); - Gvn = Cudd_Not(Gvn); - } - } else { - Gv = Gvn = G; - } - if (top == dlevel) { - Dv = cuddT(Dr); - Dvn = cuddE(Dr); - if (D != Dr) { - Dv = Cudd_Not(Dv); - Dvn = Cudd_Not(Dvn); - } - } else { - Dv = Dvn = D; - } - - /* Solve recursively. */ - res = Cudd_EquivDC(dd,Fv,Gv,Dv); - if (res != 0) { - res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn); - } - cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One)); - - return(res); - -} /* end of Cudd_EquivDC */ - - -/**Function******************************************************************** - - Synopsis [Tells whether f is less than of equal to G unless D is 1.] - - Description [Tells whether f is less than of equal to G unless D is - 1. f, g, and D are BDDs. The function returns 1 if f is less than - of equal to G, and 0 otherwise. No new nodes are created.] - - SideEffects [None] - - SeeAlso [Cudd_EquivDC Cudd_bddLeq Cudd_bddIteConstant] - -******************************************************************************/ -int -Cudd_bddLeqUnless( - DdManager *dd, - DdNode *f, - DdNode *g, - DdNode *D) -{ - DdNode *tmp, *One, *F, *G; - DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De; - int res; - unsigned int flevel, glevel, dlevel, top; - - statLine(dd); - - One = DD_ONE(dd); - - /* Check terminal cases. */ - if (f == g || g == One || f == Cudd_Not(One) || D == One || - D == f || D == Cudd_Not(g)) return(1); - /* Check for two-operand cases. */ - if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f)) - return(Cudd_bddLeq(dd,f,g)); - if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D)); - if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D)); - - /* From now on, f, g, and D are non-constant, distinct, and - ** non-complementary. */ - - /* Normalize call to increase cache efficiency. We rely on the - ** fact that f <= g unless D is equivalent to not(g) <= not(f) - ** unless D and to f <= D unless g. We make sure that D is - ** regular, and that at most one of f and g is complemented. We also - ** ensure that when two operands can be swapped, the one with the - ** lowest address comes first. */ - - if (Cudd_IsComplement(D)) { - if (Cudd_IsComplement(g)) { - /* Special case: if f is regular and g is complemented, - ** f(1,...,1) = 1 > 0 = g(1,...,1). If D(1,...,1) = 0, return 0. - */ - if (!Cudd_IsComplement(f)) return(0); - /* !g <= D unless !f or !D <= g unless !f */ - tmp = D; - D = Cudd_Not(f); - if (g < tmp) { - f = Cudd_Not(g); - g = tmp; - } else { - f = Cudd_Not(tmp); - } - } else { - if (Cudd_IsComplement(f)) { - /* !D <= !f unless g or !D <= g unless !f */ - tmp = f; - f = Cudd_Not(D); - if (tmp < g) { - D = g; - g = Cudd_Not(tmp); - } else { - D = Cudd_Not(tmp); - } - } else { - /* f <= D unless g or !D <= !f unless g */ - tmp = D; - D = g; - if (tmp < f) { - g = Cudd_Not(f); - f = Cudd_Not(tmp); - } else { - g = tmp; - } - } - } - } else { - if (Cudd_IsComplement(g)) { - if (Cudd_IsComplement(f)) { - /* !g <= !f unless D or !g <= D unless !f */ - tmp = f; - f = Cudd_Not(g); - if (D < tmp) { - g = D; - D = Cudd_Not(tmp); - } else { - g = Cudd_Not(tmp); - } - } else { - /* f <= g unless D or !g <= !f unless D */ - if (g < f) { - tmp = g; - g = Cudd_Not(f); - f = Cudd_Not(tmp); - } - } - } else { - /* f <= g unless D or f <= D unless g */ - if (D < g) { - tmp = D; - D = g; - g = tmp; - } - } - } - - /* From now on, D is regular. */ - - /* Check cache. */ - tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D); - if (tmp != NULL) return(tmp == One); - - /* Find splitting variable. */ - F = Cudd_Regular(f); - flevel = dd->perm[F->index]; - G = Cudd_Regular(g); - glevel = dd->perm[G->index]; - top = ddMin(flevel,glevel); - dlevel = dd->perm[D->index]; - top = ddMin(top,dlevel); - - /* Compute cofactors. */ - if (top == flevel) { - Ft = cuddT(F); - Fe = cuddE(F); - if (F != f) { - Ft = Cudd_Not(Ft); - Fe = Cudd_Not(Fe); - } - } else { - Ft = Fe = f; - } - if (top == glevel) { - Gt = cuddT(G); - Ge = cuddE(G); - if (G != g) { - Gt = Cudd_Not(Gt); - Ge = Cudd_Not(Ge); - } - } else { - Gt = Ge = g; - } - if (top == dlevel) { - Dt = cuddT(D); - De = cuddE(D); - } else { - Dt = De = D; - } - - /* Solve recursively. */ - res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt); - if (res != 0) { - res = Cudd_bddLeqUnless(dd,Fe,Ge,De); - } - cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res)); - - return(res); - -} /* end of Cudd_bddLeqUnless */ - - -/**Function******************************************************************** - - Synopsis [Compares two ADDs for equality within tolerance.] - - Description [Compares two ADDs for equality within tolerance. Two - ADDs are reported to be equal if the maximum difference between them - (the sup norm of their difference) is less than or equal to the - tolerance parameter. Returns 1 if the two ADDs are equal (within - tolerance); 0 otherwise. If parameter <code>pr</code> is positive - the first failure is reported to the standard output.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_EqualSupNorm( - DdManager * dd /* manager */, - DdNode * f /* first ADD */, - DdNode * g /* second ADD */, - CUDD_VALUE_TYPE tolerance /* maximum allowed difference */, - int pr /* verbosity level */) -{ - DdNode *fv, *fvn, *gv, *gvn, *r; - unsigned int topf, topg; - - statLine(dd); - /* Check terminal cases. */ - if (f == g) return(1); - if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) { - if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) { - return(1); - } else { - if (pr>0) { - (void) fprintf(dd->out,"Offending nodes:\n"); -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out, - "f: address = %lx\t value = %40.30f\n", - (unsigned long) f, cuddV(f)); - (void) fprintf(dd->out, - "g: address = %lx\t value = %40.30f\n", - (unsigned long) g, cuddV(g)); -#else - (void) fprintf(dd->out, - "f: address = %x\t value = %40.30f\n", - (unsigned) f, cuddV(f)); - (void) fprintf(dd->out, - "g: address = %x\t value = %40.30f\n", - (unsigned) g, cuddV(g)); -#endif - } - return(0); - } - } - - /* We only insert the result in the cache if the comparison is - ** successful. Therefore, if we hit we return 1. */ - r = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_EqualSupNorm,f,g); - if (r != NULL) { - return(1); - } - - /* Compute the cofactors and solve the recursive subproblems. */ - topf = cuddI(dd,f->index); - topg = cuddI(dd,g->index); - - if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} - if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} - - if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0); - if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0); - - cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_EqualSupNorm,f,g,DD_ONE(dd)); - - return(1); - -} /* end of Cudd_EqualSupNorm */ - - -/**Function******************************************************************** - - Synopsis [Expands cube to a prime implicant of f.] - - Description [Expands cube to a prime implicant of f. Returns the prime - if successful; NULL otherwise. In particular, NULL is returned if cube - is not a real cube or is not an implicant of f.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_bddMakePrime( - DdManager *dd /* manager */, - DdNode *cube /* cube to be expanded */, - DdNode *f /* function of which the cube is to be made a prime */) -{ - DdNode *res; - - if (!Cudd_bddLeq(dd,cube,f)) return(NULL); - - do { - dd->reordered = 0; - res = cuddBddMakePrime(dd,cube,f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddMakePrime */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddMakePrime.] - - Description [Performs the recursive step of Cudd_bddMakePrime. - Returns the prime if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddBddMakePrime( - DdManager *dd /* manager */, - DdNode *cube /* cube to be expanded */, - DdNode *f /* function of which the cube is to be made a prime */) -{ - DdNode *scan; - DdNode *t, *e; - DdNode *res = cube; - DdNode *zero = Cudd_Not(DD_ONE(dd)); - - Cudd_Ref(res); - scan = cube; - while (!Cudd_IsConstant(scan)) { - DdNode *reg = Cudd_Regular(scan); - DdNode *var = dd->vars[reg->index]; - DdNode *expanded = Cudd_bddExistAbstract(dd,res,var); - if (expanded == NULL) { - return(NULL); - } - Cudd_Ref(expanded); - if (Cudd_bddLeq(dd,expanded,f)) { - Cudd_RecursiveDeref(dd,res); - res = expanded; - } else { - Cudd_RecursiveDeref(dd,expanded); - } - cuddGetBranches(scan,&t,&e); - if (t == zero) { - scan = e; - } else if (e == zero) { - scan = t; - } else { - Cudd_RecursiveDeref(dd,res); - return(NULL); /* cube is not a cube */ - } - } - - if (scan == DD_ONE(dd)) { - Cudd_Deref(res); - return(res); - } else { - Cudd_RecursiveDeref(dd,res); - return(NULL); - } - -} /* end of cuddBddMakePrime */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Frees the entries of the visited symbol table.] - - Description [Frees the entries of the visited symbol table. Returns - ST_CONTINUE.] - - SideEffects [None] - -******************************************************************************/ -static enum st_retval -freePathPair( - char * key, - char * value, - char * arg) -{ - cuddPathPair *pair; - - pair = (cuddPathPair *) value; - FREE(pair); - return(ST_CONTINUE); - -} /* end of freePathPair */ - - -/**Function******************************************************************** - - Synopsis [Finds the length of the shortest path(s) in a DD.] - - Description [Finds the length of the shortest path(s) in a DD. - Uses a local symbol table to store the lengths for each - node. Only the lengths for the regular nodes are entered in the table, - because those for the complement nodes are simply obtained by swapping - the two lenghts. - Returns a pair of lengths: the length of the shortest path to 1; - and the length of the shortest path to 0. This is done so as to take - complement arcs into account.] - - SideEffects [Accumulates the support of the DD in support.] - - SeeAlso [] - -******************************************************************************/ -static cuddPathPair -getShortest( - DdNode * root, - int * cost, - int * support, - st_table * visited) -{ - cuddPathPair *my_pair, res_pair, pair_T, pair_E; - DdNode *my_root, *T, *E; - int weight; - - my_root = Cudd_Regular(root); - - if (st_lookup(visited, (char *)my_root, (char **)&my_pair)) { - if (Cudd_IsComplement(root)) { - res_pair.pos = my_pair->neg; - res_pair.neg = my_pair->pos; - } else { - res_pair.pos = my_pair->pos; - res_pair.neg = my_pair->neg; - } - return(res_pair); - } - - /* In the case of a BDD the following test is equivalent to - ** testing whether the BDD is the constant 1. This formulation, - ** however, works for ADDs as well, by assuming the usual - ** dichotomy of 0 and != 0. - */ - if (cuddIsConstant(my_root)) { - if (my_root != zero) { - res_pair.pos = 0; - res_pair.neg = DD_BIGGY; - } else { - res_pair.pos = DD_BIGGY; - res_pair.neg = 0; - } - } else { - T = cuddT(my_root); - E = cuddE(my_root); - - pair_T = getShortest(T, cost, support, visited); - pair_E = getShortest(E, cost, support, visited); - weight = WEIGHT(cost, my_root->index); - res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos); - res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg); - - /* Update support. */ - if (support != NULL) { - support[my_root->index] = 1; - } - } - - my_pair = ALLOC(cuddPathPair, 1); - if (my_pair == NULL) { - if (Cudd_IsComplement(root)) { - int tmp = res_pair.pos; - res_pair.pos = res_pair.neg; - res_pair.neg = tmp; - } - return(res_pair); - } - my_pair->pos = res_pair.pos; - my_pair->neg = res_pair.neg; - - st_insert(visited, (char *)my_root, (char *)my_pair); - if (Cudd_IsComplement(root)) { - res_pair.pos = my_pair->neg; - res_pair.neg = my_pair->pos; - } else { - res_pair.pos = my_pair->pos; - res_pair.neg = my_pair->neg; - } - return(res_pair); - -} /* end of getShortest */ - - -/**Function******************************************************************** - - Synopsis [Build a BDD for a shortest path of f.] - - Description [Build a BDD for a shortest path of f. - Given the minimum length from the root, and the minimum - lengths for each node (in visited), apply triangulation at each node. - Of the two children of each node on a shortest path, at least one is - on a shortest path. In case of ties the procedure chooses the THEN - children. - Returns a pointer to the cube BDD representing the path if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -getPath( - DdManager * manager, - st_table * visited, - DdNode * f, - int * weight, - int cost) -{ - DdNode *sol, *tmp; - DdNode *my_dd, *T, *E; - cuddPathPair *T_pair, *E_pair; - int Tcost, Ecost; - int complement; - - my_dd = Cudd_Regular(f); - complement = Cudd_IsComplement(f); - - sol = one; - cuddRef(sol); - - while (!cuddIsConstant(my_dd)) { - Tcost = cost - WEIGHT(weight, my_dd->index); - Ecost = cost; - - T = cuddT(my_dd); - E = cuddE(my_dd); - - if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);} - - st_lookup(visited, (char *)Cudd_Regular(T), (char **)&T_pair); - if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) || - (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) { - tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol); - if (tmp == NULL) { - Cudd_RecursiveDeref(manager,sol); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(manager,sol); - sol = tmp; - - complement = Cudd_IsComplement(T); - my_dd = Cudd_Regular(T); - cost = Tcost; - continue; - } - st_lookup(visited, (char *)Cudd_Regular(E), (char **)&E_pair); - if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) || - (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) { - tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol); - if (tmp == NULL) { - Cudd_RecursiveDeref(manager,sol); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(manager,sol); - sol = tmp; - complement = Cudd_IsComplement(E); - my_dd = Cudd_Regular(E); - cost = Ecost; - continue; - } - (void) fprintf(manager->err,"We shouldn't be here!!\n"); - manager->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - - cuddDeref(sol); - return(sol); - -} /* end of getPath */ - - -/**Function******************************************************************** - - Synopsis [Finds the size of the largest cube(s) in a DD.] - - Description [Finds the size of the largest cube(s) in a DD. - This problem is translated into finding the shortest paths from a node - when both THEN and ELSE arcs have unit lengths. - Uses a local symbol table to store the lengths for each - node. Only the lengths for the regular nodes are entered in the table, - because those for the complement nodes are simply obtained by swapping - the two lenghts. - Returns a pair of lengths: the length of the shortest path to 1; - and the length of the shortest path to 0. This is done so as to take - complement arcs into account.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static cuddPathPair -getLargest( - DdNode * root, - st_table * visited) -{ - cuddPathPair *my_pair, res_pair, pair_T, pair_E; - DdNode *my_root, *T, *E; - - my_root = Cudd_Regular(root); - - if (st_lookup(visited, (char *)my_root, (char **)&my_pair)) { - if (Cudd_IsComplement(root)) { - res_pair.pos = my_pair->neg; - res_pair.neg = my_pair->pos; - } else { - res_pair.pos = my_pair->pos; - res_pair.neg = my_pair->neg; - } - return(res_pair); - } - - /* In the case of a BDD the following test is equivalent to - ** testing whether the BDD is the constant 1. This formulation, - ** however, works for ADDs as well, by assuming the usual - ** dichotomy of 0 and != 0. - */ - if (cuddIsConstant(my_root)) { - if (my_root != zero) { - res_pair.pos = 0; - res_pair.neg = DD_BIGGY; - } else { - res_pair.pos = DD_BIGGY; - res_pair.neg = 0; - } - } else { - T = cuddT(my_root); - E = cuddE(my_root); - - pair_T = getLargest(T, visited); - pair_E = getLargest(E, visited); - res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1; - res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1; - } - - my_pair = ALLOC(cuddPathPair, 1); - if (my_pair == NULL) { /* simlpy do not cache this result */ - if (Cudd_IsComplement(root)) { - int tmp = res_pair.pos; - res_pair.pos = res_pair.neg; - res_pair.neg = tmp; - } - return(res_pair); - } - my_pair->pos = res_pair.pos; - my_pair->neg = res_pair.neg; - - st_insert(visited, (char *)my_root, (char *)my_pair); - if (Cudd_IsComplement(root)) { - res_pair.pos = my_pair->neg; - res_pair.neg = my_pair->pos; - } else { - res_pair.pos = my_pair->pos; - res_pair.neg = my_pair->neg; - } - return(res_pair); - -} /* end of getLargest */ - - -/**Function******************************************************************** - - Synopsis [Build a BDD for a largest cube of f.] - - Description [Build a BDD for a largest cube of f. - Given the minimum length from the root, and the minimum - lengths for each node (in visited), apply triangulation at each node. - Of the two children of each node on a shortest path, at least one is - on a shortest path. In case of ties the procedure chooses the THEN - children. - Returns a pointer to the cube BDD representing the path if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -getCube( - DdManager * manager, - st_table * visited, - DdNode * f, - int cost) -{ - DdNode *sol, *tmp; - DdNode *my_dd, *T, *E; - cuddPathPair *T_pair, *E_pair; - int Tcost, Ecost; - int complement; - - my_dd = Cudd_Regular(f); - complement = Cudd_IsComplement(f); - - sol = one; - cuddRef(sol); - - while (!cuddIsConstant(my_dd)) { - Tcost = cost - 1; - Ecost = cost - 1; - - T = cuddT(my_dd); - E = cuddE(my_dd); - - if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);} - - st_lookup(visited, (char *)Cudd_Regular(T), (char **)&T_pair); - if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) || - (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) { - tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol); - if (tmp == NULL) { - Cudd_RecursiveDeref(manager,sol); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(manager,sol); - sol = tmp; - - complement = Cudd_IsComplement(T); - my_dd = Cudd_Regular(T); - cost = Tcost; - continue; - } - st_lookup(visited, (char *)Cudd_Regular(E), (char **)&E_pair); - if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) || - (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) { - tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol); - if (tmp == NULL) { - Cudd_RecursiveDeref(manager,sol); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(manager,sol); - sol = tmp; - complement = Cudd_IsComplement(E); - my_dd = Cudd_Regular(E); - cost = Ecost; - continue; - } - (void) fprintf(manager->err,"We shouldn't be here!\n"); - manager->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - - cuddDeref(sol); - return(sol); - -} /* end of getCube */ diff --git a/src/bdd/cudd/cuddSign.c b/src/bdd/cudd/cuddSign.c deleted file mode 100644 index fcaa65c4..00000000 --- a/src/bdd/cudd/cuddSign.c +++ /dev/null @@ -1,292 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSign.c] - - PackageName [cudd] - - Synopsis [Computation of signatures] - - Description [External procedures included in this module: - <ul> - <li> Cudd_CofMinterm(); - </ul> - Static procedures included in this module: - <ul> - <li> ddCofMintermAux() - </ul> - ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSign.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static int size; - -#ifdef DD_STATS -static int num_calls; /* should equal 2n-1 (n is the # of nodes) */ -static int table_mem; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static double * ddCofMintermAux ARGS((DdManager *dd, DdNode *node, st_table *table)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes the fraction of minterms in the on-set of all the - positive cofactors of a BDD or ADD.] - - Description [Computes the fraction of minterms in the on-set of all - the positive cofactors of DD. Returns the pointer to an array of - doubles if successful; NULL otherwise. The array hs as many - positions as there are BDD variables in the manager plus one. The - last position of the array contains the fraction of the minterms in - the ON-set of the function represented by the BDD or ADD. The other - positions of the array hold the variable signatures.] - - SideEffects [None] - -******************************************************************************/ -double * -Cudd_CofMinterm( - DdManager * dd, - DdNode * node) -{ - st_table *table; - double *values; - double *result = NULL; - int i, firstLevel; - -#ifdef DD_STATS - long startTime; - startTime = util_cpu_time(); - num_calls = 0; - table_mem = sizeof(st_table); -#endif - - table = st_init_table(st_ptrcmp, st_ptrhash); - if (table == NULL) { - (void) fprintf(dd->err, - "out-of-memory, couldn't measure DD cofactors.\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - size = dd->size; - values = ddCofMintermAux(dd, node, table); - if (values != NULL) { - result = ALLOC(double,size + 1); - if (result != NULL) { -#ifdef DD_STATS - table_mem += (size + 1) * sizeof(double); -#endif - if (Cudd_IsConstant(node)) - firstLevel = 1; - else - firstLevel = cuddI(dd,Cudd_Regular(node)->index); - for (i = 0; i < size; i++) { - if (i >= cuddI(dd,Cudd_Regular(node)->index)) { - result[dd->invperm[i]] = values[i - firstLevel]; - } else { - result[dd->invperm[i]] = values[size - firstLevel]; - } - } - result[size] = values[size - firstLevel]; - } else { - dd->errorCode = CUDD_MEMORY_OUT; - } - } - -#ifdef DD_STATS - table_mem += table->num_bins * sizeof(st_table_entry *); -#endif - if (Cudd_Regular(node)->ref == 1) FREE(values); - st_foreach(table, cuddStCountfree, NULL); - st_free_table(table); -#ifdef DD_STATS - (void) fprintf(dd->out,"Number of calls: %d\tTable memory: %d bytes\n", - num_calls, table_mem); - (void) fprintf(dd->out,"Time to compute measures: %s\n", - util_print_time(util_cpu_time() - startTime)); -#endif - if (result == NULL) { - (void) fprintf(dd->out, - "out-of-memory, couldn't measure DD cofactors.\n"); - dd->errorCode = CUDD_MEMORY_OUT; - } - return(result); - -} /* end of Cudd_CofMinterm */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Recursive Step for Cudd_CofMinterm function.] - - Description [Traverses the DD node and computes the fraction of - minterms in the on-set of all positive cofactors simultaneously. - It allocates an array with two more entries than there are - variables below the one labeling the node. One extra entry (the - first in the array) is for the variable labeling the node. The other - entry (the last one in the array) holds the fraction of minterms of - the function rooted at node. Each other entry holds the value for - one cofactor. The array is put in a symbol table, to avoid repeated - computation, and its address is returned by the procedure, for use - by the caller. Returns a pointer to the array of cofactor measures.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static double * -ddCofMintermAux( - DdManager * dd, - DdNode * node, - st_table * table) -{ - DdNode *N; /* regular version of node */ - DdNode *Nv, *Nnv; - double *values; - double *valuesT, *valuesE; - int i; - int localSize, localSizeT, localSizeE; - double vT, vE; - - statLine(dd); -#ifdef DD_STATS - num_calls++; -#endif - - if (st_lookup(table, (char *) node, (char **) &values)) { - return(values); - } - - N = Cudd_Regular(node); - if (cuddIsConstant(N)) { - localSize = 1; - } else { - localSize = size - cuddI(dd,N->index) + 1; - } - values = ALLOC(double, localSize); - if (values == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - if (cuddIsConstant(N)) { - if (node == DD_ZERO(dd) || node == Cudd_Not(DD_ONE(dd))) { - values[0] = 0.0; - } else { - values[0] = 1.0; - } - } else { - Nv = Cudd_NotCond(cuddT(N),N!=node); - Nnv = Cudd_NotCond(cuddE(N),N!=node); - - valuesT = ddCofMintermAux(dd, Nv, table); - if (valuesT == NULL) return(NULL); - valuesE = ddCofMintermAux(dd, Nnv, table); - if (valuesE == NULL) return(NULL); - - if (Cudd_IsConstant(Nv)) { - localSizeT = 1; - } else { - localSizeT = size - cuddI(dd,Cudd_Regular(Nv)->index) + 1; - } - if (Cudd_IsConstant(Nnv)) { - localSizeE = 1; - } else { - localSizeE = size - cuddI(dd,Cudd_Regular(Nnv)->index) + 1; - } - values[0] = valuesT[localSizeT - 1]; - for (i = 1; i < localSize; i++) { - if (i >= cuddI(dd,Cudd_Regular(Nv)->index) - cuddI(dd,N->index)) { - vT = valuesT[i - cuddI(dd,Cudd_Regular(Nv)->index) + - cuddI(dd,N->index)]; - } else { - vT = valuesT[localSizeT - 1]; - } - if (i >= cuddI(dd,Cudd_Regular(Nnv)->index) - cuddI(dd,N->index)) { - vE = valuesE[i - cuddI(dd,Cudd_Regular(Nnv)->index) + - cuddI(dd,N->index)]; - } else { - vE = valuesE[localSizeE - 1]; - } - values[i] = (vT + vE) / 2.0; - } - if (Cudd_Regular(Nv)->ref == 1) FREE(valuesT); - if (Cudd_Regular(Nnv)->ref == 1) FREE(valuesE); - } - - if (N->ref > 1) { - if (st_add_direct(table, (char *) node, (char *) values) == ST_OUT_OF_MEM) { - FREE(values); - return(NULL); - } -#ifdef DD_STATS - table_mem += localSize * sizeof(double) + sizeof(st_table_entry); -#endif - } - return(values); - -} /* end of ddCofMintermAux */ - diff --git a/src/bdd/cudd/cuddSolve.c b/src/bdd/cudd/cuddSolve.c deleted file mode 100644 index d9c4a2e7..00000000 --- a/src/bdd/cudd/cuddSolve.c +++ /dev/null @@ -1,339 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSolve.c] - - PackageName [cudd] - - Synopsis [Boolean equation solver and related functions.] - - Description [External functions included in this modoule: - <ul> - <li> Cudd_SolveEqn() - <li> Cudd_VerifySol() - </ul> - Internal functions included in this module: - <ul> - <li> cuddSolveEqnRecur() - <li> cuddVerifySol() - </ul> ] - - SeeAlso [] - - Author [Balakrishna Kumthekar] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Structure declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSolve.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the solution of F(x,y) = 0.] - - Description [Implements the solution for F(x,y) = 0. The return - value is the consistency condition. The y variables are the unknowns - and the remaining variables are the parameters. Returns the - consistency condition if successful; NULL otherwise. Cudd_SolveEqn - allocates an array and fills it with the indices of the - unknowns. This array is used by Cudd_VerifySol.] - - SideEffects [The solution is returned in G; the indices of the y - variables are returned in yIndex.] - - SeeAlso [Cudd_VerifySol] - -******************************************************************************/ -DdNode * -Cudd_SolveEqn( - DdManager * bdd, - DdNode * F /* the left-hand side of the equation */, - DdNode * Y /* the cube of the y variables */, - DdNode ** G /* the array of solutions (return parameter) */, - int ** yIndex /* index of y variables */, - int n /* numbers of unknowns */) -{ - DdNode *res; - int *temp; - - *yIndex = temp = ALLOC(int, n); - if (temp == NULL) { - bdd->errorCode = CUDD_MEMORY_OUT; - (void) fprintf(bdd->out, - "Cudd_SolveEqn: Out of memory for yIndex\n"); - return(NULL); - } - - do { - bdd->reordered = 0; - res = cuddSolveEqnRecur(bdd, F, Y, G, n, temp, 0); - } while (bdd->reordered == 1); - - return(res); - -} /* end of Cudd_SolveEqn */ - - -/**Function******************************************************************** - - Synopsis [Checks the solution of F(x,y) = 0.] - - Description [Checks the solution of F(x,y) = 0. This procedure - substitutes the solution components for the unknowns of F and returns - the resulting BDD for F.] - - SideEffects [Frees the memory pointed by yIndex.] - - SeeAlso [Cudd_SolveEqn] - -******************************************************************************/ -DdNode * -Cudd_VerifySol( - DdManager * bdd, - DdNode * F /* the left-hand side of the equation */, - DdNode ** G /* the array of solutions */, - int * yIndex /* index of y variables */, - int n /* numbers of unknowns */) -{ - DdNode *res; - - do { - bdd->reordered = 0; - res = cuddVerifySol(bdd, F, G, yIndex, n); - } while (bdd->reordered == 1); - - FREE(yIndex); - - return(res); - -} /* end of Cudd_VerifySol */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_SolveEqn.] - - Description [Implements the recursive step of Cudd_SolveEqn. - Returns NULL if the intermediate solution blows up - or reordering occurs. The parametric solutions are - stored in the array G.] - - SideEffects [none] - - SeeAlso [Cudd_SolveEqn, Cudd_VerifySol] - -******************************************************************************/ -DdNode * -cuddSolveEqnRecur( - DdManager * bdd, - DdNode * F /* the left-hand side of the equation */, - DdNode * Y /* the cube of remaining y variables */, - DdNode ** G /* the array of solutions */, - int n /* number of unknowns */, - int * yIndex /* array holding the y variable indices */, - int i /* level of recursion */) -{ - DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one; - DdNodePtr *variables; - - int j; - - statLine(bdd); - variables = bdd->vars; - one = DD_ONE(bdd); - - /* Base condition. */ - if (Y == one) { - return F; - } - - /* Cofactor of Y. */ - yIndex[i] = Y->index; - nextY = Cudd_T(Y); - - /* Universal abstraction of F with respect to the top variable index. */ - Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]); - if (Fm1) { - Fm1 = Cudd_Not(Fm1); - cuddRef(Fm1); - } else { - return(NULL); - } - - Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1); - if (Fn) { - cuddRef(Fn); - } else { - Cudd_RecursiveDeref(bdd, Fm1); - return(NULL); - } - - Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]); - if (Fv) { - cuddRef(Fv); - } else { - Cudd_RecursiveDeref(bdd, Fm1); - Cudd_RecursiveDeref(bdd, Fn); - return(NULL); - } - - Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]])); - if (Fvbar) { - cuddRef(Fvbar); - } else { - Cudd_RecursiveDeref(bdd, Fm1); - Cudd_RecursiveDeref(bdd, Fn); - Cudd_RecursiveDeref(bdd, Fv); - return(NULL); - } - - /* Build i-th component of the solution. */ - w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar); - if (w) { - cuddRef(w); - } else { - Cudd_RecursiveDeref(bdd, Fm1); - Cudd_RecursiveDeref(bdd, Fn); - Cudd_RecursiveDeref(bdd, Fv); - Cudd_RecursiveDeref(bdd, Fvbar); - return(NULL); - } - - T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1)); - if(T) { - cuddRef(T); - } else { - Cudd_RecursiveDeref(bdd, Fm1); - Cudd_RecursiveDeref(bdd, Fn); - Cudd_RecursiveDeref(bdd, Fv); - Cudd_RecursiveDeref(bdd, Fvbar); - Cudd_RecursiveDeref(bdd, w); - return(NULL); - } - - Cudd_RecursiveDeref(bdd,Fm1); - Cudd_RecursiveDeref(bdd,w); - Cudd_RecursiveDeref(bdd,Fv); - Cudd_RecursiveDeref(bdd,Fvbar); - - /* Substitute components of solution already found into solution. */ - for (j = n-1; j > i; j--) { - w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]); - if(w) { - cuddRef(w); - } else { - Cudd_RecursiveDeref(bdd, Fn); - Cudd_RecursiveDeref(bdd, T); - return(NULL); - } - Cudd_RecursiveDeref(bdd,T); - T = w; - } - G[i] = T; - - Cudd_Deref(Fn); - - return(Fn); - -} /* end of cuddSolveEqnRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_VerifySol. ] - - Description [] - - SideEffects [none] - - SeeAlso [Cudd_VerifySol] - -******************************************************************************/ -DdNode * -cuddVerifySol( - DdManager * bdd, - DdNode * F /* the left-hand side of the equation */, - DdNode ** G /* the array of solutions */, - int * yIndex /* array holding the y variable indices */, - int n /* number of unknowns */) -{ - DdNode *w, *R; - - int j; - - R = F; - cuddRef(R); - for(j = n - 1; j >= 0; j--) { - w = Cudd_bddCompose(bdd, R, G[j], yIndex[j]); - if (w) { - cuddRef(w); - } else { - return(NULL); - } - Cudd_RecursiveDeref(bdd,R); - R = w; - } - - cuddDeref(R); - - return(R); - -} /* end of cuddVerifySol */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddSplit.c b/src/bdd/cudd/cuddSplit.c deleted file mode 100644 index e21ea7cb..00000000 --- a/src/bdd/cudd/cuddSplit.c +++ /dev/null @@ -1,657 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSplit.c] - - PackageName [cudd] - - Synopsis [Returns a subset of minterms from a boolean function.] - - Description [External functions included in this modoule: - <ul> - <li> Cudd_SplitSet() - </ul> - Internal functions included in this module: - <ul> - <li> cuddSplitSetRecur() - </u> - Static functions included in this module: - <ul> - <li> selectMintermsFromUniverse() - <li> mintermsFromUniverse() - <li> bddAnnotateMintermCount() - </ul> ] - - SeeAlso [] - - Author [Balakrishna Kumthekar] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Structure declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * selectMintermsFromUniverse ARGS((DdManager *manager, int *varSeen, double n)); -static DdNode * mintermsFromUniverse ARGS((DdManager *manager, DdNode **vars, int numVars, double n, int index)); -static double bddAnnotateMintermCount ARGS((DdManager *manager, DdNode *node, double max, st_table *table)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Returns m minterms from a BDD.] - - Description [Returns <code>m</code> minterms from a BDD whose - support has <code>n</code> variables at most. The procedure tries - to create as few extra nodes as possible. The function represented - by <code>S</code> depends on at most <code>n</code> of the variables - in <code>xVars</code>. Returns a BDD with <code>m</code> minterms - of the on-set of S if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_SplitSet( - DdManager * manager, - DdNode * S, - DdNode ** xVars, - int n, - double m) -{ - DdNode *result; - DdNode *zero, *one; - double max, num; - st_table *mtable; - int *varSeen; - int i,index, size; - - size = manager->size; - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Trivial cases. */ - if (m == 0.0) { - return(zero); - } - if (S == zero) { - return(NULL); - } - - max = pow(2.0,(double)n); - if (m > max) - return(NULL); - - do { - manager->reordered = 0; - /* varSeen is used to mark the variables that are encountered - ** while traversing the BDD S. - */ - varSeen = ALLOC(int, size); - if (varSeen == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < size; i++) { - varSeen[i] = -1; - } - for (i = 0; i < n; i++) { - index = (xVars[i])->index; - varSeen[manager->invperm[index]] = 0; - } - - if (S == one) { - if (m == max) - return(S); - result = selectMintermsFromUniverse(manager,varSeen,m); - if (result) - cuddRef(result); - FREE(varSeen); - } else { - mtable = st_init_table(st_ptrcmp,st_ptrhash); - if (mtable == NULL) { - (void) fprintf(manager->out, - "Cudd_SplitSet: out-of-memory.\n"); - FREE(varSeen); - manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - /* The nodes of BDD S are annotated by the number of minterms - ** in their onset. The node and the number of minterms in its - ** onset are stored in mtable. - */ - num = bddAnnotateMintermCount(manager,S,max,mtable); - if (m == num) { - st_foreach(mtable,cuddStCountfree,NIL(char)); - st_free_table(mtable); - FREE(varSeen); - return(S); - } - - result = cuddSplitSetRecur(manager,mtable,varSeen,S,m,max,0); - if (result) - cuddRef(result); - st_foreach(mtable,cuddStCountfree,NULL); - st_free_table(mtable); - FREE(varSeen); - } - } while (manager->reordered == 1); - - cuddDeref(result); - return(result); - -} /* end of Cudd_SplitSet */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_SplitSet.] - - Description [Implements the recursive step of Cudd_SplitSet. The - procedure recursively traverses the BDD and checks to see if any - node satisfies the minterm requirements as specified by 'n'. At any - node X, n is compared to the number of minterms in the onset of X's - children. If either of the child nodes have exactly n minterms, then - that node is returned; else, if n is greater than the onset of one - of the child nodes, that node is retained and the difference in the - number of minterms is extracted from the other child. In case n - minterms can be extracted from constant 1, the algorithm returns the - result with at most log(n) nodes.] - - SideEffects [The array 'varSeen' is updated at every recursive call - to set the variables traversed by the procedure.] - - SeeAlso [] - -******************************************************************************/ -DdNode* -cuddSplitSetRecur( - DdManager * manager, - st_table * mtable, - int * varSeen, - DdNode * p, - double n, - double max, - int index) -{ - DdNode *one, *zero, *N, *Nv; - DdNode *Nnv, *q, *r, *v; - DdNode *result; - double *dummy, numT, numE; - int variable, positive; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* If p is constant, extract n minterms from constant 1. The procedure by - ** construction guarantees that minterms will not be extracted from - ** constant 0. - */ - if (Cudd_IsConstant(p)) { - q = selectMintermsFromUniverse(manager,varSeen,n); - return(q); - } - - N = Cudd_Regular(p); - - /* Set variable as seen. */ - variable = N->index; - varSeen[manager->invperm[variable]] = -1; - - Nv = cuddT(N); - Nnv = cuddE(N); - if (Cudd_IsComplement(p)) { - Nv = Cudd_Not(Nv); - Nnv = Cudd_Not(Nnv); - } - - /* If both the children of 'p' are constants, extract n minterms from a - ** constant node. - */ - if (Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) { - q = selectMintermsFromUniverse(manager,varSeen,n); - if (q == NULL) { - return(NULL); - } - cuddRef(q); - r = cuddBddAndRecur(manager,p,q); - if (r == NULL) { - Cudd_RecursiveDeref(manager,q); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDeref(manager,q); - cuddDeref(r); - return(r); - } - - /* Lookup the # of minterms in the onset of the node from the table. */ - if (!Cudd_IsConstant(Nv)) { - st_lookup(mtable,(char *)Nv, (char **)&dummy); - numT = *dummy/(2*(1<<index)); - } else if (Nv == one) { - numT = max/(2*(1<<index)); - } else { - numT = 0; - } - - if (!Cudd_IsConstant(Nnv)) { - st_lookup(mtable,(char *)Nnv, (char **)&dummy); - numE = *dummy/(2*(1<<index)); - } else if (Nnv == one) { - numE = max/(2*(1<<index)); - } else { - numE = 0; - } - - v = cuddUniqueInter(manager,variable,one,zero); - cuddRef(v); - - /* If perfect match. */ - if (numT == n) { - q = cuddBddAndRecur(manager,v,Nv); - if (q == NULL) { - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(q); - Cudd_RecursiveDeref(manager,v); - cuddDeref(q); - return(q); - } - if (numE == n) { - q = cuddBddAndRecur(manager,Cudd_Not(v),Nnv); - if (q == NULL) { - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(q); - Cudd_RecursiveDeref(manager,v); - cuddDeref(q); - return(q); - } - /* If n is greater than numT, extract the difference from the ELSE child - ** and retain the function represented by the THEN branch. - */ - if (numT < n) { - q = cuddSplitSetRecur(manager,mtable,varSeen, - Nnv,(n-numT),max,index+1); - if (q == NULL) { - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(q); - r = cuddBddIteRecur(manager,v,Nv,q); - if (r == NULL) { - Cudd_RecursiveDeref(manager,q); - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDeref(manager,q); - Cudd_RecursiveDeref(manager,v); - cuddDeref(r); - return(r); - } - /* If n is greater than numE, extract the difference from the THEN child - ** and retain the function represented by the ELSE branch. - */ - if (numE < n) { - q = cuddSplitSetRecur(manager,mtable,varSeen, - Nv, (n-numE),max,index+1); - if (q == NULL) { - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(q); - r = cuddBddIteRecur(manager,v,q,Nnv); - if (r == NULL) { - Cudd_RecursiveDeref(manager,q); - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDeref(manager,q); - Cudd_RecursiveDeref(manager,v); - cuddDeref(r); - return(r); - } - - /* None of the above cases; (n < numT and n < numE) and either of - ** the Nv, Nnv or both are not constants. If possible extract the - ** required minterms the constant branch. - */ - if (Cudd_IsConstant(Nv) && !Cudd_IsConstant(Nnv)) { - q = selectMintermsFromUniverse(manager,varSeen,n); - if (q == NULL) { - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(q); - result = cuddBddAndRecur(manager,v,q); - if (result == NULL) { - Cudd_RecursiveDeref(manager,q); - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(result); - Cudd_RecursiveDeref(manager,q); - Cudd_RecursiveDeref(manager,v); - cuddDeref(result); - return(result); - } else if (!Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) { - q = selectMintermsFromUniverse(manager,varSeen,n); - if (q == NULL) { - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(q); - result = cuddBddAndRecur(manager,Cudd_Not(v),q); - if (result == NULL) { - Cudd_RecursiveDeref(manager,q); - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(result); - Cudd_RecursiveDeref(manager,q); - Cudd_RecursiveDeref(manager,v); - cuddDeref(result); - return(result); - } - - /* Both Nv and Nnv are not constants. So choose the one which - ** has fewer minterms in its onset. - */ - positive = 0; - if (numT < numE) { - q = cuddSplitSetRecur(manager,mtable,varSeen, - Nv,n,max,index+1); - positive = 1; - } else { - q = cuddSplitSetRecur(manager,mtable,varSeen, - Nnv,n,max,index+1); - } - - if (q == NULL) { - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(q); - - if (positive) { - result = cuddBddAndRecur(manager,v,q); - } else { - result = cuddBddAndRecur(manager,Cudd_Not(v),q); - } - if (result == NULL) { - Cudd_RecursiveDeref(manager,q); - Cudd_RecursiveDeref(manager,v); - return(NULL); - } - cuddRef(result); - Cudd_RecursiveDeref(manager,q); - Cudd_RecursiveDeref(manager,v); - cuddDeref(result); - - return(result); - -} /* end of cuddSplitSetRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [This function prepares an array of variables which have not been - encountered so far when traversing the procedure cuddSplitSetRecur.] - - Description [This function prepares an array of variables which have not been - encountered so far when traversing the procedure cuddSplitSetRecur. This - array is then used to extract the required number of minterms from a constant - 1. The algorithm guarantees that the size of BDD will be utmost \log(n).] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -selectMintermsFromUniverse( - DdManager * manager, - int * varSeen, - double n) -{ - int numVars; - int i, size, j; - DdNode *one, *zero, *result; - DdNode **vars; - - numVars = 0; - size = manager->size; - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Count the number of variables not encountered so far in procedure - ** cuddSplitSetRecur. - */ - for (i = size-1; i >= 0; i--) { - if(varSeen[i] == 0) - numVars++; - } - vars = ALLOC(DdNode *, numVars); - if (!vars) { - manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - j = 0; - for (i = size-1; i >= 0; i--) { - if(varSeen[i] == 0) { - vars[j] = cuddUniqueInter(manager,manager->perm[i],one,zero); - cuddRef(vars[j]); - j++; - } - } - - /* Compute a function which has n minterms and depends on at most - ** numVars variables. - */ - result = mintermsFromUniverse(manager,vars,numVars,n, 0); - if (result) - cuddRef(result); - - for (i = 0; i < numVars; i++) - Cudd_RecursiveDeref(manager,vars[i]); - FREE(vars); - - return(result); - -} /* end of selectMintermsFromUniverse */ - - -/**Function******************************************************************** - - Synopsis [Recursive procedure to extract n mintems from constant 1.] - - Description [Recursive procedure to extract n mintems from constant 1.] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -mintermsFromUniverse( - DdManager * manager, - DdNode ** vars, - int numVars, - double n, - int index) -{ - DdNode *one, *zero; - DdNode *q, *result; - double max, max2; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - max = pow(2.0, (double)numVars); - max2 = max / 2.0; - - if (n == max) - return(one); - if (n == 0.0) - return(zero); - /* if n == 2^(numVars-1), return a single variable */ - if (n == max2) - return vars[index]; - else if (n > max2) { - /* When n > 2^(numVars-1), a single variable vars[index] - ** contains 2^(numVars-1) minterms. The rest are extracted - ** from a constant with 1 less variable. - */ - q = mintermsFromUniverse(manager,vars,numVars-1,(n-max2),index+1); - if (q == NULL) - return(NULL); - cuddRef(q); - result = cuddBddIteRecur(manager,vars[index],one,q); - } else { - /* When n < 2^(numVars-1), a literal of variable vars[index] - ** is selected. The required n minterms are extracted from a - ** constant with 1 less variable. - */ - q = mintermsFromUniverse(manager,vars,numVars-1,n,index+1); - if (q == NULL) - return(NULL); - cuddRef(q); - result = cuddBddAndRecur(manager,vars[index],q); - } - - if (result == NULL) { - Cudd_RecursiveDeref(manager,q); - return(NULL); - } - cuddRef(result); - Cudd_RecursiveDeref(manager,q); - cuddDeref(result); - return(result); - -} /* end of mintermsFromUniverse */ - - -/**Function******************************************************************** - - Synopsis [Annotates every node in the BDD node with its minterm count.] - - Description [Annotates every node in the BDD node with its minterm count. - In this function, every node and the minterm count represented by it are - stored in a hash table.] - - SideEffects [Fills up 'table' with the pair <node,minterm_count>.] - -******************************************************************************/ -static double -bddAnnotateMintermCount( - DdManager * manager, - DdNode * node, - double max, - st_table * table) -{ - - DdNode *N,*Nv,*Nnv; - register double min_v,min_nv; - register double min_N; - double *pmin; - double *dummy; - - statLine(manager); - N = Cudd_Regular(node); - if (cuddIsConstant(N)) { - if (node == DD_ONE(manager)) { - return(max); - } else { - return(0.0); - } - } - - if (st_lookup(table,(char *)node,(char **)&dummy)) { - return(*dummy); - } - - Nv = cuddT(N); - Nnv = cuddE(N); - if (N != node) { - Nv = Cudd_Not(Nv); - Nnv = Cudd_Not(Nnv); - } - - /* Recur on the two branches. */ - min_v = bddAnnotateMintermCount(manager,Nv,max,table) / 2.0; - if (min_v == (double)CUDD_OUT_OF_MEM) - return ((double)CUDD_OUT_OF_MEM); - min_nv = bddAnnotateMintermCount(manager,Nnv,max,table) / 2.0; - if (min_nv == (double)CUDD_OUT_OF_MEM) - return ((double)CUDD_OUT_OF_MEM); - min_N = min_v + min_nv; - - pmin = ALLOC(double,1); - if (pmin == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return((double)CUDD_OUT_OF_MEM); - } - *pmin = min_N; - - if (st_insert(table,(char *)node, (char *)pmin) == ST_OUT_OF_MEM) { - FREE(pmin); - return((double)CUDD_OUT_OF_MEM); - } - - return(min_N); - -} /* end of bddAnnotateMintermCount */ diff --git a/src/bdd/cudd/cuddSubsetHB.c b/src/bdd/cudd/cuddSubsetHB.c deleted file mode 100644 index 24d41ce5..00000000 --- a/src/bdd/cudd/cuddSubsetHB.c +++ /dev/null @@ -1,1311 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSubsetHB.c] - - PackageName [cudd] - - Synopsis [Procedure to subset the given BDD by choosing the heavier - branches] - - - Description [External procedures provided by this module: - <ul> - <li> Cudd_SubsetHeavyBranch() - <li> Cudd_SupersetHeavyBranch() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddSubsetHeavyBranch() - </ul> - Static procedures included in this module: - <ul> - <li> ResizeCountMintermPages(); - <li> ResizeNodeDataPages() - <li> ResizeCountNodePages() - <li> SubsetCountMintermAux() - <li> SubsetCountMinterm() - <li> SubsetCountNodesAux() - <li> SubsetCountNodes() - <li> BuildSubsetBdd() - </ul> - ] - - SeeAlso [cuddSubsetSP.c] - - Author [Kavita Ravi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no - warranty about the suitability of this software for any - purpose. It is presented on an AS IS basis.] - -******************************************************************************/ - -#ifdef __STDC__ -#include <float.h> -#else -#define DBL_MAX_EXP 1024 -#endif -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DEFAULT_PAGE_SIZE 2048 -#define DEFAULT_NODE_DATA_PAGE_SIZE 1024 -#define INITIAL_PAGES 128 - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/* data structure to store the information on each node. It keeps - * the number of minterms represented by the DAG rooted at this node - * in terms of the number of variables specified by the user, number - * of nodes in this DAG and the number of nodes of its child with - * lesser number of minterms that are not shared by the child with - * more minterms - */ -struct NodeData { - double *mintermPointer; - int *nodesPointer; - int *lightChildNodesPointer; -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct NodeData NodeData_t; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static int memOut; -#ifdef DEBUG -static int num_calls; -#endif - -static DdNode *zero, *one; /* constant functions */ -static double **mintermPages; /* pointers to the pages */ -static int **nodePages; /* pointers to the pages */ -static int **lightNodePages; /* pointers to the pages */ -static double *currentMintermPage; /* pointer to the current - page */ -static double max; /* to store the 2^n value of the number - * of variables */ - -static int *currentNodePage; /* pointer to the current - page */ -static int *currentLightNodePage; /* pointer to the - * current page */ -static int pageIndex; /* index to next element */ -static int page; /* index to current page */ -static int pageSize = DEFAULT_PAGE_SIZE; /* page size */ -static int maxPages; /* number of page pointers */ - -static NodeData_t *currentNodeDataPage; /* pointer to the current - page */ -static int nodeDataPage; /* index to next element */ -static int nodeDataPageIndex; /* index to next element */ -static NodeData_t **nodeDataPages; /* index to current page */ -static int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE; - /* page size */ -static int maxNodeDataPages; /* number of page pointers */ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void ResizeNodeDataPages ARGS(()); -static void ResizeCountMintermPages ARGS(()); -static void ResizeCountNodePages ARGS(()); -static double SubsetCountMintermAux ARGS((DdNode *node, double max, st_table *table)); -static st_table * SubsetCountMinterm ARGS((DdNode *node, int nvars)); -static int SubsetCountNodesAux ARGS((DdNode *node, st_table *table, double max)); -static int SubsetCountNodes ARGS((DdNode *node, st_table *table, int nvars)); -static void StoreNodes ARGS((st_table *storeTable, DdManager *dd, DdNode *node)); -static DdNode * BuildSubsetBdd ARGS((DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Extracts a dense subset from a BDD with the heavy branch - heuristic.] - - Description [Extracts a dense subset from a BDD. This procedure - builds a subset by throwing away one of the children of each node, - starting from the root, until the result is small enough. The child - that is eliminated from the result is the one that contributes the - fewer minterms. Returns a pointer to the BDD of the subset if - successful. NULL if the procedure runs out of memory. The parameter - numVars is the maximum number of variables to be used in minterm - calculation and node count calculation. The optimal number should - be as close as possible to the size of the support of f. However, - it is safe to pass the value returned by Cudd_ReadSize for numVars - when the number of variables is under 1023. If numVars is larger - than 1023, it will overflow. If a 0 parameter is passed then the - procedure will compute a value which will avoid overflow but will - cause underflow with 2046 variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_SubsetHeavyBranch( - DdManager * dd /* manager */, - DdNode * f /* function to be subset */, - int numVars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the subset */) -{ - DdNode *subset; - - memOut = 0; - do { - dd->reordered = 0; - subset = cuddSubsetHeavyBranch(dd, f, numVars, threshold); - } while ((dd->reordered == 1) && (!memOut)); - - return(subset); - -} /* end of Cudd_SubsetHeavyBranch */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense superset from a BDD with the heavy branch - heuristic.] - - Description [Extracts a dense superset from a BDD. The procedure is - identical to the subset procedure except for the fact that it - receives the complement of the given function. Extracting the subset - of the complement function is equivalent to extracting the superset - of the function. This procedure builds a superset by throwing away - one of the children of each node starting from the root of the - complement function, until the result is small enough. The child - that is eliminated from the result is the one that contributes the - fewer minterms. - Returns a pointer to the BDD of the superset if successful. NULL if - intermediate result causes the procedure to run out of memory. The - parameter numVars is the maximum number of variables to be used in - minterm calculation and node count calculation. The optimal number - should be as close as possible to the size of the support of f. - However, it is safe to pass the value returned by Cudd_ReadSize for - numVars when the number of variables is under 1023. If numVars is - larger than 1023, it will overflow. If a 0 parameter is passed then - the procedure will compute a value which will avoid overflow but - will cause underflow with 2046 variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_SupersetHeavyBranch( - DdManager * dd /* manager */, - DdNode * f /* function to be superset */, - int numVars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the superset */) -{ - DdNode *subset, *g; - - g = Cudd_Not(f); - memOut = 0; - do { - dd->reordered = 0; - subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold); - } while ((dd->reordered == 1) && (!memOut)); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_SupersetHeavyBranch */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [The main procedure that returns a subset by choosing the heavier - branch in the BDD.] - - Description [Here a subset BDD is built by throwing away one of the - children. Starting at root, annotate each node with the number of - minterms (in terms of the total number of variables specified - - numVars), number of nodes taken by the DAG rooted at this node and - number of additional nodes taken by the child that has the lesser - minterms. The child with the lower number of minterms is thrown away - and a dyanmic count of the nodes of the subset is kept. Once the - threshold is reached the subset is returned to the calling - procedure.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetHeavyBranch] - -******************************************************************************/ -DdNode * -cuddSubsetHeavyBranch( - DdManager * dd /* DD manager */, - DdNode * f /* current DD */, - int numVars /* maximum number of variables */, - int threshold /* threshold size for the subset */) -{ - - int i, *size; - st_table *visitedTable; - int numNodes; - NodeData_t *currNodeQual; - DdNode *subset; - double minN; - st_table *storeTable, *approxTable; - char *key, *value; - st_generator *stGen; - - if (f == NULL) { - fprintf(dd->err, "Cannot subset, nil object\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - one = Cudd_ReadOne(dd); - zero = Cudd_Not(one); - - /* If user does not know numVars value, set it to the maximum - * exponent that the pow function can take. The -1 is due to the - * discrepancy in the value that pow takes and the value that - * log gives. - */ - if (numVars == 0) { - /* set default value */ - numVars = DBL_MAX_EXP - 1; - } - - if (Cudd_IsConstant(f)) { - return(f); - } - - max = pow(2.0, (double)numVars); - - /* Create visited table where structures for node data are allocated and - stored in a st_table */ - visitedTable = SubsetCountMinterm(f, numVars); - if ((visitedTable == NULL) || memOut) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - numNodes = SubsetCountNodes(f, visitedTable, numVars); - if (memOut) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - - if (st_lookup(visitedTable, (char *)f, (char **)&currNodeQual)) { - minN = *(((NodeData_t *)currNodeQual)->mintermPointer); - } else { - fprintf(dd->err, - "Something is wrong, ought to be node quality table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - } - - size = ALLOC(int, 1); - if (size == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - *size = numNodes; - -#ifdef DEBUG - num_calls = 0; -#endif - /* table to store nodes being created. */ - storeTable = st_init_table(st_ptrcmp, st_ptrhash); - /* insert the constant */ - cuddRef(one); - if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) == - ST_OUT_OF_MEM) { - fprintf(dd->out, "Something wrong, st_table insert failed\n"); - } - /* table to store approximations of nodes */ - approxTable = st_init_table(st_ptrcmp, st_ptrhash); - subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold, - storeTable, approxTable); - if (subset != NULL) { - cuddRef(subset); - } - - stGen = st_init_gen(approxTable); - if (stGen == NULL) { - st_free_table(approxTable); - return(NULL); - } - while(st_gen(stGen, (char **)&key, (char **)&value)) { - Cudd_RecursiveDeref(dd, (DdNode *)value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(approxTable); - - stGen = st_init_gen(storeTable); - if (stGen == NULL) { - st_free_table(storeTable); - return(NULL); - } - while(st_gen(stGen, (char **)&key, (char **)&value)) { - Cudd_RecursiveDeref(dd, (DdNode *)key); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(storeTable); - - for (i = 0; i <= page; i++) { - FREE(mintermPages[i]); - } - FREE(mintermPages); - for (i = 0; i <= page; i++) { - FREE(nodePages[i]); - } - FREE(nodePages); - for (i = 0; i <= page; i++) { - FREE(lightNodePages[i]); - } - FREE(lightNodePages); - for (i = 0; i <= nodeDataPage; i++) { - FREE(nodeDataPages[i]); - } - FREE(nodeDataPages); - st_free_table(visitedTable); - FREE(size); -#if 0 - (void) Cudd_DebugCheck(dd); - (void) Cudd_CheckKeys(dd); -#endif - - if (subset != NULL) { -#ifdef DD_DEBUG - if (!Cudd_bddLeq(dd, subset, f)) { - fprintf(dd->err, "Wrong subset\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } -#endif - cuddDeref(subset); - return(subset); - } else { - return(NULL); - } -} /* end of cuddSubsetHeavyBranch */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Resize the number of pages allocated to store the node data.] - - Description [Resize the number of pages allocated to store the node data - The procedure moves the counter to the next page when the end of - the page is reached and allocates new pages when necessary.] - - SideEffects [Changes the size of pages, page, page index, maximum - number of pages freeing stuff in case of memory out. ] - - SeeAlso [] - -******************************************************************************/ -static void -ResizeNodeDataPages( - ) -{ - int i; - NodeData_t **newNodeDataPages; - - nodeDataPage++; - /* If the current page index is larger than the number of pages - * allocated, allocate a new page array. Page numbers are incremented by - * INITIAL_PAGES - */ - if (nodeDataPage == maxNodeDataPages) { - newNodeDataPages = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES); - if (newNodeDataPages == NULL) { - for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - memOut = 1; - return; - } else { - for (i = 0; i < maxNodeDataPages; i++) { - newNodeDataPages[i] = nodeDataPages[i]; - } - /* Increase total page count */ - maxNodeDataPages += INITIAL_PAGES; - FREE(nodeDataPages); - nodeDataPages = newNodeDataPages; - } - } - /* Allocate a new page */ - currentNodeDataPage = nodeDataPages[nodeDataPage] = - ALLOC(NodeData_t ,nodeDataPageSize); - if (currentNodeDataPage == NULL) { - for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - memOut = 1; - return; - } - /* reset page index */ - nodeDataPageIndex = 0; - return; - -} /* end of ResizeNodeDataPages */ - - -/**Function******************************************************************** - - Synopsis [Resize the number of pages allocated to store the minterm - counts. ] - - Description [Resize the number of pages allocated to store the minterm - counts. The procedure moves the counter to the next page when the - end of the page is reached and allocates new pages when necessary.] - - SideEffects [Changes the size of minterm pages, page, page index, maximum - number of pages freeing stuff in case of memory out. ] - - SeeAlso [] - -******************************************************************************/ -static void -ResizeCountMintermPages( - ) -{ - int i; - double **newMintermPages; - - page++; - /* If the current page index is larger than the number of pages - * allocated, allocate a new page array. Page numbers are incremented by - * INITIAL_PAGES - */ - if (page == maxPages) { - newMintermPages = ALLOC(double *,maxPages + INITIAL_PAGES); - if (newMintermPages == NULL) { - for (i = 0; i < page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - memOut = 1; - return; - } else { - for (i = 0; i < maxPages; i++) { - newMintermPages[i] = mintermPages[i]; - } - /* Increase total page count */ - maxPages += INITIAL_PAGES; - FREE(mintermPages); - mintermPages = newMintermPages; - } - } - /* Allocate a new page */ - currentMintermPage = mintermPages[page] = ALLOC(double,pageSize); - if (currentMintermPage == NULL) { - for (i = 0; i < page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - memOut = 1; - return; - } - /* reset page index */ - pageIndex = 0; - return; - -} /* end of ResizeCountMintermPages */ - - -/**Function******************************************************************** - - Synopsis [Resize the number of pages allocated to store the node counts.] - - Description [Resize the number of pages allocated to store the node counts. - The procedure moves the counter to the next page when the end of - the page is reached and allocates new pages when necessary.] - - SideEffects [Changes the size of pages, page, page index, maximum - number of pages freeing stuff in case of memory out.] - - SeeAlso [] - -******************************************************************************/ -static void -ResizeCountNodePages( - ) -{ - int i; - int **newNodePages; - - page++; - - /* If the current page index is larger than the number of pages - * allocated, allocate a new page array. The number of pages is incremented - * by INITIAL_PAGES. - */ - if (page == maxPages) { - newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); - if (newNodePages == NULL) { - for (i = 0; i < page; i++) FREE(nodePages[i]); - FREE(nodePages); - for (i = 0; i < page; i++) FREE(lightNodePages[i]); - FREE(lightNodePages); - memOut = 1; - return; - } else { - for (i = 0; i < maxPages; i++) { - newNodePages[i] = nodePages[i]; - } - FREE(nodePages); - nodePages = newNodePages; - } - - newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); - if (newNodePages == NULL) { - for (i = 0; i < page; i++) FREE(nodePages[i]); - FREE(nodePages); - for (i = 0; i < page; i++) FREE(lightNodePages[i]); - FREE(lightNodePages); - memOut = 1; - return; - } else { - for (i = 0; i < maxPages; i++) { - newNodePages[i] = lightNodePages[i]; - } - FREE(lightNodePages); - lightNodePages = newNodePages; - } - /* Increase total page count */ - maxPages += INITIAL_PAGES; - } - /* Allocate a new page */ - currentNodePage = nodePages[page] = ALLOC(int,pageSize); - if (currentNodePage == NULL) { - for (i = 0; i < page; i++) FREE(nodePages[i]); - FREE(nodePages); - for (i = 0; i < page; i++) FREE(lightNodePages[i]); - FREE(lightNodePages); - memOut = 1; - return; - } - /* Allocate a new page */ - currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); - if (currentLightNodePage == NULL) { - for (i = 0; i <= page; i++) FREE(nodePages[i]); - FREE(nodePages); - for (i = 0; i < page; i++) FREE(lightNodePages[i]); - FREE(lightNodePages); - memOut = 1; - return; - } - /* reset page index */ - pageIndex = 0; - return; - -} /* end of ResizeCountNodePages */ - - -/**Function******************************************************************** - - Synopsis [Recursively counts minterms of each node in the DAG.] - - Description [Recursively counts minterms of each node in the DAG. - Similar to the cuddCountMintermAux which recursively counts the - number of minterms for the dag rooted at each node in terms of the - total number of variables (max). This procedure creates the node - data structure and stores the minterm count as part of the node - data structure. ] - - SideEffects [Creates structures of type node quality and fills the st_table] - - SeeAlso [SubsetCountMinterm] - -******************************************************************************/ -static double -SubsetCountMintermAux( - DdNode * node /* function to analyze */, - double max /* number of minterms of constant 1 */, - st_table * table /* visitedTable table */) -{ - - DdNode *N,*Nv,*Nnv; /* nodes to store cofactors */ - double min,*pmin; /* minterm count */ - double min1, min2; /* minterm count */ - NodeData_t *dummy; - NodeData_t *newEntry; - int i; - -#ifdef DEBUG - num_calls++; -#endif - - /* Constant case */ - if (Cudd_IsConstant(node)) { - if (node == zero) { - return(0.0); - } else { - return(max); - } - } else { - - /* check if entry for this node exists */ - if (st_lookup(table,(char *)node, (char **)&dummy)) { - min = *(dummy->mintermPointer); - return(min); - } - - /* Make the node regular to extract cofactors */ - N = Cudd_Regular(node); - - /* store the cofactors */ - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - min1 = SubsetCountMintermAux(Nv, max,table)/2.0; - if (memOut) return(0.0); - min2 = SubsetCountMintermAux(Nnv,max,table)/2.0; - if (memOut) return(0.0); - min = (min1+min2); - - /* if page index is at the bottom, then create a new page */ - if (pageIndex == pageSize) ResizeCountMintermPages(); - if (memOut) { - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0.0); - } - - /* point to the correct location in the page */ - pmin = currentMintermPage+pageIndex; - pageIndex++; - - /* store the minterm count of this node in the page */ - *pmin = min; - - /* Note I allocate the struct here. Freeing taken care of later */ - if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages(); - if (memOut) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - st_free_table(table); - return(0.0); - } - - newEntry = currentNodeDataPage + nodeDataPageIndex; - nodeDataPageIndex++; - - /* points to the correct location in the page */ - newEntry->mintermPointer = pmin; - /* initialize this field of the Node Quality structure */ - newEntry->nodesPointer = NULL; - - /* insert entry for the node in the table */ - if (st_insert(table,(char *)node, (char *)newEntry) == ST_OUT_OF_MEM) { - memOut = 1; - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0.0); - } - return(min); - } - -} /* end of SubsetCountMintermAux */ - - -/**Function******************************************************************** - - Synopsis [Counts minterms of each node in the DAG] - - Description [Counts minterms of each node in the DAG. Similar to the - Cudd_CountMinterm procedure except this returns the minterm count for - all the nodes in the bdd in an st_table.] - - SideEffects [none] - - SeeAlso [SubsetCountMintermAux] - -******************************************************************************/ -static st_table * -SubsetCountMinterm( - DdNode * node /* function to be analyzed */, - int nvars /* number of variables node depends on */) -{ - st_table *table; - double num; - int i; - - -#ifdef DEBUG - num_calls = 0; -#endif - - max = pow(2.0,(double) nvars); - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) goto OUT_OF_MEM; - maxPages = INITIAL_PAGES; - mintermPages = ALLOC(double *,maxPages); - if (mintermPages == NULL) { - st_free_table(table); - goto OUT_OF_MEM; - } - page = 0; - currentMintermPage = ALLOC(double,pageSize); - mintermPages[page] = currentMintermPage; - if (currentMintermPage == NULL) { - FREE(mintermPages); - st_free_table(table); - goto OUT_OF_MEM; - } - pageIndex = 0; - maxNodeDataPages = INITIAL_PAGES; - nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages); - if (nodeDataPages == NULL) { - for (i = 0; i <= page ; i++) FREE(mintermPages[i]); - FREE(mintermPages); - st_free_table(table); - goto OUT_OF_MEM; - } - nodeDataPage = 0; - currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize); - nodeDataPages[nodeDataPage] = currentNodeDataPage; - if (currentNodeDataPage == NULL) { - for (i = 0; i <= page ; i++) FREE(mintermPages[i]); - FREE(mintermPages); - FREE(nodeDataPages); - st_free_table(table); - goto OUT_OF_MEM; - } - nodeDataPageIndex = 0; - - num = SubsetCountMintermAux(node,max,table); - if (memOut) goto OUT_OF_MEM; - return(table); - -OUT_OF_MEM: - memOut = 1; - return(NULL); - -} /* end of SubsetCountMinterm */ - - -/**Function******************************************************************** - - Synopsis [Recursively counts the number of nodes under the dag. - Also counts the number of nodes under the lighter child of - this node.] - - Description [Recursively counts the number of nodes under the dag. - Also counts the number of nodes under the lighter child of - this node. . Note that the same dag may be the lighter child of two - different nodes and have different counts. As with the minterm counts, - the node counts are stored in pages to be space efficient and the - address for these node counts are stored in an st_table associated - to each node. ] - - SideEffects [Updates the node data table with node counts] - - SeeAlso [SubsetCountNodes] - -******************************************************************************/ -static int -SubsetCountNodesAux( - DdNode * node /* current node */, - st_table * table /* table to update node count, also serves as visited table. */, - double max /* maximum number of variables */) -{ - int tval, eval, i; - DdNode *N, *Nv, *Nnv; - double minNv, minNnv; - NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar; - int *pmin, *pminBar, *val; - - if ((node == NULL) || Cudd_IsConstant(node)) - return(0); - - /* if this node has been processed do nothing */ - if (st_lookup(table, (char *)node, (char **)&dummyN) == 1) { - val = dummyN->nodesPointer; - if (val != NULL) - return(0); - } else { - return(0); - } - - N = Cudd_Regular(node); - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - /* find the minterm counts for the THEN and ELSE branches */ - if (Cudd_IsConstant(Nv)) { - if (Nv == zero) { - minNv = 0.0; - } else { - minNv = max; - } - } else { - if (st_lookup(table, (char *)Nv, (char **)&dummyNv) == 1) - minNv = *(dummyNv->mintermPointer); - else { - return(0); - } - } - if (Cudd_IsConstant(Nnv)) { - if (Nnv == zero) { - minNnv = 0.0; - } else { - minNnv = max; - } - } else { - if (st_lookup(table, (char *)Nnv, (char **)&dummyNnv) == 1) { - minNnv = *(dummyNnv->mintermPointer); - } - else { - return(0); - } - } - - - /* recur based on which has larger minterm, */ - if (minNv >= minNnv) { - tval = SubsetCountNodesAux(Nv, table, max); - if (memOut) return(0); - eval = SubsetCountNodesAux(Nnv, table, max); - if (memOut) return(0); - - /* store the node count of the lighter child. */ - if (pageIndex == pageSize) ResizeCountNodePages(); - if (memOut) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0); - } - pmin = currentLightNodePage + pageIndex; - *pmin = eval; /* Here the ELSE child is lighter */ - dummyN->lightChildNodesPointer = pmin; - - } else { - eval = SubsetCountNodesAux(Nnv, table, max); - if (memOut) return(0); - tval = SubsetCountNodesAux(Nv, table, max); - if (memOut) return(0); - - /* store the node count of the lighter child. */ - if (pageIndex == pageSize) ResizeCountNodePages(); - if (memOut) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0); - } - pmin = currentLightNodePage + pageIndex; - *pmin = tval; /* Here the THEN child is lighter */ - dummyN->lightChildNodesPointer = pmin; - - } - /* updating the page index for node count storage. */ - pmin = currentNodePage + pageIndex; - *pmin = tval + eval + 1; - dummyN->nodesPointer = pmin; - - /* pageIndex is parallel page index for count_nodes and count_lightNodes */ - pageIndex++; - - /* if this node has been reached first, it belongs to a heavier - branch. Its complement will be reached later on a lighter branch. - Hence the complement has zero node count. */ - - if (st_lookup(table, (char *)Cudd_Not(node), (char **)&dummyNBar) == 1) { - if (pageIndex == pageSize) ResizeCountNodePages(); - if (memOut) { - for (i = 0; i < page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0); - } - pminBar = currentLightNodePage + pageIndex; - *pminBar = 0; - dummyNBar->lightChildNodesPointer = pminBar; - /* The lighter child has less nodes than the parent. - * So if parent 0 then lighter child zero - */ - if (pageIndex == pageSize) ResizeCountNodePages(); - if (memOut) { - for (i = 0; i < page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0); - } - pminBar = currentNodePage + pageIndex; - *pminBar = 0; - dummyNBar->nodesPointer = pminBar ; /* maybe should point to zero */ - - pageIndex++; - } - return(*pmin); -} /*end of SubsetCountNodesAux */ - - -/**Function******************************************************************** - - Synopsis [Counts the nodes under the current node and its lighter child] - - Description [Counts the nodes under the current node and its lighter - child. Calls a recursive procedure to count the number of nodes of - a DAG rooted at a particular node and the number of nodes taken by its - lighter child.] - - SideEffects [None] - - SeeAlso [SubsetCountNodesAux] - -******************************************************************************/ -static int -SubsetCountNodes( - DdNode * node /* function to be analyzed */, - st_table * table /* node quality table */, - int nvars /* number of variables node depends on */) -{ - int num; - int i; - -#ifdef DEBUG - num_calls = 0; -#endif - - max = pow(2.0,(double) nvars); - maxPages = INITIAL_PAGES; - nodePages = ALLOC(int *,maxPages); - if (nodePages == NULL) { - goto OUT_OF_MEM; - } - - lightNodePages = ALLOC(int *,maxPages); - if (lightNodePages == NULL) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - FREE(nodePages); - goto OUT_OF_MEM; - } - - page = 0; - currentNodePage = nodePages[page] = ALLOC(int,pageSize); - if (currentNodePage == NULL) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - FREE(lightNodePages); - FREE(nodePages); - goto OUT_OF_MEM; - } - - currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); - if (currentLightNodePage == NULL) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - FREE(currentNodePage); - FREE(lightNodePages); - FREE(nodePages); - goto OUT_OF_MEM; - } - - pageIndex = 0; - num = SubsetCountNodesAux(node,table,max); - if (memOut) goto OUT_OF_MEM; - return(num); - -OUT_OF_MEM: - memOut = 1; - return(0); - -} /* end of SubsetCountNodes */ - - -/**Function******************************************************************** - - Synopsis [Procedure to recursively store nodes that are retained in the subset.] - - Description [rocedure to recursively store nodes that are retained in the subset.] - - SideEffects [None] - - SeeAlso [StoreNodes] - -******************************************************************************/ -static void -StoreNodes( - st_table * storeTable, - DdManager * dd, - DdNode * node) -{ - char *dummy; - DdNode *N, *Nt, *Ne; - if (Cudd_IsConstant(dd)) { - return; - } - N = Cudd_Regular(node); - if (st_lookup(storeTable, (char *)N, (char **)&dummy)) { - return; - } - cuddRef(N); - if (st_insert(storeTable, (char *)N, NIL(char)) == ST_OUT_OF_MEM) { - fprintf(dd->err,"Something wrong, st_table insert failed\n"); - } - - Nt = Cudd_T(N); - Ne = Cudd_E(N); - - StoreNodes(storeTable, dd, Nt); - StoreNodes(storeTable, dd, Ne); - return; - -} - - -/**Function******************************************************************** - - Synopsis [Builds the subset BDD using the heavy branch method.] - - Description [The procedure carries out the building of the subset BDD - starting at the root. Using the three different counts labelling each node, - the procedure chooses the heavier branch starting from the root and keeps - track of the number of nodes it discards at each step, thus keeping count - of the size of the subset BDD dynamically. Once the threshold is satisfied, - the procedure then calls ITE to build the BDD.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -BuildSubsetBdd( - DdManager * dd /* DD manager */, - DdNode * node /* current node */, - int * size /* current size of the subset */, - st_table * visitedTable /* visited table storing all node data */, - int threshold, - st_table * storeTable, - st_table * approxTable) -{ - - DdNode *Nv, *Nnv, *N, *topv, *neW; - double minNv, minNnv; - NodeData_t *currNodeQual; - NodeData_t *currNodeQualT; - NodeData_t *currNodeQualE; - DdNode *ThenBranch, *ElseBranch; - unsigned int topid; - char *dummy; - -#ifdef DEBUG - num_calls++; -#endif - /*If the size of the subset is below the threshold, dont do - anything. */ - if ((*size) <= threshold) { - /* store nodes below this, so we can recombine if possible */ - StoreNodes(storeTable, dd, node); - return(node); - } - - if (Cudd_IsConstant(node)) - return(node); - - /* Look up minterm count for this node. */ - if (!st_lookup(visitedTable, (char *)node, (char **)&currNodeQual)) { - fprintf(dd->err, - "Something is wrong, ought to be in node quality table\n"); - } - - /* Get children. */ - N = Cudd_Regular(node); - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - /* complement if necessary */ - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - if (!Cudd_IsConstant(Nv)) { - /* find out minterms and nodes contributed by then child */ - if (!st_lookup(visitedTable, (char *)Nv, - (char **)&currNodeQualT)) { - fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - else { - minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer); - } - } else { - if (Nv == zero) { - minNv = 0; - } else { - minNv = max; - } - } - if (!Cudd_IsConstant(Nnv)) { - /* find out minterms and nodes contributed by else child */ - if (!st_lookup(visitedTable, (char *)Nnv, (char **)&currNodeQualE)) { - fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } else { - minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer); - } - } else { - if (Nnv == zero) { - minNnv = 0; - } else { - minNnv = max; - } - } - - /* keep track of size of subset by subtracting the number of - * differential nodes contributed by lighter child - */ - *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer); - if (minNv >= minNnv) { /*SubsetCountNodesAux procedure takes - the Then branch in case of a tie */ - - /* recur with the Then branch */ - ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size, - visitedTable, threshold, storeTable, approxTable); - if (ThenBranch == NULL) { - return(NULL); - } - cuddRef(ThenBranch); - /* The Else branch is either a node that already exists in the - * subset, or one whose approximation has been computed, or - * Zero. - */ - if (st_lookup(storeTable, (char *)Cudd_Regular(Nnv), (char **)&dummy)) { - ElseBranch = Nnv; - cuddRef(ElseBranch); - } else { - if (st_lookup(approxTable, (char *)Nnv, (char **)&dummy)) { - ElseBranch = (DdNode *)dummy; - cuddRef(ElseBranch); - } else { - ElseBranch = zero; - cuddRef(ElseBranch); - } - } - - } - else { - /* recur with the Else branch */ - ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size, - visitedTable, threshold, storeTable, approxTable); - if (ElseBranch == NULL) { - return(NULL); - } - cuddRef(ElseBranch); - /* The Then branch is either a node that already exists in the - * subset, or one whose approximation has been computed, or - * Zero. - */ - if (st_lookup(storeTable, (char *)Cudd_Regular(Nv), (char **)&dummy)) { - ThenBranch = Nv; - cuddRef(ThenBranch); - } else { - if (st_lookup(approxTable, (char *)Nv, (char **)&dummy)) { - ThenBranch = (DdNode *)dummy; - cuddRef(ThenBranch); - } else { - ThenBranch = zero; - cuddRef(ThenBranch); - } - } - } - - /* construct the Bdd with the top variable and the two children */ - topid = Cudd_NodeReadIndex(N); - topv = Cudd_ReadVars(dd, topid); - cuddRef(topv); - neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); - if (neW != NULL) { - cuddRef(neW); - } - Cudd_RecursiveDeref(dd, topv); - Cudd_RecursiveDeref(dd, ThenBranch); - Cudd_RecursiveDeref(dd, ElseBranch); - - - if (neW == NULL) - return(NULL); - else { - /* store this node in the store table */ - if (!st_lookup(storeTable, (char *)Cudd_Regular(neW), (char **)&dummy)) { - cuddRef(neW); - st_insert(storeTable, (char *)Cudd_Regular(neW), (char *)NIL(char)); - - } - /* store the approximation for this node */ - if (N != Cudd_Regular(neW)) { - if (st_lookup(approxTable, (char *)node, (char **)&dummy)) { - fprintf(dd->err, "This node should not be in the approximated table\n"); - } else { - cuddRef(neW); - st_insert(approxTable, (char *)node, (char *)neW); - } - } - cuddDeref(neW); - return(neW); - } -} /* end of BuildSubsetBdd */ - diff --git a/src/bdd/cudd/cuddSubsetSP.c b/src/bdd/cudd/cuddSubsetSP.c deleted file mode 100644 index 55ee3470..00000000 --- a/src/bdd/cudd/cuddSubsetSP.c +++ /dev/null @@ -1,1624 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSubsetSP.c] - - PackageName [cudd] - - Synopsis [Procedure to subset the given BDD choosing the shortest paths - (largest cubes) in the BDD.] - - - Description [External procedures included in this module: - <ul> - <li> Cudd_SubsetShortPaths() - <li> Cudd_SupersetShortPaths() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddSubsetShortPaths() - </ul> - Static procedures included in this module: - <ul> - <li> BuildSubsetBdd() - <li> CreatePathTable() - <li> AssessPathLength() - <li> CreateTopDist() - <li> CreateBotDist() - <li> ResizeNodeDistPages() - <li> ResizeQueuePages() - <li> stPathTableDdFree() - </ul> - ] - - SeeAlso [cuddSubsetHB.c] - - Author [Kavita Ravi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DEFAULT_PAGE_SIZE 2048 /* page size to store the BFS queue element type */ -#define DEFAULT_NODE_DIST_PAGE_SIZE 2048 /* page sizesto store NodeDist_t type */ -#define MAXSHORTINT ((DdHalfWord) ~0) /* constant defined to store - * maximum distance of a node - * from the root or the - * constant - */ -#define INITIAL_PAGES 128 /* number of initial pages for the - * queue/NodeDist_t type */ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/* structure created to store subset results for each node and distances with - * odd and even parity of the node from the root and sink. Main data structure - * in this procedure. - */ -struct NodeDist{ - DdHalfWord oddTopDist; - DdHalfWord evenTopDist; - DdHalfWord oddBotDist; - DdHalfWord evenBotDist; - DdNode *regResult; - DdNode *compResult; -}; - -/* assorted information needed by the BuildSubsetBdd procedure. */ -struct AssortedInfo { - unsigned int maxpath; - int findShortestPath; - int thresholdReached; - st_table *maxpathTable; - int threshold; -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct NodeDist NodeDist_t; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -#ifdef DD_DEBUG -static int numCalls; -static int hits; -static int thishit; -#endif - - -static int memOut; /* flag to indicate out of memory */ -static DdNode *zero, *one; /* constant functions */ - -static NodeDist_t **nodeDistPages; /* pointers to the pages */ -static int nodeDistPageIndex; /* index to next element */ -static int nodeDistPage; /* index to current page */ -static int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE; /* page size */ -static int maxNodeDistPages; /* number of page pointers */ -static NodeDist_t *currentNodeDistPage; /* current page */ - -static DdNode ***queuePages; /* pointers to the pages */ -static int queuePageIndex; /* index to next element */ -static int queuePage; /* index to current page */ -static int queuePageSize = DEFAULT_PAGE_SIZE; /* page size */ -static int maxQueuePages; /* number of page pointers */ -static DdNode **currentQueuePage; /* current page */ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void ResizeNodeDistPages ARGS(()); -static void ResizeQueuePages ARGS(()); -static void CreateTopDist ARGS((st_table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp)); -static int CreateBotDist ARGS((DdNode *node, st_table *pathTable, unsigned int *pathLengthArray, FILE *fp)); -static st_table * CreatePathTable ARGS((DdNode *node, unsigned int *pathLengthArray, FILE *fp)); -static unsigned int AssessPathLength ARGS((unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp)); -static DdNode * BuildSubsetBdd ARGS((DdManager *dd, st_table *pathTable, DdNode *node, struct AssortedInfo *info, st_table *subsetNodeTable)); -static enum st_retval stPathTableDdFree ARGS((char *key, char *value, char *arg)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of Exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense subset from a BDD with the shortest paths - heuristic.] - - Description [Extracts a dense subset from a BDD. This procedure - tries to preserve the shortest paths of the input BDD, because they - give many minterms and contribute few nodes. This procedure may - increase the number of nodes in trying to create the subset or - reduce the number of nodes due to recombination as compared to the - original BDD. Hence the threshold may not be strictly adhered to. In - practice, recombination overshadows the increase in the number of - nodes and results in small BDDs as compared to the threshold. The - hardlimit specifies whether threshold needs to be strictly adhered - to. If it is set to 1, the procedure ensures that result is never - larger than the specified limit but may be considerably less than - the threshold. Returns a pointer to the BDD for the subset if - successful; NULL otherwise. The value for numVars should be as - close as possible to the size of the support of f for better - efficiency. However, it is safe to pass the value returned by - Cudd_ReadSize for numVars. If 0 is passed, then the value returned - by Cudd_ReadSize is used.] - - SideEffects [None] - - SeeAlso [Cudd_SupersetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_SubsetShortPaths( - DdManager * dd /* manager */, - DdNode * f /* function to be subset */, - int numVars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the subset */, - int hardlimit /* flag: 1 if threshold is a hard limit */) -{ - DdNode *subset; - - memOut = 0; - do { - dd->reordered = 0; - subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit); - } while((dd->reordered ==1) && (!memOut)); - - return(subset); - -} /* end of Cudd_SubsetShortPaths */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense superset from a BDD with the shortest paths - heuristic.] - - Description [Extracts a dense superset from a BDD. The procedure is - identical to the subset procedure except for the fact that it - receives the complement of the given function. Extracting the subset - of the complement function is equivalent to extracting the superset - of the function. This procedure tries to preserve the shortest - paths of the complement BDD, because they give many minterms and - contribute few nodes. This procedure may increase the number of - nodes in trying to create the superset or reduce the number of nodes - due to recombination as compared to the original BDD. Hence the - threshold may not be strictly adhered to. In practice, recombination - overshadows the increase in the number of nodes and results in small - BDDs as compared to the threshold. The hardlimit specifies whether - threshold needs to be strictly adhered to. If it is set to 1, the - procedure ensures that result is never larger than the specified - limit but may be considerably less than the threshold. Returns a - pointer to the BDD for the superset if successful; NULL - otherwise. The value for numVars should be as close as possible to - the size of the support of f for better efficiency. However, it is - safe to pass the value returned by Cudd_ReadSize for numVar. If 0 - is passed, then the value returned by Cudd_ReadSize is used.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_SupersetShortPaths( - DdManager * dd /* manager */, - DdNode * f /* function to be superset */, - int numVars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the subset */, - int hardlimit /* flag: 1 if threshold is a hard limit */) -{ - DdNode *subset, *g; - - g = Cudd_Not(f); - memOut = 0; - do { - dd->reordered = 0; - subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit); - } while((dd->reordered ==1) && (!memOut)); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_SupersetShortPaths */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [The outermost procedure to return a subset of the given BDD - with the shortest path lengths.] - - Description [The outermost procedure to return a subset of the given - BDD with the largest cubes. The path lengths are calculated, the maximum - allowable path length is determined and the number of nodes of this - path length that can be used to build a subset. If the threshold is - larger than the size of the original BDD, the original BDD is - returned. ] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths] - -******************************************************************************/ -DdNode * -cuddSubsetShortPaths( - DdManager * dd /* DD manager */, - DdNode * f /* function to be subset */, - int numVars /* total number of variables in consideration */, - int threshold /* maximum number of nodes allowed in the subset */, - int hardlimit /* flag determining whether thershold should be respected strictly */) -{ - st_table *pathTable; - DdNode *N, *subset; - - unsigned int *pathLengthArray; - unsigned int maxpath, oddLen, evenLen, pathLength, *excess; - int i; - NodeDist_t *nodeStat; - struct AssortedInfo *info; - st_table *subsetNodeTable; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - if (numVars == 0) { - /* set default value */ - numVars = Cudd_ReadSize(dd); - } - - if (threshold > numVars) { - threshold = threshold - numVars; - } - if (f == NULL) { - fprintf(dd->err, "Cannot partition, nil object\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - if (Cudd_IsConstant(f)) - return (f); - - pathLengthArray = ALLOC(unsigned int, numVars+1); - for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0; - - -#ifdef DD_DEBUG - numCalls = 0; -#endif - - pathTable = CreatePathTable(f, pathLengthArray, dd->err); - - if ((pathTable == NULL) || (memOut)) { - if (pathTable != NULL) - st_free_table(pathTable); - FREE(pathLengthArray); - return (NIL(DdNode)); - } - - excess = ALLOC(unsigned int, 1); - *excess = 0; - maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess, - dd->err); - - if (maxpath != (unsigned) (numVars + 1)) { - - info = ALLOC(struct AssortedInfo, 1); - info->maxpath = maxpath; - info->findShortestPath = 0; - info->thresholdReached = *excess; - info->maxpathTable = st_init_table(st_ptrcmp, st_ptrhash); - info->threshold = threshold; - -#ifdef DD_DEBUG - (void) fprintf(dd->out, "Path length array\n"); - for (i = 0; i < (numVars+1); i++) { - if (pathLengthArray[i]) - (void) fprintf(dd->out, "%d ",i); - } - (void) fprintf(dd->out, "\n"); - for (i = 0; i < (numVars+1); i++) { - if (pathLengthArray[i]) - (void) fprintf(dd->out, "%d ",pathLengthArray[i]); - } - (void) fprintf(dd->out, "\n"); - (void) fprintf(dd->out, "Maxpath = %d, Thresholdreached = %d\n", - maxpath, info->thresholdReached); -#endif - - N = Cudd_Regular(f); - if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { - fprintf(dd->err, "Something wrong, root node must be in table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } else { - if ((nodeStat->oddTopDist != MAXSHORTINT) && - (nodeStat->oddBotDist != MAXSHORTINT)) - oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); - else - oddLen = MAXSHORTINT; - - if ((nodeStat->evenTopDist != MAXSHORTINT) && - (nodeStat->evenBotDist != MAXSHORTINT)) - evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); - else - evenLen = MAXSHORTINT; - - pathLength = (oddLen <= evenLen) ? oddLen : evenLen; - if (pathLength > maxpath) { - (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %d, %d\n", maxpath, pathLength); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - } - -#ifdef DD_DEBUG - numCalls = 0; - hits = 0; - thishit = 0; -#endif - /* initialize a table to store computed nodes */ - if (hardlimit) { - subsetNodeTable = st_init_table(st_ptrcmp, st_ptrhash); - } else { - subsetNodeTable = NIL(st_table); - } - subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable); - if (subset != NULL) { - cuddRef(subset); - } - /* record the number of times a computed result for a node is hit */ - -#ifdef DD_DEBUG - (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n", - hits, thishit, numCalls); -#endif - - if (subsetNodeTable != NIL(st_table)) { - st_free_table(subsetNodeTable); - } - st_free_table(info->maxpathTable); - st_foreach(pathTable, stPathTableDdFree, (char *)dd); - - FREE(info); - - } else {/* if threshold larger than size of dd */ - subset = f; - cuddRef(subset); - } - FREE(excess); - st_free_table(pathTable); - FREE(pathLengthArray); - for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - -#ifdef DD_DEBUG - /* check containment of subset in f */ - if (subset != NULL) { - DdNode *check; - check = Cudd_bddIteConstant(dd, subset, f, one); - if (check != one) { - (void) fprintf(dd->err, "Wrong partition\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - } -#endif - - if (subset != NULL) { - cuddDeref(subset); - return(subset); - } else { - return(NULL); - } - -} /* end of cuddSubsetShortPaths */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Resize the number of pages allocated to store the distances - related to each node.] - - Description [Resize the number of pages allocated to store the distances - related to each node. The procedure moves the counter to the - next page when the end of the page is reached and allocates new - pages when necessary. ] - - SideEffects [Changes the size of pages, page, page index, maximum - number of pages freeing stuff in case of memory out. ] - - SeeAlso [] - -******************************************************************************/ -static void -ResizeNodeDistPages( - ) -{ - int i; - NodeDist_t **newNodeDistPages; - - /* move to next page */ - nodeDistPage++; - - /* If the current page index is larger than the number of pages - * allocated, allocate a new page array. Page numbers are incremented by - * INITIAL_PAGES - */ - if (nodeDistPage == maxNodeDistPages) { - newNodeDistPages = ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES); - if (newNodeDistPages == NULL) { - for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - memOut = 1; - return; - } else { - for (i = 0; i < maxNodeDistPages; i++) { - newNodeDistPages[i] = nodeDistPages[i]; - } - /* Increase total page count */ - maxNodeDistPages += INITIAL_PAGES; - FREE(nodeDistPages); - nodeDistPages = newNodeDistPages; - } - } - /* Allocate a new page */ - currentNodeDistPage = nodeDistPages[nodeDistPage] = ALLOC(NodeDist_t, - nodeDistPageSize); - if (currentNodeDistPage == NULL) { - for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - memOut = 1; - return; - } - /* reset page index */ - nodeDistPageIndex = 0; - return; - -} /* end of ResizeNodeDistPages */ - - -/**Function******************************************************************** - - Synopsis [Resize the number of pages allocated to store nodes in the BFS - traversal of the Bdd .] - - Description [Resize the number of pages allocated to store nodes in the BFS - traversal of the Bdd. The procedure moves the counter to the - next page when the end of the page is reached and allocates new - pages when necessary.] - - SideEffects [Changes the size of pages, page, page index, maximum - number of pages freeing stuff in case of memory out. ] - - SeeAlso [] - -******************************************************************************/ -static void -ResizeQueuePages( - ) -{ - int i; - DdNode ***newQueuePages; - - queuePage++; - /* If the current page index is larger than the number of pages - * allocated, allocate a new page array. Page numbers are incremented by - * INITIAL_PAGES - */ - if (queuePage == maxQueuePages) { - newQueuePages = ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES); - if (newQueuePages == NULL) { - for (i = 0; i < queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - memOut = 1; - return; - } else { - for (i = 0; i < maxQueuePages; i++) { - newQueuePages[i] = queuePages[i]; - } - /* Increase total page count */ - maxQueuePages += INITIAL_PAGES; - FREE(queuePages); - queuePages = newQueuePages; - } - } - /* Allocate a new page */ - currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *,queuePageSize); - if (currentQueuePage == NULL) { - for (i = 0; i < queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - memOut = 1; - return; - } - /* reset page index */ - queuePageIndex = 0; - return; - -} /* end of ResizeQueuePages */ - - -/**Function******************************************************************** - - Synopsis [ Labels each node with its shortest distance from the root] - - Description [ Labels each node with its shortest distance from the root. - This is done in a BFS search of the BDD. The nodes are processed - in a queue implemented as pages(array) to reduce memory fragmentation. - An entry is created for each node visited. The distance from the root - to the node with the corresponding parity is updated. The procedure - is called recursively each recusion level handling nodes at a given - level from the root.] - - - SideEffects [Creates entries in the pathTable] - - SeeAlso [CreatePathTable CreateBotDist] - -******************************************************************************/ -static void -CreateTopDist( - st_table * pathTable /* hast table to store path lengths */, - int parentPage /* the pointer to the page on which the first parent in the queue is to be found. */, - int parentQueueIndex /* pointer to the first parent on the page */, - int topLen /* current distance from the root */, - DdNode ** childPage /* pointer to the page on which the first child is to be added. */, - int childQueueIndex /* pointer to the first child */, - int numParents /* number of parents to process in this recursive call */, - FILE *fp /* where to write messages */) -{ - NodeDist_t *nodeStat; - DdNode *N, *Nv, *Nnv, *node, *child, *regChild; - int i; - int processingDone, childrenCount; - -#ifdef DD_DEBUG - numCalls++; - - /* assume this procedure comes in with only the root node*/ - /* set queue index to the next available entry for addition */ - /* set queue page to page of addition */ - if ((queuePages[parentPage] == childPage) && (parentQueueIndex == - childQueueIndex)) { - fprintf(fp, "Should not happen that they are equal\n"); - } - assert(queuePageIndex == childQueueIndex); - assert(currentQueuePage == childPage); -#endif - /* number children added to queue is initialized , needed for - * numParents in the next call - */ - childrenCount = 0; - /* process all the nodes in this level */ - while (numParents) { - numParents--; - if (parentQueueIndex == queuePageSize) { - parentPage++; - parentQueueIndex = 0; - } - /* a parent to process */ - node = *(queuePages[parentPage] + parentQueueIndex); - parentQueueIndex++; - /* get its children */ - N = Cudd_Regular(node); - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - processingDone = 2; - while (processingDone) { - /* processing the THEN and the ELSE children, the THEN - * child first - */ - if (processingDone == 2) { - child = Nv; - } else { - child = Nnv; - } - - regChild = Cudd_Regular(child); - /* dont process if the child is a constant */ - if (!Cudd_IsConstant(child)) { - /* check is already visited, if not add a new entry in - * the path Table - */ - if (!st_lookup(pathTable, (char *)regChild, (char **)&nodeStat)) { - /* if not in table, has never been visited */ - /* create entry for table */ - if (nodeDistPageIndex == nodeDistPageSize) - ResizeNodeDistPages(); - if (memOut) { - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - st_free_table(pathTable); - return; - } - /* New entry for child in path Table is created here */ - nodeStat = currentNodeDistPage + nodeDistPageIndex; - nodeDistPageIndex++; - - /* Initialize fields of the node data */ - nodeStat->oddTopDist = MAXSHORTINT; - nodeStat->evenTopDist = MAXSHORTINT; - nodeStat->evenBotDist = MAXSHORTINT; - nodeStat->oddBotDist = MAXSHORTINT; - nodeStat->regResult = NULL; - nodeStat->compResult = NULL; - /* update the table entry element, the distance keeps - * track of the parity of the path from the root - */ - if (Cudd_IsComplement(child)) { - nodeStat->oddTopDist = (DdHalfWord) topLen + 1; - } else { - nodeStat->evenTopDist = (DdHalfWord) topLen + 1; - } - - /* insert entry element for child in the table */ - if (st_insert(pathTable, (char *)regChild, - (char *)nodeStat) == ST_OUT_OF_MEM) { - memOut = 1; - for (i = 0; i <= nodeDistPage; i++) - FREE(nodeDistPages[i]); - FREE(nodeDistPages); - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - st_free_table(pathTable); - return; - } - - /* Create list element for this child to process its children. - * If this node has been processed already, then it appears - * in the path table and hence is never added to the list - * again. - */ - - if (queuePageIndex == queuePageSize) ResizeQueuePages(); - if (memOut) { - for (i = 0; i <= nodeDistPage; i++) - FREE(nodeDistPages[i]); - FREE(nodeDistPages); - st_free_table(pathTable); - return; - } - *(currentQueuePage + queuePageIndex) = child; - queuePageIndex++; - - childrenCount++; - } else { - /* if not been met in a path with this parity before */ - /* put in list */ - if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist == - MAXSHORTINT)) || ((!Cudd_IsComplement(child)) && - (nodeStat->evenTopDist == MAXSHORTINT))) { - - if (queuePageIndex == queuePageSize) ResizeQueuePages(); - if (memOut) { - for (i = 0; i <= nodeDistPage; i++) - FREE(nodeDistPages[i]); - FREE(nodeDistPages); - st_free_table(pathTable); - return; - - } - *(currentQueuePage + queuePageIndex) = child; - queuePageIndex++; - - /* update the distance with the appropriate parity */ - if (Cudd_IsComplement(child)) { - nodeStat->oddTopDist = (DdHalfWord) topLen + 1; - } else { - nodeStat->evenTopDist = (DdHalfWord) topLen + 1; - } - childrenCount++; - } - - } /* end of else (not found in st_table) */ - } /*end of if Not constant child */ - processingDone--; - } /*end of while processing Nv, Nnv */ - } /*end of while numParents */ - -#ifdef DD_DEBUG - assert(queuePages[parentPage] == childPage); - assert(parentQueueIndex == childQueueIndex); -#endif - - if (childrenCount != 0) { - topLen++; - childPage = currentQueuePage; - childQueueIndex = queuePageIndex; - CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen, - childPage, childQueueIndex, childrenCount, fp); - } - - return; - -} /* end of CreateTopDist */ - - -/**Function******************************************************************** - - Synopsis [ Labels each node with the shortest distance from the constant.] - - Description [Labels each node with the shortest distance from the constant. - This is done in a DFS search of the BDD. Each node has an odd - and even parity distance from the sink (since there exists paths to both - zero and one) which is less than MAXSHORTINT. At each node these distances - are updated using the minimum distance of its children from the constant. - SInce now both the length from the root and child is known, the minimum path - length(length of the shortest path between the root and the constant that - this node lies on) of this node can be calculated and used to update the - pathLengthArray] - - SideEffects [Updates Path Table and path length array] - - SeeAlso [CreatePathTable CreateTopDist AssessPathLength] - -******************************************************************************/ -static int -CreateBotDist( - DdNode * node /* current node */, - st_table * pathTable /* path table with path lengths */, - unsigned int * pathLengthArray /* array that stores number of nodes belonging to a particular path length. */, - FILE *fp /* where to write messages */) -{ - DdNode *N, *Nv, *Nnv; - DdNode *realChild; - DdNode *child, *regChild; - NodeDist_t *nodeStat, *nodeStatChild; - unsigned int oddLen, evenLen, pathLength; - DdHalfWord botDist; - int processingDone; - - if (Cudd_IsConstant(node)) - return(1); - N = Cudd_Regular(node); - /* each node has one table entry */ - /* update as you go down the min dist of each node from - the root in each (odd and even) parity */ - if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { - fprintf(fp, "Something wrong, the entry doesn't exist\n"); - return(0); - } - - /* compute length of odd parity distances */ - if ((nodeStat->oddTopDist != MAXSHORTINT) && - (nodeStat->oddBotDist != MAXSHORTINT)) - oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); - else - oddLen = MAXSHORTINT; - - /* compute length of even parity distances */ - if (!((nodeStat->evenTopDist == MAXSHORTINT) || - (nodeStat->evenBotDist == MAXSHORTINT))) - evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); - else - evenLen = MAXSHORTINT; - - /* assign pathlength to minimum of the two */ - pathLength = (oddLen <= evenLen) ? oddLen : evenLen; - - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - /* process each child */ - processingDone = 0; - while (processingDone != 2) { - if (!processingDone) { - child = Nv; - } else { - child = Nnv; - } - - realChild = Cudd_NotCond(child, Cudd_IsComplement(node)); - regChild = Cudd_Regular(child); - if (Cudd_IsConstant(realChild)) { - /* Found a minterm; count parity and shortest distance - ** from the constant. - */ - if (Cudd_IsComplement(child)) - nodeStat->oddBotDist = 1; - else - nodeStat->evenBotDist = 1; - } else { - /* If node not in table, recur. */ - if (!st_lookup(pathTable, (char *) regChild, - (char **)&nodeStatChild)) { - fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n"); - return(0); - } - - if (nodeStatChild->oddBotDist == MAXSHORTINT) { - if (nodeStatChild->evenBotDist == MAXSHORTINT) { - if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp)) - return(0); - } else { - fprintf(fp, "Something wrong, both bot nodeStats should be there\n"); - return(0); - } - } - - /* Update shortest distance from the constant depending on - ** parity. */ - - if (Cudd_IsComplement(child)) { - /* If parity on the edge then add 1 to even distance - ** of child to get odd parity distance and add 1 to - ** odd distance of child to get even parity - ** distance. Change distance of current node only if - ** the calculated distance is less than existing - ** distance. */ - if (nodeStatChild->oddBotDist != MAXSHORTINT) - botDist = nodeStatChild->oddBotDist + 1; - else - botDist = MAXSHORTINT; - if (nodeStat->evenBotDist > botDist ) - nodeStat->evenBotDist = botDist; - - if (nodeStatChild->evenBotDist != MAXSHORTINT) - botDist = nodeStatChild->evenBotDist + 1; - else - botDist = MAXSHORTINT; - if (nodeStat->oddBotDist > botDist) - nodeStat->oddBotDist = botDist; - - } else { - /* If parity on the edge then add 1 to even distance - ** of child to get even parity distance and add 1 to - ** odd distance of child to get odd parity distance. - ** Change distance of current node only if the - ** calculated distance is lesser than existing - ** distance. */ - if (nodeStatChild->evenBotDist != MAXSHORTINT) - botDist = nodeStatChild->evenBotDist + 1; - else - botDist = MAXSHORTINT; - if (nodeStat->evenBotDist > botDist) - nodeStat->evenBotDist = botDist; - - if (nodeStatChild->oddBotDist != MAXSHORTINT) - botDist = nodeStatChild->oddBotDist + 1; - else - botDist = MAXSHORTINT; - if (nodeStat->oddBotDist > botDist) - nodeStat->oddBotDist = botDist; - } - } /* end of else (if not constant child ) */ - processingDone++; - } /* end of while processing Nv, Nnv */ - - /* Compute shortest path length on the fly. */ - if ((nodeStat->oddTopDist != MAXSHORTINT) && - (nodeStat->oddBotDist != MAXSHORTINT)) - oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); - else - oddLen = MAXSHORTINT; - - if ((nodeStat->evenTopDist != MAXSHORTINT) && - (nodeStat->evenBotDist != MAXSHORTINT)) - evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); - else - evenLen = MAXSHORTINT; - - /* Update path length array that has number of nodes of a particular - ** path length. */ - if (oddLen < pathLength ) { - if (pathLength != MAXSHORTINT) - pathLengthArray[pathLength]--; - if (oddLen != MAXSHORTINT) - pathLengthArray[oddLen]++; - pathLength = oddLen; - } - if (evenLen < pathLength ) { - if (pathLength != MAXSHORTINT) - pathLengthArray[pathLength]--; - if (evenLen != MAXSHORTINT) - pathLengthArray[evenLen]++; - } - - return(1); - -} /*end of CreateBotDist */ - - -/**Function******************************************************************** - - Synopsis [ The outer procedure to label each node with its shortest - distance from the root and constant] - - Description [ The outer procedure to label each node with its shortest - distance from the root and constant. Calls CreateTopDist and CreateBotDist. - The basis for computing the distance between root and constant is that - the distance may be the sum of even distances from the node to the root - and constant or the sum of odd distances from the node to the root and - constant. Both CreateTopDist and CreateBotDist create the odd and - even parity distances from the root and constant respectively.] - - SideEffects [None] - - SeeAlso [CreateTopDist CreateBotDist] - -******************************************************************************/ -static st_table * -CreatePathTable( - DdNode * node /* root of function */, - unsigned int * pathLengthArray /* array of path lengths to store nodes labeled with the various path lengths */, - FILE *fp /* where to write messages */) -{ - - st_table *pathTable; - NodeDist_t *nodeStat; - DdHalfWord topLen; - DdNode *N; - int i, numParents; - int insertValue; - DdNode **childPage; - int parentPage; - int childQueueIndex, parentQueueIndex; - - /* Creating path Table for storing data about nodes */ - pathTable = st_init_table(st_ptrcmp,st_ptrhash); - - /* initializing pages for info about each node */ - maxNodeDistPages = INITIAL_PAGES; - nodeDistPages = ALLOC(NodeDist_t *, maxNodeDistPages); - if (nodeDistPages == NULL) { - goto OUT_OF_MEM; - } - nodeDistPage = 0; - currentNodeDistPage = nodeDistPages[nodeDistPage] = - ALLOC(NodeDist_t, nodeDistPageSize); - if (currentNodeDistPage == NULL) { - for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - goto OUT_OF_MEM; - } - nodeDistPageIndex = 0; - - /* Initializing pages for the BFS search queue, implemented as an array. */ - maxQueuePages = INITIAL_PAGES; - queuePages = ALLOC(DdNode **, maxQueuePages); - if (queuePages == NULL) { - goto OUT_OF_MEM; - } - queuePage = 0; - currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *, queuePageSize); - if (currentQueuePage == NULL) { - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - goto OUT_OF_MEM; - } - queuePageIndex = 0; - - /* Enter the root node into the queue to start with. */ - parentPage = queuePage; - parentQueueIndex = queuePageIndex; - topLen = 0; - *(currentQueuePage + queuePageIndex) = node; - queuePageIndex++; - childPage = currentQueuePage; - childQueueIndex = queuePageIndex; - - N = Cudd_Regular(node); - - if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages(); - if (memOut) { - for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - st_free_table(pathTable); - goto OUT_OF_MEM; - } - - nodeStat = currentNodeDistPage + nodeDistPageIndex; - nodeDistPageIndex++; - - nodeStat->oddTopDist = MAXSHORTINT; - nodeStat->evenTopDist = MAXSHORTINT; - nodeStat->evenBotDist = MAXSHORTINT; - nodeStat->oddBotDist = MAXSHORTINT; - nodeStat->regResult = NULL; - nodeStat->compResult = NULL; - - insertValue = st_insert(pathTable, (char *)N, (char *)nodeStat); - if (insertValue == ST_OUT_OF_MEM) { - memOut = 1; - for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - st_free_table(pathTable); - goto OUT_OF_MEM; - } else if (insertValue == 1) { - fprintf(fp, "Something wrong, the entry exists but didnt show up in st_lookup\n"); - return(NULL); - } - - if (Cudd_IsComplement(node)) { - nodeStat->oddTopDist = 0; - } else { - nodeStat->evenTopDist = 0; - } - numParents = 1; - /* call the function that counts the distance of each node from the - * root - */ -#ifdef DD_DEBUG - numCalls = 0; -#endif - CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen, - childPage, childQueueIndex, numParents, fp); - if (memOut) { - fprintf(fp, "Out of Memory and cant count path lengths\n"); - goto OUT_OF_MEM; - } - -#ifdef DD_DEBUG - numCalls = 0; -#endif - /* call the function that counts the distance of each node from the - * constant - */ - if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL); - - /* free BFS queue pages as no longer required */ - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - return(pathTable); - -OUT_OF_MEM: - (void) fprintf(fp, "Out of Memory, cannot allocate pages\n"); - memOut = 1; - return(NULL); - -} /*end of CreatePathTable */ - - -/**Function******************************************************************** - - Synopsis [Chooses the maximum allowable path length of nodes under the - threshold.] - - Description [Chooses the maximum allowable path length under each node. - The corner cases are when the threshold is larger than the number - of nodes in the BDD iself, in which case 'numVars + 1' is returned. - If all nodes of a particular path length are needed, then the - maxpath returned is the next one with excess nodes = 0;] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static unsigned int -AssessPathLength( - unsigned int * pathLengthArray /* array determining number of nodes belonging to the different path lengths */, - int threshold /* threshold to determine maximum allowable nodes in the subset */, - int numVars /* maximum number of variables */, - unsigned int * excess /* number of nodes labeled maxpath required in the subset */, - FILE *fp /* where to write messages */) -{ - unsigned int i, maxpath; - int temp; - - temp = threshold; - i = 0; - maxpath = 0; - /* quit loop if i reaches max number of variables or if temp reaches - * below zero - */ - while ((i < (unsigned) numVars+1) && (temp > 0)) { - if (pathLengthArray[i] > 0) { - maxpath = i; - temp = temp - pathLengthArray[i]; - } - i++; - } - /* if all nodes of max path are needed */ - if (temp >= 0) { - maxpath++; /* now maxpath becomes the next maxppath or max number - of variables */ - *excess = 0; - } else { /* normal case when subset required is less than size of - original BDD */ - *excess = temp + pathLengthArray[maxpath]; - } - - if (maxpath == 0) { - fprintf(fp, "Path Length array seems to be all zeroes, check\n"); - } - return(maxpath); - -} /* end of AssessPathLength */ - - -/**Function******************************************************************** - - Synopsis [Builds the BDD with nodes labeled with path length less than or equal to maxpath] - - Description [Builds the BDD with nodes labeled with path length - under maxpath and as many nodes labeled maxpath as determined by the - threshold. The procedure uses the path table to determine which nodes - in the original bdd need to be retained. This procedure picks a - shortest path (tie break decided by taking the child with the shortest - distance to the constant) and recurs down the path till it reaches the - constant. the procedure then starts building the subset upward from - the constant. All nodes labeled by path lengths less than the given - maxpath are used to build the subset. However, in the case of nodes - that have label equal to maxpath, as many are chosen as required by - the threshold. This number is stored in the info structure in the - field thresholdReached. This field is decremented whenever a node - labeled maxpath is encountered and the nodes labeled maxpath are - aggregated in a maxpath table. As soon as the thresholdReached count - goes to 0, the shortest path from this node to the constant is found. - The extraction of nodes with the above labeling is based on the fact - that each node, labeled with a path length, P, has at least one child - labeled P or less. So extracting all nodes labeled a given path length - P ensures complete paths between the root and the constant. Extraction - of a partial number of nodes with a given path length may result in - incomplete paths and hence the additional number of nodes are grabbed - to complete the path. Since the Bdd is built bottom-up, other nodes - labeled maxpath do lie on complete paths. The procedure may cause the - subset to have a larger or smaller number of nodes than the specified - threshold. The increase in the number of nodes is caused by the - building of a subset and the reduction by recombination. However in - most cases, the recombination overshadows the increase and the - procedure returns a result with lower number of nodes than specified. - The subsetNodeTable is NIL when there is no hard limit on the number - of nodes. Further efforts towards keeping the subset closer to the - threshold number were abandoned in favour of keeping the procedure - simple and fast.] - - SideEffects [SubsetNodeTable is changed if it is not NIL.] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -BuildSubsetBdd( - DdManager * dd /* DD manager */, - st_table * pathTable /* path table with path lengths and computed results */, - DdNode * node /* current node */, - struct AssortedInfo * info /* assorted information structure */, - st_table * subsetNodeTable /* table storing computed results */) -{ - DdNode *N, *Nv, *Nnv; - DdNode *ThenBranch, *ElseBranch, *childBranch; - DdNode *child, *regChild, *regNnv, *regNv; - NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv; - DdNode *neW, *topv, *regNew; - char *entry; - unsigned int topid; - unsigned int childPathLength, oddLen, evenLen, NnvPathLength, NvPathLength; - unsigned int NvBotDist, NnvBotDist; - int tiebreakChild; - int processingDone, thenDone, elseDone; - - -#ifdef DD_DEBUG - numCalls++; -#endif - if (Cudd_IsConstant(node)) - return(node); - - N = Cudd_Regular(node); - /* Find node in table. */ - if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { - (void) fprintf(dd->err, "Something wrong, node must be in table \n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - /* If the node in the table has been visited, then return the corresponding - ** Dd. Since a node can become a subset of itself, its - ** complement (that is te same node reached by a different parity) will - ** become a superset of the original node and result in some minterms - ** that were not in the original set. Hence two different results are - ** maintained, corresponding to the odd and even parities. - */ - - /* If this node is reached with an odd parity, get odd parity results. */ - if (Cudd_IsComplement(node)) { - if (nodeStat->compResult != NULL) { -#ifdef DD_DEBUG - hits++; -#endif - return(nodeStat->compResult); - } - } else { - /* if this node is reached with an even parity, get even parity - * results - */ - if (nodeStat->regResult != NULL) { -#ifdef DD_DEBUG - hits++; -#endif - return(nodeStat->regResult); - } - } - - - /* get children */ - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - /* no child processed */ - processingDone = 0; - /* then child not processed */ - thenDone = 0; - ThenBranch = NULL; - /* else child not processed */ - elseDone = 0; - ElseBranch = NULL; - /* if then child constant, branch is the child */ - if (Cudd_IsConstant(Nv)) { - /*shortest path found */ - if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) { - info->findShortestPath = 0; - } - - ThenBranch = Nv; - cuddRef(ThenBranch); - if (ThenBranch == NULL) { - return(NULL); - } - - thenDone++; - processingDone++; - NvBotDist = MAXSHORTINT; - } else { - /* Derive regular child for table lookup. */ - regNv = Cudd_Regular(Nv); - /* Get node data for shortest path length. */ - if (!st_lookup(pathTable, (char *)regNv, (char **)&nodeStatNv) ) { - (void) fprintf(dd->err, "Something wrong, node must be in table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - /* Derive shortest path length for child. */ - if ((nodeStatNv->oddTopDist != MAXSHORTINT) && - (nodeStatNv->oddBotDist != MAXSHORTINT)) { - oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist); - } else { - oddLen = MAXSHORTINT; - } - - if ((nodeStatNv->evenTopDist != MAXSHORTINT) && - (nodeStatNv->evenBotDist != MAXSHORTINT)) { - evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist); - } else { - evenLen = MAXSHORTINT; - } - - NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; - NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist: - nodeStatNv->evenBotDist; - } - /* if else child constant, branch is the child */ - if (Cudd_IsConstant(Nnv)) { - /*shortest path found */ - if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) { - info->findShortestPath = 0; - } - - ElseBranch = Nnv; - cuddRef(ElseBranch); - if (ElseBranch == NULL) { - return(NULL); - } - - elseDone++; - processingDone++; - NnvBotDist = MAXSHORTINT; - } else { - /* Derive regular child for table lookup. */ - regNnv = Cudd_Regular(Nnv); - /* Get node data for shortest path length. */ - if (!st_lookup(pathTable, (char *)regNnv, (char **)&nodeStatNnv) ) { - (void) fprintf(dd->err, "Something wrong, node must be in table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - /* Derive shortest path length for child. */ - if ((nodeStatNnv->oddTopDist != MAXSHORTINT) && - (nodeStatNnv->oddBotDist != MAXSHORTINT)) { - oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist); - } else { - oddLen = MAXSHORTINT; - } - - if ((nodeStatNnv->evenTopDist != MAXSHORTINT) && - (nodeStatNnv->evenBotDist != MAXSHORTINT)) { - evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist); - } else { - evenLen = MAXSHORTINT; - } - - NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; - NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist : - nodeStatNnv->evenBotDist; - } - - tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0; - /* while both children not processed */ - while (processingDone != 2) { - if (!processingDone) { - /* if no child processed */ - /* pick the child with shortest path length and record which one - * picked - */ - if ((NvPathLength < NnvPathLength) || - ((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) { - child = Nv; - regChild = regNv; - thenDone = 1; - childPathLength = NvPathLength; - } else { - child = Nnv; - regChild = regNnv; - elseDone = 1; - childPathLength = NnvPathLength; - } /* then path length less than else path length */ - } else { - /* if one child processed, process the other */ - if (thenDone) { - child = Nnv; - regChild = regNnv; - elseDone = 1; - childPathLength = NnvPathLength; - } else { - child = Nv; - regChild = regNv; - thenDone = 1; - childPathLength = NvPathLength; - } /* end of else pick the Then child if ELSE child processed */ - } /* end of else one child has been processed */ - - /* ignore (replace with constant 0) all nodes which lie on paths larger - * than the maximum length of the path required - */ - if (childPathLength > info->maxpath) { - /* record nodes visited */ - childBranch = zero; - } else { - if (childPathLength < info->maxpath) { - if (info->findShortestPath) { - info->findShortestPath = 0; - } - childBranch = BuildSubsetBdd(dd, pathTable, child, info, - subsetNodeTable); - - } else { /* Case: path length of node = maxpath */ - /* If the node labeled with maxpath is found in the - ** maxpathTable, use it to build the subset BDD. */ - if (st_lookup(info->maxpathTable, (char *)regChild, - (char **)&entry)) { - /* When a node that is already been chosen is hit, - ** the quest for a complete path is over. */ - if (info->findShortestPath) { - info->findShortestPath = 0; - } - childBranch = BuildSubsetBdd(dd, pathTable, child, info, - subsetNodeTable); - } else { - /* If node is not found in the maxpathTable and - ** the threshold has been reached, then if the - ** path needs to be completed, continue. Else - ** replace the node with a zero. */ - if (info->thresholdReached <= 0) { - if (info->findShortestPath) { - if (st_insert(info->maxpathTable, (char *)regChild, - (char *)NIL(char)) == ST_OUT_OF_MEM) { - memOut = 1; - (void) fprintf(dd->err, "OUT of memory\n"); - info->thresholdReached = 0; - childBranch = zero; - } else { - info->thresholdReached--; - childBranch = BuildSubsetBdd(dd, pathTable, - child, info,subsetNodeTable); - } - } else { /* not find shortest path, we dont need this - node */ - childBranch = zero; - } - } else { /* Threshold hasn't been reached, - ** need the node. */ - if (st_insert(info->maxpathTable, (char *)regChild, - (char *)NIL(char)) == ST_OUT_OF_MEM) { - memOut = 1; - (void) fprintf(dd->err, "OUT of memory\n"); - info->thresholdReached = 0; - childBranch = zero; - } else { - info->thresholdReached--; - if (info->thresholdReached <= 0) { - info->findShortestPath = 1; - } - childBranch = BuildSubsetBdd(dd, pathTable, - child, info, subsetNodeTable); - - } /* end of st_insert successful */ - } /* end of threshold hasnt been reached yet */ - } /* end of else node not found in maxpath table */ - } /* end of if (path length of node = maxpath) */ - } /* end if !(childPathLength > maxpath) */ - if (childBranch == NULL) { - /* deref other stuff incase reordering has taken place */ - if (ThenBranch != NULL) { - Cudd_RecursiveDeref(dd, ThenBranch); - ThenBranch = NULL; - } - if (ElseBranch != NULL) { - Cudd_RecursiveDeref(dd, ElseBranch); - ElseBranch = NULL; - } - return(NULL); - } - - cuddRef(childBranch); - - if (child == Nv) { - ThenBranch = childBranch; - } else { - ElseBranch = childBranch; - } - processingDone++; - - } /*end of while processing Nv, Nnv */ - - info->findShortestPath = 0; - topid = Cudd_NodeReadIndex(N); - topv = Cudd_ReadVars(dd, topid); - cuddRef(topv); - neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); - if (neW != NULL) { - cuddRef(neW); - } - Cudd_RecursiveDeref(dd, topv); - Cudd_RecursiveDeref(dd, ThenBranch); - Cudd_RecursiveDeref(dd, ElseBranch); - - - /* Hard Limit of threshold has been imposed */ - if (subsetNodeTable != NIL(st_table)) { - /* check if a new node is created */ - regNew = Cudd_Regular(neW); - /* subset node table keeps all new nodes that have been created to keep - * a running count of how many nodes have been built in the subset. - */ - if (!st_lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) { - if (!Cudd_IsConstant(regNew)) { - if (st_insert(subsetNodeTable, (char *)regNew, - (char *)NULL) == ST_OUT_OF_MEM) { - (void) fprintf(dd->err, "Out of memory\n"); - return (NULL); - } - if (st_count(subsetNodeTable) > info->threshold) { - info->thresholdReached = 0; - } - } - } - } - - - if (neW == NULL) { - return(NULL); - } else { - /*store computed result in regular form*/ - if (Cudd_IsComplement(node)) { - nodeStat->compResult = neW; - cuddRef(nodeStat->compResult); - /* if the new node is the same as the corresponding node in the - * original bdd then its complement need not be computed as it - * cannot be larger than the node itself - */ - if (neW == node) { -#ifdef DD_DEBUG - thishit++; -#endif - /* if a result for the node has already been computed, then - * it can only be smaller than teh node itself. hence store - * the node result in order not to break recombination - */ - if (nodeStat->regResult != NULL) { - Cudd_RecursiveDeref(dd, nodeStat->regResult); - } - nodeStat->regResult = Cudd_Not(neW); - cuddRef(nodeStat->regResult); - } - - } else { - nodeStat->regResult = neW; - cuddRef(nodeStat->regResult); - if (neW == node) { -#ifdef DD_DEBUG - thishit++; -#endif - if (nodeStat->compResult != NULL) { - Cudd_RecursiveDeref(dd, nodeStat->compResult); - } - nodeStat->compResult = Cudd_Not(neW); - cuddRef(nodeStat->compResult); - } - } - - cuddDeref(neW); - return(neW); - } /* end of else i.e. Subset != NULL */ -} /* end of BuildSubsetBdd */ - - -/**Function******************************************************************** - - Synopsis [Procedure to free te result dds stored in the NodeDist pages.] - - Description [None] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static enum st_retval -stPathTableDdFree( - char * key, - char * value, - char * arg) -{ - NodeDist_t *nodeStat; - DdManager *dd; - - nodeStat = (NodeDist_t *)value; - dd = (DdManager *)arg; - if (nodeStat->regResult != NULL) { - Cudd_RecursiveDeref(dd, nodeStat->regResult); - } - if (nodeStat->compResult != NULL) { - Cudd_RecursiveDeref(dd, nodeStat->compResult); - } - return(ST_CONTINUE); - -} /* end of stPathTableFree */ diff --git a/src/bdd/cudd/cuddSymmetry.c b/src/bdd/cudd/cuddSymmetry.c deleted file mode 100644 index e5488b17..00000000 --- a/src/bdd/cudd/cuddSymmetry.c +++ /dev/null @@ -1,1668 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSymmetry.c] - - PackageName [cudd] - - Synopsis [Functions for symmetry-based variable reordering.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_SymmProfile() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddSymmCheck() - <li> cuddSymmSifting() - <li> cuddSymmSiftingConv() - </ul> - Static procedures included in this module: - <ul> - <li> ddSymmUniqueCompare() - <li> ddSymmSiftingAux() - <li> ddSymmSiftingConvAux() - <li> ddSymmSiftingUp() - <li> ddSymmSiftingDown() - <li> ddSymmGroupMove() - <li> ddSymmGroupMoveBackward() - <li> ddSymmSiftingBackward() - <li> ddSymmSummary() - </ul>] - - Author [Shipra Panda, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define MV_OOM (Move *)1 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static int *entry; - -extern int ddTotalNumberSwapping; -#ifdef DD_STATS -extern int ddTotalNISwaps; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddSymmUniqueCompare ARGS((int *ptrX, int *ptrY)); -static int ddSymmSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static int ddSymmSiftingConvAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static Move * ddSymmSiftingUp ARGS((DdManager *table, int y, int xLow)); -static Move * ddSymmSiftingDown ARGS((DdManager *table, int x, int xHigh)); -static int ddSymmGroupMove ARGS((DdManager *table, int x, int y, Move **moves)); -static int ddSymmGroupMoveBackward ARGS((DdManager *table, int x, int y)); -static int ddSymmSiftingBackward ARGS((DdManager *table, Move *moves, int size)); -static void ddSymmSummary ARGS((DdManager *table, int lower, int upper, int *symvars, int *symgroups)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints statistics on symmetric variables.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -void -Cudd_SymmProfile( - DdManager * table, - int lower, - int upper) -{ - int i,x,gbot; - int TotalSymm = 0; - int TotalSymmGroups = 0; - - for (i = lower; i <= upper; i++) { - if (table->subtables[i].next != (unsigned) i) { - x = i; - (void) fprintf(table->out,"Group:"); - do { - (void) fprintf(table->out," %d",table->invperm[x]); - TotalSymm++; - gbot = x; - x = table->subtables[x].next; - } while (x != i); - TotalSymmGroups++; -#ifdef DD_DEBUG - assert(table->subtables[gbot].next == (unsigned) i); -#endif - i = gbot; - (void) fprintf(table->out,"\n"); - } - } - (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm); - (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups); - -} /* end of Cudd_SymmProfile */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Checks for symmetry of x and y.] - - Description [Checks for symmetry of x and y. Ignores projection - functions, unless they are isolated. Returns 1 in case of symmetry; 0 - otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddSymmCheck( - DdManager * table, - int x, - int y) -{ - DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; - int comple; /* f0 is complemented */ - int xsymmy; /* x and y may be positively symmetric */ - int xsymmyp; /* x and y may be negatively symmetric */ - int arccount; /* number of arcs from layer x to layer y */ - int TotalRefCount; /* total reference count of layer y minus 1 */ - int yindex; - int i; - DdNodePtr *list; - int slots; - DdNode *sentinel = &(table->sentinel); -#ifdef DD_DEBUG - int xindex; -#endif - - /* Checks that x and y are not the projection functions. - ** For x it is sufficient to check whether there is only one - ** node; indeed, if there is one node, it is the projection function - ** and it cannot point to y. Hence, if y isn't just the projection - ** function, it has one arc coming from a layer different from x. - */ - if (table->subtables[x].keys == 1) { - return(0); - } - yindex = table->invperm[y]; - if (table->subtables[y].keys == 1) { - if (table->vars[yindex]->ref == 1) - return(0); - } - - xsymmy = xsymmyp = 1; - arccount = 0; - slots = table->subtables[x].slots; - list = table->subtables[x].nodelist; - for (i = 0; i < slots; i++) { - f = list[i]; - while (f != sentinel) { - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); - f0 = Cudd_Regular(cuddE(f)); - comple = Cudd_IsComplement(cuddE(f)); - if ((int) f1->index == yindex) { - arccount++; - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - if ((int) f0->index != yindex) { - /* If f is an isolated projection function it is - ** allowed to bypass layer y. - */ - if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) - return(0); /* f bypasses layer y */ - } - f11 = f10 = f1; - } - if ((int) f0->index == yindex) { - arccount++; - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = f00 = f0; - } - if (comple) { - f01 = Cudd_Not(f01); - f00 = Cudd_Not(f00); - } - - if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) { - xsymmy &= f01 == f10; - xsymmyp &= f11 == f00; - if ((xsymmy == 0) && (xsymmyp == 0)) - return(0); - } - - f = f->next; - } /* while */ - } /* for */ - - /* Calculate the total reference counts of y */ - TotalRefCount = -1; /* -1 for projection function */ - slots = table->subtables[y].slots; - list = table->subtables[y].nodelist; - for (i = 0; i < slots; i++) { - f = list[i]; - while (f != sentinel) { - TotalRefCount += f->ref; - f = f->next; - } - } - -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (arccount == TotalRefCount) { - xindex = table->invperm[x]; - (void) fprintf(table->out, - "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", - xindex,yindex,x,y); - } -#endif - - return(arccount == TotalRefCount); - -} /* end of cuddSymmCheck */ - - -/**Function******************************************************************** - - Synopsis [Symmetric sifting algorithm.] - - Description [Symmetric sifting algorithm. - Assumes that no dead nodes are present. - <ol> - <li> Order all the variables according to the number of entries in - each unique subtable. - <li> Sift the variable up and down, remembering each time the total - size of the DD heap and grouping variables that are symmetric. - <li> Select the best permutation. - <li> Repeat 3 and 4 for all variables. - </ol> - Returns 1 plus the number of symmetric variables if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddSymmSiftingConv] - -******************************************************************************/ -int -cuddSymmSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; - int symvars; - int symgroups; -#ifdef DD_STATS - int previousSize; -#endif - - size = table->size; - - /* Find order in which to sift variables. */ - var = NULL; - entry = ALLOC(int,size); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddSymmSiftingOutOfMem; - } - var = ALLOC(int,size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddSymmSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->perm[i]; - entry[i] = table->subtables[x].keys; - var[i] = i; - } - - qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare); - - /* Initialize the symmetry of each subtable to itself. */ - for (i = lower; i <= upper; i++) { - table->subtables[i].next = i; - } - - for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->perm[var[i]]; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - if (x < lower || x > upper) continue; - if (table->subtables[x].next == (unsigned) x) { - result = ddSymmSiftingAux(table,x,lower,upper); - if (!result) goto ddSymmSiftingOutOfMem; -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + - table->isolated) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } - - FREE(var); - FREE(entry); - - ddSymmSummary(table, lower, upper, &symvars, &symgroups); - -#ifdef DD_STATS - (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", - symvars); - (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", - symgroups); -#endif - - return(1+symvars); - -ddSymmSiftingOutOfMem: - - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddSymmSifting */ - - -/**Function******************************************************************** - - Synopsis [Symmetric sifting to convergence algorithm.] - - Description [Symmetric sifting to convergence algorithm. - Assumes that no dead nodes are present. - <ol> - <li> Order all the variables according to the number of entries in - each unique subtable. - <li> Sift the variable up and down, remembering each time the total - size of the DD heap and grouping variables that are symmetric. - <li> Select the best permutation. - <li> Repeat 3 and 4 for all variables. - <li> Repeat 1-4 until no further improvement. - </ol> - Returns 1 plus the number of symmetric variables if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddSymmSifting] - -******************************************************************************/ -int -cuddSymmSiftingConv( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; - int symvars; - int symgroups; - int classes; - int initialSize; -#ifdef DD_STATS - int previousSize; -#endif - - initialSize = table->keys - table->isolated; - - size = table->size; - - /* Find order in which to sift variables. */ - var = NULL; - entry = ALLOC(int,size); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddSymmSiftingConvOutOfMem; - } - var = ALLOC(int,size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddSymmSiftingConvOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->perm[i]; - entry[i] = table->subtables[x].keys; - var[i] = i; - } - - qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare); - - /* Initialize the symmetry of each subtable to itself - ** for first pass of converging symmetric sifting. - */ - for (i = lower; i <= upper; i++) { - table->subtables[i].next = i; - } - - for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->perm[var[i]]; - if (x < lower || x > upper) continue; - /* Only sift if not in symmetry group already. */ - if (table->subtables[x].next == (unsigned) x) { -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddSymmSiftingAux(table,x,lower,upper); - if (!result) goto ddSymmSiftingConvOutOfMem; -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + - table->isolated) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } - - /* Sifting now until convergence. */ - while ((unsigned) initialSize > table->keys - table->isolated) { - initialSize = table->keys - table->isolated; -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); -#endif - /* Here we consider only one representative for each symmetry class. */ - for (x = lower, classes = 0; x <= upper; x++, classes++) { - while ((unsigned) x < table->subtables[x].next) { - x = table->subtables[x].next; - } - /* Here x is the largest index in a group. - ** Groups consist of adjacent variables. - ** Hence, the next increment of x will move it to a new group. - */ - i = table->invperm[x]; - entry[i] = table->subtables[x].keys; - var[classes] = i; - } - - qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->perm[var[i]]; - if ((unsigned) x >= table->subtables[x].next) { -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddSymmSiftingConvAux(table,x,lower,upper); - if (!result ) goto ddSymmSiftingConvOutOfMem; -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + - table->isolated) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } /* for */ - } - - ddSymmSummary(table, lower, upper, &symvars, &symgroups); - -#ifdef DD_STATS - (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", - symvars); - (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", - symgroups); -#endif - - FREE(var); - FREE(entry); - - return(1+symvars); - -ddSymmSiftingConvOutOfMem: - - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddSymmSiftingConv */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the variables - according to the number of keys in the subtables. - Returns the difference in number of keys between the two - variables being compared.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmUniqueCompare( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of ddSymmUniqueCompare */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Assumes that x is not part of a symmetry group. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - Move *move; - Move *moveUp; /* list of up moves */ - Move *moveDown; /* list of down moves */ - int initialSize; - int result; - int i; - int topbot; /* index to either top or bottom of symmetry group */ - int initGroupSize, finalGroupSize; - - -#ifdef DD_DEBUG - /* check for previously detected symmetry */ - assert(table->subtables[x].next == (unsigned) x); -#endif - - initialSize = table->keys - table->isolated; - - moveDown = NULL; - moveUp = NULL; - - if ((x - xLow) > (xHigh - x)) { - /* Will go down first, unless x == xHigh: - ** Look for consecutive symmetries above x. - */ - for (i = x; i > xLow; i--) { - if (!cuddSymmCheck(table,i-1,i)) - break; - topbot = table->subtables[i-1].next; /* find top of i-1's group */ - table->subtables[i-1].next = i; - table->subtables[x].next = topbot; /* x is bottom of group so its */ - /* next is top of i-1's group */ - i = topbot + 1; /* add 1 for i--; new i is top of symm group */ - } - } else { - /* Will go up first unless x == xlow: - ** Look for consecutive symmetries below x. - */ - for (i = x; i < xHigh; i++) { - if (!cuddSymmCheck(table,i,i+1)) - break; - /* find bottom of i+1's symm group */ - topbot = i + 1; - while ((unsigned) topbot < table->subtables[topbot].next) { - topbot = table->subtables[topbot].next; - } - table->subtables[topbot].next = table->subtables[i].next; - table->subtables[i].next = i + 1; - i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */ - } - } - - /* Now x may be in the middle of a symmetry group. - ** Find bottom of x's symm group. - */ - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - - if (x == xLow) { /* Sift down */ - -#ifdef DD_DEBUG - /* x must be a singleton */ - assert((unsigned) x == table->subtables[x].next); -#endif - if (x == xHigh) return(1); /* just one variable */ - - initGroupSize = 1; - - moveDown = ddSymmSiftingDown(table,x,xHigh); - /* after this point x --> xHigh, unless early term */ - if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - if (moveDown == NULL) return(1); - - x = moveDown->y; - /* Find bottom of x's group */ - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetry group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - finalGroupSize = i - x + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetry groups detected, return to best position */ - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } else { - initialSize = table->keys - table->isolated; - moveUp = ddSymmSiftingUp(table,x,xLow); - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } - if (!result) goto ddSymmSiftingAuxOutOfMem; - - } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ - /* Find top of x's symm group */ - i = x; /* bottom */ - x = table->subtables[x].next; /* top */ - - if (x == xLow) return(1); /* just one big group */ - - initGroupSize = i - x + 1; - - moveUp = ddSymmSiftingUp(table,x,xLow); - /* after this point x --> xLow, unless early term */ - if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - if (moveUp == NULL) return(1); - - x = moveUp->x; - /* Find top of x's group */ - i = table->subtables[x].next; -#ifdef DD_DEBUG - /* x should be the bottom of the symmetry group and i the top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - finalGroupSize = x - i + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetry groups detected, return to best position */ - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } else { - initialSize = table->keys - table->isolated; - moveDown = ddSymmSiftingDown(table,x,xHigh); - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } - if (!result) goto ddSymmSiftingAuxOutOfMem; - - } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ - - moveDown = ddSymmSiftingDown(table,x,xHigh); - /* at this point x == xHigh, unless early term */ - if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - - if (moveDown != NULL) { - x = moveDown->y; /* x is top here */ - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } - } else { - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } - x = table->subtables[i].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetry group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - initGroupSize = i - x + 1; - - moveUp = ddSymmSiftingUp(table,x,xLow); - if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - - if (moveUp != NULL) { - x = moveUp->x; - i = table->subtables[x].next; - } else { - i = x; - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x should be the bottom of the symmetry group and i the top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - finalGroupSize = x - i + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetry groups detected, return to best position */ - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } else { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - initialSize = table->keys - table->isolated; - moveDown = ddSymmSiftingDown(table,x,xHigh); - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } - if (!result) goto ddSymmSiftingAuxOutOfMem; - - } else { /* moving up first: shorter */ - /* Find top of x's symmetry group */ - x = table->subtables[x].next; - - moveUp = ddSymmSiftingUp(table,x,xLow); - /* at this point x == xHigh, unless early term */ - if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - - if (moveUp != NULL) { - x = moveUp->x; - i = table->subtables[x].next; - } else { - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - i = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x is bottom of the symmetry group and i is top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - initGroupSize = x - i + 1; - - moveDown = ddSymmSiftingDown(table,x,xHigh); - if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - - if (moveDown != NULL) { - x = moveDown->y; - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } - } else { - i = x; - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetry group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - finalGroupSize = i - x + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetries detected, go back to best position */ - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } else { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - initialSize = table->keys - table->isolated; - moveUp = ddSymmSiftingUp(table,x,xLow); - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } - if (!result) goto ddSymmSiftingAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - - return(1); - -ddSymmSiftingAuxOutOfMem: - if (moveDown != MV_OOM) { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - } - if (moveUp != MV_OOM) { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - } - - return(0); - -} /* end of ddSymmSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Assumes that x is either an isolated variable, or it is the bottom of - a symmetry group. All symmetries may not have been found, because of - exceeded growth limit. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmSiftingConvAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - Move *move; - Move *moveUp; /* list of up moves */ - Move *moveDown; /* list of down moves */ - int initialSize; - int result; - int i; - int initGroupSize, finalGroupSize; - - - initialSize = table->keys - table->isolated; - - moveDown = NULL; - moveUp = NULL; - - if (x == xLow) { /* Sift down */ -#ifdef DD_DEBUG - /* x is bottom of symmetry group */ - assert((unsigned) x >= table->subtables[x].next); -#endif - i = table->subtables[x].next; - initGroupSize = x - i + 1; - - moveDown = ddSymmSiftingDown(table,x,xHigh); - /* at this point x == xHigh, unless early term */ - if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - if (moveDown == NULL) return(1); - - x = moveDown->y; - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetric group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - finalGroupSize = i - x + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetries detected, go back to best position */ - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } else { - initialSize = table->keys - table->isolated; - moveUp = ddSymmSiftingUp(table,x,xLow); - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } - if (!result) goto ddSymmSiftingConvAuxOutOfMem; - - } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ - /* Find top of x's symm group */ - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - i = x; /* bottom */ - x = table->subtables[x].next; /* top */ - - if (x == xLow) return(1); - - initGroupSize = i - x + 1; - - moveUp = ddSymmSiftingUp(table,x,xLow); - /* at this point x == xLow, unless early term */ - if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - if (moveUp == NULL) return(1); - - x = moveUp->x; - i = table->subtables[x].next; -#ifdef DD_DEBUG - /* x should be the bottom of the symmetry group and i the top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - finalGroupSize = x - i + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetry groups detected, return to best position */ - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } else { - initialSize = table->keys - table->isolated; - moveDown = ddSymmSiftingDown(table,x,xHigh); - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } - if (!result) - goto ddSymmSiftingConvAuxOutOfMem; - - } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ - moveDown = ddSymmSiftingDown(table,x,xHigh); - /* at this point x == xHigh, unless early term */ - if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - - if (moveDown != NULL) { - x = moveDown->y; - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } - } else { - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - i = x; - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetry group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - initGroupSize = i - x + 1; - - moveUp = ddSymmSiftingUp(table,x,xLow); - if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - - if (moveUp != NULL) { - x = moveUp->x; - i = table->subtables[x].next; - } else { - i = x; - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x should be the bottom of the symmetry group and i the top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - finalGroupSize = x - i + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetry groups detected, return to best position */ - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } else { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - initialSize = table->keys - table->isolated; - moveDown = ddSymmSiftingDown(table,x,xHigh); - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } - if (!result) goto ddSymmSiftingConvAuxOutOfMem; - - } else { /* moving up first: shorter */ - /* Find top of x's symmetry group */ - x = table->subtables[x].next; - - moveUp = ddSymmSiftingUp(table,x,xLow); - /* at this point x == xHigh, unless early term */ - if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - - if (moveUp != NULL) { - x = moveUp->x; - i = table->subtables[x].next; - } else { - i = x; - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x is bottom of the symmetry group and i is top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - initGroupSize = x - i + 1; - - moveDown = ddSymmSiftingDown(table,x,xHigh); - if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - - if (moveDown != NULL) { - x = moveDown->y; - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } - } else { - i = x; - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetry group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - finalGroupSize = i - x + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetries detected, go back to best position */ - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } else { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - initialSize = table->keys - table->isolated; - moveUp = ddSymmSiftingUp(table,x,xLow); - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } - if (!result) goto ddSymmSiftingConvAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - - return(1); - -ddSymmSiftingConvAuxOutOfMem: - if (moveDown != MV_OOM) { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - } - if (moveUp != MV_OOM) { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - } - - return(0); - -} /* end of ddSymmSiftingConvAux */ - - -/**Function******************************************************************** - - Synopsis [Moves x up until either it reaches the bound (xLow) or - the size of the DD heap increases too much.] - - Description [Moves x up until either it reaches the bound (xLow) or - the size of the DD heap increases too much. Assumes that x is the top - of a symmetry group. Checks x for symmetry to the adjacent - variables. If symmetry is found, the symmetry group of x is merged - with the symmetry group of the other variable. Returns the set of - moves in case of success; MV_OOM if memory is full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddSymmSiftingUp( - DdManager * table, - int y, - int xLow) -{ - Move *moves; - Move *move; - int x; - int size; - int i; - int gxtop,gybot; - int limitSize; - int xindex, yindex; - int zindex; - int z; - int isolated; - int L; /* lower bound on DD size */ -#ifdef DD_DEBUG - int checkL; -#endif - - - moves = NULL; - yindex = table->invperm[y]; - - /* Initialize the lower bound. - ** The part of the DD below the bottom of y' group will not change. - ** The part of the DD above y that does not interact with y will not - ** change. The rest may vanish in the best case, except for - ** the nodes at level xLow, which will not vanish, regardless. - */ - limitSize = L = table->keys - table->isolated; - gybot = y; - while ((unsigned) gybot < table->subtables[gybot].next) - gybot = table->subtables[gybot].next; - for (z = xLow + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - L -= table->subtables[z].keys - isolated; - } - } - - x = cuddNextLow(table,y); - while (x >= xLow && L <= limitSize) { -#ifdef DD_DEBUG - gybot = y; - while ((unsigned) gybot < table->subtables[gybot].next) - gybot = table->subtables[gybot].next; - checkL = table->keys - table->isolated; - for (z = xLow + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - checkL -= table->subtables[z].keys - isolated; - } - } - assert(L == checkL); -#endif - gxtop = table->subtables[x].next; - if (cuddSymmCheck(table,x,y)) { - /* Symmetry found, attach symm groups */ - table->subtables[x].next = y; - i = table->subtables[y].next; - while (table->subtables[i].next != (unsigned) y) - i = table->subtables[i].next; - table->subtables[i].next = gxtop; - } else if (table->subtables[x].next == (unsigned) x && - table->subtables[y].next == (unsigned) y) { - /* x and y have self symmetry */ - xindex = table->invperm[x]; - size = cuddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtables[x].next == (unsigned) x); - assert(table->subtables[y].next == (unsigned) y); -#endif - if (size == 0) goto ddSymmSiftingUpOutOfMem; - /* Update the lower bound. */ - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L += table->subtables[y].keys - isolated; - } - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSymmSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > (double) limitSize * table->maxGrowth) - return(moves); - if (size < limitSize) limitSize = size; - } else { /* Group move */ - size = ddSymmGroupMove(table,x,y,&moves); - if (size == 0) goto ddSymmSiftingUpOutOfMem; - /* Update the lower bound. */ - z = moves->y; - do { - zindex = table->invperm[z]; - if (cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - L += table->subtables[z].keys - isolated; - } - z = table->subtables[z].next; - } while (z != (int) moves->y); - if ((double) size > (double) limitSize * table->maxGrowth) - return(moves); - if (size < limitSize) limitSize = size; - } - y = gxtop; - x = cuddNextLow(table,y); - } - - return(moves); - -ddSymmSiftingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(MV_OOM); - -} /* end of ddSymmSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Moves x down until either it reaches the bound (xHigh) or - the size of the DD heap increases too much.] - - Description [Moves x down until either it reaches the bound (xHigh) - or the size of the DD heap increases too much. Assumes that x is the - bottom of a symmetry group. Checks x for symmetry to the adjacent - variables. If symmetry is found, the symmetry group of x is merged - with the symmetry group of the other variable. Returns the set of - moves in case of success; MV_OOM if memory is full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddSymmSiftingDown( - DdManager * table, - int x, - int xHigh) -{ - Move *moves; - Move *move; - int y; - int size; - int limitSize; - int gxtop,gybot; - int R; /* upper bound on node decrease */ - int xindex, yindex; - int isolated; - int z; - int zindex; -#ifdef DD_DEBUG - int checkR; -#endif - - moves = NULL; - /* Initialize R */ - xindex = table->invperm[x]; - gxtop = table->subtables[x].next; - limitSize = size = table->keys - table->isolated; - R = 0; - for (z = xHigh; z > gxtop; z--) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R += table->subtables[z].keys - isolated; - } - } - - y = cuddNextHigh(table,x); - while (y <= xHigh && size - R < limitSize) { -#ifdef DD_DEBUG - gxtop = table->subtables[x].next; - checkR = 0; - for (z = xHigh; z > gxtop; z--) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - checkR += table->subtables[z].keys - isolated; - } - } - assert(R == checkR); -#endif - gybot = table->subtables[y].next; - while (table->subtables[gybot].next != (unsigned) y) - gybot = table->subtables[gybot].next; - if (cuddSymmCheck(table,x,y)) { - /* Symmetry found, attach symm groups */ - gxtop = table->subtables[x].next; - table->subtables[x].next = y; - table->subtables[gybot].next = gxtop; - } else if (table->subtables[x].next == (unsigned) x && - table->subtables[y].next == (unsigned) y) { - /* x and y have self symmetry */ - /* Update upper bound on node decrease. */ - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R -= table->subtables[y].keys - isolated; - } - size = cuddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtables[x].next == (unsigned) x); - assert(table->subtables[y].next == (unsigned) y); -#endif - if (size == 0) goto ddSymmSiftingDownOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSymmSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > (double) limitSize * table->maxGrowth) - return(moves); - if (size < limitSize) limitSize = size; - } else { /* Group move */ - /* Update upper bound on node decrease: first phase. */ - gxtop = table->subtables[x].next; - z = gxtop + 1; - do { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R -= table->subtables[z].keys - isolated; - } - z++; - } while (z <= gybot); - size = ddSymmGroupMove(table,x,y,&moves); - if (size == 0) goto ddSymmSiftingDownOutOfMem; - if ((double) size > (double) limitSize * table->maxGrowth) - return(moves); - if (size < limitSize) limitSize = size; - /* Update upper bound on node decrease: second phase. */ - gxtop = table->subtables[gybot].next; - for (z = gxtop + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R += table->subtables[z].keys - isolated; - } - } - } - x = gybot; - y = cuddNextHigh(table,x); - } - - return(moves); - -ddSymmSiftingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(MV_OOM); - -} /* end of ddSymmSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Swaps two groups.] - - Description [Swaps two groups. x is assumed to be the bottom variable - of the first group. y is assumed to be the top variable of the second - group. Updates the list of moves. Returns the number of keys in the - table if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmGroupMove( - DdManager * table, - int x, - int y, - Move ** moves) -{ - Move *move; - int size; - int i,j; - int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - int swapx,swapy; - -#if DD_DEBUG - assert(x < y); /* we assume that x < y */ -#endif - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtables[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtables[ybot].next) - ybot = table->subtables[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - - /* Sift the variables of the second group up through the first group. */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddSwapInPlace(table,x,y); - if (size == 0) return(0); - swapx = x; swapy = y; - y = x; - x = y - 1; - } - y = ytop + i; - x = y - 1; - } - - /* fix symmetries */ - y = xtop; /* ytop is now where xtop used to be */ - for (i = 0; i < ysize-1 ; i++) { - table->subtables[y].next = y + 1; - y = y + 1; - } - table->subtables[y].next = xtop; /* y is bottom of its group, join */ - /* its symmetry to top of its group */ - x = y + 1; - newxtop = x; - for (i = 0; i < xsize - 1 ; i++) { - table->subtables[x].next = x + 1; - x = x + 1; - } - table->subtables[x].next = newxtop; /* x is bottom of its group, join */ - /* its symmetry to top of its group */ - /* Store group move */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) return(0); - move->x = swapx; - move->y = swapy; - move->size = size; - move->next = *moves; - *moves = move; - - return(size); - -} /* end of ddSymmGroupMove */ - - -/**Function******************************************************************** - - Synopsis [Undoes the swap of two groups.] - - Description [Undoes the swap of two groups. x is assumed to be the - bottom variable of the first group. y is assumed to be the top - variable of the second group. Returns the number of keys in the table - if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmGroupMoveBackward( - DdManager * table, - int x, - int y) -{ - int size; - int i,j; - int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - -#if DD_DEBUG - assert(x < y); /* We assume that x < y */ -#endif - - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtables[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtables[ybot].next) - ybot = table->subtables[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - - /* Sift the variables of the second group up through the first group. */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddSwapInPlace(table,x,y); - if (size == 0) return(0); - y = x; - x = cuddNextLow(table,y); - } - y = ytop + i; - x = y - 1; - } - - /* Fix symmetries. */ - y = xtop; - for (i = 0; i < ysize-1 ; i++) { - table->subtables[y].next = y + 1; - y = y + 1; - } - table->subtables[y].next = xtop; /* y is bottom of its group, join */ - /* its symmetry to top of its group */ - x = y + 1; - newxtop = x; - for (i = 0; i < xsize-1 ; i++) { - table->subtables[x].next = x + 1; - x = x + 1; - } - table->subtables[x].next = newxtop; /* x is bottom of its group, join */ - /* its symmetry to top of its group */ - - return(size); - -} /* end of ddSymmGroupMoveBackward */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the DD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the DD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmSiftingBackward( - DdManager * table, - Move * moves, - int size) -{ - Move *move; - int res; - - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) { - res = cuddSwapInPlace(table,(int)move->x,(int)move->y); -#ifdef DD_DEBUG - assert(table->subtables[move->x].next == move->x); - assert(table->subtables[move->y].next == move->y); -#endif - } else { /* Group move necessary */ - res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y); - } - if (!res) return(0); - } - - return(1); - -} /* end of ddSymmSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Counts numbers of symmetric variables and symmetry - groups.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -static void -ddSymmSummary( - DdManager * table, - int lower, - int upper, - int * symvars, - int * symgroups) -{ - int i,x,gbot; - int TotalSymm = 0; - int TotalSymmGroups = 0; - - for (i = lower; i <= upper; i++) { - if (table->subtables[i].next != (unsigned) i) { - TotalSymmGroups++; - x = i; - do { - TotalSymm++; - gbot = x; - x = table->subtables[x].next; - } while (x != i); -#ifdef DD_DEBUG - assert(table->subtables[gbot].next == (unsigned) i); -#endif - i = gbot; - } - } - *symvars = TotalSymm; - *symgroups = TotalSymmGroups; - - return; - -} /* end of ddSymmSummary */ diff --git a/src/bdd/cudd/cuddTable.c b/src/bdd/cudd/cuddTable.c deleted file mode 100644 index 7f14aed1..00000000 --- a/src/bdd/cudd/cuddTable.c +++ /dev/null @@ -1,3141 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddTable.c] - - PackageName [cudd] - - Synopsis [Unique table management functions.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_Prime() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddAllocNode() - <li> cuddInitTable() - <li> cuddFreeTable() - <li> cuddGarbageCollect() - <li> cuddGarbageCollectZdd() - <li> cuddZddGetNode() - <li> cuddZddGetNodeIVO() - <li> cuddUniqueInter() - <li> cuddUniqueInterIVO() - <li> cuddUniqueInterZdd() - <li> cuddUniqueConst() - <li> cuddRehash() - <li> cuddShrinkSubtable() - <li> cuddInsertSubtables() - <li> cuddDestroySubtables() - <li> cuddResizeTableZdd() - <li> cuddSlowTableGrowth() - </ul> - Static procedures included in this module: - <ul> - <li> ddRehashZdd() - <li> ddResizeTable() - <li> cuddFindParent() - <li> cuddOrderedInsert() - <li> cuddOrderedThread() - <li> cuddRotateLeft() - <li> cuddRotateRight() - <li> cuddDoRebalance() - <li> cuddCheckCollisionOrdering() - </ul>] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef DD_UNSORTED_FREE_LIST -/* Constants for red/black trees. */ -#define DD_STACK_SIZE 128 -#define DD_RED 0 -#define DD_BLACK 1 -#define DD_PAGE_SIZE 8192 -#define DD_PAGE_MASK ~(DD_PAGE_SIZE - 1) -#define DD_INSERT_COMPARE(x,y) \ - (((ptruint) (x) & DD_PAGE_MASK) - ((ptruint) (y) & DD_PAGE_MASK)) -#endif - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/* This is a hack for when CUDD_VALUE_TYPE is double */ -typedef union hack { - CUDD_VALUE_TYPE value; - unsigned int bits[2]; -} hack; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddTable.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -#ifndef DD_UNSORTED_FREE_LIST -/* Macros for red/black trees. */ -#define DD_COLOR(p) ((p)->index) -#define DD_IS_BLACK(p) ((p)->index == DD_BLACK) -#define DD_IS_RED(p) ((p)->index == DD_RED) -#define DD_LEFT(p) cuddT(p) -#define DD_RIGHT(p) cuddE(p) -#define DD_NEXT(p) ((p)->next) -#endif - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void ddRehashZdd ARGS((DdManager *unique, int i)); -static int ddResizeTable ARGS((DdManager *unique, int index)); -static int cuddFindParent ARGS((DdManager *table, DdNode *node)); -DD_INLINE static void ddFixLimits ARGS((DdManager *unique)); -static void cuddOrderedInsert ARGS((DdNodePtr *root, DdNodePtr node)); -static DdNode * cuddOrderedThread ARGS((DdNode *root, DdNode *list)); -static void cuddRotateLeft ARGS((DdNodePtr *nodeP)); -static void cuddRotateRight ARGS((DdNodePtr *nodeP)); -static void cuddDoRebalance ARGS((DdNodePtr **stack, int stackN)); -static void ddPatchTree ARGS((DdManager *dd, MtrNode *treenode)); -#ifdef DD_DEBUG -static int cuddCheckCollisionOrdering ARGS((DdManager *unique, int i, int j)); -#endif -static void ddReportRefMess ARGS((DdManager *unique, int i, char *caller)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -unsigned int -Cudd_Prime( - unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Fast storage allocation for DdNodes in the table.] - - Description [Fast storage allocation for DdNodes in the table. The - first 4 bytes of a chunk contain a pointer to the next block; the - rest contains DD_MEM_CHUNK spaces for DdNodes. Returns a pointer to - a new node if successful; NULL is memory is full.] - - SideEffects [None] - - SeeAlso [cuddDynamicAllocNode] - -******************************************************************************/ -DdNode * -cuddAllocNode( - DdManager * unique) -{ - int i; - DdNodePtr *mem; - DdNode *list, *node; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - if (unique->nextFree == NULL) { /* free list is empty */ - /* Check for exceeded limits. */ - if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) > - unique->maxLive) { - unique->errorCode = CUDD_TOO_MANY_NODES; - return(NULL); - } - if (unique->stash == NULL || unique->memused > unique->maxmemhard) { - (void) cuddGarbageCollect(unique,1); - mem = NULL; - } - if (unique->nextFree == NULL) { - if (unique->memused > unique->maxmemhard) { - unique->errorCode = CUDD_MAX_MEM_EXCEEDED; - return(NULL); - } - /* Try to allocate a new block. */ - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); - MMoutOfMemory = saveHandler; - if (mem == NULL) { - /* No more memory: Try collecting garbage. If this succeeds, - ** we end up with mem still NULL, but unique->nextFree != - ** NULL. */ - if (cuddGarbageCollect(unique,1) == 0) { - /* Last resort: Free the memory stashed away, if there - ** any. If this succeeeds, mem != NULL and - ** unique->nextFree still NULL. */ - if (unique->stash != NULL) { - FREE(unique->stash); - unique->stash = NULL; - /* Inhibit resizing of tables. */ - cuddSlowTableGrowth(unique); - /* Now try again. */ - mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); - } - if (mem == NULL) { - /* Out of luck. Call the default handler to do - ** whatever it specifies for a failed malloc. - ** If this handler returns, then set error code, - ** print warning, and return. */ - (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); - unique->errorCode = CUDD_MEMORY_OUT; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "cuddAllocNode: out of memory"); - (void) fprintf(unique->err, "Memory in use = %ld\n", - unique->memused); -#endif - return(NULL); - } - } - } - if (mem != NULL) { /* successful allocation; slice memory */ - ptruint offset; - unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); - mem[0] = (DdNodePtr) unique->memoryList; - unique->memoryList = mem; - - /* Here we rely on the fact that a DdNode is as large - ** as 4 pointers. */ - offset = (ptruint) mem & (sizeof(DdNode) - 1); - mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); - assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0); - list = (DdNode *) mem; - - i = 1; - do { - list[i - 1].next = &list[i]; - } while (++i < DD_MEM_CHUNK); - - list[DD_MEM_CHUNK-1].next = NULL; - - unique->nextFree = &list[0]; - } - } - } - unique->allocated++; - node = unique->nextFree; - unique->nextFree = node->next; - return(node); - -} /* end of cuddAllocNode */ - - -/**Function******************************************************************** - - Synopsis [Creates and initializes the unique table.] - - Description [Creates and initializes the unique table. Returns a pointer - to the table if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Init cuddFreeTable] - -******************************************************************************/ -DdManager * -cuddInitTable( - unsigned int numVars /* Initial number of BDD variables (and subtables) */, - unsigned int numVarsZ /* Initial number of ZDD variables (and subtables) */, - unsigned int numSlots /* Initial size of the BDD subtables */, - unsigned int looseUpTo /* Limit for fast table growth */) -{ - DdManager *unique = ALLOC(DdManager,1); - int i, j; - DdNodePtr *nodelist; - DdNode *sentinel; - unsigned int slots; - int shift; - - if (unique == NULL) { - return(NULL); - } - sentinel = &(unique->sentinel); - sentinel->ref = 0; - sentinel->index = 0; - cuddT(sentinel) = NULL; - cuddE(sentinel) = NULL; - sentinel->next = NULL; - unique->epsilon = DD_EPSILON; - unique->maxGrowth = DD_MAX_REORDER_GROWTH; - unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH; - unique->reordCycle = 0; /* do not use alternate threshold */ - unique->size = numVars; - unique->sizeZ = numVarsZ; - unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars); - unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ); - - /* Adjust the requested number of slots to a power of 2. */ - slots = 8; - while (slots < numSlots) { - slots <<= 1; - } - unique->initSlots = slots; - shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots); - - unique->slots = (numVars + numVarsZ + 1) * slots; - unique->keys = 0; - unique->maxLive = ~0; /* very large number */ - unique->keysZ = 0; - unique->dead = 0; - unique->deadZ = 0; - unique->gcFrac = DD_GC_FRAC_HI; - unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); - unique->looseUpTo = looseUpTo; - unique->gcEnabled = 1; - unique->allocated = 0; - unique->reclaimed = 0; - unique->subtables = ALLOC(DdSubtable,unique->maxSize); - if (unique->subtables == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ); - if (unique->subtableZ == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->perm = ALLOC(int,unique->maxSize); - if (unique->perm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->invperm = ALLOC(int,unique->maxSize); - if (unique->invperm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->permZ = ALLOC(int,unique->maxSizeZ); - if (unique->permZ == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->invpermZ = ALLOC(int,unique->maxSizeZ); - if (unique->invpermZ == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->map = NULL; - unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1); - if (unique->stack == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->stack[0] = NULL; /* to suppress harmless UMR */ - -#ifndef DD_NO_DEATH_ROW - unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2); - unique->deathRow = ALLOC(DdNodePtr,unique->deathRowDepth); - if (unique->deathRow == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < unique->deathRowDepth; i++) { - unique->deathRow[i] = NULL; - } - unique->nextDead = 0; - unique->deadMask = unique->deathRowDepth - 1; -#endif - - for (i = 0; (unsigned) i < numVars; i++) { - unique->subtables[i].slots = slots; - unique->subtables[i].shift = shift; - unique->subtables[i].keys = 0; - unique->subtables[i].dead = 0; - unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - unique->subtables[i].bindVar = 0; - unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; - unique->subtables[i].pairIndex = 0; - unique->subtables[i].varHandled = 0; - unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; - - nodelist = unique->subtables[i].nodelist = ALLOC(DdNodePtr,slots); - if (nodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = sentinel; - } - unique->perm[i] = i; - unique->invperm[i] = i; - } - for (i = 0; (unsigned) i < numVarsZ; i++) { - unique->subtableZ[i].slots = slots; - unique->subtableZ[i].shift = shift; - unique->subtableZ[i].keys = 0; - unique->subtableZ[i].dead = 0; - unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - nodelist = unique->subtableZ[i].nodelist = ALLOC(DdNodePtr,slots); - if (nodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - unique->permZ[i] = i; - unique->invpermZ[i] = i; - } - unique->constants.slots = slots; - unique->constants.shift = shift; - unique->constants.keys = 0; - unique->constants.dead = 0; - unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - nodelist = unique->constants.nodelist = ALLOC(DdNodePtr,slots); - if (nodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - - unique->memoryList = NULL; - unique->nextFree = NULL; - - unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ) - * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) * - slots * sizeof(DdNodePtr) + - (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr); -#ifndef DD_NO_DEATH_ROW - unique->memused += unique->deathRowDepth * sizeof(DdNodePtr); -#endif - - /* Initialize fields concerned with automatic dynamic reordering */ - unique->reorderings = 0; - unique->autoDyn = 0; /* initially disabled */ - unique->autoDynZ = 0; /* initially disabled */ - unique->realign = 0; /* initially disabled */ - unique->realignZ = 0; /* initially disabled */ - unique->reordered = 0; - unique->autoMethod = CUDD_REORDER_SIFT; - unique->autoMethodZ = CUDD_REORDER_SIFT; - unique->nextDyn = DD_FIRST_REORDER; - unique->countDead = ~0; - unique->siftMaxVar = DD_SIFT_MAX_VAR; - unique->siftMaxSwap = DD_SIFT_MAX_SWAPS; - unique->tree = NULL; - unique->treeZ = NULL; - unique->groupcheck = CUDD_GROUP_CHECK7; - unique->recomb = DD_DEFAULT_RECOMB; - unique->symmviolation = 0; - unique->arcviolation = 0; - unique->populationSize = 0; - unique->numberXovers = 0; - unique->linear = NULL; - unique->linearSize = 0; - - /* Initialize ZDD universe. */ - unique->univ = (DdNodePtr *)NULL; - - /* Initialize auxiliary fields. */ - unique->localCaches = NULL; - unique->preGCHook = NULL; - unique->postGCHook = NULL; - unique->preReorderingHook = NULL; - unique->postReorderingHook = NULL; - unique->out = stdout; - unique->err = stderr; - unique->errorCode = CUDD_NO_ERROR; - - /* Initialize statistical counters. */ - unique->maxmemhard = (long) ((~ (unsigned long) 0) >> 1); - unique->garbageCollections = 0; - unique->GCTime = 0; - unique->reordTime = 0; -#ifdef DD_STATS - unique->nodesDropped = 0; - unique->nodesFreed = 0; -#endif - unique->peakLiveNodes = 0; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLookUps = 0; - unique->uniqueLinks = 0; -#endif -#ifdef DD_COUNT - unique->recursiveCalls = 0; - unique->swapSteps = 0; -#ifdef DD_STATS - unique->nextSample = 250000; -#endif -#endif - - return(unique); - -} /* end of cuddInitTable */ - - -/**Function******************************************************************** - - Synopsis [Frees the resources associated to a unique table.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddInitTable] - -******************************************************************************/ -void -cuddFreeTable( - DdManager * unique) -{ - DdNodePtr *next; - DdNodePtr *memlist = unique->memoryList; - int i; - - if (unique->univ != NULL) cuddZddFreeUniv(unique); - while (memlist != NULL) { - next = (DdNodePtr *) memlist[0]; /* link to next block */ - FREE(memlist); - memlist = next; - } - unique->nextFree = NULL; - unique->memoryList = NULL; - - for (i = 0; i < unique->size; i++) { - FREE(unique->subtables[i].nodelist); - } - for (i = 0; i < unique->sizeZ; i++) { - FREE(unique->subtableZ[i].nodelist); - } - FREE(unique->constants.nodelist); - FREE(unique->subtables); - FREE(unique->subtableZ); - FREE(unique->acache); - FREE(unique->perm); - FREE(unique->permZ); - FREE(unique->invperm); - FREE(unique->invpermZ); - FREE(unique->vars); - if (unique->map != NULL) FREE(unique->map); - FREE(unique->stack); -#ifndef DD_NO_DEATH_ROW - FREE(unique->deathRow); -#endif - if (unique->tree != NULL) Mtr_FreeTree(unique->tree); - if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ); - if (unique->linear != NULL) FREE(unique->linear); - while (unique->preGCHook != NULL) - Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK); - while (unique->postGCHook != NULL) - Cudd_RemoveHook(unique,unique->postGCHook->f,CUDD_POST_GC_HOOK); - while (unique->preReorderingHook != NULL) - Cudd_RemoveHook(unique,unique->preReorderingHook->f, - CUDD_PRE_REORDERING_HOOK); - while (unique->postReorderingHook != NULL) - Cudd_RemoveHook(unique,unique->postReorderingHook->f, - CUDD_POST_REORDERING_HOOK); - FREE(unique); - -} /* end of cuddFreeTable */ - - -/**Function******************************************************************** - - Synopsis [Performs garbage collection on a unique table.] - - Description [Performs garbage collection on a unique table. - If clearCache is 0, the cache is not cleared. This should only be - specified if the cache has been cleared right before calling - cuddGarbageCollect. (As in the case of dynamic reordering.) - Returns the total number of deleted nodes.] - - SideEffects [None] - - SeeAlso [cuddGarbageCollectZdd] - -******************************************************************************/ -int -cuddGarbageCollect( - DdManager * unique, - int clearCache) -{ - DdHook *hook; - DdCache *cache = unique->cache; - DdNode *sentinel = &(unique->sentinel); - DdNodePtr *nodelist; - int i, j, deleted, totalDeleted; - DdCache *c; - DdNode *node,*next; - DdNodePtr *lastP; - int slots; - long localTime; -#ifndef DD_UNSORTED_FREE_LIST - DdNodePtr tree; -#endif - -#ifndef DD_NO_DEATH_ROW - cuddClearDeathRow(unique); -#endif - - hook = unique->preGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"BDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - - if (unique->dead == 0) { - hook = unique->postGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"BDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - return(0); - } - - /* If many nodes are being reclaimed, we want to resize the tables - ** more aggressively, to reduce the frequency of garbage collection. - */ - if (clearCache && unique->gcFrac == DD_GC_FRAC_LO && - unique->slots <= unique->looseUpTo && unique->stash != NULL) { - unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); -#ifdef DD_VERBOSE - (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); -#endif - unique->gcFrac = DD_GC_FRAC_HI; - return(0); - } - - localTime = util_cpu_time(); - - unique->garbageCollections++; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "garbage collecting (%d dead out of %d, min %d)...", - unique->dead, unique->keys, unique->minDead); -#endif - - /* Remove references to garbage collected nodes from the cache. */ - if (clearCache) { - slots = unique->cacheSlots; - for (i = 0; i < slots; i++) { - c = &cache[i]; - if (c->data != NULL) { - if (cuddClean(c->f)->ref == 0 || - cuddClean(c->g)->ref == 0 || - (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || - (c->data != DD_NON_CONSTANT && - Cudd_Regular(c->data)->ref == 0)) { - c->data = NULL; - unique->cachedeletions++; - } - } - } - cuddLocalCacheClearDead(unique); - } - - /* Now return dead nodes to free list. Count them for sanity check. */ - totalDeleted = 0; -#ifndef DD_UNSORTED_FREE_LIST - tree = NULL; -#endif - - for (i = 0; i < unique->size; i++) { - if (unique->subtables[i].dead == 0) continue; - nodelist = unique->subtables[i].nodelist; - - deleted = 0; - slots = unique->subtables[i].slots; - for (j = 0; j < slots; j++) { - lastP = &(nodelist[j]); - node = *lastP; - while (node != sentinel) { - next = node->next; - if (node->ref == 0) { - deleted++; -#ifndef DD_UNSORTED_FREE_LIST -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - cuddOrderedInsert(&tree,node); -#ifdef __osf__ -#pragma pointer_size restore -#endif -#else - cuddDeallocNode(unique,node); -#endif - } else { - *lastP = node; - lastP = &(node->next); - } - node = next; - } - *lastP = sentinel; - } - if ((unsigned) deleted != unique->subtables[i].dead) { - ddReportRefMess(unique, i, "cuddGarbageCollect"); - } - totalDeleted += deleted; - unique->subtables[i].keys -= deleted; - unique->subtables[i].dead = 0; - } - if (unique->constants.dead != 0) { - nodelist = unique->constants.nodelist; - deleted = 0; - slots = unique->constants.slots; - for (j = 0; j < slots; j++) { - lastP = &(nodelist[j]); - node = *lastP; - while (node != NULL) { - next = node->next; - if (node->ref == 0) { - deleted++; -#ifndef DD_UNSORTED_FREE_LIST -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - cuddOrderedInsert(&tree,node); -#ifdef __osf__ -#pragma pointer_size restore -#endif -#else - cuddDeallocNode(unique,node); -#endif - } else { - *lastP = node; - lastP = &(node->next); - } - node = next; - } - *lastP = NULL; - } - if ((unsigned) deleted != unique->constants.dead) { - ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect"); - } - totalDeleted += deleted; - unique->constants.keys -= deleted; - unique->constants.dead = 0; - } - if ((unsigned) totalDeleted != unique->dead) { - ddReportRefMess(unique, -1, "cuddGarbageCollect"); - } - unique->keys -= totalDeleted; - unique->dead = 0; -#ifdef DD_STATS - unique->nodesFreed += (double) totalDeleted; -#endif - -#ifndef DD_UNSORTED_FREE_LIST - unique->nextFree = cuddOrderedThread(tree,unique->nextFree); -#endif - - unique->GCTime += util_cpu_time() - localTime; - - hook = unique->postGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"BDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - -#ifdef DD_VERBOSE - (void) fprintf(unique->err," done\n"); -#endif - - return(totalDeleted); - -} /* end of cuddGarbageCollect */ - - -/**Function******************************************************************** - - Synopsis [Performs garbage collection on a ZDD unique table.] - - Description [Performs garbage collection on a ZDD unique table. - If clearCache is 0, the cache is not cleared. This should only be - specified if the cache has been cleared right before calling - cuddGarbageCollectZdd. (As in the case of dynamic reordering.) - Returns the total number of deleted nodes.] - - SideEffects [None] - - SeeAlso [cuddGarbageCollect] - -******************************************************************************/ -int -cuddGarbageCollectZdd( - DdManager * unique, - int clearCache) -{ - DdHook *hook; - DdCache *cache = unique->cache; - DdNodePtr *nodelist; - int i, j, deleted, totalDeleted; - DdCache *c; - DdNode *node,*next; - DdNodePtr *lastP; - int slots; - long localTime; -#ifndef DD_UNSORTED_FREE_LIST - DdNodePtr tree; -#endif - - hook = unique->preGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"ZDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - - if (unique->deadZ == 0) { - hook = unique->postGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"ZDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - return(0); - } - - /* If many nodes are being reclaimed, we want to resize the tables - ** more aggressively, to reduce the frequency of garbage collection. - */ - if (clearCache && unique->slots <= unique->looseUpTo) { - unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); -#ifdef DD_VERBOSE - if (unique->gcFrac == DD_GC_FRAC_LO) { - (void) fprintf(unique->err,"GC fraction = %.2f\t", - DD_GC_FRAC_HI); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); - } -#endif - unique->gcFrac = DD_GC_FRAC_HI; - } - - localTime = util_cpu_time(); - - unique->garbageCollections++; -#ifdef DD_VERBOSE - (void) fprintf(unique->err,"garbage collecting (%d dead out of %d)...", - unique->deadZ,unique->keysZ); -#endif - - /* Remove references to garbage collected nodes from the cache. */ - if (clearCache) { - slots = unique->cacheSlots; - for (i = 0; i < slots; i++) { - c = &cache[i]; - if (c->data != NULL) { - if (cuddClean(c->f)->ref == 0 || - cuddClean(c->g)->ref == 0 || - (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || - (c->data != DD_NON_CONSTANT && - Cudd_Regular(c->data)->ref == 0)) { - c->data = NULL; - unique->cachedeletions++; - } - } - } - } - - /* Now return dead nodes to free list. Count them for sanity check. */ - totalDeleted = 0; -#ifndef DD_UNSORTED_FREE_LIST - tree = NULL; -#endif - - for (i = 0; i < unique->sizeZ; i++) { - if (unique->subtableZ[i].dead == 0) continue; - nodelist = unique->subtableZ[i].nodelist; - - deleted = 0; - slots = unique->subtableZ[i].slots; - for (j = 0; j < slots; j++) { - lastP = &(nodelist[j]); - node = *lastP; - while (node != NULL) { - next = node->next; - if (node->ref == 0) { - deleted++; -#ifndef DD_UNSORTED_FREE_LIST -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - cuddOrderedInsert(&tree,node); -#ifdef __osf__ -#pragma pointer_size restore -#endif -#else - cuddDeallocNode(unique,node); -#endif - } else { - *lastP = node; - lastP = &(node->next); - } - node = next; - } - *lastP = NULL; - } - if ((unsigned) deleted != unique->subtableZ[i].dead) { - ddReportRefMess(unique, i, "cuddGarbageCollectZdd"); - } - totalDeleted += deleted; - unique->subtableZ[i].keys -= deleted; - unique->subtableZ[i].dead = 0; - } - - /* No need to examine the constant table for ZDDs. - ** If we did we should be careful not to count whatever dead - ** nodes we found there among the dead ZDD nodes. */ - if ((unsigned) totalDeleted != unique->deadZ) { - ddReportRefMess(unique, -1, "cuddGarbageCollectZdd"); - } - unique->keysZ -= totalDeleted; - unique->deadZ = 0; -#ifdef DD_STATS - unique->nodesFreed += (double) totalDeleted; -#endif - -#ifndef DD_UNSORTED_FREE_LIST - unique->nextFree = cuddOrderedThread(tree,unique->nextFree); -#endif - - unique->GCTime += util_cpu_time() - localTime; - - hook = unique->postGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"ZDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - -#ifdef DD_VERBOSE - (void) fprintf(unique->err," done\n"); -#endif - - return(totalDeleted); - -} /* end of cuddGarbageCollectZdd */ - - -/**Function******************************************************************** - - Synopsis [Wrapper for cuddUniqueInterZdd.] - - Description [Wrapper for cuddUniqueInterZdd, which applies the ZDD - reduction rule. Returns a pointer to the result node under normal - conditions; NULL if reordering occurred or memory was exhausted.] - - SideEffects [None] - - SeeAlso [cuddUniqueInterZdd] - -******************************************************************************/ -DdNode * -cuddZddGetNode( - DdManager * zdd, - int id, - DdNode * T, - DdNode * E) -{ - DdNode *node; - - if (T == DD_ZERO(zdd)) - return(E); - node = cuddUniqueInterZdd(zdd, id, T, E); - return(node); - -} /* end of cuddZddGetNode */ - - -/**Function******************************************************************** - - Synopsis [Wrapper for cuddUniqueInterZdd that is independent of variable - ordering.] - - Description [Wrapper for cuddUniqueInterZdd that is independent of - variable ordering (IVO). This function does not require parameter - index to precede the indices of the top nodes of g and h in the - variable order. Returns a pointer to the result node under normal - conditions; NULL if reordering occurred or memory was exhausted.] - - SideEffects [None] - - SeeAlso [cuddZddGetNode cuddZddIsop] - -******************************************************************************/ -DdNode * -cuddZddGetNodeIVO( - DdManager * dd, - int index, - DdNode * g, - DdNode * h) -{ - DdNode *f, *r, *t; - DdNode *zdd_one = DD_ONE(dd); - DdNode *zdd_zero = DD_ZERO(dd); - - f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero); - if (f == NULL) { - return(NULL); - } - cuddRef(f); - t = cuddZddProduct(dd, f, g); - if (t == NULL) { - Cudd_RecursiveDerefZdd(dd, f); - return(NULL); - } - cuddRef(t); - Cudd_RecursiveDerefZdd(dd, f); - r = cuddZddUnion(dd, t, h); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, t); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDerefZdd(dd, t); - - cuddDeref(r); - return(r); - -} /* end of cuddZddGetNodeIVO */ - - -/**Function******************************************************************** - - Synopsis [Checks the unique table for the existence of an internal node.] - - Description [Checks the unique table for the existence of an internal - node. If it does not exist, it creates a new one. Does not - modify the reference count of whatever is returned. A newly created - internal node comes back with a reference count 0. For a newly - created node, increments the reference counts of what T and E point - to. Returns a pointer to the new node if successful; NULL if memory - is exhausted or if reordering took place.] - - SideEffects [None] - - SeeAlso [cuddUniqueInterZdd] - -******************************************************************************/ -DdNode * -cuddUniqueInter( - DdManager * unique, - int index, - DdNode * T, - DdNode * E) -{ - int pos; - unsigned int level; - int retval; - DdNodePtr *nodelist; - DdNode *looking; - DdNodePtr *previousP; - DdSubtable *subtable; - int gcNumber; - -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLookUps++; -#endif - - if (index >= unique->size) { - if (!ddResizeTable(unique,index)) return(NULL); - } - - level = unique->perm[index]; - subtable = &(unique->subtables[level]); - -#ifdef DD_DEBUG - assert(level < (unsigned) cuddI(unique,T->index)); - assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); -#endif - - pos = ddHash(T, E, subtable->shift); - nodelist = subtable->nodelist; - previousP = &(nodelist[pos]); - looking = *previousP; - - while (T < cuddT(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - while (T == cuddT(looking) && E < cuddE(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - if (T == cuddT(looking) && E == cuddE(looking)) { - if (looking->ref == 0) { - cuddReclaim(unique,looking); - } - return(looking); - } - - /* countDead is 0 if deads should be counted and ~0 if they should not. */ - if (unique->autoDyn && - unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn) { -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(unique); - if (retval != 0) return(NULL); - retval = Cudd_CheckKeys(unique); - if (retval != 0) return(NULL); -#endif - retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */ - if (retval == 0) unique->reordered = 2; -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(unique); - if (retval != 0) unique->reordered = 2; - retval = Cudd_CheckKeys(unique); - if (retval != 0) unique->reordered = 2; -#endif - return(NULL); - } - - if (subtable->keys > subtable->maxKeys) { - if (unique->gcEnabled && - ((unique->dead > unique->minDead) || - ((unique->dead > unique->minDead / 2) && - (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */ - (void) cuddGarbageCollect(unique,1); - } else { - cuddRehash(unique,(int)level); - } - /* Update pointer to insertion point. In the case of rehashing, - ** the slot may have changed. In the case of garbage collection, - ** the predecessor may have been dead. */ - pos = ddHash(T, E, subtable->shift); - nodelist = subtable->nodelist; - previousP = &(nodelist[pos]); - looking = *previousP; - - while (T < cuddT(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - while (T == cuddT(looking) && E < cuddE(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - } - - gcNumber = unique->garbageCollections; - looking = cuddAllocNode(unique); - if (looking == NULL) { - return(NULL); - } - unique->keys++; - subtable->keys++; - - if (gcNumber != unique->garbageCollections) { - DdNode *looking2; - pos = ddHash(T, E, subtable->shift); - nodelist = subtable->nodelist; - previousP = &(nodelist[pos]); - looking2 = *previousP; - - while (T < cuddT(looking2)) { - previousP = &(looking2->next); - looking2 = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - while (T == cuddT(looking2) && E < cuddE(looking2)) { - previousP = &(looking2->next); - looking2 = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - } - looking->ref = 0; - looking->index = index; - cuddT(looking) = T; - cuddE(looking) = E; - looking->next = *previousP; - *previousP = looking; - cuddSatInc(T->ref); /* we know T is a regular pointer */ - cuddRef(E); - -#ifdef DD_DEBUG - cuddCheckCollisionOrdering(unique,level,pos); -#endif - - return(looking); - -} /* end of cuddUniqueInter */ - - -/**Function******************************************************************** - - Synopsis [Wrapper for cuddUniqueInter that is independent of variable - ordering.] - - Description [Wrapper for cuddUniqueInter that is independent of - variable ordering (IVO). This function does not require parameter - index to precede the indices of the top nodes of T and E in the - variable order. Returns a pointer to the result node under normal - conditions; NULL if reordering occurred or memory was exhausted.] - - SideEffects [None] - - SeeAlso [cuddUniqueInter Cudd_MakeBddFromZddCover] - -******************************************************************************/ -DdNode * -cuddUniqueInterIVO( - DdManager * unique, - int index, - DdNode * T, - DdNode * E) -{ - DdNode *result; - DdNode *v; - - v = cuddUniqueInter(unique, index, DD_ONE(unique), - Cudd_Not(DD_ONE(unique))); - if (v == NULL) - return(NULL); - cuddRef(v); - result = cuddBddIteRecur(unique, v, T, E); - Cudd_RecursiveDeref(unique, v); - return(result); -} - - -/**Function******************************************************************** - - Synopsis [Checks the unique table for the existence of an internal - ZDD node.] - - Description [Checks the unique table for the existence of an internal - ZDD node. If it does not exist, it creates a new one. Does not - modify the reference count of whatever is returned. A newly created - internal node comes back with a reference count 0. For a newly - created node, increments the reference counts of what T and E point - to. Returns a pointer to the new node if successful; NULL if memory - is exhausted or if reordering took place.] - - SideEffects [None] - - SeeAlso [cuddUniqueInter] - -******************************************************************************/ -DdNode * -cuddUniqueInterZdd( - DdManager * unique, - int index, - DdNode * T, - DdNode * E) -{ - int pos; - unsigned int level; - int retval; - DdNodePtr *nodelist; - DdNode *looking; - DdSubtable *subtable; - -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLookUps++; -#endif - - if (index >= unique->sizeZ) { - if (!cuddResizeTableZdd(unique,index)) return(NULL); - } - - level = unique->permZ[index]; - subtable = &(unique->subtableZ[level]); - -#ifdef DD_DEBUG - assert(level < (unsigned) cuddIZ(unique,T->index)); - assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index)); -#endif - - if (subtable->keys > subtable->maxKeys) { - if (unique->gcEnabled && ((unique->deadZ > unique->minDead) || - (10 * subtable->dead > 9 * subtable->keys))) { /* too many dead */ - (void) cuddGarbageCollectZdd(unique,1); - } else { - ddRehashZdd(unique,(int)level); - } - } - - pos = ddHash(T, E, subtable->shift); - nodelist = subtable->nodelist; - looking = nodelist[pos]; - - while (looking != NULL) { - if (cuddT(looking) == T && cuddE(looking) == E) { - if (looking->ref == 0) { - cuddReclaimZdd(unique,looking); - } - return(looking); - } - looking = looking->next; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - - /* countDead is 0 if deads should be counted and ~0 if they should not. */ - if (unique->autoDynZ && - unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) { -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(unique); - if (retval != 0) return(NULL); - retval = Cudd_CheckKeys(unique); - if (retval != 0) return(NULL); -#endif - retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */ - if (retval == 0) unique->reordered = 2; -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(unique); - if (retval != 0) unique->reordered = 2; - retval = Cudd_CheckKeys(unique); - if (retval != 0) unique->reordered = 2; -#endif - return(NULL); - } - - unique->keysZ++; - subtable->keys++; - - looking = cuddAllocNode(unique); - if (looking == NULL) return(NULL); - looking->ref = 0; - looking->index = index; - cuddT(looking) = T; - cuddE(looking) = E; - looking->next = nodelist[pos]; - nodelist[pos] = looking; - cuddRef(T); - cuddRef(E); - - return(looking); - -} /* end of cuddUniqueInterZdd */ - - -/**Function******************************************************************** - - Synopsis [Checks the unique table for the existence of a constant node.] - - Description [Checks the unique table for the existence of a constant node. - If it does not exist, it creates a new one. Does not - modify the reference count of whatever is returned. A newly created - internal node comes back with a reference count 0. Returns a - pointer to the new node.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -cuddUniqueConst( - DdManager * unique, - CUDD_VALUE_TYPE value) -{ - int pos; - DdNodePtr *nodelist; - DdNode *looking; - hack split; - -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLookUps++; -#endif - - if (unique->constants.keys > unique->constants.maxKeys) { - if (unique->gcEnabled && ((unique->dead > unique->minDead) || - (10 * unique->constants.dead > 9 * unique->constants.keys))) { /* too many dead */ - (void) cuddGarbageCollect(unique,1); - } else { - cuddRehash(unique,CUDD_CONST_INDEX); - } - } - - cuddAdjust(value); /* for the case of crippled infinities */ - - if (ddAbs(value) < unique->epsilon) { - value = 0.0; - } - split.value = value; - - pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift); - nodelist = unique->constants.nodelist; - looking = nodelist[pos]; - - /* Here we compare values both for equality and for difference less - * than epsilon. The first comparison is required when values are - * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for - * every X. - */ - while (looking != NULL) { - if (looking->type.value == value || - ddEqualVal(looking->type.value,value,unique->epsilon)) { - if (looking->ref == 0) { - cuddReclaim(unique,looking); - } - return(looking); - } - looking = looking->next; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - - unique->keys++; - unique->constants.keys++; - - looking = cuddAllocNode(unique); - if (looking == NULL) return(NULL); - looking->ref = 0; - looking->index = CUDD_CONST_INDEX; - looking->type.value = value; - looking->next = nodelist[pos]; - nodelist[pos] = looking; - - return(looking); - -} /* end of cuddUniqueConst */ - - -/**Function******************************************************************** - - Synopsis [Rehashes a unique subtable.] - - Description [Doubles the size of a unique subtable and rehashes its - contents.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddRehash( - DdManager * unique, - int i) -{ - unsigned int slots, oldslots; - int shift, oldshift; - int j, pos; - DdNodePtr *nodelist, *oldnodelist; - DdNode *node, *next; - DdNode *sentinel = &(unique->sentinel); - hack split; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) { - unique->gcFrac = DD_GC_FRAC_LO; - unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); -#ifdef DD_VERBOSE - (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); -#endif - } - - if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) { - unique->gcFrac = DD_GC_FRAC_MIN; - unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); -#ifdef DD_VERBOSE - (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); -#endif - cuddShrinkDeathRow(unique); - if (cuddGarbageCollect(unique,1) > 0) return; - } - - if (i != CUDD_CONST_INDEX) { - oldslots = unique->subtables[i].slots; - oldshift = unique->subtables[i].shift; - oldnodelist = unique->subtables[i].nodelist; - - /* Compute the new size of the subtable. */ - slots = oldslots << 1; - shift = oldshift - 1; - - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - (void) fprintf(unique->err, - "Unable to resize subtable %d for lack of memory\n", - i); - /* Prevent frequent resizing attempts. */ - (void) cuddGarbageCollect(unique,1); - if (unique->stash != NULL) { - FREE(unique->stash); - unique->stash = NULL; - /* Inhibit resizing of tables. */ - cuddSlowTableGrowth(unique); - } - return; - } - unique->subtables[i].nodelist = nodelist; - unique->subtables[i].slots = slots; - unique->subtables[i].shift = shift; - unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - - /* Move the nodes from the old table to the new table. - ** This code depends on the type of hash function. - ** It assumes that the effect of doubling the size of the table - ** is to retain one more bit of the 32-bit hash value. - ** The additional bit is the LSB. */ - for (j = 0; (unsigned) j < oldslots; j++) { - DdNodePtr *evenP, *oddP; - node = oldnodelist[j]; - evenP = &(nodelist[j<<1]); - oddP = &(nodelist[(j<<1)+1]); - while (node != sentinel) { - next = node->next; - pos = ddHash(cuddT(node), cuddE(node), shift); - if (pos & 1) { - *oddP = node; - oddP = &(node->next); - } else { - *evenP = node; - evenP = &(node->next); - } - node = next; - } - *evenP = *oddP = sentinel; - } - FREE(oldnodelist); - -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "rehashing layer %d: keys %d dead %d new size %d\n", - i, unique->subtables[i].keys, - unique->subtables[i].dead, slots); -#endif - } else { - oldslots = unique->constants.slots; - oldshift = unique->constants.shift; - oldnodelist = unique->constants.nodelist; - - /* The constant subtable is never subjected to reordering. - ** Therefore, when it is resized, it is because it has just - ** reached the maximum load. We can safely just double the size, - ** with no need for the loop we use for the other tables. - */ - slots = oldslots << 1; - shift = oldshift - 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - int j; - (void) fprintf(unique->err, - "Unable to resize constant subtable for lack of memory\n"); - (void) cuddGarbageCollect(unique,1); - for (j = 0; j < unique->size; j++) { - unique->subtables[j].maxKeys <<= 1; - } - unique->constants.maxKeys <<= 1; - return; - } - unique->constants.slots = slots; - unique->constants.shift = shift; - unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - unique->constants.nodelist = nodelist; - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - for (j = 0; (unsigned) j < oldslots; j++) { - node = oldnodelist[j]; - while (node != NULL) { - next = node->next; - split.value = cuddV(node); - pos = ddHash(split.bits[0], split.bits[1], shift); - node->next = nodelist[pos]; - nodelist[pos] = node; - node = next; - } - } - FREE(oldnodelist); - -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "rehashing constants: keys %d dead %d new size %d\n", - unique->constants.keys,unique->constants.dead,slots); -#endif - } - - /* Update global data */ - - unique->memused += (slots - oldslots) * sizeof(DdNodePtr); - unique->slots += (slots - oldslots); - ddFixLimits(unique); - -} /* end of cuddRehash */ - - -/**Function******************************************************************** - - Synopsis [Shrinks a subtable.] - - Description [Shrinks a subtable.] - - SideEffects [None] - - SeeAlso [cuddRehash] - -******************************************************************************/ -void -cuddShrinkSubtable( - DdManager *unique, - int i) -{ - int j; - int shift, posn; - DdNodePtr *nodelist, *oldnodelist; - DdNode *node, *next; - DdNode *sentinel = &(unique->sentinel); - unsigned int slots, oldslots; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - oldnodelist = unique->subtables[i].nodelist; - oldslots = unique->subtables[i].slots; - slots = oldslots >> 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - return; - } - unique->subtables[i].nodelist = nodelist; - unique->subtables[i].slots = slots; - unique->subtables[i].shift++; - unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "shrunk layer %d (%d keys) from %d to %d slots\n", - i, unique->subtables[i].keys, oldslots, slots); -#endif - - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = sentinel; - } - shift = unique->subtables[i].shift; - for (j = 0; (unsigned) j < oldslots; j++) { - node = oldnodelist[j]; - while (node != sentinel) { - DdNode *looking, *T, *E; - DdNodePtr *previousP; - next = node->next; - posn = ddHash(cuddT(node), cuddE(node), shift); - previousP = &(nodelist[posn]); - looking = *previousP; - T = cuddT(node); - E = cuddE(node); - while (T < cuddT(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - while (T == cuddT(looking) && E < cuddE(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - node->next = *previousP; - *previousP = node; - node = next; - } - } - FREE(oldnodelist); - - unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *); - unique->slots += slots - oldslots; - unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); - unique->cacheSlack = (int) - ddMin(unique->maxCacheHard,DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) - - 2 * (int) unique->cacheSlots; - -} /* end of cuddShrinkSubtable */ - - -/**Function******************************************************************** - - Synopsis [Inserts n new subtables in a unique table at level.] - - Description [Inserts n new subtables in a unique table at level. - The number n should be positive, and level should be an existing level. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddDestroySubtables] - -******************************************************************************/ -int -cuddInsertSubtables( - DdManager * unique, - int n, - int level) -{ - DdSubtable *newsubtables; - DdNodePtr *newnodelist; - DdNodePtr *newvars; - DdNode *sentinel = &(unique->sentinel); - int oldsize,newsize; - int i,j,index,reorderSave; - unsigned int numSlots = unique->initSlots; - int *newperm, *newinvperm, *newmap; - DdNode *one, *zero; - -#ifdef DD_DEBUG - assert(n > 0 && level < unique->size); -#endif - - oldsize = unique->size; - /* Easy case: there is still room in the current table. */ - if (oldsize + n <= unique->maxSize) { - /* Shift the tables at and below level. */ - for (i = oldsize - 1; i >= level; i--) { - unique->subtables[i+n].slots = unique->subtables[i].slots; - unique->subtables[i+n].shift = unique->subtables[i].shift; - unique->subtables[i+n].keys = unique->subtables[i].keys; - unique->subtables[i+n].maxKeys = unique->subtables[i].maxKeys; - unique->subtables[i+n].dead = unique->subtables[i].dead; - unique->subtables[i+n].nodelist = unique->subtables[i].nodelist; - unique->subtables[i+n].bindVar = unique->subtables[i].bindVar; - unique->subtables[i+n].varType = unique->subtables[i].varType; - unique->subtables[i+n].pairIndex = unique->subtables[i].pairIndex; - unique->subtables[i+n].varHandled = unique->subtables[i].varHandled; - unique->subtables[i+n].varToBeGrouped = - unique->subtables[i].varToBeGrouped; - - index = unique->invperm[i]; - unique->invperm[i+n] = index; - unique->perm[index] += n; - } - /* Create new subtables. */ - for (i = 0; i < n; i++) { - unique->subtables[level+i].slots = numSlots; - unique->subtables[level+i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - unique->subtables[level+i].keys = 0; - unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - unique->subtables[level+i].dead = 0; - unique->subtables[level+i].bindVar = 0; - unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT; - unique->subtables[level+i].pairIndex = 0; - unique->subtables[level+i].varHandled = 0; - unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE; - - unique->perm[oldsize+i] = level + i; - unique->invperm[level+i] = oldsize + i; - newnodelist = unique->subtables[level+i].nodelist = - ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = sentinel; - } - } - if (unique->map != NULL) { - for (i = 0; i < n; i++) { - unique->map[oldsize+i] = oldsize + i; - } - } - } else { - /* The current table is too small: we need to allocate a new, - ** larger one; move all old subtables, and initialize the new - ** subtables. - */ - newsize = oldsize + n + DD_DEFAULT_RESIZE; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "Increasing the table size from %d to %d\n", - unique->maxSize, newsize); -#endif - /* Allocate memory for new arrays (except nodelists). */ - newsubtables = ALLOC(DdSubtable,newsize); - if (newsubtables == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newvars = ALLOC(DdNodePtr,newsize); - if (newvars == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - FREE(newsubtables); - return(0); - } - newperm = ALLOC(int,newsize); - if (newperm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - FREE(newsubtables); - FREE(newvars); - return(0); - } - newinvperm = ALLOC(int,newsize); - if (newinvperm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - FREE(newsubtables); - FREE(newvars); - FREE(newperm); - return(0); - } - if (unique->map != NULL) { - newmap = ALLOC(int,newsize); - if (newmap == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - FREE(newsubtables); - FREE(newvars); - FREE(newperm); - FREE(newinvperm); - return(0); - } - unique->memused += (newsize - unique->maxSize) * sizeof(int); - } - unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * - sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); - /* Copy levels before insertion points from old tables. */ - for (i = 0; i < level; i++) { - newsubtables[i].slots = unique->subtables[i].slots; - newsubtables[i].shift = unique->subtables[i].shift; - newsubtables[i].keys = unique->subtables[i].keys; - newsubtables[i].maxKeys = unique->subtables[i].maxKeys; - newsubtables[i].dead = unique->subtables[i].dead; - newsubtables[i].nodelist = unique->subtables[i].nodelist; - newsubtables[i].bindVar = unique->subtables[i].bindVar; - newsubtables[i].varType = unique->subtables[i].varType; - newsubtables[i].pairIndex = unique->subtables[i].pairIndex; - newsubtables[i].varHandled = unique->subtables[i].varHandled; - newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; - - newvars[i] = unique->vars[i]; - newperm[i] = unique->perm[i]; - newinvperm[i] = unique->invperm[i]; - } - /* Finish initializing permutation for new table to old one. */ - for (i = level; i < oldsize; i++) { - newperm[i] = unique->perm[i]; - } - /* Initialize new levels. */ - for (i = level; i < level + n; i++) { - newsubtables[i].slots = numSlots; - newsubtables[i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - newsubtables[i].keys = 0; - newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - newsubtables[i].dead = 0; - newsubtables[i].bindVar = 0; - newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; - newsubtables[i].pairIndex = 0; - newsubtables[i].varHandled = 0; - newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; - - newperm[oldsize + i - level] = i; - newinvperm[i] = oldsize + i - level; - newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - /* We are going to leak some memory. We should clean up. */ - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = sentinel; - } - } - /* Copy the old tables for levels past the insertion point. */ - for (i = level; i < oldsize; i++) { - newsubtables[i+n].slots = unique->subtables[i].slots; - newsubtables[i+n].shift = unique->subtables[i].shift; - newsubtables[i+n].keys = unique->subtables[i].keys; - newsubtables[i+n].maxKeys = unique->subtables[i].maxKeys; - newsubtables[i+n].dead = unique->subtables[i].dead; - newsubtables[i+n].nodelist = unique->subtables[i].nodelist; - newsubtables[i+n].bindVar = unique->subtables[i].bindVar; - newsubtables[i+n].varType = unique->subtables[i].varType; - newsubtables[i+n].pairIndex = unique->subtables[i].pairIndex; - newsubtables[i+n].varHandled = unique->subtables[i].varHandled; - newsubtables[i+n].varToBeGrouped = - unique->subtables[i].varToBeGrouped; - - newvars[i] = unique->vars[i]; - index = unique->invperm[i]; - newinvperm[i+n] = index; - newperm[index] += n; - } - /* Update the map. */ - if (unique->map != NULL) { - for (i = 0; i < oldsize; i++) { - newmap[i] = unique->map[i]; - } - for (i = oldsize; i < oldsize + n; i++) { - newmap[i] = i; - } - FREE(unique->map); - unique->map = newmap; - } - /* Install the new tables and free the old ones. */ - FREE(unique->subtables); - unique->subtables = newsubtables; - unique->maxSize = newsize; - FREE(unique->vars); - unique->vars = newvars; - FREE(unique->perm); - unique->perm = newperm; - FREE(unique->invperm); - unique->invperm = newinvperm; - /* Update the stack for iterative procedures. */ - if (newsize > unique->maxSizeZ) { - FREE(unique->stack); - unique->stack = ALLOC(DdNodePtr,newsize + 1); - if (unique->stack == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->stack[0] = NULL; /* to suppress harmless UMR */ - unique->memused += - (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) - * sizeof(DdNode *); - } - } - /* Update manager parameters to account for the new subtables. */ - unique->slots += n * numSlots; - ddFixLimits(unique); - unique->size += n; - - /* Now that the table is in a coherent state, create the new - ** projection functions. We need to temporarily disable reordering, - ** because we cannot reorder without projection functions in place. - **/ - one = unique->one; - zero = Cudd_Not(one); - - reorderSave = unique->autoDyn; - unique->autoDyn = 0; - for (i = oldsize; i < oldsize + n; i++) { - unique->vars[i] = cuddUniqueInter(unique,i,one,zero); - if (unique->vars[i] == NULL) { - unique->autoDyn = reorderSave; - /* Shift everything back so table remains coherent. */ - for (j = oldsize; j < i; j++) { - Cudd_IterDerefBdd(unique,unique->vars[j]); - cuddDeallocNode(unique,unique->vars[j]); - unique->vars[j] = NULL; - } - for (j = level; j < oldsize; j++) { - unique->subtables[j].slots = unique->subtables[j+n].slots; - unique->subtables[j].slots = unique->subtables[j+n].slots; - unique->subtables[j].shift = unique->subtables[j+n].shift; - unique->subtables[j].keys = unique->subtables[j+n].keys; - unique->subtables[j].maxKeys = - unique->subtables[j+n].maxKeys; - unique->subtables[j].dead = unique->subtables[j+n].dead; - FREE(unique->subtables[j].nodelist); - unique->subtables[j].nodelist = - unique->subtables[j+n].nodelist; - unique->subtables[j+n].nodelist = NULL; - unique->subtables[j].bindVar = - unique->subtables[j+n].bindVar; - unique->subtables[j].varType = - unique->subtables[j+n].varType; - unique->subtables[j].pairIndex = - unique->subtables[j+n].pairIndex; - unique->subtables[j].varHandled = - unique->subtables[j+n].varHandled; - unique->subtables[j].varToBeGrouped = - unique->subtables[j+n].varToBeGrouped; - index = unique->invperm[j+n]; - unique->invperm[j] = index; - unique->perm[index] -= n; - } - unique->size = oldsize; - unique->slots -= n * numSlots; - ddFixLimits(unique); - (void) Cudd_DebugCheck(unique); - return(0); - } - cuddRef(unique->vars[i]); - } - if (unique->tree != NULL) { - unique->tree->size += n; - unique->tree->index = unique->invperm[0]; - ddPatchTree(unique,unique->tree); - } - unique->autoDyn = reorderSave; - - return(1); - -} /* end of cuddInsertSubtables */ - - -/**Function******************************************************************** - - Synopsis [Destroys the n most recently created subtables in a unique table.] - - Description [Destroys the n most recently created subtables in a unique - table. n should be positive. The subtables should not contain any live - nodes, except the (isolated) projection function. The projection - functions are freed. Returns 1 if successful; 0 otherwise.] - - SideEffects [The variable map used for fast variable substitution is - destroyed if it exists. In this case the cache is also cleared.] - - SeeAlso [cuddInsertSubtables Cudd_SetVarMap] - -******************************************************************************/ -int -cuddDestroySubtables( - DdManager * unique, - int n) -{ - DdSubtable *subtables; - DdNodePtr *nodelist; - DdNodePtr *vars; - int firstIndex, lastIndex; - int index, level, newlevel; - int lowestLevel; - int shift; - int found; - - /* Sanity check and set up. */ - if (n <= 0) return(0); - if (n > unique->size) n = unique->size; - - subtables = unique->subtables; - vars = unique->vars; - firstIndex = unique->size - n; - lastIndex = unique->size; - - /* Check for nodes labeled by the variables being destroyed - ** that may still be in use. It is allowed to destroy a variable - ** only if there are no such nodes. Also, find the lowest level - ** among the variables being destroyed. This will make further - ** processing more efficient. - */ - lowestLevel = unique->size; - for (index = firstIndex; index < lastIndex; index++) { - level = unique->perm[index]; - if (level < lowestLevel) lowestLevel = level; - nodelist = subtables[level].nodelist; - if (subtables[level].keys - subtables[level].dead != 1) return(0); - /* The projection function should be isolated. If the ref count - ** is 1, everything is OK. If the ref count is saturated, then - ** we need to make sure that there are no nodes pointing to it. - ** As for the external references, we assume the application is - ** responsible for them. - */ - if (vars[index]->ref != 1) { - if (vars[index]->ref != DD_MAXREF) return(0); - found = cuddFindParent(unique,vars[index]); - if (found) { - return(0); - } else { - vars[index]->ref = 1; - } - } - Cudd_RecursiveDeref(unique,vars[index]); - } - - /* Collect garbage, because we cannot afford having dead nodes pointing - ** to the dead nodes in the subtables being destroyed. - */ - (void) cuddGarbageCollect(unique,1); - - /* Here we know we can destroy our subtables. */ - for (index = firstIndex; index < lastIndex; index++) { - level = unique->perm[index]; - nodelist = subtables[level].nodelist; -#ifdef DD_DEBUG - assert(subtables[level].keys == 0); -#endif - FREE(nodelist); - unique->memused -= sizeof(DdNodePtr) * subtables[level].slots; - unique->slots -= subtables[level].slots; - unique->dead -= subtables[level].dead; - } - - /* Here all subtables to be destroyed have their keys field == 0 and - ** their hash tables have been freed. - ** We now scan the subtables from level lowestLevel + 1 to level size - 1, - ** shifting the subtables as required. We keep a running count of - ** how many subtables have been moved, so that we know by how many - ** positions each subtable should be shifted. - */ - shift = 1; - for (level = lowestLevel + 1; level < unique->size; level++) { - if (subtables[level].keys == 0) { - shift++; - continue; - } - newlevel = level - shift; - subtables[newlevel].slots = subtables[level].slots; - subtables[newlevel].shift = subtables[level].shift; - subtables[newlevel].keys = subtables[level].keys; - subtables[newlevel].maxKeys = subtables[level].maxKeys; - subtables[newlevel].dead = subtables[level].dead; - subtables[newlevel].nodelist = subtables[level].nodelist; - index = unique->invperm[level]; - unique->perm[index] = newlevel; - unique->invperm[newlevel] = index; - subtables[newlevel].bindVar = subtables[level].bindVar; - subtables[newlevel].varType = subtables[level].varType; - subtables[newlevel].pairIndex = subtables[level].pairIndex; - subtables[newlevel].varHandled = subtables[level].varHandled; - subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped; - } - /* Destroy the map. If a surviving variable is - ** mapped to a dying variable, and the map were used again, - ** an out-of-bounds access to unique->vars would result. */ - if (unique->map != NULL) { - cuddCacheFlush(unique); - FREE(unique->map); - unique->map = NULL; - } - - unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); - unique->size -= n; - - return(1); - -} /* end of cuddDestroySubtables */ - - -/**Function******************************************************************** - - Synopsis [Increases the number of ZDD subtables in a unique table so - that it meets or exceeds index.] - - Description [Increases the number of ZDD subtables in a unique table so - that it meets or exceeds index. When new ZDD variables are created, it - is possible to preserve the functions unchanged, or it is possible to - preserve the covers unchanged, but not both. cuddResizeTableZdd preserves - the covers. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [ddResizeTable] - -******************************************************************************/ -int -cuddResizeTableZdd( - DdManager * unique, - int index) -{ - DdSubtable *newsubtables; - DdNodePtr *newnodelist; - int oldsize,newsize; - int i,j,reorderSave; - unsigned int numSlots = unique->initSlots; - int *newperm, *newinvperm; - DdNode *one, *zero; - - oldsize = unique->sizeZ; - /* Easy case: there is still room in the current table. */ - if (index < unique->maxSizeZ) { - for (i = oldsize; i <= index; i++) { - unique->subtableZ[i].slots = numSlots; - unique->subtableZ[i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - unique->subtableZ[i].keys = 0; - unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - unique->subtableZ[i].dead = 0; - unique->permZ[i] = i; - unique->invpermZ[i] = i; - newnodelist = unique->subtableZ[i].nodelist = - ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = NULL; - } - } - } else { - /* The current table is too small: we need to allocate a new, - ** larger one; move all old subtables, and initialize the new - ** subtables up to index included. - */ - newsize = index + DD_DEFAULT_RESIZE; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "Increasing the ZDD table size from %d to %d\n", - unique->maxSizeZ, newsize); -#endif - newsubtables = ALLOC(DdSubtable,newsize); - if (newsubtables == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newperm = ALLOC(int,newsize); - if (newperm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newinvperm = ALLOC(int,newsize); - if (newinvperm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) * - sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); - if (newsize > unique->maxSize) { - FREE(unique->stack); - unique->stack = ALLOC(DdNodePtr,newsize + 1); - if (unique->stack == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->stack[0] = NULL; /* to suppress harmless UMR */ - unique->memused += - (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) - * sizeof(DdNode *); - } - for (i = 0; i < oldsize; i++) { - newsubtables[i].slots = unique->subtableZ[i].slots; - newsubtables[i].shift = unique->subtableZ[i].shift; - newsubtables[i].keys = unique->subtableZ[i].keys; - newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys; - newsubtables[i].dead = unique->subtableZ[i].dead; - newsubtables[i].nodelist = unique->subtableZ[i].nodelist; - newperm[i] = unique->permZ[i]; - newinvperm[i] = unique->invpermZ[i]; - } - for (i = oldsize; i <= index; i++) { - newsubtables[i].slots = numSlots; - newsubtables[i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - newsubtables[i].keys = 0; - newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - newsubtables[i].dead = 0; - newperm[i] = i; - newinvperm[i] = i; - newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = NULL; - } - } - FREE(unique->subtableZ); - unique->subtableZ = newsubtables; - unique->maxSizeZ = newsize; - FREE(unique->permZ); - unique->permZ = newperm; - FREE(unique->invpermZ); - unique->invpermZ = newinvperm; - } - unique->slots += (index + 1 - unique->sizeZ) * numSlots; - ddFixLimits(unique); - unique->sizeZ = index + 1; - - /* Now that the table is in a coherent state, update the ZDD - ** universe. We need to temporarily disable reordering, - ** because we cannot reorder without universe in place. - */ - one = unique->one; - zero = unique->zero; - - reorderSave = unique->autoDynZ; - unique->autoDynZ = 0; - cuddZddFreeUniv(unique); - if (!cuddZddInitUniv(unique)) { - unique->autoDynZ = reorderSave; - return(0); - } - unique->autoDynZ = reorderSave; - - return(1); - -} /* end of cuddResizeTableZdd */ - - -/**Function******************************************************************** - - Synopsis [Adjusts parameters of a table to slow down its growth.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddSlowTableGrowth( - DdManager *unique) -{ - int i; - - unique->maxCacheHard = unique->cacheSlots - 1; - unique->cacheSlack = -(unique->cacheSlots + 1); - for (i = 0; i < unique->size; i++) { - unique->subtables[i].maxKeys <<= 2; - } - unique->gcFrac = DD_GC_FRAC_MIN; - unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); - cuddShrinkDeathRow(unique); - (void) fprintf(unique->err,"Slowing down table growth: "); - (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); - -} /* end of cuddSlowTableGrowth */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Rehashes a ZDD unique subtable.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddRehash] - -******************************************************************************/ -static void -ddRehashZdd( - DdManager * unique, - int i) -{ - unsigned int slots, oldslots; - int shift, oldshift; - int j, pos; - DdNodePtr *nodelist, *oldnodelist; - DdNode *node, *next; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - if (unique->slots > unique->looseUpTo) { - unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); -#ifdef DD_VERBOSE - if (unique->gcFrac == DD_GC_FRAC_HI) { - (void) fprintf(unique->err,"GC fraction = %.2f\t", - DD_GC_FRAC_LO); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); - } -#endif - unique->gcFrac = DD_GC_FRAC_LO; - } - - assert(i != CUDD_MAXINDEX); - oldslots = unique->subtableZ[i].slots; - oldshift = unique->subtableZ[i].shift; - oldnodelist = unique->subtableZ[i].nodelist; - - /* Compute the new size of the subtable. Normally, we just - ** double. However, after reordering, a table may be severely - ** overloaded. Therefore, we iterate. */ - slots = oldslots; - shift = oldshift; - do { - slots <<= 1; - shift--; - } while (slots * DD_MAX_SUBTABLE_DENSITY < unique->subtableZ[i].keys); - - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - int j; - (void) fprintf(unique->err, - "Unable to resize ZDD subtable %d for lack of memory.\n", - i); - (void) cuddGarbageCollectZdd(unique,1); - for (j = 0; j < unique->sizeZ; j++) { - unique->subtableZ[j].maxKeys <<= 1; - } - return; - } - unique->subtableZ[i].nodelist = nodelist; - unique->subtableZ[i].slots = slots; - unique->subtableZ[i].shift = shift; - unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - for (j = 0; (unsigned) j < oldslots; j++) { - node = oldnodelist[j]; - while (node != NULL) { - next = node->next; - pos = ddHash(cuddT(node), cuddE(node), shift); - node->next = nodelist[pos]; - nodelist[pos] = node; - node = next; - } - } - FREE(oldnodelist); - -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "rehashing layer %d: keys %d dead %d new size %d\n", - i, unique->subtableZ[i].keys, - unique->subtableZ[i].dead, slots); -#endif - - /* Update global data. */ - unique->memused += (slots - oldslots) * sizeof(DdNode *); - unique->slots += (slots - oldslots); - ddFixLimits(unique); - -} /* end of ddRehashZdd */ - - -/**Function******************************************************************** - - Synopsis [Increases the number of subtables in a unique table so - that it meets or exceeds index.] - - Description [Increases the number of subtables in a unique table so - that it meets or exceeds index. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddResizeTableZdd] - -******************************************************************************/ -static int -ddResizeTable( - DdManager * unique, - int index) -{ - DdSubtable *newsubtables; - DdNodePtr *newnodelist; - DdNodePtr *newvars; - DdNode *sentinel = &(unique->sentinel); - int oldsize,newsize; - int i,j,reorderSave; - int numSlots = unique->initSlots; - int *newperm, *newinvperm, *newmap; - DdNode *one, *zero; - - oldsize = unique->size; - /* Easy case: there is still room in the current table. */ - if (index < unique->maxSize) { - for (i = oldsize; i <= index; i++) { - unique->subtables[i].slots = numSlots; - unique->subtables[i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - unique->subtables[i].keys = 0; - unique->subtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - unique->subtables[i].dead = 0; - unique->subtables[i].bindVar = 0; - unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; - unique->subtables[i].pairIndex = 0; - unique->subtables[i].varHandled = 0; - unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; - - unique->perm[i] = i; - unique->invperm[i] = i; - newnodelist = unique->subtables[i].nodelist = - ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - for (j = oldsize; j < i; j++) { - FREE(unique->subtables[j].nodelist); - } - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = sentinel; - } - } - if (unique->map != NULL) { - for (i = oldsize; i <= index; i++) { - unique->map[i] = i; - } - } - } else { - /* The current table is too small: we need to allocate a new, - ** larger one; move all old subtables, and initialize the new - ** subtables up to index included. - */ - newsize = index + DD_DEFAULT_RESIZE; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "Increasing the table size from %d to %d\n", - unique->maxSize, newsize); -#endif - newsubtables = ALLOC(DdSubtable,newsize); - if (newsubtables == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newvars = ALLOC(DdNodePtr,newsize); - if (newvars == NULL) { - FREE(newsubtables); - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newperm = ALLOC(int,newsize); - if (newperm == NULL) { - FREE(newsubtables); - FREE(newvars); - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newinvperm = ALLOC(int,newsize); - if (newinvperm == NULL) { - FREE(newsubtables); - FREE(newvars); - FREE(newperm); - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - if (unique->map != NULL) { - newmap = ALLOC(int,newsize); - if (newmap == NULL) { - FREE(newsubtables); - FREE(newvars); - FREE(newperm); - FREE(newinvperm); - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->memused += (newsize - unique->maxSize) * sizeof(int); - } - unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * - sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); - if (newsize > unique->maxSizeZ) { - FREE(unique->stack); - unique->stack = ALLOC(DdNodePtr,newsize + 1); - if (unique->stack == NULL) { - FREE(newsubtables); - FREE(newvars); - FREE(newperm); - FREE(newinvperm); - if (unique->map != NULL) { - FREE(newmap); - } - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->stack[0] = NULL; /* to suppress harmless UMR */ - unique->memused += - (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) - * sizeof(DdNode *); - } - for (i = 0; i < oldsize; i++) { - newsubtables[i].slots = unique->subtables[i].slots; - newsubtables[i].shift = unique->subtables[i].shift; - newsubtables[i].keys = unique->subtables[i].keys; - newsubtables[i].maxKeys = unique->subtables[i].maxKeys; - newsubtables[i].dead = unique->subtables[i].dead; - newsubtables[i].nodelist = unique->subtables[i].nodelist; - newsubtables[i].bindVar = unique->subtables[i].bindVar; - newsubtables[i].varType = unique->subtables[i].varType; - newsubtables[i].pairIndex = unique->subtables[i].pairIndex; - newsubtables[i].varHandled = unique->subtables[i].varHandled; - newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; - - newvars[i] = unique->vars[i]; - newperm[i] = unique->perm[i]; - newinvperm[i] = unique->invperm[i]; - } - for (i = oldsize; i <= index; i++) { - newsubtables[i].slots = numSlots; - newsubtables[i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - newsubtables[i].keys = 0; - newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - newsubtables[i].dead = 0; - newsubtables[i].bindVar = 0; - newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; - newsubtables[i].pairIndex = 0; - newsubtables[i].varHandled = 0; - newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; - - newperm[i] = i; - newinvperm[i] = i; - newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = sentinel; - } - } - if (unique->map != NULL) { - for (i = 0; i < oldsize; i++) { - newmap[i] = unique->map[i]; - } - for (i = oldsize; i <= index; i++) { - newmap[i] = i; - } - FREE(unique->map); - unique->map = newmap; - } - FREE(unique->subtables); - unique->subtables = newsubtables; - unique->maxSize = newsize; - FREE(unique->vars); - unique->vars = newvars; - FREE(unique->perm); - unique->perm = newperm; - FREE(unique->invperm); - unique->invperm = newinvperm; - } - - /* Now that the table is in a coherent state, create the new - ** projection functions. We need to temporarily disable reordering, - ** because we cannot reorder without projection functions in place. - **/ - one = unique->one; - zero = Cudd_Not(one); - - unique->size = index + 1; - unique->slots += (index + 1 - oldsize) * numSlots; - ddFixLimits(unique); - - reorderSave = unique->autoDyn; - unique->autoDyn = 0; - for (i = oldsize; i <= index; i++) { - unique->vars[i] = cuddUniqueInter(unique,i,one,zero); - if (unique->vars[i] == NULL) { - unique->autoDyn = reorderSave; - for (j = oldsize; j < i; j++) { - Cudd_IterDerefBdd(unique,unique->vars[j]); - cuddDeallocNode(unique,unique->vars[j]); - unique->vars[j] = NULL; - } - for (j = oldsize; j <= index; j++) { - FREE(unique->subtables[j].nodelist); - unique->subtables[j].nodelist = NULL; - } - unique->size = oldsize; - unique->slots -= (index + 1 - oldsize) * numSlots; - ddFixLimits(unique); - return(0); - } - cuddRef(unique->vars[i]); - } - unique->autoDyn = reorderSave; - - return(1); - -} /* end of ddResizeTable */ - - -/**Function******************************************************************** - - Synopsis [Searches the subtables above node for a parent.] - - Description [Searches the subtables above node for a parent. Returns 1 - as soon as one parent is found. Returns 0 is the search is fruitless.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddFindParent( - DdManager * table, - DdNode * node) -{ - int i,j; - int slots; - DdNodePtr *nodelist; - DdNode *f; - - for (i = cuddI(table,node->index) - 1; i >= 0; i--) { - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - - for (j = 0; j < slots; j++) { - f = nodelist[j]; - while (cuddT(f) > node) { - f = f->next; - } - while (cuddT(f) == node && Cudd_Regular(cuddE(f)) > node) { - f = f->next; - } - if (cuddT(f) == node && Cudd_Regular(cuddE(f)) == node) { - return(1); - } - } - } - - return(0); - -} /* end of cuddFindParent */ - - -/**Function******************************************************************** - - Synopsis [Adjusts the values of table limits.] - - Description [Adjusts the values of table fields controlling the. - sizes of subtables and computed table. If the computed table is too small - according to the new values, it is resized.] - - SideEffects [Modifies manager fields. May resize computed table.] - - SeeAlso [] - -******************************************************************************/ -DD_INLINE -static void -ddFixLimits( - DdManager *unique) -{ - unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); - unique->cacheSlack = (int) ddMin(unique->maxCacheHard, - DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) - - 2 * (int) unique->cacheSlots; - if (unique->cacheSlots < unique->slots/2 && unique->cacheSlack >= 0) - cuddCacheResize(unique); - return; - -} /* end of ddFixLimits */ - - -#ifndef DD_UNSORTED_FREE_LIST -/**Function******************************************************************** - - Synopsis [Inserts a DdNode in a red/black search tree.] - - Description [Inserts a DdNode in a red/black search tree. Nodes from - the same "page" (defined by DD_PAGE_MASK) are linked in a LIFO list.] - - SideEffects [None] - - SeeAlso [cuddOrderedThread] - -******************************************************************************/ -static void -cuddOrderedInsert( - DdNodePtr * root, - DdNodePtr node) -{ - DdNode *scan; - DdNodePtr *scanP; - DdNodePtr *stack[DD_STACK_SIZE]; - int stackN = 0; - - scanP = root; - while ((scan = *scanP) != NULL) { - stack[stackN++] = scanP; - if (DD_INSERT_COMPARE(node, scan) == 0) { /* add to page list */ - DD_NEXT(node) = DD_NEXT(scan); - DD_NEXT(scan) = node; - return; - } - scanP = (node < scan) ? &DD_LEFT(scan) : &DD_RIGHT(scan); - } - DD_RIGHT(node) = DD_LEFT(node) = DD_NEXT(node) = NULL; - DD_COLOR(node) = DD_RED; - *scanP = node; - stack[stackN] = &node; - cuddDoRebalance(stack,stackN); - -} /* end of cuddOrderedInsert */ - - -/**Function******************************************************************** - - Synopsis [Threads all the nodes of a search tree into a linear list.] - - Description [Threads all the nodes of a search tree into a linear - list. For each node of the search tree, the "left" child, if non-null, has - a lower address than its parent, and the "right" child, if non-null, has a - higher address than its parent. - The list is sorted in order of increasing addresses. The search - tree is destroyed as a result of this operation. The last element of - the linear list is made to point to the address passed in list. Each - node if the search tree is a linearly-linked list of nodes from the - same memory page (as defined in DD_PAGE_MASK). When a node is added to - the linear list, all the elements of the linked list are added.] - - SideEffects [The search tree is destroyed as a result of this operation.] - - SeeAlso [cuddOrderedInsert] - -******************************************************************************/ -static DdNode * -cuddOrderedThread( - DdNode * root, - DdNode * list) -{ - DdNode *current, *next, *prev, *end; - - current = root; - /* The first word in the node is used to implement a stack that holds - ** the nodes from the root of the tree to the current node. Here we - ** put the root of the tree at the bottom of the stack. - */ - *((DdNodePtr *) current) = NULL; - - while (current != NULL) { - if (DD_RIGHT(current) != NULL) { - /* If possible, we follow the "right" link. Eventually we'll - ** find the node with the largest address in the current tree. - ** In this phase we use the first word of a node to implemen - ** a stack of the nodes on the path from the root to "current". - ** Also, we disconnect the "right" pointers to indicate that - ** we have already followed them. - */ - next = DD_RIGHT(current); - DD_RIGHT(current) = NULL; - *((DdNodePtr *)next) = current; - current = next; - } else { - /* We can't proceed along the "right" links any further. - ** Hence "current" is the largest element in the current tree. - ** We make this node the new head of "list". (Repeating this - ** operation until the tree is empty yields the desired linear - ** threading of all nodes.) - */ - prev = *((DdNodePtr *) current); /* save prev node on stack in prev */ - /* Traverse the linked list of current until the end. */ - for (end = current; DD_NEXT(end) != NULL; end = DD_NEXT(end)); - DD_NEXT(end) = list; /* attach "list" at end and make */ - list = current; /* "current" the new head of "list" */ - /* Now, if current has a "left" child, we push it on the stack. - ** Otherwise, we just continue with the parent of "current". - */ - if (DD_LEFT(current) != NULL) { - next = DD_LEFT(current); - *((DdNodePtr *) next) = prev; - current = next; - } else { - current = prev; - } - } - } - - return(list); - -} /* end of cuddOrderedThread */ - - -/**Function******************************************************************** - - Synopsis [Performs the left rotation for red/black trees.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddRotateRight] - -******************************************************************************/ -DD_INLINE -static void -cuddRotateLeft( - DdNodePtr * nodeP) -{ - DdNode *newRoot; - DdNode *oldRoot = *nodeP; - - *nodeP = newRoot = DD_RIGHT(oldRoot); - DD_RIGHT(oldRoot) = DD_LEFT(newRoot); - DD_LEFT(newRoot) = oldRoot; - -} /* end of cuddRotateLeft */ - - -/**Function******************************************************************** - - Synopsis [Performs the right rotation for red/black trees.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddRotateLeft] - -******************************************************************************/ -DD_INLINE -static void -cuddRotateRight( - DdNodePtr * nodeP) -{ - DdNode *newRoot; - DdNode *oldRoot = *nodeP; - - *nodeP = newRoot = DD_LEFT(oldRoot); - DD_LEFT(oldRoot) = DD_RIGHT(newRoot); - DD_RIGHT(newRoot) = oldRoot; - -} /* end of cuddRotateRight */ - - -/**Function******************************************************************** - - Synopsis [Rebalances a red/black tree.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -cuddDoRebalance( - DdNodePtr ** stack, - int stackN) -{ - DdNodePtr *xP, *parentP, *grandpaP; - DdNode *x, *y, *parent, *grandpa; - - xP = stack[stackN]; - x = *xP; - /* Work our way back up, re-balancing the tree. */ - while (--stackN >= 0) { - parentP = stack[stackN]; - parent = *parentP; - if (DD_IS_BLACK(parent)) break; - /* Since the root is black, here a non-null grandparent exists. */ - grandpaP = stack[stackN-1]; - grandpa = *grandpaP; - if (parent == DD_LEFT(grandpa)) { - y = DD_RIGHT(grandpa); - if (y != NULL && DD_IS_RED(y)) { - DD_COLOR(parent) = DD_BLACK; - DD_COLOR(y) = DD_BLACK; - DD_COLOR(grandpa) = DD_RED; - x = grandpa; - stackN--; - } else { - if (x == DD_RIGHT(parent)) { - cuddRotateLeft(parentP); - DD_COLOR(x) = DD_BLACK; - } else { - DD_COLOR(parent) = DD_BLACK; - } - DD_COLOR(grandpa) = DD_RED; - cuddRotateRight(grandpaP); - break; - } - } else { - y = DD_LEFT(grandpa); - if (y != NULL && DD_IS_RED(y)) { - DD_COLOR(parent) = DD_BLACK; - DD_COLOR(y) = DD_BLACK; - DD_COLOR(grandpa) = DD_RED; - x = grandpa; - stackN--; - } else { - if (x == DD_LEFT(parent)) { - cuddRotateRight(parentP); - DD_COLOR(x) = DD_BLACK; - } else { - DD_COLOR(parent) = DD_BLACK; - } - DD_COLOR(grandpa) = DD_RED; - cuddRotateLeft(grandpaP); - } - } - } - DD_COLOR(*(stack[0])) = DD_BLACK; - -} /* end of cuddDoRebalance */ -#endif - - -/**Function******************************************************************** - - Synopsis [Fixes a variable tree after the insertion of new subtables.] - - Description [Fixes a variable tree after the insertion of new subtables. - After such an insertion, the low fields of the tree below the insertion - point are inconsistent.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -ddPatchTree( - DdManager *dd, - MtrNode *treenode) -{ - MtrNode *auxnode = treenode; - - while (auxnode != NULL) { - auxnode->low = dd->perm[auxnode->index]; - if (auxnode->child != NULL) { - ddPatchTree(dd, auxnode->child); - } - auxnode = auxnode->younger; - } - - return; - -} /* end of ddPatchTree */ - - -#ifdef DD_DEBUG -/**Function******************************************************************** - - Synopsis [Checks whether a collision list is ordered.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddCheckCollisionOrdering( - DdManager *unique, - int i, - int j) -{ - int slots; - DdNode *node, *next; - DdNodePtr *nodelist; - DdNode *sentinel = &(unique->sentinel); - - nodelist = unique->subtables[i].nodelist; - slots = unique->subtables[i].slots; - node = nodelist[j]; - if (node == sentinel) return(1); - next = node->next; - while (next != sentinel) { - if (cuddT(node) < cuddT(next) || - (cuddT(node) == cuddT(next) && cuddE(node) < cuddE(next))) { - (void) fprintf(unique->err, - "Unordered list: index %u, position %d\n", i, j); - return(0); - } - node = next; - next = node->next; - } - return(1); - -} /* end of cuddCheckCollisionOrdering */ -#endif - - - - -/**Function******************************************************************** - - Synopsis [Reports problem in garbage collection.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddGarbageCollect cuddGarbageCollectZdd] - -******************************************************************************/ -static void -ddReportRefMess( - DdManager *unique /* manager */, - int i /* table in which the problem occurred */, - char *caller /* procedure that detected the problem */) -{ - if (i == CUDD_CONST_INDEX) { - (void) fprintf(unique->err, - "%s: problem in constants\n", caller); - } else if (i != -1) { - (void) fprintf(unique->err, - "%s: problem in table %d\n", caller, i); - } - (void) fprintf(unique->err, " dead count != deleted\n"); - (void) fprintf(unique->err, " This problem is often due to a missing \ -call to Cudd_Ref\n or to an extra call to Cudd_RecursiveDeref.\n \ -See the CUDD Programmer's Guide for additional details."); - abort(); - -} /* end of ddReportRefMess */ diff --git a/src/bdd/cudd/cuddUtil.c b/src/bdd/cudd/cuddUtil.c deleted file mode 100644 index d5fa18e2..00000000 --- a/src/bdd/cudd/cuddUtil.c +++ /dev/null @@ -1,3633 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddUtil.c] - - PackageName [cudd] - - Synopsis [Utility functions.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_PrintMinterm() - <li> Cudd_PrintDebug() - <li> Cudd_DagSize() - <li> Cudd_EstimateCofactor() - <li> Cudd_EstimateCofactorSimple() - <li> Cudd_SharingSize() - <li> Cudd_CountMinterm() - <li> Cudd_EpdCountMinterm() - <li> Cudd_CountPath() - <li> Cudd_CountPathsToNonZero() - <li> Cudd_Support() - <li> Cudd_SupportIndex() - <li> Cudd_SupportSize() - <li> Cudd_VectorSupport() - <li> Cudd_VectorSupportIndex() - <li> Cudd_VectorSupportSize() - <li> Cudd_ClassifySupport() - <li> Cudd_CountLeaves() - <li> Cudd_bddPickOneCube() - <li> Cudd_bddPickOneMinterm() - <li> Cudd_bddPickArbitraryMinterms() - <li> Cudd_SubsetWithMaskVars() - <li> Cudd_FirstCube() - <li> Cudd_NextCube() - <li> Cudd_bddComputeCube() - <li> Cudd_addComputeCube() - <li> Cudd_FirstNode() - <li> Cudd_NextNode() - <li> Cudd_GenFree() - <li> Cudd_IsGenEmpty() - <li> Cudd_IndicesToCube() - <li> Cudd_PrintVersion() - <li> Cudd_AverageDistance() - <li> Cudd_Random() - <li> Cudd_Srandom() - <li> Cudd_Density() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddP() - <li> cuddStCountfree() - <li> cuddCollectNodes() - </ul> - Static procedures included in this module: - <ul> - <li> dp2() - <li> ddPrintMintermAux() - <li> ddDagInt() - <li> ddCountMintermAux() - <li> ddEpdCountMintermAux() - <li> ddCountPathAux() - <li> ddSupportStep() - <li> ddClearFlag() - <li> ddLeavesInt() - <li> ddPickArbitraryMinterms() - <li> ddPickRepresentativeCube() - <li> ddEpdFree() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/* Random generator constants. */ -#define MODULUS1 2147483563 -#define LEQA1 40014 -#define LEQQ1 53668 -#define LEQR1 12211 -#define MODULUS2 2147483399 -#define LEQA2 40692 -#define LEQQ2 52774 -#define LEQR2 3791 -#define STAB_SIZE 64 -#define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE) - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddUtil.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static DdNode *background, *zero; - -static long cuddRand = 0; -static long cuddRand2; -static long shuffleSelect; -static long shuffleTable[STAB_SIZE]; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -#define bang(f) ((Cudd_IsComplement(f)) ? '!' : ' ') - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int dp2 ARGS((DdManager *dd, DdNode *f, st_table *t)); -static void ddPrintMintermAux ARGS((DdManager *dd, DdNode *node, int *list)); -static int ddDagInt ARGS((DdNode *n)); -static int cuddEstimateCofactor ARGS((DdManager *dd, st_table *table, DdNode * node, int i, int phase, DdNode ** ptr)); -static DdNode * cuddUniqueLookup ARGS((DdManager * unique, int index, DdNode * T, DdNode * E)); -static int cuddEstimateCofactorSimple ARGS((DdNode * node, int i)); -static double ddCountMintermAux ARGS((DdNode *node, double max, DdHashTable *table)); -static int ddEpdCountMintermAux ARGS((DdNode *node, EpDouble *max, EpDouble *epd, st_table *table)); -static double ddCountPathAux ARGS((DdNode *node, st_table *table)); -static double ddCountPathsToNonZero ARGS((DdNode * N, st_table * table)); -static void ddSupportStep ARGS((DdNode *f, int *support)); -static void ddClearFlag ARGS((DdNode *f)); -static int ddLeavesInt ARGS((DdNode *n)); -static int ddPickArbitraryMinterms ARGS((DdManager *dd, DdNode *node, int nvars, int nminterms, char **string)); -static int ddPickRepresentativeCube ARGS((DdManager *dd, DdNode *node, int nvars, double *weight, char *string)); -static enum st_retval ddEpdFree ARGS((char * key, char * value, char * arg)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints a disjoint sum of products.] - - Description [Prints a disjoint sum of product cover for the function - rooted at node. Each product corresponds to a path from node to a - leaf node different from the logical zero, and different from the - background value. Uses the package default output file. Returns 1 - if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintDebug Cudd_bddPrintCover] - -******************************************************************************/ -int -Cudd_PrintMinterm( - DdManager * manager, - DdNode * node) -{ - int i, *list; - - background = manager->background; - zero = Cudd_Not(manager->one); - list = ALLOC(int,manager->size); - if (list == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < manager->size; i++) list[i] = 2; - ddPrintMintermAux(manager,node,list); - FREE(list); - return(1); - -} /* end of Cudd_PrintMinterm */ - - -/**Function******************************************************************** - - Synopsis [Prints a sum of prime implicants of a BDD.] - - Description [Prints a sum of product cover for an incompletely - specified function given by a lower bound and an upper bound. Each - product is a prime implicant obtained by expanding the product - corresponding to a path from node to the constant one. Uses the - package default output file. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintMinterm] - -******************************************************************************/ -int -Cudd_bddPrintCover( - DdManager *dd, - DdNode *l, - DdNode *u) -{ - int *array; - int q, result; - DdNode *lb; -#ifdef DD_DEBUG - DdNode *cover; -#endif - - array = ALLOC(int, Cudd_ReadSize(dd)); - if (array == NULL) return(0); - lb = l; - cuddRef(lb); -#ifdef DD_DEBUG - cover = Cudd_ReadLogicZero(dd); - cuddRef(cover); -#endif - while (lb != Cudd_ReadLogicZero(dd)) { - DdNode *implicant, *prime, *tmp; - int length; - implicant = Cudd_LargestCube(dd,lb,&length); - if (implicant == NULL) { - Cudd_RecursiveDeref(dd,lb); - FREE(array); - return(0); - } - cuddRef(implicant); - prime = Cudd_bddMakePrime(dd,implicant,u); - if (prime == NULL) { - Cudd_RecursiveDeref(dd,lb); - Cudd_RecursiveDeref(dd,implicant); - FREE(array); - return(0); - } - cuddRef(prime); - Cudd_RecursiveDeref(dd,implicant); - tmp = Cudd_bddAnd(dd,lb,Cudd_Not(prime)); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,lb); - Cudd_RecursiveDeref(dd,prime); - FREE(array); - return(0); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,lb); - lb = tmp; - result = Cudd_BddToCubeArray(dd,prime,array); - if (result == 0) { - Cudd_RecursiveDeref(dd,lb); - Cudd_RecursiveDeref(dd,prime); - FREE(array); - return(0); - } - for (q = 0; q < dd->size; q++) { - switch (array[q]) { - case 0: - (void) fprintf(dd->out, "0"); - break; - case 1: - (void) fprintf(dd->out, "1"); - break; - case 2: - (void) fprintf(dd->out, "-"); - break; - default: - (void) fprintf(dd->out, "?"); - } - } - (void) fprintf(dd->out, " 1\n"); -#ifdef DD_DEBUG - tmp = Cudd_bddOr(dd,prime,cover); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,cover); - Cudd_RecursiveDeref(dd,lb); - Cudd_RecursiveDeref(dd,prime); - FREE(array); - return(0); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,cover); - cover = tmp; -#endif - Cudd_RecursiveDeref(dd,prime); - } - (void) fprintf(dd->out, "\n"); - Cudd_RecursiveDeref(dd,lb); - FREE(array); -#ifdef DD_DEBUG - if (!Cudd_bddLeq(dd,cover,u) || !Cudd_bddLeq(dd,l,cover)) { - Cudd_RecursiveDeref(dd,cover); - return(0); - } - Cudd_RecursiveDeref(dd,cover); -#endif - return(1); - -} /* end of Cudd_bddPrintCover */ - - -/**Function******************************************************************** - - Synopsis [Prints to the standard output a DD and its statistics.] - - Description [Prints to the standard output a DD and its statistics. - The statistics include the number of nodes, the number of leaves, and - the number of minterms. (The number of minterms is the number of - assignments to the variables that cause the function to be different - from the logical zero (for BDDs) and from the background value (for - ADDs.) 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 product - <li> pr = 3 : prints counts + list of nodes - <li> pr > 3 : prints counts + disjoint sum of product + list of nodes - </ul> - For the purpose of counting the number of minterms, the function is - supposed to depend on n variables. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_DagSize Cudd_CountLeaves Cudd_CountMinterm - Cudd_PrintMinterm] - -******************************************************************************/ -int -Cudd_PrintDebug( - DdManager * dd, - DdNode * f, - int n, - int pr) -{ - DdNode *azero, *bzero; - int nodes; - int leaves; - double minterms; - int retval = 1; - - if (f == NULL) { - (void) fprintf(dd->out,": is the NULL DD\n"); - (void) fflush(dd->out); - return(0); - } - azero = DD_ZERO(dd); - bzero = Cudd_Not(DD_ONE(dd)); - if ((f == azero || f == bzero) && pr > 0){ - (void) fprintf(dd->out,": is the zero DD\n"); - (void) fflush(dd->out); - return(1); - } - if (pr > 0) { - nodes = Cudd_DagSize(f); - if (nodes == CUDD_OUT_OF_MEM) retval = 0; - leaves = Cudd_CountLeaves(f); - if (leaves == CUDD_OUT_OF_MEM) retval = 0; - minterms = Cudd_CountMinterm(dd, f, n); - if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0; - (void) fprintf(dd->out,": %d nodes %d leaves %g minterms\n", - nodes, leaves, minterms); - if (pr > 2) { - if (!cuddP(dd, f)) retval = 0; - } - if (pr == 2 || pr > 3) { - if (!Cudd_PrintMinterm(dd,f)) retval = 0; - (void) fprintf(dd->out,"\n"); - } - (void) fflush(dd->out); - } - return(retval); - -} /* end of Cudd_PrintDebug */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of nodes in a DD.] - - Description [Counts the number of nodes in a DD. Returns the number - of nodes in the graph rooted at node.] - - SideEffects [None] - - SeeAlso [Cudd_SharingSize Cudd_PrintDebug] - -******************************************************************************/ -int -Cudd_DagSize( - DdNode * node) -{ - int i; - - i = ddDagInt(Cudd_Regular(node)); - ddClearFlag(Cudd_Regular(node)); - - return(i); - -} /* end of Cudd_DagSize */ - - -/**Function******************************************************************** - - Synopsis [Estimates the number of nodes in a cofactor of a DD.] - - Description [Estimates the number of nodes in a cofactor of a DD. - Returns an estimate of the number of nodes in a cofactor of - the graph rooted at node with respect to the variable whose index is i. - In case of failure, returns CUDD_OUT_OF_MEM. - This function uses a refinement of the algorithm of Cabodi et al. - (ICCAD96). The refinement allows the procedure to account for part - of the recombination that may occur in the part of the cofactor above - the cofactoring variable. This procedure does no create any new node. - It does keep a small table of results; therefore itmay run out of memory. - If this is a concern, one should use Cudd_EstimateCofactorSimple, which - is faster, does not allocate any memory, but is less accurate.] - - SideEffects [None] - - SeeAlso [Cudd_DagSize Cudd_EstimateCofactorSimple] - -******************************************************************************/ -int -Cudd_EstimateCofactor( - DdManager *dd /* manager */, - DdNode * f /* function */, - int i /* index of variable */, - int phase /* 1: positive; 0: negative */ - ) -{ - int val; - DdNode *ptr; - st_table *table; - - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) return(CUDD_OUT_OF_MEM); - val = cuddEstimateCofactor(dd,table,Cudd_Regular(f),i,phase,&ptr); - ddClearFlag(Cudd_Regular(f)); - st_free_table(table); - - return(val); - -} /* end of Cudd_EstimateCofactor */ - - -/**Function******************************************************************** - - Synopsis [Estimates the number of nodes in a cofactor of a DD.] - - Description [Estimates the number of nodes in a cofactor of a DD. - Returns an estimate of the number of nodes in the positive cofactor of - the graph rooted at node with respect to the variable whose index is i. - This procedure implements with minor changes the algorithm of Cabodi et al. - (ICCAD96). It does not allocate any memory, it does not change the - state of the manager, and it is fast. However, it has been observed to - overestimate the size of the cofactor by as much as a factor of 2.] - - SideEffects [None] - - SeeAlso [Cudd_DagSize] - -******************************************************************************/ -int -Cudd_EstimateCofactorSimple( - DdNode * node, - int i) -{ - int val; - - val = cuddEstimateCofactorSimple(Cudd_Regular(node),i); - ddClearFlag(Cudd_Regular(node)); - - return(val); - -} /* end of Cudd_EstimateCofactorSimple */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of nodes in an array of DDs.] - - Description [Counts the number of nodes in an array of DDs. Shared - nodes are counted only once. Returns the total number of nodes.] - - SideEffects [None] - - SeeAlso [Cudd_DagSize] - -******************************************************************************/ -int -Cudd_SharingSize( - DdNode ** nodeArray, - int n) -{ - int i,j; - - i = 0; - for (j = 0; j < n; j++) { - i += ddDagInt(Cudd_Regular(nodeArray[j])); - } - for (j = 0; j < n; j++) { - ddClearFlag(Cudd_Regular(nodeArray[j])); - } - return(i); - -} /* end of Cudd_SharingSize */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms of a DD.] - - Description [Counts the number of minterms of a DD. The function is - assumed to depend on nvars variables. The minterm count is - represented as a double, to allow for a larger number of variables. - Returns the number of minterms of the function rooted at node if - successful; (double) CUDD_OUT_OF_MEM otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintDebug Cudd_CountPath] - -******************************************************************************/ -double -Cudd_CountMinterm( - DdManager * manager, - DdNode * node, - int nvars) -{ - double max; - DdHashTable *table; - double res; - CUDD_VALUE_TYPE epsilon; - - background = manager->background; - zero = Cudd_Not(manager->one); - - max = pow(2.0,(double)nvars); - table = cuddHashTableInit(manager,1,2); - if (table == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - epsilon = Cudd_ReadEpsilon(manager); - Cudd_SetEpsilon(manager,(CUDD_VALUE_TYPE)0.0); - res = ddCountMintermAux(node,max,table); - cuddHashTableQuit(table); - Cudd_SetEpsilon(manager,epsilon); - - return(res); - -} /* end of Cudd_CountMinterm */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of paths of a DD.] - - Description [Counts the number of paths of a DD. Paths to all - terminal nodes are counted. The path count is represented as a - double, to allow for a larger number of variables. Returns the - number of paths of the function rooted at node if successful; - (double) CUDD_OUT_OF_MEM otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_CountMinterm] - -******************************************************************************/ -double -Cudd_CountPath( - DdNode * node) -{ - - st_table *table; - double i; - - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - i = ddCountPathAux(Cudd_Regular(node),table); - st_foreach(table, cuddStCountfree, NULL); - st_free_table(table); - return(i); - -} /* end of Cudd_CountPath */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms of a DD with extended precision.] - - Description [Counts the number of minterms of a DD with extended precision. - The function is assumed to depend on nvars variables. The minterm count is - represented as an EpDouble, to allow any number of variables. - Returns 0 if successful; CUDD_OUT_OF_MEM otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintDebug Cudd_CountPath] - -******************************************************************************/ -int -Cudd_EpdCountMinterm( - DdManager * manager, - DdNode * node, - int nvars, - EpDouble * epd) -{ - EpDouble max, tmp; - st_table *table; - int status; - - background = manager->background; - zero = Cudd_Not(manager->one); - - EpdPow2(nvars, &max); - table = st_init_table(EpdCmp, st_ptrhash); - if (table == NULL) { - EpdMakeZero(epd, 0); - return(CUDD_OUT_OF_MEM); - } - status = ddEpdCountMintermAux(Cudd_Regular(node),&max,epd,table); - st_foreach(table, ddEpdFree, NULL); - st_free_table(table); - if (status == CUDD_OUT_OF_MEM) { - EpdMakeZero(epd, 0); - return(CUDD_OUT_OF_MEM); - } - if (Cudd_IsComplement(node)) { - EpdSubtract3(&max, epd, &tmp); - EpdCopy(&tmp, epd); - } - return(0); - -} /* end of Cudd_EpdCountMinterm */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of paths to a non-zero terminal of a DD.] - - Description [Counts the number of paths to a non-zero terminal of a - DD. The path count is - represented as a double, to allow for a larger number of variables. - Returns the number of paths of the function rooted at node.] - - SideEffects [None] - - SeeAlso [Cudd_CountMinterm Cudd_CountPath] - -******************************************************************************/ -double -Cudd_CountPathsToNonZero( - DdNode * node) -{ - - st_table *table; - double i; - - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - i = ddCountPathsToNonZero(node,table); - st_foreach(table, cuddStCountfree, NULL); - st_free_table(table); - return(i); - -} /* end of Cudd_CountPathsToNonZero */ - - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a DD depends.] - - Description [Finds the variables on which a DD depends. - Returns a BDD consisting of the product of the variables if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_VectorSupport Cudd_ClassifySupport] - -******************************************************************************/ -DdNode * -Cudd_Support( - DdManager * dd /* manager */, - DdNode * f /* DD 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. */ - ddSupportStep(Cudd_Regular(f),support); - ddClearFlag(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) { - 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_Support */ - - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a DD depends.] - - Description [Finds the variables on which a DD depends. - Returns an index array of the variables if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport] - -******************************************************************************/ -int * -Cudd_SupportIndex( - DdManager * dd /* manager */, - DdNode * f /* DD whose support is sought */) -{ - int *support; - int i; - 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. */ - ddSupportStep(Cudd_Regular(f),support); - ddClearFlag(Cudd_Regular(f)); - - return(support); - -} /* end of Cudd_SupportIndex */ - - -/**Function******************************************************************** - - Synopsis [Counts the variables on which a DD depends.] - - Description [Counts the variables on which a DD depends. - Returns the number of the variables if successful; CUDD_OUT_OF_MEM - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Support] - -******************************************************************************/ -int -Cudd_SupportSize( - DdManager * dd /* manager */, - DdNode * f /* DD whose support size is sought */) -{ - int *support; - int i; - int size; - int count; - - /* 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(CUDD_OUT_OF_MEM); - } - for (i = 0; i < size; i++) { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - ddSupportStep(Cudd_Regular(f),support); - ddClearFlag(Cudd_Regular(f)); - - /* Count support variables. */ - count = 0; - for (i = 0; i < size; i++) { - if (support[i] == 1) count++; - } - - FREE(support); - return(count); - -} /* end of Cudd_SupportSize */ - - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a set of DDs depends.] - - Description [Finds the variables on which a set of DDs depends. - The set must contain either BDDs and ADDs, or ZDDs. - Returns a BDD consisting of the product of the variables if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Support Cudd_ClassifySupport] - -******************************************************************************/ -DdNode * -Cudd_VectorSupport( - DdManager * dd /* manager */, - DdNode ** F /* array of DDs whose support is sought */, - int n /* size of the array */) -{ - 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. */ - for (i = 0; i < n; i++) { - ddSupportStep(Cudd_Regular(F[i]),support); - } - for (i = 0; i < n; i++) { - ddClearFlag(Cudd_Regular(F[i])); - } - - /* Transform support from array to cube. */ - 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) { - var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); - cuddRef(var); - tmp = Cudd_bddAnd(dd,res,var); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,res); - Cudd_RecursiveDeref(dd,var); - FREE(support); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,res); - Cudd_RecursiveDeref(dd,var); - res = tmp; - } - } - - FREE(support); - cuddDeref(res); - return(res); - -} /* end of Cudd_VectorSupport */ - - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a set of DDs depends.] - - Description [Finds the variables on which a set of DDs depends. - The set must contain either BDDs and ADDs, or ZDDs. - Returns an index array of the variables if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_SupportIndex Cudd_VectorSupport Cudd_ClassifySupport] - -******************************************************************************/ -int * -Cudd_VectorSupportIndex( - DdManager * dd /* manager */, - DdNode ** F /* array of DDs whose support is sought */, - int n /* size of the array */) -{ - int *support; - int i; - 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. */ - for (i = 0; i < n; i++) { - ddSupportStep(Cudd_Regular(F[i]),support); - } - for (i = 0; i < n; i++) { - ddClearFlag(Cudd_Regular(F[i])); - } - - return(support); - -} /* end of Cudd_VectorSupportIndex */ - - -/**Function******************************************************************** - - Synopsis [Counts the variables on which a set of DDs depends.] - - Description [Counts the variables on which a set of DDs depends. - The set must contain either BDDs and ADDs, or ZDDs. - Returns the number of the variables if successful; CUDD_OUT_OF_MEM - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_VectorSupport Cudd_SupportSize] - -******************************************************************************/ -int -Cudd_VectorSupportSize( - DdManager * dd /* manager */, - DdNode ** F /* array of DDs whose support is sought */, - int n /* size of the array */) -{ - int *support; - int i; - int size; - int count; - - /* 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(CUDD_OUT_OF_MEM); - } - for (i = 0; i < size; i++) { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - for (i = 0; i < n; i++) { - ddSupportStep(Cudd_Regular(F[i]),support); - } - for (i = 0; i < n; i++) { - ddClearFlag(Cudd_Regular(F[i])); - } - - /* Count vriables in support. */ - count = 0; - for (i = 0; i < size; i++) { - if (support[i] == 1) count++; - } - - FREE(support); - return(count); - -} /* end of Cudd_VectorSupportSize */ - - -/**Function******************************************************************** - - Synopsis [Classifies the variables in the support of two DDs.] - - Description [Classifies the variables in the support of two DDs - <code>f</code> and <code>g</code>, depending on whther they appear - in both DDs, only in <code>f</code>, or only in <code>g</code>. - Returns 1 if successful; 0 otherwise.] - - SideEffects [The cubes of the three classes of variables are - returned as side effects.] - - SeeAlso [Cudd_Support Cudd_VectorSupport] - -******************************************************************************/ -int -Cudd_ClassifySupport( - DdManager * dd /* manager */, - DdNode * f /* first DD */, - DdNode * g /* second DD */, - DdNode ** common /* cube of shared variables */, - DdNode ** onlyF /* cube of variables only in f */, - DdNode ** onlyG /* cube of variables only in g */) -{ - int *supportF, *supportG; - DdNode *tmp, *var; - int i,j; - int size; - - /* Allocate and initialize support arrays for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - supportF = ALLOC(int,size); - if (supportF == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - supportG = ALLOC(int,size); - if (supportG == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(supportF); - return(0); - } - for (i = 0; i < size; i++) { - supportF[i] = 0; - supportG[i] = 0; - } - - /* Compute supports and clean up markers. */ - ddSupportStep(Cudd_Regular(f),supportF); - ddClearFlag(Cudd_Regular(f)); - ddSupportStep(Cudd_Regular(g),supportG); - ddClearFlag(Cudd_Regular(g)); - - /* Classify variables and create cubes. */ - *common = *onlyF = *onlyG = DD_ONE(dd); - cuddRef(*common); cuddRef(*onlyF); cuddRef(*onlyG); - for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */ - i = (j >= dd->size) ? j : dd->invperm[j]; - if (supportF[i] == 0 && supportG[i] == 0) continue; - var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); - cuddRef(var); - if (supportG[i] == 0) { - tmp = Cudd_bddAnd(dd,*onlyF,var); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,*common); - Cudd_RecursiveDeref(dd,*onlyF); - Cudd_RecursiveDeref(dd,*onlyG); - Cudd_RecursiveDeref(dd,var); - FREE(supportF); FREE(supportG); - return(0); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,*onlyF); - *onlyF = tmp; - } else if (supportF[i] == 0) { - tmp = Cudd_bddAnd(dd,*onlyG,var); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,*common); - Cudd_RecursiveDeref(dd,*onlyF); - Cudd_RecursiveDeref(dd,*onlyG); - Cudd_RecursiveDeref(dd,var); - FREE(supportF); FREE(supportG); - return(0); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,*onlyG); - *onlyG = tmp; - } else { - tmp = Cudd_bddAnd(dd,*common,var); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,*common); - Cudd_RecursiveDeref(dd,*onlyF); - Cudd_RecursiveDeref(dd,*onlyG); - Cudd_RecursiveDeref(dd,var); - FREE(supportF); FREE(supportG); - return(0); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,*common); - *common = tmp; - } - Cudd_RecursiveDeref(dd,var); - } - - FREE(supportF); FREE(supportG); - cuddDeref(*common); cuddDeref(*onlyF); cuddDeref(*onlyG); - return(1); - -} /* end of Cudd_ClassifySupport */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of leaves in a DD.] - - Description [Counts the number of leaves in a DD. Returns the number - of leaves in the DD rooted at node if successful; CUDD_OUT_OF_MEM - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintDebug] - -******************************************************************************/ -int -Cudd_CountLeaves( - DdNode * node) -{ - int i; - - i = ddLeavesInt(Cudd_Regular(node)); - ddClearFlag(Cudd_Regular(node)); - return(i); - -} /* end of Cudd_CountLeaves */ - - -/**Function******************************************************************** - - Synopsis [Picks one on-set cube randomly from the given DD.] - - Description [Picks one on-set cube randomly from the given DD. The - cube is written into an array of characters. The array must have at - least as many entries as there are variables. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPickOneMinterm] - -******************************************************************************/ -int -Cudd_bddPickOneCube( - DdManager * ddm, - DdNode * node, - char * string) -{ - DdNode *N, *T, *E; - DdNode *one, *bzero; - char dir; - int i; - - if (string == NULL || node == NULL) return(0); - - /* The constant 0 function has no on-set cubes. */ - one = DD_ONE(ddm); - bzero = Cudd_Not(one); - if (node == bzero) return(0); - - for (i = 0; i < ddm->size; i++) string[i] = 2; - - for (;;) { - - if (node == one) break; - - N = Cudd_Regular(node); - - T = cuddT(N); E = cuddE(N); - if (Cudd_IsComplement(node)) { - T = Cudd_Not(T); E = Cudd_Not(E); - } - if (T == bzero) { - string[N->index] = 0; - node = E; - } else if (E == bzero) { - string[N->index] = 1; - node = T; - } else { - dir = (char) ((Cudd_Random() & 0x2000) >> 13); - string[N->index] = dir; - node = dir ? T : E; - } - } - return(1); - -} /* end of Cudd_bddPickOneCube */ - - -/**Function******************************************************************** - - Synopsis [Picks one on-set minterm randomly from the given DD.] - - Description [Picks one on-set minterm randomly from the given - DD. The minterm is in terms of <code>vars</code>. The array - <code>vars</code> should contain at least all variables in the - support of <code>f</code>; if this condition is not met the minterm - built by this procedure may not be contained in - <code>f</code>. Builds a BDD for the minterm and returns a pointer - to it if successful; NULL otherwise. There are three reasons why the - procedure may fail: - <ul> - <li> It may run out of memory; - <li> the function <code>f</code> may be the constant 0; - <li> the minterm may not be contained in <code>f</code>. - </ul>] - - SideEffects [None] - - SeeAlso [Cudd_bddPickOneCube] - -******************************************************************************/ -DdNode * -Cudd_bddPickOneMinterm( - DdManager * dd /* manager */, - DdNode * f /* function from which to pick one minterm */, - DdNode ** vars /* array of variables */, - int n /* size of <code>vars</code> */) -{ - char *string; - int i, size; - int *indices; - int result; - DdNode *old, *neW; - - size = dd->size; - string = ALLOC(char, size); - if (string == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - indices = ALLOC(int,n); - if (indices == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(string); - return(NULL); - } - - for (i = 0; i < n; i++) { - indices[i] = vars[i]->index; - } - - result = Cudd_bddPickOneCube(dd,f,string); - if (result == 0) { - FREE(string); - FREE(indices); - return(NULL); - } - - /* Randomize choice for don't cares. */ - for (i = 0; i < n; i++) { - if (string[indices[i]] == 2) - string[indices[i]] = (char) ((Cudd_Random() & 0x20) >> 5); - } - - /* Build result BDD. */ - old = Cudd_ReadOne(dd); - cuddRef(old); - - for (i = n-1; i >= 0; i--) { - neW = Cudd_bddAnd(dd,old,Cudd_NotCond(vars[i],string[indices[i]]==0)); - if (neW == NULL) { - FREE(string); - FREE(indices); - Cudd_RecursiveDeref(dd,old); - return(NULL); - } - cuddRef(neW); - Cudd_RecursiveDeref(dd,old); - old = neW; - } - -#ifdef DD_DEBUG - /* Test. */ - if (Cudd_bddLeq(dd,old,f)) { - cuddDeref(old); - } else { - Cudd_RecursiveDeref(dd,old); - old = NULL; - } -#else - cuddDeref(old); -#endif - - FREE(string); - FREE(indices); - return(old); - -} /* end of Cudd_bddPickOneMinterm */ - - -/**Function******************************************************************** - - Synopsis [Picks k on-set minterms evenly distributed from given DD.] - - Description [Picks k on-set minterms evenly distributed from given DD. - The minterms are in terms of <code>vars</code>. The array - <code>vars</code> should contain at least all variables in the - support of <code>f</code>; if this condition is not met the minterms - built by this procedure may not be contained in - <code>f</code>. Builds an array of BDDs for the minterms and returns a - pointer to it if successful; NULL otherwise. There are three reasons - why the procedure may fail: - <ul> - <li> It may run out of memory; - <li> the function <code>f</code> may be the constant 0; - <li> the minterms may not be contained in <code>f</code>. - </ul>] - - SideEffects [None] - - SeeAlso [Cudd_bddPickOneMinterm Cudd_bddPickOneCube] - -******************************************************************************/ -DdNode ** -Cudd_bddPickArbitraryMinterms( - DdManager * dd /* manager */, - DdNode * f /* function from which to pick k minterms */, - DdNode ** vars /* array of variables */, - int n /* size of <code>vars</code> */, - int k /* number of minterms to find */) -{ - char **string; - int i, j, l, size; - int *indices; - int result; - DdNode **old, *neW; - double minterms; - char *saveString; - int saveFlag, savePoint, isSame; - - minterms = Cudd_CountMinterm(dd,f,n); - if ((double)k > minterms) { - return(NULL); - } - - size = dd->size; - string = ALLOC(char *, k); - if (string == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < k; i++) { - string[i] = ALLOC(char, size + 1); - if (string[i] == NULL) { - for (j = 0; j < i; j++) - FREE(string[i]); - FREE(string); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (j = 0; j < size; j++) string[i][j] = '2'; - string[i][size] = '\0'; - } - indices = ALLOC(int,n); - if (indices == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - for (i = 0; i < k; i++) - FREE(string[i]); - FREE(string); - return(NULL); - } - - for (i = 0; i < n; i++) { - indices[i] = vars[i]->index; - } - - result = ddPickArbitraryMinterms(dd,f,n,k,string); - if (result == 0) { - for (i = 0; i < k; i++) - FREE(string[i]); - FREE(string); - FREE(indices); - return(NULL); - } - - old = ALLOC(DdNode *, k); - if (old == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - for (i = 0; i < k; i++) - FREE(string[i]); - FREE(string); - FREE(indices); - return(NULL); - } - saveString = ALLOC(char, size + 1); - if (saveString == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - for (i = 0; i < k; i++) - FREE(string[i]); - FREE(string); - FREE(indices); - FREE(old); - return(NULL); - } - saveFlag = 0; - - /* Build result BDD array. */ - for (i = 0; i < k; i++) { - isSame = 0; - if (!saveFlag) { - for (j = i + 1; j < k; j++) { - if (strcmp(string[i], string[j]) == 0) { - savePoint = i; - strcpy(saveString, string[i]); - saveFlag = 1; - break; - } - } - } else { - if (strcmp(string[i], saveString) == 0) { - isSame = 1; - } else { - saveFlag = 0; - for (j = i + 1; j < k; j++) { - if (strcmp(string[i], string[j]) == 0) { - savePoint = i; - strcpy(saveString, string[i]); - saveFlag = 1; - break; - } - } - } - } - /* Randomize choice for don't cares. */ - for (j = 0; j < n; j++) { - if (string[i][indices[j]] == '2') - string[i][indices[j]] = (Cudd_Random() & 0x20) ? '1' : '0'; - } - - while (isSame) { - isSame = 0; - for (j = savePoint; j < i; j++) { - if (strcmp(string[i], string[j]) == 0) { - isSame = 1; - break; - } - } - if (isSame) { - strcpy(string[i], saveString); - /* Randomize choice for don't cares. */ - for (j = 0; j < n; j++) { - if (string[i][indices[j]] == '2') - string[i][indices[j]] = (Cudd_Random() & 0x20) ? - '1' : '0'; - } - } - } - - old[i] = Cudd_ReadOne(dd); - cuddRef(old[i]); - - for (j = 0; j < n; j++) { - if (string[i][indices[j]] == '0') { - neW = Cudd_bddAnd(dd,old[i],Cudd_Not(vars[j])); - } else { - neW = Cudd_bddAnd(dd,old[i],vars[j]); - } - if (neW == NULL) { - FREE(saveString); - for (l = 0; l < k; l++) - FREE(string[l]); - FREE(string); - FREE(indices); - for (l = 0; l <= i; l++) - Cudd_RecursiveDeref(dd,old[l]); - FREE(old); - return(NULL); - } - cuddRef(neW); - Cudd_RecursiveDeref(dd,old[i]); - old[i] = neW; - } - - /* Test. */ - if (!Cudd_bddLeq(dd,old[i],f)) { - FREE(saveString); - for (l = 0; l < k; l++) - FREE(string[l]); - FREE(string); - FREE(indices); - for (l = 0; l <= i; l++) - Cudd_RecursiveDeref(dd,old[l]); - FREE(old); - return(NULL); - } - } - - FREE(saveString); - for (i = 0; i < k; i++) { - cuddDeref(old[i]); - FREE(string[i]); - } - FREE(string); - FREE(indices); - return(old); - -} /* end of Cudd_bddPickArbitraryMinterms */ - - -/**Function******************************************************************** - - Synopsis [Extracts a subset from a BDD.] - - Description [Extracts a subset from a BDD in the following procedure. - 1. Compute the weight for each mask variable by counting the number of - minterms for both positive and negative cofactors of the BDD with - respect to each mask variable. (weight = #positive - #negative) - 2. Find a representative cube of the BDD by using the weight. From the - top variable of the BDD, for each variable, if the weight is greater - than 0.0, choose THEN branch, othereise ELSE branch, until meeting - the constant 1. - 3. Quantify out the variables not in maskVars from the representative - cube and if a variable in maskVars is don't care, replace the - variable with a constant(1 or 0) depending on the weight. - 4. Make a subset of the BDD by multiplying with the modified cube.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_SubsetWithMaskVars( - DdManager * dd /* manager */, - DdNode * f /* function from which to pick a cube */, - DdNode ** vars /* array of variables */, - int nvars /* size of <code>vars</code> */, - DdNode ** maskVars /* array of variables */, - int mvars /* size of <code>maskVars</code> */) -{ - double *weight; - char *string; - int i, size; - int *indices, *mask; - int result; - DdNode *zero, *cube, *newCube, *subset; - DdNode *cof; - - DdNode *support; - support = Cudd_Support(dd,f); - cuddRef(support); - Cudd_RecursiveDeref(dd,support); - - zero = Cudd_Not(dd->one); - size = dd->size; - - weight = ALLOC(double,size); - if (weight == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < size; i++) { - weight[i] = 0.0; - } - for (i = 0; i < mvars; i++) { - cof = Cudd_Cofactor(dd, f, maskVars[i]); - cuddRef(cof); - weight[i] = Cudd_CountMinterm(dd, cof, nvars); - Cudd_RecursiveDeref(dd,cof); - - cof = Cudd_Cofactor(dd, f, Cudd_Not(maskVars[i])); - cuddRef(cof); - weight[i] -= Cudd_CountMinterm(dd, cof, nvars); - Cudd_RecursiveDeref(dd,cof); - } - - string = ALLOC(char, size + 1); - if (string == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - mask = ALLOC(int, size); - if (mask == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(string); - return(NULL); - } - for (i = 0; i < size; i++) { - string[i] = '2'; - mask[i] = 0; - } - string[size] = '\0'; - indices = ALLOC(int,nvars); - if (indices == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(string); - FREE(mask); - return(NULL); - } - for (i = 0; i < nvars; i++) { - indices[i] = vars[i]->index; - } - - result = ddPickRepresentativeCube(dd,f,nvars,weight,string); - if (result == 0) { - FREE(string); - FREE(mask); - FREE(indices); - return(NULL); - } - - cube = Cudd_ReadOne(dd); - cuddRef(cube); - zero = Cudd_Not(Cudd_ReadOne(dd)); - for (i = 0; i < nvars; i++) { - if (string[indices[i]] == '0') { - newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero); - } else if (string[indices[i]] == '1') { - newCube = Cudd_bddIte(dd,cube,vars[i],zero); - } else - continue; - if (newCube == NULL) { - FREE(string); - FREE(mask); - FREE(indices); - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(newCube); - Cudd_RecursiveDeref(dd,cube); - cube = newCube; - } - Cudd_RecursiveDeref(dd,cube); - - for (i = 0; i < mvars; i++) { - mask[maskVars[i]->index] = 1; - } - for (i = 0; i < nvars; i++) { - if (mask[indices[i]]) { - if (string[indices[i]] == '2') { - if (weight[indices[i]] >= 0.0) - string[indices[i]] = '1'; - else - string[indices[i]] = '0'; - } - } else { - string[indices[i]] = '2'; - } - } - - cube = Cudd_ReadOne(dd); - cuddRef(cube); - zero = Cudd_Not(Cudd_ReadOne(dd)); - - /* Build result BDD. */ - for (i = 0; i < nvars; i++) { - if (string[indices[i]] == '0') { - newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero); - } else if (string[indices[i]] == '1') { - newCube = Cudd_bddIte(dd,cube,vars[i],zero); - } else - continue; - if (newCube == NULL) { - FREE(string); - FREE(mask); - FREE(indices); - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(newCube); - Cudd_RecursiveDeref(dd,cube); - cube = newCube; - } - - subset = Cudd_bddAnd(dd,f,cube); - cuddRef(subset); - Cudd_RecursiveDeref(dd,cube); - - /* Test. */ - if (Cudd_bddLeq(dd,subset,f)) { - cuddDeref(subset); - } else { - Cudd_RecursiveDeref(dd,subset); - subset = NULL; - } - - FREE(string); - FREE(mask); - FREE(indices); - FREE(weight); - return(subset); - -} /* end of Cudd_SubsetWithMaskVars */ - - -/**Function******************************************************************** - - Synopsis [Finds the first cube of a decision diagram.] - - Description [Defines an iterator on the onset of a decision diagram - and finds its first cube. Returns a generator that contains the - information necessary to continue the enumeration if successful; NULL - otherwise.<p> - A cube is represented as an array of literals, which are integers in - {0, 1, 2}; 0 represents a complemented literal, 1 represents an - uncomplemented literal, and 2 stands for don't care. The enumeration - produces a disjoint cover of the function associated with the diagram. - The size of the array equals the number of variables in the manager at - the time Cudd_FirstCube is called.<p> - For each cube, a value is also returned. This value is always 1 for a - BDD, while it may be different from 1 for an ADD. - For BDDs, the offset is the set of cubes whose value is the logical zero. - For ADDs, the offset is the set of cubes whose value is the - background value. The cubes of the offset are not enumerated.] - - SideEffects [The first cube and its value are returned as side effects.] - - SeeAlso [Cudd_ForeachCube Cudd_NextCube Cudd_GenFree Cudd_IsGenEmpty - Cudd_FirstNode] - -******************************************************************************/ -DdGen * -Cudd_FirstCube( - DdManager * dd, - DdNode * f, - int ** cube, - CUDD_VALUE_TYPE * value) -{ - DdGen *gen; - DdNode *top, *treg, *next, *nreg, *prev, *preg; - int i; - int nvars; - - /* Sanity Check. */ - if (dd == NULL || f == NULL) return(NULL); - - /* Allocate generator an initialize it. */ - gen = ALLOC(DdGen,1); - if (gen == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - gen->manager = dd; - gen->type = CUDD_GEN_CUBES; - 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 = dd->size; - gen->gen.cubes.cube = ALLOC(int,nvars); - if (gen->gen.cubes.cube == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(gen); - return(NULL); - } - for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2; - - /* The maximum stack depth is one plus the number of variables. - ** because a path may have nodes at all levels, including the - ** constant level. - */ - gen->stack.stack = ALLOC(DdNode *, nvars+1); - if (gen->stack.stack == NULL) { - dd->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 cube of the onset. */ - gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++; - - while (1) { - top = gen->stack.stack[gen->stack.sp-1]; - treg = Cudd_Regular(top); - if (!cuddIsConstant(treg)) { - /* Take the else branch first. */ - gen->gen.cubes.cube[treg->index] = 0; - next = cuddE(treg); - if (top != treg) next = Cudd_Not(next); - gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; - } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) { - /* Backtrack */ - while (1) { - if (gen->stack.sp == 1) { - /* The current node has no predecessor. */ - gen->status = CUDD_GEN_EMPTY; - gen->stack.sp--; - goto done; - } - prev = gen->stack.stack[gen->stack.sp-2]; - preg = Cudd_Regular(prev); - nreg = cuddT(preg); - if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[preg->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[preg->index] = 2; - gen->stack.sp--; - top = gen->stack.stack[gen->stack.sp-1]; - treg = Cudd_Regular(top); - } - } else { - gen->status = CUDD_GEN_NONEMPTY; - gen->gen.cubes.value = cuddV(top); - goto done; - } - } - -done: - *cube = gen->gen.cubes.cube; - *value = gen->gen.cubes.value; - return(gen); - -} /* end of Cudd_FirstCube */ - - -/**Function******************************************************************** - - Synopsis [Generates the next cube of a decision diagram onset.] - - Description [Generates the next cube of a decision diagram onset, - using generator gen. Returns 0 if the enumeration is completed; 1 - otherwise.] - - SideEffects [The cube and its value are returned as side effects. The - generator is modified.] - - SeeAlso [Cudd_ForeachCube Cudd_FirstCube Cudd_GenFree Cudd_IsGenEmpty - Cudd_NextNode] - -******************************************************************************/ -int -Cudd_NextCube( - DdGen * gen, - int ** cube, - CUDD_VALUE_TYPE * value) -{ - DdNode *top, *treg, *next, *nreg, *prev, *preg; - DdManager *dd = 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]; - treg = Cudd_Regular(top); - prev = gen->stack.stack[gen->stack.sp-2]; - preg = Cudd_Regular(prev); - nreg = cuddT(preg); - if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[preg->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[preg->index] = 2; - gen->stack.sp--; - } - - while (1) { - top = gen->stack.stack[gen->stack.sp-1]; - treg = Cudd_Regular(top); - if (!cuddIsConstant(treg)) { - /* Take the else branch first. */ - gen->gen.cubes.cube[treg->index] = 0; - next = cuddE(treg); - if (top != treg) next = Cudd_Not(next); - gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; - } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) { - /* Backtrack */ - while (1) { - if (gen->stack.sp == 1) { - /* The current node has no predecessor. */ - gen->status = CUDD_GEN_EMPTY; - gen->stack.sp--; - goto done; - } - prev = gen->stack.stack[gen->stack.sp-2]; - preg = Cudd_Regular(prev); - nreg = cuddT(preg); - if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[preg->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[preg->index] = 2; - gen->stack.sp--; - top = gen->stack.stack[gen->stack.sp-1]; - treg = Cudd_Regular(top); - } - } else { - gen->status = CUDD_GEN_NONEMPTY; - gen->gen.cubes.value = cuddV(top); - goto done; - } - } - -done: - if (gen->status == CUDD_GEN_EMPTY) return(0); - *cube = gen->gen.cubes.cube; - *value = gen->gen.cubes.value; - return(1); - -} /* end of Cudd_NextCube */ - - -/**Function******************************************************************** - - Synopsis [Computes the cube of an array of BDD variables.] - - Description [Computes the cube of an array of BDD variables. If - non-null, the phase argument indicates which literal of each - variable should appear in the cube. If phase\[i\] is nonzero, then the - positive literal is used. If phase is NULL, the cube is positive unate. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addComputeCube Cudd_IndicesToCube Cudd_CubeArrayToBdd] - -******************************************************************************/ -DdNode * -Cudd_bddComputeCube( - DdManager * dd, - DdNode ** vars, - int * phase, - int n) -{ - DdNode *cube; - DdNode *fn; - int i; - - cube = DD_ONE(dd); - cuddRef(cube); - - for (i = n - 1; i >= 0; i--) { - if (phase == NULL || phase[i] != 0) { - fn = Cudd_bddAnd(dd,vars[i],cube); - } else { - fn = Cudd_bddAnd(dd,Cudd_Not(vars[i]),cube); - } - if (fn == NULL) { - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(fn); - Cudd_RecursiveDeref(dd,cube); - cube = fn; - } - cuddDeref(cube); - - return(cube); - -} /* end of Cudd_bddComputeCube */ - - -/**Function******************************************************************** - - Synopsis [Computes the cube of an array of ADD variables.] - - Description [Computes the cube of an array of ADD variables. If - non-null, the phase argument indicates which literal of each - variable should appear in the cube. If phase\[i\] is nonzero, then the - positive literal is used. If phase is NULL, the cube is positive unate. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [none] - - SeeAlso [Cudd_bddComputeCube] - -******************************************************************************/ -DdNode * -Cudd_addComputeCube( - DdManager * dd, - DdNode ** vars, - int * phase, - int n) -{ - DdNode *cube, *zero; - DdNode *fn; - int i; - - cube = DD_ONE(dd); - cuddRef(cube); - zero = DD_ZERO(dd); - - for (i = n - 1; i >= 0; i--) { - if (phase == NULL || phase[i] != 0) { - fn = Cudd_addIte(dd,vars[i],cube,zero); - } else { - fn = Cudd_addIte(dd,vars[i],zero,cube); - } - if (fn == NULL) { - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(fn); - Cudd_RecursiveDeref(dd,cube); - cube = fn; - } - cuddDeref(cube); - - return(cube); - -} /* end of Cudd_addComputeCube */ - - -/**Function******************************************************************** - - Synopsis [Builds the BDD of a cube from a positional array.] - - Description [Builds a cube from a positional array. The array must - have one integer entry for each BDD variable. If the i-th entry is - 1, the variable of index i appears in true form in the cube; If the - i-th entry is 0, the variable of index i appears complemented in the - cube; otherwise the variable does not appear in the cube. Returns a - pointer to the BDD for the cube if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddComputeCube Cudd_IndicesToCube Cudd_BddToCubeArray] - -******************************************************************************/ -DdNode * -Cudd_CubeArrayToBdd( - DdManager *dd, - int *array) -{ - DdNode *cube, *var, *tmp; - int i; - int size = Cudd_ReadSize(dd); - - cube = DD_ONE(dd); - cuddRef(cube); - for (i = size - 1; i >= 0; i--) { - if ((array[i] & ~1) == 0) { - var = Cudd_bddIthVar(dd,i); - tmp = Cudd_bddAnd(dd,cube,Cudd_NotCond(var,array[i]==0)); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,cube); - cube = tmp; - } - } - cuddDeref(cube); - return(cube); - -} /* end of Cudd_CubeArrayToBdd */ - - -/**Function******************************************************************** - - Synopsis [Builds a positional array from the BDD of a cube.] - - Description [Builds a positional array from the BDD of a cube. - Array must have one entry for each BDD variable. The positional - array has 1 in i-th position if the variable of index i appears in - true form in the cube; it has 0 in i-th position if the variable of - index i appears in complemented form in the cube; finally, it has 2 - in i-th position if the variable of index i does not appear in the - cube. Returns 1 if successful (the BDD is indeed a cube); 0 - otherwise.] - - SideEffects [The result is in the array passed by reference.] - - SeeAlso [Cudd_CubeArrayToBdd] - -******************************************************************************/ -int -Cudd_BddToCubeArray( - DdManager *dd, - DdNode *cube, - int *array) -{ - DdNode *scan, *t, *e; - int i; - int size = Cudd_ReadSize(dd); - DdNode *zero = Cudd_Not(DD_ONE(dd)); - - for (i = size-1; i >= 0; i--) { - array[i] = 2; - } - scan = cube; - while (!Cudd_IsConstant(scan)) { - int index = Cudd_Regular(scan)->index; - cuddGetBranches(scan,&t,&e); - if (t == zero) { - array[index] = 0; - scan = e; - } else if (e == zero) { - array[index] = 1; - scan = t; - } else { - return(0); /* cube is not a cube */ - } - } - if (scan == zero) { - return(0); - } else { - return(1); - } - -} /* end of Cudd_BddToCubeArray */ - - -/**Function******************************************************************** - - Synopsis [Finds the first node of a decision diagram.] - - Description [Defines an iterator on the nodes of a decision diagram - and finds its first node. Returns a generator that contains the - information necessary to continue the enumeration if successful; NULL - otherwise.] - - SideEffects [The first node is returned as a side effect.] - - SeeAlso [Cudd_ForeachNode Cudd_NextNode Cudd_GenFree Cudd_IsGenEmpty - Cudd_FirstCube] - -******************************************************************************/ -DdGen * -Cudd_FirstNode( - DdManager * dd, - DdNode * f, - DdNode ** node) -{ - DdGen *gen; - int retval; - - /* Sanity Check. */ - if (dd == NULL || f == NULL) return(NULL); - - /* Allocate generator an initialize it. */ - gen = ALLOC(DdGen,1); - if (gen == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - gen->manager = dd; - gen->type = CUDD_GEN_NODES; - gen->status = CUDD_GEN_EMPTY; - gen->gen.nodes.visited = NULL; - gen->gen.nodes.stGen = NULL; - gen->stack.sp = 0; - gen->stack.stack = NULL; - gen->node = NULL; - - gen->gen.nodes.visited = st_init_table(st_ptrcmp,st_ptrhash); - if (gen->gen.nodes.visited == NULL) { - FREE(gen); - return(NULL); - } - - /* Collect all the nodes in a st table for later perusal. */ - retval = cuddCollectNodes(Cudd_Regular(f),gen->gen.nodes.visited); - if (retval == 0) { - st_free_table(gen->gen.nodes.visited); - FREE(gen); - return(NULL); - } - - /* Initialize the st table generator. */ - gen->gen.nodes.stGen = st_init_gen(gen->gen.nodes.visited); - if (gen->gen.nodes.stGen == NULL) { - st_free_table(gen->gen.nodes.visited); - FREE(gen); - return(NULL); - } - - /* Find the first node. */ - retval = st_gen(gen->gen.nodes.stGen, (char **) &(gen->node), NULL); - if (retval != 0) { - gen->status = CUDD_GEN_NONEMPTY; - *node = gen->node; - } - - return(gen); - -} /* end of Cudd_FirstNode */ - - -/**Function******************************************************************** - - Synopsis [Finds the next node of a decision diagram.] - - Description [Finds the node of a decision diagram, using generator - gen. Returns 0 if the enumeration is completed; 1 otherwise.] - - SideEffects [The next node is returned as a side effect.] - - SeeAlso [Cudd_ForeachNode Cudd_FirstNode Cudd_GenFree Cudd_IsGenEmpty - Cudd_NextCube] - -******************************************************************************/ -int -Cudd_NextNode( - DdGen * gen, - DdNode ** node) -{ - int retval; - - /* Find the next node. */ - retval = st_gen(gen->gen.nodes.stGen, (char **) &(gen->node), NULL); - if (retval == 0) { - gen->status = CUDD_GEN_EMPTY; - } else { - *node = gen->node; - } - - return(retval); - -} /* end of Cudd_NextNode */ - - -/**Function******************************************************************** - - Synopsis [Frees a CUDD generator.] - - Description [Frees a CUDD generator. Always returns 0, so that it can - be used in mis-like foreach constructs.] - - SideEffects [None] - - SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube - Cudd_FirstNode Cudd_NextNode Cudd_IsGenEmpty] - -******************************************************************************/ -int -Cudd_GenFree( - DdGen * gen) -{ - - if (gen == NULL) return(0); - switch (gen->type) { - case CUDD_GEN_CUBES: - case CUDD_GEN_ZDD_PATHS: - FREE(gen->gen.cubes.cube); - FREE(gen->stack.stack); - break; - case CUDD_GEN_NODES: - st_free_gen(gen->gen.nodes.stGen); - st_free_table(gen->gen.nodes.visited); - break; - default: - return(0); - } - FREE(gen); - return(0); - -} /* end of Cudd_GenFree */ - - -/**Function******************************************************************** - - Synopsis [Queries the status of a generator.] - - Description [Queries the status of a generator. Returns 1 if the - generator is empty or NULL; 0 otherswise.] - - SideEffects [None] - - SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube - Cudd_FirstNode Cudd_NextNode Cudd_GenFree] - -******************************************************************************/ -int -Cudd_IsGenEmpty( - DdGen * gen) -{ - if (gen == NULL) return(1); - return(gen->status == CUDD_GEN_EMPTY); - -} /* end of Cudd_IsGenEmpty */ - - -/**Function******************************************************************** - - Synopsis [Builds a cube of BDD variables from an array of indices.] - - Description [Builds a cube of BDD variables from an array of indices. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddComputeCube Cudd_CubeArrayToBdd] - -******************************************************************************/ -DdNode * -Cudd_IndicesToCube( - DdManager * dd, - int * array, - int n) -{ - DdNode *cube, *tmp; - int i; - - cube = DD_ONE(dd); - cuddRef(cube); - for (i = n - 1; i >= 0; i--) { - tmp = Cudd_bddAnd(dd,Cudd_bddIthVar(dd,array[i]),cube); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,cube); - cube = tmp; - } - - cuddDeref(cube); - return(cube); - -} /* end of Cudd_IndicesToCube */ - - -/**Function******************************************************************** - - Synopsis [Prints the package version number.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_PrintVersion( - FILE * fp) -{ - (void) fprintf(fp, "%s\n", CUDD_VERSION); - -} /* end of Cudd_PrintVersion */ - - -/**Function******************************************************************** - - Synopsis [Computes the average distance between adjacent nodes.] - - Description [Computes the average distance between adjacent nodes in - the manager. Adjacent nodes are node pairs such that the second node - is the then child, else child, or next node in the collision list.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -double -Cudd_AverageDistance( - DdManager * dd) -{ - double tetotal, nexttotal; - double tesubtotal, nextsubtotal; - double temeasured, nextmeasured; - int i, j; - int slots, nvars; - long diff; - DdNode *scan; - DdNodePtr *nodelist; - DdNode *sentinel = &(dd->sentinel); - - nvars = dd->size; - if (nvars == 0) return(0.0); - - /* Initialize totals. */ - tetotal = 0.0; - nexttotal = 0.0; - temeasured = 0.0; - nextmeasured = 0.0; - - /* Scan the variable subtables. */ - for (i = 0; i < nvars; i++) { - nodelist = dd->subtables[i].nodelist; - tesubtotal = 0.0; - nextsubtotal = 0.0; - slots = dd->subtables[i].slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != sentinel) { - diff = (long) scan - (long) cuddT(scan); - tesubtotal += (double) ddAbs(diff); - diff = (long) scan - (long) Cudd_Regular(cuddE(scan)); - tesubtotal += (double) ddAbs(diff); - temeasured += 2.0; - if (scan->next != NULL) { - diff = (long) scan - (long) scan->next; - nextsubtotal += (double) ddAbs(diff); - nextmeasured += 1.0; - } - scan = scan->next; - } - } - tetotal += tesubtotal; - nexttotal += nextsubtotal; - } - - /* Scan the constant table. */ - nodelist = dd->constants.nodelist; - nextsubtotal = 0.0; - slots = dd->constants.slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (scan->next != NULL) { - diff = (long) scan - (long) scan->next; - nextsubtotal += (double) ddAbs(diff); - nextmeasured += 1.0; - } - scan = scan->next; - } - } - nexttotal += nextsubtotal; - - return((tetotal + nexttotal) / (temeasured + nextmeasured)); - -} /* end of Cudd_AverageDistance */ - - -/**Function******************************************************************** - - Synopsis [Portable random number generator.] - - Description [Portable number generator based on ran2 from "Numerical - Recipes in C." It is a long period (> 2 * 10^18) random number generator - of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly - distributed between 0 and 2147483561 (inclusive of the endpoint values). - The random generator can be explicitly initialized by calling - Cudd_Srandom. If no explicit initialization is performed, then the - seed 1 is assumed.] - - SideEffects [None] - - SeeAlso [Cudd_Srandom] - -******************************************************************************/ -long -Cudd_Random( - ) -{ - int i; /* index in the shuffle table */ - long int w; /* work variable */ - - /* cuddRand == 0 if the geneartor has not been initialized yet. */ - if (cuddRand == 0) Cudd_Srandom(1); - - /* Compute cuddRand = (cuddRand * LEQA1) % MODULUS1 avoiding - ** overflows by Schrage's method. - */ - w = cuddRand / LEQQ1; - cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1; - cuddRand += (cuddRand < 0) * MODULUS1; - - /* Compute cuddRand2 = (cuddRand2 * LEQA2) % MODULUS2 avoiding - ** overflows by Schrage's method. - */ - w = cuddRand2 / LEQQ2; - cuddRand2 = LEQA2 * (cuddRand2 - w * LEQQ2) - w * LEQR2; - cuddRand2 += (cuddRand2 < 0) * MODULUS2; - - /* cuddRand is shuffled with the Bays-Durham algorithm. - ** shuffleSelect and cuddRand2 are combined to generate the output. - */ - - /* Pick one element from the shuffle table; "i" will be in the range - ** from 0 to STAB_SIZE-1. - */ - i = (int) (shuffleSelect / STAB_DIV); - /* Mix the element of the shuffle table with the current iterate of - ** the second sub-generator, and replace the chosen element of the - ** shuffle table with the current iterate of the first sub-generator. - */ - shuffleSelect = shuffleTable[i] - cuddRand2; - shuffleTable[i] = cuddRand; - shuffleSelect += (shuffleSelect < 1) * (MODULUS1 - 1); - /* Since shuffleSelect != 0, and we want to be able to return 0, - ** here we subtract 1 before returning. - */ - return(shuffleSelect - 1); - -} /* end of Cudd_Random */ - - -/**Function******************************************************************** - - Synopsis [Initializer for the portable random number generator.] - - Description [Initializer for the portable number generator based on - ran2 in "Numerical Recipes in C." The input is the seed for the - generator. If it is negative, its absolute value is taken as seed. - If it is 0, then 1 is taken as seed. The initialized sets up the two - recurrences used to generate a long-period stream, and sets up the - shuffle table.] - - SideEffects [None] - - SeeAlso [Cudd_Random] - -******************************************************************************/ -void -Cudd_Srandom( - long seed) -{ - int i; - - if (seed < 0) cuddRand = -seed; - else if (seed == 0) cuddRand = 1; - else cuddRand = seed; - cuddRand2 = cuddRand; - /* Load the shuffle table (after 11 warm-ups). */ - for (i = 0; i < STAB_SIZE + 11; i++) { - long int w; - w = cuddRand / LEQQ1; - cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1; - cuddRand += (cuddRand < 0) * MODULUS1; - shuffleTable[i % STAB_SIZE] = cuddRand; - } - shuffleSelect = shuffleTable[1 % STAB_SIZE]; - -} /* end of Cudd_Srandom */ - - -/**Function******************************************************************** - - Synopsis [Computes the density of a BDD or ADD.] - - Description [Computes the density of a BDD or ADD. The density is - the ratio of the number of minterms to the number of nodes. If 0 is - passed as number of variables, the number of variables existing in - the manager is used. Returns the density if successful; (double) - CUDD_OUT_OF_MEM otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_CountMinterm Cudd_DagSize] - -******************************************************************************/ -double -Cudd_Density( - DdManager * dd /* manager */, - DdNode * f /* function whose density is sought */, - int nvars /* size of the support of f */) -{ - double minterms; - int nodes; - double density; - - if (nvars == 0) nvars = dd->size; - minterms = Cudd_CountMinterm(dd,f,nvars); - if (minterms == (double) CUDD_OUT_OF_MEM) return(minterms); - nodes = Cudd_DagSize(f); - density = minterms / (double) nodes; - return(density); - -} /* end of Cudd_Density */ - - -/**Function******************************************************************** - - Synopsis [Warns that a memory allocation failed.] - - Description [Warns that a memory allocation failed. - This function can be used as replacement of MMout_of_memory to prevent - the safe_mem functions of the util package from exiting when malloc - returns NULL. One possible use is in case of discretionary allocations; - for instance, the allocation of memory to enlarge the computed table.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_OutOfMem( - long size /* size of the allocation that failed */) -{ - (void) fflush(stdout); - (void) fprintf(stderr, "\nunable to allocate %ld bytes\n", size); - return; - -} /* end of Cudd_OutOfMem */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints a DD to the standard output. One line per node is - printed.] - - Description [Prints a DD to the standard output. One line per node is - printed. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintDebug] - -******************************************************************************/ -int -cuddP( - DdManager * dd, - DdNode * f) -{ - int retval; - st_table *table = st_init_table(st_ptrcmp,st_ptrhash); - - if (table == NULL) return(0); - - retval = dp2(dd,f,table); - st_free_table(table); - (void) fputc('\n',dd->out); - return(retval); - -} /* end of cuddP */ - - -/**Function******************************************************************** - - Synopsis [Frees the memory used to store the minterm counts recorded - in the visited table.] - - Description [Frees the memory used to store the minterm counts - recorded in the visited table. Returns ST_CONTINUE.] - - SideEffects [None] - -******************************************************************************/ -enum st_retval -cuddStCountfree( - char * key, - char * value, - char * arg) -{ - double *d; - - d = (double *)value; - FREE(d); - return(ST_CONTINUE); - -} /* end of cuddStCountfree */ - - -/**Function******************************************************************** - - Synopsis [Recursively collects all the nodes of a DD in a symbol - table.] - - Description [Traverses the BDD f and collects all its nodes in a - symbol table. f is assumed to be a regular pointer and - cuddCollectNodes guarantees this assumption in the recursive calls. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddCollectNodes( - DdNode * f, - st_table * visited) -{ - DdNode *T, *E; - int retval; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); -#endif - - /* If already visited, nothing to do. */ - if (st_is_member(visited, (char *) f) == 1) - return(1); - - /* Check for abnormal condition that should never happen. */ - if (f == NULL) - return(0); - - /* Mark node as visited. */ - if (st_add_direct(visited, (char *) f, NULL) == ST_OUT_OF_MEM) - return(0); - - /* Check terminal case. */ - if (cuddIsConstant(f)) - return(1); - - /* Recursive calls. */ - T = cuddT(f); - retval = cuddCollectNodes(T,visited); - if (retval != 1) return(retval); - E = Cudd_Regular(cuddE(f)); - retval = cuddCollectNodes(E,visited); - return(retval); - -} /* end of cuddCollectNodes */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of cuddP.] - - Description [Performs the recursive step of cuddP. Returns 1 in case - of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -dp2( - DdManager *dd, - DdNode * f, - st_table * t) -{ - DdNode *g, *n, *N; - int T,E; - - if (f == NULL) { - return(0); - } - g = Cudd_Regular(f); - if (cuddIsConstant(g)) { -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out,"ID = %c0x%lx\tvalue = %-9g\n", bang(f), - (unsigned long) g / (unsigned long) sizeof(DdNode),cuddV(g)); -#else - (void) fprintf(dd->out,"ID = %c0x%x\tvalue = %-9g\n", bang(f), - (unsigned) g / (unsigned) sizeof(DdNode),cuddV(g)); -#endif - return(1); - } - if (st_is_member(t,(char *) g) == 1) { - return(1); - } - if (st_add_direct(t,(char *) g,NULL) == ST_OUT_OF_MEM) - return(0); -#ifdef DD_STATS -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\tr = %d\t", bang(f), - (unsigned long) g / (unsigned long) sizeof(DdNode), g->index, g->ref); -#else - (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\tr = %d\t", bang(f), - (unsigned) g / (unsigned) sizeof(DdNode),g->index,g->ref); -#endif -#else -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\t", bang(f), - (unsigned long) g / (unsigned long) sizeof(DdNode),g->index); -#else - (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\t", bang(f), - (unsigned) g / (unsigned) sizeof(DdNode),g->index); -#endif -#endif - n = cuddT(g); - if (cuddIsConstant(n)) { - (void) fprintf(dd->out,"T = %-9g\t",cuddV(n)); - T = 1; - } else { -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out,"T = 0x%lx\t",(unsigned long) n / (unsigned long) sizeof(DdNode)); -#else - (void) fprintf(dd->out,"T = 0x%x\t",(unsigned) n / (unsigned) sizeof(DdNode)); -#endif - T = 0; - } - - n = cuddE(g); - N = Cudd_Regular(n); - if (cuddIsConstant(N)) { - (void) fprintf(dd->out,"E = %c%-9g\n",bang(n),cuddV(N)); - E = 1; - } else { -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out,"E = %c0x%lx\n", bang(n), (unsigned long) N/(unsigned long) sizeof(DdNode)); -#else - (void) fprintf(dd->out,"E = %c0x%x\n", bang(n), (unsigned) N/(unsigned) sizeof(DdNode)); -#endif - E = 0; - } - if (E == 0) { - if (dp2(dd,N,t) == 0) - return(0); - } - if (T == 0) { - if (dp2(dd,cuddT(g),t) == 0) - return(0); - } - return(1); - -} /* end of dp2 */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_PrintMinterm.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -static void -ddPrintMintermAux( - DdManager * dd /* manager */, - DdNode * node /* current node */, - int * list /* current recursion path */) -{ - DdNode *N,*Nv,*Nnv; - int i,v,index; - - N = Cudd_Regular(node); - - if (cuddIsConstant(N)) { - /* Terminal case: Print one cube based on the current recursion - ** path, unless we have reached the background value (ADDs) or - ** the logical zero (BDDs). - */ - if (node != background && node != zero) { - for (i = 0; i < dd->size; i++) { - v = list[i]; - if (v == 0) (void) fprintf(dd->out,"0"); - else if (v == 1) (void) fprintf(dd->out,"1"); - else (void) fprintf(dd->out,"-"); - } - (void) fprintf(dd->out," % g\n", cuddV(node)); - } - } else { - Nv = cuddT(N); - Nnv = cuddE(N); - if (Cudd_IsComplement(node)) { - Nv = Cudd_Not(Nv); - Nnv = Cudd_Not(Nnv); - } - index = N->index; - list[index] = 0; - ddPrintMintermAux(dd,Nnv,list); - list[index] = 1; - ddPrintMintermAux(dd,Nv,list); - list[index] = 2; - } - return; - -} /* end of ddPrintMintermAux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_DagSize.] - - Description [Performs the recursive step of Cudd_DagSize. Returns the - number of nodes in the graph rooted at n.] - - SideEffects [None] - -******************************************************************************/ -static int -ddDagInt( - DdNode * n) -{ - int tval, eval; - - if (Cudd_IsComplement(n->next)) { - return(0); - } - n->next = Cudd_Not(n->next); - if (cuddIsConstant(n)) { - return(1); - } - tval = ddDagInt(cuddT(n)); - eval = ddDagInt(Cudd_Regular(cuddE(n))); - return(1 + tval + eval); - -} /* end of ddDagInt */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CofactorEstimate.] - - Description [Performs the recursive step of Cudd_CofactorEstimate. - Returns an estimate of the number of nodes in the DD of a - cofactor of node. Uses the least significant bit of the next field as - visited flag. node is supposed to be regular; the invariant is maintained - by this procedure.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddEstimateCofactor( - DdManager *dd, - st_table *table, - DdNode * node, - int i, - int phase, - DdNode ** ptr) -{ - int tval, eval, val; - DdNode *ptrT, *ptrE; - - if (Cudd_IsComplement(node->next)) { - if (!st_lookup(table,(char *)node,(char **)ptr)) { - st_add_direct(table,(char *)node,(char *)node); - *ptr = node; - } - return(0); - } - node->next = Cudd_Not(node->next); - if (cuddIsConstant(node)) { - *ptr = node; - if (st_add_direct(table,(char *)node,(char *)node) == ST_OUT_OF_MEM) - return(CUDD_OUT_OF_MEM); - return(1); - } - if ((int) node->index == i) { - if (phase == 1) { - *ptr = cuddT(node); - val = ddDagInt(cuddT(node)); - } else { - *ptr = cuddE(node); - val = ddDagInt(Cudd_Regular(cuddE(node))); - } - if (node->ref > 1) { - if (st_add_direct(table,(char *)node,(char *)*ptr) == - ST_OUT_OF_MEM) - return(CUDD_OUT_OF_MEM); - } - return(val); - } - if (dd->perm[node->index] > dd->perm[i]) { - *ptr = node; - tval = ddDagInt(cuddT(node)); - eval = ddDagInt(Cudd_Regular(cuddE(node))); - if (node->ref > 1) { - if (st_add_direct(table,(char *)node,(char *)node) == - ST_OUT_OF_MEM) - return(CUDD_OUT_OF_MEM); - } - val = 1 + tval + eval; - return(val); - } - tval = cuddEstimateCofactor(dd,table,cuddT(node),i,phase,&ptrT); - eval = cuddEstimateCofactor(dd,table,Cudd_Regular(cuddE(node)),i, - phase,&ptrE); - ptrE = Cudd_NotCond(ptrE,Cudd_IsComplement(cuddE(node))); - if (ptrT == ptrE) { /* recombination */ - *ptr = ptrT; - val = tval; - if (node->ref > 1) { - if (st_add_direct(table,(char *)node,(char *)*ptr) == - ST_OUT_OF_MEM) - return(CUDD_OUT_OF_MEM); - } - } else if ((ptrT != cuddT(node) || ptrE != cuddE(node)) && - (*ptr = cuddUniqueLookup(dd,node->index,ptrT,ptrE)) != NULL) { - if (Cudd_IsComplement((*ptr)->next)) { - val = 0; - } else { - val = 1 + tval + eval; - } - if (node->ref > 1) { - if (st_add_direct(table,(char *)node,(char *)*ptr) == - ST_OUT_OF_MEM) - return(CUDD_OUT_OF_MEM); - } - } else { - *ptr = node; - val = 1 + tval + eval; - } - return(val); - -} /* end of cuddEstimateCofactor */ - - -/**Function******************************************************************** - - Synopsis [Checks the unique table for the existence of an internal node.] - - Description [Checks the unique table for the existence of an internal - node. Returns a pointer to the node if it is in the table; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddUniqueInter] - -******************************************************************************/ -static DdNode * -cuddUniqueLookup( - DdManager * unique, - int index, - DdNode * T, - DdNode * E) -{ - int posn; - unsigned int level; - DdNodePtr *nodelist; - DdNode *looking; - DdSubtable *subtable; - - if (index >= unique->size) { - return(NULL); - } - - level = unique->perm[index]; - subtable = &(unique->subtables[level]); - -#ifdef DD_DEBUG - assert(level < (unsigned) cuddI(unique,T->index)); - assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); -#endif - - posn = ddHash(T, E, subtable->shift); - nodelist = subtable->nodelist; - looking = nodelist[posn]; - - while (T < cuddT(looking)) { - looking = Cudd_Regular(looking->next); - } - while (T == cuddT(looking) && E < cuddE(looking)) { - looking = Cudd_Regular(looking->next); - } - if (cuddT(looking) == T && cuddE(looking) == E) { - return(looking); - } - - return(NULL); - -} /* end of cuddUniqueLookup */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CofactorEstimateSimple.] - - Description [Performs the recursive step of Cudd_CofactorEstimateSimple. - Returns an estimate of the number of nodes in the DD of the positive - cofactor of node. Uses the least significant bit of the next field as - visited flag. node is supposed to be regular; the invariant is maintained - by this procedure.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddEstimateCofactorSimple( - DdNode * node, - int i) -{ - int tval, eval; - - if (Cudd_IsComplement(node->next)) { - return(0); - } - node->next = Cudd_Not(node->next); - if (cuddIsConstant(node)) { - return(1); - } - tval = cuddEstimateCofactorSimple(cuddT(node),i); - if ((int) node->index == i) return(tval); - eval = cuddEstimateCofactorSimple(Cudd_Regular(cuddE(node)),i); - return(1 + tval + eval); - -} /* end of cuddEstimateCofactorSimple */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CountMinterm.] - - Description [Performs the recursive step of Cudd_CountMinterm. - It is based on the following identity. Let |f| be the - number of minterms of f. Then: - <xmp> - |f| = (|f0|+|f1|)/2 - </xmp> - where f0 and f1 are the two cofactors of f. Does not use the - identity |f'| = max - |f|, to minimize loss of accuracy due to - roundoff. Returns the number of minterms of the function rooted at - node.] - - SideEffects [None] - -******************************************************************************/ -static double -ddCountMintermAux( - DdNode * node, - double max, - DdHashTable * table) -{ - DdNode *N, *Nt, *Ne; - double min, minT, minE; - DdNode *res; - - N = Cudd_Regular(node); - - if (cuddIsConstant(N)) { - if (node == background || node == zero) { - return(0.0); - } else { - return(max); - } - } - if (N->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) { - min = cuddV(res); - if (res->ref == 0) { - table->manager->dead++; - table->manager->constants.dead++; - } - return(min); - } - - Nt = cuddT(N); Ne = cuddE(N); - if (Cudd_IsComplement(node)) { - Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); - } - - minT = ddCountMintermAux(Nt,max,table); - if (minT == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - minT *= 0.5; - minE = ddCountMintermAux(Ne,max,table); - if (minE == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - minE *= 0.5; - min = minT + minE; - - if (N->ref != 1) { - ptrint fanout = (ptrint) N->ref; - cuddSatDec(fanout); - res = cuddUniqueConst(table->manager,min); - if (!cuddHashTableInsert1(table,node,res,fanout)) { - cuddRef(res); Cudd_RecursiveDeref(table->manager, res); - return((double)CUDD_OUT_OF_MEM); - } - } - - return(min); - -} /* end of ddCountMintermAux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CountPath.] - - Description [Performs the recursive step of Cudd_CountPath. - It is based on the following identity. Let |f| be the - number of paths of f. Then: - <xmp> - |f| = |f0|+|f1| - </xmp> - where f0 and f1 are the two cofactors of f. Uses the - identity |f'| = |f|, to improve the utilization of the (local) cache. - Returns the number of paths of the function rooted at node.] - - SideEffects [None] - -******************************************************************************/ -static double -ddCountPathAux( - DdNode * node, - st_table * table) -{ - - DdNode *Nv, *Nnv; - double paths, *ppaths, paths1, paths2; - double *dummy; - - - if (cuddIsConstant(node)) { - return(1.0); - } - if (st_lookup(table, (char *)node, (char **)&dummy)) { - paths = *dummy; - return(paths); - } - - Nv = cuddT(node); Nnv = cuddE(node); - - paths1 = ddCountPathAux(Nv,table); - if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - paths2 = ddCountPathAux(Cudd_Regular(Nnv),table); - if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - paths = paths1 + paths2; - - ppaths = ALLOC(double,1); - if (ppaths == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - - *ppaths = paths; - - if (st_add_direct(table,(char *)node, (char *)ppaths) == ST_OUT_OF_MEM) { - FREE(ppaths); - return((double)CUDD_OUT_OF_MEM); - } - return(paths); - -} /* end of ddCountPathAux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CountMinterm.] - - Description [Performs the recursive step of Cudd_CountMinterm. - It is based on the following identity. Let |f| be the - number of minterms of f. Then: - <xmp> - |f| = (|f0|+|f1|)/2 - </xmp> - where f0 and f1 are the two cofactors of f. Does not use the - identity |f'| = max - |f|, to minimize loss of accuracy due to - roundoff. Returns the number of minterms of the function rooted at - node.] - - SideEffects [None] - -******************************************************************************/ -static int -ddEpdCountMintermAux( - DdNode * node, - EpDouble * max, - EpDouble * epd, - st_table * table) -{ - DdNode *Nt, *Ne; - EpDouble *min, minT, minE; - EpDouble *res; - int status; - - if (cuddIsConstant(node)) { - if (node == background || node == zero) { - EpdMakeZero(epd, 0); - } else { - EpdCopy(max, epd); - } - return(0); - } - if (node->ref != 1 && st_lookup(table, (char *)node, (char **)&res)) { - EpdCopy(res, epd); - return(0); - } - - Nt = cuddT(node); Ne = cuddE(node); - if (Cudd_IsComplement(node)) { - Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); - } - - status = ddEpdCountMintermAux(Nt,max,&minT,table); - if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); - EpdMultiply(&minT, (double)0.5); - status = ddEpdCountMintermAux(Ne,max,&minE,table); - if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); - if (Cudd_IsComplement(Ne)) { - EpdSubtract3(max, &minE, epd); - EpdCopy(epd, &minE); - } - EpdMultiply(&minE, (double)0.5); - EpdAdd3(&minT, &minE, epd); - - if (node->ref > 1) { - min = EpdAlloc(); - if (!min) - return(CUDD_OUT_OF_MEM); - EpdCopy(epd, min); - if (st_insert(table, (char *)node, (char *)min) == ST_OUT_OF_MEM) { - EpdFree(min); - return(CUDD_OUT_OF_MEM); - } - } - - return(0); - -} /* end of ddEpdCountMintermAux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CountPathsToNonZero.] - - Description [Performs the recursive step of Cudd_CountPathsToNonZero. - It is based on the following identity. Let |f| be the - number of paths of f. Then: - <xmp> - |f| = |f0|+|f1| - </xmp> - where f0 and f1 are the two cofactors of f. Returns the number of - paths of the function rooted at node.] - - SideEffects [None] - -******************************************************************************/ -static double -ddCountPathsToNonZero( - DdNode * N, - st_table * table) -{ - - DdNode *node, *Nt, *Ne; - double paths, *ppaths, paths1, paths2; - double *dummy; - - node = Cudd_Regular(N); - if (cuddIsConstant(node)) { - return((double) !(Cudd_IsComplement(N) || cuddV(node)==DD_ZERO_VAL)); - } - if (st_lookup(table, (char *)N, (char **)&dummy)) { - paths = *dummy; - return(paths); - } - - Nt = cuddT(node); Ne = cuddE(node); - if (node != N) { - Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); - } - - paths1 = ddCountPathsToNonZero(Nt,table); - if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - paths2 = ddCountPathsToNonZero(Ne,table); - if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - paths = paths1 + paths2; - - ppaths = ALLOC(double,1); - if (ppaths == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - - *ppaths = paths; - - if (st_add_direct(table,(char *)N, (char *)ppaths) == ST_OUT_OF_MEM) { - FREE(ppaths); - return((double)CUDD_OUT_OF_MEM); - } - return(paths); - -} /* end of ddCountPathsToNonZero */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_Support.] - - Description [Performs the recursive step of Cudd_Support. 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 [ddClearFlag] - -******************************************************************************/ -static void -ddSupportStep( - DdNode * f, - int * support) -{ - if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) { - return; - } - - support[f->index] = 1; - ddSupportStep(cuddT(f),support); - ddSupportStep(Cudd_Regular(cuddE(f)),support); - /* Mark as visited. */ - f->next = Cudd_Not(f->next); - return; - -} /* end of ddSupportStep */ - - -/**Function******************************************************************** - - Synopsis [Performs a DFS from f, clearing the LSB of the next - pointers.] - - Description [] - - SideEffects [None] - - SeeAlso [ddSupportStep ddDagInt] - -******************************************************************************/ -static void -ddClearFlag( - DdNode * f) -{ - if (!Cudd_IsComplement(f->next)) { - return; - } - /* Clear visited flag. */ - f->next = Cudd_Regular(f->next); - if (cuddIsConstant(f)) { - return; - } - ddClearFlag(cuddT(f)); - ddClearFlag(Cudd_Regular(cuddE(f))); - return; - -} /* end of ddClearFlag */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CountLeaves.] - - Description [Performs the recursive step of Cudd_CountLeaves. Returns - the number of leaves in the DD rooted at n.] - - SideEffects [None] - - SeeAlso [Cudd_CountLeaves] - -******************************************************************************/ -static int -ddLeavesInt( - DdNode * n) -{ - int tval, eval; - - if (Cudd_IsComplement(n->next)) { - return(0); - } - n->next = Cudd_Not(n->next); - if (cuddIsConstant(n)) { - return(1); - } - tval = ddLeavesInt(cuddT(n)); - eval = ddLeavesInt(Cudd_Regular(cuddE(n))); - return(tval + eval); - -} /* end of ddLeavesInt */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddPickArbitraryMinterms.] - - Description [Performs the recursive step of Cudd_bddPickArbitraryMinterms. - Returns 1 if successful; 0 otherwise.] - - SideEffects [none] - - SeeAlso [Cudd_bddPickArbitraryMinterms] - -******************************************************************************/ -static int -ddPickArbitraryMinterms( - DdManager *dd, - DdNode *node, - int nvars, - int nminterms, - char **string) -{ - DdNode *N, *T, *E; - DdNode *one, *bzero; - int i, t, result; - double min1, min2; - - if (string == NULL || node == NULL) return(0); - - /* The constant 0 function has no on-set cubes. */ - one = DD_ONE(dd); - bzero = Cudd_Not(one); - if (nminterms == 0 || node == bzero) return(1); - if (node == one) { - return(1); - } - - N = Cudd_Regular(node); - T = cuddT(N); E = cuddE(N); - if (Cudd_IsComplement(node)) { - T = Cudd_Not(T); E = Cudd_Not(E); - } - - min1 = Cudd_CountMinterm(dd, T, nvars) / 2.0; - if (min1 == (double)CUDD_OUT_OF_MEM) return(0); - min2 = Cudd_CountMinterm(dd, E, nvars) / 2.0; - if (min2 == (double)CUDD_OUT_OF_MEM) return(0); - - t = (int)((double)nminterms * min1 / (min1 + min2) + 0.5); - for (i = 0; i < t; i++) - string[i][N->index] = '1'; - for (i = t; i < nminterms; i++) - string[i][N->index] = '0'; - - result = ddPickArbitraryMinterms(dd,T,nvars,t,&string[0]); - if (result == 0) - return(0); - result = ddPickArbitraryMinterms(dd,E,nvars,nminterms-t,&string[t]); - return(result); - -} /* end of ddPickArbitraryMinterms */ - - -/**Function******************************************************************** - - Synopsis [Finds a representative cube of a BDD.] - - Description [Finds a representative cube of a BDD with the weight of - each variable. From the top variable, if the weight is greater than or - equal to 0.0, choose THEN branch unless the child is the constant 0. - Otherwise, choose ELSE branch unless the child is the constant 0.] - - SideEffects [Cudd_SubsetWithMaskVars Cudd_bddPickOneCube] - -******************************************************************************/ -static int -ddPickRepresentativeCube( - DdManager *dd, - DdNode *node, - int nvars, - double *weight, - char *string) -{ - DdNode *N, *T, *E; - DdNode *one, *bzero; - - if (string == NULL || node == NULL) return(0); - - /* The constant 0 function has no on-set cubes. */ - one = DD_ONE(dd); - bzero = Cudd_Not(one); - if (node == bzero) return(0); - - if (node == DD_ONE(dd)) return(1); - - for (;;) { - N = Cudd_Regular(node); - if (N == one) - break; - T = cuddT(N); - E = cuddE(N); - if (Cudd_IsComplement(node)) { - T = Cudd_Not(T); - E = Cudd_Not(E); - } - if (weight[N->index] >= 0.0) { - if (T == bzero) { - node = E; - string[N->index] = '0'; - } else { - node = T; - string[N->index] = '1'; - } - } else { - if (E == bzero) { - node = T; - string[N->index] = '1'; - } else { - node = E; - string[N->index] = '0'; - } - } - } - return(1); - -} /* end of ddPickRepresentativeCube */ - - -/**Function******************************************************************** - - Synopsis [Frees the memory used to store the minterm counts recorded - in the visited table.] - - Description [Frees the memory used to store the minterm counts - recorded in the visited table. Returns ST_CONTINUE.] - - SideEffects [None] - -******************************************************************************/ -static enum st_retval -ddEpdFree( - char * key, - char * value, - char * arg) -{ - EpDouble *epd; - - epd = (EpDouble *) value; - EpdFree(epd); - return(ST_CONTINUE); - -} /* end of ddEpdFree */ diff --git a/src/bdd/cudd/cuddWindow.c b/src/bdd/cudd/cuddWindow.c deleted file mode 100644 index 9ceb79b2..00000000 --- a/src/bdd/cudd/cuddWindow.c +++ /dev/null @@ -1,997 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddWindow.c] - - PackageName [cudd] - - Synopsis [Functions for window permutation] - - Description [Internal procedures included in this module: - <ul> - <li> cuddWindowReorder() - </ul> - Static procedures included in this module: - <ul> - <li> ddWindow2() - <li> ddWindowConv2() - <li> ddPermuteWindow3() - <li> ddWindow3() - <li> ddWindowConv3() - <li> ddPermuteWindow4() - <li> ddWindow4() - <li> ddWindowConv4() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddWindow.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -#ifdef DD_STATS -extern int ddTotalNumberSwapping; -extern int ddTotalNISwaps; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddWindow2 ARGS((DdManager *table, int low, int high)); -static int ddWindowConv2 ARGS((DdManager *table, int low, int high)); -static int ddPermuteWindow3 ARGS((DdManager *table, int x)); -static int ddWindow3 ARGS((DdManager *table, int low, int high)); -static int ddWindowConv3 ARGS((DdManager *table, int low, int high)); -static int ddPermuteWindow4 ARGS((DdManager *table, int w)); -static int ddWindow4 ARGS((DdManager *table, int low, int high)); -static int ddWindowConv4 ARGS((DdManager *table, int low, int high)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Reorders by applying the method of the sliding window.] - - Description [Reorders by applying the method of the sliding window. - Tries all possible permutations to the variables in a window that - slides from low to high. The size of the window is determined by - submethod. Assumes that no dead nodes are present. Returns 1 in - case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddWindowReorder( - DdManager * table /* DD table */, - int low /* lowest index to reorder */, - int high /* highest index to reorder */, - Cudd_ReorderingType submethod /* window reordering option */) -{ - - int res; -#ifdef DD_DEBUG - int supposedOpt; -#endif - - switch (submethod) { - case CUDD_REORDER_WINDOW2: - res = ddWindow2(table,low,high); - break; - case CUDD_REORDER_WINDOW3: - res = ddWindow3(table,low,high); - break; - case CUDD_REORDER_WINDOW4: - res = ddWindow4(table,low,high); - break; - case CUDD_REORDER_WINDOW2_CONV: - res = ddWindowConv2(table,low,high); - break; - case CUDD_REORDER_WINDOW3_CONV: - res = ddWindowConv3(table,low,high); -#ifdef DD_DEBUG - supposedOpt = table->keys - table->isolated; - res = ddWindow3(table,low,high); - if (table->keys - table->isolated != (unsigned) supposedOpt) { - (void) fprintf(table->err, "Convergence failed! (%d != %d)\n", - table->keys - table->isolated, supposedOpt); - } -#endif - break; - case CUDD_REORDER_WINDOW4_CONV: - res = ddWindowConv4(table,low,high); -#ifdef DD_DEBUG - supposedOpt = table->keys - table->isolated; - res = ddWindow4(table,low,high); - if (table->keys - table->isolated != (unsigned) supposedOpt) { - (void) fprintf(table->err,"Convergence failed! (%d != %d)\n", - table->keys - table->isolated, supposedOpt); - } -#endif - break; - default: return(0); - } - - return(res); - -} /* end of cuddWindowReorder */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Reorders by applying a sliding window of width 2.] - - Description [Reorders by applying a sliding window of width 2. - Tries both permutations of the variables in a window - that slides from low to high. Assumes that no dead nodes are - present. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindow2( - DdManager * table, - int low, - int high) -{ - - int x; - int res; - int size; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 1) return(0); - - res = table->keys - table->isolated; - for (x = low; x < high; x++) { - size = res; - res = cuddSwapInPlace(table,x,x+1); - if (res == 0) return(0); - if (res >= size) { /* no improvement: undo permutation */ - res = cuddSwapInPlace(table,x,x+1); - if (res == 0) return(0); - } -#ifdef DD_STATS - if (res < size) { - (void) fprintf(table->out,"-"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - return(1); - -} /* end of ddWindow2 */ - - -/**Function******************************************************************** - - Synopsis [Reorders by repeatedly applying a sliding window of width 2.] - - Description [Reorders by repeatedly applying a sliding window of width - 2. Tries both permutations of the variables in a window - that slides from low to high. Assumes that no dead nodes are - present. Uses an event-driven approach to determine convergence. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindowConv2( - DdManager * table, - int low, - int high) -{ - int x; - int res; - int nwin; - int newevent; - int *events; - int size; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 1) return(ddWindowConv2(table,low,high)); - - nwin = high-low; - events = ALLOC(int,nwin); - if (events == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (x=0; x<nwin; x++) { - events[x] = 1; - } - - res = table->keys - table->isolated; - do { - newevent = 0; - for (x=0; x<nwin; x++) { - if (events[x]) { - size = res; - res = cuddSwapInPlace(table,x+low,x+low+1); - if (res == 0) { - FREE(events); - return(0); - } - if (res >= size) { /* no improvement: undo permutation */ - res = cuddSwapInPlace(table,x+low,x+low+1); - if (res == 0) { - FREE(events); - return(0); - } - } - if (res < size) { - if (x < nwin-1) events[x+1] = 1; - if (x > 0) events[x-1] = 1; - newevent = 1; - } - events[x] = 0; -#ifdef DD_STATS - if (res < size) { - (void) fprintf(table->out,"-"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } -#ifdef DD_STATS - if (newevent) { - (void) fprintf(table->out,"|"); - fflush(table->out); - } -#endif - } while (newevent); - - FREE(events); - - return(1); - -} /* end of ddWindowConv3 */ - - -/**Function******************************************************************** - - Synopsis [Tries all the permutations of the three variables between - x and x+2 and retains the best.] - - Description [Tries all the permutations of the three variables between - x and x+2 and retains the best. Assumes that no dead nodes are - present. Returns the index of the best permutation (1-6) in case of - success; 0 otherwise.Assumes that no dead nodes are present. Returns - the index of the best permutation (1-6) in case of success; 0 - otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddPermuteWindow3( - DdManager * table, - int x) -{ - int y,z; - int size,sizeNew; - int best; - -#ifdef DD_DEBUG - assert(table->dead == 0); - assert(x+2 < table->size); -#endif - - size = table->keys - table->isolated; - y = x+1; z = y+1; - - /* The permutation pattern is: - ** (x,y)(y,z) - ** repeated three times to get all 3! = 6 permutations. - */ -#define ABC 1 - best = ABC; - -#define BAC 2 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = BAC; - size = sizeNew; - } -#define BCA 3 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = BCA; - size = sizeNew; - } -#define CBA 4 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = CBA; - size = sizeNew; - } -#define CAB 5 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = CAB; - size = sizeNew; - } -#define ACB 6 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = ACB; - size = sizeNew; - } - - /* Now take the shortest route to the best permuytation. - ** The initial permutation is ACB. - */ - switch(best) { - case BCA: if (!cuddSwapInPlace(table,y,z)) return(0); - case CBA: if (!cuddSwapInPlace(table,x,y)) return(0); - case ABC: if (!cuddSwapInPlace(table,y,z)) return(0); - case ACB: break; - case BAC: if (!cuddSwapInPlace(table,y,z)) return(0); - case CAB: if (!cuddSwapInPlace(table,x,y)) return(0); - break; - default: return(0); - } - -#ifdef DD_DEBUG - assert(table->keys - table->isolated == (unsigned) size); -#endif - - return(best); - -} /* end of ddPermuteWindow3 */ - - -/**Function******************************************************************** - - Synopsis [Reorders by applying a sliding window of width 3.] - - Description [Reorders by applying a sliding window of width 3. - Tries all possible permutations to the variables in a - window that slides from low to high. Assumes that no dead nodes are - present. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindow3( - DdManager * table, - int low, - int high) -{ - - int x; - int res; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 2) return(ddWindow2(table,low,high)); - - for (x = low; x+1 < high; x++) { - res = ddPermuteWindow3(table,x); - if (res == 0) return(0); -#ifdef DD_STATS - if (res == ABC) { - (void) fprintf(table->out,"="); - } else { - (void) fprintf(table->out,"-"); - } - fflush(table->out); -#endif - } - - return(1); - -} /* end of ddWindow3 */ - - -/**Function******************************************************************** - - Synopsis [Reorders by repeatedly applying a sliding window of width 3.] - - Description [Reorders by repeatedly applying a sliding window of width - 3. Tries all possible permutations to the variables in a - window that slides from low to high. Assumes that no dead nodes are - present. Uses an event-driven approach to determine convergence. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindowConv3( - DdManager * table, - int low, - int high) -{ - int x; - int res; - int nwin; - int newevent; - int *events; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 2) return(ddWindowConv2(table,low,high)); - - nwin = high-low-1; - events = ALLOC(int,nwin); - if (events == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (x=0; x<nwin; x++) { - events[x] = 1; - } - - do { - newevent = 0; - for (x=0; x<nwin; x++) { - if (events[x]) { - res = ddPermuteWindow3(table,x+low); - switch (res) { - case ABC: - break; - case BAC: - if (x < nwin-1) events[x+1] = 1; - if (x > 1) events[x-2] = 1; - newevent = 1; - break; - case BCA: - case CBA: - case CAB: - if (x < nwin-2) events[x+2] = 1; - if (x < nwin-1) events[x+1] = 1; - if (x > 0) events[x-1] = 1; - if (x > 1) events[x-2] = 1; - newevent = 1; - break; - case ACB: - if (x < nwin-2) events[x+2] = 1; - if (x > 0) events[x-1] = 1; - newevent = 1; - break; - default: - FREE(events); - return(0); - } - events[x] = 0; -#ifdef DD_STATS - if (res == ABC) { - (void) fprintf(table->out,"="); - } else { - (void) fprintf(table->out,"-"); - } - fflush(table->out); -#endif - } - } -#ifdef DD_STATS - if (newevent) { - (void) fprintf(table->out,"|"); - fflush(table->out); - } -#endif - } while (newevent); - - FREE(events); - - return(1); - -} /* end of ddWindowConv3 */ - - -/**Function******************************************************************** - - Synopsis [Tries all the permutations of the four variables between w - and w+3 and retains the best.] - - Description [Tries all the permutations of the four variables between - w and w+3 and retains the best. Assumes that no dead nodes are - present. Returns the index of the best permutation (1-24) in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddPermuteWindow4( - DdManager * table, - int w) -{ - int x,y,z; - int size,sizeNew; - int best; - -#ifdef DD_DEBUG - assert(table->dead == 0); - assert(w+3 < table->size); -#endif - - size = table->keys - table->isolated; - x = w+1; y = x+1; z = y+1; - - /* The permutation pattern is: - * (w,x)(y,z)(w,x)(x,y) - * (y,z)(w,x)(y,z)(x,y) - * repeated three times to get all 4! = 24 permutations. - * This gives a hamiltonian circuit of Cayley's graph. - * The codes to the permutation are assigned in topological order. - * The permutations at lower distance from the final permutation are - * assigned lower codes. This way we can choose, between - * permutations that give the same size, one that requires the minimum - * number of swaps from the final permutation of the hamiltonian circuit. - * There is an exception to this rule: ABCD is given Code 1, to - * avoid oscillation when convergence is sought. - */ -#define ABCD 1 - best = ABCD; - -#define BACD 7 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = BACD; - size = sizeNew; - } -#define BADC 13 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = BADC; - size = sizeNew; - } -#define ABDC 8 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && ABDC < best)) { - if (sizeNew == 0) return(0); - best = ABDC; - size = sizeNew; - } -#define ADBC 14 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = ADBC; - size = sizeNew; - } -#define ADCB 9 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && ADCB < best)) { - if (sizeNew == 0) return(0); - best = ADCB; - size = sizeNew; - } -#define DACB 15 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = DACB; - size = sizeNew; - } -#define DABC 20 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = DABC; - size = sizeNew; - } -#define DBAC 23 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = DBAC; - size = sizeNew; - } -#define BDAC 19 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && BDAC < best)) { - if (sizeNew == 0) return(0); - best = BDAC; - size = sizeNew; - } -#define BDCA 21 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && BDCA < best)) { - if (sizeNew == 0) return(0); - best = BDCA; - size = sizeNew; - } -#define DBCA 24 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = DBCA; - size = sizeNew; - } -#define DCBA 22 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size || (sizeNew == size && DCBA < best)) { - if (sizeNew == 0) return(0); - best = DCBA; - size = sizeNew; - } -#define DCAB 18 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && DCAB < best)) { - if (sizeNew == 0) return(0); - best = DCAB; - size = sizeNew; - } -#define CDAB 12 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && CDAB < best)) { - if (sizeNew == 0) return(0); - best = CDAB; - size = sizeNew; - } -#define CDBA 17 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && CDBA < best)) { - if (sizeNew == 0) return(0); - best = CDBA; - size = sizeNew; - } -#define CBDA 11 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size || (sizeNew == size && CBDA < best)) { - if (sizeNew == 0) return(0); - best = CBDA; - size = sizeNew; - } -#define BCDA 16 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && BCDA < best)) { - if (sizeNew == 0) return(0); - best = BCDA; - size = sizeNew; - } -#define BCAD 10 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && BCAD < best)) { - if (sizeNew == 0) return(0); - best = BCAD; - size = sizeNew; - } -#define CBAD 5 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && CBAD < best)) { - if (sizeNew == 0) return(0); - best = CBAD; - size = sizeNew; - } -#define CABD 3 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size || (sizeNew == size && CABD < best)) { - if (sizeNew == 0) return(0); - best = CABD; - size = sizeNew; - } -#define CADB 6 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && CADB < best)) { - if (sizeNew == 0) return(0); - best = CADB; - size = sizeNew; - } -#define ACDB 4 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && ACDB < best)) { - if (sizeNew == 0) return(0); - best = ACDB; - size = sizeNew; - } -#define ACBD 2 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && ACBD < best)) { - if (sizeNew == 0) return(0); - best = ACBD; - size = sizeNew; - } - - /* Now take the shortest route to the best permutation. - ** The initial permutation is ACBD. - */ - switch(best) { - case DBCA: if (!cuddSwapInPlace(table,y,z)) return(0); - case BDCA: if (!cuddSwapInPlace(table,x,y)) return(0); - case CDBA: if (!cuddSwapInPlace(table,w,x)) return(0); - case ADBC: if (!cuddSwapInPlace(table,y,z)) return(0); - case ABDC: if (!cuddSwapInPlace(table,x,y)) return(0); - case ACDB: if (!cuddSwapInPlace(table,y,z)) return(0); - case ACBD: break; - case DCBA: if (!cuddSwapInPlace(table,y,z)) return(0); - case BCDA: if (!cuddSwapInPlace(table,x,y)) return(0); - case CBDA: if (!cuddSwapInPlace(table,w,x)) return(0); - if (!cuddSwapInPlace(table,x,y)) return(0); - if (!cuddSwapInPlace(table,y,z)) return(0); - break; - case DBAC: if (!cuddSwapInPlace(table,x,y)) return(0); - case DCAB: if (!cuddSwapInPlace(table,w,x)) return(0); - case DACB: if (!cuddSwapInPlace(table,y,z)) return(0); - case BACD: if (!cuddSwapInPlace(table,x,y)) return(0); - case CABD: if (!cuddSwapInPlace(table,w,x)) return(0); - break; - case DABC: if (!cuddSwapInPlace(table,y,z)) return(0); - case BADC: if (!cuddSwapInPlace(table,x,y)) return(0); - case CADB: if (!cuddSwapInPlace(table,w,x)) return(0); - if (!cuddSwapInPlace(table,y,z)) return(0); - break; - case BDAC: if (!cuddSwapInPlace(table,x,y)) return(0); - case CDAB: if (!cuddSwapInPlace(table,w,x)) return(0); - case ADCB: if (!cuddSwapInPlace(table,y,z)) return(0); - case ABCD: if (!cuddSwapInPlace(table,x,y)) return(0); - break; - case BCAD: if (!cuddSwapInPlace(table,x,y)) return(0); - case CBAD: if (!cuddSwapInPlace(table,w,x)) return(0); - if (!cuddSwapInPlace(table,x,y)) return(0); - break; - default: return(0); - } - -#ifdef DD_DEBUG - assert(table->keys - table->isolated == (unsigned) size); -#endif - - return(best); - -} /* end of ddPermuteWindow4 */ - - -/**Function******************************************************************** - - Synopsis [Reorders by applying a sliding window of width 4.] - - Description [Reorders by applying a sliding window of width 4. - Tries all possible permutations to the variables in a - window that slides from low to high. Assumes that no dead nodes are - present. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindow4( - DdManager * table, - int low, - int high) -{ - - int w; - int res; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 3) return(ddWindow3(table,low,high)); - - for (w = low; w+2 < high; w++) { - res = ddPermuteWindow4(table,w); - if (res == 0) return(0); -#ifdef DD_STATS - if (res == ABCD) { - (void) fprintf(table->out,"="); - } else { - (void) fprintf(table->out,"-"); - } - fflush(table->out); -#endif - } - - return(1); - -} /* end of ddWindow4 */ - - -/**Function******************************************************************** - - Synopsis [Reorders by repeatedly applying a sliding window of width 4.] - - Description [Reorders by repeatedly applying a sliding window of width - 4. Tries all possible permutations to the variables in a - window that slides from low to high. Assumes that no dead nodes are - present. Uses an event-driven approach to determine convergence. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindowConv4( - DdManager * table, - int low, - int high) -{ - int x; - int res; - int nwin; - int newevent; - int *events; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 3) return(ddWindowConv3(table,low,high)); - - nwin = high-low-2; - events = ALLOC(int,nwin); - if (events == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (x=0; x<nwin; x++) { - events[x] = 1; - } - - do { - newevent = 0; - for (x=0; x<nwin; x++) { - if (events[x]) { - res = ddPermuteWindow4(table,x+low); - switch (res) { - case ABCD: - break; - case BACD: - if (x < nwin-1) events[x+1] = 1; - if (x > 2) events[x-3] = 1; - newevent = 1; - break; - case BADC: - if (x < nwin-3) events[x+3] = 1; - if (x < nwin-1) events[x+1] = 1; - if (x > 0) events[x-1] = 1; - if (x > 2) events[x-3] = 1; - newevent = 1; - break; - case ABDC: - if (x < nwin-3) events[x+3] = 1; - if (x > 0) events[x-1] = 1; - newevent = 1; - break; - case ADBC: - case ADCB: - case ACDB: - if (x < nwin-3) events[x+3] = 1; - if (x < nwin-2) events[x+2] = 1; - if (x > 0) events[x-1] = 1; - if (x > 1) events[x-2] = 1; - newevent = 1; - break; - case DACB: - case DABC: - case DBAC: - case BDAC: - case BDCA: - case DBCA: - case DCBA: - case DCAB: - case CDAB: - case CDBA: - case CBDA: - case BCDA: - case CADB: - if (x < nwin-3) events[x+3] = 1; - if (x < nwin-2) events[x+2] = 1; - if (x < nwin-1) events[x+1] = 1; - if (x > 0) events[x-1] = 1; - if (x > 1) events[x-2] = 1; - if (x > 2) events[x-3] = 1; - newevent = 1; - break; - case BCAD: - case CBAD: - case CABD: - if (x < nwin-2) events[x+2] = 1; - if (x < nwin-1) events[x+1] = 1; - if (x > 1) events[x-2] = 1; - if (x > 2) events[x-3] = 1; - newevent = 1; - break; - case ACBD: - if (x < nwin-2) events[x+2] = 1; - if (x > 1) events[x-2] = 1; - newevent = 1; - break; - default: - FREE(events); - return(0); - } - events[x] = 0; -#ifdef DD_STATS - if (res == ABCD) { - (void) fprintf(table->out,"="); - } else { - (void) fprintf(table->out,"-"); - } - fflush(table->out); -#endif - } - } -#ifdef DD_STATS - if (newevent) { - (void) fprintf(table->out,"|"); - fflush(table->out); - } -#endif - } while (newevent); - - FREE(events); - - return(1); - -} /* end of ddWindowConv4 */ - diff --git a/src/bdd/cudd/cuddZddCount.c b/src/bdd/cudd/cuddZddCount.c deleted file mode 100644 index 6c6ec1df..00000000 --- a/src/bdd/cudd/cuddZddCount.c +++ /dev/null @@ -1,324 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddCount.c] - - PackageName [cudd] - - Synopsis [Procedures to count the number of minterms of a ZDD.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_zddCount(); - <li> Cudd_zddCountDouble(); - </ul> - Internal procedures included in this module: - <ul> - </ul> - Static procedures included in this module: - <ul> - <li> cuddZddCountStep(); - <li> cuddZddCountDoubleStep(); - <li> st_zdd_count_dbl_free() - <li> st_zdd_countfree() - </ul> - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddCount.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int cuddZddCountStep ARGS((DdNode *P, st_table *table, DdNode *base, DdNode *empty)); -static double cuddZddCountDoubleStep ARGS((DdNode *P, st_table *table, DdNode *base, DdNode *empty)); -static enum st_retval st_zdd_countfree ARGS((char *key, char *value, char *arg)); -static enum st_retval st_zdd_count_dbl_free ARGS((char *key, char *value, char *arg)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms in a ZDD.] - - Description [Returns an integer representing the number of minterms - in a ZDD.] - - SideEffects [None] - - SeeAlso [Cudd_zddCountDouble] - -******************************************************************************/ -int -Cudd_zddCount( - DdManager * zdd, - DdNode * P) -{ - st_table *table; - int res; - DdNode *base, *empty; - - base = DD_ONE(zdd); - empty = DD_ZERO(zdd); - table = st_init_table(st_ptrcmp, st_ptrhash); - if (table == NULL) return(CUDD_OUT_OF_MEM); - res = cuddZddCountStep(P, table, base, empty); - if (res == CUDD_OUT_OF_MEM) { - zdd->errorCode = CUDD_MEMORY_OUT; - } - st_foreach(table, st_zdd_countfree, NIL(char)); - st_free_table(table); - - return(res); - -} /* end of Cudd_zddCount */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms of a ZDD.] - - Description [Counts the number of minterms of a ZDD. The result is - returned as a double. If the procedure runs out of memory, it - returns (double) CUDD_OUT_OF_MEM. This procedure is used in - Cudd_zddCountMinterm.] - - SideEffects [None] - - SeeAlso [Cudd_zddCountMinterm Cudd_zddCount] - -******************************************************************************/ -double -Cudd_zddCountDouble( - DdManager * zdd, - DdNode * P) -{ - st_table *table; - double res; - DdNode *base, *empty; - - base = DD_ONE(zdd); - empty = DD_ZERO(zdd); - table = st_init_table(st_ptrcmp, st_ptrhash); - if (table == NULL) return((double)CUDD_OUT_OF_MEM); - res = cuddZddCountDoubleStep(P, table, base, empty); - if (res == (double)CUDD_OUT_OF_MEM) { - zdd->errorCode = CUDD_MEMORY_OUT; - } - st_foreach(table, st_zdd_count_dbl_free, NIL(char)); - st_free_table(table); - - return(res); - -} /* end of Cudd_zddCountDouble */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddCount.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddCountStep( - DdNode * P, - st_table * table, - DdNode * base, - DdNode * empty) -{ - int res; - int *dummy; - - if (P == empty) - return(0); - if (P == base) - return(1); - - /* Check cache. */ - if (st_lookup(table, (char *)P, (char **)(&dummy))) { - res = *dummy; - return(res); - } - - res = cuddZddCountStep(cuddE(P), table, base, empty) + - cuddZddCountStep(cuddT(P), table, base, empty); - - dummy = ALLOC(int, 1); - if (dummy == NULL) { - return(CUDD_OUT_OF_MEM); - } - *dummy = res; - if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) { - FREE(dummy); - return(CUDD_OUT_OF_MEM); - } - - return(res); - -} /* end of cuddZddCountStep */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddCountDouble.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static double -cuddZddCountDoubleStep( - DdNode * P, - st_table * table, - DdNode * base, - DdNode * empty) -{ - double res; - double *dummy; - - if (P == empty) - return((double)0.0); - if (P == base) - return((double)1.0); - - /* Check cache */ - if (st_lookup(table, (char *)P, (char **)(&dummy))) { - res = *dummy; - return(res); - } - - res = cuddZddCountDoubleStep(cuddE(P), table, base, empty) + - cuddZddCountDoubleStep(cuddT(P), table, base, empty); - - dummy = ALLOC(double, 1); - if (dummy == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - *dummy = res; - if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) { - FREE(dummy); - return((double)CUDD_OUT_OF_MEM); - } - - return(res); - -} /* end of cuddZddCountDoubleStep */ - - -/**Function******************************************************************** - - Synopsis [Frees the memory associated with the computed table of - Cudd_zddCount.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static enum st_retval -st_zdd_countfree( - char * key, - char * value, - char * arg) -{ - int *d; - - d = (int *)value; - FREE(d); - return(ST_CONTINUE); - -} /* end of st_zdd_countfree */ - - -/**Function******************************************************************** - - Synopsis [Frees the memory associated with the computed table of - Cudd_zddCountDouble.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static enum st_retval -st_zdd_count_dbl_free( - char * key, - char * value, - char * arg) -{ - double *d; - - d = (double *)value; - FREE(d); - return(ST_CONTINUE); - -} /* end of st_zdd_count_dbl_free */ diff --git a/src/bdd/cudd/cuddZddFuncs.c b/src/bdd/cudd/cuddZddFuncs.c deleted file mode 100644 index 9dc27a95..00000000 --- a/src/bdd/cudd/cuddZddFuncs.c +++ /dev/null @@ -1,1603 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddFuncs.c] - - PackageName [cudd] - - Synopsis [Functions to manipulate covers represented as ZDDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_zddProduct(); - <li> Cudd_zddUnateProduct(); - <li> Cudd_zddWeakDiv(); - <li> Cudd_zddWeakDivF(); - <li> Cudd_zddDivide(); - <li> Cudd_zddDivideF(); - <li> Cudd_zddComplement(); - </ul> - Internal procedures included in this module: - <ul> - <li> cuddZddProduct(); - <li> cuddZddUnateProduct(); - <li> cuddZddWeakDiv(); - <li> cuddZddWeakDivF(); - <li> cuddZddDivide(); - <li> cuddZddDivideF(); - <li> cuddZddGetCofactors3() - <li> cuddZddGetCofactors2() - <li> cuddZddComplement(); - <li> cuddZddGetPosVarIndex(); - <li> cuddZddGetNegVarIndex(); - <li> cuddZddGetPosVarLevel(); - <li> cuddZddGetNegVarLevel(); - </ul> - Static procedures included in this module: - <ul> - </ul> - ] - - SeeAlso [] - - Author [In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddFuncs.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the product of two covers represented by ZDDs.] - - Description [Computes the product of two covers represented by - ZDDs. The result is also a ZDD. Returns a pointer to the result if - successful; NULL otherwise. The covers on which Cudd_zddProduct - operates use two ZDD variables for each function variable (one ZDD - variable for each literal of the variable). Those two ZDD variables - should be adjacent in the order.] - - SideEffects [None] - - SeeAlso [Cudd_zddUnateProduct] - -******************************************************************************/ -DdNode * -Cudd_zddProduct( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddProduct(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddProduct */ - - -/**Function******************************************************************** - - Synopsis [Computes the product of two unate covers.] - - Description [Computes the product of two unate covers represented as - ZDDs. Unate covers use one ZDD variable for each BDD - variable. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddProduct] - -******************************************************************************/ -DdNode * -Cudd_zddUnateProduct( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddUnateProduct(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddUnateProduct */ - - -/**Function******************************************************************** - - Synopsis [Applies weak division to two covers.] - - Description [Applies weak division to two ZDDs representing two - covers. Returns a pointer to the ZDD representing the result if - successful; NULL otherwise. The result of weak division depends on - the variable order. The covers on which Cudd_zddWeakDiv operates use - two ZDD variables for each function variable (one ZDD variable for - each literal of the variable). Those two ZDD variables should be - adjacent in the order.] - - SideEffects [None] - - SeeAlso [Cudd_zddDivide] - -******************************************************************************/ -DdNode * -Cudd_zddWeakDiv( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddWeakDiv(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddWeakDiv */ - - -/**Function******************************************************************** - - Synopsis [Computes the quotient of two unate covers.] - - Description [Computes the quotient of two unate covers represented - by ZDDs. Unate covers use one ZDD variable for each BDD - variable. Returns a pointer to the resulting ZDD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddWeakDiv] - -******************************************************************************/ -DdNode * -Cudd_zddDivide( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddDivide(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddDivide */ - - -/**Function******************************************************************** - - Synopsis [Modified version of Cudd_zddWeakDiv.] - - Description [Modified version of Cudd_zddWeakDiv. This function may - disappear in future releases.] - - SideEffects [None] - - SeeAlso [Cudd_zddWeakDiv] - -******************************************************************************/ -DdNode * -Cudd_zddWeakDivF( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddWeakDivF(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddWeakDivF */ - - -/**Function******************************************************************** - - Synopsis [Modified version of Cudd_zddDivide.] - - Description [Modified version of Cudd_zddDivide. This function may - disappear in future releases.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddDivideF( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddDivideF(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddDivideF */ - - -/**Function******************************************************************** - - Synopsis [Computes a complement cover for a ZDD node.] - - Description [Computes a complement cover for a ZDD node. For lack of a - better method, we first extract the function BDD from the ZDD cover, - then make the complement of the ZDD cover from the complement of the - BDD node by using ISOP. Returns a pointer to the resulting cover if - successful; NULL otherwise. The result depends on current variable - order.] - - SideEffects [The result depends on current variable order.] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddComplement( - DdManager *dd, - DdNode *node) -{ - DdNode *b, *isop, *zdd_I; - - /* Check cache */ - zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); - if (zdd_I) - return(zdd_I); - - b = Cudd_MakeBddFromZddCover(dd, node); - if (!b) - return(NULL); - Cudd_Ref(b); - isop = Cudd_zddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); - if (!isop) { - Cudd_RecursiveDeref(dd, b); - return(NULL); - } - Cudd_Ref(isop); - Cudd_Ref(zdd_I); - Cudd_RecursiveDeref(dd, b); - Cudd_RecursiveDeref(dd, isop); - - cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); - Cudd_Deref(zdd_I); - return(zdd_I); -} /* end of Cudd_zddComplement */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddProduct.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddProduct] - -******************************************************************************/ -DdNode * -cuddZddProduct( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v, top_f, top_g; - DdNode *tmp, *term1, *term2, *term3; - DdNode *f0, *f1, *fd, *g0, *g1, *gd; - DdNode *R0, *R1, *Rd, *N0, *N1; - DdNode *r; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - int flag; - int pv, nv; - - statLine(dd); - if (f == zero || g == zero) - return(zero); - if (f == one) - return(g); - if (g == one) - return(f); - - top_f = dd->permZ[f->index]; - top_g = dd->permZ[g->index]; - - if (top_f > top_g) - return(cuddZddProduct(dd, g, f)); - - /* Check cache */ - r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g); - if (r) - return(r); - - v = f->index; /* either yi or zi */ - flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - Cudd_Ref(fd); - flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - Cudd_Ref(gd); - pv = cuddZddGetPosVarIndex(dd, v); - nv = cuddZddGetNegVarIndex(dd, v); - - Rd = cuddZddProduct(dd, fd, gd); - if (Rd == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(Rd); - - term1 = cuddZddProduct(dd, f0, g0); - if (term1 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - return(NULL); - } - Cudd_Ref(term1); - term2 = cuddZddProduct(dd, f0, gd); - if (term2 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - Cudd_RecursiveDerefZdd(dd, term1); - return(NULL); - } - Cudd_Ref(term2); - term3 = cuddZddProduct(dd, fd, g0); - if (term3 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - return(NULL); - } - Cudd_Ref(term3); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g0); - tmp = cuddZddUnion(dd, term1, term2); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - Cudd_RecursiveDerefZdd(dd, term3); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - R0 = cuddZddUnion(dd, tmp, term3); - if (R0 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - Cudd_RecursiveDerefZdd(dd, term3); - Cudd_RecursiveDerefZdd(dd, tmp); - return(NULL); - } - Cudd_Ref(R0); - Cudd_RecursiveDerefZdd(dd, tmp); - Cudd_RecursiveDerefZdd(dd, term3); - N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */ - if (N0 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - Cudd_RecursiveDerefZdd(dd, R0); - return(NULL); - } - Cudd_Ref(N0); - Cudd_RecursiveDerefZdd(dd, R0); - Cudd_RecursiveDerefZdd(dd, Rd); - - term1 = cuddZddProduct(dd, f1, g1); - if (term1 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, N0); - return(NULL); - } - Cudd_Ref(term1); - term2 = cuddZddProduct(dd, f1, gd); - if (term2 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, N0); - Cudd_RecursiveDerefZdd(dd, term1); - return(NULL); - } - Cudd_Ref(term2); - term3 = cuddZddProduct(dd, fd, g1); - if (term3 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, N0); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - return(NULL); - } - Cudd_Ref(term3); - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - tmp = cuddZddUnion(dd, term1, term2); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, N0); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - Cudd_RecursiveDerefZdd(dd, term3); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - R1 = cuddZddUnion(dd, tmp, term3); - if (R1 == NULL) { - Cudd_RecursiveDerefZdd(dd, N0); - Cudd_RecursiveDerefZdd(dd, term3); - Cudd_RecursiveDerefZdd(dd, tmp); - return(NULL); - } - Cudd_Ref(R1); - Cudd_RecursiveDerefZdd(dd, tmp); - Cudd_RecursiveDerefZdd(dd, term3); - N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */ - if (N1 == NULL) { - Cudd_RecursiveDerefZdd(dd, N0); - Cudd_RecursiveDerefZdd(dd, R1); - return(NULL); - } - Cudd_Ref(N1); - Cudd_RecursiveDerefZdd(dd, R1); - Cudd_RecursiveDerefZdd(dd, N0); - - cuddCacheInsert2(dd, cuddZddProduct, f, g, N1); - Cudd_Deref(N1); - return(N1); - -} /* end of cuddZddProduct */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddUnateProduct.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddUnateProduct] - -******************************************************************************/ -DdNode * -cuddZddUnateProduct( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v, top_f, top_g; - DdNode *term1, *term2, *term3, *term4; - DdNode *sum1, *sum2; - DdNode *f0, *f1, *g0, *g1; - DdNode *r; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - int flag; - - statLine(dd); - if (f == zero || g == zero) - return(zero); - if (f == one) - return(g); - if (g == one) - return(f); - - top_f = dd->permZ[f->index]; - top_g = dd->permZ[g->index]; - - if (top_f > top_g) - return(cuddZddUnateProduct(dd, g, f)); - - /* Check cache */ - r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g); - if (r) - return(r); - - v = f->index; /* either yi or zi */ - flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - - term1 = cuddZddUnateProduct(dd, f1, g1); - if (term1 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - return(NULL); - } - Cudd_Ref(term1); - term2 = cuddZddUnateProduct(dd, f1, g0); - if (term2 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, term1); - return(NULL); - } - Cudd_Ref(term2); - term3 = cuddZddUnateProduct(dd, f0, g1); - if (term3 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - return(NULL); - } - Cudd_Ref(term3); - term4 = cuddZddUnateProduct(dd, f0, g0); - if (term4 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - Cudd_RecursiveDerefZdd(dd, term3); - return(NULL); - } - Cudd_Ref(term4); - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - sum1 = cuddZddUnion(dd, term1, term2); - if (sum1 == NULL) { - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - Cudd_RecursiveDerefZdd(dd, term3); - Cudd_RecursiveDerefZdd(dd, term4); - return(NULL); - } - Cudd_Ref(sum1); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - sum2 = cuddZddUnion(dd, sum1, term3); - if (sum2 == NULL) { - Cudd_RecursiveDerefZdd(dd, term3); - Cudd_RecursiveDerefZdd(dd, term4); - Cudd_RecursiveDerefZdd(dd, sum1); - return(NULL); - } - Cudd_Ref(sum2); - Cudd_RecursiveDerefZdd(dd, sum1); - Cudd_RecursiveDerefZdd(dd, term3); - r = cuddZddGetNode(dd, v, sum2, term4); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, term4); - Cudd_RecursiveDerefZdd(dd, sum2); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDerefZdd(dd, sum2); - Cudd_RecursiveDerefZdd(dd, term4); - - cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r); - Cudd_Deref(r); - return(r); - -} /* end of cuddZddUnateProduct */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddWeakDiv.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddWeakDiv] - -******************************************************************************/ -DdNode * -cuddZddWeakDiv( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - DdNode *f0, *f1, *fd, *g0, *g1, *gd; - DdNode *q, *tmp; - DdNode *r; - int flag; - - statLine(dd); - if (g == one) - return(f); - if (f == zero || f == one) - return(zero); - if (f == g) - return(one); - - /* Check cache. */ - r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g); - if (r) - return(r); - - v = g->index; - - flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - Cudd_Ref(fd); - flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - Cudd_Ref(gd); - - q = g; - - if (g0 != zero) { - q = cuddZddWeakDiv(dd, f0, g0); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(q); - } - else - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g0); - - if (q == zero) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); - Cudd_Deref(q); - return(zero); - } - - if (g1 != zero) { - Cudd_RecursiveDerefZdd(dd, q); - tmp = cuddZddWeakDiv(dd, f1, g1); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - if (q == g) - q = tmp; - else { - q = cuddZddIntersect(dd, q, tmp); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - } - else { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - } - - if (q == zero) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); - Cudd_Deref(q); - return(zero); - } - - if (gd != zero) { - Cudd_RecursiveDerefZdd(dd, q); - tmp = cuddZddWeakDiv(dd, fd, gd); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - if (q == g) - q = tmp; - else { - q = cuddZddIntersect(dd, q, tmp); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, tmp); - return(NULL); - } - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - } - else { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - } - - cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q); - Cudd_Deref(q); - return(q); - -} /* end of cuddZddWeakDiv */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddWeakDivF.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddWeakDivF] - -******************************************************************************/ -DdNode * -cuddZddWeakDivF( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v, top_f, top_g, vf, vg; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - DdNode *f0, *f1, *fd, *g0, *g1, *gd; - DdNode *q, *tmp; - DdNode *r; - DdNode *term1, *term0, *termd; - int flag; - int pv, nv; - - statLine(dd); - if (g == one) - return(f); - if (f == zero || f == one) - return(zero); - if (f == g) - return(one); - - /* Check cache. */ - r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g); - if (r) - return(r); - - top_f = dd->permZ[f->index]; - top_g = dd->permZ[g->index]; - vf = top_f >> 1; - vg = top_g >> 1; - v = ddMin(top_f, top_g); - - if (v == top_f && vf < vg) { - v = f->index; - flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - Cudd_Ref(fd); - - pv = cuddZddGetPosVarIndex(dd, v); - nv = cuddZddGetNegVarIndex(dd, v); - - term1 = cuddZddWeakDivF(dd, f1, g); - if (term1 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - return(NULL); - } - Cudd_Ref(term1); - Cudd_RecursiveDerefZdd(dd, f1); - term0 = cuddZddWeakDivF(dd, f0, g); - if (term0 == NULL) { - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, term1); - return(NULL); - } - Cudd_Ref(term0); - Cudd_RecursiveDerefZdd(dd, f0); - termd = cuddZddWeakDivF(dd, fd, g); - if (termd == NULL) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term0); - return(NULL); - } - Cudd_Ref(termd); - Cudd_RecursiveDerefZdd(dd, fd); - - tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */ - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term0); - Cudd_RecursiveDerefZdd(dd, termd); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, term0); - Cudd_RecursiveDerefZdd(dd, termd); - q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */ - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, tmp); - return(NULL); - } - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, tmp); - - cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); - Cudd_Deref(q); - return(q); - } - - if (v == top_f) - v = f->index; - else - v = g->index; - - flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - Cudd_Ref(fd); - flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - Cudd_Ref(gd); - - q = g; - - if (g0 != zero) { - q = cuddZddWeakDivF(dd, f0, g0); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(q); - } - else - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g0); - - if (q == zero) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); - Cudd_Deref(q); - return(zero); - } - - if (g1 != zero) { - Cudd_RecursiveDerefZdd(dd, q); - tmp = cuddZddWeakDivF(dd, f1, g1); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - if (q == g) - q = tmp; - else { - q = cuddZddIntersect(dd, q, tmp); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - } - else { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - } - - if (q == zero) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); - Cudd_Deref(q); - return(zero); - } - - if (gd != zero) { - Cudd_RecursiveDerefZdd(dd, q); - tmp = cuddZddWeakDivF(dd, fd, gd); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - if (q == g) - q = tmp; - else { - q = cuddZddIntersect(dd, q, tmp); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, tmp); - return(NULL); - } - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - } - else { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - } - - cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); - Cudd_Deref(q); - return(q); - -} /* end of cuddZddWeakDivF */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddDivide.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddDivide] - -******************************************************************************/ -DdNode * -cuddZddDivide( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - DdNode *f0, *f1, *g0, *g1; - DdNode *q, *r, *tmp; - int flag; - - statLine(dd); - if (g == one) - return(f); - if (f == zero || f == one) - return(zero); - if (f == g) - return(one); - - /* Check cache. */ - r = cuddCacheLookup2Zdd(dd, cuddZddDivide, f, g); - if (r) - return(r); - - v = g->index; - - flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - - r = cuddZddDivide(dd, f1, g1); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - return(NULL); - } - Cudd_Ref(r); - - if (r != zero && g0 != zero) { - tmp = r; - q = cuddZddDivide(dd, f0, g0); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - return(NULL); - } - Cudd_Ref(q); - r = cuddZddIntersect(dd, r, q); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, q); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDerefZdd(dd, q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - - cuddCacheInsert2(dd, cuddZddDivide, f, g, r); - Cudd_Deref(r); - return(r); - -} /* end of cuddZddDivide */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddDivideF.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddDivideF] - -******************************************************************************/ -DdNode * -cuddZddDivideF( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - DdNode *f0, *f1, *g0, *g1; - DdNode *q, *r, *tmp; - int flag; - - statLine(dd); - if (g == one) - return(f); - if (f == zero || f == one) - return(zero); - if (f == g) - return(one); - - /* Check cache. */ - r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g); - if (r) - return(r); - - v = g->index; - - flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - - r = cuddZddDivideF(dd, f1, g1); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - return(NULL); - } - Cudd_Ref(r); - - if (r != zero && g0 != zero) { - tmp = r; - q = cuddZddDivideF(dd, f0, g0); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - return(NULL); - } - Cudd_Ref(q); - r = cuddZddIntersect(dd, r, q); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, q); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDerefZdd(dd, q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - - cuddCacheInsert2(dd, cuddZddDivideF, f, g, r); - Cudd_Deref(r); - return(r); - -} /* end of cuddZddDivideF */ - - -/**Function******************************************************************** - - Synopsis [Computes the three-way decomposition of f w.r.t. v.] - - Description [Computes the three-way decomposition of function f (represented - by a ZDD) wit respect to variable v.] - - SideEffects [The results are returned in f1, f0, and fd.] - - SeeAlso [cuddZddGetCofactors2] - -******************************************************************************/ -int -cuddZddGetCofactors3( - DdManager * dd, - DdNode * f, - int v, - DdNode ** f1, - DdNode ** f0, - DdNode ** fd) -{ - DdNode *pc, *nc; - DdNode *zero = DD_ZERO(dd); - int top, hv, ht, pv, nv; - int level; - - top = dd->permZ[f->index]; - level = dd->permZ[v]; - hv = level >> 1; - ht = top >> 1; - - if (hv < ht) { - *f1 = zero; - *f0 = zero; - *fd = f; - } - else { - pv = cuddZddGetPosVarIndex(dd, v); - nv = cuddZddGetNegVarIndex(dd, v); - - /* not to create intermediate ZDD node */ - if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) { - pc = cuddZddSubset1(dd, f, pv); - if (pc == NULL) - return(1); - Cudd_Ref(pc); - nc = cuddZddSubset0(dd, f, pv); - if (nc == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - return(1); - } - Cudd_Ref(nc); - - *f1 = cuddZddSubset0(dd, pc, nv); - if (*f1 == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - return(1); - } - Cudd_Ref(*f1); - *f0 = cuddZddSubset1(dd, nc, nv); - if (*f0 == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - Cudd_RecursiveDerefZdd(dd, *f1); - return(1); - } - Cudd_Ref(*f0); - - *fd = cuddZddSubset0(dd, nc, nv); - if (*fd == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - Cudd_RecursiveDerefZdd(dd, *f1); - Cudd_RecursiveDerefZdd(dd, *f0); - return(1); - } - Cudd_Ref(*fd); - } else { - pc = cuddZddSubset1(dd, f, nv); - if (pc == NULL) - return(1); - Cudd_Ref(pc); - nc = cuddZddSubset0(dd, f, nv); - if (nc == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - return(1); - } - Cudd_Ref(nc); - - *f0 = cuddZddSubset0(dd, pc, pv); - if (*f0 == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - return(1); - } - Cudd_Ref(*f0); - *f1 = cuddZddSubset1(dd, nc, pv); - if (*f1 == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - Cudd_RecursiveDerefZdd(dd, *f1); - return(1); - } - Cudd_Ref(*f1); - - *fd = cuddZddSubset0(dd, nc, pv); - if (*fd == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - Cudd_RecursiveDerefZdd(dd, *f1); - Cudd_RecursiveDerefZdd(dd, *f0); - return(1); - } - Cudd_Ref(*fd); - } - - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - Cudd_Deref(*f1); - Cudd_Deref(*f0); - Cudd_Deref(*fd); - } - return(0); - -} /* end of cuddZddGetCofactors3 */ - - -/**Function******************************************************************** - - Synopsis [Computes the two-way decomposition of f w.r.t. v.] - - Description [] - - SideEffects [The results are returned in f1 and f0.] - - SeeAlso [cuddZddGetCofactors3] - -******************************************************************************/ -int -cuddZddGetCofactors2( - DdManager * dd, - DdNode * f, - int v, - DdNode ** f1, - DdNode ** f0) -{ - *f1 = cuddZddSubset1(dd, f, v); - if (*f1 == NULL) - return(1); - *f0 = cuddZddSubset0(dd, f, v); - if (*f0 == NULL) { - Cudd_RecursiveDerefZdd(dd, *f1); - return(1); - } - return(0); - -} /* end of cuddZddGetCofactors2 */ - - -/**Function******************************************************************** - - Synopsis [Computes a complement of a ZDD node.] - - Description [Computes the complement of a ZDD node. So far, since we - couldn't find a direct way to get the complement of a ZDD cover, we first - convert a ZDD cover to a BDD, then make the complement of the ZDD cover - from the complement of the BDD node by using ISOP.] - - SideEffects [The result depends on current variable order.] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddComplement( - DdManager * dd, - DdNode *node) -{ - DdNode *b, *isop, *zdd_I; - - /* Check cache */ - zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); - if (zdd_I) - return(zdd_I); - - b = cuddMakeBddFromZddCover(dd, node); - if (!b) - return(NULL); - cuddRef(b); - isop = cuddZddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); - if (!isop) { - Cudd_RecursiveDeref(dd, b); - return(NULL); - } - cuddRef(isop); - cuddRef(zdd_I); - Cudd_RecursiveDeref(dd, b); - Cudd_RecursiveDeref(dd, isop); - - cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); - cuddDeref(zdd_I); - return(zdd_I); -} /* end of cuddZddComplement */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of positive ZDD variable.] - - Description [Returns the index of positive ZDD variable.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddGetPosVarIndex( - DdManager * dd, - int index) -{ - int pv = (index >> 1) << 1; - return(pv); -} /* end of cuddZddGetPosVarIndex */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of negative ZDD variable.] - - Description [Returns the index of negative ZDD variable.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddGetNegVarIndex( - DdManager * dd, - int index) -{ - int nv = index | 0x1; - return(nv); -} /* end of cuddZddGetPosVarIndex */ - - -/**Function******************************************************************** - - Synopsis [Returns the level of positive ZDD variable.] - - Description [Returns the level of positive ZDD variable.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddGetPosVarLevel( - DdManager * dd, - int index) -{ - int pv = cuddZddGetPosVarIndex(dd, index); - return(dd->permZ[pv]); -} /* end of cuddZddGetPosVarLevel */ - - -/**Function******************************************************************** - - Synopsis [Returns the level of negative ZDD variable.] - - Description [Returns the level of negative ZDD variable.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddGetNegVarLevel( - DdManager * dd, - int index) -{ - int nv = cuddZddGetNegVarIndex(dd, index); - return(dd->permZ[nv]); -} /* end of cuddZddGetNegVarLevel */ diff --git a/src/bdd/cudd/cuddZddGroup.c b/src/bdd/cudd/cuddZddGroup.c deleted file mode 100644 index 621fa43f..00000000 --- a/src/bdd/cudd/cuddZddGroup.c +++ /dev/null @@ -1,1317 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddGroup.c] - - PackageName [cudd] - - Synopsis [Functions for ZDD group sifting.] - - Description [External procedures included in this file: - <ul> - <li> Cudd_MakeZddTreeNode() - </ul> - Internal procedures included in this file: - <ul> - <li> cuddZddTreeSifting() - </ul> - Static procedures included in this module: - <ul> - <li> zddTreeSiftingAux() - <li> zddCountInternalMtrNodes() - <li> zddReorderChildren() - <li> zddFindNodeHiLo() - <li> zddUniqueCompareGroup() - <li> zddGroupSifting() - <li> zddGroupSiftingAux() - <li> zddGroupSiftingUp() - <li> zddGroupSiftingDown() - <li> zddGroupMove() - <li> zddGroupMoveBackward() - <li> zddGroupSiftingBackward() - <li> zddMergeGroups() - </ul>] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -static int *entry; -extern int zddTotalNumberSwapping; -#ifdef DD_STATS -static int extsymmcalls; -static int extsymm; -static int secdiffcalls; -static int secdiff; -static int secdiffmisfire; -#endif -#ifdef DD_DEBUG -static int pr = 0; /* flag to enable printing while debugging */ - /* by depositing a 1 into it */ -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int zddTreeSiftingAux ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); -#ifdef DD_STATS -static int zddCountInternalMtrNodes ARGS((DdManager *table, MtrNode *treenode)); -#endif -static int zddReorderChildren ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); -static void zddFindNodeHiLo ARGS((DdManager *table, MtrNode *treenode, int *lower, int *upper)); -static int zddUniqueCompareGroup ARGS((int *ptrX, int *ptrY)); -static int zddGroupSifting ARGS((DdManager *table, int lower, int upper)); -static int zddGroupSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static int zddGroupSiftingUp ARGS((DdManager *table, int y, int xLow, Move **moves)); -static int zddGroupSiftingDown ARGS((DdManager *table, int x, int xHigh, Move **moves)); -static int zddGroupMove ARGS((DdManager *table, int x, int y, Move **moves)); -static int zddGroupMoveBackward ARGS((DdManager *table, int x, int y)); -static int zddGroupSiftingBackward ARGS((DdManager *table, Move *moves, int size)); -static void zddMergeGroups ARGS((DdManager *table, MtrNode *treenode, int low, int high)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Creates a new ZDD variable group.] - - Description [Creates a new ZDD variable group. The group starts at - variable and contains size variables. The parameter low is the index - of the first variable. If the variable already exists, its current - position in the order is known to the manager. If the variable does - not exist yet, the position is assumed to be the same as the index. - The group tree is created if it does not exist yet. - Returns a pointer to the group if successful; NULL otherwise.] - - SideEffects [The ZDD variable tree is changed.] - - SeeAlso [Cudd_MakeTreeNode] - -******************************************************************************/ -MtrNode * -Cudd_MakeZddTreeNode( - DdManager * dd /* manager */, - unsigned int low /* index of the first group variable */, - unsigned int size /* number of variables in the group */, - unsigned int type /* MTR_DEFAULT or MTR_FIXED */) -{ - MtrNode *group; - MtrNode *tree; - unsigned int level; - - /* If the variable does not exist yet, the position is assumed to be - ** the same as the index. Therefore, applications that rely on - ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new - ** variables have to create the variables before they group them. - */ - level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low; - - if (level + size - 1> (int) MTR_MAXHIGH) - return(NULL); - - /* If the tree does not exist yet, create it. */ - tree = dd->treeZ; - if (tree == NULL) { - dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ); - if (tree == NULL) - return(NULL); - tree->index = dd->invpermZ[0]; - } - - /* Extend the upper bound of the tree if necessary. This allows the - ** application to create groups even before the variables are created. - */ - tree->size = ddMax(tree->size, level + size); - - /* Create the group. */ - group = Mtr_MakeGroup(tree, level, size, type); - if (group == NULL) - return(NULL); - - /* Initialize the index field to the index of the variable currently - ** in position low. This field will be updated by the reordering - ** procedure to provide a handle to the group once it has been moved. - */ - group->index = (MtrHalfWord) low; - - return(group); - -} /* end of Cudd_MakeZddTreeNode */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Tree sifting algorithm for ZDDs.] - - Description [Tree sifting algorithm for ZDDs. Assumes that a tree - representing a group hierarchy is passed as a parameter. It then - reorders each group in postorder fashion by calling - zddTreeSiftingAux. Assumes that no dead nodes are present. Returns - 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddZddTreeSifting( - DdManager * table /* DD table */, - Cudd_ReorderingType method /* reordering method for the groups of leaves */) -{ - int i; - int nvars; - int result; - int tempTree; - - /* If no tree is provided we create a temporary one in which all - ** variables are in a single group. After reordering this tree is - ** destroyed. - */ - tempTree = table->treeZ == NULL; - if (tempTree) { - table->treeZ = Mtr_InitGroupTree(0,table->sizeZ); - table->treeZ->index = table->invpermZ[0]; - } - nvars = table->sizeZ; - -#ifdef DD_DEBUG - if (pr > 0 && !tempTree) - (void) fprintf(table->out,"cuddZddTreeSifting:"); - Mtr_PrintGroups(table->treeZ,pr <= 0); -#endif -#if 0 - /* Debugging code. */ - if (table->tree && table->treeZ) { - (void) fprintf(table->out,"\n"); - Mtr_PrintGroups(table->tree, 0); - cuddPrintVarGroups(table,table->tree,0,0); - for (i = 0; i < table->size; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->invperm[i]); - } - (void) fprintf(table->out,"\n"); - for (i = 0; i < table->size; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->perm[i]); - } - (void) fprintf(table->out,"\n\n"); - Mtr_PrintGroups(table->treeZ,0); - cuddPrintVarGroups(table,table->treeZ,1,0); - for (i = 0; i < table->sizeZ; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->invpermZ[i]); - } - (void) fprintf(table->out,"\n"); - for (i = 0; i < table->sizeZ; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->permZ[i]); - } - (void) fprintf(table->out,"\n"); - } - /* End of debugging code. */ -#endif -#ifdef DD_STATS - extsymmcalls = 0; - extsymm = 0; - secdiffcalls = 0; - secdiff = 0; - secdiffmisfire = 0; - - (void) fprintf(table->out,"\n"); - if (!tempTree) - (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", - zddCountInternalMtrNodes(table,table->treeZ)); -#endif - - /* Initialize the group of each subtable to itself. Initially - ** there are no groups. Groups are created according to the tree - ** structure in postorder fashion. - */ - for (i = 0; i < nvars; i++) - table->subtableZ[i].next = i; - - /* Reorder. */ - result = zddTreeSiftingAux(table, table->treeZ, method); - -#ifdef DD_STATS /* print stats */ - if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && - (table->groupcheck == CUDD_GROUP_CHECK7 || - table->groupcheck == CUDD_GROUP_CHECK5)) { - (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); - (void) fprintf(table->out,"extsymm = %d",extsymm); - } - if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && - table->groupcheck == CUDD_GROUP_CHECK7) { - (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); - (void) fprintf(table->out,"secdiff = %d\n",secdiff); - (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); - } -#endif - - if (tempTree) - Cudd_FreeZddTree(table); - return(result); - -} /* end of cuddZddTreeSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Visits the group tree and reorders each group.] - - Description [Recursively visits the group tree and reorders each - group in postorder fashion. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddTreeSiftingAux( - DdManager * table, - MtrNode * treenode, - Cudd_ReorderingType method) -{ - MtrNode *auxnode; - int res; - -#ifdef DD_DEBUG - Mtr_PrintGroups(treenode,1); -#endif - - auxnode = treenode; - while (auxnode != NULL) { - if (auxnode->child != NULL) { - if (!zddTreeSiftingAux(table, auxnode->child, method)) - return(0); - res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT); - if (res == 0) - return(0); - } else if (auxnode->size > 1) { - if (!zddReorderChildren(table, auxnode, method)) - return(0); - } - auxnode = auxnode->younger; - } - - return(1); - -} /* end of zddTreeSiftingAux */ - - -#ifdef DD_STATS -/**Function******************************************************************** - - Synopsis [Counts the number of internal nodes of the group tree.] - - Description [Counts the number of internal nodes of the group tree. - Returns the count.] - - SideEffects [None] - -******************************************************************************/ -static int -zddCountInternalMtrNodes( - DdManager * table, - MtrNode * treenode) -{ - MtrNode *auxnode; - int count,nodeCount; - - - nodeCount = 0; - auxnode = treenode; - while (auxnode != NULL) { - if (!(MTR_TEST(auxnode,MTR_TERMINAL))) { - nodeCount++; - count = zddCountInternalMtrNodes(table,auxnode->child); - nodeCount += count; - } - auxnode = auxnode->younger; - } - - return(nodeCount); - -} /* end of zddCountInternalMtrNodes */ -#endif - - -/**Function******************************************************************** - - Synopsis [Reorders the children of a group tree node according to - the options.] - - Description [Reorders the children of a group tree node according to - the options. After reordering puts all the variables in the group - and/or its descendents in a single group. This allows hierarchical - reordering. If the variables in the group do not exist yet, simply - does nothing. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddReorderChildren( - DdManager * table, - MtrNode * treenode, - Cudd_ReorderingType method) -{ - int lower; - int upper; - int result; - unsigned int initialSize; - - zddFindNodeHiLo(table,treenode,&lower,&upper); - /* If upper == -1 these variables do not exist yet. */ - if (upper == -1) - return(1); - - if (treenode->flags == MTR_FIXED) { - result = 1; - } else { -#ifdef DD_STATS - (void) fprintf(table->out," "); -#endif - switch (method) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - result = cuddZddSwapping(table,lower,upper,method); - break; - case CUDD_REORDER_SIFT: - result = cuddZddSifting(table,lower,upper); - break; - case CUDD_REORDER_SIFT_CONVERGE: - do { - initialSize = table->keysZ; - result = cuddZddSifting(table,lower,upper); - if (initialSize <= table->keysZ) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - case CUDD_REORDER_SYMM_SIFT: - result = cuddZddSymmSifting(table,lower,upper); - break; - case CUDD_REORDER_SYMM_SIFT_CONV: - result = cuddZddSymmSiftingConv(table,lower,upper); - break; - case CUDD_REORDER_GROUP_SIFT: - result = zddGroupSifting(table,lower,upper); - break; - case CUDD_REORDER_LINEAR: - result = cuddZddLinearSifting(table,lower,upper); - break; - case CUDD_REORDER_LINEAR_CONVERGE: - do { - initialSize = table->keysZ; - result = cuddZddLinearSifting(table,lower,upper); - if (initialSize <= table->keysZ) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - default: - return(0); - } - } - - /* Create a single group for all the variables that were sifted, - ** so that they will be treated as a single block by successive - ** invocations of zddGroupSifting. - */ - zddMergeGroups(table,treenode,lower,upper); - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:"); -#endif - - return(result); - -} /* end of zddReorderChildren */ - - -/**Function******************************************************************** - - Synopsis [Finds the lower and upper bounds of the group represented - by treenode.] - - Description [Finds the lower and upper bounds of the group represented - by treenode. The high and low fields of treenode are indices. From - those we need to derive the current positions, and find maximum and - minimum.] - - SideEffects [The bounds are returned as side effects.] - - SeeAlso [] - -******************************************************************************/ -static void -zddFindNodeHiLo( - DdManager * table, - MtrNode * treenode, - int * lower, - int * upper) -{ - int low; - int high; - - /* Check whether no variables in this group already exist. - ** If so, return immediately. The calling procedure will know from - ** the values of upper that no reordering is needed. - */ - if ((int) treenode->low >= table->sizeZ) { - *lower = table->sizeZ; - *upper = -1; - return; - } - - *lower = low = (unsigned int) table->permZ[treenode->index]; - high = (int) (low + treenode->size - 1); - - if (high >= table->sizeZ) { - /* This is the case of a partially existing group. The aim is to - ** reorder as many variables as safely possible. If the tree - ** node is terminal, we just reorder the subset of the group - ** that is currently in existence. If the group has - ** subgroups, then we only reorder those subgroups that are - ** fully instantiated. This way we avoid breaking up a group. - */ - MtrNode *auxnode = treenode->child; - if (auxnode == NULL) { - *upper = (unsigned int) table->sizeZ - 1; - } else { - /* Search the subgroup that strands the table->sizeZ line. - ** If the first group starts at 0 and goes past table->sizeZ - ** upper will get -1, thus correctly signaling that no reordering - ** should take place. - */ - while (auxnode != NULL) { - int thisLower = table->permZ[auxnode->low]; - int thisUpper = thisLower + auxnode->size - 1; - if (thisUpper >= table->sizeZ && thisLower < table->sizeZ) - *upper = (unsigned int) thisLower - 1; - auxnode = auxnode->younger; - } - } - } else { - /* Normal case: All the variables of the group exist. */ - *upper = (unsigned int) high; - } - -#ifdef DD_DEBUG - /* Make sure that all variables in group are contiguous. */ - assert(treenode->size >= *upper - *lower + 1); -#endif - - return; - -} /* end of zddFindNodeHiLo */ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the variables - according to the number of keys in the subtables. Returns the - difference in number of keys between the two variables being - compared.] - - SideEffects [None] - -******************************************************************************/ -static int -zddUniqueCompareGroup( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of zddUniqueCompareGroup */ - - -/**Function******************************************************************** - - Synopsis [Sifts from treenode->low to treenode->high.] - - Description [Sifts from treenode->low to treenode->high. If - croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the - end of the initial sifting. If a group is created, it is then sifted - again. After sifting one variable, the group that contains it is - dissolved. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSifting( - DdManager * table, - int lower, - int upper) -{ - int *var; - int i,j,x,xInit; - int nvars; - int classes; - int result; - int *sifted; -#ifdef DD_STATS - unsigned previousSize; -#endif - int xindex; - - nvars = table->sizeZ; - - /* Order variables to sift. */ - entry = NULL; - sifted = NULL; - var = ALLOC(int,nvars); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto zddGroupSiftingOutOfMem; - } - entry = ALLOC(int,nvars); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto zddGroupSiftingOutOfMem; - } - sifted = ALLOC(int,nvars); - if (sifted == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto zddGroupSiftingOutOfMem; - } - - /* Here we consider only one representative for each group. */ - for (i = 0, classes = 0; i < nvars; i++) { - sifted[i] = 0; - x = table->permZ[i]; - if ((unsigned) x >= table->subtableZ[x].next) { - entry[i] = table->subtableZ[x].keys; - var[classes] = i; - classes++; - } - } - - qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))zddUniqueCompareGroup); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - xindex = var[i]; - if (sifted[xindex] == 1) /* variable already sifted as part of group */ - continue; - x = table->permZ[xindex]; /* find current level of this variable */ - if (x < lower || x > upper) - continue; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif -#ifdef DD_DEBUG - /* x is bottom of group */ - assert((unsigned) x >= table->subtableZ[x].next); -#endif - result = zddGroupSiftingAux(table,x,lower,upper); - if (!result) goto zddGroupSiftingOutOfMem; - -#ifdef DD_STATS - if (table->keysZ < previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > previousSize) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - - /* Mark variables in the group just sifted. */ - x = table->permZ[xindex]; - if ((unsigned) x != table->subtableZ[x].next) { - xInit = x; - do { - j = table->invpermZ[x]; - sifted[j] = 1; - x = table->subtableZ[x].next; - } while (x != xInit); - } - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:"); -#endif - } /* for */ - - FREE(sifted); - FREE(var); - FREE(entry); - - return(1); - -zddGroupSiftingOutOfMem: - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - if (sifted != NULL) FREE(sifted); - - return(0); - -} /* end of zddGroupSifting */ - - -/**Function******************************************************************** - - Synopsis [Sifts one variable up and down until it has taken all - positions. Checks for aggregation.] - - Description [Sifts one variable up and down until it has taken all - positions. Checks for aggregation. There may be at most two sweeps, - even if the group grows. Assumes that x is either an isolated - variable, or it is the bottom of a group. All groups may not have - been found. The variable being moved is returned to the best position - seen during sifting. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - Move *move; - Move *moves; /* list of moves */ - int initialSize; - int result; - - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh); - assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */ -#endif - - initialSize = table->keysZ; - moves = NULL; - - if (x == xLow) { /* Sift down */ -#ifdef DD_DEBUG - /* x must be a singleton */ - assert((unsigned) x == table->subtableZ[x].next); -#endif - if (x == xHigh) return(1); /* just one variable */ - - if (!zddGroupSiftingDown(table,x,xHigh,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - - } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */ -#ifdef DD_DEBUG - /* x is bottom of group */ - assert((unsigned) x >= table->subtableZ[x].next); -#endif - /* Find top of x's group */ - x = table->subtableZ[x].next; - - if (!zddGroupSiftingUp(table,x,xLow,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xLow, unless early term */ - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - - } else if (x - xLow > xHigh - x) { /* must go down first: shorter */ - if (!zddGroupSiftingDown(table,x,xHigh,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - /* Find top of group */ - if (moves) { - x = moves->y; - } - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; -#ifdef DD_DEBUG - /* x should be the top of a group */ - assert((unsigned) x <= table->subtableZ[x].next); -#endif - - if (!zddGroupSiftingUp(table,x,xLow,&moves)) - goto zddGroupSiftingAuxOutOfMem; - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - - } else { /* moving up first: shorter */ - /* Find top of x's group */ - x = table->subtableZ[x].next; - - if (!zddGroupSiftingUp(table,x,xLow,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - if (moves) { - x = moves->x; - } - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; -#ifdef DD_DEBUG - /* x is bottom of a group */ - assert((unsigned) x >= table->subtableZ[x].next); -#endif - - if (!zddGroupSiftingDown(table,x,xHigh,&moves)) - goto zddGroupSiftingAuxOutOfMem; - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - } - - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(1); - -zddGroupSiftingAuxOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(0); - -} /* end of zddGroupSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts up a variable until either it reaches position xLow - or the size of the DD heap increases too much.] - - Description [Sifts up a variable until either it reaches position - xLow or the size of the DD heap increases too much. Assumes that y is - the top of a group (or a singleton). Checks y for aggregation to the - adjacent variables. Records all the moves that are appended to the - list of moves received as input and returned as a side effect. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingUp( - DdManager * table, - int y, - int xLow, - Move ** moves) -{ - Move *move; - int x; - int size; - int gxtop; - int limitSize; - int xindex, yindex; - - yindex = table->invpermZ[y]; - - limitSize = table->keysZ; - - x = cuddZddNextLow(table,y); - while (x >= xLow) { - gxtop = table->subtableZ[x].next; - if (table->subtableZ[x].next == (unsigned) x && - table->subtableZ[y].next == (unsigned) y) { - /* x and y are self groups */ - xindex = table->invpermZ[x]; - size = cuddZddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtableZ[x].next == (unsigned) x); - assert(table->subtableZ[y].next == (unsigned) y); -#endif - if (size == 0) goto zddGroupSiftingUpOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto zddGroupSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_DEFAULT; - move->size = size; - move->next = *moves; - *moves = move; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n"); -#endif - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } else { /* group move */ - size = zddGroupMove(table,x,y,moves); - if (size == 0) goto zddGroupSiftingUpOutOfMem; - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } - y = gxtop; - x = cuddZddNextLow(table,y); - } - - return(1); - -zddGroupSiftingUpOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - return(0); - -} /* end of zddGroupSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts down a variable until it reaches position xHigh.] - - Description [Sifts down a variable until it reaches position xHigh. - Assumes that x is the bottom of a group (or a singleton). Records - all the moves. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingDown( - DdManager * table, - int x, - int xHigh, - Move ** moves) -{ - Move *move; - int y; - int size; - int limitSize; - int gxtop,gybot; - int xindex; - - - /* Initialize R */ - xindex = table->invpermZ[x]; - gxtop = table->subtableZ[x].next; - limitSize = size = table->keysZ; - y = cuddZddNextHigh(table,x); - while (y <= xHigh) { - /* Find bottom of y group. */ - gybot = table->subtableZ[y].next; - while (table->subtableZ[gybot].next != (unsigned) y) - gybot = table->subtableZ[gybot].next; - - if (table->subtableZ[x].next == (unsigned) x && - table->subtableZ[y].next == (unsigned) y) { - /* x and y are self groups */ - size = cuddZddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtableZ[x].next == (unsigned) x); - assert(table->subtableZ[y].next == (unsigned) y); -#endif - if (size == 0) goto zddGroupSiftingDownOutOfMem; - - /* Record move. */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto zddGroupSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_DEFAULT; - move->size = size; - move->next = *moves; - *moves = move; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n"); -#endif - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - x = y; - y = cuddZddNextHigh(table,x); - } else { /* Group move */ - size = zddGroupMove(table,x,y,moves); - if (size == 0) goto zddGroupSiftingDownOutOfMem; - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } - x = gybot; - y = cuddZddNextHigh(table,x); - } - - return(1); - -zddGroupSiftingDownOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - - return(0); - -} /* end of zddGroupSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Swaps two groups and records the move.] - - Description [Swaps two groups and records the move. Returns the - number of keys in the DD table in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupMove( - DdManager * table, - int x, - int y, - Move ** moves) -{ - Move *move; - int size; - int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - int swapx,swapy; -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - int initialSize,bestSize; -#endif - -#if DD_DEBUG - /* We assume that x < y */ - assert(x < y); -#endif - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtableZ[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtableZ[ybot].next) - ybot = table->subtableZ[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - initialSize = bestSize = table->keysZ; -#endif - /* Sift the variables of the second group up through the first group */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddZddSwapInPlace(table,x,y); - if (size == 0) goto zddGroupMoveOutOfMem; -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (size < bestSize) - bestSize = size; -#endif - swapx = x; swapy = y; - y = x; - x = cuddZddNextLow(table,y); - } - y = ytop + i; - x = cuddZddNextLow(table,y); - } -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if ((bestSize < initialSize) && (bestSize < size)) - (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size); -#endif - - /* fix groups */ - y = xtop; /* ytop is now where xtop used to be */ - for (i = 0; i < ysize - 1; i++) { - table->subtableZ[y].next = cuddZddNextHigh(table,y); - y = cuddZddNextHigh(table,y); - } - table->subtableZ[y].next = xtop; /* y is bottom of its group, join */ - /* it to top of its group */ - x = cuddZddNextHigh(table,y); - newxtop = x; - for (i = 0; i < xsize - 1; i++) { - table->subtableZ[x].next = cuddZddNextHigh(table,x); - x = cuddZddNextHigh(table,x); - } - table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */ - /* it to top of its group */ -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n"); -#endif - - /* Store group move */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto zddGroupMoveOutOfMem; - move->x = swapx; - move->y = swapy; - move->flags = MTR_DEFAULT; - move->size = table->keysZ; - move->next = *moves; - *moves = move; - - return(table->keysZ); - -zddGroupMoveOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - return(0); - -} /* end of zddGroupMove */ - - -/**Function******************************************************************** - - Synopsis [Undoes the swap two groups.] - - Description [Undoes the swap two groups. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupMoveBackward( - DdManager * table, - int x, - int y) -{ - int size; - int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - - -#if DD_DEBUG - /* We assume that x < y */ - assert(x < y); -#endif - - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtableZ[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtableZ[ybot].next) - ybot = table->subtableZ[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - - /* Sift the variables of the second group up through the first group */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddZddSwapInPlace(table,x,y); - if (size == 0) - return(0); - y = x; - x = cuddZddNextLow(table,y); - } - y = ytop + i; - x = cuddZddNextLow(table,y); - } - - /* fix groups */ - y = xtop; - for (i = 0; i < ysize - 1; i++) { - table->subtableZ[y].next = cuddZddNextHigh(table,y); - y = cuddZddNextHigh(table,y); - } - table->subtableZ[y].next = xtop; /* y is bottom of its group, join */ - /* to its top */ - x = cuddZddNextHigh(table,y); - newxtop = x; - for (i = 0; i < xsize - 1; i++) { - table->subtableZ[x].next = cuddZddNextHigh(table,x); - x = cuddZddNextHigh(table,x); - } - table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */ - /* to its top */ -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n"); -#endif - - return(1); - -} /* end of zddGroupMoveBackward */ - - -/**Function******************************************************************** - - Synopsis [Determines the best position for a variables and returns - it there.] - - Description [Determines the best position for a variables and returns - it there. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingBackward( - DdManager * table, - Move * moves, - int size) -{ - Move *move; - int res; - - - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - if ((table->subtableZ[move->x].next == move->x) && - (table->subtableZ[move->y].next == move->y)) { - res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n"); - assert(table->subtableZ[move->x].next == move->x); - assert(table->subtableZ[move->y].next == move->y); -#endif - } else { /* Group move necessary */ - res = zddGroupMoveBackward(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - } - - return(1); - -} /* end of zddGroupSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Merges groups in the DD table.] - - Description [Creates a single group from low to high and adjusts the - idex field of the tree node.] - - SideEffects [None] - -******************************************************************************/ -static void -zddMergeGroups( - DdManager * table, - MtrNode * treenode, - int low, - int high) -{ - int i; - MtrNode *auxnode; - int saveindex; - int newindex; - - /* Merge all variables from low to high in one group, unless - ** this is the topmost group. In such a case we do not merge lest - ** we lose the symmetry information. */ - if (treenode != table->treeZ) { - for (i = low; i < high; i++) - table->subtableZ[i].next = i+1; - table->subtableZ[high].next = low; - } - - /* Adjust the index fields of the tree nodes. If a node is the - ** first child of its parent, then the parent may also need adjustment. */ - saveindex = treenode->index; - newindex = table->invpermZ[low]; - auxnode = treenode; - do { - auxnode->index = newindex; - if (auxnode->parent == NULL || - (int) auxnode->parent->index != saveindex) - break; - auxnode = auxnode->parent; - } while (1); - return; - -} /* end of zddMergeGroups */ - diff --git a/src/bdd/cudd/cuddZddIsop.c b/src/bdd/cudd/cuddZddIsop.c deleted file mode 100644 index f4b057ea..00000000 --- a/src/bdd/cudd/cuddZddIsop.c +++ /dev/null @@ -1,885 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddIsop.c] - - PackageName [cudd] - - Synopsis [Functions to find irredundant SOP covers as ZDDs from BDDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_bddIsop() - <li> Cudd_zddIsop() - <li> Cudd_MakeBddFromZddCover() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddBddIsop() - <li> cuddZddIsop() - <li> cuddMakeBddFromZddCover() - </ul> - Static procedures included in this module: - <ul> - </ul> - ] - - SeeAlso [] - - Author [In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddIsop.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes an ISOP in ZDD form from BDDs.] - - Description [Computes an irredundant sum of products (ISOP) in ZDD - form from BDDs. The two BDDs L and U represent the lower bound and - the upper bound, respectively, of the function. The ISOP uses two - ZDD variables for each BDD variable: One for the positive literal, - and one for the negative literal. These two variables should be - adjacent in the ZDD order. The two ZDD variables corresponding to - BDD variable <code>i</code> should have indices <code>2i</code> and - <code>2i+1</code>. The result of this procedure depends on the - variable order. If successful, Cudd_zddIsop returns the BDD for - the function chosen from the interval. The ZDD representing the - irredundant cover is returned as a side effect in zdd_I. In case of - failure, NULL is returned.] - - SideEffects [zdd_I holds the pointer to the ZDD for the ISOP on - successful return.] - - SeeAlso [Cudd_bddIsop Cudd_zddVarsFromBddVars] - -******************************************************************************/ -DdNode * -Cudd_zddIsop( - DdManager * dd, - DdNode * L, - DdNode * U, - DdNode ** zdd_I) -{ - DdNode *res; - int autoDynZ; - - autoDynZ = dd->autoDynZ; - dd->autoDynZ = 0; - - do { - dd->reordered = 0; - res = cuddZddIsop(dd, L, U, zdd_I); - } while (dd->reordered == 1); - dd->autoDynZ = autoDynZ; - return(res); - -} /* end of Cudd_zddIsop */ - - -/**Function******************************************************************** - - Synopsis [Computes a BDD in the interval between L and U with a - simple sum-of-produuct cover.] - - Description [Computes a BDD in the interval between L and U with a - simple sum-of-produuct cover. This procedure is similar to - Cudd_zddIsop, but it does not return the ZDD for the cover. Returns - a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddIsop] - -******************************************************************************/ -DdNode * -Cudd_bddIsop( - DdManager * dd, - DdNode * L, - DdNode * U) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddIsop(dd, L, U); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddIsop */ - - -/**Function******************************************************************** - - Synopsis [Converts a ZDD cover to a BDD graph.] - - Description [Converts a ZDD cover to a BDD graph. If successful, it - returns a BDD node, otherwise it returns NULL.] - - SideEffects [] - - SeeAlso [cuddMakeBddFromZddCover] - -******************************************************************************/ -DdNode * -Cudd_MakeBddFromZddCover( - DdManager * dd, - DdNode * node) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddMakeBddFromZddCover(dd, node); - } while (dd->reordered == 1); - return(res); -} /* end of Cudd_MakeBddFromZddCover */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddIsop.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddIsop] - -******************************************************************************/ -DdNode * -cuddZddIsop( - DdManager * dd, - DdNode * L, - DdNode * U, - DdNode ** zdd_I) -{ - DdNode *one = DD_ONE(dd); - DdNode *zero = Cudd_Not(one); - DdNode *zdd_one = DD_ONE(dd); - DdNode *zdd_zero = DD_ZERO(dd); - int v, top_l, top_u; - DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; - DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; - DdNode *Isub0, *Isub1, *Id; - DdNode *zdd_Isub0, *zdd_Isub1, *zdd_Id; - DdNode *x; - DdNode *term0, *term1, *sum; - DdNode *Lv, *Uv, *Lnv, *Unv; - DdNode *r, *y, *z; - int index; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - - statLine(dd); - if (L == zero) { - *zdd_I = zdd_zero; - return(zero); - } - if (U == one) { - *zdd_I = zdd_one; - return(one); - } - - if (U == zero || L == one) { - printf("*** ERROR : illegal condition for ISOP (U < L).\n"); - exit(1); - } - - /* Check the cache. We store two results for each recursive call. - ** One is the BDD, and the other is the ZDD. Both are needed. - ** Hence we need a double hit in the cache to terminate the - ** recursion. Clearly, collisions may evict only one of the two - ** results. */ - cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) cuddZddIsop; - r = cuddCacheLookup2(dd, cuddBddIsop, L, U); - if (r) { - *zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U); - if (*zdd_I) - return(r); - else { - /* The BDD result may have been dead. In that case - ** cuddCacheLookup2 would have called cuddReclaim, - ** whose effects we now have to undo. */ - cuddRef(r); - Cudd_RecursiveDeref(dd, r); - } - } - - top_l = dd->perm[Cudd_Regular(L)->index]; - top_u = dd->perm[Cudd_Regular(U)->index]; - v = ddMin(top_l, top_u); - - /* Compute cofactors. */ - if (top_l == v) { - index = Cudd_Regular(L)->index; - Lv = Cudd_T(L); - Lnv = Cudd_E(L); - if (Cudd_IsComplement(L)) { - Lv = Cudd_Not(Lv); - Lnv = Cudd_Not(Lnv); - } - } - else { - index = Cudd_Regular(U)->index; - Lv = Lnv = L; - } - - if (top_u == v) { - Uv = Cudd_T(U); - Unv = Cudd_E(U); - if (Cudd_IsComplement(U)) { - Uv = Cudd_Not(Uv); - Unv = Cudd_Not(Unv); - } - } - else { - Uv = Unv = U; - } - - Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); - if (Lsub0 == NULL) - return(NULL); - Cudd_Ref(Lsub0); - Usub0 = Unv; - Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); - if (Lsub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - return(NULL); - } - Cudd_Ref(Lsub1); - Usub1 = Uv; - - Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0); - if (Isub0 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - return(NULL); - } - /* - if ((!cuddIsConstant(Cudd_Regular(Isub0))) && - (Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 || - dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) { - printf("*** ERROR : illegal permutation in ZDD. ***\n"); - } - */ - Cudd_Ref(Isub0); - Cudd_Ref(zdd_Isub0); - Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1); - if (Isub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - return(NULL); - } - /* - if ((!cuddIsConstant(Cudd_Regular(Isub1))) && - (Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 || - dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) { - printf("*** ERROR : illegal permutation in ZDD. ***\n"); - } - */ - Cudd_Ref(Isub1); - Cudd_Ref(zdd_Isub1); - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - - Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); - if (Lsuper0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - return(NULL); - } - Cudd_Ref(Lsuper0); - Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); - if (Lsuper1 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - return(NULL); - } - Cudd_Ref(Lsuper1); - Usuper0 = Unv; - Usuper1 = Uv; - - /* Ld = Lsuper0 + Lsuper1 */ - Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); - if (Ld == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - return(NULL); - } - Ld = Cudd_Not(Ld); - Cudd_Ref(Ld); - /* Ud = Usuper0 * Usuper1 */ - Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); - if (Ud == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - Cudd_RecursiveDeref(dd, Ld); - return(NULL); - } - Cudd_Ref(Ud); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - - Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id); - if (Id == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - return(NULL); - } - /* - if ((!cuddIsConstant(Cudd_Regular(Id))) && - (Cudd_Regular(Id)->index != zdd_Id->index / 2 || - dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) { - printf("*** ERROR : illegal permutation in ZDD. ***\n"); - } - */ - Cudd_Ref(Id); - Cudd_Ref(zdd_Id); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - - x = cuddUniqueInter(dd, index, one, zero); - if (x == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - return(NULL); - } - Cudd_Ref(x); - /* term0 = x * Isub0 */ - term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); - if (term0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, x); - return(NULL); - } - Cudd_Ref(term0); - Cudd_RecursiveDeref(dd, Isub0); - /* term1 = x * Isub1 */ - term1 = cuddBddAndRecur(dd, x, Isub1); - if (term1 == NULL) { - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, term0); - return(NULL); - } - Cudd_Ref(term1); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, Isub1); - /* sum = term0 + term1 */ - sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); - if (sum == NULL) { - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - return(NULL); - } - sum = Cudd_Not(sum); - Cudd_Ref(sum); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - /* r = sum + Id */ - r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); - r = Cudd_NotCond(r, r != NULL); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, sum); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDeref(dd, sum); - Cudd_RecursiveDeref(dd, Id); - - if (zdd_Isub0 != zdd_zero) { - z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id); - if (z == NULL) { - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, r); - return(NULL); - } - } - else { - z = zdd_Id; - } - Cudd_Ref(z); - if (zdd_Isub1 != zdd_zero) { - y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z); - if (y == NULL) { - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, r); - Cudd_RecursiveDerefZdd(dd, z); - return(NULL); - } - } - else - y = z; - Cudd_Ref(y); - - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDerefZdd(dd, z); - - cuddCacheInsert2(dd, cuddBddIsop, L, U, r); - cuddCacheInsert2(dd, cacheOp, L, U, y); - - Cudd_Deref(r); - Cudd_Deref(y); - *zdd_I = y; - /* - if (Cudd_Regular(r)->index != y->index / 2) { - printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n"); - } - */ - return(r); - -} /* end of cuddZddIsop */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddIsop.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_bddIsop] - -******************************************************************************/ -DdNode * -cuddBddIsop( - DdManager * dd, - DdNode * L, - DdNode * U) -{ - DdNode *one = DD_ONE(dd); - DdNode *zero = Cudd_Not(one); - int v, top_l, top_u; - DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; - DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; - DdNode *Isub0, *Isub1, *Id; - DdNode *x; - DdNode *term0, *term1, *sum; - DdNode *Lv, *Uv, *Lnv, *Unv; - DdNode *r; - int index; - - statLine(dd); - if (L == zero) - return(zero); - if (U == one) - return(one); - - /* Check cache */ - r = cuddCacheLookup2(dd, cuddBddIsop, L, U); - if (r) - return(r); - - top_l = dd->perm[Cudd_Regular(L)->index]; - top_u = dd->perm[Cudd_Regular(U)->index]; - v = ddMin(top_l, top_u); - - /* Compute cofactors */ - if (top_l == v) { - index = Cudd_Regular(L)->index; - Lv = Cudd_T(L); - Lnv = Cudd_E(L); - if (Cudd_IsComplement(L)) { - Lv = Cudd_Not(Lv); - Lnv = Cudd_Not(Lnv); - } - } - else { - index = Cudd_Regular(U)->index; - Lv = Lnv = L; - } - - if (top_u == v) { - Uv = Cudd_T(U); - Unv = Cudd_E(U); - if (Cudd_IsComplement(U)) { - Uv = Cudd_Not(Uv); - Unv = Cudd_Not(Unv); - } - } - else { - Uv = Unv = U; - } - - Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); - if (Lsub0 == NULL) - return(NULL); - Cudd_Ref(Lsub0); - Usub0 = Unv; - Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); - if (Lsub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - return(NULL); - } - Cudd_Ref(Lsub1); - Usub1 = Uv; - - Isub0 = cuddBddIsop(dd, Lsub0, Usub0); - if (Isub0 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - return(NULL); - } - Cudd_Ref(Isub0); - Isub1 = cuddBddIsop(dd, Lsub1, Usub1); - if (Isub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - Cudd_RecursiveDeref(dd, Isub0); - return(NULL); - } - Cudd_Ref(Isub1); - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - - Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); - if (Lsuper0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - return(NULL); - } - Cudd_Ref(Lsuper0); - Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); - if (Lsuper1 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - return(NULL); - } - Cudd_Ref(Lsuper1); - Usuper0 = Unv; - Usuper1 = Uv; - - /* Ld = Lsuper0 + Lsuper1 */ - Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); - Ld = Cudd_NotCond(Ld, Ld != NULL); - if (Ld == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - return(NULL); - } - Cudd_Ref(Ld); - Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); - if (Ud == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - Cudd_RecursiveDeref(dd, Ld); - return(NULL); - } - Cudd_Ref(Ud); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - - Id = cuddBddIsop(dd, Ld, Ud); - if (Id == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - return(NULL); - } - Cudd_Ref(Id); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - - x = cuddUniqueInter(dd, index, one, zero); - if (x == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - return(NULL); - } - Cudd_Ref(x); - term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); - if (term0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, x); - return(NULL); - } - Cudd_Ref(term0); - Cudd_RecursiveDeref(dd, Isub0); - term1 = cuddBddAndRecur(dd, x, Isub1); - if (term1 == NULL) { - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, term0); - return(NULL); - } - Cudd_Ref(term1); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, Isub1); - /* sum = term0 + term1 */ - sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); - sum = Cudd_NotCond(sum, sum != NULL); - if (sum == NULL) { - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - return(NULL); - } - Cudd_Ref(sum); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - /* r = sum + Id */ - r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); - r = Cudd_NotCond(r, r != NULL); - if (r == NULL) { - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, sum); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDeref(dd, sum); - Cudd_RecursiveDeref(dd, Id); - - cuddCacheInsert2(dd, cuddBddIsop, L, U, r); - - Cudd_Deref(r); - return(r); - -} /* end of cuddBddIsop */ - - -/**Function******************************************************************** - - Synopsis [Converts a ZDD cover to a BDD graph.] - - Description [Converts a ZDD cover to a BDD graph. If successful, it - returns a BDD node, otherwise it returns NULL. It is a recursive - algorithm as the following. First computes 3 cofactors of a ZDD cover; - f1, f0 and fd. Second, compute BDDs(b1, b0 and bd) of f1, f0 and fd. - Third, compute T=b1+bd and E=b0+bd. Fourth, compute ITE(v,T,E) where v - is the variable which has the index of the top node of the ZDD cover. - In this case, since the index of v can be larger than either one of T or - one of E, cuddUniqueInterIVO is called, here IVO stands for - independent variable ordering.] - - SideEffects [] - - SeeAlso [Cudd_MakeBddFromZddCover] - -******************************************************************************/ -DdNode * -cuddMakeBddFromZddCover( - DdManager * dd, - DdNode * node) -{ - DdNode *neW; - int v; - DdNode *f1, *f0, *fd; - DdNode *b1, *b0, *bd; - DdNode *T, *E; - - statLine(dd); - if (node == dd->one) - return(dd->one); - if (node == dd->zero) - return(Cudd_Not(dd->one)); - - /* Check cache */ - neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node); - if (neW) - return(neW); - - v = Cudd_Regular(node)->index; /* either yi or zi */ - cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd); - Cudd_Ref(f1); - Cudd_Ref(f0); - Cudd_Ref(fd); - - b1 = cuddMakeBddFromZddCover(dd, f1); - if (!b1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - return(NULL); - } - Cudd_Ref(b1); - b0 = cuddMakeBddFromZddCover(dd, f0); - if (!b1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDeref(dd, b1); - return(NULL); - } - Cudd_Ref(b0); - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - if (fd != dd->zero) { - bd = cuddMakeBddFromZddCover(dd, fd); - if (!bd) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDeref(dd, b1); - Cudd_RecursiveDeref(dd, b0); - return(NULL); - } - Cudd_Ref(bd); - Cudd_RecursiveDerefZdd(dd, fd); - - T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd)); - if (!T) { - Cudd_RecursiveDeref(dd, b1); - Cudd_RecursiveDeref(dd, b0); - Cudd_RecursiveDeref(dd, bd); - return(NULL); - } - T = Cudd_NotCond(T, T != NULL); - Cudd_Ref(T); - Cudd_RecursiveDeref(dd, b1); - E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd)); - if (!E) { - Cudd_RecursiveDeref(dd, b0); - Cudd_RecursiveDeref(dd, bd); - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - E = Cudd_NotCond(E, E != NULL); - Cudd_Ref(E); - Cudd_RecursiveDeref(dd, b0); - Cudd_RecursiveDeref(dd, bd); - } - else { - Cudd_RecursiveDerefZdd(dd, fd); - T = b1; - E = b0; - } - - if (Cudd_IsComplement(T)) { - neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E)); - if (!neW) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - neW = Cudd_Not(neW); - } - else { - neW = cuddUniqueInterIVO(dd, v / 2, T, E); - if (!neW) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - Cudd_Ref(neW); - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - - cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW); - Cudd_Deref(neW); - return(neW); - -} /* end of cuddMakeBddFromZddCover */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddZddLin.c b/src/bdd/cudd/cuddZddLin.c deleted file mode 100644 index ef2cd298..00000000 --- a/src/bdd/cudd/cuddZddLin.c +++ /dev/null @@ -1,939 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddLin.c] - - PackageName [cudd] - - Synopsis [Procedures for dynamic variable ordering of ZDDs.] - - Description [Internal procedures included in this module: - <ul> - <li> cuddZddLinearSifting() - </ul> - Static procedures included in this module: - <ul> - <li> cuddZddLinearInPlace() - <li> cuddZddLinerAux() - <li> cuddZddLinearUp() - <li> cuddZddLinearDown() - <li> cuddZddLinearBackward() - <li> cuddZddUndoMoves() - </ul> - ] - - SeeAlso [cuddLinear.c cuddZddReord.c] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define CUDD_SWAP_MOVE 0 -#define CUDD_LINEAR_TRANSFORM_MOVE 1 -#define CUDD_INVERSE_TRANSFORM_MOVE 2 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddLin.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -extern int *zdd_entry; -extern int zddTotalNumberSwapping; -static int zddTotalNumberLinearTr; -static DdNode *empty; - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int cuddZddLinearAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static Move * cuddZddLinearUp ARGS((DdManager *table, int y, int xLow, Move *prevMoves)); -static Move * cuddZddLinearDown ARGS((DdManager *table, int x, int xHigh, Move *prevMoves)); -static int cuddZddLinearBackward ARGS((DdManager *table, int size, Move *moves)); -static Move* cuddZddUndoMoves ARGS((DdManager *table, Move *moves)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - - - -/**Function******************************************************************** - - Synopsis [Implementation of the linear sifting algorithm for ZDDs.] - - Description [Implementation of the linear sifting algorithm for ZDDs. - Assumes that no dead nodes are present. - <ol> - <li> Order all the variables according to the number of entries - in each unique table. - <li> Sift the variable up and down and applies the XOR transformation, - remembering each time the total size of the DD heap. - <li> Select the best permutation. - <li> Repeat 3 and 4 for all variables. - </ol> - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddLinearSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; -#ifdef DD_STATS - int previousSize; -#endif - - size = table->sizeZ; - empty = table->zero; - - /* Find order in which to sift variables. */ - var = NULL; - zdd_entry = ALLOC(int, size); - if (zdd_entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSiftingOutOfMem; - } - var = ALLOC(int, size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->permZ[i]; - zdd_entry[i] = table->subtableZ[x].keys; - var[i] = i; - } - - qsort((void *)var, size, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; - if (x < lower || x > upper) continue; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = cuddZddLinearAux(table, x, lower, upper); - if (!result) - goto cuddZddSiftingOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - FREE(var); - FREE(zdd_entry); - - return(1); - -cuddZddSiftingOutOfMem: - - if (zdd_entry != NULL) FREE(zdd_entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddZddLinearSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Linearly combines two adjacent variables.] - - Description [Linearly combines two adjacent variables. It assumes - that no dead nodes are present on entry to this procedure. The - procedure then guarantees that no dead nodes will be present when it - terminates. cuddZddLinearInPlace assumes that x < y. Returns the - number of keys in the table if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddZddSwapInPlace cuddLinearInPlace] - -******************************************************************************/ -int -cuddZddLinearInPlace( - DdManager * table, - int x, - int y) -{ - DdNodePtr *xlist, *ylist; - int xindex, yindex; - int xslots, yslots; - int xshift, yshift; - int oldxkeys, oldykeys; - int newxkeys, newykeys; - int i; - int posn; - DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; - DdNode *newf1, *newf0, *g, *next, *previous; - DdNode *special; - -#ifdef DD_DEBUG - assert(x < y); - assert(cuddZddNextHigh(table,x) == y); - assert(table->subtableZ[x].keys != 0); - assert(table->subtableZ[y].keys != 0); - assert(table->subtableZ[x].dead == 0); - assert(table->subtableZ[y].dead == 0); -#endif - - zddTotalNumberLinearTr++; - - /* Get parameters of x subtable. */ - xindex = table->invpermZ[x]; - xlist = table->subtableZ[x].nodelist; - oldxkeys = table->subtableZ[x].keys; - xslots = table->subtableZ[x].slots; - xshift = table->subtableZ[x].shift; - newxkeys = 0; - - /* Get parameters of y subtable. */ - yindex = table->invpermZ[y]; - ylist = table->subtableZ[y].nodelist; - oldykeys = table->subtableZ[y].keys; - yslots = table->subtableZ[y].slots; - yshift = table->subtableZ[y].shift; - newykeys = oldykeys; - - /* The nodes in the x layer are put in two chains. The chain - ** pointed by g holds the normal nodes. When re-expressed they stay - ** in the x list. The chain pointed by special holds the elements - ** that will move to the y list. - */ - g = special = NULL; - for (i = 0; i < xslots; i++) { - f = xlist[i]; - if (f == NULL) continue; - xlist[i] = NULL; - while (f != NULL) { - next = f->next; - f1 = cuddT(f); - /* if (f1->index == yindex) */ cuddSatDec(f1->ref); - f0 = cuddE(f); - /* if (f0->index == yindex) */ cuddSatDec(f0->ref); - if ((int) f1->index == yindex && cuddE(f1) == empty && - (int) f0->index != yindex) { - f->next = special; - special = f; - } else { - f->next = g; - g = f; - } - f = next; - } /* while there are elements in the collision chain */ - } /* for each slot of the x subtable */ - - /* Mark y nodes with pointers from above x. We mark them by - ** changing their index to x. - */ - for (i = 0; i < yslots; i++) { - f = ylist[i]; - while (f != NULL) { - if (f->ref != 0) { - f->index = xindex; - } - f = f->next; - } /* while there are elements in the collision chain */ - } /* for each slot of the y subtable */ - - /* Move special nodes to the y list. */ - f = special; - while (f != NULL) { - next = f->next; - f1 = cuddT(f); - f11 = cuddT(f1); - cuddT(f) = f11; - cuddSatInc(f11->ref); - f0 = cuddE(f); - cuddSatInc(f0->ref); - f->index = yindex; - /* Insert at the beginning of the list so that it will be - ** found first if there is a duplicate. The duplicate will - ** eventually be moved or garbage collected. No node - ** re-expression will add a pointer to it. - */ - posn = ddHash(f11, f0, yshift); - f->next = ylist[posn]; - ylist[posn] = f; - newykeys++; - f = next; - } - - /* Take care of the remaining x nodes that must be re-expressed. - ** They form a linked list pointed by g. - */ - f = g; - while (f != NULL) { -#ifdef DD_COUNT - table->swapSteps++; -#endif - next = f->next; - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); - if ((int) f1->index == yindex || (int) f1->index == xindex) { - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - f11 = empty; f10 = f1; - } - f0 = cuddE(f); - if ((int) f0->index == yindex || (int) f0->index == xindex) { - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = empty; f00 = f0; - } - /* Create the new T child. */ - if (f01 == empty) { - newf1 = f10; - cuddSatInc(newf1->ref); - } else { - /* Check ylist for triple (yindex, f01, f10). */ - posn = ddHash(f01, f10, yshift); - /* For each element newf1 in collision list ylist[posn]. */ - newf1 = ylist[posn]; - /* Search the collision chain skipping the marked nodes. */ - while (newf1 != NULL) { - if (cuddT(newf1) == f01 && cuddE(newf1) == f10 && - (int) newf1->index == yindex) { - cuddSatInc(newf1->ref); - break; /* match */ - } - newf1 = newf1->next; - } /* while newf1 */ - if (newf1 == NULL) { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto zddSwapOutOfMem; - newf1->index = yindex; newf1->ref = 1; - cuddT(newf1) = f01; - cuddE(newf1) = f10; - /* Insert newf1 in the collision list ylist[pos]; - ** increase the ref counts of f01 and f10 - */ - newykeys++; - newf1->next = ylist[posn]; - ylist[posn] = newf1; - cuddSatInc(f01->ref); - cuddSatInc(f10->ref); - } - } - cuddT(f) = newf1; - - /* Do the same for f0. */ - /* Create the new E child. */ - if (f11 == empty) { - newf0 = f00; - cuddSatInc(newf0->ref); - } else { - /* Check ylist for triple (yindex, f11, f00). */ - posn = ddHash(f11, f00, yshift); - /* For each element newf0 in collision list ylist[posn]. */ - newf0 = ylist[posn]; - while (newf0 != NULL) { - if (cuddT(newf0) == f11 && cuddE(newf0) == f00 && - (int) newf0->index == yindex) { - cuddSatInc(newf0->ref); - break; /* match */ - } - newf0 = newf0->next; - } /* while newf0 */ - if (newf0 == NULL) { /* no match */ - newf0 = cuddDynamicAllocNode(table); - if (newf0 == NULL) - goto zddSwapOutOfMem; - newf0->index = yindex; newf0->ref = 1; - cuddT(newf0) = f11; cuddE(newf0) = f00; - /* Insert newf0 in the collision list ylist[posn]; - ** increase the ref counts of f11 and f00. - */ - newykeys++; - newf0->next = ylist[posn]; - ylist[posn] = newf0; - cuddSatInc(f11->ref); - cuddSatInc(f00->ref); - } - } - cuddE(f) = newf0; - - /* Re-insert the modified f in xlist. - ** The modified f does not already exists in xlist. - ** (Because of the uniqueness of the cofactors.) - */ - posn = ddHash(newf1, newf0, xshift); - newxkeys++; - f->next = xlist[posn]; - xlist[posn] = f; - f = next; - } /* while f != NULL */ - - /* GC the y layer and move the marked nodes to the x list. */ - - /* For each node f in ylist. */ - for (i = 0; i < yslots; i++) { - previous = NULL; - f = ylist[i]; - while (f != NULL) { - next = f->next; - if (f->ref == 0) { - cuddSatDec(cuddT(f)->ref); - cuddSatDec(cuddE(f)->ref); - cuddDeallocNode(table, f); - newykeys--; - if (previous == NULL) - ylist[i] = next; - else - previous->next = next; - } else if ((int) f->index == xindex) { /* move marked node */ - if (previous == NULL) - ylist[i] = next; - else - previous->next = next; - f1 = cuddT(f); - cuddSatDec(f1->ref); - /* Check ylist for triple (yindex, f1, empty). */ - posn = ddHash(f1, empty, yshift); - /* For each element newf1 in collision list ylist[posn]. */ - newf1 = ylist[posn]; - while (newf1 != NULL) { - if (cuddT(newf1) == f1 && cuddE(newf1) == empty && - (int) newf1->index == yindex) { - cuddSatInc(newf1->ref); - break; /* match */ - } - newf1 = newf1->next; - } /* while newf1 */ - if (newf1 == NULL) { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto zddSwapOutOfMem; - newf1->index = yindex; newf1->ref = 1; - cuddT(newf1) = f1; cuddE(newf1) = empty; - /* Insert newf1 in the collision list ylist[posn]; - ** increase the ref counts of f1 and empty. - */ - newykeys++; - newf1->next = ylist[posn]; - ylist[posn] = newf1; - if (posn == i && previous == NULL) - previous = newf1; - cuddSatInc(f1->ref); - cuddSatInc(empty->ref); - } - cuddT(f) = newf1; - f0 = cuddE(f); - /* Insert f in x list. */ - posn = ddHash(newf1, f0, xshift); - newxkeys++; - newykeys--; - f->next = xlist[posn]; - xlist[posn] = f; - } else { - previous = f; - } - f = next; - } /* while f */ - } /* for i */ - - /* Set the appropriate fields in table. */ - table->subtableZ[x].keys = newxkeys; - table->subtableZ[y].keys = newykeys; - - table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; - - /* Update univ section; univ[x] remains the same. */ - table->univ[y] = cuddT(table->univ[x]); - -#if 0 - (void) fprintf(table->out,"x = %d y = %d\n", x, y); - (void) Cudd_DebugCheck(table); - (void) Cudd_CheckKeys(table); -#endif - - return (table->keysZ); - -zddSwapOutOfMem: - (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); - - return (0); - -} /* end of cuddZddLinearInPlace */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddLinearAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - Move *move; - Move *moveUp; /* list of up move */ - Move *moveDown; /* list of down move */ - - int initial_size; - int result; - - initial_size = table->keysZ; - -#ifdef DD_DEBUG - assert(table->subtableZ[x].keys > 0); -#endif - - moveDown = NULL; - moveUp = NULL; - - if (x == xLow) { - moveDown = cuddZddLinearDown(table, x, xHigh, NULL); - /* At this point x --> xHigh. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - /* Move backward and stop at best position. */ - result = cuddZddLinearBackward(table, initial_size, moveDown); - if (!result) - goto cuddZddLinearAuxOutOfMem; - - } else if (x == xHigh) { - moveUp = cuddZddLinearUp(table, x, xLow, NULL); - /* At this point x --> xLow. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - /* Move backward and stop at best position. */ - result = cuddZddLinearBackward(table, initial_size, moveUp); - if (!result) - goto cuddZddLinearAuxOutOfMem; - - } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ - moveDown = cuddZddLinearDown(table, x, xHigh, NULL); - /* At this point x --> xHigh. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - moveUp = cuddZddUndoMoves(table,moveDown); -#ifdef DD_DEBUG - assert(moveUp == NULL || moveUp->x == x); -#endif - moveUp = cuddZddLinearUp(table, x, xLow, moveUp); - if (moveUp == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - /* Move backward and stop at best position. */ - result = cuddZddLinearBackward(table, initial_size, moveUp); - if (!result) - goto cuddZddLinearAuxOutOfMem; - - } else { - moveUp = cuddZddLinearUp(table, x, xLow, NULL); - /* At this point x --> xHigh. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - /* Then move up. */ - moveDown = cuddZddUndoMoves(table,moveUp); -#ifdef DD_DEBUG - assert(moveDown == NULL || moveDown->y == x); -#endif - moveDown = cuddZddLinearDown(table, x, xHigh, moveDown); - if (moveDown == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - /* Move backward and stop at best position. */ - result = cuddZddLinearBackward(table, initial_size, moveDown); - if (!result) - goto cuddZddLinearAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *)moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *)moveUp); - moveUp = move; - } - - return(1); - -cuddZddLinearAuxOutOfMem: - if (moveDown != (Move *) CUDD_OUT_OF_MEM) { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *)moveDown); - moveDown = move; - } - } - if (moveUp != (Move *) CUDD_OUT_OF_MEM) { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *)moveUp); - moveUp = move; - } - } - - return(0); - -} /* end of cuddZddLinearAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable up applying the XOR transformation.] - - Description [Sifts a variable up applying the XOR - transformation. Moves y up until either it reaches the bound (xLow) - or the size of the ZDD heap increases too much. Returns the set of - moves in case of success; NULL if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddLinearUp( - DdManager * table, - int y, - int xLow, - Move * prevMoves) -{ - Move *moves; - Move *move; - int x; - int size, newsize; - int limitSize; - - moves = prevMoves; - limitSize = table->keysZ; - - x = cuddZddNextLow(table, y); - while (x >= xLow) { - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto cuddZddLinearUpOutOfMem; - newsize = cuddZddLinearInPlace(table, x, y); - if (newsize == 0) - goto cuddZddLinearUpOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddLinearUpOutOfMem; - move->x = x; - move->y = y; - move->next = moves; - moves = move; - move->flags = CUDD_SWAP_MOVE; - if (newsize > size) { - /* Undo transformation. The transformation we apply is - ** its own inverse. Hence, we just apply the transformation - ** again. - */ - newsize = cuddZddLinearInPlace(table,x,y); - if (newsize == 0) goto cuddZddLinearUpOutOfMem; -#ifdef DD_DEBUG - if (newsize != size) { - (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize); - } -#endif - } else { - size = newsize; - move->flags = CUDD_LINEAR_TRANSFORM_MOVE; - } - move->size = size; - - if ((double)size > (double)limitSize * table->maxGrowth) - break; - if (size < limitSize) - limitSize = size; - - y = x; - x = cuddZddNextLow(table, y); - } - return(moves); - -cuddZddLinearUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of cuddZddLinearUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable down and applies the XOR transformation.] - - Description [Sifts a variable down. Moves x down until either it - reaches the bound (xHigh) or the size of the ZDD heap increases too - much. Returns the set of moves in case of success; NULL if memory is - full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddLinearDown( - DdManager * table, - int x, - int xHigh, - Move * prevMoves) -{ - Move *moves; - Move *move; - int y; - int size, newsize; - int limitSize; - - moves = prevMoves; - limitSize = table->keysZ; - - y = cuddZddNextHigh(table, x); - while (y <= xHigh) { - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto cuddZddLinearDownOutOfMem; - newsize = cuddZddLinearInPlace(table, x, y); - if (newsize == 0) - goto cuddZddLinearDownOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddLinearDownOutOfMem; - move->x = x; - move->y = y; - move->next = moves; - moves = move; - move->flags = CUDD_SWAP_MOVE; - if (newsize > size) { - /* Undo transformation. The transformation we apply is - ** its own inverse. Hence, we just apply the transformation - ** again. - */ - newsize = cuddZddLinearInPlace(table,x,y); - if (newsize == 0) goto cuddZddLinearDownOutOfMem; - if (newsize != size) { - (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize); - } - } else { - size = newsize; - move->flags = CUDD_LINEAR_TRANSFORM_MOVE; - } - move->size = size; - - if ((double)size > (double)limitSize * table->maxGrowth) - break; - if (size < limitSize) - limitSize = size; - - x = y; - y = cuddZddNextHigh(table, x); - } - return(moves); - -cuddZddLinearDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of cuddZddLinearDown */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the ZDD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the ZDD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddLinearBackward( - DdManager * table, - int size, - Move * moves) -{ - Move *move; - int res; - - /* Find the minimum size among moves. */ - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { - res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - res = cuddZddSwapInPlace(table, move->x, move->y); - if (!res) - return(0); - if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { - res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - } - - return(1); - -} /* end of cuddZddLinearBackward */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the ZDD heap to the order - in effect before the moves.] - - Description [Given a set of moves, returns the ZDD heap to the - order in effect before the moves. Returns 1 in case of success; - 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static Move* -cuddZddUndoMoves( - DdManager * table, - Move * moves) -{ - Move *invmoves = NULL; - Move *move; - Move *invmove; - int size; - - for (move = moves; move != NULL; move = move->next) { - invmove = (Move *) cuddDynamicAllocNode(table); - if (invmove == NULL) goto cuddZddUndoMovesOutOfMem; - invmove->x = move->x; - invmove->y = move->y; - invmove->next = invmoves; - invmoves = invmove; - if (move->flags == CUDD_SWAP_MOVE) { - invmove->flags = CUDD_SWAP_MOVE; - size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto cuddZddUndoMovesOutOfMem; - } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { - invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; - size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); - if (!size) goto cuddZddUndoMovesOutOfMem; - size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto cuddZddUndoMovesOutOfMem; - } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ -#ifdef DD_DEBUG - (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); -#endif - invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; - size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto cuddZddUndoMovesOutOfMem; - size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); - if (!size) goto cuddZddUndoMovesOutOfMem; - } - invmove->size = size; - } - - return(invmoves); - -cuddZddUndoMovesOutOfMem: - while (invmoves != NULL) { - move = invmoves->next; - cuddDeallocNode(table, (DdNode *) invmoves); - invmoves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of cuddZddUndoMoves */ - diff --git a/src/bdd/cudd/cuddZddMisc.c b/src/bdd/cudd/cuddZddMisc.c deleted file mode 100644 index 6a4ddd09..00000000 --- a/src/bdd/cudd/cuddZddMisc.c +++ /dev/null @@ -1,252 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddMisc.c] - - PackageName [cudd] - - Synopsis [.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_zddDagSize() - <li> Cudd_zddCountMinterm() - <li> Cudd_zddPrintSubtable() - </ul> - Internal procedures included in this module: - <ul> - </ul> - Static procedures included in this module: - <ul> - <li> cuddZddDagInt() - </ul> - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include <math.h> -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddMisc.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int cuddZddDagInt ARGS((DdNode *n, st_table *tab)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Counts the number of nodes in a ZDD.] - - Description [Counts the number of nodes in a ZDD. This function - duplicates Cudd_DagSize and is only retained for compatibility.] - - SideEffects [None] - - SeeAlso [Cudd_DagSize] - -******************************************************************************/ -int -Cudd_zddDagSize( - DdNode * p_node) -{ - - int i; - st_table *table; - - table = st_init_table(st_ptrcmp, st_ptrhash); - i = cuddZddDagInt(p_node, table); - st_free_table(table); - return(i); - -} /* end of Cudd_zddDagSize */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms of a ZDD.] - - Description [Counts the number of minterms of the ZDD rooted at - <code>node</code>. This procedure takes a parameter - <code>path</code> that specifies how many variables are in the - support of the function. If the procedure runs out of memory, it - returns (double) CUDD_OUT_OF_MEM.] - - SideEffects [None] - - SeeAlso [Cudd_zddCountDouble] - -******************************************************************************/ -double -Cudd_zddCountMinterm( - DdManager * zdd, - DdNode * node, - int path) -{ - double dc_var, minterms; - - dc_var = (double)((double)(zdd->sizeZ) - (double)path); - minterms = Cudd_zddCountDouble(zdd, node) / pow(2.0, dc_var); - return(minterms); - -} /* end of Cudd_zddCountMinterm */ - - -/**Function******************************************************************** - - Synopsis [Prints the ZDD table.] - - Description [Prints the ZDD table for debugging purposes.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_zddPrintSubtable( - DdManager * table) -{ - int i, j; - DdNode *z1, *z1_next, *base; - DdSubtable *ZSubTable; - - base = table->one; - for (i = table->sizeZ - 1; i >= 0; i--) { - ZSubTable = &(table->subtableZ[i]); - printf("subtable[%d]:\n", i); - for (j = ZSubTable->slots - 1; j >= 0; j--) { - z1 = ZSubTable->nodelist[j]; - while (z1 != NIL(DdNode)) { - (void) fprintf(table->out, -#if SIZEOF_VOID_P == 8 - "ID = 0x%lx\tindex = %d\tr = %d\t", - (unsigned long) z1 / (unsigned long) sizeof(DdNode), - z1->index, z1->ref); -#else - "ID = 0x%x\tindex = %d\tr = %d\t", - (unsigned) z1 / (unsigned) sizeof(DdNode), - z1->index, z1->ref); -#endif - z1_next = cuddT(z1); - if (Cudd_IsConstant(z1_next)) { - (void) fprintf(table->out, "T = %d\t\t", - (z1_next == base)); - } - else { -#if SIZEOF_VOID_P == 8 - (void) fprintf(table->out, "T = 0x%lx\t", - (unsigned long) z1_next / (unsigned long) sizeof(DdNode)); -#else - (void) fprintf(table->out, "T = 0x%x\t", - (unsigned) z1_next / (unsigned) sizeof(DdNode)); -#endif - } - z1_next = cuddE(z1); - if (Cudd_IsConstant(z1_next)) { - (void) fprintf(table->out, "E = %d\n", - (z1_next == base)); - } - else { -#if SIZEOF_VOID_P == 8 - (void) fprintf(table->out, "E = 0x%lx\n", - (unsigned long) z1_next / (unsigned long) sizeof(DdNode)); -#else - (void) fprintf(table->out, "E = 0x%x\n", - (unsigned) z1_next / (unsigned) sizeof(DdNode)); -#endif - } - - z1_next = z1->next; - z1 = z1_next; - } - } - } - putchar('\n'); - -} /* Cudd_zddPrintSubtable */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddDagSize.] - - Description [Performs the recursive step of Cudd_zddDagSize. Does - not check for out-of-memory conditions.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddDagInt( - DdNode * n, - st_table * tab) -{ - if (n == NIL(DdNode)) - return(0); - - if (st_is_member(tab, (char *)n) == 1) - return(0); - - if (Cudd_IsConstant(n)) - return(0); - - (void)st_insert(tab, (char *)n, NIL(char)); - return(1 + cuddZddDagInt(cuddT(n), tab) + - cuddZddDagInt(cuddE(n), tab)); - -} /* cuddZddDagInt */ - diff --git a/src/bdd/cudd/cuddZddPort.c b/src/bdd/cudd/cuddZddPort.c deleted file mode 100644 index 6d4a3236..00000000 --- a/src/bdd/cudd/cuddZddPort.c +++ /dev/null @@ -1,354 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddPort.c] - - PackageName [cudd] - - Synopsis [Functions that translate BDDs to ZDDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_zddPortFromBdd() - <li> Cudd_zddPortToBdd() - </ul> - Internal procedures included in this module: - <ul> - </ul> - Static procedures included in this module: - <ul> - <li> zddPortFromBddStep() - <li> zddPortToBddStep() - </ul> - ] - - SeeAlso [] - - Author [Hyong-kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddPort.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * zddPortFromBddStep ARGS((DdManager *dd, DdNode *B, int expected)); -static DdNode * zddPortToBddStep ARGS((DdManager *dd, DdNode *f, int depth)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Converts a BDD into a ZDD.] - - Description [Converts a BDD into a ZDD. This function assumes that - there is a one-to-one correspondence between the BDD variables and the - ZDD variables, and that the variable order is the same for both types - of variables. These conditions are established if the ZDD variables - are created by one call to Cudd_zddVarsFromBddVars with multiplicity = - 1. Returns a pointer to the resulting ZDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddVarsFromBddVars] - -******************************************************************************/ -DdNode * -Cudd_zddPortFromBdd( - DdManager * dd, - DdNode * B) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = zddPortFromBddStep(dd,B,0); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_zddPortFromBdd */ - - -/**Function******************************************************************** - - Synopsis [Converts a ZDD into a BDD.] - - Description [Converts a ZDD into a BDD. Returns a pointer to the resulting - ZDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddPortFromBdd] - -******************************************************************************/ -DdNode * -Cudd_zddPortToBdd( - DdManager * dd, - DdNode * f) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = zddPortToBddStep(dd,f,0); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_zddPortToBdd */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddPortFromBdd.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -zddPortFromBddStep( - DdManager * dd, - DdNode * B, - int expected) -{ - DdNode *res, *prevZdd, *t, *e; - DdNode *Breg, *Bt, *Be; - int id, level; - - statLine(dd); - /* Terminal cases. */ - if (B == Cudd_Not(DD_ONE(dd))) - return(DD_ZERO(dd)); - if (B == DD_ONE(dd)) { - if (expected >= dd->sizeZ) { - return(DD_ONE(dd)); - } else { - return(dd->univ[expected]); - } - } - - Breg = Cudd_Regular(B); - - /* Computed table look-up. */ - res = cuddCacheLookup1Zdd(dd,Cudd_zddPortFromBdd,B); - if (res != NULL) { - level = cuddI(dd,Breg->index); - /* Adding DC vars. */ - if (expected < level) { - /* Add suppressed variables. */ - cuddRef(res); - for (level--; level >= expected; level--) { - prevZdd = res; - id = dd->invperm[level]; - res = cuddZddGetNode(dd, id, prevZdd, prevZdd); - if (res == NULL) { - Cudd_RecursiveDerefZdd(dd, prevZdd); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDerefZdd(dd, prevZdd); - } - cuddDeref(res); - } - return(res); - } /* end of cache look-up */ - - if (Cudd_IsComplement(B)) { - Bt = Cudd_Not(cuddT(Breg)); - Be = Cudd_Not(cuddE(Breg)); - } else { - Bt = cuddT(Breg); - Be = cuddE(Breg); - } - - id = Breg->index; - level = cuddI(dd,id); - t = zddPortFromBddStep(dd, Bt, level+1); - if (t == NULL) return(NULL); - cuddRef(t); - e = zddPortFromBddStep(dd, Be, level+1); - if (e == NULL) { - Cudd_RecursiveDerefZdd(dd, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(dd, id, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(dd, t); - Cudd_RecursiveDerefZdd(dd, e); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDerefZdd(dd, t); - Cudd_RecursiveDerefZdd(dd, e); - - cuddCacheInsert1(dd,Cudd_zddPortFromBdd,B,res); - - for (level--; level >= expected; level--) { - prevZdd = res; - id = dd->invperm[level]; - res = cuddZddGetNode(dd, id, prevZdd, prevZdd); - if (res == NULL) { - Cudd_RecursiveDerefZdd(dd, prevZdd); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDerefZdd(dd, prevZdd); - } - - cuddDeref(res); - return(res); - -} /* end of zddPortFromBddStep */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddPortToBdd.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -zddPortToBddStep( - DdManager * dd /* manager */, - DdNode * f /* ZDD to be converted */, - int depth /* recursion depth */) -{ - DdNode *one, *zero, *T, *E, *res, *var; - unsigned int index; - unsigned int level; - - statLine(dd); - one = DD_ONE(dd); - zero = DD_ZERO(dd); - if (f == zero) return(Cudd_Not(one)); - - if (depth == dd->sizeZ) return(one); - - index = dd->invpermZ[depth]; - level = cuddIZ(dd,f->index); - var = cuddUniqueInter(dd,index,one,Cudd_Not(one)); - if (var == NULL) return(NULL); - cuddRef(var); - - if (level > (unsigned) depth) { - E = zddPortToBddStep(dd,f,depth+1); - if (E == NULL) { - Cudd_RecursiveDeref(dd,var); - return(NULL); - } - cuddRef(E); - res = cuddBddIteRecur(dd,var,Cudd_Not(one),E); - if (res == NULL) { - Cudd_RecursiveDeref(dd,var); - Cudd_RecursiveDeref(dd,E); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd,var); - Cudd_RecursiveDeref(dd,E); - cuddDeref(res); - return(res); - } - - res = cuddCacheLookup1(dd,Cudd_zddPortToBdd,f); - if (res != NULL) { - Cudd_RecursiveDeref(dd,var); - return(res); - } - - T = zddPortToBddStep(dd,cuddT(f),depth+1); - if (T == NULL) { - Cudd_RecursiveDeref(dd,var); - return(NULL); - } - cuddRef(T); - E = zddPortToBddStep(dd,cuddE(f),depth+1); - if (E == NULL) { - Cudd_RecursiveDeref(dd,var); - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - - res = cuddBddIteRecur(dd,var,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd,var); - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd,var); - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - cuddDeref(res); - - cuddCacheInsert1(dd,Cudd_zddPortToBdd,f,res); - - return(res); - -} /* end of zddPortToBddStep */ - diff --git a/src/bdd/cudd/cuddZddReord.c b/src/bdd/cudd/cuddZddReord.c deleted file mode 100644 index e2da37f2..00000000 --- a/src/bdd/cudd/cuddZddReord.c +++ /dev/null @@ -1,1633 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddReord.c] - - PackageName [cudd] - - Synopsis [Procedures for dynamic variable ordering of ZDDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_zddReduceHeap() - <li> Cudd_zddShuffleHeap() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddZddAlignToBdd() - <li> cuddZddNextHigh() - <li> cuddZddNextLow() - <li> cuddZddUniqueCompare() - <li> cuddZddSwapInPlace() - <li> cuddZddSwapping() - <li> cuddZddSifting() - </ul> - Static procedures included in this module: - <ul> - <li> zddSwapAny() - <li> cuddZddSiftingAux() - <li> cuddZddSiftingUp() - <li> cuddZddSiftingDown() - <li> cuddZddSiftingBackward() - <li> zddReorderPreprocess() - <li> zddReorderPostprocess() - <li> zddShuffle() - <li> zddSiftUp() - </ul> - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_MAX_SUBTABLE_SPARSITY 8 -#define DD_SHRINK_FACTOR 2 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -int *zdd_entry; - -int zddTotalNumberSwapping; - -static DdNode *empty; - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static Move * zddSwapAny ARGS((DdManager *table, int x, int y)); -static int cuddZddSiftingAux ARGS((DdManager *table, int x, int x_low, int x_high)); -static Move * cuddZddSiftingUp ARGS((DdManager *table, int x, int x_low, int initial_size)); -static Move * cuddZddSiftingDown ARGS((DdManager *table, int x, int x_high, int initial_size)); -static int cuddZddSiftingBackward ARGS((DdManager *table, Move *moves, int size)); -static void zddReorderPreprocess ARGS((DdManager *table)); -static int zddReorderPostprocess ARGS((DdManager *table)); -static int zddShuffle ARGS((DdManager *table, int *permutation)); -static int zddSiftUp ARGS((DdManager *table, int x, int xLow)); -static void zddFixTree ARGS((DdManager *table, MtrNode *treenode)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Main dynamic reordering routine for ZDDs.] - - Description [Main dynamic reordering routine for ZDDs. - Calls one of the possible reordering procedures: - <ul> - <li>Swapping - <li>Sifting - <li>Symmetric Sifting - </ul> - - For sifting and symmetric sifting it is possible to request reordering - to convergence.<p> - - The core of all methods is the reordering procedure - cuddZddSwapInPlace() which swaps two adjacent variables. - Returns 1 in case of success; 0 otherwise. In the case of symmetric - sifting (with and without convergence) returns 1 plus the number of - symmetric variables, in case of success.] - - SideEffects [Changes the variable order for all ZDDs and clears - the cache.] - -******************************************************************************/ -int -Cudd_zddReduceHeap( - DdManager * table /* DD manager */, - Cudd_ReorderingType heuristic /* method used for reordering */, - int minsize /* bound below which no reordering occurs */) -{ - DdHook *hook; - int result; - unsigned int nextDyn; -#ifdef DD_STATS - unsigned int initialSize; - unsigned int finalSize; -#endif - long localTime; - - /* Don't reorder if there are too many dead nodes. */ - if (table->keysZ - table->deadZ < (unsigned) minsize) - return(1); - - if (heuristic == CUDD_REORDER_SAME) { - heuristic = table->autoMethodZ; - } - if (heuristic == CUDD_REORDER_NONE) { - return(1); - } - - /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore - ** we count it. - */ - table->reorderings++; - empty = table->zero; - - localTime = util_cpu_time(); - - /* Run the hook functions. */ - hook = table->preReorderingHook; - while (hook != NULL) { - int res = (hook->f)(table, "ZDD", (void *)heuristic); - if (res == 0) return(0); - hook = hook->next; - } - - /* Clear the cache and collect garbage. */ - zddReorderPreprocess(table); - zddTotalNumberSwapping = 0; - -#ifdef DD_STATS - initialSize = table->keysZ; - - switch(heuristic) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - (void) fprintf(table->out,"#:I_RANDOM "); - break; - case CUDD_REORDER_SIFT: - case CUDD_REORDER_SIFT_CONVERGE: - case CUDD_REORDER_SYMM_SIFT: - case CUDD_REORDER_SYMM_SIFT_CONV: - (void) fprintf(table->out,"#:I_SIFTING "); - break; - case CUDD_REORDER_LINEAR: - case CUDD_REORDER_LINEAR_CONVERGE: - (void) fprintf(table->out,"#:I_LINSIFT "); - break; - default: - (void) fprintf(table->err,"Unsupported ZDD reordering method\n"); - return(0); - } - (void) fprintf(table->out,"%8d: initial size",initialSize); -#endif - - result = cuddZddTreeSifting(table,heuristic); - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - finalSize = table->keysZ; - (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); - (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", - ((double)(util_cpu_time() - localTime)/1000.0)); - (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", - zddTotalNumberSwapping); -#endif - - if (result == 0) - return(0); - - if (!zddReorderPostprocess(table)) - return(0); - - if (table->realignZ) { - if (!cuddBddAlignToZdd(table)) - return(0); - } - - nextDyn = table->keysZ * DD_DYN_RATIO; - if (table->reorderings < 20 || nextDyn > table->nextDyn) - table->nextDyn = nextDyn; - else - table->nextDyn += 20; - - table->reordered = 1; - - /* Run hook functions. */ - hook = table->postReorderingHook; - while (hook != NULL) { - int res = (hook->f)(table, "ZDD", (void *)localTime); - if (res == 0) return(0); - hook = hook->next; - } - /* Update cumulative reordering time. */ - table->reordTime += util_cpu_time() - localTime; - - return(result); - -} /* end of Cudd_zddReduceHeap */ - - -/**Function******************************************************************** - - Synopsis [Reorders ZDD variables according to given permutation.] - - Description [Reorders ZDD variables according to given permutation. - The i-th entry of the permutation array contains the index of the variable - that should be brought to the i-th level. The size of the array should be - equal or greater to the number of variables currently in use. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [Changes the ZDD variable order for all diagrams and clears - the cache.] - - SeeAlso [Cudd_zddReduceHeap] - -******************************************************************************/ -int -Cudd_zddShuffleHeap( - DdManager * table /* DD manager */, - int * permutation /* required variable permutation */) -{ - - int result; - - empty = table->zero; - zddReorderPreprocess(table); - - result = zddShuffle(table,permutation); - - if (!zddReorderPostprocess(table)) return(0); - - return(result); - -} /* end of Cudd_zddShuffleHeap */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Reorders ZDD variables according to the order of the BDD - variables.] - - Description [Reorders ZDD variables according to the order of the - BDD variables. This function can be called at the end of BDD - reordering to insure that the order of the ZDD variables is - consistent with the order of the BDD variables. The number of ZDD - variables must be a multiple of the number of BDD variables. Let - <code>M</code> be the ratio of the two numbers. cuddZddAlignToBdd - then considers the ZDD variables from <code>M*i</code> to - <code>(M+1)*i-1</code> as corresponding to BDD variable - <code>i</code>. This function should be normally called from - Cudd_ReduceHeap, which clears the cache. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [Changes the ZDD variable order for all diagrams and performs - garbage collection of the ZDD unique table.] - - SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap] - -******************************************************************************/ -int -cuddZddAlignToBdd( - DdManager * table /* DD manager */) -{ - int *invpermZ; /* permutation array */ - int M; /* ratio of ZDD variables to BDD variables */ - int i,j; /* loop indices */ - int result; /* return value */ - - /* We assume that a ratio of 0 is OK. */ - if (table->sizeZ == 0) - return(1); - - empty = table->zero; - M = table->sizeZ / table->size; - /* Check whether the number of ZDD variables is a multiple of the - ** number of BDD variables. - */ - if (M * table->size != table->sizeZ) - return(0); - /* Create and initialize the inverse permutation array. */ - invpermZ = ALLOC(int,table->sizeZ); - if (invpermZ == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < table->size; i++) { - int index = table->invperm[i]; - int indexZ = index * M; - int levelZ = table->permZ[indexZ]; - levelZ = (levelZ / M) * M; - for (j = 0; j < M; j++) { - invpermZ[M * i + j] = table->invpermZ[levelZ + j]; - } - } - /* Eliminate dead nodes. Do not scan the cache again, because we - ** assume that Cudd_ReduceHeap has already cleared it. - */ - cuddGarbageCollectZdd(table,0); - - result = zddShuffle(table, invpermZ); - FREE(invpermZ); - /* Fix the ZDD variable group tree. */ - zddFixTree(table,table->treeZ); - return(result); - -} /* end of cuddZddAlignToBdd */ - - -/**Function******************************************************************** - - Synopsis [Finds the next subtable with a larger index.] - - Description [Finds the next subtable with a larger index. Returns the - index.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddNextHigh( - DdManager * table, - int x) -{ - return(x + 1); - -} /* end of cuddZddNextHigh */ - - -/**Function******************************************************************** - - Synopsis [Finds the next subtable with a smaller index.] - - Description [Finds the next subtable with a smaller index. Returns the - index.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddNextLow( - DdManager * table, - int x) -{ - return(x - 1); - -} /* end of cuddZddNextLow */ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the - variables according to the number of keys in the subtables. - Returns the difference in number of keys between the two - variables being compared.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddUniqueCompare( - int * ptr_x, - int * ptr_y) -{ - return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]); - -} /* end of cuddZddUniqueCompare */ - - -/**Function******************************************************************** - - Synopsis [Swaps two adjacent variables.] - - Description [Swaps two adjacent variables. It assumes that no dead - nodes are present on entry to this procedure. The procedure then - guarantees that no dead nodes will be present when it terminates. - cuddZddSwapInPlace assumes that x < y. Returns the number of keys in - the table if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSwapInPlace( - DdManager * table, - int x, - int y) -{ - DdNodePtr *xlist, *ylist; - int xindex, yindex; - int xslots, yslots; - int xshift, yshift; - int oldxkeys, oldykeys; - int newxkeys, newykeys; - int i; - int posn; - DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; - DdNode *newf1, *newf0, *next; - DdNodePtr g, *lastP, *previousP; - -#ifdef DD_DEBUG - assert(x < y); - assert(cuddZddNextHigh(table,x) == y); - assert(table->subtableZ[x].keys != 0); - assert(table->subtableZ[y].keys != 0); - assert(table->subtableZ[x].dead == 0); - assert(table->subtableZ[y].dead == 0); -#endif - - zddTotalNumberSwapping++; - - /* Get parameters of x subtable. */ - xindex = table->invpermZ[x]; - xlist = table->subtableZ[x].nodelist; - oldxkeys = table->subtableZ[x].keys; - xslots = table->subtableZ[x].slots; - xshift = table->subtableZ[x].shift; - newxkeys = 0; - - yindex = table->invpermZ[y]; - ylist = table->subtableZ[y].nodelist; - oldykeys = table->subtableZ[y].keys; - yslots = table->subtableZ[y].slots; - yshift = table->subtableZ[y].shift; - newykeys = oldykeys; - - /* The nodes in the x layer that don't depend on y directly - ** will stay there; the others are put in a chain. - ** The chain is handled as a FIFO; g points to the beginning and - ** last points to the end. - */ - - g = NULL; - lastP = &g; - for (i = 0; i < xslots; i++) { - previousP = &(xlist[i]); - f = *previousP; - while (f != NULL) { - next = f->next; - f1 = cuddT(f); f0 = cuddE(f); - if ((f1->index != (DdHalfWord) yindex) && - (f0->index != (DdHalfWord) yindex)) { /* stays */ - newxkeys++; - *previousP = f; - previousP = &(f->next); - } else { - f->index = yindex; - *lastP = f; - lastP = &(f->next); - } - f = next; - } /* while there are elements in the collision chain */ - *previousP = NULL; - } /* for each slot of the x subtable */ - *lastP = NULL; - - -#ifdef DD_COUNT - table->swapSteps += oldxkeys - newxkeys; -#endif - /* Take care of the x nodes that must be re-expressed. - ** They form a linked list pointed by g. Their index has been - ** changed to yindex already. - */ - f = g; - while (f != NULL) { - next = f->next; - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); - if ((int) f1->index == yindex) { - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - f11 = empty; f10 = f1; - } - f0 = cuddE(f); - if ((int) f0->index == yindex) { - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = empty; f00 = f0; - } - - /* Decrease ref count of f1. */ - cuddSatDec(f1->ref); - /* Create the new T child. */ - if (f11 == empty) { - if (f01 != empty) { - newf1 = f01; - cuddSatInc(newf1->ref); - } - /* else case was already handled when finding nodes - ** with both children below level y - */ - } else { - /* Check xlist for triple (xindex, f11, f01). */ - posn = ddHash(f11, f01, xshift); - /* For each element newf1 in collision list xlist[posn]. */ - newf1 = xlist[posn]; - while (newf1 != NULL) { - if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { - cuddSatInc(newf1->ref); - break; /* match */ - } - newf1 = newf1->next; - } /* while newf1 */ - if (newf1 == NULL) { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto zddSwapOutOfMem; - newf1->index = xindex; newf1->ref = 1; - cuddT(newf1) = f11; - cuddE(newf1) = f01; - /* Insert newf1 in the collision list xlist[pos]; - ** increase the ref counts of f11 and f01 - */ - newxkeys++; - newf1->next = xlist[posn]; - xlist[posn] = newf1; - cuddSatInc(f11->ref); - cuddSatInc(f01->ref); - } - } - cuddT(f) = newf1; - - /* Do the same for f0. */ - /* Decrease ref count of f0. */ - cuddSatDec(f0->ref); - /* Create the new E child. */ - if (f10 == empty) { - newf0 = f00; - cuddSatInc(newf0->ref); - } else { - /* Check xlist for triple (xindex, f10, f00). */ - posn = ddHash(f10, f00, xshift); - /* For each element newf0 in collision list xlist[posn]. */ - newf0 = xlist[posn]; - while (newf0 != NULL) { - if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { - cuddSatInc(newf0->ref); - break; /* match */ - } - newf0 = newf0->next; - } /* while newf0 */ - if (newf0 == NULL) { /* no match */ - newf0 = cuddDynamicAllocNode(table); - if (newf0 == NULL) - goto zddSwapOutOfMem; - newf0->index = xindex; newf0->ref = 1; - cuddT(newf0) = f10; cuddE(newf0) = f00; - /* Insert newf0 in the collision list xlist[posn]; - ** increase the ref counts of f10 and f00. - */ - newxkeys++; - newf0->next = xlist[posn]; - xlist[posn] = newf0; - cuddSatInc(f10->ref); - cuddSatInc(f00->ref); - } - } - cuddE(f) = newf0; - - /* Insert the modified f in ylist. - ** The modified f does not already exists in ylist. - ** (Because of the uniqueness of the cofactors.) - */ - posn = ddHash(newf1, newf0, yshift); - newykeys++; - f->next = ylist[posn]; - ylist[posn] = f; - f = next; - } /* while f != NULL */ - - /* GC the y layer. */ - - /* For each node f in ylist. */ - for (i = 0; i < yslots; i++) { - previousP = &(ylist[i]); - f = *previousP; - while (f != NULL) { - next = f->next; - if (f->ref == 0) { - cuddSatDec(cuddT(f)->ref); - cuddSatDec(cuddE(f)->ref); - cuddDeallocNode(table, f); - newykeys--; - } else { - *previousP = f; - previousP = &(f->next); - } - f = next; - } /* while f */ - *previousP = NULL; - } /* for i */ - - /* Set the appropriate fields in table. */ - table->subtableZ[x].nodelist = ylist; - table->subtableZ[x].slots = yslots; - table->subtableZ[x].shift = yshift; - table->subtableZ[x].keys = newykeys; - table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; - - table->subtableZ[y].nodelist = xlist; - table->subtableZ[y].slots = xslots; - table->subtableZ[y].shift = xshift; - table->subtableZ[y].keys = newxkeys; - table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; - - table->permZ[xindex] = y; table->permZ[yindex] = x; - table->invpermZ[x] = yindex; table->invpermZ[y] = xindex; - - table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; - - /* Update univ section; univ[x] remains the same. */ - table->univ[y] = cuddT(table->univ[x]); - - return (table->keysZ); - -zddSwapOutOfMem: - (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); - - return (0); - -} /* end of cuddZddSwapInPlace */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.] - - Description [Implementation of Plessier's algorithm that reorders - variables by a sequence of (non-adjacent) swaps. - <ol> - <li> Select two variables (RANDOM or HEURISTIC). - <li> Permute these variables. - <li> If the nodes have decreased accept the permutation. - <li> Otherwise reconstruct the original heap. - <li> Loop. - </ol> - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSwapping( - DdManager * table, - int lower, - int upper, - Cudd_ReorderingType heuristic) -{ - int i, j; - int max, keys; - int nvars; - int x, y; - int iterate; - int previousSize; - Move *moves, *move; - int pivot; - int modulo; - int result; - -#ifdef DD_DEBUG - /* Sanity check */ - assert(lower >= 0 && upper < table->sizeZ && lower <= upper); -#endif - - nvars = upper - lower + 1; - iterate = nvars; - - for (i = 0; i < iterate; i++) { - if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { - /* Find pivot <= id with maximum keys. */ - for (max = -1, j = lower; j <= upper; j++) { - if ((keys = table->subtableZ[j].keys) > max) { - max = keys; - pivot = j; - } - } - - modulo = upper - pivot; - if (modulo == 0) { - y = pivot; /* y = nvars-1 */ - } else { - /* y = random # from {pivot+1 .. nvars-1} */ - y = pivot + 1 + (int) (Cudd_Random() % modulo); - } - - modulo = pivot - lower - 1; - if (modulo < 1) { /* if pivot = 1 or 0 */ - x = lower; - } else { - do { /* x = random # from {0 .. pivot-2} */ - x = (int) Cudd_Random() % modulo; - } while (x == y); - /* Is this condition really needed, since x and y - are in regions separated by pivot? */ - } - } else { - x = (int) (Cudd_Random() % nvars) + lower; - do { - y = (int) (Cudd_Random() % nvars) + lower; - } while (x == y); - } - - previousSize = table->keysZ; - moves = zddSwapAny(table, x, y); - if (moves == NULL) - goto cuddZddSwappingOutOfMem; - - result = cuddZddSiftingBackward(table, moves, previousSize); - if (!result) - goto cuddZddSwappingOutOfMem; - - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - return(1); - -cuddZddSwappingOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(0); - -} /* end of cuddZddSwapping */ - - -/**Function******************************************************************** - - Synopsis [Implementation of Rudell's sifting algorithm.] - - Description [Implementation of Rudell's sifting algorithm. - Assumes that no dead nodes are present. - <ol> - <li> Order all the variables according to the number of entries - in each unique table. - <li> Sift the variable up and down, remembering each time the - total size of the DD heap. - <li> Select the best permutation. - <li> Repeat 3 and 4 for all variables. - </ol> - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; -#ifdef DD_STATS - int previousSize; -#endif - - size = table->sizeZ; - - /* Find order in which to sift variables. */ - var = NULL; - zdd_entry = ALLOC(int, size); - if (zdd_entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSiftingOutOfMem; - } - var = ALLOC(int, size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->permZ[i]; - zdd_entry[i] = table->subtableZ[x].keys; - var[i] = i; - } - - qsort((void *)var, size, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; - if (x < lower || x > upper) continue; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = cuddZddSiftingAux(table, x, lower, upper); - if (!result) - goto cuddZddSiftingOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - FREE(var); - FREE(zdd_entry); - - return(1); - -cuddZddSiftingOutOfMem: - - if (zdd_entry != NULL) FREE(zdd_entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddZddSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Swaps any two variables.] - - Description [Swaps any two variables. Returns the set of moves.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -zddSwapAny( - DdManager * table, - int x, - int y) -{ - Move *move, *moves; - int tmp, size; - int x_ref, y_ref; - int x_next, y_next; - int limit_size; - - if (x > y) { /* make x precede y */ - tmp = x; x = y; y = tmp; - } - - x_ref = x; y_ref = y; - - x_next = cuddZddNextHigh(table, x); - y_next = cuddZddNextLow(table, y); - moves = NULL; - limit_size = table->keysZ; - - for (;;) { - if (x_next == y_next) { /* x < x_next = y_next < y */ - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - size = cuddZddSwapInPlace(table, y_next, y); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; x = y; y = tmp; - - } else if (x == y_next) { /* x = y_next < y = x_next */ - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; x = y; y = tmp; - } else { - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - size = cuddZddSwapInPlace(table, y_next, y); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - x = x_next; y = y_next; - } - - x_next = cuddZddNextHigh(table, x); - y_next = cuddZddNextLow(table, y); - if (x_next > y_ref) - break; /* if x == y_ref */ - - if ((double) size > table->maxGrowth * (double) limit_size) - break; - if (size < limit_size) - limit_size = size; - } - if (y_next >= x_ref) { - size = cuddZddSwapInPlace(table, y_next, y); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - } - - return(moves); - -zddSwapAnyOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(NULL); - -} /* end of zddSwapAny */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSiftingAux( - DdManager * table, - int x, - int x_low, - int x_high) -{ - Move *move; - Move *moveUp; /* list of up move */ - Move *moveDown; /* list of down move */ - - int initial_size; - int result; - - initial_size = table->keysZ; - -#ifdef DD_DEBUG - assert(table->subtableZ[x].keys > 0); -#endif - - moveDown = NULL; - moveUp = NULL; - - if (x == x_low) { - moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); - /* after that point x --> x_high */ - if (moveDown == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveDown, - initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - - } - else if (x == x_high) { - moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); - /* after that point x --> x_low */ - if (moveUp == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveUp, initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - } - else if ((x - x_low) > (x_high - x)) { - /* must go down first:shorter */ - moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); - /* after that point x --> x_high */ - if (moveDown == NULL) - goto cuddZddSiftingAuxOutOfMem; - moveUp = cuddZddSiftingUp(table, moveDown->y, x_low, - initial_size); - if (moveUp == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveUp, initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - } - else { - moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); - /* after that point x --> x_high */ - if (moveUp == NULL) - goto cuddZddSiftingAuxOutOfMem; - moveDown = cuddZddSiftingDown(table, moveUp->x, x_high, - initial_size); - /* then move up */ - if (moveDown == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveDown, - initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *)moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *)moveUp); - moveUp = move; - } - - return(1); - -cuddZddSiftingAuxOutOfMem: - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *)moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *)moveUp); - moveUp = move; - } - - return(0); - -} /* end of cuddZddSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable up.] - - Description [Sifts a variable up. Moves y up until either it reaches - the bound (x_low) or the size of the ZDD heap increases too much. - Returns the set of moves in case of success; NULL if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddSiftingUp( - DdManager * table, - int x, - int x_low, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - - moves = NULL; - y = cuddZddNextLow(table, x); - while (y >= x_low) { - size = cuddZddSwapInPlace(table, y, x); - if (size == 0) - goto cuddZddSiftingUpOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddSiftingUpOutOfMem; - move->x = y; - move->y = x; - move->size = size; - move->next = moves; - moves = move; - - if ((double)size > (double)limit_size * table->maxGrowth) - break; - if (size < limit_size) - limit_size = size; - - x = y; - y = cuddZddNextLow(table, x); - } - return(moves); - -cuddZddSiftingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(NULL); - -} /* end of cuddZddSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable down.] - - Description [Sifts a variable down. Moves x down until either it - reaches the bound (x_high) or the size of the ZDD heap increases too - much. Returns the set of moves in case of success; NULL if memory is - full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddSiftingDown( - DdManager * table, - int x, - int x_high, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - - moves = NULL; - y = cuddZddNextHigh(table, x); - while (y <= x_high) { - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto cuddZddSiftingDownOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - if ((double)size > (double)limit_size * table->maxGrowth) - break; - if (size < limit_size) - limit_size = size; - - x = y; - y = cuddZddNextHigh(table, x); - } - return(moves); - -cuddZddSiftingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(NULL); - -} /* end of cuddZddSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the ZDD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the ZDD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSiftingBackward( - DdManager * table, - Move * moves, - int size) -{ - int i; - int i_best; - Move *move; - int res; - - /* Find the minimum size among moves. */ - i_best = -1; - for (move = moves, i = 0; move != NULL; move = move->next, i++) { - if (move->size < size) { - i_best = i; - size = move->size; - } - } - - for (move = moves, i = 0; move != NULL; move = move->next, i++) { - if (i == i_best) - break; - res = cuddZddSwapInPlace(table, move->x, move->y); - if (!res) - return(0); - if (i_best == -1 && res == size) - break; - } - - return(1); - -} /* end of cuddZddSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Prepares the ZDD heap for dynamic reordering.] - - Description [Prepares the ZDD heap for dynamic reordering. Does - garbage collection, to guarantee that there are no dead nodes; - and clears the cache, which is invalidated by dynamic reordering.] - - SideEffects [None] - -******************************************************************************/ -static void -zddReorderPreprocess( - DdManager * table) -{ - - /* Clear the cache. */ - cuddCacheFlush(table); - - /* Eliminate dead nodes. Do not scan the cache again. */ - cuddGarbageCollectZdd(table,0); - - return; - -} /* end of ddReorderPreprocess */ - - -/**Function******************************************************************** - - Synopsis [Shrinks almost empty ZDD subtables at the end of reordering - to guarantee that they have a reasonable load factor.] - - Description [Shrinks almost empty subtables at the end of reordering to - guarantee that they have a reasonable load factor. However, if there many - nodes are being reclaimed, then no resizing occurs. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddReorderPostprocess( - DdManager * table) -{ - int i, j, posn; - DdNodePtr *nodelist, *oldnodelist; - DdNode *node, *next; - unsigned int slots, oldslots; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - -#ifdef DD_VERBOSE - (void) fflush(table->out); -#endif - - /* If we have very many reclaimed nodes, we do not want to shrink - ** the subtables, because this will lead to more garbage - ** collections. More garbage collections mean shorter mean life for - ** nodes with zero reference count; hence lower probability of finding - ** a result in the cache. - */ - if (table->reclaimed > table->allocated * 0.5) return(1); - - /* Resize subtables. */ - for (i = 0; i < table->sizeZ; i++) { - int shift; - oldslots = table->subtableZ[i].slots; - if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY || - oldslots <= table->initSlots) continue; - oldnodelist = table->subtableZ[i].nodelist; - slots = oldslots >> 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - return(1); - } - table->subtableZ[i].nodelist = nodelist; - table->subtableZ[i].slots = slots; - table->subtableZ[i].shift++; - table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; -#ifdef DD_VERBOSE - (void) fprintf(table->err, - "shrunk layer %d (%d keys) from %d to %d slots\n", - i, table->subtableZ[i].keys, oldslots, slots); -#endif - - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - shift = table->subtableZ[i].shift; - for (j = 0; (unsigned) j < oldslots; j++) { - node = oldnodelist[j]; - while (node != NULL) { - next = node->next; - posn = ddHash(cuddT(node), cuddE(node), shift); - node->next = nodelist[posn]; - nodelist[posn] = node; - node = next; - } - } - FREE(oldnodelist); - - table->memused += (slots - oldslots) * sizeof(DdNode *); - table->slots += slots - oldslots; - table->minDead = (unsigned) (table->gcFrac * (double) table->slots); - table->cacheSlack = (int) ddMin(table->maxCacheHard, - DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) - - 2 * (int) table->cacheSlots; - } - /* We don't look at the constant subtable, because it is not - ** affected by reordering. - */ - - return(1); - -} /* end of zddReorderPostprocess */ - - -/**Function******************************************************************** - - Synopsis [Reorders ZDD variables according to a given permutation.] - - Description [Reorders ZDD variables according to a given permutation. - The i-th permutation array contains the index of the variable that - should be brought to the i-th level. zddShuffle assumes that no - dead nodes are present. The reordering is achieved by a series of - upward sifts. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zddShuffle( - DdManager * table, - int * permutation) -{ - int index; - int level; - int position; - int numvars; - int result; -#ifdef DD_STATS - long localTime; - int initialSize; - int finalSize; - int previousSize; -#endif - - zddTotalNumberSwapping = 0; -#ifdef DD_STATS - localTime = util_cpu_time(); - initialSize = table->keysZ; - (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", - initialSize); -#endif - - numvars = table->sizeZ; - - for (level = 0; level < numvars; level++) { - index = permutation[level]; - position = table->permZ[index]; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = zddSiftUp(table,position,level); - if (!result) return(0); -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - finalSize = table->keysZ; - (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); - (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", - ((double)(util_cpu_time() - localTime)/1000.0)); - (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", - zddTotalNumberSwapping); -#endif - - return(1); - -} /* end of zddShuffle */ - - -/**Function******************************************************************** - - Synopsis [Moves one ZDD variable up.] - - Description [Takes a ZDD variable from position x and sifts it up to - position xLow; xLow should be less than or equal to x. - Returns 1 if successful; 0 otherwise] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zddSiftUp( - DdManager * table, - int x, - int xLow) -{ - int y; - int size; - - y = cuddZddNextLow(table,x); - while (y >= xLow) { - size = cuddZddSwapInPlace(table,y,x); - if (size == 0) { - return(0); - } - x = y; - y = cuddZddNextLow(table,x); - } - return(1); - -} /* end of zddSiftUp */ - - -/**Function******************************************************************** - - Synopsis [Fixes the ZDD variable group tree after a shuffle.] - - Description [Fixes the ZDD variable group tree after a - shuffle. Assumes that the order of the variables in a terminal node - has not been changed.] - - SideEffects [Changes the ZDD variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static void -zddFixTree( - DdManager * table, - MtrNode * treenode) -{ - if (treenode == NULL) return; - treenode->low = ((int) treenode->index < table->sizeZ) ? - table->permZ[treenode->index] : treenode->index; - if (treenode->child != NULL) { - zddFixTree(table, treenode->child); - } - if (treenode->younger != NULL) - zddFixTree(table, treenode->younger); - if (treenode->parent != NULL && treenode->low < treenode->parent->low) { - treenode->parent->low = treenode->low; - treenode->parent->index = treenode->index; - } - return; - -} /* end of zddFixTree */ - diff --git a/src/bdd/cudd/cuddZddSetop.c b/src/bdd/cudd/cuddZddSetop.c deleted file mode 100644 index f1bd72f3..00000000 --- a/src/bdd/cudd/cuddZddSetop.c +++ /dev/null @@ -1,1137 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddSetop.c] - - PackageName [cudd] - - Synopsis [Set operations on ZDDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_zddIte() - <li> Cudd_zddUnion() - <li> Cudd_zddIntersect() - <li> Cudd_zddDiff() - <li> Cudd_zddDiffConst() - <li> Cudd_zddSubset1() - <li> Cudd_zddSubset0() - <li> Cudd_zddChange() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddZddIte() - <li> cuddZddUnion() - <li> cuddZddIntersect() - <li> cuddZddDiff() - <li> cuddZddChangeAux() - <li> cuddZddSubset1() - <li> cuddZddSubset0() - </ul> - Static procedures included in this module: - <ul> - <li> zdd_subset1_aux() - <li> zdd_subset0_aux() - <li> zddVarToConst() - </ul> - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddSetop.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * zdd_subset1_aux ARGS((DdManager *zdd, DdNode *P, DdNode *zvar)); -static DdNode * zdd_subset0_aux ARGS((DdManager *zdd, DdNode *P, DdNode *zvar)); -static void zddVarToConst ARGS((DdNode *f, DdNode **gp, DdNode **hp, DdNode *base, DdNode *empty)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the ITE of three ZDDs.] - - Description [Computes the ITE of three ZDDs. Returns a pointer to the - result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddIte( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddIte(dd, f, g, h); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddIte */ - - -/**Function******************************************************************** - - Synopsis [Computes the union of two ZDDs.] - - Description [Computes the union of two ZDDs. Returns a pointer to the - result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddUnion( - DdManager * dd, - DdNode * P, - DdNode * Q) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddUnion(dd, P, Q); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddUnion */ - - -/**Function******************************************************************** - - Synopsis [Computes the intersection of two ZDDs.] - - Description [Computes the intersection of two ZDDs. Returns a pointer to - the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddIntersect( - DdManager * dd, - DdNode * P, - DdNode * Q) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddIntersect(dd, P, Q); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddIntersect */ - - -/**Function******************************************************************** - - Synopsis [Computes the difference of two ZDDs.] - - Description [Computes the difference of two ZDDs. Returns a pointer to the - result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddDiffConst] - -******************************************************************************/ -DdNode * -Cudd_zddDiff( - DdManager * dd, - DdNode * P, - DdNode * Q) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddDiff(dd, P, Q); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddDiff */ - - -/**Function******************************************************************** - - Synopsis [Performs the inclusion test for ZDDs (P implies Q).] - - Description [Inclusion test for ZDDs (P implies Q). No new nodes are - generated by this procedure. Returns empty if true; - a valid pointer different from empty or DD_NON_CONSTANT otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddDiff] - -******************************************************************************/ -DdNode * -Cudd_zddDiffConst( - DdManager * zdd, - DdNode * P, - DdNode * Q) -{ - int p_top, q_top; - DdNode *empty = DD_ZERO(zdd), *t, *res; - DdManager *table = zdd; - - statLine(zdd); - if (P == empty) - return(empty); - if (Q == empty) - return(P); - if (P == Q) - return(empty); - - /* Check cache. The cache is shared by cuddZddDiff(). */ - res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q); - if (res != NULL) - return(res); - - if (cuddIsConstant(P)) - p_top = P->index; - else - p_top = zdd->permZ[P->index]; - if (cuddIsConstant(Q)) - q_top = Q->index; - else - q_top = zdd->permZ[Q->index]; - if (p_top < q_top) { - res = DD_NON_CONSTANT; - } else if (p_top > q_top) { - res = Cudd_zddDiffConst(zdd, P, cuddE(Q)); - } else { - t = Cudd_zddDiffConst(zdd, cuddT(P), cuddT(Q)); - if (t != empty) - res = DD_NON_CONSTANT; - else - res = Cudd_zddDiffConst(zdd, cuddE(P), cuddE(Q)); - } - - cuddCacheInsert2(table, cuddZddDiff, P, Q, res); - - return(res); - -} /* end of Cudd_zddDiffConst */ - - -/**Function******************************************************************** - - Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.] - - Description [Computes the positive cofactor of a ZDD w.r.t. a - variable. In terms of combinations, the result is the set of all - combinations in which the variable is asserted. Returns a pointer to - the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddSubset0] - -******************************************************************************/ -DdNode * -Cudd_zddSubset1( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *r; - - do { - dd->reordered = 0; - r = cuddZddSubset1(dd, P, var); - } while (dd->reordered == 1); - - return(r); - -} /* end of Cudd_zddSubset1 */ - - -/**Function******************************************************************** - - Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.] - - Description [Computes the negative cofactor of a ZDD w.r.t. a - variable. In terms of combinations, the result is the set of all - combinations in which the variable is negated. Returns a pointer to - the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddSubset1] - -******************************************************************************/ -DdNode * -Cudd_zddSubset0( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *r; - - do { - dd->reordered = 0; - r = cuddZddSubset0(dd, P, var); - } while (dd->reordered == 1); - - return(r); - -} /* end of Cudd_zddSubset0 */ - - -/**Function******************************************************************** - - Synopsis [Substitutes a variable with its complement in a ZDD.] - - Description [Substitutes a variable with its complement in a ZDD. - returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddChange( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *res; - - if ((unsigned int) var >= CUDD_MAXINDEX - 1) return(NULL); - - do { - dd->reordered = 0; - res = cuddZddChange(dd, P, var); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddChange */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddIte.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddIte( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *tautology, *empty; - DdNode *r,*Gv,*Gvn,*Hv,*Hvn,*t,*e; - unsigned int topf,topg,toph,v,top; - int index; - - statLine(dd); - /* Trivial cases. */ - /* One variable cases. */ - if (f == (empty = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ - return(h); - } - topf = cuddIZ(dd,f->index); - topg = cuddIZ(dd,g->index); - toph = cuddIZ(dd,h->index); - v = ddMin(topg,toph); - top = ddMin(topf,v); - - tautology = (top == CUDD_MAXINDEX) ? DD_ONE(dd) : dd->univ[top]; - if (f == tautology) { /* ITE(1,G,H) = G */ - return(g); - } - - /* From now on, f is known to not be a constant. */ - zddVarToConst(f,&g,&h,tautology,empty); - - /* Check remaining one variable cases. */ - if (g == h) { /* ITE(F,G,G) = G */ - return(g); - } - - if (g == tautology) { /* ITE(F,1,0) = F */ - if (h == empty) return(f); - } - - /* Check cache. */ - r = cuddCacheLookupZdd(dd,DD_ZDD_ITE_TAG,f,g,h); - if (r != NULL) { - return(r); - } - - /* Recompute these because they may have changed in zddVarToConst. */ - topg = cuddIZ(dd,g->index); - toph = cuddIZ(dd,h->index); - v = ddMin(topg,toph); - - if (topf < v) { - r = cuddZddIte(dd,cuddE(f),g,h); - if (r == NULL) return(NULL); - } else if (topf > v) { - if (topg > v) { - Gvn = g; - index = h->index; - } else { - Gvn = cuddE(g); - index = g->index; - } - if (toph > v) { - Hv = empty; Hvn = h; - } else { - Hv = cuddT(h); Hvn = cuddE(h); - } - e = cuddZddIte(dd,f,Gvn,Hvn); - if (e == NULL) return(NULL); - cuddRef(e); - r = cuddZddGetNode(dd,index,Hv,e); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd,e); - return(NULL); - } - cuddDeref(e); - } else { - index = f->index; - if (topg > v) { - Gv = empty; Gvn = g; - } else { - Gv = cuddT(g); Gvn = cuddE(g); - } - if (toph > v) { - Hv = empty; Hvn = h; - } else { - Hv = cuddT(h); Hvn = cuddE(h); - } - e = cuddZddIte(dd,cuddE(f),Gvn,Hvn); - if (e == NULL) return(NULL); - cuddRef(e); - t = cuddZddIte(dd,cuddT(f),Gv,Hv); - if (t == NULL) { - Cudd_RecursiveDerefZdd(dd,e); - return(NULL); - } - cuddRef(t); - r = cuddZddGetNode(dd,index,t,e); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd,e); - Cudd_RecursiveDerefZdd(dd,t); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert(dd,DD_ZDD_ITE_TAG,f,g,h,r); - - return(r); - -} /* end of cuddZddIte */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddUnion.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddUnion( - DdManager * zdd, - DdNode * P, - DdNode * Q) -{ - int p_top, q_top; - DdNode *empty = DD_ZERO(zdd), *t, *e, *res; - DdManager *table = zdd; - - statLine(zdd); - if (P == empty) - return(Q); - if (Q == empty) - return(P); - if (P == Q) - return(P); - - /* Check cache */ - res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q); - if (res != NULL) - return(res); - - if (cuddIsConstant(P)) - p_top = P->index; - else - p_top = zdd->permZ[P->index]; - if (cuddIsConstant(Q)) - q_top = Q->index; - else - q_top = zdd->permZ[Q->index]; - if (p_top < q_top) { - e = cuddZddUnion(zdd, cuddE(P), Q); - if (e == NULL) return (NULL); - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, cuddT(P), e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(e); - } else if (p_top > q_top) { - e = cuddZddUnion(zdd, P, cuddE(Q)); - if (e == NULL) return(NULL); - cuddRef(e); - res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(e); - } else { - t = cuddZddUnion(zdd, cuddT(P), cuddT(Q)); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddZddUnion(zdd, cuddE(P), cuddE(Q)); - if (e == NULL) { - Cudd_RecursiveDerefZdd(table, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, t); - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(table, cuddZddUnion, P, Q, res); - - return(res); - -} /* end of cuddZddUnion */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddIntersect.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddIntersect( - DdManager * zdd, - DdNode * P, - DdNode * Q) -{ - int p_top, q_top; - DdNode *empty = DD_ZERO(zdd), *t, *e, *res; - DdManager *table = zdd; - - statLine(zdd); - if (P == empty) - return(empty); - if (Q == empty) - return(empty); - if (P == Q) - return(P); - - /* Check cache. */ - res = cuddCacheLookup2Zdd(table, cuddZddIntersect, P, Q); - if (res != NULL) - return(res); - - if (cuddIsConstant(P)) - p_top = P->index; - else - p_top = zdd->permZ[P->index]; - if (cuddIsConstant(Q)) - q_top = Q->index; - else - q_top = zdd->permZ[Q->index]; - if (p_top < q_top) { - res = cuddZddIntersect(zdd, cuddE(P), Q); - if (res == NULL) return(NULL); - } else if (p_top > q_top) { - res = cuddZddIntersect(zdd, P, cuddE(Q)); - if (res == NULL) return(NULL); - } else { - t = cuddZddIntersect(zdd, cuddT(P), cuddT(Q)); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddZddIntersect(zdd, cuddE(P), cuddE(Q)); - if (e == NULL) { - Cudd_RecursiveDerefZdd(table, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, t); - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(table, cuddZddIntersect, P, Q, res); - - return(res); - -} /* end of cuddZddIntersect */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddDiff.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddDiff( - DdManager * zdd, - DdNode * P, - DdNode * Q) -{ - int p_top, q_top; - DdNode *empty = DD_ZERO(zdd), *t, *e, *res; - DdManager *table = zdd; - - statLine(zdd); - if (P == empty) - return(empty); - if (Q == empty) - return(P); - if (P == Q) - return(empty); - - /* Check cache. The cache is shared by Cudd_zddDiffConst(). */ - res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q); - if (res != NULL && res != DD_NON_CONSTANT) - return(res); - - if (cuddIsConstant(P)) - p_top = P->index; - else - p_top = zdd->permZ[P->index]; - if (cuddIsConstant(Q)) - q_top = Q->index; - else - q_top = zdd->permZ[Q->index]; - if (p_top < q_top) { - e = cuddZddDiff(zdd, cuddE(P), Q); - if (e == NULL) return(NULL); - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, cuddT(P), e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(e); - } else if (p_top > q_top) { - res = cuddZddDiff(zdd, P, cuddE(Q)); - if (res == NULL) return(NULL); - } else { - t = cuddZddDiff(zdd, cuddT(P), cuddT(Q)); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddZddDiff(zdd, cuddE(P), cuddE(Q)); - if (e == NULL) { - Cudd_RecursiveDerefZdd(table, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, t); - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(table, cuddZddDiff, P, Q, res); - - return(res); - -} /* end of cuddZddDiff */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddChange.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddChangeAux( - DdManager * zdd, - DdNode * P, - DdNode * zvar) -{ - int top_var, level; - DdNode *res, *t, *e; - DdNode *base = DD_ONE(zdd); - DdNode *empty = DD_ZERO(zdd); - - statLine(zdd); - if (P == empty) - return(empty); - if (P == base) - return(zvar); - - /* Check cache. */ - res = cuddCacheLookup2Zdd(zdd, cuddZddChangeAux, P, zvar); - if (res != NULL) - return(res); - - top_var = zdd->permZ[P->index]; - level = zdd->permZ[zvar->index]; - - if (top_var > level) { - res = cuddZddGetNode(zdd, zvar->index, P, DD_ZERO(zdd)); - if (res == NULL) return(NULL); - } else if (top_var == level) { - res = cuddZddGetNode(zdd, zvar->index, cuddE(P), cuddT(P)); - if (res == NULL) return(NULL); - } else { - t = cuddZddChangeAux(zdd, cuddT(P), zvar); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddZddChangeAux(zdd, cuddE(P), zvar); - if (e == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - Cudd_RecursiveDerefZdd(zdd, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(zdd, cuddZddChangeAux, P, zvar, res); - - return(res); - -} /* end of cuddZddChangeAux */ - - -/**Function******************************************************************** - - Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.] - - Description [Computes the positive cofactor of a ZDD w.r.t. a - variable. In terms of combinations, the result is the set of all - combinations in which the variable is asserted. Returns a pointer to - the result if successful; NULL otherwise. cuddZddSubset1 performs - the same function as Cudd_zddSubset1, but does not restart if - reordering has taken place. Therefore it can be called from within a - recursive procedure.] - - SideEffects [None] - - SeeAlso [cuddZddSubset0 Cudd_zddSubset1] - -******************************************************************************/ -DdNode * -cuddZddSubset1( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *zvar, *r; - DdNode *base, *empty; - - base = DD_ONE(dd); - empty = DD_ZERO(dd); - - zvar = cuddUniqueInterZdd(dd, var, base, empty); - if (zvar == NULL) { - return(NULL); - } else { - cuddRef(zvar); - r = zdd_subset1_aux(dd, P, zvar); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, zvar); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDerefZdd(dd, zvar); - } - - cuddDeref(r); - return(r); - -} /* end of cuddZddSubset1 */ - - -/**Function******************************************************************** - - Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.] - - Description [Computes the negative cofactor of a ZDD w.r.t. a - variable. In terms of combinations, the result is the set of all - combinations in which the variable is negated. Returns a pointer to - the result if successful; NULL otherwise. cuddZddSubset0 performs - the same function as Cudd_zddSubset0, but does not restart if - reordering has taken place. Therefore it can be called from within a - recursive procedure.] - - SideEffects [None] - - SeeAlso [cuddZddSubset1 Cudd_zddSubset0] - -******************************************************************************/ -DdNode * -cuddZddSubset0( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *zvar, *r; - DdNode *base, *empty; - - base = DD_ONE(dd); - empty = DD_ZERO(dd); - - zvar = cuddUniqueInterZdd(dd, var, base, empty); - if (zvar == NULL) { - return(NULL); - } else { - cuddRef(zvar); - r = zdd_subset0_aux(dd, P, zvar); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, zvar); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDerefZdd(dd, zvar); - } - - cuddDeref(r); - return(r); - -} /* end of cuddZddSubset0 */ - - -/**Function******************************************************************** - - Synopsis [Substitutes a variable with its complement in a ZDD.] - - Description [Substitutes a variable with its complement in a ZDD. - returns a pointer to the result if successful; NULL - otherwise. cuddZddChange performs the same function as - Cudd_zddChange, but does not restart if reordering has taken - place. Therefore it can be called from within a recursive - procedure.] - - SideEffects [None] - - SeeAlso [Cudd_zddChange] - -******************************************************************************/ -DdNode * -cuddZddChange( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *zvar, *res; - - zvar = cuddUniqueInterZdd(dd, var, DD_ONE(dd), DD_ZERO(dd)); - if (zvar == NULL) return(NULL); - cuddRef(zvar); - - res = cuddZddChangeAux(dd, P, zvar); - if (res == NULL) { - Cudd_RecursiveDerefZdd(dd,zvar); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDerefZdd(dd,zvar); - cuddDeref(res); - return(res); - -} /* end of cuddZddChange */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddSubset1.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -zdd_subset1_aux( - DdManager * zdd, - DdNode * P, - DdNode * zvar) -{ - int top_var, level; - DdNode *res, *t, *e; - DdNode *base, *empty; - - statLine(zdd); - base = DD_ONE(zdd); - empty = DD_ZERO(zdd); - - /* Check cache. */ - res = cuddCacheLookup2Zdd(zdd, zdd_subset1_aux, P, zvar); - if (res != NULL) - return(res); - - if (cuddIsConstant(P)) { - res = empty; - cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res); - return(res); - } - - top_var = zdd->permZ[P->index]; - level = zdd->permZ[zvar->index]; - - if (top_var > level) { - res = empty; - } else if (top_var == level) { - res = cuddT(P); - } else { - t = zdd_subset1_aux(zdd, cuddT(P), zvar); - if (t == NULL) return(NULL); - cuddRef(t); - e = zdd_subset1_aux(zdd, cuddE(P), zvar); - if (e == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - Cudd_RecursiveDerefZdd(zdd, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res); - - return(res); - -} /* end of zdd_subset1_aux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddSubset0.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -zdd_subset0_aux( - DdManager * zdd, - DdNode * P, - DdNode * zvar) -{ - int top_var, level; - DdNode *res, *t, *e; - DdNode *base, *empty; - - statLine(zdd); - base = DD_ONE(zdd); - empty = DD_ZERO(zdd); - - /* Check cache. */ - res = cuddCacheLookup2Zdd(zdd, zdd_subset0_aux, P, zvar); - if (res != NULL) - return(res); - - if (cuddIsConstant(P)) { - res = P; - cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res); - return(res); - } - - top_var = zdd->permZ[P->index]; - level = zdd->permZ[zvar->index]; - - if (top_var > level) { - res = P; - } - else if (top_var == level) { - res = cuddE(P); - } - else { - t = zdd_subset0_aux(zdd, cuddT(P), zvar); - if (t == NULL) return(NULL); - cuddRef(t); - e = zdd_subset0_aux(zdd, cuddE(P), zvar); - if (e == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - Cudd_RecursiveDerefZdd(zdd, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res); - - return(res); - -} /* end of zdd_subset0_aux */ - - -/**Function******************************************************************** - - Synopsis [Replaces variables with constants if possible (part of - canonical form).] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -zddVarToConst( - DdNode * f, - DdNode ** gp, - DdNode ** hp, - DdNode * base, - DdNode * empty) -{ - DdNode *g = *gp; - DdNode *h = *hp; - - if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ - *gp = base; - } - - if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ - *hp = empty; - } - -} /* end of zddVarToConst */ - diff --git a/src/bdd/cudd/cuddZddSymm.c b/src/bdd/cudd/cuddZddSymm.c deleted file mode 100644 index 54019892..00000000 --- a/src/bdd/cudd/cuddZddSymm.c +++ /dev/null @@ -1,1677 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddSymm.c] - - PackageName [cudd] - - Synopsis [Functions for symmetry-based ZDD variable reordering.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_zddSymmProfile() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddZddSymmCheck() - <li> cuddZddSymmSifting() - <li> cuddZddSymmSiftingConv() - </ul> - Static procedures included in this module: - <ul> - <li> cuddZddUniqueCompare() - <li> cuddZddSymmSiftingAux() - <li> cuddZddSymmSiftingConvAux() - <li> cuddZddSymmSifting_up() - <li> cuddZddSymmSifting_down() - <li> zdd_group_move() - <li> cuddZddSymmSiftingBackward() - <li> zdd_group_move_backward() - </ul> - ] - - SeeAlso [cuddSymmetry.c] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define ZDD_MV_OOM (Move *)1 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -extern int *zdd_entry; - -extern int zddTotalNumberSwapping; - -static DdNode *empty; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int cuddZddSymmSiftingAux ARGS((DdManager *table, int x, int x_low, int x_high)); -static int cuddZddSymmSiftingConvAux ARGS((DdManager *table, int x, int x_low, int x_high)); -static Move * cuddZddSymmSifting_up ARGS((DdManager *table, int x, int x_low, int initial_size)); -static Move * cuddZddSymmSifting_down ARGS((DdManager *table, int x, int x_high, int initial_size)); -static int cuddZddSymmSiftingBackward ARGS((DdManager *table, Move *moves, int size)); -static int zdd_group_move ARGS((DdManager *table, int x, int y, Move **moves)); -static int zdd_group_move_backward ARGS((DdManager *table, int x, int y)); -static void cuddZddSymmSummary ARGS((DdManager *table, int lower, int upper, int *symvars, int *symgroups)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints statistics on symmetric ZDD variables.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_zddSymmProfile( - DdManager * table, - int lower, - int upper) -{ - int i, x, gbot; - int TotalSymm = 0; - int TotalSymmGroups = 0; - int nvars; - - nvars = table->sizeZ; - - for (i = lower; i < upper; i++) { - if (table->subtableZ[i].next != (unsigned) i) { - x = i; - (void) fprintf(table->out,"Group:"); - do { - (void) fprintf(table->out," %d", table->invpermZ[x]); - TotalSymm++; - gbot = x; - x = table->subtableZ[x].next; - } while (x != i); - TotalSymmGroups++; -#ifdef DD_DEBUG - assert(table->subtableZ[gbot].next == (unsigned) i); -#endif - i = gbot; - (void) fprintf(table->out,"\n"); - } - } - (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm); - (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups); - -} /* end of Cudd_zddSymmProfile */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Checks for symmetry of x and y.] - - Description [Checks for symmetry of x and y. Ignores projection - functions, unless they are isolated. Returns 1 in case of - symmetry; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSymmCheck( - DdManager * table, - int x, - int y) -{ - int i; - DdNode *f, *f0, *f1, *f01, *f00, *f11, *f10; - int yindex; - int xsymmy = 1; - int xsymmyp = 1; - int arccount = 0; - int TotalRefCount = 0; - int symm_found; - - empty = table->zero; - - yindex = table->invpermZ[y]; - for (i = table->subtableZ[x].slots - 1; i >= 0; i--) { - f = table->subtableZ[x].nodelist[i]; - while (f != NULL) { - /* Find f1, f0, f11, f10, f01, f00 */ - f1 = cuddT(f); - f0 = cuddE(f); - if ((int) f1->index == yindex) { - f11 = cuddT(f1); - f10 = cuddE(f1); - if (f10 != empty) - arccount++; - } else { - if ((int) f0->index != yindex) { - return(0); /* f bypasses layer y */ - } - f11 = empty; - f10 = f1; - } - if ((int) f0->index == yindex) { - f01 = cuddT(f0); - f00 = cuddE(f0); - if (f00 != empty) - arccount++; - } else { - f01 = empty; - f00 = f0; - } - if (f01 != f10) - xsymmy = 0; - if (f11 != f00) - xsymmyp = 0; - if ((xsymmy == 0) && (xsymmyp == 0)) - return(0); - - f = f->next; - } /* for each element of the collision list */ - } /* for each slot of the subtable */ - - /* Calculate the total reference counts of y - ** whose else arc is not empty. - */ - for (i = table->subtableZ[y].slots - 1; i >= 0; i--) { - f = table->subtableZ[y].nodelist[i]; - while (f != NIL(DdNode)) { - if (cuddE(f) != empty) - TotalRefCount += f->ref; - f = f->next; - } - } - - symm_found = (arccount == TotalRefCount); -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (symm_found) { - int xindex = table->invpermZ[x]; - (void) fprintf(table->out, - "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", - xindex,yindex,x,y); - } -#endif - - return(symm_found); - -} /* end cuddZddSymmCheck */ - - -/**Function******************************************************************** - - Synopsis [Symmetric sifting algorithm for ZDDs.] - - Description [Symmetric sifting algorithm. - Assumes that no dead nodes are present. - <ol> - <li> Order all the variables according to the number of entries in - each unique subtable. - <li> Sift the variable up and down, remembering each time the total - size of the ZDD heap and grouping variables that are symmetric. - <li> Select the best permutation. - <li> Repeat 3 and 4 for all variables. - </ol> - Returns 1 plus the number of symmetric variables if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddZddSymmSiftingConv] - -******************************************************************************/ -int -cuddZddSymmSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int nvars; - int x; - int result; - int symvars; - int symgroups; - int iteration; -#ifdef DD_STATS - int previousSize; -#endif - - nvars = table->sizeZ; - - /* Find order in which to sift variables. */ - var = NULL; - zdd_entry = ALLOC(int, nvars); - if (zdd_entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSymmSiftingOutOfMem; - } - var = ALLOC(int, nvars); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSymmSiftingOutOfMem; - } - - for (i = 0; i < nvars; i++) { - x = table->permZ[i]; - zdd_entry[i] = table->subtableZ[x].keys; - var[i] = i; - } - - qsort((void *)var, nvars, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Initialize the symmetry of each subtable to itself. */ - for (i = lower; i <= upper; i++) - table->subtableZ[i].next = i; - - iteration = ddMin(table->siftMaxVar, nvars); - for (i = 0; i < iteration; i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - if (x < lower || x > upper) continue; - if (table->subtableZ[x].next == (unsigned) x) { - result = cuddZddSymmSiftingAux(table, x, lower, upper); - if (!result) - goto cuddZddSymmSiftingOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); -#ifdef DD_VERBOSE - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); -#endif - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } - - FREE(var); - FREE(zdd_entry); - - cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); - -#ifdef DD_STATS - (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars); - (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups); -#endif - - return(1+symvars); - -cuddZddSymmSiftingOutOfMem: - - if (zdd_entry != NULL) - FREE(zdd_entry); - if (var != NULL) - FREE(var); - - return(0); - -} /* end of cuddZddSymmSifting */ - - -/**Function******************************************************************** - - Synopsis [Symmetric sifting to convergence algorithm for ZDDs.] - - Description [Symmetric sifting to convergence algorithm for ZDDs. - Assumes that no dead nodes are present. - <ol> - <li> Order all the variables according to the number of entries in - each unique subtable. - <li> Sift the variable up and down, remembering each time the total - size of the ZDD heap and grouping variables that are symmetric. - <li> Select the best permutation. - <li> Repeat 3 and 4 for all variables. - <li> Repeat 1-4 until no further improvement. - </ol> - Returns 1 plus the number of symmetric variables if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddZddSymmSifting] - -******************************************************************************/ -int -cuddZddSymmSiftingConv( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int nvars; - int initialSize; - int x; - int result; - int symvars; - int symgroups; - int classes; - int iteration; -#ifdef DD_STATS - int previousSize; -#endif - - initialSize = table->keysZ; - - nvars = table->sizeZ; - - /* Find order in which to sift variables. */ - var = NULL; - zdd_entry = ALLOC(int, nvars); - if (zdd_entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSymmSiftingConvOutOfMem; - } - var = ALLOC(int, nvars); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSymmSiftingConvOutOfMem; - } - - for (i = 0; i < nvars; i++) { - x = table->permZ[i]; - zdd_entry[i] = table->subtableZ[x].keys; - var[i] = i; - } - - qsort((void *)var, nvars, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Initialize the symmetry of each subtable to itself - ** for first pass of converging symmetric sifting. - */ - for (i = lower; i <= upper; i++) - table->subtableZ[i].next = i; - - iteration = ddMin(table->siftMaxVar, table->sizeZ); - for (i = 0; i < iteration; i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; - if (x < lower || x > upper) continue; - /* Only sift if not in symmetry group already. */ - if (table->subtableZ[x].next == (unsigned) x) { -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = cuddZddSymmSiftingAux(table, x, lower, upper); - if (!result) - goto cuddZddSymmSiftingConvOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); -#ifdef DD_VERBOSE - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); -#endif - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } - - /* Sifting now until convergence. */ - while ((unsigned) initialSize > table->keysZ) { - initialSize = table->keysZ; -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); -#endif - /* Here we consider only one representative for each symmetry class. */ - for (x = lower, classes = 0; x <= upper; x++, classes++) { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - /* Here x is the largest index in a group. - ** Groups consists of adjacent variables. - ** Hence, the next increment of x will move it to a new group. - */ - i = table->invpermZ[x]; - zdd_entry[i] = table->subtableZ[x].keys; - var[classes] = i; - } - - qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Now sift. */ - iteration = ddMin(table->siftMaxVar, nvars); - for (i = 0; i < iteration; i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; - if ((unsigned) x >= table->subtableZ[x].next) { -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = cuddZddSymmSiftingConvAux(table, x, lower, upper); - if (!result) - goto cuddZddSymmSiftingConvOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); -#ifdef DD_VERBOSE - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); -#endif - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } /* for */ - } - - cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); - -#ifdef DD_STATS - (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n", - symvars); - (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n", - symgroups); -#endif - - FREE(var); - FREE(zdd_entry); - - return(1+symvars); - -cuddZddSymmSiftingConvOutOfMem: - - if (zdd_entry != NULL) - FREE(zdd_entry); - if (var != NULL) - FREE(var); - - return(0); - -} /* end of cuddZddSymmSiftingConv */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Given x_low <= x <= x_high moves x up and down between the - boundaries.] - - Description [Given x_low <= x <= x_high moves x up and down between the - boundaries. Finds the best position and does the required changes. - Assumes that x is not part of a symmetry group. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSymmSiftingAux( - DdManager * table, - int x, - int x_low, - int x_high) -{ - Move *move; - Move *move_up; /* list of up move */ - Move *move_down; /* list of down move */ - int initial_size; - int result; - int i; - int topbot; /* index to either top or bottom of symmetry group */ - int init_group_size, final_group_size; - - initial_size = table->keysZ; - - move_down = NULL; - move_up = NULL; - - /* Look for consecutive symmetries above x. */ - for (i = x; i > x_low; i--) { - if (!cuddZddSymmCheck(table, i - 1, i)) - break; - /* find top of i-1's symmetry */ - topbot = table->subtableZ[i - 1].next; - table->subtableZ[i - 1].next = i; - table->subtableZ[x].next = topbot; - /* x is bottom of group so its symmetry is top of i-1's - group */ - i = topbot + 1; /* add 1 for i--, new i is top of symm group */ - } - /* Look for consecutive symmetries below x. */ - for (i = x; i < x_high; i++) { - if (!cuddZddSymmCheck(table, i, i + 1)) - break; - /* find bottom of i+1's symm group */ - topbot = i + 1; - while ((unsigned) topbot < table->subtableZ[topbot].next) - topbot = table->subtableZ[topbot].next; - - table->subtableZ[topbot].next = table->subtableZ[i].next; - table->subtableZ[i].next = i + 1; - i = topbot - 1; /* add 1 for i++, - new i is bottom of symm group */ - } - - /* Now x maybe in the middle of a symmetry group. */ - if (x == x_low) { /* Sift down */ - /* Find bottom of x's symm group */ - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - - i = table->subtableZ[x].next; - init_group_size = x - i + 1; - - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - /* after that point x --> x_high, unless early term */ - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_down == NULL || - table->subtableZ[move_down->y].next != move_down->y) { - /* symmetry detected may have to make another complete - pass */ - if (move_down != NULL) - x = move_down->y; - else - x = table->subtableZ[x].next; - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - final_group_size = i - x + 1; - - if (init_group_size == final_group_size) { - /* No new symmetry groups detected, - return to best position */ - result = cuddZddSymmSiftingBackward(table, - move_down, initial_size); - } - else { - initial_size = table->keysZ; - move_up = cuddZddSymmSifting_up(table, x, x_low, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingAuxOutOfMem; - } - else if (x == x_high) { /* Sift up */ - /* Find top of x's symm group */ - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - init_group_size = i - x + 1; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - /* after that point x --> x_low, unless early term */ - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_up == NULL || - table->subtableZ[move_up->x].next != move_up->x) { - /* symmetry detected may have to make another complete - pass */ - if (move_up != NULL) - x = move_up->x; - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - final_group_size = x - i + 1; - - if (init_group_size == final_group_size) { - /* No new symmetry groups detected, - return to best position */ - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - else { - initial_size = table->keysZ; - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingAuxOutOfMem; - } - else if ((x - x_low) > (x_high - x)) { /* must go down first: - shorter */ - /* Find bottom of x's symm group */ - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - /* after that point x --> x_high, unless early term */ - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_down != NULL) { - x = move_down->y; - } - else { - x = table->subtableZ[x].next; - } - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - init_group_size = i - x + 1; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_up == NULL || - table->subtableZ[move_up->x].next != move_up->x) { - /* symmetry detected may have to make another complete - pass */ - if (move_up != NULL) { - x = move_up->x; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - final_group_size = x - i + 1; - - if (init_group_size == final_group_size) { - /* No new symmetry groups detected, - return to best position */ - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - else { - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - initial_size = table->keysZ; - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingAuxOutOfMem; - } - else { /* moving up first:shorter */ - /* Find top of x's symmetry group */ - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - /* after that point x --> x_high, unless early term */ - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_up != NULL) { - x = move_up->x; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - init_group_size = x - i + 1; - - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_down == NULL || - table->subtableZ[move_down->y].next != move_down->y) { - /* symmetry detected may have to make another complete - pass */ - if (move_down != NULL) { - x = move_down->y; - } - else { - x = table->subtableZ[x].next; - } - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - final_group_size = i - x + 1; - - if (init_group_size == final_group_size) { - /* No new symmetries detected, - go back to best position */ - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - else { - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - initial_size = table->keysZ; - move_up = cuddZddSymmSifting_up(table, x, x_low, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingAuxOutOfMem; - } - - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - - return(1); - -cuddZddSymmSiftingAuxOutOfMem: - if (move_down != ZDD_MV_OOM) { - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - } - if (move_up != ZDD_MV_OOM) { - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - } - - return(0); - -} /* end of cuddZddSymmSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Given x_low <= x <= x_high moves x up and down between the - boundaries.] - - Description [Given x_low <= x <= x_high moves x up and down between the - boundaries. Finds the best position and does the required changes. - Assumes that x is either an isolated variable, or it is the bottom of - a symmetry group. All symmetries may not have been found, because of - exceeded growth limit. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSymmSiftingConvAux( - DdManager * table, - int x, - int x_low, - int x_high) -{ - Move *move; - Move *move_up; /* list of up move */ - Move *move_down; /* list of down move */ - int initial_size; - int result; - int i; - int init_group_size, final_group_size; - - initial_size = table->keysZ; - - move_down = NULL; - move_up = NULL; - - if (x == x_low) { /* Sift down */ - i = table->subtableZ[x].next; - init_group_size = x - i + 1; - - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - /* after that point x --> x_high, unless early term */ - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_down == NULL || - table->subtableZ[move_down->y].next != move_down->y) { - /* symmetry detected may have to make another complete - pass */ - if (move_down != NULL) - x = move_down->y; - else { - while ((unsigned) x < table->subtableZ[x].next); - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - } - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - final_group_size = i - x + 1; - - if (init_group_size == final_group_size) { - /* No new symmetries detected, - go back to best position */ - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - else { - initial_size = table->keysZ; - move_up = cuddZddSymmSifting_up(table, x, x_low, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingConvAuxOutOfMem; - } - else if (x == x_high) { /* Sift up */ - /* Find top of x's symm group */ - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - init_group_size = i - x + 1; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - /* after that point x --> x_low, unless early term */ - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_up == NULL || - table->subtableZ[move_up->x].next != move_up->x) { - /* symmetry detected may have to make another complete - pass */ - if (move_up != NULL) - x = move_up->x; - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - final_group_size = x - i + 1; - - if (init_group_size == final_group_size) { - /* No new symmetry groups detected, - return to best position */ - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - else { - initial_size = table->keysZ; - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingConvAuxOutOfMem; - } - else if ((x - x_low) > (x_high - x)) { /* must go down first: - shorter */ - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - /* after that point x --> x_high */ - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_down != NULL) { - x = move_down->y; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - } - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - init_group_size = i - x + 1; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_up == NULL || - table->subtableZ[move_up->x].next != move_up->x) { - /* symmetry detected may have to make another complete - pass */ - if (move_up != NULL) { - x = move_up->x; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - final_group_size = x - i + 1; - - if (init_group_size == final_group_size) { - /* No new symmetry groups detected, - return to best position */ - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - else { - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - initial_size = table->keysZ; - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingConvAuxOutOfMem; - } - else { /* moving up first:shorter */ - /* Find top of x's symmetry group */ - x = table->subtableZ[x].next; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - /* after that point x --> x_high, unless early term */ - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_up != NULL) { - x = move_up->x; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - init_group_size = x - i + 1; - - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_down == NULL || - table->subtableZ[move_down->y].next != move_down->y) { - /* symmetry detected may have to make another complete - pass */ - if (move_down != NULL) { - x = move_down->y; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - } - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - final_group_size = i - x + 1; - - if (init_group_size == final_group_size) { - /* No new symmetries detected, - go back to best position */ - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - else { - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - initial_size = table->keysZ; - move_up = cuddZddSymmSifting_up(table, x, x_low, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingConvAuxOutOfMem; - } - - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - - return(1); - -cuddZddSymmSiftingConvAuxOutOfMem: - if (move_down != ZDD_MV_OOM) { - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - } - if (move_up != ZDD_MV_OOM) { - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - } - - return(0); - -} /* end of cuddZddSymmSiftingConvAux */ - - -/**Function******************************************************************** - - Synopsis [Moves x up until either it reaches the bound (x_low) or - the size of the ZDD heap increases too much.] - - Description [Moves x up until either it reaches the bound (x_low) or - the size of the ZDD heap increases too much. Assumes that x is the top - of a symmetry group. Checks x for symmetry to the adjacent - variables. If symmetry is found, the symmetry group of x is merged - with the symmetry group of the other variable. Returns the set of - moves in case of success; ZDD_MV_OOM if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddSymmSifting_up( - DdManager * table, - int x, - int x_low, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - int i, gytop; - - moves = NULL; - y = cuddZddNextLow(table, x); - while (y >= x_low) { - gytop = table->subtableZ[y].next; - if (cuddZddSymmCheck(table, y, x)) { - /* Symmetry found, attach symm groups */ - table->subtableZ[y].next = x; - i = table->subtableZ[x].next; - while (table->subtableZ[i].next != (unsigned) x) - i = table->subtableZ[i].next; - table->subtableZ[i].next = gytop; - } - else if ((table->subtableZ[x].next == (unsigned) x) && - (table->subtableZ[y].next == (unsigned) y)) { - /* x and y have self symmetry */ - size = cuddZddSwapInPlace(table, y, x); - if (size == 0) - goto cuddZddSymmSifting_upOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddSymmSifting_upOutOfMem; - move->x = y; - move->y = x; - move->size = size; - move->next = moves; - moves = move; - if ((double)size > - (double)limit_size * table->maxGrowth) - return(moves); - if (size < limit_size) - limit_size = size; - } - else { /* Group move */ - size = zdd_group_move(table, y, x, &moves); - if ((double)size > - (double)limit_size * table->maxGrowth) - return(moves); - if (size < limit_size) - limit_size = size; - } - x = gytop; - y = cuddZddNextLow(table, x); - } - - return(moves); - -cuddZddSymmSifting_upOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(ZDD_MV_OOM); - -} /* end of cuddZddSymmSifting_up */ - - -/**Function******************************************************************** - - Synopsis [Moves x down until either it reaches the bound (x_high) or - the size of the ZDD heap increases too much.] - - Description [Moves x down until either it reaches the bound (x_high) - or the size of the ZDD heap increases too much. Assumes that x is the - bottom of a symmetry group. Checks x for symmetry to the adjacent - variables. If symmetry is found, the symmetry group of x is merged - with the symmetry group of the other variable. Returns the set of - moves in case of success; ZDD_MV_OOM if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddSymmSifting_down( - DdManager * table, - int x, - int x_high, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - int i, gxtop, gybot; - - moves = NULL; - y = cuddZddNextHigh(table, x); - while (y <= x_high) { - gybot = table->subtableZ[y].next; - while (table->subtableZ[gybot].next != (unsigned) y) - gybot = table->subtableZ[gybot].next; - if (cuddZddSymmCheck(table, x, y)) { - /* Symmetry found, attach symm groups */ - gxtop = table->subtableZ[x].next; - table->subtableZ[x].next = y; - i = table->subtableZ[y].next; - while (table->subtableZ[i].next != (unsigned) y) - i = table->subtableZ[i].next; - table->subtableZ[i].next = gxtop; - } - else if ((table->subtableZ[x].next == (unsigned) x) && - (table->subtableZ[y].next == (unsigned) y)) { - /* x and y have self symmetry */ - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto cuddZddSymmSifting_downOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddSymmSifting_downOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double)size > - (double)limit_size * table->maxGrowth) - return(moves); - if (size < limit_size) - limit_size = size; - x = y; - y = cuddZddNextHigh(table, x); - } - else { /* Group move */ - size = zdd_group_move(table, x, y, &moves); - if ((double)size > - (double)limit_size * table->maxGrowth) - return(moves); - if (size < limit_size) - limit_size = size; - } - x = gybot; - y = cuddZddNextHigh(table, x); - } - - return(moves); - -cuddZddSymmSifting_downOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(ZDD_MV_OOM); - -} /* end of cuddZddSymmSifting_down */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the ZDD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the ZDD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSymmSiftingBackward( - DdManager * table, - Move * moves, - int size) -{ - int i; - int i_best; - Move *move; - int res; - - i_best = -1; - for (move = moves, i = 0; move != NULL; move = move->next, i++) { - if (move->size < size) { - i_best = i; - size = move->size; - } - } - - for (move = moves, i = 0; move != NULL; move = move->next, i++) { - if (i == i_best) break; - if ((table->subtableZ[move->x].next == move->x) && - (table->subtableZ[move->y].next == move->y)) { - res = cuddZddSwapInPlace(table, move->x, move->y); - if (!res) return(0); - } - else { /* Group move necessary */ - res = zdd_group_move_backward(table, move->x, move->y); - } - if (i_best == -1 && res == size) - break; - } - - return(1); - -} /* end of cuddZddSymmSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Swaps two groups.] - - Description [Swaps two groups. x is assumed to be the bottom variable - of the first group. y is assumed to be the top variable of the second - group. Updates the list of moves. Returns the number of keys in the - table if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zdd_group_move( - DdManager * table, - int x, - int y, - Move ** moves) -{ - Move *move; - int size; - int i, temp, gxtop, gxbot, gytop, gybot, yprev; - int swapx, swapy; - -#ifdef DD_DEBUG - assert(x < y); /* we assume that x < y */ -#endif - /* Find top and bottom for the two groups. */ - gxtop = table->subtableZ[x].next; - gytop = y; - gxbot = x; - gybot = table->subtableZ[y].next; - while (table->subtableZ[gybot].next != (unsigned) y) - gybot = table->subtableZ[gybot].next; - yprev = gybot; - - while (x <= y) { - while (y > gxtop) { - /* Set correct symmetries. */ - temp = table->subtableZ[x].next; - if (temp == x) - temp = y; - i = gxtop; - for (;;) { - if (table->subtableZ[i].next == (unsigned) x) { - table->subtableZ[i].next = y; - break; - } else { - i = table->subtableZ[i].next; - } - } - if (table->subtableZ[y].next != (unsigned) y) { - table->subtableZ[x].next = table->subtableZ[y].next; - } else { - table->subtableZ[x].next = x; - } - - if (yprev != y) { - table->subtableZ[yprev].next = x; - } else { - yprev = x; - } - table->subtableZ[y].next = temp; - - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto zdd_group_moveOutOfMem; - swapx = x; - swapy = y; - y = x; - x--; - } /* while y > gxtop */ - - /* Trying to find the next y. */ - if (table->subtableZ[y].next <= (unsigned) y) { - gybot = y; - } else { - y = table->subtableZ[y].next; - } - - yprev = gxtop; - gxtop++; - gxbot++; - x = gxbot; - } /* while x <= y, end of group movement */ - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zdd_group_moveOutOfMem; - move->x = swapx; - move->y = swapy; - move->size = table->keysZ; - move->next = *moves; - *moves = move; - - return(table->keysZ); - -zdd_group_moveOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *)(*moves)); - *moves = move; - } - return(0); - -} /* end of zdd_group_move */ - - -/**Function******************************************************************** - - Synopsis [Undoes the swap of two groups.] - - Description [Undoes the swap of two groups. x is assumed to be the - bottom variable of the first group. y is assumed to be the top - variable of the second group. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zdd_group_move_backward( - DdManager * table, - int x, - int y) -{ - int size; - int i, temp, gxtop, gxbot, gytop, gybot, yprev; - -#ifdef DD_DEBUG - assert(x < y); /* we assume that x < y */ -#endif - /* Find top and bottom of the two groups. */ - gxtop = table->subtableZ[x].next; - gytop = y; - gxbot = x; - gybot = table->subtableZ[y].next; - while (table->subtableZ[gybot].next != (unsigned) y) - gybot = table->subtableZ[gybot].next; - yprev = gybot; - - while (x <= y) { - while (y > gxtop) { - /* Set correct symmetries. */ - temp = table->subtableZ[x].next; - if (temp == x) - temp = y; - i = gxtop; - for (;;) { - if (table->subtableZ[i].next == (unsigned) x) { - table->subtableZ[i].next = y; - break; - } else { - i = table->subtableZ[i].next; - } - } - if (table->subtableZ[y].next != (unsigned) y) { - table->subtableZ[x].next = table->subtableZ[y].next; - } else { - table->subtableZ[x].next = x; - } - - if (yprev != y) { - table->subtableZ[yprev].next = x; - } else { - yprev = x; - } - table->subtableZ[y].next = temp; - - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - return(0); - y = x; - x--; - } /* while y > gxtop */ - - /* Trying to find the next y. */ - if (table->subtableZ[y].next <= (unsigned) y) { - gybot = y; - } else { - y = table->subtableZ[y].next; - } - - yprev = gxtop; - gxtop++; - gxbot++; - x = gxbot; - } /* while x <= y, end of group movement backward */ - - return(size); - -} /* end of zdd_group_move_backward */ - - -/**Function******************************************************************** - - Synopsis [Counts numbers of symmetric variables and symmetry - groups.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -static void -cuddZddSymmSummary( - DdManager * table, - int lower, - int upper, - int * symvars, - int * symgroups) -{ - int i,x,gbot; - int TotalSymm = 0; - int TotalSymmGroups = 0; - - for (i = lower; i <= upper; i++) { - if (table->subtableZ[i].next != (unsigned) i) { - TotalSymmGroups++; - x = i; - do { - TotalSymm++; - gbot = x; - x = table->subtableZ[x].next; - } while (x != i); -#ifdef DD_DEBUG - assert(table->subtableZ[gbot].next == (unsigned) i); -#endif - i = gbot; - } - } - *symvars = TotalSymm; - *symgroups = TotalSymmGroups; - - return; - -} /* end of cuddZddSymmSummary */ - diff --git a/src/bdd/cudd/cuddZddUtil.c b/src/bdd/cudd/cuddZddUtil.c deleted file mode 100644 index 616d16d4..00000000 --- a/src/bdd/cudd/cuddZddUtil.c +++ /dev/null @@ -1,1021 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddUtil.c] - - PackageName [cudd] - - Synopsis [Utility functions for ZDDs.] - - Description [External procedures included in this module: - <ul> - <li> Cudd_zddPrintMinterm() - <li> Cudd_zddPrintCover() - <li> Cudd_zddPrintDebug() - <li> Cudd_zddDumpDot() - </ul> - Internal procedures included in this module: - <ul> - <li> cuddZddP() - </ul> - Static procedures included in this module: - <ul> - <li> zp2() - <li> zdd_print_minterm_aux() - </ul> - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddUtil.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int zp2 ARGS((DdManager *zdd, DdNode *f, st_table *t)); -static void zdd_print_minterm_aux ARGS((DdManager *zdd, DdNode *node, int level, int *list)); -static void zddPrintCoverAux ARGS((DdManager *zdd, DdNode *node, int level, int *list)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints a disjoint sum of product form for a ZDD.] - - Description [Prints a disjoint sum of product form for a ZDD. Returns 1 - if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddPrintDebug Cudd_zddPrintCover] - -******************************************************************************/ -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(DdNode *, nvars+1); - if (gen->stack.stack == NULL) { - zdd->errorCode = CUDD_MEMORY_OUT; - FREE(gen->gen.cubes.cube); - FREE(gen); - return(NULL); - } - for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL; - - /* Find the first path of the ZDD. */ - gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++; - - while (1) { - top = gen->stack.stack[gen->stack.sp-1]; - if (!cuddIsConstant(top)) { - /* Take the else branch first. */ - gen->gen.cubes.cube[top->index] = 0; - next = cuddE(top); - gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; - } else if (top == DD_ZERO(zdd)) { - /* Backtrack. */ - while (1) { - if (gen->stack.sp == 1) { - /* The current node has no predecessor. */ - gen->status = CUDD_GEN_EMPTY; - gen->stack.sp--; - goto done; - } - prev = gen->stack.stack[gen->stack.sp-2]; - next = cuddT(prev); - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[prev->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[prev->index] = 2; - gen->stack.sp--; - top = gen->stack.stack[gen->stack.sp-1]; - } - } else { - gen->status = CUDD_GEN_NONEMPTY; - gen->gen.cubes.value = cuddV(top); - goto done; - } - } - -done: - *path = gen->gen.cubes.cube; - return(gen); - -} /* end of Cudd_zddFirstPath */ - - -/**Function******************************************************************** - - Synopsis [Generates the next path of a ZDD.] - - Description [Generates the next path of a ZDD onset, - using generator gen. Returns 0 if the enumeration is completed; 1 - otherwise.] - - SideEffects [The path is returned as a side effect. The - generator is modified.] - - SeeAlso [Cudd_zddForeachPath Cudd_zddFirstPath Cudd_GenFree - Cudd_IsGenEmpty] - -******************************************************************************/ -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 = gen->stack.stack[gen->stack.sp-2]; - next = cuddT(prev); - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[prev->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[prev->index] = 2; - gen->stack.sp--; - } - - while (1) { - top = gen->stack.stack[gen->stack.sp-1]; - if (!cuddIsConstant(top)) { - /* Take the else branch first. */ - gen->gen.cubes.cube[top->index] = 0; - next = cuddE(top); - gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; - } else if (top == DD_ZERO(zdd)) { - /* Backtrack. */ - while (1) { - if (gen->stack.sp == 1) { - /* The current node has no predecessor. */ - gen->status = CUDD_GEN_EMPTY; - gen->stack.sp--; - goto done; - } - prev = gen->stack.stack[gen->stack.sp-2]; - next = cuddT(prev); - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[prev->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[prev->index] = 2; - gen->stack.sp--; - top = gen->stack.stack[gen->stack.sp-1]; - } - } else { - gen->status = CUDD_GEN_NONEMPTY; - gen->gen.cubes.value = cuddV(top); - goto done; - } - } - -done: - if (gen->status == CUDD_GEN_EMPTY) return(0); - *path = gen->gen.cubes.cube; - return(1); - -} /* end of Cudd_zddNextPath */ - - -/**Function******************************************************************** - - Synopsis [Converts a path of a ZDD representing a cover to a string.] - - Description [Converts a path of a ZDD representing a cover to a - string. The string represents an implicant of the cover. The path - is typically produced by Cudd_zddForeachPath. Returns a pointer to - the string if successful; NULL otherwise. If the str input is NULL, - it allocates a new string. The string passed to this function must - have enough room for all variables and for the terminator.] - - SideEffects [None] - - SeeAlso [Cudd_zddForeachPath] - -******************************************************************************/ -char * -Cudd_zddCoverPathToString( - DdManager *zdd /* DD manager */, - int *path /* path of ZDD representing a cover */, - char *str /* pointer to string to use if != NULL */ - ) -{ - int nvars = zdd->sizeZ; - int i; - char *res; - - if (nvars & 1) return(NULL); - nvars >>= 1; - if (str == NULL) { - res = ALLOC(char, nvars+1); - if (res == NULL) return(NULL); - } else { - res = str; - } - for (i = 0; i < nvars; i++) { - int v = (path[2*i] << 2) | path[2*i+1]; - switch (v) { - case 0: - case 2: - case 8: - case 10: - res[i] = '-'; - break; - case 1: - case 9: - res[i] = '0'; - break; - case 4: - case 6: - res[i] = '1'; - break; - default: - res[i] = '?'; - } - } - res[nvars] = 0; - - return(res); - -} /* end of Cudd_zddCoverPathToString */ - - -/**Function******************************************************************** - - Synopsis [Writes a dot file representing the argument ZDDs.] - - Description [Writes a file representing the argument ZDDs in a format - suitable for the graph drawing program dot. - It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, - file system full). - Cudd_zddDumpDot does not close the file: This is the caller - responsibility. Cudd_zddDumpDot uses a minimal unique subset of the - hexadecimal address of a node as name for it. - If the argument inames is non-null, it is assumed to hold the pointers - to the names of the inputs. Similarly for onames. - Cudd_zddDumpDot uses the following convention to draw arcs: - <ul> - <li> solid line: THEN arcs; - <li> dashed line: ELSE arcs. - </ul> - The dot options are chosen so that the drawing fits on a letter-size - sheet. - ] - - SideEffects [None] - - SeeAlso [Cudd_DumpDot Cudd_zddPrintDebug] - -******************************************************************************/ -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_Support(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, (char **) &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,"\"%lx\";\n", (mask & (long) 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,"\"%lx\";\n", (mask & (long) 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," -> \"%lx\" [style = solid];\n", - (mask & (long) 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, - "\"%lx\" -> \"%lx\";\n", - (mask & (long) scan) / sizeof(DdNode), - (mask & (long) cuddT(scan)) / sizeof(DdNode)); - if (retval == EOF) goto failure; - retval = fprintf(fp, - "\"%lx\" -> \"%lx\" [style = dashed];\n", - (mask & (long) scan) / sizeof(DdNode), - (mask & (long) 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,"\"%lx\" [label = \"%g\"];\n", - (mask & (long) 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 (support != NULL) Cudd_RecursiveDeref(dd,support); - 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 = %d\tr = %d\t", - (unsigned long)f / (unsigned long) sizeof(DdNode), f->index, f->ref); -#else - (void) fprintf(zdd->out, "ID = 0x%x\tindex = %d\tr = %d\t", - (unsigned)f / (unsigned) 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", (unsigned long) n / - (unsigned long) sizeof(DdNode)); -#else - (void) fprintf(zdd->out, "T = 0x%x\t", (unsigned) n / (unsigned) 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", (unsigned long) n / - (unsigned long) sizeof(DdNode)); -#else - (void) fprintf(zdd->out, "E = 0x%x\n", (unsigned) n / (unsigned) 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 */ diff --git a/src/bdd/cudd/module.make b/src/bdd/cudd/module.make deleted file mode 100644 index c526a50e..00000000 --- a/src/bdd/cudd/module.make +++ /dev/null @@ -1,61 +0,0 @@ -SRC += src/bdd/cudd/cuddAPI.c \ - src/bdd/cudd/cuddAddAbs.c \ - src/bdd/cudd/cuddAddApply.c \ - src/bdd/cudd/cuddAddFind.c \ - src/bdd/cudd/cuddAddInv.c \ - src/bdd/cudd/cuddAddIte.c \ - src/bdd/cudd/cuddAddNeg.c \ - src/bdd/cudd/cuddAddWalsh.c \ - src/bdd/cudd/cuddAndAbs.c \ - src/bdd/cudd/cuddAnneal.c \ - src/bdd/cudd/cuddApa.c \ - src/bdd/cudd/cuddApprox.c \ - src/bdd/cudd/cuddBddAbs.c \ - src/bdd/cudd/cuddBddCorr.c \ - src/bdd/cudd/cuddBddIte.c \ - src/bdd/cudd/cuddBridge.c \ - src/bdd/cudd/cuddCache.c \ - src/bdd/cudd/cuddCheck.c \ - src/bdd/cudd/cuddClip.c \ - src/bdd/cudd/cuddCof.c \ - src/bdd/cudd/cuddCompose.c \ - src/bdd/cudd/cuddDecomp.c \ - src/bdd/cudd/cuddEssent.c \ - src/bdd/cudd/cuddExact.c \ - src/bdd/cudd/cuddExport.c \ - src/bdd/cudd/cuddGenCof.c \ - src/bdd/cudd/cuddGenetic.c \ - src/bdd/cudd/cuddGroup.c \ - src/bdd/cudd/cuddHarwell.c \ - src/bdd/cudd/cuddInit.c \ - src/bdd/cudd/cuddInteract.c \ - src/bdd/cudd/cuddLCache.c \ - src/bdd/cudd/cuddLevelQ.c \ - src/bdd/cudd/cuddLinear.c \ - src/bdd/cudd/cuddLiteral.c \ - src/bdd/cudd/cuddMatMult.c \ - src/bdd/cudd/cuddPriority.c \ - src/bdd/cudd/cuddRead.c \ - src/bdd/cudd/cuddRef.c \ - src/bdd/cudd/cuddReorder.c \ - src/bdd/cudd/cuddSat.c \ - src/bdd/cudd/cuddSign.c \ - src/bdd/cudd/cuddSolve.c \ - src/bdd/cudd/cuddSplit.c \ - src/bdd/cudd/cuddSubsetHB.c \ - src/bdd/cudd/cuddSubsetSP.c \ - src/bdd/cudd/cuddSymmetry.c \ - src/bdd/cudd/cuddTable.c \ - src/bdd/cudd/cuddUtil.c \ - src/bdd/cudd/cuddWindow.c \ - src/bdd/cudd/cuddZddCount.c \ - src/bdd/cudd/cuddZddFuncs.c \ - src/bdd/cudd/cuddZddGroup.c \ - src/bdd/cudd/cuddZddIsop.c \ - src/bdd/cudd/cuddZddLin.c \ - src/bdd/cudd/cuddZddMisc.c \ - src/bdd/cudd/cuddZddPort.c \ - src/bdd/cudd/cuddZddReord.c \ - src/bdd/cudd/cuddZddSetop.c \ - src/bdd/cudd/cuddZddSymm.c \ - src/bdd/cudd/cuddZddUtil.c diff --git a/src/bdd/cudd/r7x8.1.mat b/src/bdd/cudd/r7x8.1.mat deleted file mode 100644 index b0dd0a0a..00000000 --- a/src/bdd/cudd/r7x8.1.mat +++ /dev/null @@ -1,53 +0,0 @@ -7 9 -0 0 1 -0 1 1 -0 2 1 -0 3 4 -0 4 3 -0 5 3 -0 6 3 -0 8 3 -1 0 4 -1 1 3 -1 2 2 -1 3 4 -1 4 1 -1 5 2 -1 6 4 -1 8 3 -2 0 1 -2 1 1 -2 2 4 -2 4 2 -2 5 3 -2 6 3 -2 8 3 -3 0 2 -3 1 1 -3 3 4 -3 4 4 -3 5 1 -3 8 1 -4 0 2 -4 1 3 -4 2 2 -4 3 4 -4 4 1 -4 5 1 -4 6 2 -4 8 2 -5 0 3 -5 1 3 -5 2 4 -5 3 4 -5 4 1 -5 5 3 -5 6 3 -5 8 4 -6 1 1 -6 2 1 -6 3 4 -6 4 2 -6 5 4 -6 6 4 -6 8 2 diff --git a/src/bdd/cudd/testcudd.c b/src/bdd/cudd/testcudd.c deleted file mode 100644 index d8affadc..00000000 --- a/src/bdd/cudd/testcudd.c +++ /dev/null @@ -1,988 +0,0 @@ -/**CFile*********************************************************************** - - FileName [testcudd.c] - - PackageName [cudd] - - Synopsis [Sanity check tests for some CUDD functions.] - - Description [testcudd reads a matrix with real coefficients and - transforms it into an ADD. It then performs various operations on - the ADD and on the BDD corresponding to the ADD pattern. Finally, - testcudd tests functions relate to Walsh matrices and matrix - multiplication.] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define TESTCUDD_VERSION "TestCudd Version #1.0, Release date 3/17/01" - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: testcudd.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -static char *onames[] = { "C", "M" }; /* names of functions to be dumped */ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void usage ARGS((char * prog)); -static FILE *open_file ARGS((char *filename, char *mode)); -static int testIterators ARGS((DdManager *dd, DdNode *M, DdNode *C, int pr)); -static int testXor ARGS((DdManager *dd, DdNode *f, int pr, int nvars)); -static int testHamming ARGS((DdManager *dd, DdNode *f, int pr, int nvars)); -static int testWalsh ARGS((DdManager *dd, int N, int cmu, int approach, int pr)); - -/**AutomaticEnd***************************************************************/ - - -/**Function******************************************************************** - - Synopsis [Main function for testcudd.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -main(int argc, char **argv) -{ - FILE *fp; /* pointer to input file */ - char *file = ""; /* input file name */ - FILE *dfp = NULL; /* pointer to dump file */ - char *dfile; /* file for DD dump */ - DdNode *dfunc[2]; /* addresses of the functions to be dumped */ - DdManager *dd; /* pointer to DD manager */ - DdNode *one, *zero; /* fast access to constant functions */ - DdNode *M; - DdNode **x; /* pointers to variables */ - DdNode **y; /* pointers to variables */ - DdNode **xn; /* complements of row variables */ - DdNode **yn_; /* complements of column variables */ - DdNode **xvars; - DdNode **yvars; - DdNode *C; /* result of converting from ADD to BDD */ - DdNode *ess; /* cube of essential variables */ - DdNode *shortP; /* BDD cube of shortest path */ - DdNode *largest; /* BDD of largest cube */ - DdNode *shortA; /* ADD cube of shortest path */ - DdNode *constN; /* value returned by evaluation of ADD */ - DdNode *ycube; /* cube of the negated y vars for c-proj */ - DdNode *CP; /* C-Projection of C */ - DdNode *CPr; /* C-Selection of C */ - int length; /* length of the shortest path */ - int nx; /* number of variables */ - int ny; - int maxnx; - int maxny; - int m; - int n; - int N; - int cmu; /* use CMU multiplication */ - int pr; /* verbose printout level */ - int harwell; - int multiple; /* read multiple matrices */ - int ok; - int c; /* variable to read in options */ - int approach; /* reordering approach */ - int autodyn; /* automatic reordering */ - int groupcheck; /* option for group sifting */ - int profile; /* print heap profile if != 0 */ - int keepperm; /* keep track of permutation */ - int clearcache; /* clear the cache after each matrix */ - int blifOrDot; /* dump format: 0 -> dot, 1 -> blif, ... */ - int retval; /* return value */ - int i; /* loop index */ - long startTime; /* initial time */ - long lapTime; - int size; - unsigned int cacheSize, maxMemory; - unsigned int nvars,nslots; - - startTime = util_cpu_time(); - - approach = CUDD_REORDER_NONE; - autodyn = 0; - pr = 0; - harwell = 0; - multiple = 0; - profile = 0; - keepperm = 0; - cmu = 0; - N = 4; - nvars = 4; - cacheSize = 127; - maxMemory = 0; - nslots = CUDD_UNIQUE_SLOTS; - clearcache = 0; - groupcheck = CUDD_GROUP_CHECK7; - dfile = NULL; - blifOrDot = 0; /* dot format */ - - /* Parse command line. */ - while ((c = util_getopt(argc, argv, "CDHMPS:a:bcd:g:hkmn:p:v:x:X:")) - != EOF) { - switch(c) { - case 'C': - cmu = 1; - break; - case 'D': - autodyn = 1; - break; - case 'H': - harwell = 1; - break; - case 'M': -#ifdef MNEMOSYNE - (void) mnem_setrecording(0); -#endif - break; - case 'P': - profile = 1; - break; - case 'S': - nslots = atoi(util_optarg); - break; - case 'X': - maxMemory = atoi(util_optarg); - break; - case 'a': - approach = atoi(util_optarg); - break; - case 'b': - blifOrDot = 1; /* blif format */ - break; - case 'c': - clearcache = 1; - break; - case 'd': - dfile = util_optarg; - break; - case 'g': - groupcheck = atoi(util_optarg); - break; - case 'k': - keepperm = 1; - break; - case 'm': - multiple = 1; - break; - case 'n': - N = atoi(util_optarg); - break; - case 'p': - pr = atoi(util_optarg); - break; - case 'v': - nvars = atoi(util_optarg); - break; - case 'x': - cacheSize = atoi(util_optarg); - break; - case 'h': - default: - usage(argv[0]); - break; - } - } - - if (argc - util_optind == 0) { - file = "-"; - } else if (argc - util_optind == 1) { - file = argv[util_optind]; - } else { - usage(argv[0]); - } - if ((approach<0) || (approach>17)) { - (void) fprintf(stderr,"Invalid approach: %d \n",approach); - usage(argv[0]); - } - - if (pr >= 0) { - (void) printf("# %s\n", TESTCUDD_VERSION); - /* Echo command line and arguments. */ - (void) printf("#"); - for (i = 0; i < argc; i++) { - (void) printf(" %s", argv[i]); - } - (void) printf("\n"); - (void) fflush(stdout); - } - - /* Initialize manager and provide easy reference to terminals. */ - dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory); - one = DD_ONE(dd); - zero = DD_ZERO(dd); - dd->groupcheck = (Cudd_AggregationType) groupcheck; - if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME); - - /* Open input file. */ - fp = open_file(file, "r"); - - /* Open dump file if requested */ - if (dfile != NULL) { - dfp = open_file(dfile, "w"); - } - - x = y = xn = yn_ = NULL; - do { - /* We want to start anew for every matrix. */ - maxnx = maxny = 0; - nx = maxnx; ny = maxny; - if (pr>0) lapTime = util_cpu_time(); - if (harwell) { - if (pr >= 0) (void) printf(":name: "); - ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, - &m, &n, 0, 2, 1, 2, pr); - } else { - ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, - &m, &n, 0, 2, 1, 2); - if (pr >= 0) - (void) printf(":name: %s: %d rows %d columns\n", file, m, n); - } - if (!ok) { - (void) fprintf(stderr, "Error reading matrix\n"); - exit(1); - } - - if (nx > maxnx) maxnx = nx; - if (ny > maxny) maxny = ny; - - /* Build cube of negated y's. */ - ycube = DD_ONE(dd); - Cudd_Ref(ycube); - for (i = maxny - 1; i >= 0; i--) { - DdNode *tmpp; - tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube); - if (tmpp == NULL) exit(2); - Cudd_Ref(tmpp); - Cudd_RecursiveDeref(dd,ycube); - ycube = tmpp; - } - /* Initialize vectors of BDD variables used by priority func. */ - xvars = ALLOC(DdNode *, nx); - if (xvars == NULL) exit(2); - for (i = 0; i < nx; i++) { - xvars[i] = dd->vars[x[i]->index]; - } - yvars = ALLOC(DdNode *, ny); - if (yvars == NULL) exit(2); - for (i = 0; i < ny; i++) { - yvars[i] = dd->vars[y[i]->index]; - } - - /* Clean up */ - for (i=0; i < maxnx; i++) { - Cudd_RecursiveDeref(dd, x[i]); - Cudd_RecursiveDeref(dd, xn[i]); - } - FREE(x); - FREE(xn); - for (i=0; i < maxny; i++) { - Cudd_RecursiveDeref(dd, y[i]); - Cudd_RecursiveDeref(dd, yn_[i]); - } - FREE(y); - FREE(yn_); - - if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} - - if (pr>0) (void) printf(":2: time to read the matrix = %s\n", - util_print_time(util_cpu_time() - lapTime)); - - C = Cudd_addBddPattern(dd, M); - if (C == 0) exit(2); - Cudd_Ref(C); - if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);} - - /* Test iterators. */ - retval = testIterators(dd,M,C,pr); - if (retval == 0) exit(2); - - cuddCacheProfile(dd,stdout); - - /* Test XOR */ - retval = testXor(dd,C,pr,nx+ny); - if (retval == 0) exit(2); - - /* Test Hamming distance functions. */ - retval = testHamming(dd,C,pr,nx+ny); - if (retval == 0) exit(2); - - /* Test selection functions. */ - CP = Cudd_CProjection(dd,C,ycube); - if (CP == NULL) exit(2); - Cudd_Ref(CP); - if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);} - if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);} - - if (nx == ny) { - CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL, - (DdNode *)NULL,ny,Cudd_Xgty); - if (CPr == NULL) exit(2); - Cudd_Ref(CPr); - if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);} - if (CP != CPr) { - (void) printf("CP != CPr!\n"); - } - Cudd_RecursiveDeref(dd, CPr); - } - FREE(xvars); FREE(yvars); - - Cudd_RecursiveDeref(dd, CP); - Cudd_RecursiveDeref(dd, ycube); - - /* Test functions for essential variables. */ - ess = Cudd_FindEssential(dd,C); - if (ess == NULL) exit(2); - Cudd_Ref(ess); - if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);} - Cudd_RecursiveDeref(dd, ess); - - /* Test functions for shortest paths. */ - shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length); - if (shortP == NULL) exit(2); - Cudd_Ref(shortP); - if (pr>0) { - (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); - } - /* Test functions for largest cubes. */ - largest = Cudd_LargestCube(dd, Cudd_Not(C), &length); - if (largest == NULL) exit(2); - Cudd_Ref(largest); - if (pr>0) { - (void) printf(":5b: largest"); - Cudd_PrintDebug(dd,largest,nx+ny,pr); - } - Cudd_RecursiveDeref(dd, largest); - - /* Test Cudd_addEvalConst and Cudd_addIteConstant. */ - shortA = Cudd_BddToAdd(dd,shortP); - if (shortA == NULL) exit(2); - Cudd_Ref(shortA); - Cudd_RecursiveDeref(dd, shortP); - constN = Cudd_addEvalConst(dd,shortA,M); - if (constN == DD_NON_CONSTANT) exit(2); - if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2); - if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));} - Cudd_RecursiveDeref(dd, shortA); - - shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length); - if (shortP == NULL) exit(2); - Cudd_Ref(shortP); - if (pr>0) { - (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); - } - - /* Test Cudd_bddIteConstant and Cudd_bddLeq. */ - if (!Cudd_bddLeq(dd,shortP,C)) exit(2); - if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),one,C) != one) exit(2); - Cudd_RecursiveDeref(dd, shortP); - - if (profile) { - retval = cuddHeapProfile(dd); - } - - size = dd->size; - - if (pr>0) { - (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); - } - - /* Reorder if so requested. */ - if (approach != CUDD_REORDER_NONE) { -#ifndef DD_STATS - retval = Cudd_EnableReorderingReporting(dd); - if (retval == 0) { - (void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n"); - exit(3); - } -#endif -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); - exit(3); - } - retval = Cudd_CheckKeys(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); - exit(3); - } -#endif - retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); - if (retval == 0) { - (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); - exit(3); - } -#ifndef DD_STATS - retval = Cudd_DisableReorderingReporting(dd); - if (retval == 0) { - (void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n"); - exit(3); - } -#endif -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); - exit(3); - } - retval = Cudd_CheckKeys(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); - exit(3); - } -#endif - if (approach == CUDD_REORDER_SYMM_SIFT || - approach == CUDD_REORDER_SYMM_SIFT_CONV) { - Cudd_SymmProfile(dd,0,dd->size-1); - } - - if (pr>0) { - (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); - } - - if (keepperm) { - /* Print variable permutation. */ - (void) printf("Variable Permutation:"); - for (i=0; i<size; i++) { - if (i%20 == 0) (void) printf("\n"); - (void) printf("%d ", dd->invperm[i]); - } - (void) printf("\n"); - (void) printf("Inverse Permutation:"); - for (i=0; i<size; i++) { - if (i%20 == 0) (void) printf("\n"); - (void) printf("%d ", dd->perm[i]); - } - (void) printf("\n"); - } - - if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} - - if (profile) { - retval = cuddHeapProfile(dd); - } - - } - - /* Dump DDs of C and M if so requested. */ - if (dfile != NULL) { - dfunc[0] = C; - dfunc[1] = M; - if (blifOrDot == 1) { - /* Only dump C because blif cannot handle ADDs */ - retval = Cudd_DumpBlif(dd,1,dfunc,NULL,onames,NULL,dfp); - } else { - retval = Cudd_DumpDot(dd,2,dfunc,NULL,onames,dfp); - } - if (retval != 1) { - (void) fprintf(stderr,"abnormal termination\n"); - exit(2); - } - } - - Cudd_RecursiveDeref(dd, C); - Cudd_RecursiveDeref(dd, M); - - if (clearcache) { - if (pr>0) {(void) printf("Clearing the cache... ");} - for (i = dd->cacheSlots - 1; i>=0; i--) { - dd->cache[i].data = NIL(DdNode); - } - if (pr>0) {(void) printf("done\n");} - } - if (pr>0) { - (void) printf("Number of variables = %6d\t",dd->size); - (void) printf("Number of slots = %6d\n",dd->slots); - (void) printf("Number of keys = %6d\t",dd->keys); - (void) printf("Number of min dead = %6d\n",dd->minDead); - } - - } while (multiple && !feof(fp)); - - fclose(fp); - if (dfile != NULL) { - fclose(dfp); - } - - /* Second phase: experiment with Walsh matrices. */ - if (!testWalsh(dd,N,cmu,approach,pr)) { - exit(2); - } - - /* Check variable destruction. */ - assert(cuddDestroySubtables(dd,3)); - assert(Cudd_DebugCheck(dd) == 0); - assert(Cudd_CheckKeys(dd) == 0); - - retval = Cudd_CheckZeroRef(dd); - ok = retval != 0; /* ok == 0 means O.K. */ - if (retval != 0) { - (void) fprintf(stderr, - "%d non-zero DD reference counts after dereferencing\n", retval); - } - - if (pr >= 0) { - (void) Cudd_PrintInfo(dd,stdout); - } - - Cudd_Quit(dd); - -#ifdef MNEMOSYNE - mnem_writestats(); -#endif - - if (pr>0) (void) printf("total time = %s\n", - util_print_time(util_cpu_time() - startTime)); - - if (pr >= 0) util_print_cpu_stats(stdout); - exit(ok); - /* NOTREACHED */ - -} /* end of main */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints usage info for testcudd.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -usage(char *prog) -{ - (void) fprintf(stderr, "usage: %s [options] [file]\n", prog); - (void) fprintf(stderr, " -C\t\tuse CMU multiplication algorithm\n"); - (void) fprintf(stderr, " -D\t\tenable automatic dynamic reordering\n"); - (void) fprintf(stderr, " -H\t\tread matrix in Harwell format\n"); - (void) fprintf(stderr, " -M\t\tturns off memory allocation recording\n"); - (void) fprintf(stderr, " -P\t\tprint BDD heap profile\n"); - (void) fprintf(stderr, " -S n\t\tnumber of slots for each subtable\n"); - (void) fprintf(stderr, " -X n\t\ttarget maximum memory in bytes\n"); - (void) fprintf(stderr, " -a n\t\tchoose reordering approach (0-13)\n"); - (void) fprintf(stderr, " \t\t\t0: same as autoMethod\n"); - (void) fprintf(stderr, " \t\t\t1: no reordering (default)\n"); - (void) fprintf(stderr, " \t\t\t2: random\n"); - (void) fprintf(stderr, " \t\t\t3: pivot\n"); - (void) fprintf(stderr, " \t\t\t4: sifting\n"); - (void) fprintf(stderr, " \t\t\t5: sifting to convergence\n"); - (void) fprintf(stderr, " \t\t\t6: symmetric sifting\n"); - (void) fprintf(stderr, " \t\t\t7: symmetric sifting to convergence\n"); - (void) fprintf(stderr, " \t\t\t8-10: window of size 2-4\n"); - (void) fprintf(stderr, " \t\t\t11-13: window of size 2-4 to conv.\n"); - (void) fprintf(stderr, " \t\t\t14: group sifting\n"); - (void) fprintf(stderr, " \t\t\t15: group sifting to convergence\n"); - (void) fprintf(stderr, " \t\t\t16: simulated annealing\n"); - (void) fprintf(stderr, " \t\t\t17: genetic algorithm\n"); - (void) fprintf(stderr, " -b\t\tuse blif as format for dumps\n"); - (void) fprintf(stderr, " -c\t\tclear the cache after each matrix\n"); - (void) fprintf(stderr, " -d file\tdump DDs to file\n"); - (void) fprintf(stderr, " -g\t\tselect aggregation criterion (0,5,7)\n"); - (void) fprintf(stderr, " -h\t\tprints this message\n"); - (void) fprintf(stderr, " -k\t\tprint the variable permutation\n"); - (void) fprintf(stderr, " -m\t\tread multiple matrices (only with -H)\n"); - (void) fprintf(stderr, " -n n\t\tnumber of variables\n"); - (void) fprintf(stderr, " -p n\t\tcontrol verbosity\n"); - (void) fprintf(stderr, " -v n\t\tinitial variables in the unique table\n"); - (void) fprintf(stderr, " -x n\t\tinitial size of the cache\n"); - exit(2); -} /* end of usage */ - - -/**Function******************************************************************** - - Synopsis [Opens a file.] - - Description [Opens a file, or fails with an error message and exits. - Allows '-' as a synonym for standard input.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static FILE * -open_file(char *filename, char *mode) -{ - FILE *fp; - - if (strcmp(filename, "-") == 0) { - return mode[0] == 'r' ? stdin : stdout; - } else if ((fp = fopen(filename, mode)) == NULL) { - perror(filename); - exit(1); - } - return fp; - -} /* end of open_file */ - - -/**Function******************************************************************** - - Synopsis [Tests Walsh matrix multiplication.] - - Description [Tests Walsh matrix multiplication. Return 1 if successful; - 0 otherwise.] - - SideEffects [May create new variables in the manager.] - - SeeAlso [] - -******************************************************************************/ -static int -testWalsh( - DdManager *dd /* manager */, - int N /* number of variables */, - int cmu /* use CMU approach to matrix multiplication */, - int approach /* reordering approach */, - int pr /* verbosity level */) -{ - DdNode *walsh1, *walsh2, *wtw; - DdNode **x, **v, **z; - int i, retval; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - - if (N > 3) { - x = ALLOC(DdNode *,N); - v = ALLOC(DdNode *,N); - z = ALLOC(DdNode *,N); - - for (i = N-1; i >= 0; i--) { - Cudd_Ref(x[i]=cuddUniqueInter(dd,3*i,one,zero)); - Cudd_Ref(v[i]=cuddUniqueInter(dd,3*i+1,one,zero)); - Cudd_Ref(z[i]=cuddUniqueInter(dd,3*i+2,one,zero)); - } - Cudd_Ref(walsh1 = Cudd_addWalsh(dd,v,z,N)); - if (pr>0) {(void) printf("walsh1"); Cudd_PrintDebug(dd,walsh1,2*N,pr);} - Cudd_Ref(walsh2 = Cudd_addWalsh(dd,x,v,N)); - if (cmu) { - Cudd_Ref(wtw = Cudd_addTimesPlus(dd,walsh2,walsh1,v,N)); - } else { - Cudd_Ref(wtw = Cudd_addMatrixMultiply(dd,walsh2,walsh1,v,N)); - } - if (pr>0) {(void) printf("wtw"); Cudd_PrintDebug(dd,wtw,2*N,pr);} - - if (approach != CUDD_REORDER_NONE) { -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); - return(0); - } -#endif - retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); - if (retval == 0) { - (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); - return(0); - } -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); - return(0); - } -#endif - if (approach == CUDD_REORDER_SYMM_SIFT || - approach == CUDD_REORDER_SYMM_SIFT_CONV) { - Cudd_SymmProfile(dd,0,dd->size-1); - } - } - /* Clean up. */ - Cudd_RecursiveDeref(dd, wtw); - Cudd_RecursiveDeref(dd, walsh1); - Cudd_RecursiveDeref(dd, walsh2); - for (i=0; i < N; i++) { - Cudd_RecursiveDeref(dd, x[i]); - Cudd_RecursiveDeref(dd, v[i]); - Cudd_RecursiveDeref(dd, z[i]); - } - FREE(x); - FREE(v); - FREE(z); - } - return(1); - -} /* end of testWalsh */ - -/**Function******************************************************************** - - Synopsis [Tests iterators.] - - Description [Tests iterators on cubes and nodes.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -testIterators( - DdManager *dd, - DdNode *M, - DdNode *C, - int pr) -{ - int *cube; - CUDD_VALUE_TYPE value; - DdGen *gen; - int q; - - /* Test iterator for cubes. */ - if (pr>1) { - (void) printf("Testing iterator on cubes:\n"); - Cudd_ForeachCube(dd,M,gen,cube,value) { - for (q = 0; q < dd->size; q++) { - switch (cube[q]) { - case 0: - (void) printf("0"); - break; - case 1: - (void) printf("1"); - break; - case 2: - (void) printf("-"); - break; - default: - (void) printf("?"); - } - } - (void) printf(" %g\n",value); - } - (void) printf("\n"); - } - - if (pr>1) { - (void) printf("Testing prime expansion of cubes:\n"); - if (!Cudd_bddPrintCover(dd,C,C)) return(0); - } - - /* Test iterator on nodes. */ - if (pr>2) { - DdGen *gen; - DdNode *node; - (void) printf("Testing iterator on nodes:\n"); - Cudd_ForeachNode(dd,M,gen,node) { - if (Cudd_IsConstant(node)) { -#if SIZEOF_VOID_P == 8 - (void) printf("ID = 0x%lx\tvalue = %-9g\n", - (unsigned long) node / - (unsigned long) sizeof(DdNode), - Cudd_V(node)); -#else - (void) printf("ID = 0x%x\tvalue = %-9g\n", - (unsigned int) node / - (unsigned int) sizeof(DdNode), - Cudd_V(node)); -#endif - } else { -#if SIZEOF_VOID_P == 8 - (void) printf("ID = 0x%lx\tindex = %d\tr = %d\n", - (unsigned long) node / - (unsigned long) sizeof(DdNode), - node->index, node->ref); -#else - (void) printf("ID = 0x%x\tindex = %d\tr = %d\n", - (unsigned int) node / - (unsigned int) sizeof(DdNode), - node->index, node->ref); -#endif - } - } - (void) printf("\n"); - } - return(1); - -} /* end of testIterators */ - - -/**Function******************************************************************** - - Synopsis [Tests the functions related to the exclusive OR.] - - Description [Tests the functions related to the exclusive OR. It - builds the boolean difference of the given function in three - different ways and checks that the results is the same. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -testXor(DdManager *dd, DdNode *f, int pr, int nvars) -{ - DdNode *f1, *f0, *res1, *res2; - int x; - - /* Extract cofactors w.r.t. mid variable. */ - x = nvars / 2; - f1 = Cudd_Cofactor(dd,f,dd->vars[x]); - if (f1 == NULL) return(0); - Cudd_Ref(f1); - - f0 = Cudd_Cofactor(dd,f,Cudd_Not(dd->vars[x])); - if (f0 == NULL) { - Cudd_RecursiveDeref(dd,f1); - return(0); - } - Cudd_Ref(f0); - - /* Compute XOR of cofactors with ITE. */ - res1 = Cudd_bddIte(dd,f1,Cudd_Not(f0),f0); - if (res1 == NULL) return(0); - Cudd_Ref(res1); - - if (pr>0) {(void) printf("xor1"); Cudd_PrintDebug(dd,res1,nvars,pr);} - - /* Compute XOR of cofactors with XOR. */ - res2 = Cudd_bddXor(dd,f1,f0); - if (res2 == NULL) { - Cudd_RecursiveDeref(dd,res1); - return(0); - } - Cudd_Ref(res2); - - if (res1 != res2) { - if (pr>0) {(void) printf("xor2"); Cudd_PrintDebug(dd,res2,nvars,pr);} - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,res2); - return(0); - } - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,f1); - Cudd_RecursiveDeref(dd,f0); - - /* Compute boolean difference directly. */ - res1 = Cudd_bddBooleanDiff(dd,f,x); - if (res1 == NULL) { - Cudd_RecursiveDeref(dd,res2); - return(0); - } - Cudd_Ref(res1); - - if (res1 != res2) { - if (pr>0) {(void) printf("xor3"); Cudd_PrintDebug(dd,res1,nvars,pr);} - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,res2); - return(0); - } - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,res2); - return(1); - -} /* end of testXor */ - - -/**Function******************************************************************** - - Synopsis [Tests the Hamming distance functions.] - - Description [Tests the Hammming distance functions. Returns - 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -testHamming( - DdManager *dd, - DdNode *f, - int pr, - int nvars) -{ - DdNode **vars, *minBdd, *zero, *scan; - int i; - int d; - int *minterm; - int size = Cudd_ReadSize(dd); - - vars = ALLOC(DdNode *, size); - if (vars == NULL) return(0); - for (i = 0; i < size; i++) { - vars[i] = Cudd_bddIthVar(dd,i); - } - - minBdd = Cudd_bddPickOneMinterm(dd,Cudd_Not(f),vars,size); - Cudd_Ref(minBdd); - if (pr > 0) { - (void) printf("Chosen minterm for Hamming distance test: "); - Cudd_PrintDebug(dd,minBdd,size,pr); - } - - minterm = ALLOC(int,size); - if (minterm == NULL) { - FREE(vars); - Cudd_RecursiveDeref(dd,minBdd); - return(0); - } - scan = minBdd; - zero = Cudd_Not(DD_ONE(dd)); - while (!Cudd_IsConstant(scan)) { - DdNode *R = Cudd_Regular(scan); - DdNode *T = Cudd_T(R); - DdNode *E = Cudd_E(R); - if (R != scan) { - T = Cudd_Not(T); - E = Cudd_Not(E); - } - if (T == zero) { - minterm[R->index] = 0; - scan = E; - } else { - minterm[R->index] = 1; - scan = T; - } - } - Cudd_RecursiveDeref(dd,minBdd); - - d = Cudd_MinHammingDist(dd,f,minterm,size); - - (void) printf("Minimum Hamming distance = %d\n", d); - - FREE(vars); - FREE(minterm); - return(1); - -} /* end of testHamming */ diff --git a/src/bdd/dsd/dsd.h b/src/bdd/dsd/dsd.h deleted file mode 100644 index b73b81ab..00000000 --- a/src/bdd/dsd/dsd.h +++ /dev/null @@ -1,129 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsd.h] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [External declarations of the package. - This fast BDD-based recursive algorithm for simple - (single-output) DSD is based on the following papers: - (1) V. Bertacco and M. Damiani, "Disjunctive decomposition of - logic functions," Proc. ICCAD '97, pp. 78-82. - (2) Y. Matsunaga, "An exact and efficient algorithm for disjunctive - decomposition", Proc. SASIMI '98, pp. 44-50. - The scope of detected decompositions is the same as in the paper: - T. Sasao and M. Matsuura, "DECOMPOS: An integrated system for - functional decomposition," Proc. IWLS '98, pp. 471-477.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsd.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DSD_H__ -#define __DSD_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// TYPEDEF DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dsd_Manager_t_ Dsd_Manager_t; -typedef struct Dsd_Node_t_ Dsd_Node_t; -typedef enum Dsd_Type_t_ Dsd_Type_t; - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// types of DSD nodes -enum Dsd_Type_t_ { - DSD_NODE_NONE = 0, - DSD_NODE_CONST1 = 1, - DSD_NODE_BUF = 2, - DSD_NODE_OR = 3, - DSD_NODE_EXOR = 4, - DSD_NODE_PRIME = 5, -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// complementation and testing for pointers for decomposition entries -#define Dsd_IsComplement(p) (((int)((unsigned long) (p) & 01))) -#define Dsd_Regular(p) ((Dsd_Node_t *)((unsigned long)(p) & ~01)) -#define Dsd_Not(p) ((Dsd_Node_t *)((unsigned long)(p) ^ 01)) -#define Dsd_NotCond(p,c) ((Dsd_Node_t *)((unsigned long)(p) ^ (c))) - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator through the transitions -#define Dsd_NodeForEachChild( Node, Index, Child ) \ - for ( Index = 0; \ - Index < Dsd_NodeReadDecsNum(Node) && \ - ((Child = Dsd_NodeReadDec(Node,Index))>=0); \ - Index++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== dsdApi.c =======================================================*/ -extern Dsd_Type_t Dsd_NodeReadType( Dsd_Node_t * p ); -extern DdNode * Dsd_NodeReadFunc( Dsd_Node_t * p ); -extern DdNode * Dsd_NodeReadSupp( Dsd_Node_t * p ); -extern Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p ); -extern Dsd_Node_t * Dsd_NodeReadDec ( Dsd_Node_t * p, int i ); -extern int Dsd_NodeReadDecsNum( Dsd_Node_t * p ); -extern int Dsd_NodeReadMark( Dsd_Node_t * p ); -extern void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ); -extern DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ); -extern Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ); -extern Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ); -extern Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ); -/*=== dsdMan.c =======================================================*/ -extern Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ); -extern void Dsd_ManagerStop( Dsd_Manager_t * dMan ); -/*=== dsdProc.c =======================================================*/ -extern void Dsd_Decompose( Dsd_Manager_t * dMan, DdNode ** pbFuncs, int nFuncs ); -extern Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc ); -/*=== dsdTree.c =======================================================*/ -extern void Dsd_TreeNodeGetInfo( Dsd_Manager_t * dMan, int * DepthMax, int * GateSizeMax ); -extern void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax ); -extern int Dsd_TreeGetAigCost( Dsd_Node_t * pNode ); -extern int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * dMan ); -extern int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot ); -extern int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan ); -extern int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ); -extern int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, int * pVars ); -extern Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * dMan, int * pnNodes ); -extern Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ); -extern void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ); -extern void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ); -/*=== dsdLocal.c =======================================================*/ -extern DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdApi.c b/src/bdd/dsd/dsdApi.c deleted file mode 100644 index d1c90e23..00000000 --- a/src/bdd/dsd/dsdApi.c +++ /dev/null @@ -1,97 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdApi.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Implementation of API functions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdApi.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [APIs of the DSD node.] - - Description [The node's type can be retrieved by calling - Dsd_NodeReadType(). The type is one of the following: constant 1 node, - the buffer (or the elementary variable), OR gate, EXOR gate, or - PRIME function (a non-DSD-decomposable function with more than two - inputs). The return value of Dsd_NodeReadFunc() is the global function - of the DSD node. The return value of Dsd_NodeReadSupp() is the support - of the global function of the DSD node. The array of DSD nodes - returned by Dsd_NodeReadDecs() is the array of decomposition nodes for - the formal inputs of the given node. The number of decomposition entries - returned by Dsd_NodeReadDecsNum() is the number of formal inputs. - The mark is explained below.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Type_t Dsd_NodeReadType( Dsd_Node_t * p ) { return p->Type; } -DdNode * Dsd_NodeReadFunc( Dsd_Node_t * p ) { return p->G; } -DdNode * Dsd_NodeReadSupp( Dsd_Node_t * p ) { return p->S; } -Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p ) { return p->pDecs; } -Dsd_Node_t * Dsd_NodeReadDec ( Dsd_Node_t * p, int i ) { return p->pDecs[i]; } -int Dsd_NodeReadDecsNum( Dsd_Node_t * p ) { return p->nDecs; } -int Dsd_NodeReadMark( Dsd_Node_t * p ) { return p->Mark; } - -/**Function************************************************************* - - Synopsis [APIs of the DSD node.] - - Description [This API allows the user to set the integer mark in the - given DSD node. The mark is guaranteed to persist as long as the - calls to the decomposition are not performed. In any case, the mark - is useful to associate the node with some temporary information, such - as its number in the DFS ordered list of the DSD nodes or its number in - the BLIF file that it being written.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ){ p->Mark = Mark; } - -/**Function************************************************************* - - Synopsis [APIs of the DSD manager.] - - Description [Allows the use to get hold of an individual leave of - the DSD tree (Dsd_ManagerReadInput) or an individual root of the - decomposition tree (Dsd_ManagerReadRoot). The root may have the - complemented attribute.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ) { return pMan->pRoots[i]; } -Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ) { return pMan->pInputs[i]; } -Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ) { return pMan->pConst1; } -DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ) { return pMan->dd; } - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdCheck.c b/src/bdd/dsd/dsdCheck.c deleted file mode 100644 index 58b824d2..00000000 --- a/src/bdd/dsd/dsdCheck.c +++ /dev/null @@ -1,314 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdCheck.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Procedures to check the identity of root functions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdCheck.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dsd_Cache_t_ Dds_Cache_t; -typedef struct Dsd_Entry_t_ Dsd_Entry_t; - -struct Dsd_Cache_t_ -{ - Dsd_Entry_t * pTable; - int nTableSize; - int nSuccess; - int nFailure; -}; - -struct Dsd_Entry_t_ -{ - DdNode * bX[5]; -}; - -static Dds_Cache_t * pCache; - -static int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function******************************************************************** - - Synopsis [(Re)allocates the local cache.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Dsd_CheckCacheAllocate( int nEntries ) -{ - int nRequested; - - pCache = ALLOC( Dds_Cache_t, 1 ); - memset( pCache, 0, sizeof(Dds_Cache_t) ); - - // check what is the size of the current cache - nRequested = Cudd_Prime( nEntries ); - if ( pCache->nTableSize != nRequested ) - { // the current size is different - // deallocate the old, allocate the new - if ( pCache->nTableSize ) - Dsd_CheckCacheDeallocate(); - // allocate memory for the hash table - pCache->nTableSize = nRequested; - pCache->pTable = ALLOC( Dsd_Entry_t, nRequested ); - } - // otherwise, there is no need to allocate, just clean - Dsd_CheckCacheClear(); -// printf( "\nThe number of allocated cache entries = %d.\n\n", pCache->nTableSize ); -} - -/**Function******************************************************************** - - Synopsis [Deallocates the local cache.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Dsd_CheckCacheDeallocate() -{ - free( pCache->pTable ); - free( pCache ); -} - -/**Function******************************************************************** - - Synopsis [Clears the local cache.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Dsd_CheckCacheClear() -{ - int i; - for ( i = 0; i < pCache->nTableSize; i++ ) - pCache->pTable[0].bX[0] = NULL; -} - - -/**Function******************************************************************** - - Synopsis [Checks whether it is true that bF1(bC1=0) == bF2(bC2=0).] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ) -{ - int RetValue; -// pCache->nSuccess = 0; -// pCache->nFailure = 0; - RetValue = Dsd_CheckRootFunctionIdentity_rec(dd, bF1, bF2, bC1, bC2); -// printf( "Cache success = %d. Cache failure = %d.\n", pCache->nSuccess, pCache->nFailure ); - return RetValue; -} - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Dsd_CheckRootFunctionIdentity().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ) -{ - unsigned HKey; - - // if either bC1 or bC2 is zero, the test is true -// if ( bC1 == b0 || bC2 == b0 ) return 1; - assert( bC1 != b0 ); - assert( bC2 != b0 ); - - // if both bC1 and bC2 are one - perform comparison - if ( bC1 == b1 && bC2 == b1 ) return (int)( bF1 == bF2 ); - - if ( bF1 == b0 ) - return Cudd_bddLeq( dd, bC2, Cudd_Not(bF2) ); - - if ( bF1 == b1 ) - return Cudd_bddLeq( dd, bC2, bF2 ); - - if ( bF2 == b0 ) - return Cudd_bddLeq( dd, bC1, Cudd_Not(bF1) ); - - if ( bF2 == b1 ) - return Cudd_bddLeq( dd, bC1, bF1 ); - - // otherwise, keep expanding - - // check cache -// HKey = _Hash( ((unsigned)bF1), ((unsigned)bF2), ((unsigned)bC1), ((unsigned)bC2) ); - HKey = hashKey4( bF1, bF2, bC1, bC2, pCache->nTableSize ); - if ( pCache->pTable[HKey].bX[0] == bF1 && - pCache->pTable[HKey].bX[1] == bF2 && - pCache->pTable[HKey].bX[2] == bC1 && - pCache->pTable[HKey].bX[3] == bC2 ) - { - pCache->nSuccess++; - return (int)pCache->pTable[HKey].bX[4]; // the last bit records the result (yes/no) - } - else - { - - // determine the top variables - int RetValue; - DdNode * bA[4] = { bF1, bF2, bC1, bC2 }; // arguments - DdNode * bAR[4] = { Cudd_Regular(bF1), Cudd_Regular(bF2), Cudd_Regular(bC1), Cudd_Regular(bC2) }; // regular arguments - int CurLevel[4] = { cuddI(dd,bAR[0]->index), cuddI(dd,bAR[1]->index), cuddI(dd,bAR[2]->index), cuddI(dd,bAR[3]->index) }; - int TopLevel = CUDD_CONST_INDEX; - int i; - DdNode * bE[4], * bT[4]; - DdNode * bF1next, * bF2next, * bC1next, * bC2next; - - pCache->nFailure++; - - // determine the top level - for ( i = 0; i < 4; i++ ) - if ( TopLevel > CurLevel[i] ) - TopLevel = CurLevel[i]; - - // compute the cofactors - for ( i = 0; i < 4; i++ ) - if ( TopLevel == CurLevel[i] ) - { - if ( bA[i] != bAR[i] ) // complemented - { - bE[i] = Cudd_Not(cuddE(bAR[i])); - bT[i] = Cudd_Not(cuddT(bAR[i])); - } - else - { - bE[i] = cuddE(bAR[i]); - bT[i] = cuddT(bAR[i]); - } - } - else - bE[i] = bT[i] = bA[i]; - - // solve subproblems - // three cases are possible - - // (1) the top var belongs to both C1 and C2 - // in this case, any cofactor of F1 and F2 will do, - // as long as the corresponding cofactor of C1 and C2 is not equal to 0 - if ( TopLevel == CurLevel[2] && TopLevel == CurLevel[3] ) - { - if ( bE[2] != b0 ) // C1 - { - bF1next = bE[0]; - bC1next = bE[2]; - } - else - { - bF1next = bT[0]; - bC1next = bT[2]; - } - if ( bE[3] != b0 ) // C2 - { - bF2next = bE[1]; - bC2next = bE[3]; - } - else - { - bF2next = bT[1]; - bC2next = bT[3]; - } - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bF2next, bC1next, bC2next ); - } - // (2) the top var belongs to either C1 or C2 - // in this case normal splitting of cofactors - else if ( TopLevel == CurLevel[2] && TopLevel != CurLevel[3] ) - { - if ( bE[2] != b0 ) // C1 - { - bF1next = bE[0]; - bC1next = bE[2]; - } - else - { - bF1next = bT[0]; - bC1next = bT[2]; - } - // split around this variable - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bE[1], bC1next, bE[3] ); - if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bT[1], bC1next, bT[3] ); - } - else if ( TopLevel != CurLevel[2] && TopLevel == CurLevel[3] ) - { - if ( bE[3] != b0 ) // C2 - { - bF2next = bE[1]; - bC2next = bE[3]; - } - else - { - bF2next = bT[1]; - bC2next = bT[3]; - } - // split around this variable - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bF2next, bE[2], bC2next ); - if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bF2next, bT[2], bC2next ); - } - // (3) the top var does not belong to C1 and C2 - // in this case normal splitting of cofactors - else // if ( TopLevel != CurLevel[2] && TopLevel != CurLevel[3] ) - { - // split around this variable - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bE[1], bE[2], bE[3] ); - if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bT[1], bT[2], bT[3] ); - } - - // set cache - for ( i = 0; i < 4; i++ ) - pCache->pTable[HKey].bX[i] = bA[i]; - pCache->pTable[HKey].bX[4] = (DdNode*)RetValue; - - return RetValue; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/dsd/dsdInt.h b/src/bdd/dsd/dsdInt.h deleted file mode 100644 index 62ce7e99..00000000 --- a/src/bdd/dsd/dsdInt.h +++ /dev/null @@ -1,91 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdInt.h] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Internal declarations of the package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdInt.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DSD_INT_H__ -#define __DSD_INT_H__ - -#include "extra.h" -#include "dsd.h" - -//////////////////////////////////////////////////////////////////////// -/// TYPEDEF DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef unsigned char byte; - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// DSD manager -struct Dsd_Manager_t_ -{ - DdManager * dd; // the BDD manager - st_table * Table; // the mapping of BDDs into their DEs - int nInputs; // the number of primary inputs - int nRoots; // the number of primary outputs - int nRootsAlloc;// the number of primary outputs - Dsd_Node_t ** pInputs; // the primary input nodes - Dsd_Node_t ** pRoots; // the primary output nodes - Dsd_Node_t * pConst1; // the constant node - int fVerbose; // the verbosity level -}; - -// DSD node -struct Dsd_Node_t_ -{ - Dsd_Type_t Type; // decomposition type - DdNode * G; // function of the node - DdNode * S; // support of this function - Dsd_Node_t ** pDecs; // pointer to structures for formal inputs - int Mark; // the mark used by CASE 4 of disjoint decomposition - short nDecs; // the number of formal inputs - short nVisits; // the counter of visits -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define MAXINPUTS 1000 - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== dsdCheck.c =======================================================*/ -extern void Dsd_CheckCacheAllocate( int nEntries ); -extern void Dsd_CheckCacheDeallocate(); -extern void Dsd_CheckCacheClear(); -extern int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); -/*=== dsdTree.c =======================================================*/ -extern Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum ); -extern void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode ); -extern void Dsd_TreeUnmark( Dsd_Manager_t * dMan ); -extern DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/dsd/dsdLocal.c b/src/bdd/dsd/dsdLocal.c deleted file mode 100644 index 6dd6e7d1..00000000 --- a/src/bdd/dsd/dsdLocal.c +++ /dev/null @@ -1,337 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdLocal.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Deriving the local function of the DSD node.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdLocal.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STATIC VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -static DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bFunc, st_table * pCache, - int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ); -static DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the local function of the DSD node. ] - - Description [The local function is computed using the global function - of the node and the global functions of the formal inputs. The resulting - local function is mapped using the topmost N variables of the manager. - The number of variables N is equal to the number of formal inputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ) -{ - int * pForm2Var; // the mapping of each formal input into its first var - int * pVar2Form; // the mapping of each var into its formal inputs - int i, iVar, iLev, * pPermute; - DdNode ** pbCube0, ** pbCube1; - DdNode * bFunc, * bRes, * bTemp; - st_table * pCache; - - pPermute = ALLOC( int, dd->size ); - pVar2Form = ALLOC( int, dd->size ); - pForm2Var = ALLOC( int, dd->size ); - - pbCube0 = ALLOC( DdNode *, dd->size ); - pbCube1 = ALLOC( DdNode *, dd->size ); - - // remap the global function in such a way that - // the support variables of each formal input are adjacent - iLev = 0; - for ( i = 0; i < pNode->nDecs; i++ ) - { - pForm2Var[i] = dd->invperm[i]; - for ( bTemp = pNode->pDecs[i]->S; bTemp != b1; bTemp = cuddT(bTemp) ) - { - iVar = dd->invperm[iLev]; - pPermute[bTemp->index] = iVar; - pVar2Form[iVar] = i; - iLev++; - } - - // collect the cubes representing each assignment - pbCube0[i] = Extra_bddGetOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); - Cudd_Ref( pbCube0[i] ); - pbCube1[i] = Extra_bddGetOneCube( dd, pNode->pDecs[i]->G ); - Cudd_Ref( pbCube1[i] ); - } - - // remap the function - bFunc = Cudd_bddPermute( dd, pNode->G, pPermute ); Cudd_Ref( bFunc ); - // remap the cube - for ( i = 0; i < pNode->nDecs; i++ ) - { - pbCube0[i] = Cudd_bddPermute( dd, bTemp = pbCube0[i], pPermute ); Cudd_Ref( pbCube0[i] ); - Cudd_RecursiveDeref( dd, bTemp ); - pbCube1[i] = Cudd_bddPermute( dd, bTemp = pbCube1[i], pPermute ); Cudd_Ref( pbCube1[i] ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - // remap the function - pCache = st_init_table(st_ptrcmp,st_ptrhash); - bRes = Extra_dsdRemap( dd, bFunc, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes ); - st_free_table( pCache ); - - Cudd_RecursiveDeref( dd, bFunc ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - Cudd_RecursiveDeref( dd, pbCube0[i] ); - Cudd_RecursiveDeref( dd, pbCube1[i] ); - } -/* -//////////// - // permute the function once again - // in such a way that i-th var stood for i-th formal input - for ( i = 0; i < dd->size; i++ ) - pPermute[i] = -1; - for ( i = 0; i < pNode->nDecs; i++ ) - pPermute[dd->invperm[i]] = i; - bRes = Cudd_bddPermute( dd, bTemp = bRes, pPermute ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); -//////////// -*/ - FREE(pPermute); - FREE(pVar2Form); - FREE(pForm2Var); - FREE(pbCube0); - FREE(pbCube1); - - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bF, st_table * pCache, - int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ) -{ - DdNode * bFR, * bF0, * bF1; - DdNode * bRes0, * bRes1, * bRes; - int iForm; - - bFR = Cudd_Regular(bF); - if ( cuddIsConstant(bFR) ) - return bF; - - // check the hash-table - if ( bFR->ref != 1 ) - { - if ( st_lookup( pCache, (char *)bF, (char **)&bRes ) ) - return bRes; - } - - // get the formal input - iForm = pVar2Form[bFR->index]; - - // get the nodes pointed to by the cube - bF0 = Extra_bddNodePointedByCube( dd, bF, pbCube0[iForm] ); - bF1 = Extra_bddNodePointedByCube( dd, bF, pbCube1[iForm] ); - - // call recursively for these nodes - bRes0 = Extra_dsdRemap( dd, bF0, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes0 ); - bRes1 = Extra_dsdRemap( dd, bF1, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes1 ); - - // derive the result using ITE - bRes = Cudd_bddIte( dd, dd->vars[ pForm2Var[iForm] ], bRes1, bRes0 ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bRes1 ); - - // add to the hash table - if ( bFR->ref != 1 ) - st_insert( pCache, (char *)bF, (char *)bRes ); - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ) -{ - DdNode * bFR, * bCR; - DdNode * bF0, * bF1; - DdNode * bC0, * bC1; - int LevelF, LevelC; - - assert( bC != b0 ); - if ( bC == b1 ) - return bF; - -// bRes = cuddCacheLookup2( dd, Extra_bddNodePointedByCube, bF, bC ); -// if ( bRes ) -// return bRes; - // there is no need for caching because this operation is very fast - // there will no gain reusing the results of this operations - // instead, it will flush CUDD cache of other useful entries - - - bFR = Cudd_Regular( bF ); - bCR = Cudd_Regular( bC ); - assert( !cuddIsConstant( bFR ) ); - - LevelF = dd->perm[bFR->index]; - LevelC = dd->perm[bCR->index]; - - if ( LevelF <= LevelC ) - { - if ( bFR != bF ) - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - } - else - { - bF0 = bF1 = bF; - } - - if ( LevelC <= LevelF ) - { - if ( bCR != bC ) - { - bC0 = Cudd_Not( cuddE(bCR) ); - bC1 = Cudd_Not( cuddT(bCR) ); - } - else - { - bC0 = cuddE(bCR); - bC1 = cuddT(bCR); - } - } - else - { - bC0 = bC1 = bC; - } - - assert( bC0 == b0 || bC1 == b0 ); - if ( bC0 == b0 ) - return Extra_bddNodePointedByCube( dd, bF1, bC1 ); - return Extra_bddNodePointedByCube( dd, bF0, bC0 ); -} - -#if 0 - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * dsdTreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) -{ - DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; - int i; - int fAllBuffs = 1; - static int Permute[MAXINPUTS]; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->Type == DT_PRIME ); - - // transform the function of this block to depend on inputs - // corresponding to the formal inputs - - // first, substitute those inputs that have some blocks associated with them - // second, remap the inputs to the top of the manager (then, it is easy to output them) - - // start the function - bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); - // go over all primary inputs - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pNode->pDecs[i]->Type != DT_BUF ) // remap only if it is not the buffer - { - bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); - bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); - Cudd_RecursiveDeref( dd, bCube0 ); - - bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); - bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); - Cudd_RecursiveDeref( dd, bCube1 ); - - Cudd_RecursiveDeref( dd, bNewFunc ); - - // use the variable in the i-th level of the manager -// bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - // use the first variale in the support of the component - bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - } - - if ( fRemap ) - { - // remap the function to the top of the manager - // remap the function to the first variables of the manager - for ( i = 0; i < pNode->nDecs; i++ ) - // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; - Permute[ pNode->pDecs[i]->S->index ] = i; - - bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - Cudd_Deref( bNewFunc ); - return bNewFunc; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdMan.c b/src/bdd/dsd/dsdMan.c deleted file mode 100644 index 6e43f0f4..00000000 --- a/src/bdd/dsd/dsdMan.c +++ /dev/null @@ -1,114 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdMan.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [APIs of the DSD manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdMan.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// API OF DSD MANAGER /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the DSD manager.] - - Description [Takes the started BDD manager and the maximum support size - of the function to be DSD-decomposed. The manager should have at least as - many variables as there are variables in the support. The functions should - be expressed using the first nSuppSizeMax variables in the manager (these - may be ordered not necessarily on top of the manager).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ) -{ - Dsd_Manager_t * dMan; - Dsd_Node_t * pNode; - int i; - - assert( nSuppMax <= dd->size ); - - dMan = ALLOC( Dsd_Manager_t, 1 ); - memset( dMan, 0, sizeof(Dsd_Manager_t) ); - dMan->dd = dd; - dMan->nInputs = nSuppMax; - dMan->fVerbose = fVerbose; - dMan->nRoots = 0; - dMan->nRootsAlloc = 50; - dMan->pRoots = (Dsd_Node_t **) malloc( dMan->nRootsAlloc * sizeof(Dsd_Node_t *) ); - dMan->pInputs = (Dsd_Node_t **) malloc( dMan->nInputs * sizeof(Dsd_Node_t *) ); - - // create the primary inputs and insert them into the table - dMan->Table = st_init_table(st_ptrcmp, st_ptrhash); - for ( i = 0; i < dMan->nInputs; i++ ) - { - pNode = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, 0 ); - pNode->G = dd->vars[i]; Cudd_Ref( pNode->G ); - pNode->S = dd->vars[i]; Cudd_Ref( pNode->S ); - st_insert( dMan->Table, (char*)dd->vars[i], (char*)pNode ); - dMan->pInputs[i] = pNode; - } - pNode = Dsd_TreeNodeCreate( DSD_NODE_CONST1, 0, 0 ); - pNode->G = b1; Cudd_Ref( pNode->G ); - pNode->S = b1; Cudd_Ref( pNode->S ); - st_insert( dMan->Table, (char*)b1, (char*)pNode ); - dMan->pConst1 = pNode; - - Dsd_CheckCacheAllocate( 5000 ); - return dMan; -} - -/**Function************************************************************* - - Synopsis [Stops the DSD manager.] - - Description [Stopping the DSD manager automatically derefereces and - deallocates all the DSD nodes that were created during the life time - of the DSD manager. As a result, the user does not need to deref or - deallocate any DSD nodes or trees that are derived and placed in - the manager while it exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_ManagerStop( Dsd_Manager_t * dMan ) -{ - st_generator * gen; - Dsd_Node_t * pNode; - DdNode * bFunc; - // delete the nodes - st_foreach_item( dMan->Table, gen, (char**)&bFunc, (char**)&pNode ) - Dsd_TreeNodeDelete( dMan->dd, Dsd_Regular(pNode) ); - st_free_table(dMan->Table); - free( dMan->pInputs ); - free( dMan->pRoots ); - free( dMan ); - Dsd_CheckCacheDeallocate(); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdProc.c b/src/bdd/dsd/dsdProc.c deleted file mode 100644 index 543ad387..00000000 --- a/src/bdd/dsd/dsdProc.c +++ /dev/null @@ -1,1617 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdProc.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [The core procedures of the package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdProc.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the most important procedures -void dsdKernelDecompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs ); -static Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * F ); - -// additional procedures -static Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity ); -static int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH ); -static void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor ); -static int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall ); - -// list copying -static void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize ); -static void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int Skipped ); - -// debugging procedures -static int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE ); - -//////////////////////////////////////////////////////////////////////// -/// STATIC VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -// the counter of marks -static int s_Mark; - -// debugging flag -static int s_Show = 0; -// temporary var used for debugging -static int Depth = 0; - -static int s_Loops1; -static int s_Loops2; -static int s_Loops3; -static int s_Pivot; -static int s_PivotNo; -static int s_Common; -static int s_CommonNo; - -static int s_Case4Calls; -static int s_Case4CallsSpecial; - -static int s_Case5; -static int s_Loops2Useless; - - -static int s_DecNodesTotal; -static int s_DecNodesUsed; - -// statistical variables -static int s_nDecBlocks; -static int s_nLiterals; -static int s_nExorGates; -static int s_nReusedBlocks; -static int s_nCascades; -static float s_nArea; -static float s_MaxDelay; -static long s_Time; -static int s_nInvertors; -static int s_nPrimeBlocks; - -static int HashSuccess = 0; -static int HashFailure = 0; - -static int s_CacheEntries; - - -//////////////////////////////////////////////////////////////////////// -/// DECOMPOSITION FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs DSD for the array of functions represented by BDDs.] - - Description [This function takes the DSD manager, which should be - previously allocated by the call to Dsd_ManagerStart(). The resulting - DSD tree is stored in the DSD manager (pDsdMan->pRoots, pDsdMan->nRoots). - Access to the tree is through the APIs of the manager. The resulting - tree is a shared DSD DAG for the functions given in the array. For one - function the resulting DAG is always a tree. The root node pointers can - be complemented, as discussed in the literature referred to in "dsd.h". - This procedure can be called repeatedly for different functions. There is - no need to remove the decomposition tree after it is returned, because - the next call to the DSD manager will "recycle" the tree. The user should - not modify or dereference any data associated with the nodes of the - DSD trees (the user can only change the contents of a temporary - mark associated with each node by the calling to Dsd_NodeSetMark()). - All the decomposition trees and intermediate nodes will be removed when - the DSD manager is deallocated at the end by calling Dsd_ManagerStop().] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_Decompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs ) -{ - DdManager * dd = pDsdMan->dd; - int i; - long clk; - Dsd_Node_t * pTemp; - int SumMaxGateSize = 0; - int nDecOutputs = 0; - int nCBFOutputs = 0; -/* -s_Loops1 = 0; -s_Loops2 = 0; -s_Loops3 = 0; -s_Case4Calls = 0; -s_Case4CallsSpecial = 0; -s_Case5 = 0; -s_Loops2Useless = 0; -*/ - // resize the number of roots in the manager - if ( pDsdMan->nRootsAlloc < nFuncs ) - { - if ( pDsdMan->nRootsAlloc > 0 ) - free( pDsdMan->pRoots ); - pDsdMan->nRootsAlloc = nFuncs; - pDsdMan->pRoots = (Dsd_Node_t **) malloc( pDsdMan->nRootsAlloc * sizeof(Dsd_Node_t *) ); - } - - if ( pDsdMan->fVerbose ) - printf( "\nDecomposability statistics for individual outputs:\n" ); - - // set the counter of decomposition nodes - s_nDecBlocks = 0; - - // perform decomposition for all outputs - clk = clock(); - pDsdMan->nRoots = 0; - s_nCascades = 0; - for ( i = 0; i < nFuncs; i++ ) - { - int nLiteralsPrev; - int nDecBlocksPrev; - int nExorGatesPrev; - int nReusedBlocksPres; - int nCascades; - int MaxBlock; - int nPrimeBlocks; - long clk; - - clk = clock(); - nLiteralsPrev = s_nLiterals; - nDecBlocksPrev = s_nDecBlocks; - nExorGatesPrev = s_nExorGates; - nReusedBlocksPres = s_nReusedBlocks; - nPrimeBlocks = s_nPrimeBlocks; - - pDsdMan->pRoots[ pDsdMan->nRoots++ ] = dsdKernelDecompose_rec( pDsdMan, pbFuncs[i] ); - - Dsd_TreeNodeGetInfoOne( pDsdMan->pRoots[i], &nCascades, &MaxBlock ); - s_nCascades = ddMax( s_nCascades, nCascades ); - pTemp = Dsd_Regular(pDsdMan->pRoots[i]); - if ( pTemp->Type != DSD_NODE_PRIME || pTemp->nDecs != Extra_bddSuppSize(dd,pTemp->S) ) - nDecOutputs++; - if ( MaxBlock < 3 ) - nCBFOutputs++; - SumMaxGateSize += MaxBlock; - - if ( pDsdMan->fVerbose ) - { - printf("#%02d: ", i ); - printf("Ins=%2d. ", Cudd_SupportSize(dd,pbFuncs[i]) ); - printf("Gts=%3d. ", Dsd_TreeCountNonTerminalNodesOne( pDsdMan->pRoots[i] ) ); - printf("Pri=%3d. ", Dsd_TreeCountPrimeNodesOne( pDsdMan->pRoots[i] ) ); - printf("Max=%3d. ", MaxBlock ); - printf("Reuse=%2d. ", s_nReusedBlocks-nReusedBlocksPres ); - printf("Csc=%2d. ", nCascades ); - printf("T= %.2f s. ", (float)(clock()-clk)/(float)(CLOCKS_PER_SEC) ) ; - printf("Bdd=%2d. ", Cudd_DagSize(pbFuncs[i]) ); - printf("\n"); - fflush( stdout ); - } - } - assert( pDsdMan->nRoots == nFuncs ); - - if ( pDsdMan->fVerbose ) - { - printf( "\n" ); - printf( "The cumulative decomposability statistics:\n" ); - printf( " Total outputs = %5d\n", nFuncs ); - printf( " Decomposable outputs = %5d\n", nDecOutputs ); - printf( " Completely decomposable outputs = %5d\n", nCBFOutputs ); - printf( " The sum of max gate sizes = %5d\n", SumMaxGateSize ); - printf( " Shared BDD size = %5d\n", Cudd_SharingSize( pbFuncs, nFuncs ) ); - printf( " Decomposition entries = %5d\n", st_count( pDsdMan->Table ) ); - printf( " Pure decomposition time = %.2f sec\n", (float)(clock() - clk)/(float)(CLOCKS_PER_SEC) ); - } -/* - printf( "s_Loops1 = %d.\n", s_Loops1 ); - printf( "s_Loops2 = %d.\n", s_Loops2 ); - printf( "s_Loops3 = %d.\n", s_Loops3 ); - printf( "s_Case4Calls = %d.\n", s_Case4Calls ); - printf( "s_Case4CallsSpecial = %d.\n", s_Case4CallsSpecial ); - printf( "s_Case5 = %d.\n", s_Case5 ); - printf( "s_Loops2Useless = %d.\n", s_Loops2Useless ); -*/ -} - -/**Function************************************************************* - - Synopsis [Performs decomposition for one function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc ) -{ - return dsdKernelDecompose_rec( pDsdMan, bFunc ); -} - -/**Function************************************************************* - - Synopsis [The main function of this module. Recursive implementation of DSD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * bFunc0 ) -{ - DdManager * dd = pDsdMan->dd; - DdNode * bLow; - DdNode * bLowR; - DdNode * bHigh; - - int VarInt; - DdNode * bVarCur; - Dsd_Node_t * pVarCurDE; - // works only if var indices start from 0!!! - DdNode * bSuppNew = NULL, * bTemp; - - int fContained; - int nSuppLH; - int nSuppL; - int nSuppH; - - - - // various decomposition nodes - Dsd_Node_t * pThis, * pL, * pH, * pLR, * pHR; - - Dsd_Node_t * pSmallR, * pLargeR; - Dsd_Node_t * pTableEntry; - - - // treat the complemented case - DdNode * bF = Cudd_Regular(bFunc0); - int fCompF = (int)(bF != bFunc0); - - // check cache - if ( st_lookup( pDsdMan->Table, (char*)bF, (char**)&pTableEntry ) ) - { // the entry is present - HashSuccess++; - return Dsd_NotCond( pTableEntry, fCompF ); - } - HashFailure++; - Depth++; - - // proceed to consider "four cases" - ////////////////////////////////////////////////////////////////////// - // TERMINAL CASES - CASES 1 and 2 - ////////////////////////////////////////////////////////////////////// - bLow = cuddE(bF); - bLowR = Cudd_Regular(bLow); - bHigh = cuddT(bF); - VarInt = bF->index; - bVarCur = dd->vars[VarInt]; - pVarCurDE = pDsdMan->pInputs[VarInt]; - // works only if var indices start from 0!!! - bSuppNew = NULL; - - if ( bLowR->index == CUDD_CONST_INDEX || bHigh->index == CUDD_CONST_INDEX ) - { // one of the cofactors in the constant - if ( bHigh == b1 ) // bHigh cannot be equal to b0, because then it will be complemented - if ( bLow == b0 ) // bLow cannot be equal to b1, because then the node will have bLow == bHigh - ///////////////////////////////////////////////////////////////// - // bLow == 0, bHigh == 1, F = x'&0 + x&1 = x - ///////////////////////////////////////////////////////////////// - { // create the elementary variable node - assert(0); // should be already in the hash table - pThis = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, s_nDecBlocks++ ); - pThis->pDecs[0] = NULL; - } - else // if ( bLow != constant ) - ///////////////////////////////////////////////////////////////// - // bLow != const, bHigh == 1, F = x'&bLow + x&1 = bLow + x --- DSD_NODE_OR(x,bLow) - ///////////////////////////////////////////////////////////////// - { - pL = dsdKernelDecompose_rec( pDsdMan, bLow ); - pLR = Dsd_Regular( pL ); - bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew); - if ( pLR->Type == DSD_NODE_OR && pL == pLR ) // OR and no complement - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pL->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pVarCurDE, pL->pDecs, pL->nDecs ); - } - else // all other cases - { // create a new 2-input OR-gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 ); - } - } - else // if ( bHigh != const ) // meaning that bLow should be a constant - { - pH = dsdKernelDecompose_rec( pDsdMan, bHigh ); - pHR = Dsd_Regular( pH ); - bSuppNew = Cudd_bddAnd( dd, bVarCur, pHR->S ); Cudd_Ref(bSuppNew); - if ( bLow == b0 ) - ///////////////////////////////////////////////////////////////// - // Low == 0, High != 1, F = x'&0+x&High = (x'+High')'--- NOR(x',High') - ///////////////////////////////////////////////////////////////// - if ( pHR->Type == DSD_NODE_OR && pH != pHR ) // DSD_NODE_OR and complement - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pHR->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pHR->pDecs, pHR->nDecs ); - pThis = Dsd_Not(pThis); - } - else // all other cases - { // create a new 2-input NOR gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - pH = Dsd_Not(pH); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 ); - pThis = Dsd_Not(pThis); - } - else // if ( bLow == b1 ) - ///////////////////////////////////////////////////////////////// - // Low == 1, High != 1, F = x'&1 + x&High = x' + High --- DSD_NODE_OR(x',High) - ///////////////////////////////////////////////////////////////// - if ( pHR->Type == DSD_NODE_OR && pH == pHR ) // OR and no complement - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pH->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pH->pDecs, pH->nDecs ); - } - else // all other cases - { // create a new 2-input OR-gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 ); - } - } - goto EXIT; - } - // else if ( bLow != const && bHigh != const ) - - // the case of equal cofactors (up to complementation) - if ( bLowR == bHigh ) - ///////////////////////////////////////////////////////////////// - // Low == G, High == G', F = x'&G + x&G' = (x(+)G) --- EXOR(x,Low) - ///////////////////////////////////////////////////////////////// - { - pL = dsdKernelDecompose_rec( pDsdMan, bLow ); - pLR = Dsd_Regular( pL ); - bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew); - if ( pLR->Type == DSD_NODE_EXOR ) // complemented or not - does not matter! - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, pLR->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pVarCurDE, pLR->pDecs, pLR->nDecs ); - if ( pL != pLR ) - pThis = Dsd_Not( pThis ); - } - else // all other cases - { // create a new 2-input EXOR-gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ ); - if ( pL != pLR ) // complemented - { - dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pLR, 1 ); - pThis = Dsd_Not( pThis ); - } - else // non-complemented - dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 ); - } - goto EXIT; - } - - ////////////////////////////////////////////////////////////////////// - // solve subproblems - ////////////////////////////////////////////////////////////////////// - pL = dsdKernelDecompose_rec( pDsdMan, bLow ); - pH = dsdKernelDecompose_rec( pDsdMan, bHigh ); - pLR = Dsd_Regular( pL ); - pHR = Dsd_Regular( pH ); - - assert( pLR->Type == DSD_NODE_BUF || pLR->Type == DSD_NODE_OR || pLR->Type == DSD_NODE_EXOR || pLR->Type == DSD_NODE_PRIME ); - assert( pHR->Type == DSD_NODE_BUF || pHR->Type == DSD_NODE_OR || pHR->Type == DSD_NODE_EXOR || pHR->Type == DSD_NODE_PRIME ); - -/* -if ( Depth == 1 ) -{ -// PRK(bLow,pDecTreeTotal->nInputs); -// PRK(bHigh,pDecTreeTotal->nInputs); -if ( s_Show ) -{ - PRD( pL ); - PRD( pH ); -} -} -*/ - // compute the new support - bTemp = Cudd_bddAnd( dd, pLR->S, pHR->S ); Cudd_Ref( bTemp ); - nSuppL = Extra_bddSuppSize( dd, pLR->S ); - nSuppH = Extra_bddSuppSize( dd, pHR->S ); - nSuppLH = Extra_bddSuppSize( dd, bTemp ); - bSuppNew = Cudd_bddAnd( dd, bTemp, bVarCur ); Cudd_Ref( bSuppNew ); - Cudd_RecursiveDeref( dd, bTemp ); - - - // several possibilities are possible - // (1) support of one component contains another - // (2) none of the supports is contained in another - fContained = dsdKernelCheckContainment( pDsdMan, pLR, pHR, &pLargeR, &pSmallR ); - - ////////////////////////////////////////////////////////////////////// - // CASE 3.b One of the cofactors in a constant (OR and EXOR) - ////////////////////////////////////////////////////////////////////// - // the support of the larger component should contain the support of the smaller - // it is possible to have PRIME function in this role - // for example: F = ITE( a+b, c(+)d, e+f ), F0 = ITE( b, c(+)d, e+f ), F1 = c(+)d - if ( fContained ) - { - Dsd_Node_t * pSmall, * pLarge; - int c, iCompLarge; // the number of the component is Large is equal to the whole of Small - int fLowIsLarge; - - DdNode * bFTemp; // the changed input function - Dsd_Node_t * pDETemp, * pDENew; - - Dsd_Node_t * pComp = NULL; - int nComp; - - if ( pSmallR == pLR ) - { // Low is Small => High is Large - pSmall = pL; - pLarge = pH; - fLowIsLarge = 0; - } - else - { // vice versa - pSmall = pH; - pLarge = pL; - fLowIsLarge = 1; - } - - // treat the situation when the larger is PRIME - if ( pLargeR->Type == DSD_NODE_PRIME ) //&& pLargeR->nDecs != pSmallR->nDecs ) - { - // QUESTION: Is it possible for pLargeR->nDecs > 3 - // and pSmall contained as one of input in pLarge? - // Yes, for example F = a'c + a & MUX(b,c',d) = a'c + abc' + ab'd is non-decomposable - // Consider the function H(a->xy) = F( xy, b, c, d ) - // H0 = H(x=0) = F(0,b,c,d) = c - // H1 = F(x=1) = F(y,b,c,d) - non-decomposable - // - // QUESTION: Is it possible that pLarge is PRIME(3) and pSmall is OR(2), - // which is not contained in PRIME as one input? - // Yes, for example F = abcd + b'c'd' + a'c'd' = PRIME(ab, c, d) - // F(a=0) = c'd' = NOT(OR(a,d)) F(a=1) = bcd + b'c'd' = PRIME(b,c,d) - // To find decomposition, we have to prove that F(a=1)|b=0 = F(a=0) - - // Is it possible that (pLargeR->nDecs == pSmallR->nDecs) and yet this case holds? - // Yes, consider the function such that F(a=0) = PRIME(a,b+c,d,e) and F(a=1) = OR(b,c,d,e) - // They have the same number of inputs and it is possible that they will be the cofactors - // as discribed in the previous example. - - // find the component, which when substituted for 0 or 1, produces the desired result - int g, fFoundComp; // {0,1} depending on whether setting cofactor to 0 or 1 worked out - - DdNode * bLarge, * bSmall; - if ( fLowIsLarge ) - { - bLarge = bLow; - bSmall = bHigh; - } - else - { - bLarge = bHigh; - bSmall = bLow; - } - - for ( g = 0; g < pLargeR->nDecs; g++ ) -// if ( g != c ) - { - pDETemp = pLargeR->pDecs[g]; // cannot be complemented - if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, pDETemp->G, b1 ) ) - { - fFoundComp = 1; - break; - } - - s_Loops1++; - - if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, Cudd_Not(pDETemp->G), b1 ) ) - { - fFoundComp = 0; - break; - } - - s_Loops1++; - } - - if ( g != pLargeR->nDecs ) - { // decomposition is found - if ( fFoundComp ) - if ( fLowIsLarge ) - bFTemp = Cudd_bddOr( dd, bVarCur, pLargeR->pDecs[g]->G ); - else - bFTemp = Cudd_bddOr( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G ); - else - if ( fLowIsLarge ) - bFTemp = Cudd_bddAnd( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G ); - else - bFTemp = Cudd_bddAnd( dd, bVarCur, pLargeR->pDecs[g]->G ); - Cudd_Ref( bFTemp ); - - pDENew = dsdKernelDecompose_rec( pDsdMan, bFTemp ); - pDENew = Dsd_Regular( pDENew ); - Cudd_RecursiveDeref( dd, bFTemp ); - - // get the new gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLargeR->nDecs, s_nDecBlocks++ ); - dsdKernelCopyListPlusOneMinusOne( pThis, pDENew, pLargeR->pDecs, pLargeR->nDecs, g ); - goto EXIT; - } - } - - // try to find one component in the pLarger that is equal to the whole of pSmaller - for ( c = 0; c < pLargeR->nDecs; c++ ) - if ( pLargeR->pDecs[c] == pSmall || pLargeR->pDecs[c] == Dsd_Not(pSmall) ) - { - iCompLarge = c; - break; - } - - // assign the equal component - if ( c != pLargeR->nDecs ) // the decomposition is possible! - { - pComp = pLargeR->pDecs[iCompLarge]; - nComp = 1; - } - else // the decomposition is still possible - { // for example F = OR(ab,c,d), F(a=0) = OR(c,d), F(a=1) = OR(b,c,d) - // supp(F0) is contained in supp(F1), Polarity(F(a=0)) == Polarity(F(a=1)) - - // try to find a group of common components - if ( pLargeR->Type == pSmallR->Type && - (pLargeR->Type == DSD_NODE_EXOR || pSmallR->Type == DSD_NODE_OR&& ((pLarge==pLargeR) == (pSmall==pSmallR))) ) - { - Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; - int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLargeR, pSmallR, &pCommon, &pLastDiffL, &pLastDiffH ); - // if all the components of pSmall are contained in pLarge, - // then the decomposition exists - if ( nCommon == pSmallR->nDecs ) - { - pComp = pSmallR; - nComp = pSmallR->nDecs; - } - } - } - - if ( pComp ) // the decomposition is possible! - { -// Dsd_Node_t * pComp = pLargeR->pDecs[iCompLarge]; - Dsd_Node_t * pCompR = Dsd_Regular( pComp ); - int fComp1 = (int)( pLarge != pLargeR ); - int fComp2 = (int)( pComp != pCompR ); - int fComp3 = (int)( pSmall != pSmallR ); - - DdNode * bFuncComp; // the function of the given component - DdNode * bFuncNew; // the function of the input component - - if ( pLargeR->Type == DSD_NODE_OR ) // Figure 4 of Matsunaga's paper - { - // the decomposition exists only if the polarity assignment - // along the paths is the same - if ( (fComp1 ^ fComp2) == fComp3 ) - { // decomposition exists = consider 4 cases - // consideration of cases leads to the following conclusion - // fComp1 gives the polarity of the resulting DSD_NODE_OR gate - // fComp2 gives the polarity of the common component feeding into the DSD_NODE_OR gate - // - // | fComp1 pL/ |pS - // <> .........<=>....... <> | - // | / | - // [OR] [OR] | fComp3 - // / \ fComp2 / | \ | - // <> <> .......<=>... /..|..<> | - // / \ / | \| - // [OR] [C] S1 S2 C - // / \ - // <> \ - // / \ - // [OR] [x] - // / \ - // S1 S2 - // - - - // at this point we have the function F (bFTemp) and the common component C (bFuncComp) - // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0 - // we compute the following R = Exist( F - C, supp(C) ) - bFTemp = (fComp1)? Cudd_Not( bF ): bF; - bFuncComp = (fComp2)? Cudd_Not( pCompR->G ): pCompR->G; - bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bFuncComp), pCompR->S ); Cudd_Ref( bFuncNew ); - - // there is no need to copy the dec entry list first, because pComp is a component - // which will not be destroyed by the recursive call to decomposition - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - assert( Dsd_IsComplement(pDENew) ); // follows from the consideration of cases - Cudd_RecursiveDeref( dd, bFuncNew ); - - // get the new gate - if ( nComp == 1 ) - { - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - pThis->pDecs[0] = pDENew; - pThis->pDecs[1] = pComp; // takes the complement - } - else - { // pComp is not complemented - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nComp+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp ); - } - - if ( fComp1 ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - } - else if ( pLargeR->Type == DSD_NODE_EXOR ) // Figure 5 of Matsunaga's paper (with correction) - { // decomposition always exists = consider 4 cases - - // consideration of cases leads to the following conclusion - // fComp3 gives the COMPLEMENT of the polarity of the resulting EXOR gate - // (if fComp3 is 0, the EXOR gate is complemented, and vice versa) - // - // | fComp1 pL/ |pS - // <> .........<=>....... /....| fComp3 - // | / | - // [XOR] [XOR] | - // / \ fComp2==0 / | \ | - // / \ / | \ | - // / \ / | \| - // [OR] [C] S1 S2 C - // / \ - // <> \ - // / \ - // [XOR] [x] - // / \ - // S1 S2 - // - - assert( fComp2 == 0 ); - // find the functionality of the lower gates - bFTemp = (fComp3)? bF: Cudd_Not( bF ); - bFuncNew = Cudd_bddXor( dd, bFTemp, pComp->G ); Cudd_Ref( bFuncNew ); - - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases - Cudd_RecursiveDeref( dd, bFuncNew ); - - // get the new gate - if ( nComp == 1 ) - { - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ ); - pThis->pDecs[0] = pDENew; - pThis->pDecs[1] = pComp; - } - else - { // pComp is not complemented - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nComp+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp ); - } - - if ( !fComp3 ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - } - } - - // this case was added to fix the trivial bug found November 4, 2002 in Japan - // by running the example provided by T. Sasao - if ( nSuppLH == nSuppL + nSuppH ) // the supports of the components are disjoint - { - // create a new component of the type ITE( a, pH, pL ) - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, 3, s_nDecBlocks++ ); - if ( dd->perm[pLR->S->index] < dd->perm[pHR->S->index] ) // pLR is higher in the varible order - { - pThis->pDecs[1] = pLR; - pThis->pDecs[2] = pHR; - } - else // pHR is higher in the varible order - { - pThis->pDecs[1] = pHR; - pThis->pDecs[2] = pLR; - } - // add the first component - pThis->pDecs[0] = pVarCurDE; - goto EXIT; - } - - - ////////////////////////////////////////////////////////////////////// - // CASE 3.a Neither of the cofactors is a constant (OR, EXOR, PRIME) - ////////////////////////////////////////////////////////////////////// - // the component types are identical - // and if they are OR, they are either both complemented or both not complemented - // and if they are PRIME, their dec numbers should be the same - if ( pLR->Type == pHR->Type && - pLR->Type != DSD_NODE_BUF && - (pLR->Type != DSD_NODE_OR || ( pL == pLR && pH == pHR || pL != pLR && pH != pHR ) ) && - (pLR->Type != DSD_NODE_PRIME || pLR->nDecs == pHR->nDecs) ) - { - // array to store common comps in pL and pH - Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; - int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLR, pHR, &pCommon, &pLastDiffL, &pLastDiffH ); - if ( nCommon ) - { - if ( pLR->Type == DSD_NODE_OR ) // Figure 2 of Matsunaga's paper - { // at this point we have the function F and the group of common components C - // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0 - // we compute the following R = Exist( F - C, supp(C) ) - - // compute the sum total of the common components and the union of their supports - DdNode * bCommF, * bCommS, * bFTemp, * bFuncNew; - Dsd_Node_t * pDENew; - - dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, &bCommS, 0 ); - Cudd_Ref( bCommF ); - Cudd_Ref( bCommS ); - bFTemp = ( pL != pLR )? Cudd_Not(bF): bF; - - bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bCommF), bCommS ); Cudd_Ref( bFuncNew ); - Cudd_RecursiveDeref( dd, bCommF ); - Cudd_RecursiveDeref( dd, bCommS ); - - // get the new gate - - // copy the components first, then call the decomposition - // because decomposition will distroy the list used for copying - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nCommon + 1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); - - // call the decomposition recursively - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); -// assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases - Cudd_RecursiveDeref( dd, bFuncNew ); - - // add the first component - pThis->pDecs[0] = pDENew; - - if ( pL != pLR ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - else - if ( pLR->Type == DSD_NODE_EXOR ) // Figure 3 of Matsunaga's paper - { - // compute the sum total of the common components and the union of their supports - DdNode * bCommF, * bFuncNew; - Dsd_Node_t * pDENew; - int fCompExor; - - dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, 1 ); - Cudd_Ref( bCommF ); - - bFuncNew = Cudd_bddXor( dd, bF, bCommF ); Cudd_Ref( bFuncNew ); - Cudd_RecursiveDeref( dd, bCommF ); - - // get the new gate - - // copy the components first, then call the decomposition - // because decomposition will distroy the list used for copying - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nCommon + 1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); - - // call the decomposition recursively - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - Cudd_RecursiveDeref( dd, bFuncNew ); - - // remember the fact that it was complemented - fCompExor = Dsd_IsComplement(pDENew); - pDENew = Dsd_Regular(pDENew); - - // add the first component - pThis->pDecs[0] = pDENew; - - - if ( fCompExor ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - else - if ( pLR->Type == DSD_NODE_PRIME && (nCommon == pLR->nDecs-1 || nCommon == pLR->nDecs) ) - { - // for example the function F(a,b,c,d) = ITE(b,c,a(+)d) produces - // two cofactors F(a=0) = PRIME(b,c,d) and F(a=1) = PRIME(b,c,d) - // with exactly the same list of common components - - Dsd_Node_t * pDENew; - DdNode * bFuncNew; - int fCompComp = 0; // this flag can be {0,1,2} - // if it is 0 there is no identity - // if it is 1/2, the cofactored functions are equal in the direct/complemented polarity - - if ( nCommon == pLR->nDecs ) - { // all the components are the same - // find the formal input, in which pLow and pHigh differ (if such input exists) - int m; - Dsd_Node_t * pTempL, * pTempH; - - s_Common++; - for ( m = 0; m < pLR->nDecs; m++ ) - { - pTempL = pLR->pDecs[m]; // cannot be complemented - pTempH = pHR->pDecs[m]; // cannot be complemented - - if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pTempL->G, Cudd_Not(pTempH->G) ) && - Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pTempL->G), pTempH->G ) ) - { - pLastDiffL = pTempL; - pLastDiffH = pTempH; - assert( pLastDiffL == pLastDiffH ); - fCompComp = 2; - break; - } - - s_Loops2++; - s_Loops2++; -/* - if ( s_Loops2 % 10000 == 0 ) - { - int i; - for ( i = 0; i < pLR->nDecs; i++ ) - printf( " %d(s=%d)", pLR->pDecs[i]->Type, - Extra_bddSuppSize(dd, pLR->pDecs[i]->S) ); - printf( "\n" ); - } -*/ - - } -// if ( pLR->nDecs == Extra_bddSuppSize(dd, pLR->S) ) -// s_Loops2Useless += pLR->nDecs * 2; - - if ( fCompComp ) - { // put the equal components into pCommon, so that they could be copied into the new dec entry - nCommon = 0; - for ( m = 0; m < pLR->nDecs; m++ ) - if ( pLR->pDecs[m] != pLastDiffL ) - pCommon[nCommon++] = pLR->pDecs[m]; - assert( nCommon = pLR->nDecs-1 ); - } - } - else - { // the differing components are known - check that they have compatible PRIME function - - s_CommonNo++; - - // find the numbers of different components - assert( pLastDiffL ); - assert( pLastDiffH ); - // also, they cannot be complemented, because the decomposition type is PRIME - - if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), Cudd_Not(pLastDiffH->G) ) && - Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, pLastDiffH->G ) ) - fCompComp = 1; - else if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, Cudd_Not(pLastDiffH->G) ) && - Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), pLastDiffH->G ) ) - fCompComp = 2; - - s_Loops3 += 4; - } - - if ( fCompComp ) - { - if ( fCompComp == 1 ) // it is true that bLow(G=0) == bHigh(H=0) && bLow(G=1) == bHigh(H=1) - bFuncNew = Cudd_bddIte( dd, bVarCur, pLastDiffH->G, pLastDiffL->G ); - else // it is true that bLow(G=0) == bHigh(H=1) && bLow(G=1) == bHigh(H=0) - bFuncNew = Cudd_bddIte( dd, bVarCur, Cudd_Not(pLastDiffH->G), pLastDiffL->G ); - Cudd_Ref( bFuncNew ); - - // get the new gate - - // copy the components first, then call the decomposition - // because decomposition will distroy the list used for copying - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLR->nDecs, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); - - // create a new component - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - Cudd_RecursiveDeref( dd, bFuncNew ); - // the BDD of the argument function in PRIME decomposition, should be regular - pDENew = Dsd_Regular(pDENew); - - // add the first component - pThis->pDecs[0] = pDENew; - goto EXIT; - } - } // end of PRIME type - } // end of existing common components - } // end of CASE 3.a - -// if ( Depth != 1) -// { - -//CASE4: - ////////////////////////////////////////////////////////////////////// - // CASE 4 - ////////////////////////////////////////////////////////////////////// - { - // estimate the number of entries in the list - int nEntriesMax = pDsdMan->nInputs - dd->perm[VarInt]; - - // create the new decomposition entry - int nEntries = 0; - - DdNode * SuppL, * SuppH, * SuppL_init, * SuppH_init; - Dsd_Node_t *pHigher, *pLower, * pTemp, * pDENew; - - - int levTopSuppL; - int levTopSuppH; - int levTop; - - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, nEntriesMax, s_nDecBlocks++ ); - pThis->pDecs[ nEntries++ ] = pVarCurDE; - // other entries will be added to this list one-by-one during analysis - - // count how many times does it happen that the decomposition entries are - s_Case4Calls++; - - // consider the simplest case: when the supports are equal - // and at least one of the components - // is the PRIME without decompositions, or - // when both of them are without decomposition - if ( (((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) || (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) && pLR->S == pHR->S) || - ((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) && (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) ) - { - - s_Case4CallsSpecial++; - // walk through both supports and create the decomposition list composed of simple entries - SuppL = pLR->S; - SuppH = pHR->S; - do - { - // determine levels - levTopSuppL = cuddI(dd,SuppL->index); - levTopSuppH = cuddI(dd,SuppH->index); - - // skip the topmost variable in both supports - if ( levTopSuppL <= levTopSuppH ) - { - levTop = levTopSuppL; - SuppL = cuddT(SuppL); - } - else - levTop = levTopSuppH; - - if ( levTopSuppH <= levTopSuppL ) - SuppH = cuddT(SuppH); - - // set the new decomposition entry - pThis->pDecs[ nEntries++ ] = pDsdMan->pInputs[ dd->invperm[levTop] ]; - } - while ( SuppL != b1 || SuppH != b1 ); - } - else - { - - // compare two different decomposition lists - SuppL_init = pLR->S; - SuppH_init = pHR->S; - // start references (because these supports will change) - SuppL = pLR->S; Cudd_Ref( SuppL ); - SuppH = pHR->S; Cudd_Ref( SuppH ); - while ( SuppL != b1 || SuppH != b1 ) - { - // determine the top level in cofactors and - // whether they have the same top level - int TopLevL = cuddI(dd,SuppL->index); - int TopLevH = cuddI(dd,SuppH->index); - int TopLevel = TopLevH; - int fEqualLevel = 0; - - DdNode * bVarTop; - DdNode * bSuppSubract; - - - if ( TopLevL < TopLevH ) - { - pHigher = pLR; - pLower = pHR; - TopLevel = TopLevL; - } - else if ( TopLevL > TopLevH ) - { - pHigher = pHR; - pLower = pLR; - } - else - fEqualLevel = 1; - assert( TopLevel != CUDD_CONST_INDEX ); - - - // find the currently top variable in the decomposition lists - bVarTop = dd->vars[dd->invperm[TopLevel]]; - - if ( !fEqualLevel ) - { - // find the lower support - DdNode * bSuppLower = (TopLevL < TopLevH)? SuppH_init: SuppL_init; - - // find the first component in pHigher - // whose support does not overlap with supp(Lower) - // and remember the previous component - int fPolarity; - Dsd_Node_t * pPrev = NULL; // the pointer to the component proceeding pCur - Dsd_Node_t * pCur = pHigher; // the first component not contained in supp(Lower) - while ( Extra_bddSuppOverlapping( dd, pCur->S, bSuppLower ) ) - { // get the next component - pPrev = pCur; - pCur = dsdKernelFindContainingComponent( pDsdMan, pCur, bVarTop, &fPolarity ); - }; - - // look for the possibility to subtract more than one component - if ( pPrev == NULL || pPrev->Type == DSD_NODE_PRIME ) - { // if there is no previous component, or if the previous component is PRIME - // there is no way to subtract more than one component - - // add the new decomposition entry (it is already regular) - pThis->pDecs[ nEntries++ ] = pCur; - // assign the support to be subtracted from both components - bSuppSubract = pCur->S; - } - else // all other types - { - // go through the decomposition list of pPrev and find components - // whose support does not overlap with supp(Lower) - - static Dsd_Node_t * pNonOverlap[MAXINPUTS]; - int i, nNonOverlap = 0; - for ( i = 0; i < pPrev->nDecs; i++ ) - { - pTemp = Dsd_Regular( pPrev->pDecs[i] ); - if ( !Extra_bddSuppOverlapping( dd, pTemp->S, bSuppLower ) ) - pNonOverlap[ nNonOverlap++ ] = pPrev->pDecs[i]; - } - assert( nNonOverlap > 0 ); - - if ( nNonOverlap == 1 ) - { // one one component was found, which is the original one - assert( Dsd_Regular(pNonOverlap[0]) == pCur); - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pCur; - // assign the support to be subtracted from both components - bSuppSubract = pCur->S; - } - else // more than one components was found - { - // find the OR (EXOR) of the non-overlapping components - DdNode * bCommF; - dsdKernelComputeSumOfComponents( pDsdMan, pNonOverlap, nNonOverlap, &bCommF, NULL, (int)(pPrev->Type==DSD_NODE_EXOR) ); - Cudd_Ref( bCommF ); - - // create a new gated - pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF ); - Cudd_RecursiveDeref(dd, bCommF); - // make it regular... it must be regular already - assert( !Dsd_IsComplement(pDENew) ); - - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pDENew; - // assign the support to be subtracted from both components - bSuppSubract = pDENew->S; - } - } - - // subtract its support from the support of upper component - if ( TopLevL < TopLevH ) - { - SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ); Cudd_Ref( SuppL ); - Cudd_RecursiveDeref(dd, bTemp); - } - else - { - SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ); Cudd_Ref( SuppH ); - Cudd_RecursiveDeref(dd, bTemp); - } - } // end of if ( !fEqualLevel ) - else // if ( fEqualLevel ) -- they have the same top level var - { - static Dsd_Node_t * pMarkedLeft[MAXINPUTS]; // the pointers to the marked blocks - static char pMarkedPols[MAXINPUTS]; // polarities of the marked blocks - int nMarkedLeft = 0; - - int fPolarity = 0; - Dsd_Node_t * pTempL = pLR; - - int fPolarityCurH = 0; - Dsd_Node_t * pPrevH = NULL, * pCurH = pHR; - - int fPolarityCurL = 0; - Dsd_Node_t * pPrevL = NULL, * pCurL = pLR; // = pMarkedLeft[0]; - int index = 1; - - // set the new mark - s_Mark++; - - // go over the dec list of pL, mark all components that contain the given variable - assert( Extra_bddSuppContainVar( dd, pLR->S, bVarTop ) ); - assert( Extra_bddSuppContainVar( dd, pHR->S, bVarTop ) ); - do { - pTempL->Mark = s_Mark; - pMarkedLeft[ nMarkedLeft ] = pTempL; - pMarkedPols[ nMarkedLeft ] = fPolarity; - nMarkedLeft++; - } while ( pTempL = dsdKernelFindContainingComponent( pDsdMan, pTempL, bVarTop, &fPolarity ) ); - - // go over the dec list of pH, and find the component that is marked and the previos one - // (such component always exists, because they have common variables) - while ( pCurH->Mark != s_Mark ) - { - pPrevH = pCurH; - pCurH = dsdKernelFindContainingComponent( pDsdMan, pCurH, bVarTop, &fPolarityCurH ); - assert( pCurH ); - } - - // go through the first list once again and find - // the component proceeding the one marked found in the second list - while ( pCurL != pCurH ) - { - pPrevL = pCurL; - pCurL = pMarkedLeft[index]; - fPolarityCurL = pMarkedPols[index]; - index++; - } - - // look for the possibility to subtract more than one component - if ( !pPrevL || !pPrevH || pPrevL->Type != pPrevH->Type || pPrevL->Type == DSD_NODE_PRIME || fPolarityCurL != fPolarityCurH ) - { // there is no way to extract more than one - pThis->pDecs[ nEntries++ ] = pCurH; - // assign the support to be subtracted from both components - bSuppSubract = pCurH->S; - } - else - { - // find the equal components in two decomposition lists - Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; - int nCommon = dsdKernelFindCommonComponents( pDsdMan, pPrevL, pPrevH, &pCommon, &pLastDiffL, &pLastDiffH ); - - if ( nCommon == 0 || nCommon == 1 ) - { // one one component was found, which is the original one - // assert( Dsd_Regular(pCommon[0]) == pCurL); - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pCurL; - // assign the support to be subtracted from both components - bSuppSubract = pCurL->S; - } - else // more than one components was found - { - // find the OR (EXOR) of the non-overlapping components - DdNode * bCommF; - dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, (int)(pPrevL->Type==DSD_NODE_EXOR) ); - Cudd_Ref( bCommF ); - - pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF ); - assert( !Dsd_IsComplement(pDENew) ); // cannot be complemented because of construction - Cudd_RecursiveDeref( dd, bCommF ); - - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pDENew; - - // assign the support to be subtracted from both components - bSuppSubract = pDENew->S; - } - } - - SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ), Cudd_Ref( SuppL ); - Cudd_RecursiveDeref(dd, bTemp); - - SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ), Cudd_Ref( SuppH ); - Cudd_RecursiveDeref(dd, bTemp); - - } // end of if ( fEqualLevel ) - - } // end of decomposition list comparison - Cudd_RecursiveDeref( dd, SuppL ); - Cudd_RecursiveDeref( dd, SuppH ); - - } - - // check that the estimation of the number of entries was okay - assert( nEntries <= nEntriesMax ); - -// if ( nEntries != Extra_bddSuppSize(dd, bSuppNew) ) -// s_Case5++; - - // update the number of entries in the new decomposition list - pThis->nDecs = nEntries; - } -//} -EXIT: - - { - // if the component created is complemented, it represents a function without complement - // therefore, as it is, without complement, it should recieve the complemented function - Dsd_Node_t * pThisR = Dsd_Regular( pThis ); - assert( pThisR->G == NULL ); - assert( pThisR->S == NULL ); - - if ( pThisR == pThis ) // set regular function - pThisR->G = bF; - else // set complemented function - pThisR->G = Cudd_Not(bF); - Cudd_Ref(bF); // reference the function in the component - - assert( bSuppNew ); - pThisR->S = bSuppNew; // takes the reference from the new support - if ( st_insert( pDsdMan->Table, (char*)bF, (char*)pThis ) ) - { - assert( 0 ); - } - s_CacheEntries++; - - -/* - if ( dsdKernelVerifyDecomposition(dd, pThis) == 0 ) - { - // write the function, for which verification does not work - cout << endl << "Internal verification failed!"" ); - - // create the variable mask - static int s_pVarMask[MAXINPUTS]; - int nInputCounter = 0; - - Cudd_SupportArray( dd, bF, s_pVarMask ); - int k; - for ( k = 0; k < dd->size; k++ ) - if ( s_pVarMask[k] ) - nInputCounter++; - - cout << endl << "The problem function is "" ); - - DdNode * zNewFunc = Cudd_zddIsopCover( dd, bF, bF ); Cudd_Ref( zNewFunc ); - cuddWriteFunctionSop( stdout, dd, zNewFunc, -1, dd->size, "1", s_pVarMask ); - Cudd_RecursiveDerefZdd( dd, zNewFunc ); - } -*/ - - } - - Depth--; - return Dsd_NotCond( pThis, fCompF ); -} - - -//////////////////////////////////////////////////////////////////////// -/// OTHER FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Finds the corresponding decomposition entry.] - - Description [This function returns the non-complemented pointer to the - DecEntry of that component which contains the given variable in its - support, or NULL if no such component exists] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity ) - -{ - Dsd_Node_t * pTemp; - int i; - -// assert( !Dsd_IsComplement( pWhere ) ); -// assert( Extra_bddSuppContainVar( pDsdMan->dd, pWhere->S, Var ) ); - - if ( pWhere->nDecs == 1 ) - return NULL; - - for( i = 0; i < pWhere->nDecs; i++ ) - { - pTemp = Dsd_Regular( pWhere->pDecs[i] ); - if ( Extra_bddSuppContainVar( pDsdMan->dd, pTemp->S, Var ) ) - { - *fPolarity = (int)( pTemp != pWhere->pDecs[i] ); - return pTemp; - } - } - assert( 0 ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Find the common decomposition components.] - - Description [This function determines the common components. It counts - the number of common components in the decomposition lists of pL and pH - and returns their number and the lists of common components. It assumes - that pL and pH are regular pointers. It retuns also the pointers to the - last different components encountered in pL and pH.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH ) -{ - static Dsd_Node_t * Common[MAXINPUTS]; - int nCommon = 0; - - // pointers to the current decomposition entries - Dsd_Node_t * pLcur; - Dsd_Node_t * pHcur; - - // the pointers to their supports - DdNode * bSLcur; - DdNode * bSHcur; - - // the top variable in the supports - int TopVar; - - // the indices running through the components - int iCurL = 0; - int iCurH = 0; - while ( iCurL < pL->nDecs && iCurH < pH->nDecs ) - { // both did not run out - - pLcur = Dsd_Regular(pL->pDecs[iCurL]); - pHcur = Dsd_Regular(pH->pDecs[iCurH]); - - bSLcur = pLcur->S; - bSHcur = pHcur->S; - - // find out what component is higher in the BDD - if ( pDsdMan->dd->perm[bSLcur->index] < pDsdMan->dd->perm[bSHcur->index] ) - TopVar = bSLcur->index; - else - TopVar = bSHcur->index; - - if ( TopVar == bSLcur->index && TopVar == bSHcur->index ) - { - // the components may be equal - should match exactly! - if ( pL->pDecs[iCurL] == pH->pDecs[iCurH] ) - Common[nCommon++] = pL->pDecs[iCurL]; - else - { - *pLastDiffL = pL->pDecs[iCurL]; - *pLastDiffH = pH->pDecs[iCurH]; - } - - // skip both - iCurL++; - iCurH++; - } - else if ( TopVar == bSLcur->index ) - { // the components cannot be equal - // skip the top-most one - *pLastDiffL = pL->pDecs[iCurL++]; - } - else // if ( TopVar == bSHcur->index ) - { // the components cannot be equal - // skip the top-most one - *pLastDiffH = pH->pDecs[iCurH++]; - } - } - - // if one of the lists still has components, write the first one down - if ( iCurL < pL->nDecs ) - *pLastDiffL = pL->pDecs[iCurL]; - - if ( iCurH < pH->nDecs ) - *pLastDiffH = pH->pDecs[iCurH]; - - // return the pointer to the array - *pCommon = Common; - // return the number of common components - return nCommon; -} - -/**Function************************************************************* - - Synopsis [Computes the sum (OR or EXOR) of the functions of the components.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor ) -{ - DdManager * dd = pDsdMan->dd; - DdNode * bF, * bS, * bFadd, * bTemp; - Dsd_Node_t * pDE, * pDER; - int i; - - // start the function - bF = b0; Cudd_Ref( bF ); - // start the support - if ( pCompS ) - bS = b1, Cudd_Ref( bS ); - - assert( nCommon > 0 ); - for ( i = 0; i < nCommon; i++ ) - { - pDE = pCommon[i]; - pDER = Dsd_Regular( pDE ); - bFadd = (pDE != pDER)? Cudd_Not(pDER->G): pDER->G; - // add to the function - if ( fExor ) - bF = Cudd_bddXor( dd, bTemp = bF, bFadd ); - else - bF = Cudd_bddOr( dd, bTemp = bF, bFadd ); - Cudd_Ref( bF ); - Cudd_RecursiveDeref( dd, bTemp ); - if ( pCompS ) - { - // add to the support - bS = Cudd_bddAnd( dd, bTemp = bS, pDER->S ); Cudd_Ref( bS ); - Cudd_RecursiveDeref( dd, bTemp ); - } - } - // return the function - Cudd_Deref( bF ); - *pCompF = bF; - - // return the support - if ( pCompS ) - Cudd_Deref( bS ), *pCompS = bS; -} - -/**Function************************************************************* - - Synopsis [Checks support containment of the decomposition components.] - - Description [This function returns 1 if support of one component is contained - in that of another. In this case, pLarge (pSmall) is assigned to point to the - larger (smaller) support. If the supports are identical return 0, and does not - assign the components.] -] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall ) -{ - DdManager * dd = pDsdMan->dd; - DdNode * bSuppLarge, * bSuppSmall; - int RetValue; - - RetValue = Extra_bddSuppCheckContainment( dd, pL->S, pH->S, &bSuppLarge, &bSuppSmall ); - - if ( RetValue == 0 ) - return 0; - - if ( pH->S == bSuppLarge ) - { - *pLarge = pH; - *pSmall = pL; - } - else // if ( pL->S == bSuppLarge ) - { - *pLarge = pL; - *pSmall = pH; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Copies the list of components plus one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize ) -{ - int i; - assert( nListSize+1 == p->nDecs ); - p->pDecs[0] = First; - for( i = 0; i < nListSize; i++ ) - p->pDecs[i+1] = ppList[i]; -} - -/**Function************************************************************* - - Synopsis [Copies the list of components plus one, and skips one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int iSkipped ) -{ - int i, Counter; - assert( nListSize == p->nDecs ); - p->pDecs[0] = First; - for( i = 0, Counter = 1; i < nListSize; i++ ) - if ( i != iSkipped ) - p->pDecs[Counter++] = ppList[i]; -} - -/**Function************************************************************* - - Synopsis [Debugging procedure to compute the functionality of the decomposed structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE ) -{ - DdManager * dd = pDsdMan->dd; - Dsd_Node_t * pR = Dsd_Regular(pDE); - int fCompP = (int)( pDE != pR ); - int RetValue; - - DdNode * bRes; - if ( pR->Type == DSD_NODE_CONST1 ) - bRes = b1; - else if ( pR->Type == DSD_NODE_BUF ) - bRes = pR->G; - else if ( pR->Type == DSD_NODE_OR || pR->Type == DSD_NODE_EXOR ) - dsdKernelComputeSumOfComponents( pDsdMan, pR->pDecs, pR->nDecs, &bRes, NULL, (int)(pR->Type == DSD_NODE_EXOR) ); - else if ( pR->Type == DSD_NODE_PRIME ) - { - int i; - static DdNode * bGVars[MAXINPUTS]; - // transform the function of this block, so that it depended on inputs - // corresponding to the formal inputs - DdNode * bNewFunc = Dsd_TreeGetPrimeFunctionOld( dd, pR, 1 ); Cudd_Ref( bNewFunc ); - - // compose this function with the inputs - // create the elementary permutation - for ( i = 0; i < dd->size; i++ ) - bGVars[i] = dd->vars[i]; - - // assign functions to be composed - for ( i = 0; i < pR->nDecs; i++ ) - bGVars[dd->invperm[i]] = pR->pDecs[i]->G; - - // perform the composition - bRes = Cudd_bddVectorCompose( dd, bNewFunc, bGVars ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bNewFunc ); - - ///////////////////////////////////////////////////////// - RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) ); - ///////////////////////////////////////////////////////// - Cudd_Deref( bRes ); - } - else - { - assert(0); - } - - Cudd_Ref( bRes ); - RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) ); - Cudd_RecursiveDeref( dd, bRes ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdTree.c b/src/bdd/dsd/dsdTree.c deleted file mode 100644 index 2855d68d..00000000 --- a/src/bdd/dsd/dsdTree.c +++ /dev/null @@ -1,1068 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdTree.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Managing the decomposition tree.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdTree.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode ); -static void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ); -static int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode ); -static int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode ); -static int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars ); -static void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes ); -static void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fCcmp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames ); -static void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter ); - -//////////////////////////////////////////////////////////////////////// -/// STATIC VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -static int s_DepthMax; -static int s_GateSizeMax; - -static int s_CounterBlocks; -static int s_CounterPos; -static int s_CounterNeg; -static int s_CounterNo; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Create the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum ) -{ - // allocate memory for this node - Dsd_Node_t * p = (Dsd_Node_t *) malloc( sizeof(Dsd_Node_t) ); - memset( p, 0, sizeof(Dsd_Node_t) ); - p->Type = Type; // the type of this block - p->nDecs = nDecs; // the number of decompositions - if ( p->nDecs ) - { - p->pDecs = (Dsd_Node_t **) malloc( p->nDecs * sizeof(Dsd_Node_t *) ); - p->pDecs[0] = NULL; - } - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode ) -{ - if ( pNode->G ) Cudd_RecursiveDeref( dd, pNode->G ); - if ( pNode->S ) Cudd_RecursiveDeref( dd, pNode->S ); - FREE( pNode->pDecs ); - FREE( pNode ); -} - -/**Function************************************************************* - - Synopsis [Unmarks the decomposition tree.] - - Description [This function assumes that originally pNode->nVisits are - set to zero!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeUnmark( Dsd_Manager_t * pDsdMan ) -{ - int i; - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Dsd_TreeUnmark_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); -} - - -/**Function************************************************************* - - Synopsis [Recursive unmarking.] - - Description [This function should be called with a non-complemented - pointer.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode ) -{ - int i; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits > 0 ); - - if ( --pNode->nVisits ) // if this is not the last visit, return - return; - - // upon the last visit, go through the list of successors and call recursively - if ( pNode->Type != DSD_NODE_BUF && pNode->Type != DSD_NODE_CONST1 ) - for ( i = 0; i < pNode->nDecs; i++ ) - Dsd_TreeUnmark_rec( Dsd_Regular(pNode->pDecs[i]) ); -} - -/**Function************************************************************* - - Synopsis [Getting information about the node.] - - Description [This function computes the max depth and the max gate size - of the tree rooted at the node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeNodeGetInfo( Dsd_Manager_t * pDsdMan, int * DepthMax, int * GateSizeMax ) -{ - int i; - s_DepthMax = 0; - s_GateSizeMax = 0; - - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Dsd_TreeGetInfo_rec( Dsd_Regular( pDsdMan->pRoots[i] ), 0 ); - - if ( DepthMax ) - *DepthMax = s_DepthMax; - if ( GateSizeMax ) - *GateSizeMax = s_GateSizeMax; -} - -/**Function************************************************************* - - Synopsis [Getting information about the node.] - - Description [This function computes the max depth and the max gate size - of the tree rooted at the node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax ) -{ - s_DepthMax = 0; - s_GateSizeMax = 0; - - Dsd_TreeGetInfo_rec( Dsd_Regular(pNode), 0 ); - - if ( DepthMax ) - *DepthMax = s_DepthMax; - if ( GateSizeMax ) - *GateSizeMax = s_GateSizeMax; -} - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Dsd_TreeNodeGetInfo().] - - Description [pNode is the node, for the tree rooted in which we are - determining info. RankCur is the current rank to assign to the node. - fSetRank is the flag saying whether the rank will be written in the - node. s_DepthMax is the maximum depths of the tree. s_GateSizeMax is - the maximum gate size.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ) -{ - int i; - int GateSize; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - // we don't want the two-input gates to count for non-decomposable blocks - if ( pNode->Type == DSD_NODE_OR || - pNode->Type == DSD_NODE_EXOR ) - GateSize = 2; - else - GateSize = pNode->nDecs; - - // update the max size of the node - if ( s_GateSizeMax < GateSize ) - s_GateSizeMax = GateSize; - - if ( pNode->nDecs < 2 ) - return; - - // update the max rank - if ( s_DepthMax < RankCur+1 ) - s_DepthMax = RankCur+1; - - // call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Dsd_TreeGetInfo_rec( Dsd_Regular(pNode->pDecs[i]), RankCur+1 ); -} - -/**Function************************************************************* - - Synopsis [Counts AIG nodes needed to implement this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeGetAigCost_rec( Dsd_Node_t * pNode ) -{ - int i, Counter = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nDecs < 2 ) - return 0; - - // we don't want the two-input gates to count for non-decomposable blocks - if ( pNode->Type == DSD_NODE_OR ) - Counter += pNode->nDecs - 1; - else if ( pNode->Type == DSD_NODE_EXOR ) - Counter += 3*(pNode->nDecs - 1); - else if ( pNode->Type == DSD_NODE_PRIME && pNode->nDecs == 3 ) - Counter += 3; - - // call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Counter += Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode->pDecs[i]) ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts AIG nodes needed to implement this node.] - - Description [Assumes that the only primes of the DSD tree are MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeGetAigCost( Dsd_Node_t * pNode ) -{ - return Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode) ); -} - -/**Function************************************************************* - - Synopsis [Counts non-terminal nodes of the DSD tree.] - - Description [Nonterminal nodes include all the nodes with the - support more than 1. These are OR, EXOR, and PRIME nodes. They - do not include the elementary variable nodes and the constant 1 - node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * pDsdMan ) -{ - int Counter, i; - Counter = 0; - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); - Dsd_TreeUnmark( pDsdMan ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot ) -{ - int Counter = 0; - - // go through the list of successors and call recursively - Counter = Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pRoot) ); - - Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) ); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Counts non-terminal nodes for one root.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode ) -{ - int i; - int Counter = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nVisits++ ) // if this is not the first visit, return zero - return 0; - - if ( pNode->nDecs <= 1 ) - return 0; - - // upon the first visit, go through the list of successors and call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pNode->pDecs[i]) ); - - return Counter + 1; -} - - -/**Function************************************************************* - - Synopsis [Counts prime nodes of the DSD tree.] - - Description [Prime nodes are nodes with the support more than 2, - that is not an OR or EXOR gate.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan ) -{ - int Counter, i; - Counter = 0; - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); - Dsd_TreeUnmark( pDsdMan ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts prime nodes for one root.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ) -{ - int Counter = 0; - - // go through the list of successors and call recursively - Counter = Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pRoot) ); - - Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) ); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode ) -{ - int i; - int Counter = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nVisits++ ) // if this is not the first visit, return zero - return 0; - - if ( pNode->nDecs <= 1 ) - return 0; - - // upon the first visit, go through the list of successors and call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pNode->pDecs[i]) ); - - if ( pNode->Type == DSD_NODE_PRIME ) - Counter++; - - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Collects the decomposable vars on the PI side.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * pDsdMan, int * pVars ) -{ - int nVars; - - // set the vars collected to 0 - nVars = 0; - Dsd_TreeCollectDecomposableVars_rec( pDsdMan->dd, Dsd_Regular(pDsdMan->pRoots[0]), pVars, &nVars ); - // return the number of collected vars - return nVars; -} - -/**Function************************************************************* - - Synopsis [Implements the recursive part of Dsd_TreeCollectDecomposableVars().] - - Description [Adds decomposable variables as they are found to pVars and increments - nVars. Returns 1 if a non-dec node with more than 4 inputs was encountered - in the processed subtree. Returns 0, otherwise. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars ) -{ - int fSkipThisNode, i; - Dsd_Node_t * pTemp; - int fVerbose = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - - if ( pNode->nDecs <= 1 ) - return 0; - - // go through the list of successors and call recursively - fSkipThisNode = 0; - for ( i = 0; i < pNode->nDecs; i++ ) - if ( Dsd_TreeCollectDecomposableVars_rec(dd, Dsd_Regular(pNode->pDecs[i]), pVars, nVars) ) - fSkipThisNode = 1; - - if ( !fSkipThisNode && (pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR || pNode->nDecs <= 4) ) - { -if ( fVerbose ) -printf( "Node of type <%d> (OR=6,EXOR=8,RAND=1): ", pNode->Type ); - - for ( i = 0; i < pNode->nDecs; i++ ) - { - pTemp = Dsd_Regular(pNode->pDecs[i]); - if ( pTemp->Type == DSD_NODE_BUF ) - { - if ( pVars ) - pVars[ (*nVars)++ ] = pTemp->S->index; - else - (*nVars)++; - -if ( fVerbose ) -printf( "%d ", pTemp->S->index ); - } - } -if ( fVerbose ) -printf( "\n" ); - } - else - fSkipThisNode = 1; - - - return fSkipThisNode; -} - - -/**Function************************************************************* - - Synopsis [Creates the DFS ordered array of DSD nodes in the tree.] - - Description [The collected nodes do not include the terminal nodes - and the constant 1 node. The array of nodes is returned. The number - of entries in the array is returned in the variale pnNodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * pDsdMan, int * pnNodes ) -{ - Dsd_Node_t ** ppNodes; - int nNodes, nNodesAlloc; - int i; - - nNodesAlloc = Dsd_TreeCountNonTerminalNodes(pDsdMan); - nNodes = 0; - ppNodes = ALLOC( Dsd_Node_t *, nNodesAlloc ); - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pDsdMan->pRoots[i]), ppNodes, &nNodes ); - Dsd_TreeUnmark( pDsdMan ); - assert( nNodesAlloc == nNodes ); - *pnNodes = nNodes; - return ppNodes; -} - -/**Function************************************************************* - - Synopsis [Creates the DFS ordered array of DSD nodes in the tree.] - - Description [The collected nodes do not include the terminal nodes - and the constant 1 node. The array of nodes is returned. The number - of entries in the array is returned in the variale pnNodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ) -{ - Dsd_Node_t ** ppNodes; - int nNodes, nNodesAlloc; - nNodesAlloc = Dsd_TreeCountNonTerminalNodesOne(pNode); - nNodes = 0; - ppNodes = ALLOC( Dsd_Node_t *, nNodesAlloc ); - Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode), ppNodes, &nNodes ); - Dsd_TreeUnmark_rec(Dsd_Regular(pNode)); - assert( nNodesAlloc == nNodes ); - *pnNodes = nNodes; - return ppNodes; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes ) -{ - int i; - assert( pNode ); - assert( !Dsd_IsComplement(pNode) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nVisits++ ) // if this is not the first visit, return zero - return; - if ( pNode->nDecs <= 1 ) - return; - - // upon the first visit, go through the list of successors and call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode->pDecs[i]), ppNodes, pnNodes ); - - ppNodes[ (*pnNodes)++ ] = pNode; -} - -/**Function************************************************************* - - Synopsis [Prints the decompostion tree into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * pDsdMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ) -{ - Dsd_Node_t * pNode; - int SigCounter; - int i; - SigCounter = 1; - - if ( Output == -1 ) - { - for ( i = 0; i < pDsdMan->nRoots; i++ ) - { - pNode = Dsd_Regular( pDsdMan->pRoots[i] ); - Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[i]), pInputNames, pOutputNames[i], 0, &SigCounter, fShortNames ); - } - } - else - { - assert( Output >= 0 && Output < pDsdMan->nRoots ); - pNode = Dsd_Regular( pDsdMan->pRoots[Output] ); - Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[Output]), pInputNames, pOutputNames[Output], 0, &SigCounter, fShortNames ); - } -} - -/**Function************************************************************* - - Synopsis [Prints the decompostion tree into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames ) -{ - char Buffer[100]; - Dsd_Node_t * pInput; - int * pInputNums; - int fCompNew, i; - - assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || - pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); - - Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); - if ( !fComp ) - fprintf( pFile, "%s = ", pOutputName ); - else - fprintf( pFile, "NOT(%s) = ", pOutputName ); - pInputNums = ALLOC( int, pNode->nDecs ); - if ( pNode->Type == DSD_NODE_CONST1 ) - { - fprintf( pFile, " Constant 1.\n" ); - } - else if ( pNode->Type == DSD_NODE_BUF ) - { - if ( fShortNames ) - fprintf( pFile, "%d", 'a' + pNode->S->index ); - else - fprintf( pFile, "%s", pInputNames[pNode->S->index] ); - fprintf( pFile, "\n" ); - } - else if ( pNode->Type == DSD_NODE_PRIME ) - { - // print the line - fprintf( pFile, "PRIME(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - if ( fShortNames ) - fprintf( pFile, "%d", pInput->S->index ); - else - fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, ")" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); - } - } - else if ( pNode->Type == DSD_NODE_OR ) - { - // print the line - fprintf( pFile, "OR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - if ( fShortNames ) - fprintf( pFile, "%c", 'a' + pInput->S->index ); - else - fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, ")" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); - } - } - else if ( pNode->Type == DSD_NODE_EXOR ) - { - // print the line - fprintf( pFile, "EXOR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - if ( fShortNames ) - fprintf( pFile, "%c", 'a' + pInput->S->index ); - else - fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, ")" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); - } - } - free( pInputNums ); -} - -/**Function************************************************************* - - Synopsis [Prints the decompostion tree into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ) -{ - Dsd_Node_t * pNodeR; - int SigCounter = 1; - pNodeR = Dsd_Regular(pNode); - Dsd_NodePrint_rec( pFile, pNodeR, pNodeR != pNode, "F", 0, &SigCounter ); -} - -/**Function************************************************************* - - Synopsis [Prints one node of the decomposition tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter ) -{ - char Buffer[100]; - Dsd_Node_t * pInput; - int * pInputNums; - int fCompNew, i; - - assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || - pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); - - Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); - if ( !fComp ) - fprintf( pFile, "%s = ", pOutputName ); - else - fprintf( pFile, "NOT(%s) = ", pOutputName ); - pInputNums = ALLOC( int, pNode->nDecs ); - if ( pNode->Type == DSD_NODE_CONST1 ) - { - fprintf( pFile, " Constant 1.\n" ); - } - else if ( pNode->Type == DSD_NODE_BUF ) - { - fprintf( pFile, " " ); - fprintf( pFile, "%c", 'a' + pNode->S->index ); - fprintf( pFile, "\n" ); - } - else if ( pNode->Type == DSD_NODE_PRIME ) - { - // print the line - fprintf( pFile, "PRIME(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - assert( fCompNew == 0 ); - if ( i ) - fprintf( pFile, "," ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - fprintf( pFile, " %c", 'a' + pInput->S->index ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, "\'" ); - } - fprintf( pFile, " )\n" ); -/* - fprintf( pFile, " ) " ); - { - DdNode * bLocal; - bLocal = Dsd_TreeGetPrimeFunction( dd, pNodeDsd ); Cudd_Ref( bLocal ); - Extra_bddPrint( dd, bLocal ); - Cudd_RecursiveDeref( dd, bLocal ); - } -*/ - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); - } - } - else if ( pNode->Type == DSD_NODE_OR ) - { - // print the line - fprintf( pFile, "OR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - fprintf( pFile, " %c", 'a' + pInput->S->index ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, "\'" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); - } - } - else if ( pNode->Type == DSD_NODE_EXOR ) - { - // print the line - fprintf( pFile, "EXOR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - assert( fCompNew == 0 ); - if ( i ) - fprintf( pFile, "," ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - fprintf( pFile, " %c", 'a' + pInput->S->index ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, "\'" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); - } - } - free( pInputNums ); -} - - -/**Function************************************************************* - - Synopsis [Retuns the function of one node of the decomposition tree.] - - Description [This is the old procedure. It is now superceded by the - procedure Dsd_TreeGetPrimeFunction() found in "dsdLocal.c".] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) -{ - DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; - int i; - int fAllBuffs = 1; - static int Permute[MAXINPUTS]; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->Type == DSD_NODE_PRIME ); - - // transform the function of this block to depend on inputs - // corresponding to the formal inputs - - // first, substitute those inputs that have some blocks associated with them - // second, remap the inputs to the top of the manager (then, it is easy to output them) - - // start the function - bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); - // go over all primary inputs - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pNode->pDecs[i]->Type != DSD_NODE_BUF ) // remap only if it is not the buffer - { - bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); - bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); - Cudd_RecursiveDeref( dd, bCube0 ); - - bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); - bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); - Cudd_RecursiveDeref( dd, bCube1 ); - - Cudd_RecursiveDeref( dd, bNewFunc ); - - // use the variable in the i-th level of the manager -// bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - // use the first variale in the support of the component - bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - } - - if ( fRemap ) - { - // remap the function to the top of the manager - // remap the function to the first variables of the manager - for ( i = 0; i < pNode->nDecs; i++ ) - // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; - Permute[ pNode->pDecs[i]->S->index ] = i; - - bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - Cudd_Deref( bNewFunc ); - return bNewFunc; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/module.make b/src/bdd/dsd/module.make deleted file mode 100644 index f5e6673d..00000000 --- a/src/bdd/dsd/module.make +++ /dev/null @@ -1,6 +0,0 @@ -SRC += src/bdd/dsd/dsdApi.c \ - src/bdd/dsd/dsdCheck.c \ - src/bdd/dsd/dsdLocal.c \ - src/bdd/dsd/dsdMan.c \ - src/bdd/dsd/dsdProc.c \ - src/bdd/dsd/dsdTree.c diff --git a/src/bdd/epd/epd.c b/src/bdd/epd/epd.c deleted file mode 100644 index a80240bc..00000000 --- a/src/bdd/epd/epd.c +++ /dev/null @@ -1,1314 +0,0 @@ -/**CFile*********************************************************************** - - FileName [epd.c] - - PackageName [epd] - - Synopsis [Arithmetic functions with extended double precision.] - - Description [] - - SeeAlso [] - - Author [In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: epd.c,v 1.1.1.1 2003/02/24 22:23:57 wjiang Exp $] - -******************************************************************************/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include "util_hack.h" -#include "epd.h" - - -/**Function******************************************************************** - - Synopsis [Allocates an EpDouble struct.] - - Description [Allocates an EpDouble struct.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -EpDouble * -EpdAlloc() -{ - EpDouble *epd; - - epd = ALLOC(EpDouble, 1); - return(epd); -} - - -/**Function******************************************************************** - - Synopsis [Compares two EpDouble struct.] - - Description [Compares two EpDouble struct.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdCmp(const char *key1, const char *key2) -{ - EpDouble *epd1 = (EpDouble *) key1; - EpDouble *epd2 = (EpDouble *) key2; - if (epd1->type.value != epd2->type.value || - epd1->exponent != epd2->exponent) { - return(1); - } - return(0); -} - - -/**Function******************************************************************** - - Synopsis [Frees an EpDouble struct.] - - Description [Frees an EpDouble struct.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdFree(EpDouble *epd) -{ - FREE(epd); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdGetString(EpDouble *epd, char *str) -{ - double value; - int exponent; - char *pos; - - if (IsNanDouble(epd->type.value)) { - sprintf(str, "NaN"); - return; - } else if (IsInfDouble(epd->type.value)) { - if (epd->type.bits.sign == 1) - sprintf(str, "-Inf"); - else - sprintf(str, "Inf"); - return; - } - - assert(epd->type.bits.exponent == EPD_MAX_BIN || - epd->type.bits.exponent == 0); - - EpdGetValueAndDecimalExponent(epd, &value, &exponent); - sprintf(str, "%e", value); - pos = strstr(str, "e"); - if (exponent >= 0) { - if (exponent < 10) - sprintf(pos + 1, "+0%d", exponent); - else - sprintf(pos + 1, "+%d", exponent); - } else { - exponent *= -1; - if (exponent < 10) - sprintf(pos + 1, "-0%d", exponent); - else - sprintf(pos + 1, "-%d", exponent); - } -} - - -/**Function******************************************************************** - - Synopsis [Converts double to EpDouble struct.] - - Description [Converts double to EpDouble struct.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdConvert(double value, EpDouble *epd) -{ - epd->type.value = value; - epd->exponent = 0; - EpdNormalize(epd); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMultiply(EpDouble *epd1, double value) -{ - EpDouble epd2; - double tmp; - int exponent; - - if (EpdIsNan(epd1) || IsNanDouble(value)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || IsInfDouble(value)) { - int sign; - - EpdConvert(value, &epd2); - sign = epd1->type.bits.sign ^ epd2.type.bits.sign; - EpdMakeInf(epd1, sign); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - - EpdConvert(value, &epd2); - tmp = epd1->type.value * epd2.type.value; - exponent = epd1->exponent + epd2.exponent; - epd1->type.value = tmp; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMultiply2(EpDouble *epd1, EpDouble *epd2) -{ - double value; - int exponent; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd1, sign); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - value = epd1->type.value * epd2->type.value; - exponent = epd1->exponent + epd2->exponent; - epd1->type.value = value; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2) -{ - double value; - int exponent; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd1, sign); - return; - } - - value = epd1->type.value * epd2->type.value; - exponent = epd1->exponent + epd2->exponent; - epd1->type.value = value; - epd1->exponent = exponent; - EpdNormalizeDecimal(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) -{ - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd3, sign); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - epd3->type.value = epd1->type.value * epd2->type.value; - epd3->exponent = epd1->exponent + epd2->exponent; - EpdNormalize(epd3); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) -{ - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd3, sign); - return; - } - - epd3->type.value = epd1->type.value * epd2->type.value; - epd3->exponent = epd1->exponent + epd2->exponent; - EpdNormalizeDecimal(epd3); -} - - -/**Function******************************************************************** - - Synopsis [Divides two arbitrary precision double values.] - - Description [Divides two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdDivide(EpDouble *epd1, double value) -{ - EpDouble epd2; - double tmp; - int exponent; - - if (EpdIsNan(epd1) || IsNanDouble(value)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || IsInfDouble(value)) { - int sign; - - EpdConvert(value, &epd2); - if (EpdIsInf(epd1) && IsInfDouble(value)) { - EpdMakeNan(epd1); - } else if (EpdIsInf(epd1)) { - sign = epd1->type.bits.sign ^ epd2.type.bits.sign; - EpdMakeInf(epd1, sign); - } else { - sign = epd1->type.bits.sign ^ epd2.type.bits.sign; - EpdMakeZero(epd1, sign); - } - return; - } - - if (value == 0.0) { - EpdMakeNan(epd1); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - - EpdConvert(value, &epd2); - tmp = epd1->type.value / epd2.type.value; - exponent = epd1->exponent - epd2.exponent; - epd1->type.value = tmp; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Divides two arbitrary precision double values.] - - Description [Divides two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdDivide2(EpDouble *epd1, EpDouble *epd2) -{ - double value; - int exponent; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - EpdMakeNan(epd1); - } else if (EpdIsInf(epd1)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd1, sign); - } else { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeZero(epd1, sign); - } - return; - } - - if (epd2->type.value == 0.0) { - EpdMakeNan(epd1); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - value = epd1->type.value / epd2->type.value; - exponent = epd1->exponent - epd2->exponent; - epd1->type.value = value; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Divides two arbitrary precision double values.] - - Description [Divides two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) -{ - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd3); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - EpdMakeNan(epd3); - } else if (EpdIsInf(epd1)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd3, sign); - } else { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeZero(epd3, sign); - } - return; - } - - if (epd2->type.value == 0.0) { - EpdMakeNan(epd3); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - epd3->type.value = epd1->type.value / epd2->type.value; - epd3->exponent = epd1->exponent - epd2->exponent; - EpdNormalize(epd3); -} - - -/**Function******************************************************************** - - Synopsis [Adds two arbitrary precision double values.] - - Description [Adds two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdAdd(EpDouble *epd1, double value) -{ - EpDouble epd2; - double tmp; - int exponent, diff; - - if (EpdIsNan(epd1) || IsNanDouble(value)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || IsInfDouble(value)) { - int sign; - - EpdConvert(value, &epd2); - if (EpdIsInf(epd1) && IsInfDouble(value)) { - sign = epd1->type.bits.sign ^ epd2.type.bits.sign; - if (sign == 1) - EpdMakeNan(epd1); - } else if (EpdIsInf(&epd2)) { - EpdCopy(&epd2, epd1); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - - EpdConvert(value, &epd2); - if (epd1->exponent > epd2.exponent) { - diff = epd1->exponent - epd2.exponent; - if (diff <= EPD_MAX_BIN) - tmp = epd1->type.value + epd2.type.value / pow((double)2.0, (double)diff); - else - tmp = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2.exponent) { - diff = epd2.exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) - tmp = epd1->type.value / pow((double)2.0, (double)diff) + epd2.type.value; - else - tmp = epd2.type.value; - exponent = epd2.exponent; - } else { - tmp = epd1->type.value + epd2.type.value; - exponent = epd1->exponent; - } - epd1->type.value = tmp; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Adds two arbitrary precision double values.] - - Description [Adds two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdAdd2(EpDouble *epd1, EpDouble *epd2) -{ - double value; - int exponent, diff; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - if (sign == 1) - EpdMakeNan(epd1); - } else if (EpdIsInf(epd2)) { - EpdCopy(epd2, epd1); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - if (epd1->exponent > epd2->exponent) { - diff = epd1->exponent - epd2->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value + - epd2->type.value / pow((double)2.0, (double)diff); - } else - value = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2->exponent) { - diff = epd2->exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value / pow((double)2.0, (double)diff) + - epd2->type.value; - } else - value = epd2->type.value; - exponent = epd2->exponent; - } else { - value = epd1->type.value + epd2->type.value; - exponent = epd1->exponent; - } - epd1->type.value = value; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Adds two arbitrary precision double values.] - - Description [Adds two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) -{ - double value; - int exponent, diff; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd3); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - if (sign == 1) - EpdMakeNan(epd3); - else - EpdCopy(epd1, epd3); - } else if (EpdIsInf(epd1)) { - EpdCopy(epd1, epd3); - } else { - EpdCopy(epd2, epd3); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - if (epd1->exponent > epd2->exponent) { - diff = epd1->exponent - epd2->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value + - epd2->type.value / pow((double)2.0, (double)diff); - } else - value = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2->exponent) { - diff = epd2->exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value / pow((double)2.0, (double)diff) + - epd2->type.value; - } else - value = epd2->type.value; - exponent = epd2->exponent; - } else { - value = epd1->type.value + epd2->type.value; - exponent = epd1->exponent; - } - epd3->type.value = value; - epd3->exponent = exponent; - EpdNormalize(epd3); -} - - -/**Function******************************************************************** - - Synopsis [Subtracts two arbitrary precision double values.] - - Description [Subtracts two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdSubtract(EpDouble *epd1, double value) -{ - EpDouble epd2; - double tmp; - int exponent, diff; - - if (EpdIsNan(epd1) || IsNanDouble(value)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || IsInfDouble(value)) { - int sign; - - EpdConvert(value, &epd2); - if (EpdIsInf(epd1) && IsInfDouble(value)) { - sign = epd1->type.bits.sign ^ epd2.type.bits.sign; - if (sign == 0) - EpdMakeNan(epd1); - } else if (EpdIsInf(&epd2)) { - EpdCopy(&epd2, epd1); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - - EpdConvert(value, &epd2); - if (epd1->exponent > epd2.exponent) { - diff = epd1->exponent - epd2.exponent; - if (diff <= EPD_MAX_BIN) - tmp = epd1->type.value - epd2.type.value / pow((double)2.0, (double)diff); - else - tmp = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2.exponent) { - diff = epd2.exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) - tmp = epd1->type.value / pow((double)2.0, (double)diff) - epd2.type.value; - else - tmp = epd2.type.value * (double)(-1.0); - exponent = epd2.exponent; - } else { - tmp = epd1->type.value - epd2.type.value; - exponent = epd1->exponent; - } - epd1->type.value = tmp; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Subtracts two arbitrary precision double values.] - - Description [Subtracts two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdSubtract2(EpDouble *epd1, EpDouble *epd2) -{ - double value; - int exponent, diff; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - if (sign == 0) - EpdMakeNan(epd1); - } else if (EpdIsInf(epd2)) { - EpdCopy(epd2, epd1); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - if (epd1->exponent > epd2->exponent) { - diff = epd1->exponent - epd2->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value - - epd2->type.value / pow((double)2.0, (double)diff); - } else - value = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2->exponent) { - diff = epd2->exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value / pow((double)2.0, (double)diff) - - epd2->type.value; - } else - value = epd2->type.value * (double)(-1.0); - exponent = epd2->exponent; - } else { - value = epd1->type.value - epd2->type.value; - exponent = epd1->exponent; - } - epd1->type.value = value; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Subtracts two arbitrary precision double values.] - - Description [Subtracts two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) -{ - double value; - int exponent, diff; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd3); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - if (sign == 0) - EpdCopy(epd1, epd3); - else - EpdMakeNan(epd3); - } else if (EpdIsInf(epd1)) { - EpdCopy(epd1, epd1); - } else { - sign = epd2->type.bits.sign ^ 0x1; - EpdMakeInf(epd3, sign); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - if (epd1->exponent > epd2->exponent) { - diff = epd1->exponent - epd2->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value - - epd2->type.value / pow((double)2.0, (double)diff); - } else - value = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2->exponent) { - diff = epd2->exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value / pow((double)2.0, (double)diff) - - epd2->type.value; - } else - value = epd2->type.value * (double)(-1.0); - exponent = epd2->exponent; - } else { - value = epd1->type.value - epd2->type.value; - exponent = epd1->exponent; - } - epd3->type.value = value; - epd3->exponent = exponent; - EpdNormalize(epd3); -} - - -/**Function******************************************************************** - - Synopsis [Computes arbitrary precision pow of base 2.] - - Description [Computes arbitrary precision pow of base 2.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdPow2(int n, EpDouble *epd) -{ - if (n <= EPD_MAX_BIN) { - EpdConvert(pow((double)2.0, (double)n), epd); - } else { - EpDouble epd1, epd2; - int n1, n2; - - n1 = n / 2; - n2 = n - n1; - EpdPow2(n1, &epd1); - EpdPow2(n2, &epd2); - EpdMultiply3(&epd1, &epd2, epd); - } -} - - -/**Function******************************************************************** - - Synopsis [Computes arbitrary precision pow of base 2.] - - Description [Computes arbitrary precision pow of base 2.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdPow2Decimal(int n, EpDouble *epd) -{ - if (n <= EPD_MAX_BIN) { - epd->type.value = pow((double)2.0, (double)n); - epd->exponent = 0; - EpdNormalizeDecimal(epd); - } else { - EpDouble epd1, epd2; - int n1, n2; - - n1 = n / 2; - n2 = n - n1; - EpdPow2Decimal(n1, &epd1); - EpdPow2Decimal(n2, &epd2); - EpdMultiply3Decimal(&epd1, &epd2, epd); - } -} - - -/**Function******************************************************************** - - Synopsis [Normalize an arbitrary precision double value.] - - Description [Normalize an arbitrary precision double value.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdNormalize(EpDouble *epd) -{ - int exponent; - - if (IsNanOrInfDouble(epd->type.value)) { - epd->exponent = 0; - return; - } - - exponent = EpdGetExponent(epd->type.value); - if (exponent == EPD_MAX_BIN) - return; - exponent -= EPD_MAX_BIN; - epd->type.bits.exponent = EPD_MAX_BIN; - epd->exponent += exponent; -} - - -/**Function******************************************************************** - - Synopsis [Normalize an arbitrary precision double value.] - - Description [Normalize an arbitrary precision double value.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdNormalizeDecimal(EpDouble *epd) -{ - int exponent; - - if (IsNanOrInfDouble(epd->type.value)) { - epd->exponent = 0; - return; - } - - exponent = EpdGetExponentDecimal(epd->type.value); - epd->type.value /= pow((double)10.0, (double)exponent); - epd->exponent += exponent; -} - - -/**Function******************************************************************** - - Synopsis [Returns value and decimal exponent of EpDouble.] - - Description [Returns value and decimal exponent of EpDouble.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent) -{ - EpDouble epd1, epd2; - - if (EpdIsNanOrInf(epd)) - return; - - if (EpdIsZero(epd)) { - *value = 0.0; - *exponent = 0; - return; - } - - epd1.type.value = epd->type.value; - epd1.exponent = 0; - EpdPow2Decimal(epd->exponent, &epd2); - EpdMultiply2Decimal(&epd1, &epd2); - - *value = epd1.type.value; - *exponent = epd1.exponent; -} - -/**Function******************************************************************** - - Synopsis [Returns the exponent value of a double.] - - Description [Returns the exponent value of a double.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdGetExponent(double value) -{ - int exponent; - EpDouble epd; - - epd.type.value = value; - exponent = epd.type.bits.exponent; - return(exponent); -} - - -/**Function******************************************************************** - - Synopsis [Returns the decimal exponent value of a double.] - - Description [Returns the decimal exponent value of a double.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdGetExponentDecimal(double value) -{ - char *pos, str[24]; - int exponent; - - sprintf(str, "%E", value); - pos = strstr(str, "E"); - sscanf(pos, "E%d", &exponent); - return(exponent); -} - - -/**Function******************************************************************** - - Synopsis [Makes EpDouble Inf.] - - Description [Makes EpDouble Inf.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMakeInf(EpDouble *epd, int sign) -{ - epd->type.bits.mantissa1 = 0; - epd->type.bits.mantissa0 = 0; - epd->type.bits.exponent = EPD_EXP_INF; - epd->type.bits.sign = sign; - epd->exponent = 0; -} - - -/**Function******************************************************************** - - Synopsis [Makes EpDouble Zero.] - - Description [Makes EpDouble Zero.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMakeZero(EpDouble *epd, int sign) -{ - epd->type.bits.mantissa1 = 0; - epd->type.bits.mantissa0 = 0; - epd->type.bits.exponent = 0; - epd->type.bits.sign = sign; - epd->exponent = 0; -} - - -/**Function******************************************************************** - - Synopsis [Makes EpDouble NaN.] - - Description [Makes EpDouble NaN.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMakeNan(EpDouble *epd) -{ - epd->type.nan.mantissa1 = 0; - epd->type.nan.mantissa0 = 0; - epd->type.nan.quiet_bit = 1; - epd->type.nan.exponent = EPD_EXP_INF; - epd->type.nan.sign = 1; - epd->exponent = 0; -} - - -/**Function******************************************************************** - - Synopsis [Copies a EpDouble struct.] - - Description [Copies a EpDouble struct.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdCopy(EpDouble *from, EpDouble *to) -{ - to->type.value = from->type.value; - to->exponent = from->exponent; -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is Inf.] - - Description [Checks whether the value is Inf.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdIsInf(EpDouble *epd) -{ - return(IsInfDouble(epd->type.value)); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is Zero.] - - Description [Checks whether the value is Zero.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdIsZero(EpDouble *epd) -{ - if (epd->type.value == 0.0) - return(1); - else - return(0); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is NaN.] - - Description [Checks whether the value is NaN.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdIsNan(EpDouble *epd) -{ - return(IsNanDouble(epd->type.value)); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is NaN or Inf.] - - Description [Checks whether the value is NaN or Inf.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdIsNanOrInf(EpDouble *epd) -{ - return(IsNanOrInfDouble(epd->type.value)); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is Inf.] - - Description [Checks whether the value is Inf.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -IsInfDouble(double value) -{ - IeeeDouble *ptr = (IeeeDouble *)(&value); - - if (ptr->exponent == EPD_EXP_INF && - ptr->mantissa0 == 0 && - ptr->mantissa1 == 0) { - if (ptr->sign == 0) - return(1); - else - return(-1); - } - return(0); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is NaN.] - - Description [Checks whether the value is NaN.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -IsNanDouble(double value) -{ - IeeeNan *ptr = (IeeeNan *)(&value); - - if (ptr->exponent == EPD_EXP_INF && - ptr->sign == 1 && - ptr->quiet_bit == 1 && - ptr->mantissa0 == 0 && - ptr->mantissa1 == 0) { - return(1); - } - return(0); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is NaN or Inf.] - - Description [Checks whether the value is NaN or Inf.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -IsNanOrInfDouble(double value) -{ - IeeeNan *ptr = (IeeeNan *)(&value); - - if (ptr->exponent == EPD_EXP_INF && - ptr->mantissa0 == 0 && - ptr->mantissa1 == 0 && - (ptr->sign == 1 || ptr->quiet_bit == 0)) { - return(1); - } - return(0); -} diff --git a/src/bdd/epd/epd.h b/src/bdd/epd/epd.h deleted file mode 100644 index 66db80e3..00000000 --- a/src/bdd/epd/epd.h +++ /dev/null @@ -1,160 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [epd.h] - - PackageName [epd] - - Synopsis [The University of Colorado extended double precision package.] - - Description [arithmetic functions with extended double precision.] - - SeeAlso [] - - Author [In-Ho Moon] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: epd.h,v 1.1.1.1 2003/02/24 22:23:57 wjiang Exp $] - -******************************************************************************/ - -#ifndef _EPD -#define _EPD - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define EPD_MAX_BIN 1023 -#define EPD_MAX_DEC 308 -#define EPD_EXP_INF 0x7ff - -/*---------------------------------------------------------------------------*/ -/* Structure declarations */ -/*---------------------------------------------------------------------------*/ - -/**Struct********************************************************************** - - Synopsis [IEEE double struct.] - - Description [IEEE double struct.] - - SeeAlso [] - -******************************************************************************/ -#ifdef EPD_BIG_ENDIAN -struct IeeeDoubleStruct { /* BIG_ENDIAN */ - unsigned int sign: 1; - unsigned int exponent: 11; - unsigned int mantissa0: 20; - unsigned int mantissa1: 32; -}; -#else -struct IeeeDoubleStruct { /* LITTLE_ENDIAN */ - unsigned int mantissa1: 32; - unsigned int mantissa0: 20; - unsigned int exponent: 11; - unsigned int sign: 1; -}; -#endif - -/**Struct********************************************************************** - - Synopsis [IEEE double NaN struct.] - - Description [IEEE double NaN struct.] - - SeeAlso [] - -******************************************************************************/ -#ifdef EPD_BIG_ENDIAN -struct IeeeNanStruct { /* BIG_ENDIAN */ - unsigned int sign: 1; - unsigned int exponent: 11; - unsigned int quiet_bit: 1; - unsigned int mantissa0: 19; - unsigned int mantissa1: 32; -}; -#else -struct IeeeNanStruct { /* LITTLE_ENDIAN */ - unsigned int mantissa1: 32; - unsigned int mantissa0: 19; - unsigned int quiet_bit: 1; - unsigned int exponent: 11; - unsigned int sign: 1; -}; -#endif - -/**Struct********************************************************************** - - Synopsis [Extended precision double to keep very large value.] - - Description [Extended precision double to keep very large value.] - - SeeAlso [] - -******************************************************************************/ -struct EpDoubleStruct { - union { - double value; - struct IeeeDoubleStruct bits; - struct IeeeNanStruct nan; - } type; - int exponent; -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ -typedef struct EpDoubleStruct EpDouble; -typedef struct IeeeDoubleStruct IeeeDouble; -typedef struct IeeeNanStruct IeeeNan; - - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - -EpDouble *EpdAlloc(); -int EpdCmp(const char *key1, const char *key2); -void EpdFree(EpDouble *epd); -void EpdGetString(EpDouble *epd, char *str); -void EpdConvert(double value, EpDouble *epd); -void EpdMultiply(EpDouble *epd1, double value); -void EpdMultiply2(EpDouble *epd1, EpDouble *epd2); -void EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2); -void EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); -void EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); -void EpdDivide(EpDouble *epd1, double value); -void EpdDivide2(EpDouble *epd1, EpDouble *epd2); -void EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); -void EpdAdd(EpDouble *epd1, double value); -void EpdAdd2(EpDouble *epd1, EpDouble *epd2); -void EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); -void EpdSubtract(EpDouble *epd1, double value); -void EpdSubtract2(EpDouble *epd1, EpDouble *epd2); -void EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); -void EpdPow2(int n, EpDouble *epd); -void EpdPow2Decimal(int n, EpDouble *epd); -void EpdNormalize(EpDouble *epd); -void EpdNormalizeDecimal(EpDouble *epd); -void EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent); -int EpdGetExponent(double value); -int EpdGetExponentDecimal(double value); -void EpdMakeInf(EpDouble *epd, int sign); -void EpdMakeZero(EpDouble *epd, int sign); -void EpdMakeNan(EpDouble *epd); -void EpdCopy(EpDouble *from, EpDouble *to); -int EpdIsInf(EpDouble *epd); -int EpdIsZero(EpDouble *epd); -int EpdIsNan(EpDouble *epd); -int EpdIsNanOrInf(EpDouble *epd); -int IsInfDouble(double value); -int IsNanDouble(double value); -int IsNanOrInfDouble(double value); - -#endif /* _EPD */ diff --git a/src/bdd/epd/module.make b/src/bdd/epd/module.make deleted file mode 100644 index a8084db1..00000000 --- a/src/bdd/epd/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += src/bdd/epd/epd.c diff --git a/src/bdd/mtr/module.make b/src/bdd/mtr/module.make deleted file mode 100644 index d7fa63d9..00000000 --- a/src/bdd/mtr/module.make +++ /dev/null @@ -1,2 +0,0 @@ -SRC += src/bdd/mtr/mtrBasic.c \ - src/bdd/mtr/mtrGroup.c diff --git a/src/bdd/mtr/mtr.h b/src/bdd/mtr/mtr.h deleted file mode 100644 index 201329ae..00000000 --- a/src/bdd/mtr/mtr.h +++ /dev/null @@ -1,173 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [mtr.h] - - PackageName [mtr] - - Synopsis [Multiway-branch tree manipulation] - - Description [This package provides two layers of functions. Functions - of the lower level manipulate multiway-branch trees, implemented - according to the classical scheme whereby each node points to its - first child and its previous and next siblings. These functions are - collected in mtrBasic.c.<p> - Functions of the upper layer deal with group trees, that is the trees - used by group sifting to represent the grouping of variables. These - functions are collected in mtrGroup.c.] - - SeeAlso [The CUDD package documentation; specifically on group - sifting.] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: mtr.h,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $] - -******************************************************************************/ - -#ifndef __MTR -#define __MTR - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef SIZEOF_VOID_P -#define SIZEOF_VOID_P 4 -#endif -#ifndef SIZEOF_INT -#define SIZEOF_INT 4 -#endif - -#undef CONST -#if defined(__STDC__) || defined(__cplusplus) -#define CONST const -#else /* !(__STDC__ || __cplusplus) */ -#define CONST -#endif /* !(__STDC__ || __cplusplus) */ - -/* These are potential duplicates. */ -#ifndef EXTERN -# ifdef __cplusplus -# define EXTERN extern "C" -# else -# define EXTERN extern -# endif -#endif -#ifndef ARGS -# if defined(__STDC__) || defined(__cplusplus) -# define ARGS(protos) protos /* ANSI C */ -# else /* !(__STDC__ || __cplusplus) */ -# define ARGS(protos) () /* K&R C */ -# endif /* !(__STDC__ || __cplusplus) */ -#endif - -#if defined(__GNUC__) -#define MTR_INLINE __inline__ -# if (__GNUC__ >2 || __GNUC_MINOR__ >=7) -# define MTR_UNUSED __attribute__ ((unused)) -# else -# define MTR_UNUSED -# endif -#else -#define MTR_INLINE -#define MTR_UNUSED -#endif - -/* Flag definitions */ -#define MTR_DEFAULT 0x00000000 -#define MTR_TERMINAL 0x00000001 -#define MTR_SOFT 0x00000002 -#define MTR_FIXED 0x00000004 -#define MTR_NEWNODE 0x00000008 - -/* MTR_MAXHIGH is defined in such a way that on 32-bit and 64-bit -** machines one can cast a value to (int) without generating a negative -** number. -*/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define MTR_MAXHIGH (((MtrHalfWord) ~0) >> 1) -#else -#define MTR_MAXHIGH ((MtrHalfWord) ~0) -#endif - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -typedef unsigned int MtrHalfWord; -#else -typedef unsigned short MtrHalfWord; -#endif - -typedef struct MtrNode { - MtrHalfWord flags; - MtrHalfWord low; - MtrHalfWord size; - MtrHalfWord index; - struct MtrNode *parent; - struct MtrNode *child; - struct MtrNode *elder; - struct MtrNode *younger; -} MtrNode; - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/* Flag manipulation macros */ -#define MTR_SET(node, flag) (node->flags |= (flag)) -#define MTR_RESET(node, flag) (node->flags &= ~ (flag)) -#define MTR_TEST(node, flag) (node->flags & (flag)) - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - -EXTERN MtrNode * Mtr_AllocNode ARGS(()); -EXTERN void Mtr_DeallocNode ARGS((MtrNode *node)); -EXTERN MtrNode * Mtr_InitTree ARGS(()); -EXTERN void Mtr_FreeTree ARGS((MtrNode *node)); -EXTERN MtrNode * Mtr_CopyTree ARGS((MtrNode *node, int expansion)); -EXTERN void Mtr_MakeFirstChild ARGS((MtrNode *parent, MtrNode *child)); -EXTERN void Mtr_MakeLastChild ARGS((MtrNode *parent, MtrNode *child)); -EXTERN MtrNode * Mtr_CreateFirstChild ARGS((MtrNode *parent)); -EXTERN MtrNode * Mtr_CreateLastChild ARGS((MtrNode *parent)); -EXTERN void Mtr_MakeNextSibling ARGS((MtrNode *first, MtrNode *second)); -EXTERN void Mtr_PrintTree ARGS((MtrNode *node)); -EXTERN MtrNode * Mtr_InitGroupTree ARGS((int lower, int size)); -EXTERN MtrNode * Mtr_MakeGroup ARGS((MtrNode *root, unsigned int low, unsigned int high, unsigned int flags)); -EXTERN MtrNode * Mtr_DissolveGroup ARGS((MtrNode *group)); -EXTERN MtrNode * Mtr_FindGroup ARGS((MtrNode *root, unsigned int low, unsigned int high)); -EXTERN int Mtr_SwapGroups ARGS((MtrNode *first, MtrNode *second)); -EXTERN void Mtr_PrintGroups ARGS((MtrNode *root, int silent)); -EXTERN MtrNode * Mtr_ReadGroups ARGS((FILE *fp, int nleaves)); - -/**AutomaticEnd***************************************************************/ - -#endif /* __MTR */ diff --git a/src/bdd/mtr/mtrBasic.c b/src/bdd/mtr/mtrBasic.c deleted file mode 100644 index 94105282..00000000 --- a/src/bdd/mtr/mtrBasic.c +++ /dev/null @@ -1,426 +0,0 @@ -/**CFile*********************************************************************** - - FileName [mtrBasic.c] - - PackageName [mtr] - - Synopsis [Basic manipulation of multiway branching trees.] - - Description [External procedures included in this module: - <ul> - <li> Mtr_AllocNode() - <li> Mtr_DeallocNode() - <li> Mtr_InitTree() - <li> Mtr_FreeTree() - <li> Mtr_CopyTree() - <li> Mtr_MakeFirstChild() - <li> Mtr_MakeLastChild() - <li> Mtr_CreateFirstChild() - <li> Mtr_CreateLastChild() - <li> Mtr_MakeNextSibling() - <li> Mtr_PrintTree() - </ul> - ] - - SeeAlso [cudd package] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "mtrInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] MTR_UNUSED = "$Id: mtrBasic.c,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Allocates new tree node.] - - Description [Allocates new tree node. Returns pointer to node.] - - SideEffects [None] - - SeeAlso [Mtr_DeallocNode] - -******************************************************************************/ -MtrNode * -Mtr_AllocNode( - ) -{ - MtrNode *node; - - node = ALLOC(MtrNode,1); - return node; - -} /* Mtr_AllocNode */ - - -/**Function******************************************************************** - - Synopsis [Deallocates tree node.] - - Description [] - - SideEffects [None] - - SeeAlso [Mtr_AllocNode] - -******************************************************************************/ -void -Mtr_DeallocNode( - MtrNode * node /* node to be deallocated */) -{ - FREE(node); - return; - -} /* end of Mtr_DeallocNode */ - - -/**Function******************************************************************** - - Synopsis [Initializes tree with one node.] - - Description [Initializes tree with one node. Returns pointer to node.] - - SideEffects [None] - - SeeAlso [Mtr_FreeTree Mtr_InitGroupTree] - -******************************************************************************/ -MtrNode * -Mtr_InitTree( - ) -{ - MtrNode *node; - - node = Mtr_AllocNode(); - if (node == NULL) return(NULL); - - node->parent = node->child = node->elder = node->younger = NULL; - node->flags = 0; - - return(node); - -} /* end of Mtr_InitTree */ - - -/**Function******************************************************************** - - Synopsis [Disposes of tree rooted at node.] - - Description [] - - SideEffects [None] - - SeeAlso [Mtr_InitTree] - -******************************************************************************/ -void -Mtr_FreeTree( - MtrNode * node) -{ - if (node == NULL) return; - if (! MTR_TEST(node,MTR_TERMINAL)) Mtr_FreeTree(node->child); - Mtr_FreeTree(node->younger); - Mtr_DeallocNode(node); - return; - -} /* end of Mtr_FreeTree */ - - -/**Function******************************************************************** - - Synopsis [Makes a copy of tree.] - - Description [Makes a copy of tree. If parameter expansion is greater - than 1, it will expand the tree by that factor. It is an error for - expansion to be less than 1. Returns a pointer to the copy if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Mtr_InitTree] - -******************************************************************************/ -MtrNode * -Mtr_CopyTree( - MtrNode * node, - int expansion) -{ - MtrNode *copy; - - if (node == NULL) return(NULL); - if (expansion < 1) return(NULL); - copy = Mtr_AllocNode(); - if (copy == NULL) return(NULL); - copy->parent = copy->elder = copy->child = copy->younger = NULL; - if (node->child != NULL) { - copy->child = Mtr_CopyTree(node->child, expansion); - if (copy->child == NULL) { - Mtr_DeallocNode(copy); - return(NULL); - } - } - if (node->younger != NULL) { - copy->younger = Mtr_CopyTree(node->younger, expansion); - if (copy->younger == NULL) { - Mtr_FreeTree(copy); - return(NULL); - } - } - copy->flags = node->flags; - copy->low = node->low * expansion; - copy->size = node->size * expansion; - copy->index = node->index * expansion; - if (copy->younger) copy->younger->elder = copy; - if (copy->child) { - MtrNode *auxnode = copy->child; - while (auxnode != NULL) { - auxnode->parent = copy; - auxnode = auxnode->younger; - } - } - return(copy); - -} /* end of Mtr_CopyTree */ - - -/**Function******************************************************************** - - Synopsis [Makes child the first child of parent.] - - Description [] - - SideEffects [None] - - SeeAlso [Mtr_MakeLastChild Mtr_CreateFirstChild] - -******************************************************************************/ -void -Mtr_MakeFirstChild( - MtrNode * parent, - MtrNode * child) -{ - child->parent = parent; - child->younger = parent->child; - child->elder = NULL; - if (parent->child != NULL) { -#ifdef MTR_DEBUG - assert(parent->child->elder == NULL); -#endif - parent->child->elder = child; - } - parent->child = child; - return; - -} /* end of Mtr_MakeFirstChild */ - - -/**Function******************************************************************** - - Synopsis [Makes child the last child of parent.] - - Description [] - - SideEffects [None] - - SeeAlso [Mtr_MakeFirstChild Mtr_CreateLastChild] - -******************************************************************************/ -void -Mtr_MakeLastChild( - MtrNode * parent, - MtrNode * child) -{ - MtrNode *node; - - child->younger = NULL; - - if (parent->child == NULL) { - parent->child = child; - child->elder = NULL; - } else { - for (node = parent->child; - node->younger != NULL; - node = node->younger); - node->younger = child; - child->elder = node; - } - child->parent = parent; - return; - -} /* end of Mtr_MakeLastChild */ - - -/**Function******************************************************************** - - Synopsis [Creates a new node and makes it the first child of parent.] - - Description [Creates a new node and makes it the first child of - parent. Returns pointer to new child.] - - SideEffects [None] - - SeeAlso [Mtr_MakeFirstChild Mtr_CreateLastChild] - -******************************************************************************/ -MtrNode * -Mtr_CreateFirstChild( - MtrNode * parent) -{ - MtrNode *child; - - child = Mtr_AllocNode(); - if (child == NULL) return(NULL); - - child->child = child->younger = child-> elder = NULL; - child->flags = 0; - Mtr_MakeFirstChild(parent,child); - return(child); - -} /* end of Mtr_CreateFirstChild */ - - -/**Function******************************************************************** - - Synopsis [Creates a new node and makes it the last child of parent.] - - Description [Creates a new node and makes it the last child of parent. - Returns pointer to new child.] - - SideEffects [None] - - SeeAlso [Mtr_MakeLastChild Mtr_CreateFirstChild] - -******************************************************************************/ -MtrNode * -Mtr_CreateLastChild( - MtrNode * parent) -{ - MtrNode *child; - - child = Mtr_AllocNode(); - if (child == NULL) return(NULL); - - child->child = child->younger = child->elder = NULL; - child->flags = 0; - Mtr_MakeLastChild(parent,child); - return(child); - -} /* end of Mtr_CreateLastChild */ - - -/**Function******************************************************************** - - Synopsis [Makes second the next sibling of first.] - - Description [Makes second the next sibling of first. Second becomes a - child of the parent of first.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -Mtr_MakeNextSibling( - MtrNode * first, - MtrNode * second) -{ - second->younger = first->younger; - if (first->younger != NULL) { - first->younger->elder = second; - } - second->parent = first->parent; - first->younger = second; - second->elder = first; - return; - -} /* end of Mtr_MakeNextSibling */ - - -/**Function******************************************************************** - - Synopsis [Prints a tree, one node per line.] - - Description [] - - SideEffects [None] - - SeeAlso [Mtr_PrintGroups] - -******************************************************************************/ -void -Mtr_PrintTree( - MtrNode * node) -{ - if (node == NULL) return; - (void) fprintf(stdout, -#if SIZEOF_VOID_P == 8 - "N=0x%-8lx C=0x%-8lx Y=0x%-8lx E=0x%-8lx P=0x%-8lx F=%x L=%d S=%d\n", - (unsigned long) node, (unsigned long) node->child, - (unsigned long) node->younger, (unsigned long) node->elder, - (unsigned long) node->parent, node->flags, node->low, node->size); -#else - "N=0x%-8x C=0x%-8x Y=0x%-8x E=0x%-8x P=0x%-8x F=%x L=%d S=%d\n", - (unsigned) node, (unsigned) node->child, - (unsigned) node->younger, (unsigned) node->elder, - (unsigned) node->parent, node->flags, node->low, node->size); -#endif - if (!MTR_TEST(node,MTR_TERMINAL)) Mtr_PrintTree(node->child); - Mtr_PrintTree(node->younger); - return; - -} /* end of Mtr_PrintTree */ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/mtr/mtrGroup.c b/src/bdd/mtr/mtrGroup.c deleted file mode 100644 index 363b776b..00000000 --- a/src/bdd/mtr/mtrGroup.c +++ /dev/null @@ -1,690 +0,0 @@ -/**CFile*********************************************************************** - - FileName [mtrGroup.c] - - PackageName [mtr] - - Synopsis [Functions to support group specification for reordering.] - - Description [External procedures included in this module: - <ul> - <li> Mtr_InitGroupTree() - <li> Mtr_MakeGroup() - <li> Mtr_DissolveGroup() - <li> Mtr_FindGroup() - <li> Mtr_SwapGroups() - <li> Mtr_PrintGroups() - <li> Mtr_ReadGroups() - </ul> - Static procedures included in this module: - <ul> - <li> mtrShiftHL - </ul> - ] - - SeeAlso [cudd package] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "mtrInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] MTR_UNUSED = "$Id: mtrGroup.c,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int mtrShiftHL ARGS((MtrNode *node, int shift)); - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Allocate new tree.] - - Description [Allocate new tree with one node, whose low and size - fields are specified by the lower and size parameters. - Returns pointer to tree root.] - - SideEffects [None] - - SeeAlso [Mtr_InitTree Mtr_FreeTree] - -******************************************************************************/ -MtrNode * -Mtr_InitGroupTree( - int lower, - int size) -{ - MtrNode *root; - - root = Mtr_InitTree(); - if (root == NULL) return(NULL); - root->flags = MTR_DEFAULT; - root->low = lower; - root->size = size; - return(root); - -} /* end of Mtr_InitGroupTree */ - - -/**Function******************************************************************** - - Synopsis [Makes a new group with size leaves starting at low.] - - Description [Makes a new group with size leaves starting at low. - If the new group intersects an existing group, it must - either contain it or be contained by it. This procedure relies on - the low and size fields of each node. It also assumes that the - children of each node are sorted in order of increasing low. In - case of a valid request, the flags of the new group are set to the - value passed in `flags.' This can also be used to change the flags - of an existing group. Returns the pointer to the root of the new - group upon successful termination; NULL otherwise. If the group - already exists, the pointer to its root is returned.] - - SideEffects [None] - - SeeAlso [Mtr_DissolveGroup Mtr_ReadGroups Mtr_FindGroup] - -******************************************************************************/ -MtrNode * -Mtr_MakeGroup( - MtrNode * root /* root of the group tree */, - unsigned int low /* lower bound of the group */, - unsigned int size /* upper bound of the group */, - unsigned int flags /* flags for the new group */) -{ - MtrNode *node, - *first, - *last, - *previous, - *newn; - - /* Sanity check. */ - if (size == 0) - return(NULL); - - /* Check whether current group includes new group. This check is - ** necessary at the top-level call. In the subsequent calls it is - ** redundant. */ - if (low < (unsigned int) root->low || - low + size > (unsigned int) (root->low + root->size)) - return(NULL); - - /* Trying to create an existing group has the effect of updating - ** the flags. */ - if (root->size == size && root->low == low) { - root->flags = flags; - return(root); - } - - /* At this point we know that the new group is properly contained - ** in the group of root. We have two possible cases here: - root - ** is a terminal node; - root has children. */ - - /* Root has no children: create a new group. */ - if (root->child == NULL) { - newn = Mtr_AllocNode(); - if (newn == NULL) return(NULL); /* out of memory */ - newn->low = low; - newn->size = size; - newn->flags = flags; - newn->parent = root; - newn->elder = newn->younger = newn->child = NULL; - root->child = newn; - return(newn); - } - - /* Root has children: Find all chidren of root that are included - ** in the new group. If the group of any child entirely contains - ** the new group, call Mtr_MakeGroup recursively. */ - previous = NULL; - first = root->child; /* guaranteed to be non-NULL */ - while (first != NULL && low >= (unsigned int) (first->low + first->size)) { - previous = first; - first = first->younger; - } - if (first == NULL) { - /* We have scanned the entire list and we need to append a new - ** child at the end of it. Previous points to the last child - ** of root. */ - newn = Mtr_AllocNode(); - if (newn == NULL) return(NULL); /* out of memory */ - newn->low = low; - newn->size = size; - newn->flags = flags; - newn->parent = root; - newn->elder = previous; - previous->younger = newn; - newn->younger = newn->child = NULL; - return(newn); - } - /* Here first is non-NULL and low < first->low + first->size. */ - if (low >= (unsigned int) first->low && - low + size <= (unsigned int) (first->low + first->size)) { - /* The new group is contained in the group of first. */ - newn = Mtr_MakeGroup(first, low, size, flags); - return(newn); - } else if (low + size <= first->low) { - /* The new group is entirely contained in the gap between - ** previous and first. */ - newn = Mtr_AllocNode(); - if (newn == NULL) return(NULL); /* out of memory */ - newn->low = low; - newn->size = size; - newn->flags = flags; - newn->child = NULL; - newn->parent = root; - newn->elder = previous; - newn->younger = first; - first->elder = newn; - if (previous != NULL) { - previous->younger = newn; - } else { - root->child = newn; - } - return(newn); - } else if (low < (unsigned int) first->low && - low + size < (unsigned int) (first->low + first->size)) { - /* Trying to cut an existing group: not allowed. */ - return(NULL); - } else if (low > first->low) { - /* The new group neither is contained in the group of first - ** (this was tested above) nor contains it. It is therefore - ** trying to cut an existing group: not allowed. */ - return(NULL); - } - - /* First holds the pointer to the first child contained in the new - ** group. Here low <= first->low and low + size >= first->low + - ** first->size. One of the two inequalities is strict. */ - last = first->younger; - while (last != NULL && - (unsigned int) (last->low + last->size) < low + size) { - last = last->younger; - } - if (last == NULL) { - /* All the chilren of root from first onward become children - ** of the new group. */ - newn = Mtr_AllocNode(); - if (newn == NULL) return(NULL); /* out of memory */ - newn->low = low; - newn->size = size; - newn->flags = flags; - newn->child = first; - newn->parent = root; - newn->elder = previous; - newn->younger = NULL; - first->elder = NULL; - if (previous != NULL) { - previous->younger = newn; - } else { - root->child = newn; - } - last = first; - while (last != NULL) { - last->parent = newn; - last = last->younger; - } - return(newn); - } - - /* Here last != NULL and low + size <= last->low + last->size. */ - if (low + size - 1 >= (unsigned int) last->low && - low + size < (unsigned int) (last->low + last->size)) { - /* Trying to cut an existing group: not allowed. */ - return(NULL); - } - - /* First and last point to the first and last of the children of - ** root that are included in the new group. Allocate a new node - ** and make all children of root between first and last chidren of - ** the new node. Previous points to the child of root immediately - ** preceeding first. If it is NULL, then first is the first child - ** of root. */ - newn = Mtr_AllocNode(); - if (newn == NULL) return(NULL); /* out of memory */ - newn->low = low; - newn->size = size; - newn->flags = flags; - newn->child = first; - newn->parent = root; - if (previous == NULL) { - root->child = newn; - } else { - previous->younger = newn; - } - newn->elder = previous; - newn->younger = last->younger; - if (last->younger != NULL) { - last->younger->elder = newn; - } - last->younger = NULL; - first->elder = NULL; - for (node = first; node != NULL; node = node->younger) { - node->parent = newn; - } - - return(newn); - -} /* end of Mtr_MakeGroup */ - - -/**Function******************************************************************** - - Synopsis [Merges the children of `group' with the children of its - parent.] - - Description [Merges the children of `group' with the children of its - parent. Disposes of the node pointed by group. If group is the - root of the group tree, this procedure leaves the tree unchanged. - Returns the pointer to the parent of `group' upon successful - termination; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Mtr_MakeGroup] - -******************************************************************************/ -MtrNode * -Mtr_DissolveGroup( - MtrNode * group /* group to be dissolved */) -{ - MtrNode *parent; - MtrNode *last; - - parent = group->parent; - - if (parent == NULL) return(NULL); - if (MTR_TEST(group,MTR_TERMINAL) || group->child == NULL) return(NULL); - - /* Make all children of group children of its parent, and make - ** last point to the last child of group. */ - for (last = group->child; last->younger != NULL; last = last->younger) { - last->parent = parent; - } - last->parent = parent; - - last->younger = group->younger; - if (group->younger != NULL) { - group->younger->elder = last; - } - - group->child->elder = group->elder; - if (group == parent->child) { - parent->child = group->child; - } else { - group->elder->younger = group->child; - } - - Mtr_DeallocNode(group); - return(parent); - -} /* end of Mtr_DissolveGroup */ - - -/**Function******************************************************************** - - Synopsis [Finds a group with size leaves starting at low, if it exists.] - - Description [Finds a group with size leaves starting at low, if it - exists. This procedure relies on the low and size fields of each - node. It also assumes that the children of each node are sorted in - order of increasing low. Returns the pointer to the root of the - group upon successful termination; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -MtrNode * -Mtr_FindGroup( - MtrNode * root /* root of the group tree */, - unsigned int low /* lower bound of the group */, - unsigned int size /* upper bound of the group */) -{ - MtrNode *node; - -#ifdef MTR_DEBUG - /* We cannot have a non-empty proper subgroup of a singleton set. */ - assert(!MTR_TEST(root,MTR_TERMINAL)); -#endif - - /* Sanity check. */ - if (size < 1) return(NULL); - - /* Check whether current group includes the group sought. This - ** check is necessary at the top-level call. In the subsequent - ** calls it is redundant. */ - if (low < (unsigned int) root->low || - low + size > (unsigned int) (root->low + root->size)) - return(NULL); - - if (root->size == size && root->low == low) - return(root); - - if (root->child == NULL) - return(NULL); - - /* Find all chidren of root that are included in the new group. If - ** the group of any child entirely contains the new group, call - ** Mtr_MakeGroup recursively. */ - node = root->child; - while (low >= (unsigned int) (node->low + node->size)) { - node = node->younger; - } - if (low + size <= (unsigned int) (node->low + node->size)) { - /* The group is contained in the group of node. */ - node = Mtr_FindGroup(node, low, size); - return(node); - } else { - return(NULL); - } - -} /* end of Mtr_FindGroup */ - - -/**Function******************************************************************** - - Synopsis [Swaps two children of a tree node.] - - Description [Swaps two children of a tree node. Adjusts the high and - low fields of the two nodes and their descendants. The two children - must be adjacent. However, first may be the younger sibling of second. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Mtr_SwapGroups( - MtrNode * first /* first node to be swapped */, - MtrNode * second /* second node to be swapped */) -{ - MtrNode *node; - MtrNode *parent; - int sizeFirst; - int sizeSecond; - - if (second->younger == first) { /* make first first */ - node = first; - first = second; - second = node; - } else if (first->younger != second) { /* non-adjacent */ - return(0); - } - - sizeFirst = first->size; - sizeSecond = second->size; - - /* Swap the two nodes. */ - parent = first->parent; - if (parent == NULL || second->parent != parent) return(0); - if (parent->child == first) { - parent->child = second; - } else { /* first->elder != NULL */ - first->elder->younger = second; - } - if (second->younger != NULL) { - second->younger->elder = first; - } - first->younger = second->younger; - second->elder = first->elder; - first->elder = second; - second->younger = first; - - /* Adjust the high and low fields. */ - if (!mtrShiftHL(first,sizeSecond)) return(0); - if (!mtrShiftHL(second,-sizeFirst)) return(0); - - return(1); - -} /* end of Mtr_SwapGroups */ - - -/**Function******************************************************************** - - Synopsis [Prints the groups as a parenthesized list.] - - Description [Prints the groups as a parenthesized list. After each - group, the group's flag are printed, preceded by a `|'. For each - flag (except MTR_TERMINAL) a character is printed. - <ul> - <li>F: MTR_FIXED - <li>N: MTR_NEWNODE - <li>S: MTR_SOFT - </ul> - The second argument, silent, if different from 0, causes - Mtr_PrintGroups to only check the syntax of the group tree. - ] - - SideEffects [None] - - SeeAlso [Mtr_PrintTree] - -******************************************************************************/ -void -Mtr_PrintGroups( - MtrNode * root /* root of the group tree */, - int silent /* flag to check tree syntax only */) -{ - MtrNode *node; - - assert(root != NULL); - assert(root->younger == NULL || root->younger->elder == root); - assert(root->elder == NULL || root->elder->younger == root); - if (!silent) (void) printf("(%d",root->low); - if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) { - if (!silent) (void) printf(","); - } else { - node = root->child; - while (node != NULL) { - assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size)); - assert(node->parent == root); - Mtr_PrintGroups(node,silent); - node = node->younger; - } - } - if (!silent) { - (void) printf("%d", root->low + root->size - 1); - if (root->flags != MTR_DEFAULT) { - (void) printf("|"); - if (MTR_TEST(root,MTR_FIXED)) (void) printf("F"); - if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N"); - if (MTR_TEST(root,MTR_SOFT)) (void) printf("S"); - } - (void) printf(")"); - if (root->parent == NULL) (void) printf("\n"); - } - assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0); - return; - -} /* end of Mtr_PrintGroups */ - - -/**Function******************************************************************** - - Synopsis [Reads groups from a file and creates a group tree.] - - Description [Reads groups from a file and creates a group tree. - Each group is specified by three fields: - <xmp> - low size flags. - </xmp> - Low and size are (short) integers. Flags is a string composed of the - following characters (with associated translation): - <ul> - <li>D: MTR_DEFAULT - <li>F: MTR_FIXED - <li>N: MTR_NEWNODE - <li>S: MTR_SOFT - <li>T: MTR_TERMINAL - </ul> - Normally, the only flags that are needed are D and F. Groups and - fields are separated by white space (spaces, tabs, and newlines). - Returns a pointer to the group tree if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Mtr_InitGroupTree Mtr_MakeGroup] - -******************************************************************************/ -MtrNode * -Mtr_ReadGroups( - FILE * fp /* file pointer */, - int nleaves /* number of leaves of the new tree */) -{ - int low; - int size; - int err; - unsigned int flags; - MtrNode *root; - MtrNode *node; - char attrib[8*sizeof(unsigned int)+1]; - char *c; - - root = Mtr_InitGroupTree(0,nleaves); - if (root == NULL) return NULL; - - while (! feof(fp)) { - /* Read a triple and check for consistency. */ - err = fscanf(fp, "%d %d %s", &low, &size, attrib); - if (err == EOF) { - break; - } else if (err != 3) { - return(NULL); - } else if (low < 0 || low+size > nleaves || size < 1) { - return(NULL); - } else if (strlen(attrib) > 8 * sizeof(MtrHalfWord)) { - /* Not enough bits in the flags word to store these many - ** attributes. */ - return(NULL); - } - - /* Parse the flag string. Currently all flags are permitted, - ** to make debugging easier. Normally, specifying NEWNODE - ** wouldn't be allowed. */ - flags = MTR_DEFAULT; - for (c=attrib; *c != 0; c++) { - switch (*c) { - case 'D': - break; - case 'F': - flags |= MTR_FIXED; - break; - case 'N': - flags |= MTR_NEWNODE; - break; - case 'S': - flags |= MTR_SOFT; - break; - case 'T': - flags |= MTR_TERMINAL; - break; - default: - return NULL; - } - } - node = Mtr_MakeGroup(root, (MtrHalfWord) low, (MtrHalfWord) size, - flags); - if (node == NULL) return(NULL); - } - - return(root); - -} /* end of Mtr_ReadGroups */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Adjusts the low fields of a node and its descendants.] - - Description [Adjusts the low fields of a node and its - descendants. Adds shift to low of each node. Checks that no - out-of-bounds values result. Returns 1 in case of success; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -mtrShiftHL( - MtrNode * node /* group tree node */, - int shift /* amount by which low should be changed */) -{ - MtrNode *auxnode; - int low; - - low = (int) node->low; - - - low += shift; - - if (low < 0 || low + (int) (node->size - 1) > (int) MTR_MAXHIGH) return(0); - - node->low = (MtrHalfWord) low; - - if (!MTR_TEST(node,MTR_TERMINAL) && node->child != NULL) { - auxnode = node->child; - do { - if (!mtrShiftHL(auxnode,shift)) return(0); - auxnode = auxnode->younger; - } while (auxnode != NULL); - } - - return(1); - -} /* end of mtrShiftHL */ - diff --git a/src/bdd/mtr/mtrInt.h b/src/bdd/mtr/mtrInt.h deleted file mode 100644 index a8d5aa6c..00000000 --- a/src/bdd/mtr/mtrInt.h +++ /dev/null @@ -1,65 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [mtrInt.h] - - PackageName [mtr] - - Synopsis [Internal data structures of the mtr package] - - Description [In this package all definitions are external.] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: mtrInt.h,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $] - -******************************************************************************/ - -#ifndef _MTRINT -#define _MTRINT - -#include "mtr.h" - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - -#endif /* _MTRINT */ diff --git a/src/bdd/parse/module.make b/src/bdd/parse/module.make deleted file mode 100644 index 4f590f01..00000000 --- a/src/bdd/parse/module.make +++ /dev/null @@ -1,3 +0,0 @@ -SRC += src/bdd/parse/parseCore.c \ - src/bdd/parse/parseEqn.c \ - src/bdd/parse/parseStack.c diff --git a/src/bdd/parse/parse.h b/src/bdd/parse/parse.h deleted file mode 100644 index 4923fbdd..00000000 --- a/src/bdd/parse/parse.h +++ /dev/null @@ -1,54 +0,0 @@ -/**CFile**************************************************************** - - FileName [parse.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Parsing symbolic Boolean formulas into BDDs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: parse.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __PARSE_H__ -#define __PARSE_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== parseCore.c =============================================================*/ -extern DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormula, int nVars, int nRanks, - char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/parse/parseCore.c b/src/bdd/parse/parseCore.c deleted file mode 100644 index 21a37070..00000000 --- a/src/bdd/parse/parseCore.c +++ /dev/null @@ -1,504 +0,0 @@ -/**CFile**************************************************************** - - FileNameIn [parseCore.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Boolean formula parser.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: parseCore.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -/* - Some aspects of Boolean Formula Parser: - - 1) The names in the boolean formulas can be any strings of symbols - that start with char or underscore and contain chars, digits - and underscores: For example: 1) a&b <+> c'&d => a + b; - 2) a1 b2 c3' dummy' + (a2+b2')c3 dummy - 2) Constant values 0 and 1 can be used just like normal variables - 3) Any boolean operator (listed below) and parantheses can be used - any number of times provided there are equal number of opening - and closing parantheses. - 4) By default, absence of an operator between vars and before and - after parantheses is taken for AND. - 5) Both complementation prefix and complementation suffix can be - used at the same time (but who needs this?) - 6) Spaces (tabs, end-of-lines) may be inserted anywhere, - except between characters of the operations: <=>, =>, <=, <+> - 7) The stack size is defined by macro STACKSIZE and is used by the - stack constructor. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#include "parseInt.h" - -// the list of operation symbols to be used in expressions -#define PARSE_SYM_OPEN '(' // opening paranthesis -#define PARSE_SYM_CLOSE ')' // closing paranthesis -#define PARSE_SYM_LOWER '[' // shifts one rank down -#define PARSE_SYM_RAISE ']' // shifts one rank up -#define PARSE_SYM_CONST0 '0' // constant 0 -#define PARSE_SYM_CONST1 '1' // constant 1 -#define PARSE_SYM_NEGBEF1 '!' // negation before the variable -#define PARSE_SYM_NEGBEF2 '~' // negation before the variable -#define PARSE_SYM_NEGAFT '\'' // negation after the variable -#define PARSE_SYM_AND1 '&' // logic AND -#define PARSE_SYM_AND2 '*' // logic AND -#define PARSE_SYM_XOR1 '<' // logic EXOR (the 1st symbol) -#define PARSE_SYM_XOR2 '+' // logic EXOR (the 2nd symbol) -#define PARSE_SYM_XOR3 '>' // logic EXOR (the 3rd symbol) -#define PARSE_SYM_OR '+' // logic OR -#define PARSE_SYM_EQU1 '<' // equvalence (the 1st symbol) -#define PARSE_SYM_EQU2 '=' // equvalence (the 2nd symbol) -#define PARSE_SYM_EQU3 '>' // equvalence (the 3rd symbol) -#define PARSE_SYM_FLR1 '=' // implication (the 1st symbol) -#define PARSE_SYM_FLR2 '>' // implication (the 2nd symbol) -#define PARSE_SYM_FLL1 '<' // backward imp (the 1st symbol) -#define PARSE_SYM_FLL2 '=' // backward imp (the 2nd symbol) -// PARSE_SYM_FLR1 and PARSE_SYM_FLR2 should be the same as PARSE_SYM_EQU2 and PARSE_SYM_EQU3! - -// the list of opcodes (also specifying operation precedence) -#define PARSE_OPER_NEG 10 // negation -#define PARSE_OPER_AND 9 // logic AND -#define PARSE_OPER_XOR 8 // logic EXOR (a'b | ab') -#define PARSE_OPER_OR 7 // logic OR -#define PARSE_OPER_EQU 6 // equvalence (a'b'| ab ) -#define PARSE_OPER_FLR 5 // implication ( a' | b ) -#define PARSE_OPER_FLL 4 // backward imp ( 'b | a ) -#define PARSE_OPER_MARK 1 // OpStack token standing for an opening paranthesis - -// these are values of the internal Flag -#define PARSE_FLAG_START 1 // after the opening parenthesis -#define PARSE_FLAG_VAR 2 // after operation is received -#define PARSE_FLAG_OPER 3 // after operation symbol is received -#define PARSE_FLAG_ERROR 4 // when error is detected - -#define STACKSIZE 1000 - -static DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the BDD corresponding to the formula in language L.] - - Description [Takes the stream to output messages, the formula, the number - variables and the rank in the formula. The array of variable names is also - given. The BDD manager and the elementary 0-rank variable are the last two - arguments. The manager should have at least as many variables as - nVars * (nRanks + 1). The 0-rank variables should have numbers larger - than the variables of other ranks.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormulaInit, int nVars, int nRanks, - char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ) -{ - char * pFormula; - Parse_StackFn_t * pStackFn; - Parse_StackOp_t * pStackOp; - DdNode * bFunc, * bTemp; - char * pTemp; - int nParans, fFound, Flag; - int Oper, Oper1, Oper2; - int i, v, fLower; - - // make sure that the number of vars and ranks is correct - if ( nVars * (nRanks + 1) > dd->size ) - { - printf( "Parse_FormulaParser(): The BDD manager does not have enough variables.\n" ); - return NULL; - } - - // make sure that the number of opening and closing parantheses is the same - nParans = 0; - for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) - if ( *pTemp == '(' ) - nParans++; - else if ( *pTemp == ')' ) - nParans--; - if ( nParans != 0 ) - { - fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing parantheses ().\n" ); - return NULL; - } - - nParans = 0; - for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) - if ( *pTemp == '[' ) - nParans++; - else if ( *pTemp == ']' ) - nParans--; - if ( nParans != 0 ) - { - fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing brackets [].\n" ); - return NULL; - } - - // copy the formula - pFormula = ALLOC( char, strlen(pFormulaInit) + 3 ); - sprintf( pFormula, "(%s)", pFormulaInit ); - - // start the stacks - pStackFn = Parse_StackFnStart( STACKSIZE ); - pStackOp = Parse_StackOpStart( STACKSIZE ); - - Flag = PARSE_FLAG_START; - fLower = 0; - for ( pTemp = pFormula; *pTemp; pTemp++ ) - { - switch ( *pTemp ) - { - // skip all spaces, tabs, and end-of-lines - case ' ': - case '\t': - case '\r': - case '\n': - continue; - - // treat Constant 0 as a variable - case PARSE_SYM_CONST0: - Parse_StackFnPush( pStackFn, b0 ); Cudd_Ref( b0 ); - if ( Flag == PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 0.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_VAR; - break; - - // the same for Constant 1 - case PARSE_SYM_CONST1: - Parse_StackFnPush( pStackFn, b1 ); Cudd_Ref( b1 ); - if ( Flag == PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 1.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_VAR; - break; - - case PARSE_SYM_NEGBEF1: - case PARSE_SYM_NEGBEF2: - if ( Flag == PARSE_FLAG_VAR ) - {// if NEGBEF follows a variable, AND is assumed - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - Flag = PARSE_FLAG_OPER; - } - Parse_StackOpPush( pStackOp, PARSE_OPER_NEG ); - break; - - case PARSE_SYM_NEGAFT: - if ( Flag != PARSE_FLAG_VAR ) - {// if there is no variable before NEGAFT, it is an error - fprintf( pOutput, "Parse_FormulaParser(): No variable is specified before the negation suffix.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - else // if ( Flag == PARSE_FLAG_VAR ) - Parse_StackFnPush( pStackFn, Cudd_Not( Parse_StackFnPop(pStackFn) ) ); - break; - - case PARSE_SYM_AND1: - case PARSE_SYM_AND2: - case PARSE_SYM_OR: - if ( Flag != PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - if ( *pTemp == PARSE_SYM_AND1 || *pTemp == PARSE_SYM_AND2 ) - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - else //if ( Str[Pos] == PARSE_SYM_OR ) - Parse_StackOpPush( pStackOp, PARSE_OPER_OR ); - Flag = PARSE_FLAG_OPER; - break; - - case PARSE_SYM_EQU1: - if ( Flag != PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Equivalence or Implication\n" ); - Flag = PARSE_FLAG_ERROR; break; - } - if ( pTemp[1] == PARSE_SYM_EQU2 ) - { // check what is the next symbol in the string - pTemp++; - if ( pTemp[1] == PARSE_SYM_EQU3 ) - { - pTemp++; - Parse_StackOpPush( pStackOp, PARSE_OPER_EQU ); - } - else - { - Parse_StackOpPush( pStackOp, PARSE_OPER_FLL ); - } - } - else if ( pTemp[1] == PARSE_SYM_XOR2 ) - { - pTemp++; - if ( pTemp[1] == PARSE_SYM_XOR3 ) - { - pTemp++; - Parse_StackOpPush( pStackOp, PARSE_OPER_XOR ); - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c%c\"\n", PARSE_SYM_EQU1, PARSE_SYM_XOR2 ); - Flag = PARSE_FLAG_ERROR; - break; - } - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU1 ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_OPER; - break; - - case PARSE_SYM_EQU2: - if ( Flag != PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Reverse Implication\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - if ( pTemp[1] == PARSE_SYM_EQU3 ) - { - pTemp++; - Parse_StackOpPush( pStackOp, PARSE_OPER_FLR ); - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU2 ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_OPER; - break; - - case PARSE_SYM_LOWER: - case PARSE_SYM_OPEN: - if ( Flag == PARSE_FLAG_VAR ) - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - Parse_StackOpPush( pStackOp, PARSE_OPER_MARK ); - // after an opening bracket, it feels like starting over again - Flag = PARSE_FLAG_START; - break; - - case PARSE_SYM_RAISE: - fLower = 1; - case PARSE_SYM_CLOSE: - if ( !Parse_StackOpIsEmpty( pStackOp ) ) - { - while ( 1 ) - { - if ( Parse_StackOpIsEmpty( pStackOp ) ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no opening paranthesis\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper == PARSE_OPER_MARK ) - break; - - // perform the given operation - if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); - free( pFormula ); - return NULL; - } - } - - if ( fLower ) - { - bFunc = Parse_StackFnPop( pStackFn ); - bFunc = Extra_bddMove( dd, bTemp = bFunc, -nVars ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - Parse_StackFnPush( pStackFn, bFunc ); - } - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): There is no opening paranthesis\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - if ( Flag != PARSE_FLAG_ERROR ) - Flag = PARSE_FLAG_VAR; - fLower = 0; - break; - - - default: - // scan the next name - fFound = 0; - for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n'; i++ ) - { - for ( v = 0; v < nVars; v++ ) - if ( strncmp( pTemp, ppVarNames[v], i+1 ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i+1) ) - { - pTemp += i; - fFound = 1; - break; - } - if ( fFound ) - break; - } - if ( !fFound ) - { - fprintf( pOutput, "Parse_FormulaParser(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); - Flag = PARSE_FLAG_ERROR; - break; - } - - // assume operation AND, if vars follow one another - if ( Flag == PARSE_FLAG_VAR ) - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - Parse_StackFnPush( pStackFn, pbVars[v] ); Cudd_Ref( pbVars[v] ); - Flag = PARSE_FLAG_VAR; - break; - } - - if ( Flag == PARSE_FLAG_ERROR ) - break; // error exit - else if ( Flag == PARSE_FLAG_START ) - continue; // go on parsing - else if ( Flag == PARSE_FLAG_VAR ) - while ( 1 ) - { // check if there are negations in the OpStack - if ( Parse_StackOpIsEmpty(pStackOp) ) - break; - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper != PARSE_OPER_NEG ) - { - Parse_StackOpPush( pStackOp, Oper ); - break; - } - else - { - Parse_StackFnPush( pStackFn, Cudd_Not(Parse_StackFnPop(pStackFn)) ); - } - } - else // if ( Flag == PARSE_FLAG_OPER ) - while ( 1 ) - { // execute all the operations in the OpStack - // with precedence higher or equal than the last one - Oper1 = Parse_StackOpPop( pStackOp ); // the last operation - if ( Parse_StackOpIsEmpty(pStackOp) ) - { // if it is the only operation, push it back - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one - if ( Oper2 >= Oper1 ) - { // if Oper2 precedence is higher or equal, execute it -// Parse_StackPush( pStackFn, Operation( FunStack.Pop(), FunStack.Pop(), Oper2 ) ); - if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper2 ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); - free( pFormula ); - return NULL; - } - Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back - } - else - { // if Oper2 precedence is lower, push them back and done - Parse_StackOpPush( pStackOp, Oper2 ); - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - } - } - - if ( Flag != PARSE_FLAG_ERROR ) - { - if ( !Parse_StackFnIsEmpty(pStackFn) ) - { - bFunc = Parse_StackFnPop(pStackFn); - if ( Parse_StackFnIsEmpty(pStackFn) ) - if ( Parse_StackOpIsEmpty(pStackOp) ) - { - Parse_StackFnFree(pStackFn); - Parse_StackOpFree(pStackOp); - Cudd_Deref( bFunc ); - free( pFormula ); - return bFunc; - } - else - fprintf( pOutput, "Parse_FormulaParser(): Something is left in the operation stack\n" ); - else - fprintf( pOutput, "Parse_FormulaParser(): Something is left in the function stack\n" ); - } - else - fprintf( pOutput, "Parse_FormulaParser(): The input string is empty\n" ); - } - free( pFormula ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs the operation on the top entries in the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ) -{ - DdNode * bArg1, * bArg2, * bFunc; - // perform the given operation - bArg2 = Parse_StackFnPop( pStackFn ); - bArg1 = Parse_StackFnPop( pStackFn ); - if ( Oper == PARSE_OPER_AND ) - bFunc = Cudd_bddAnd( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_XOR ) - bFunc = Cudd_bddXor( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_OR ) - bFunc = Cudd_bddOr( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_EQU ) - bFunc = Cudd_bddXnor( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_FLR ) - bFunc = Cudd_bddOr( dd, Cudd_Not(bArg1), bArg2 ); - else if ( Oper == PARSE_OPER_FLL ) - bFunc = Cudd_bddOr( dd, Cudd_Not(bArg2), bArg1 ); - else - return NULL; - Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bArg1 ); - Cudd_RecursiveDeref( dd, bArg2 ); - Parse_StackFnPush( pStackFn, bFunc ); - return bFunc; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/parse/parseEqn.c b/src/bdd/parse/parseEqn.c deleted file mode 100644 index 02d83966..00000000 --- a/src/bdd/parse/parseEqn.c +++ /dev/null @@ -1,349 +0,0 @@ -/**CFile**************************************************************** - - FileNameIn [parseEqn.c] - - PackageName [ABC: Logic synthesis and verification system.] - - Synopsis [Boolean formula parser.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - December 18, 2006.] - - Revision [$Id: parseEqn.c,v 1.0 2006/12/18 00:00:00 alanmi Exp $] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#include "parseInt.h" -#include "vec.h" -#include "hop.h" - -// the list of operation symbols to be used in expressions -#define PARSE_EQN_SYM_OPEN '(' // opening paranthesis -#define PARSE_EQN_SYM_CLOSE ')' // closing paranthesis -#define PARSE_EQN_SYM_CONST0 '0' // constant 0 -#define PARSE_EQN_SYM_CONST1 '1' // constant 1 -#define PARSE_EQN_SYM_NEG '!' // negation before the variable -#define PARSE_EQN_SYM_AND '*' // logic AND -#define PARSE_EQN_SYM_OR '+' // logic OR - -// the list of opcodes (also specifying operation precedence) -#define PARSE_EQN_OPER_NEG 10 // negation -#define PARSE_EQN_OPER_AND 9 // logic AND -#define PARSE_EQN_OPER_OR 7 // logic OR -#define PARSE_EQN_OPER_MARK 1 // OpStack token standing for an opening paranthesis - -// these are values of the internal Flag -#define PARSE_EQN_FLAG_START 1 // after the opening parenthesis -#define PARSE_EQN_FLAG_VAR 2 // after operation is received -#define PARSE_EQN_FLAG_OPER 3 // after operation symbol is received -#define PARSE_EQN_FLAG_ERROR 4 // when error is detected - -#define PARSE_EQN_STACKSIZE 1000 - -static Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the AIG corresponding to the equation.] - - Description [Takes the stream to output messages, the formula, the vector - of variable names and the AIG manager.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ) -{ - char * pFormula; - Parse_StackFn_t * pStackFn; - Parse_StackOp_t * pStackOp; - Hop_Obj_t * gFunc; - char * pTemp, * pName; - int nParans, fFound, Flag; - int Oper, Oper1, Oper2; - int i, v; - - // make sure that the number of opening and closing parantheses is the same - nParans = 0; - for ( pTemp = pFormInit; *pTemp; pTemp++ ) - if ( *pTemp == '(' ) - nParans++; - else if ( *pTemp == ')' ) - nParans--; - if ( nParans != 0 ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): Different number of opening and closing parantheses ().\n" ); - return NULL; - } - - // copy the formula - pFormula = ALLOC( char, strlen(pFormInit) + 3 ); - sprintf( pFormula, "(%s)", pFormInit ); - - // start the stacks - pStackFn = Parse_StackFnStart( PARSE_EQN_STACKSIZE ); - pStackOp = Parse_StackOpStart( PARSE_EQN_STACKSIZE ); - - Flag = PARSE_EQN_FLAG_START; - for ( pTemp = pFormula; *pTemp; pTemp++ ) - { - switch ( *pTemp ) - { - // skip all spaces, tabs, and end-of-lines - case ' ': - case '\t': - case '\r': - case '\n': - continue; - case PARSE_EQN_SYM_CONST0: - Parse_StackFnPush( pStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( b0 ); - if ( Flag == PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 0.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Flag = PARSE_EQN_FLAG_VAR; - break; - case PARSE_EQN_SYM_CONST1: - Parse_StackFnPush( pStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( b1 ); - if ( Flag == PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 1.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Flag = PARSE_EQN_FLAG_VAR; - break; - case PARSE_EQN_SYM_NEG: - if ( Flag == PARSE_EQN_FLAG_VAR ) - {// if NEGBEF follows a variable, AND is assumed - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); - Flag = PARSE_EQN_FLAG_OPER; - } - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_NEG ); - break; - case PARSE_EQN_SYM_AND: - case PARSE_EQN_SYM_OR: - if ( Flag != PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): There is no variable before AND, EXOR, or OR.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - if ( *pTemp == PARSE_EQN_SYM_AND ) - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); - else //if ( *pTemp == PARSE_EQN_SYM_OR ) - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_OR ); - Flag = PARSE_EQN_FLAG_OPER; - break; - case PARSE_EQN_SYM_OPEN: - if ( Flag == PARSE_EQN_FLAG_VAR ) - { -// Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); - fprintf( pOutput, "Parse_FormulaParserEqn(): An opening paranthesis follows a var without operation sign.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_MARK ); - // after an opening bracket, it feels like starting over again - Flag = PARSE_EQN_FLAG_START; - break; - case PARSE_EQN_SYM_CLOSE: - if ( !Parse_StackOpIsEmpty( pStackOp ) ) - { - while ( 1 ) - { - if ( Parse_StackOpIsEmpty( pStackOp ) ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening paranthesis\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper == PARSE_EQN_OPER_MARK ) - break; - - // perform the given operation - if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); - free( pFormula ); - return NULL; - } - } - } - else - { - fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening paranthesis\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - if ( Flag != PARSE_EQN_FLAG_ERROR ) - Flag = PARSE_EQN_FLAG_VAR; - break; - - - default: - // scan the next name - for ( i = 0; pTemp[i] && - pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && - pTemp[i] != PARSE_EQN_SYM_AND && pTemp[i] != PARSE_EQN_SYM_OR && pTemp[i] != PARSE_EQN_SYM_CLOSE; i++ ) - { - if ( pTemp[i] == PARSE_EQN_SYM_NEG || pTemp[i] == PARSE_EQN_SYM_OPEN ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): The negation sign or an opening paranthesis inside the variable name.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - } - // variable name is found - fFound = 0; - Vec_PtrForEachEntry( vVarNames, pName, v ) - if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i ) - { - pTemp += i-1; - fFound = 1; - break; - } - if ( !fFound ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - if ( Flag == PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Parse_StackFnPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] ); - Flag = PARSE_EQN_FLAG_VAR; - break; - } - - if ( Flag == PARSE_EQN_FLAG_ERROR ) - break; // error exit - else if ( Flag == PARSE_EQN_FLAG_START ) - continue; // go on parsing - else if ( Flag == PARSE_EQN_FLAG_VAR ) - while ( 1 ) - { // check if there are negations in the OpStack - if ( Parse_StackOpIsEmpty(pStackOp) ) - break; - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper != PARSE_EQN_OPER_NEG ) - { - Parse_StackOpPush( pStackOp, Oper ); - break; - } - else - { - Parse_StackFnPush( pStackFn, Hop_Not(Parse_StackFnPop(pStackFn)) ); - } - } - else // if ( Flag == PARSE_EQN_FLAG_OPER ) - while ( 1 ) - { // execute all the operations in the OpStack - // with precedence higher or equal than the last one - Oper1 = Parse_StackOpPop( pStackOp ); // the last operation - if ( Parse_StackOpIsEmpty(pStackOp) ) - { // if it is the only operation, push it back - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one - if ( Oper2 >= Oper1 ) - { // if Oper2 precedence is higher or equal, execute it - if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper2 ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); - free( pFormula ); - return NULL; - } - Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back - } - else - { // if Oper2 precedence is lower, push them back and done - Parse_StackOpPush( pStackOp, Oper2 ); - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - } - } - - if ( Flag != PARSE_EQN_FLAG_ERROR ) - { - if ( !Parse_StackFnIsEmpty(pStackFn) ) - { - gFunc = Parse_StackFnPop(pStackFn); - if ( Parse_StackFnIsEmpty(pStackFn) ) - if ( Parse_StackOpIsEmpty(pStackOp) ) - { - Parse_StackFnFree(pStackFn); - Parse_StackOpFree(pStackOp); -// Cudd_Deref( gFunc ); - free( pFormula ); - return gFunc; - } - else - fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the operation stack\n" ); - else - fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the function stack\n" ); - } - else - fprintf( pOutput, "Parse_FormulaParserEqn(): The input string is empty\n" ); - } - free( pFormula ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs the operation on the top entries in the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ) -{ - Hop_Obj_t * gArg1, * gArg2, * gFunc; - // perform the given operation - gArg2 = Parse_StackFnPop( pStackFn ); - gArg1 = Parse_StackFnPop( pStackFn ); - if ( Oper == PARSE_EQN_OPER_AND ) - gFunc = Hop_And( pMan, gArg1, gArg2 ); - else if ( Oper == PARSE_EQN_OPER_OR ) - gFunc = Hop_Or( pMan, gArg1, gArg2 ); - else - return NULL; -// Cudd_Ref( gFunc ); -// Cudd_RecursiveDeref( dd, gArg1 ); -// Cudd_RecursiveDeref( dd, gArg2 ); - Parse_StackFnPush( pStackFn, gFunc ); - return gFunc; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/parse/parseInt.h b/src/bdd/parse/parseInt.h deleted file mode 100644 index 17f48375..00000000 --- a/src/bdd/parse/parseInt.h +++ /dev/null @@ -1,74 +0,0 @@ -/**CFile**************************************************************** - - FileName [parseInt.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Parsing symbolic Boolean formulas into BDDs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: parseInt.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __PARSE_INT_H__ -#define __PARSE_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - - -#include <stdio.h> -#include "cuddInt.h" -#include "extra.h" -#include "parse.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef int bool; - -typedef struct ParseStackFnStruct Parse_StackFn_t; // the function stack -typedef struct ParseStackOpStruct Parse_StackOp_t; // the operation stack - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== parseStack.c =============================================================*/ -extern Parse_StackFn_t * Parse_StackFnStart ( int nDepth ); -extern bool Parse_StackFnIsEmpty( Parse_StackFn_t * p ); -extern void Parse_StackFnPush ( Parse_StackFn_t * p, void * bFunc ); -extern void * Parse_StackFnPop ( Parse_StackFn_t * p ); -extern void Parse_StackFnFree ( Parse_StackFn_t * p ); - -extern Parse_StackOp_t * Parse_StackOpStart ( int nDepth ); -extern bool Parse_StackOpIsEmpty( Parse_StackOp_t * p ); -extern void Parse_StackOpPush ( Parse_StackOp_t * p, int Oper ); -extern int Parse_StackOpPop ( Parse_StackOp_t * p ); -extern void Parse_StackOpFree ( Parse_StackOp_t * p ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/parse/parseStack.c b/src/bdd/parse/parseStack.c deleted file mode 100644 index cd7cd7e3..00000000 --- a/src/bdd/parse/parseStack.c +++ /dev/null @@ -1,243 +0,0 @@ -/**CFile**************************************************************** - - FileName [parseStack.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Stacks used by the formula parser.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 18, 2003.] - - Revision [$Id: parseStack.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "parseInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct ParseStackFnStruct -{ - void ** pData; // the array of elements - int Top; // the index - int Size; // the stack size -}; - -struct ParseStackOpStruct -{ - int * pData; // the array of elements - int Top; // the index - int Size; // the stack size -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Parse_StackFn_t * Parse_StackFnStart( int nDepth ) -{ - Parse_StackFn_t * p; - p = ALLOC( Parse_StackFn_t, 1 ); - memset( p, 0, sizeof(Parse_StackFn_t) ); - p->pData = ALLOC( void *, nDepth ); - p->Size = nDepth; - return p; -} - -/**Function************************************************************* - - Synopsis [Checks whether the stack is empty.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Parse_StackFnIsEmpty( Parse_StackFn_t * p ) -{ - return (bool)(p->Top == 0); -} - -/**Function************************************************************* - - Synopsis [Pushes an entry into the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackFnPush( Parse_StackFn_t * p, void * bFunc ) -{ - if ( p->Top >= p->Size ) - { - printf( "Parse_StackFnPush(): Stack size is too small!\n" ); - return; - } - p->pData[ p->Top++ ] = bFunc; -} - -/**Function************************************************************* - - Synopsis [Pops an entry out of the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Parse_StackFnPop( Parse_StackFn_t * p ) -{ - if ( p->Top == 0 ) - { - printf( "Parse_StackFnPush(): Trying to extract data from the empty stack!\n" ); - return NULL; - } - return p->pData[ --p->Top ]; -} - -/**Function************************************************************* - - Synopsis [Deletes the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackFnFree( Parse_StackFn_t * p ) -{ - FREE( p->pData ); - FREE( p ); -} - - - - -/**Function************************************************************* - - Synopsis [Starts the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Parse_StackOp_t * Parse_StackOpStart( int nDepth ) -{ - Parse_StackOp_t * p; - p = ALLOC( Parse_StackOp_t, 1 ); - memset( p, 0, sizeof(Parse_StackOp_t) ); - p->pData = ALLOC( int, nDepth ); - p->Size = nDepth; - return p; -} - -/**Function************************************************************* - - Synopsis [Checks whether the stack is empty.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Parse_StackOpIsEmpty( Parse_StackOp_t * p ) -{ - return (bool)(p->Top == 0); -} - -/**Function************************************************************* - - Synopsis [Pushes an entry into the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackOpPush( Parse_StackOp_t * p, int Oper ) -{ - if ( p->Top >= p->Size ) - { - printf( "Parse_StackOpPush(): Stack size is too small!\n" ); - return; - } - p->pData[ p->Top++ ] = Oper; -} - -/**Function************************************************************* - - Synopsis [Pops an entry out of the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Parse_StackOpPop( Parse_StackOp_t * p ) -{ - if ( p->Top == 0 ) - { - printf( "Parse_StackOpPush(): Trying to extract data from the empty stack!\n" ); - return -1; - } - return p->pData[ --p->Top ]; -} - -/**Function************************************************************* - - Synopsis [Deletes the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackOpFree( Parse_StackOp_t * p ) -{ - FREE( p->pData ); - FREE( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/bdd/reo/module.make b/src/bdd/reo/module.make deleted file mode 100644 index 7eb41e0e..00000000 --- a/src/bdd/reo/module.make +++ /dev/null @@ -1,7 +0,0 @@ -SRC += src/bdd/reo/reoApi.c \ - src/bdd/reo/reoCore.c \ - src/bdd/reo/reoProfile.c \ - src/bdd/reo/reoSift.c \ - src/bdd/reo/reoSwap.c \ - src/bdd/reo/reoTransfer.c \ - src/bdd/reo/reoUnits.c diff --git a/src/bdd/reo/reo.h b/src/bdd/reo/reo.h deleted file mode 100644 index 1a31242a..00000000 --- a/src/bdd/reo/reo.h +++ /dev/null @@ -1,232 +0,0 @@ -/**CFile**************************************************************** - - FileName [reo.h] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [External and internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reo.h,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __REO_H__ -#define __REO_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdio.h> -#include <stdlib.h> -#include "extra.h" - -//#pragma warning( disable : 4514 ) - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// reordering parameters -#define REO_REORDER_LIMIT 1.15 // determines the quality/runtime trade-off -#define REO_QUAL_PAR 3 // the quality [1 = simple lower bound, 2 = strict, larger = heuristic] -// internal parameters -#define REO_CONST_LEVEL 30000 // the number of the constant level -#define REO_TOPREF_UNDEF 30000 // the undefined top reference -#define REO_CHUNK_SIZE 5000 // the number of units allocated at one time -#define REO_COST_EPSILON 0.0000001 // difference in cost large enough so that it counted as an error -#define REO_HIGH_VALUE 10000000 // a large value used to initialize some variables -// interface parameters -#define REO_ENABLE 1 // the value of the enable flag -#define REO_DISABLE 0 // the value of the disable flag - -// the types of minimization currently supported -typedef enum { - REO_MINIMIZE_NODES, - REO_MINIMIZE_WIDTH, // may not work for BDDs with complemented edges - REO_MINIMIZE_APL -} reo_min_type; - -//////////////////////////////////////////////////////////////////////// -/// DATA STRUCTURES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct _reo_unit reo_unit; // the unit representing one DD node during reordering -typedef struct _reo_plane reo_plane; // the set of nodes on one level -typedef struct _reo_hash reo_hash; // the entry in the hash table -typedef struct _reo_man reo_man; // the reordering manager -typedef struct _reo_test reo_test; // - -struct _reo_unit -{ - short lev; // the level of this node at the beginning - short TopRef; // the top level from which this node is refed (used to update BDD width) - short TopRefNew; // the new top level from which this node is refed (used to update BDD width) - short n; // the number of incoming edges (similar to ref count in the BDD) - int Sign; // the signature - - reo_unit * pE; // the pointer to the "else" branch - reo_unit * pT; // the pointer to the "then" branch - reo_unit * Next; // the link to the next one in the list - double Weight; // the probability of traversing this node -}; - -struct _reo_plane -{ - int fSifted; // to mark the sifted variables - int statsNodes; // the number of nodes in the current level - int statsWidth; // the width on the current level - double statsApl; // the sum of node probabilities on this level - double statsCost; // the current cost is stored here - double statsCostAbove; // the current cost is stored here - double statsCostBelow; // the current cost is stored here - - reo_unit * pHead; // the pointer to the beginning of the unit list -}; - -struct _reo_hash -{ - int Sign; // signature of the current cache operation - reo_unit * Arg1; // the first argument - reo_unit * Arg2; // the second argument - reo_unit * Arg3; // the third argument -}; - -struct _reo_man -{ - // these paramaters can be set by the API functions - int fMinWidth; // the flag to enable reordering for minimum width - int fMinApl; // the flag to enable reordering for minimum APL - int fVerbose; // the verbosity level - int fVerify; // the flag toggling verification - int fRemapUp; // the flag to enable remapping - int nIters; // the number of interations of sifting to perform - - // parameters given by the user when reordering is called - DdManager * dd; // the CUDD BDD manager - int * pOrder; // the resulting variable order will be returned here - - // derived parameters - int fThisIsAdd; // this flag is one if the function is the ADD - int * pSupp; // the support of the given function - int nSuppAlloc; // the max allowed number of support variables - int nSupp; // the number of support variables - int * pOrderInt; // the array storing the internal variable permutation - double * pVarCosts; // other arrays - int * pLevelOrder; // other arrays - reo_unit ** pWidthCofs; // temporary storage for cofactors used during reordering for width - - // parameters related to cost - int nNodesBeg; - int nNodesCur; - int nNodesEnd; - int nWidthCur; - int nWidthBeg; - int nWidthEnd; - double nAplCur; - double nAplBeg; - double nAplEnd; - - // mapping of the function into planes and back - int * pMapToPlanes; // the mapping of var indexes into plane levels - int * pMapToDdVarsOrig;// the mapping of plane levels into the original indexes - int * pMapToDdVarsFinal;// the mapping of plane levels into the final indexes - - // the planes table - reo_plane * pPlanes; - int nPlanes; - reo_unit ** pTops; - int nTops; - int nTopsAlloc; - - // the hash table - reo_hash * HTable; // the table itself - int nTableSize; // the size of the hash table - int Signature; // the signature counter - - // the referenced node list - int nNodesMaxAlloc; // this parameters determins how much memory is allocated - DdNode ** pRefNodes; - int nRefNodes; - int nRefNodesAlloc; - - // unit memory management - reo_unit * pUnitFreeList; - reo_unit ** pMemChunks; - int nMemChunks; - int nMemChunksAlloc; - int nUnitsUsed; - - // statistic variables - int HashSuccess; - int HashFailure; - int nSwaps; // the number of swaps - int nNISwaps; // the number of swaps without interaction -}; - -// used to manipulate units -#define Unit_Regular(u) ((reo_unit *)((unsigned long)(u) & ~01)) -#define Unit_Not(u) ((reo_unit *)((unsigned long)(u) ^ 01)) -#define Unit_NotCond(u,c) ((reo_unit *)((unsigned long)(u) ^ (c))) -#define Unit_IsConstant(u) ((int)((u)->lev == REO_CONST_LEVEL)) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// ======================= reoApi.c ======================================== -extern reo_man * Extra_ReorderInit( int nDdVarsMax, int nNodesMax ); -extern void Extra_ReorderQuit( reo_man * p ); -extern void Extra_ReorderSetMinimizationType( reo_man * p, reo_min_type fMinType ); -extern void Extra_ReorderSetRemapping( reo_man * p, int fRemapUp ); -extern void Extra_ReorderSetIterations( reo_man * p, int nIters ); -extern void Extra_ReorderSetVerbosity( reo_man * p, int fVerbose ); -extern void Extra_ReorderSetVerification( reo_man * p, int fVerify ); -extern DdNode * Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder ); -extern void Extra_ReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ); -// ======================= reoCore.c ======================================= -extern void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ); -extern void reoResizeStructures( reo_man * p, int nDdVarsMax, int nNodesMax, int nFuncs ); -// ======================= reoProfile.c ====================================== -extern void reoProfileNodesStart( reo_man * p ); -extern void reoProfileAplStart( reo_man * p ); -extern void reoProfileWidthStart( reo_man * p ); -extern void reoProfileWidthStart2( reo_man * p ); -extern void reoProfileAplPrint( reo_man * p ); -extern void reoProfileNodesPrint( reo_man * p ); -extern void reoProfileWidthPrint( reo_man * p ); -extern void reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level ); -// ======================= reoSift.c ======================================= -extern void reoReorderSift( reo_man * p ); -// ======================= reoSwap.c ======================================= -extern double reoReorderSwapAdjacentVars( reo_man * p, int Level, int fMovingUp ); -// ======================= reoTransfer.c =================================== -extern reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ); -extern DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ); -// ======================= reoUnits.c ====================================== -extern reo_unit * reoUnitsGetNextUnit(reo_man * p ); -extern void reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit ); -extern void reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane ); -extern void reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit ); -extern void reoUnitsStopDispenser( reo_man * p ); -// ======================= reoTest.c ======================================= -extern void Extra_ReorderTest( DdManager * dd, DdNode * Func ); -extern DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermuteReo[] ); -extern int Extra_bddReorderTest( DdManager * dd, DdNode * bF ); -extern int Extra_addReorderTest( DdManager * dd, DdNode * aF ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/reo/reoApi.c b/src/bdd/reo/reoApi.c deleted file mode 100644 index e833dabd..00000000 --- a/src/bdd/reo/reoApi.c +++ /dev/null @@ -1,289 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoApi.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Implementation of API functions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoApi.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Initializes the reordering engine.] - - Description [The first argument is the max number of variables in the - CUDD DD manager which will be used with the reordering engine - (this number of should be the maximum of BDD and ZDD parts). - The second argument is the maximum number of BDD nodes in the BDDs - to be reordered. These limits are soft. Setting lower limits will later - cause the reordering manager to resize internal data structures. - However, setting the exact values will make reordering more efficient - because resizing will be not necessary.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -reo_man * Extra_ReorderInit( int nDdVarsMax, int nNodesMax ) -{ - reo_man * p; - // allocate and clean the data structure - p = ALLOC( reo_man, 1 ); - memset( p, 0, sizeof(reo_man) ); - // resize the manager to meet user's needs - reoResizeStructures( p, nDdVarsMax, nNodesMax, 100 ); - // set the defaults - p->fMinApl = 0; - p->fMinWidth = 0; - p->fRemapUp = 0; - p->fVerbose = 0; - p->fVerify = 0; - p->nIters = 1; - return p; -} - -/**Function************************************************************* - - Synopsis [Disposes of the reordering engine.] - - Description [Removes all memory associated with the reordering engine.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderQuit( reo_man * p ) -{ - free( p->pTops ); - free( p->pSupp ); - free( p->pOrderInt ); - free( p->pWidthCofs ); - free( p->pMapToPlanes ); - free( p->pMapToDdVarsOrig ); - free( p->pMapToDdVarsFinal ); - free( p->pPlanes ); - free( p->pVarCosts ); - free( p->pLevelOrder ); - free( p->HTable ); - free( p->pRefNodes ); - reoUnitsStopDispenser( p ); - free( p->pMemChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Sets the type of DD minimizationl that will be performed.] - - Description [Currently, three different types of minimization are supported. - It is possible to minimize the number of BDD nodes. This is a classical type - of minimization, which is attempting to reduce the total number of nodes in - the (shared) BDD of the given Boolean functions. It is also possible to - minimize the BDD width, defined as the sum total of the number of cofactors - on each level in the (shared) BDD (note that the number of cofactors on the - given level may be larger than the number of nodes appearing on the given level). - It is also possible to minimize the average path length in the (shared) BDD - defined as the sum of products, for all BDD paths from the top node to any - terminal node, of the number of minterms on the path by the number of nodes - on the path. The default reordering type is minimization for the number of - BDD nodes. Calling this function with REO_MINIMIZE_WIDTH or REO_MINIMIZE_APL - as the second argument, changes the default minimization option for all the - reorder calls performed afterwards.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderSetMinimizationType( reo_man * p, reo_min_type fMinType ) -{ - if ( fMinType == REO_MINIMIZE_NODES ) - { - p->fMinWidth = 0; - p->fMinApl = 0; - } - else if ( fMinType == REO_MINIMIZE_WIDTH ) - { - p->fMinWidth = 1; - p->fMinApl = 0; - } - else if ( fMinType == REO_MINIMIZE_APL ) - { - p->fMinWidth = 0; - p->fMinApl = 1; - } - else - { - assert( 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Sets the type of remapping performed by the engine.] - - Description [The remapping refers to the way the resulting BDD - is expressed using the elementary variables of the CUDD BDD manager. - Currently, two types possibilities are supported: remapping and no - remapping. Remapping means that the function(s) after reordering - depend on the topmost variables in the manager. No remapping means - that the function(s) after reordering depend on the same variables - as before. Consider the following example. Suppose the initial four - variable function depends on variables 2,4,5, and 9 on the CUDD BDD - manager, which may be found anywhere in the current variable order. - If remapping is set, the function after ordering depends on the - topmost variables in the manager, which may or may not be the same - as the variables 2,4,5, and 9. If no remapping is set, then the - reordered function depend on the same variables 2,4,5, and 9, but - the meaning of each variale has changed according to the new ordering. - The resulting ordering is returned in the array "pOrder" filled out - by the reordering engine in the call to Extra_Reorder(). The default - is no remapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderSetRemapping( reo_man * p, int fRemapUp ) -{ - p->fRemapUp = fRemapUp; -} - -/**Function************************************************************* - - Synopsis [Sets the number of iterations of sifting performed.] - - Description [The default is one iteration. But a higher minimization - quality is desired, it is possible to set the number of iterations - to any number larger than 1. Convergence is often reached after - several iterations, so typically it make no sense to set the number - of iterations higher than 3.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderSetIterations( reo_man * p, int nIters ) -{ - p->nIters = nIters; -} - -/**Function************************************************************* - - Synopsis [Sets the verification mode.] - - Description [Setting the level to 1 results in verifying the results - of variable reordering. Verification is performed by remapping the - resulting functions into the original variable order and comparing - them with the original functions given by the user. Enabling verification - typically leads to 20-30% increase in the total runtime of REO.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderSetVerification( reo_man * p, int fVerify ) -{ - p->fVerify = fVerify; -} - -/**Function************************************************************* - - Synopsis [Sets the verbosity level.] - - Description [Setting the level to 1 results in printing statistics - before and after the reordering.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderSetVerbosity( reo_man * p, int fVerbose ) -{ - p->fVerbose = fVerbose; -} - -/**Function************************************************************* - - Synopsis [Performs reordering of the function.] - - Description [Returns the DD minimized by variable reordering in the REO - engine. Takes the CUDD decision diagram manager (dd) and the function (Func) - represented as a BDD or ADD (MTBDD). If the variable array (pOrder) is not NULL, - returns the resulting variable permutation. The permutation is such that if the resulting - function is permuted by Cudd_(add,bdd)Permute() using pOrder as the permutation - array, the initial function (Func) results. - Several flag set by other interface functions specify reordering options: - - Remappig can be set by Extra_ReorderSetRemapping(). Then the resulting DD after - reordering is remapped into the topmost levels of the DD manager. Otherwise, - the resulting DD after reordering is mapped using the same variables, on which it - originally depended, only (possibly) permuted as a result of reordering. - - Minimization type can be set by Extra_ReorderSetMinimizationType(). Note - that when the BDD is minimized for the total width of the total APL, the number - BDD nodes can increase. The total width is defines as sum total of widths on each - level. The width on one level is defined as the number of distinct BDD nodes - pointed by the nodes situated above the given level. - - The number of iterations of sifting can be set by Extra_ReorderSetIterations(). - The decision diagram returned by this procedure is not referenced.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder ) -{ - DdNode * FuncRes; - Extra_ReorderArray( p, dd, &Func, &FuncRes, 1, pOrder ); - Cudd_Deref( FuncRes ); - return FuncRes; -} - -/**Function************************************************************* - - Synopsis [Performs reordering of the array of functions.] - - Description [The options are similar to the procedure Extra_Reorder(), except that - the user should also provide storage for the resulting DDs, which are returned - referenced.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ) -{ - reoReorderArray( p, dd, Funcs, FuncsRes, nFuncs, pOrder ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoCore.c b/src/bdd/reo/reoCore.c deleted file mode 100644 index 3782631c..00000000 --- a/src/bdd/reo/reoCore.c +++ /dev/null @@ -1,438 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoCore.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Implementation of the core reordering procedure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoCore.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define CALLOC(type, num) ((type *) calloc((long)(num), (long)sizeof(type))) - -static int reoRecursiveDeref( reo_unit * pUnit ); -static int reoCheckZeroRefs( reo_plane * pPlane ); -static int reoCheckLevels( reo_man * p ); - -double s_AplBefore; -double s_AplAfter; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ) -{ - int Counter, i; - - // set the initial parameters - p->dd = dd; - p->pOrder = pOrder; - p->nTops = nFuncs; - // get the initial number of nodes - p->nNodesBeg = Cudd_SharingSize( Funcs, nFuncs ); - // resize the internal data structures of the manager if necessary - reoResizeStructures( p, ddMax(dd->size,dd->sizeZ), p->nNodesBeg, nFuncs ); - // compute the support - p->pSupp = Extra_VectorSupportArray( dd, Funcs, nFuncs, p->pSupp ); - // get the number of support variables - p->nSupp = 0; - for ( i = 0; i < dd->size; i++ ) - p->nSupp += p->pSupp[i]; - - // if it is the constant function, no need to reorder - if ( p->nSupp == 0 ) - { - for ( i = 0; i < nFuncs; i++ ) - { - FuncsRes[i] = Funcs[i]; Cudd_Ref( FuncsRes[i] ); - } - return; - } - - // create the internal variable maps - // go through variable levels in the manager - Counter = 0; - for ( i = 0; i < dd->size; i++ ) - if ( p->pSupp[ dd->invperm[i] ] ) - { - p->pMapToPlanes[ dd->invperm[i] ] = Counter; - p->pMapToDdVarsOrig[Counter] = dd->invperm[i]; - if ( !p->fRemapUp ) - p->pMapToDdVarsFinal[Counter] = dd->invperm[i]; - else - p->pMapToDdVarsFinal[Counter] = dd->invperm[Counter]; - p->pOrderInt[Counter] = Counter; - Counter++; - } - - // set the initial parameters - p->nUnitsUsed = 0; - p->nNodesCur = 0; - p->fThisIsAdd = 0; - p->Signature++; - // transfer the function from the CUDD package into REO"s internal data structure - for ( i = 0; i < nFuncs; i++ ) - p->pTops[i] = reoTransferNodesToUnits_rec( p, Funcs[i] ); - assert( p->nNodesBeg == p->nNodesCur ); - - if ( !p->fThisIsAdd && p->fMinWidth ) - { - printf( "An important message from the REO reordering engine:\n" ); - printf( "The BDD given to the engine for reordering contains complemented edges.\n" ); - printf( "Currently, such BDDs cannot be reordered for the minimum width.\n" ); - printf( "Therefore, minimization for the number of BDD nodes is performed.\n" ); - fflush( stdout ); - p->fMinApl = 0; - p->fMinWidth = 0; - } - - if ( p->fMinWidth ) - reoProfileWidthStart(p); - else if ( p->fMinApl ) - reoProfileAplStart(p); - else - reoProfileNodesStart(p); - - if ( p->fVerbose ) - { - printf( "INITIAL: " ); - if ( p->fMinWidth ) - reoProfileWidthPrint(p); - else if ( p->fMinApl ) - reoProfileAplPrint(p); - else - reoProfileNodesPrint(p); - } - - /////////////////////////////////////////////////////////////////// - // performs the reordering - p->nSwaps = 0; - p->nNISwaps = 0; - for ( i = 0; i < p->nIters; i++ ) - { - reoReorderSift( p ); - // print statistics after each iteration - if ( p->fVerbose ) - { - printf( "ITER #%d: ", i+1 ); - if ( p->fMinWidth ) - reoProfileWidthPrint(p); - else if ( p->fMinApl ) - reoProfileAplPrint(p); - else - reoProfileNodesPrint(p); - } - // if the cost function did not change, stop iterating - if ( p->fMinWidth ) - { - p->nWidthEnd = p->nWidthCur; - assert( p->nWidthEnd <= p->nWidthBeg ); - if ( p->nWidthEnd == p->nWidthBeg ) - break; - } - else if ( p->fMinApl ) - { - p->nAplEnd = p->nAplCur; - assert( p->nAplEnd <= p->nAplBeg ); - if ( p->nAplEnd == p->nAplBeg ) - break; - } - else - { - p->nNodesEnd = p->nNodesCur; - assert( p->nNodesEnd <= p->nNodesBeg ); - if ( p->nNodesEnd == p->nNodesBeg ) - break; - } - } - assert( reoCheckLevels( p ) ); - /////////////////////////////////////////////////////////////////// - -s_AplBefore = p->nAplBeg; -s_AplAfter = p->nAplEnd; - - // set the initial parameters - p->nRefNodes = 0; - p->nNodesCur = 0; - p->Signature++; - // transfer the BDDs from REO's internal data structure to CUDD - for ( i = 0; i < nFuncs; i++ ) - { - FuncsRes[i] = reoTransferUnitsToNodes_rec( p, p->pTops[i] ); Cudd_Ref( FuncsRes[i] ); - } - // undo the DDs referenced for storing in the cache - for ( i = 0; i < p->nRefNodes; i++ ) - Cudd_RecursiveDeref( dd, p->pRefNodes[i] ); - // verify zero refs of the terminal nodes - for ( i = 0; i < nFuncs; i++ ) - { - assert( reoRecursiveDeref( p->pTops[i] ) ); - } - assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) ); - - // prepare the variable map to return to the user - if ( p->pOrder ) - { - // i is the current level in the planes data structure - // p->pOrderInt[i] is the original level in the planes data structure - // p->pMapToDdVarsOrig[i] is the variable, into which we remap when we construct the BDD from planes - // p->pMapToDdVarsOrig[ p->pOrderInt[i] ] is the original BDD variable corresponding to this level - // Therefore, p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ] - // creates the permutation, which remaps the resulting BDD variable into the original BDD variable - for ( i = 0; i < p->nSupp; i++ ) - p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; - } - - if ( p->fVerify ) - { - int fVerification; - DdNode * FuncRemapped; - int * pOrder; - - if ( p->pOrder == NULL ) - { - pOrder = ALLOC( int, p->nSupp ); - for ( i = 0; i < p->nSupp; i++ ) - pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; - } - else - pOrder = p->pOrder; - - fVerification = 1; - for ( i = 0; i < nFuncs; i++ ) - { - // verify the result - if ( p->fThisIsAdd ) - FuncRemapped = Cudd_addPermute( dd, FuncsRes[i], pOrder ); - else - FuncRemapped = Cudd_bddPermute( dd, FuncsRes[i], pOrder ); - Cudd_Ref( FuncRemapped ); - - if ( FuncRemapped != Funcs[i] ) - { - fVerification = 0; - printf( "REO: Internal verification has failed!\n" ); - fflush( stdout ); - } - Cudd_RecursiveDeref( dd, FuncRemapped ); - } - if ( fVerification ) - printf( "REO: Internal verification is okay!\n" ); - - if ( p->pOrder == NULL ) - free( pOrder ); - } - - // recycle the data structure - for ( i = 0; i <= p->nSupp; i++ ) - reoUnitsRecycleUnitList( p, p->pPlanes + i ); -} - -/**Function************************************************************* - - Synopsis [Resizes the internal manager data structures.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoResizeStructures( reo_man * p, int nDdVarsMax, int nNodesMax, int nFuncs ) -{ - // resize data structures depending on the number of variables in the DD manager - if ( p->nSuppAlloc == 0 ) - { - p->pSupp = ALLOC( int, nDdVarsMax + 1 ); - p->pOrderInt = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToPlanes = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToDdVarsOrig = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToDdVarsFinal = ALLOC( int, nDdVarsMax + 1 ); - p->pPlanes = CALLOC( reo_plane, nDdVarsMax + 1 ); - p->pVarCosts = ALLOC( double, nDdVarsMax + 1 ); - p->pLevelOrder = ALLOC( int, nDdVarsMax + 1 ); - p->nSuppAlloc = nDdVarsMax + 1; - } - else if ( p->nSuppAlloc < nDdVarsMax ) - { - free( p->pSupp ); - free( p->pOrderInt ); - free( p->pMapToPlanes ); - free( p->pMapToDdVarsOrig ); - free( p->pMapToDdVarsFinal ); - free( p->pPlanes ); - free( p->pVarCosts ); - free( p->pLevelOrder ); - - p->pSupp = ALLOC( int, nDdVarsMax + 1 ); - p->pOrderInt = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToPlanes = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToDdVarsOrig = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToDdVarsFinal = ALLOC( int, nDdVarsMax + 1 ); - p->pPlanes = CALLOC( reo_plane, nDdVarsMax + 1 ); - p->pVarCosts = ALLOC( double, nDdVarsMax + 1 ); - p->pLevelOrder = ALLOC( int, nDdVarsMax + 1 ); - p->nSuppAlloc = nDdVarsMax + 1; - } - - // resize the data structures depending on the number of nodes - if ( p->nRefNodesAlloc == 0 ) - { - p->nNodesMaxAlloc = nNodesMax; - p->nTableSize = 3*nNodesMax + 1; - p->nRefNodesAlloc = 3*nNodesMax + 1; - p->nMemChunksAlloc = (10*nNodesMax + 1)/REO_CHUNK_SIZE + 1; - - p->HTable = CALLOC( reo_hash, p->nTableSize ); - p->pRefNodes = ALLOC( DdNode *, p->nRefNodesAlloc ); - p->pWidthCofs = ALLOC( reo_unit *, p->nRefNodesAlloc ); - p->pMemChunks = ALLOC( reo_unit *, p->nMemChunksAlloc ); - } - else if ( p->nNodesMaxAlloc < nNodesMax ) - { - void * pTemp; - int nMemChunksAllocPrev = p->nMemChunksAlloc; - - p->nNodesMaxAlloc = nNodesMax; - p->nTableSize = 3*nNodesMax + 1; - p->nRefNodesAlloc = 3*nNodesMax + 1; - p->nMemChunksAlloc = (10*nNodesMax + 1)/REO_CHUNK_SIZE + 1; - - free( p->HTable ); - free( p->pRefNodes ); - free( p->pWidthCofs ); - p->HTable = CALLOC( reo_hash, p->nTableSize ); - p->pRefNodes = ALLOC( DdNode *, p->nRefNodesAlloc ); - p->pWidthCofs = ALLOC( reo_unit *, p->nRefNodesAlloc ); - // p->pMemChunks should be reallocated because it contains pointers currently in use - pTemp = ALLOC( reo_unit *, p->nMemChunksAlloc ); - memmove( pTemp, p->pMemChunks, sizeof(reo_unit *) * nMemChunksAllocPrev ); - free( p->pMemChunks ); - p->pMemChunks = pTemp; - } - - // resize the data structures depending on the number of functions - if ( p->nTopsAlloc == 0 ) - { - p->pTops = ALLOC( reo_unit *, nFuncs ); - p->nTopsAlloc = nFuncs; - } - else if ( p->nTopsAlloc < nFuncs ) - { - free( p->pTops ); - p->pTops = ALLOC( reo_unit *, nFuncs ); - p->nTopsAlloc = nFuncs; - } -} - - -/**Function************************************************************* - - Synopsis [Dereferences units the data structure after reordering.] - - Description [This function is only useful for debugging.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int reoRecursiveDeref( reo_unit * pUnit ) -{ - reo_unit * pUnitR; - pUnitR = Unit_Regular(pUnit); - pUnitR->n--; - if ( Unit_IsConstant(pUnitR) ) - return 1; - if ( pUnitR->n == 0 ) - { - reoRecursiveDeref( pUnitR->pE ); - reoRecursiveDeref( pUnitR->pT ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks the zero references for the given plane.] - - Description [This function is only useful for debugging.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int reoCheckZeroRefs( reo_plane * pPlane ) -{ - reo_unit * pUnit; - for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) - { - if ( pUnit->n != 0 ) - { - assert( 0 ); - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks the zero references for the given plane.] - - Description [This function is only useful for debugging.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int reoCheckLevels( reo_man * p ) -{ - reo_unit * pUnit; - int i; - - for ( i = 0; i < p->nSupp; i++ ) - { - // there are some nodes left on each level - assert( p->pPlanes[i].statsNodes ); - for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) - { - // the level is properly set - assert( pUnit->lev == i ); - } - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoProfile.c b/src/bdd/reo/reoProfile.c deleted file mode 100644 index 84a0bc19..00000000 --- a/src/bdd/reo/reoProfile.c +++ /dev/null @@ -1,365 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoProfile.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Procudures that compute variables profiles (nodes, width, APL).] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoProfile.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function******************************************************************** - - Synopsis [Start the profile for the BDD nodes.] - - Description [TopRef is the first level, on this the given node counts towards - the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileNodesStart( reo_man * p ) -{ - int Total, i; - Total = 0; - for ( i = 0; i <= p->nSupp; i++ ) - { - p->pPlanes[i].statsCost = p->pPlanes[i].statsNodes; - Total += p->pPlanes[i].statsNodes; - } - assert( Total == p->nNodesCur ); - p->nNodesBeg = p->nNodesCur; -} - -/**Function************************************************************* - - Synopsis [Start the profile for the APL.] - - Description [Computes the total path length. The path length is normalized - by dividing it by 2^|supp(f)|. To get the "real" APL, multiply by 2^|supp(f)|. - This procedure assumes that Weight field of all nodes has been set to 0.0 - before the call, except for the weight of the topmost node, which is set to 1.0 - (1.0 is the probability of traversing the topmost node). This procedure - assigns the edge weights. Because of the equal probability of selecting 0 and 1 - assignment at a node, the edge weights are the same for the node. - Instead of storing them, we store the weight of the node, which is the probability - of traversing the node (pUnit->Weight) during the top down evalation of the BDD. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoProfileAplStart( reo_man * p ) -{ - reo_unit * pER, * pTR; - reo_unit * pUnit; - double Res, Half; - int i; - - // clean the weights of all nodes - for ( i = 0; i < p->nSupp; i++ ) - for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) - pUnit->Weight = 0.0; - // to assign the node weights (the probability of visiting each node) - // we visit the node after visiting its predecessors - - // set the probability of visits to the top nodes - for ( i = 0; i < p->nTops; i++ ) - Unit_Regular(p->pTops[i])->Weight += 1.0; - - // to compute the path length (the sum of products of edge weight by edge length) - // we visit the nodes in any order (the above order will do) - Res = 0.0; - for ( i = 0; i < p->nSupp; i++ ) - { - p->pPlanes[i].statsCost = 0.0; - for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) - { - pER = Unit_Regular(pUnit->pE); - pTR = Unit_Regular(pUnit->pT); - Half = 0.5 * pUnit->Weight; - pER->Weight += Half; - pTR->Weight += Half; - // add to the path length - p->pPlanes[i].statsCost += pUnit->Weight; - } - Res += p->pPlanes[i].statsCost; - } - p->pPlanes[p->nSupp].statsCost = 0.0; - p->nAplBeg = p->nAplCur = Res; -} - -/**Function******************************************************************** - - Synopsis [Start the profile for the BDD width. Complexity of the algorithm is O(N + n).] - - Description [TopRef is the first level, on which the given node counts towards - the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileWidthStart( reo_man * p ) -{ - reo_unit * pUnit; - int * pWidthStart; - int * pWidthStop; - int v; - - // allocate and clean the storage for starting and stopping levels - pWidthStart = ALLOC( int, p->nSupp + 1 ); - pWidthStop = ALLOC( int, p->nSupp + 1 ); - memset( pWidthStart, 0, sizeof(int) * (p->nSupp + 1) ); - memset( pWidthStop, 0, sizeof(int) * (p->nSupp + 1) ); - - // go through the non-constant nodes and set the topmost level of their cofactors - for ( v = 0; v <= p->nSupp; v++ ) - for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) - { - pUnit->TopRef = REO_TOPREF_UNDEF; - pUnit->Sign = 0; - } - - // add the topmost level of the width profile - for ( v = 0; v < p->nTops; v++ ) - { - pUnit = Unit_Regular(p->pTops[v]); - if ( pUnit->TopRef == REO_TOPREF_UNDEF ) - { - // set the starting level - pUnit->TopRef = 0; - pWidthStart[pUnit->TopRef]++; - // set the stopping level - if ( pUnit->lev != REO_CONST_LEVEL ) - pWidthStop[pUnit->lev+1]++; - } - } - - for ( v = 0; v < p->nSupp; v++ ) - for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) - { - if ( pUnit->pE->TopRef == REO_TOPREF_UNDEF ) - { - // set the starting level - pUnit->pE->TopRef = pUnit->lev + 1; - pWidthStart[pUnit->pE->TopRef]++; - // set the stopping level - if ( pUnit->pE->lev != REO_CONST_LEVEL ) - pWidthStop[pUnit->pE->lev+1]++; - } - if ( pUnit->pT->TopRef == REO_TOPREF_UNDEF ) - { - // set the starting level - pUnit->pT->TopRef = pUnit->lev + 1; - pWidthStart[pUnit->pT->TopRef]++; - // set the stopping level - if ( pUnit->pT->lev != REO_CONST_LEVEL ) - pWidthStop[pUnit->pT->lev+1]++; - } - } - - // verify the top reference - for ( v = 0; v < p->nSupp; v++ ) - reoProfileWidthVerifyLevel( p->pPlanes + v, v ); - - // derive the profile - p->nWidthCur = 0; - for ( v = 0; v <= p->nSupp; v++ ) - { - if ( v == 0 ) - p->pPlanes[v].statsWidth = pWidthStart[v] - pWidthStop[v]; - else - p->pPlanes[v].statsWidth = p->pPlanes[v-1].statsWidth + pWidthStart[v] - pWidthStop[v]; - p->pPlanes[v].statsCost = p->pPlanes[v].statsWidth; - p->nWidthCur += p->pPlanes[v].statsWidth; -// printf( "Level %2d: Width = %5d. Correct = %d.\n", v, Temp, p->pPlanes[v].statsWidth ); - } - p->nWidthBeg = p->nWidthCur; - free( pWidthStart ); - free( pWidthStop ); -} - -/**Function******************************************************************** - - Synopsis [Start the profile for the BDD width. Complexity of the algorithm is O(N * n).] - - Description [TopRef is the first level, on which the given node counts towards - the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileWidthStart2( reo_man * p ) -{ - reo_unit * pUnit; - int i, v; - - // clean the profile - for ( i = 0; i <= p->nSupp; i++ ) - p->pPlanes[i].statsWidth = 0; - - // clean the node structures - for ( v = 0; v <= p->nSupp; v++ ) - for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) - { - pUnit->TopRef = REO_TOPREF_UNDEF; - pUnit->Sign = 0; - } - - // set the topref to the topmost nodes - for ( i = 0; i < p->nTops; i++ ) - Unit_Regular(p->pTops[i])->TopRef = 0; - - // go through the non-constant nodes and set the topmost level of their cofactors - for ( i = 0; i < p->nSupp; i++ ) - for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) - { - if ( pUnit->pE->TopRef > i+1 ) - pUnit->pE->TopRef = i+1; - if ( pUnit->pT->TopRef > i+1 ) - pUnit->pT->TopRef = i+1; - } - - // verify the top reference - for ( i = 0; i < p->nSupp; i++ ) - reoProfileWidthVerifyLevel( p->pPlanes + i, i ); - - // compute the profile for the internal nodes - for ( i = 0; i < p->nSupp; i++ ) - for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) - for ( v = pUnit->TopRef; v <= pUnit->lev; v++ ) - p->pPlanes[v].statsWidth++; - - // compute the profile for the constant nodes - for ( pUnit = p->pPlanes[p->nSupp].pHead; pUnit; pUnit = pUnit->Next ) - for ( v = pUnit->TopRef; v <= p->nSupp; v++ ) - p->pPlanes[v].statsWidth++; - - // get the width cost - p->nWidthCur = 0; - for ( i = 0; i <= p->nSupp; i++ ) - { - p->pPlanes[i].statsCost = p->pPlanes[i].statsWidth; - p->nWidthCur += p->pPlanes[i].statsWidth; - } - p->nWidthBeg = p->nWidthCur; -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileNodesPrint( reo_man * p ) -{ - printf( "NODES: Total = %6d. Average = %6.2f.\n", p->nNodesCur, p->nNodesCur / (float)p->nSupp ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileAplPrint( reo_man * p ) -{ - printf( "APL: Total = %8.2f. Average =%6.2f.\n", p->nAplCur, p->nAplCur / (float)p->nSupp ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileWidthPrint( reo_man * p ) -{ - int WidthMax; - int TotalWidth; - int i; - - WidthMax = 0; - TotalWidth = 0; - for ( i = 0; i <= p->nSupp; i++ ) - { -// printf( "Level = %2d. Width = %3d.\n", i, p->pProfile[i] ); - if ( WidthMax < p->pPlanes[i].statsWidth ) - WidthMax = p->pPlanes[i].statsWidth; - TotalWidth += p->pPlanes[i].statsWidth; - } - assert( p->nWidthCur == TotalWidth ); - printf( "WIDTH: " ); - printf( "Maximum = %5d. ", WidthMax ); - printf( "Total = %7d. ", p->nWidthCur ); - printf( "Average = %6.2f.\n", TotalWidth / (float)p->nSupp ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level ) -{ - reo_unit * pUnit; - for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) - { - assert( pUnit->TopRef <= Level ); - assert( pUnit->pE->TopRef <= Level + 1 ); - assert( pUnit->pT->TopRef <= Level + 1 ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoSift.c b/src/bdd/reo/reoSift.c deleted file mode 100644 index 93d82f08..00000000 --- a/src/bdd/reo/reoSift.c +++ /dev/null @@ -1,341 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoSift.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Implementation of the sifting algorihtm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoSift.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Implements the variable sifting algorithm.] - - Description [Performs a sequence of adjacent variable swaps known as "sifting". - Uses the cost functions determined by the flag.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoReorderSift( reo_man * p ) -{ - double CostCurrent; // the cost of the current permutation - double CostLimit; // the maximum increase in cost that can be tolerated - double CostBest; // the best cost - int BestQ; // the best position - int VarCurrent; // the current variable to move - int q; // denotes the current position of the variable - int c; // performs the loops over variables until all of them are sifted - int v; // used for other purposes - - assert( p->nSupp > 0 ); - - // set the current cost depending on the minimization criteria - if ( p->fMinWidth ) - CostCurrent = p->nWidthCur; - else if ( p->fMinApl ) - CostCurrent = p->nAplCur; - else - CostCurrent = p->nNodesCur; - - // find the upper bound on tbe cost growth - CostLimit = 1 + (int)(REO_REORDER_LIMIT * CostCurrent); - - // perform sifting for each of p->nSupp variables - for ( c = 0; c < p->nSupp; c++ ) - { - // select the current variable to be the one with the largest number of nodes that is not sifted yet - VarCurrent = -1; - CostBest = -1.0; - for ( v = 0; v < p->nSupp; v++ ) - { - p->pVarCosts[v] = REO_HIGH_VALUE; - if ( !p->pPlanes[v].fSifted ) - { -// VarCurrent = v; -// if ( CostBest < p->pPlanes[v].statsCost ) - if ( CostBest < p->pPlanes[v].statsNodes ) - { -// CostBest = p->pPlanes[v].statsCost; - CostBest = p->pPlanes[v].statsNodes; - VarCurrent = v; - } - - } - } - assert( VarCurrent != -1 ); - // mark this variable as sifted - p->pPlanes[VarCurrent].fSifted = 1; - - // set the current value - p->pVarCosts[VarCurrent] = CostCurrent; - - // set the best cost - CostBest = CostCurrent; - BestQ = VarCurrent; - - // determine which way to move the variable first (up or down) - // the rationale is that if we move the shorter way first - // it is more likely that the best position will be found on the longer way - // and the reverse movement (to take the best position) will be faster - if ( VarCurrent < p->nSupp/2 ) // move up first, then down - { - // set the total cost on all levels above the current level - p->pPlanes[0].statsCostAbove = 0; - for ( v = 1; v <= VarCurrent; v++ ) - p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost; - // set the total cost on all levels below the current level - p->pPlanes[p->nSupp].statsCostBelow = 0; - for ( v = p->nSupp - 1; v >= VarCurrent; v-- ) - p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost; - - assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + - p->pPlanes[VarCurrent].statsCost + - p->pPlanes[VarCurrent].statsCostBelow ); - - // move up - for ( q = VarCurrent-1; q >= 0; q-- ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 ); - // now q points to the position of this var in the order - p->pVarCosts[q] = CostCurrent; - // update the lower bound (assuming that for level q+1 it is set correctly) - p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost; - // check the upper bound - if ( CostCurrent >= CostLimit ) - break; - // check the lower bound - if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest ) - break; - // update the best cost - if ( CostBest > CostCurrent ) - { - CostBest = CostCurrent; - BestQ = q; - // adjust node limit - CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); - } - - // when we are reordering for width or APL, it may happen that - // the number of nodes has grown above certain limit, - // in which case we have to resize the data structures - if ( p->fMinWidth || p->fMinApl ) - { - if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) - { -// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); - reoResizeStructures( p, 0, p->nNodesCur, 0 ); - } - } - } - // fix the plane index - if ( q == -1 ) - q++; - // now p points to the position of this var in the order - - // move down - for ( ; q < p->nSupp-1; ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); - q++; // change q to point to the position of this var in the order - // sanity check: the number of nodes on the back pass should be the same - if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON ) - printf("reoReorderSift(): Error! On the backward move, the costs are different.\n"); - p->pVarCosts[q] = CostCurrent; - // update the lower bound (assuming that for level q-1 it is set correctly) - p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost; - // check the bounds only if the variable already reached its previous position - if ( q >= BestQ ) - { - // check the upper bound - if ( CostCurrent >= CostLimit ) - break; - // check the lower bound - if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest ) - break; - } - // update the best cost - if ( CostBest >= CostCurrent ) - { - CostBest = CostCurrent; - BestQ = q; - // adjust node limit - CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); - } - - // when we are reordering for width or APL, it may happen that - // the number of nodes has grown above certain limit, - // in which case we have to resize the data structures - if ( p->fMinWidth || p->fMinApl ) - { - if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) - { -// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); - reoResizeStructures( p, 0, p->nNodesCur, 0 ); - } - } - } - // move the variable up from the given position (q) to the best position (BestQ) - assert( q >= BestQ ); - for ( ; q > BestQ; q-- ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q-1, 1 ); - // sanity check: the number of nodes on the back pass should be the same - if ( fabs( p->pVarCosts[q-1] - CostCurrent ) > REO_COST_EPSILON ) - { - printf("reoReorderSift(): Error! On the return move, the costs are different.\n" ); - fflush(stdout); - } - } - } - else // move down first, then up - { - // set the current number of nodes on all levels above the given level - p->pPlanes[0].statsCostAbove = 0; - for ( v = 1; v <= VarCurrent; v++ ) - p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost; - // set the current number of nodes on all levels below the given level - p->pPlanes[p->nSupp].statsCostBelow = 0; - for ( v = p->nSupp - 1; v >= VarCurrent; v-- ) - p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost; - - assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + - p->pPlanes[VarCurrent].statsCost + - p->pPlanes[VarCurrent].statsCostBelow ); - - // move down - for ( q = VarCurrent; q < p->nSupp-1; ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); - q++; // change q to point to the position of this var in the order - p->pVarCosts[q] = CostCurrent; - // update the lower bound (assuming that for level q-1 it is set correctly) - p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost; - // check the upper bound - if ( CostCurrent >= CostLimit ) - break; - // check the lower bound - if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest ) - break; - // update the best cost - if ( CostBest > CostCurrent ) - { - CostBest = CostCurrent; - BestQ = q; - // adjust node limit - CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); - } - - // when we are reordering for width or APL, it may happen that - // the number of nodes has grown above certain limit, - // in which case we have to resize the data structures - if ( p->fMinWidth || p->fMinApl ) - { - if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) - { -// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); - reoResizeStructures( p, 0, p->nNodesCur, 0 ); - } - } - } - - // move up - for ( --q; q >= 0; q-- ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 ); - // now q points to the position of this var in the order - // sanity check: the number of nodes on the back pass should be the same - if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON ) - printf("reoReorderSift(): Error! On the backward move, the costs are different.\n"); - p->pVarCosts[q] = CostCurrent; - // update the lower bound (assuming that for level q+1 it is set correctly) - p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost; - // check the bounds only if the variable already reached its previous position - if ( q <= BestQ ) - { - // check the upper bound - if ( CostCurrent >= CostLimit ) - break; - // check the lower bound - if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest ) - break; - } - // update the best cost - if ( CostBest >= CostCurrent ) - { - CostBest = CostCurrent; - BestQ = q; - // adjust node limit - CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); - } - - // when we are reordering for width or APL, it may happen that - // the number of nodes has grown above certain limit, - // in which case we have to resize the data structures - if ( p->fMinWidth || p->fMinApl ) - { - if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) - { -// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); - reoResizeStructures( p, 0, p->nNodesCur, 0 ); - } - } - } - // fix the plane index - if ( q == -1 ) - q++; - // now q points to the position of this var in the order - // move the variable down from the given position (q) to the best position (BestQ) - assert( q <= BestQ ); - for ( ; q < BestQ; q++ ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); - // sanity check: the number of nodes on the back pass should be the same - if ( fabs( p->pVarCosts[q+1] - CostCurrent ) > REO_COST_EPSILON ) - { - printf("reoReorderSift(): Error! On the return move, the costs are different.\n" ); - fflush(stdout); - } - } - } - assert( fabs( CostBest - CostCurrent ) < REO_COST_EPSILON ); - - // update the cost - if ( p->fMinWidth ) - p->nWidthCur = (int)CostBest; - else if ( p->fMinApl ) - p->nAplCur = CostCurrent; - else - p->nNodesCur = (int)CostBest; - } - - // remove the sifted attributes if any - for ( v = 0; v < p->nSupp; v++ ) - p->pPlanes[v].fSifted = 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoSwap.c b/src/bdd/reo/reoSwap.c deleted file mode 100644 index 4afa650c..00000000 --- a/src/bdd/reo/reoSwap.c +++ /dev/null @@ -1,898 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoSwap.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Implementation of the two-variable swap.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoSwap.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define AddToLinkedList( ppList, pLink ) (((pLink)->Next = *(ppList)), (*(ppList) = (pLink))) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [Takes the level (lev0) of the plane, which should be swapped - with the next plane. Returns the gain using the current cost function.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) -{ - // the levels in the decision diagram - int lev1 = lev0 + 1, lev2 = lev0 + 2; - // the new nodes on lev0 - reo_unit * pLoop, * pUnit; - // the new nodes on lev1 - reo_unit * pNewPlane20, * pNewPlane21, * pNewPlane20R; - reo_unit * pUnitE, * pUnitER, * pUnitT; - // the nodes below lev1 - reo_unit * pNew1E, * pNew1T, * pNew2E, * pNew2T; - reo_unit * pNew1ER, * pNew2ER; - // the old linked lists - reo_unit * pListOld0 = p->pPlanes[lev0].pHead; - reo_unit * pListOld1 = p->pPlanes[lev1].pHead; - // working planes and one more temporary plane - reo_unit * pListNew0 = NULL, ** ppListNew0 = &pListNew0; - reo_unit * pListNew1 = NULL, ** ppListNew1 = &pListNew1; - reo_unit * pListTemp = NULL, ** ppListTemp = &pListTemp; - // various integer variables - int fComp, fCompT, fFound, nWidthCofs, HKey, fInteract, temp, c; - // statistical variables - int nNodesUpMovedDown = 0; - int nNodesDownMovedUp = 0; - int nNodesUnrefRemoved = 0; - int nNodesUnrefAdded = 0; - int nWidthReduction = 0; - double AplWeightTotalLev0; - double AplWeightTotalLev1; - double AplWeightHalf; - double AplWeightPrev; - double AplWeightAfter; - double nCostGain; - - // set the old lists - assert( lev0 >= 0 && lev1 < p->nSupp ); - pListOld0 = p->pPlanes[lev0].pHead; - pListOld1 = p->pPlanes[lev1].pHead; - - // make sure the planes have nodes - assert( p->pPlanes[lev0].statsNodes && p->pPlanes[lev1].statsNodes ); - assert( pListOld0 && pListOld1 ); - - if ( p->fMinWidth ) - { - // verify that the width parameters are set correctly - reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 ); - reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 ); - // start the storage for cofactors - nWidthCofs = 0; - } - else if ( p->fMinApl ) - { - AplWeightPrev = p->nAplCur; - AplWeightAfter = p->nAplCur; - AplWeightTotalLev0 = 0.0; - AplWeightTotalLev1 = 0.0; - } - - // check if the planes interact - fInteract = 0; // assume that they do not interact - for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) - { - if ( pUnit->pT->lev == lev1 || Unit_Regular(pUnit->pE)->lev == lev1 ) - { - fInteract = 1; - break; - } - // change the level now, this is done for efficiency reasons - pUnit->lev = lev1; - } - - // set the new signature for hashing - p->nSwaps++; - if ( !fInteract ) -// if ( 0 ) - { - // perform the swap without interaction - p->nNISwaps++; - - // change the levels - if ( p->fMinWidth ) - { - // go through the current lower level, which will become upper - for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next ) - { - pUnit->lev = lev0; - - pUnitER = Unit_Regular(pUnit->pE); - if ( pUnitER->TopRef > lev0 ) - { - if ( pUnitER->Sign != p->nSwaps ) - { - if ( pUnitER->TopRef == lev2 ) - { - pUnitER->TopRef = lev1; - nWidthReduction--; - } - else - { - assert( pUnitER->TopRef == lev1 ); - } - pUnitER->Sign = p->nSwaps; - } - } - - pUnitT = pUnit->pT; - if ( pUnitT->TopRef > lev0 ) - { - if ( pUnitT->Sign != p->nSwaps ) - { - if ( pUnitT->TopRef == lev2 ) - { - pUnitT->TopRef = lev1; - nWidthReduction--; - } - else - { - assert( pUnitT->TopRef == lev1 ); - } - pUnitT->Sign = p->nSwaps; - } - } - - } - - // go through the current upper level, which will become lower - for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) - { - pUnit->lev = lev1; - - pUnitER = Unit_Regular(pUnit->pE); - if ( pUnitER->TopRef > lev0 ) - { - if ( pUnitER->Sign != p->nSwaps ) - { - assert( pUnitER->TopRef == lev1 ); - pUnitER->TopRef = lev2; - pUnitER->Sign = p->nSwaps; - nWidthReduction++; - } - } - - pUnitT = pUnit->pT; - if ( pUnitT->TopRef > lev0 ) - { - if ( pUnitT->Sign != p->nSwaps ) - { - assert( pUnitT->TopRef == lev1 ); - pUnitT->TopRef = lev2; - pUnitT->Sign = p->nSwaps; - nWidthReduction++; - } - } - } - } - else - { -// for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) -// pUnit->lev = lev1; - for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next ) - pUnit->lev = lev0; - } - - // set the new linked lists, which will be attached to the planes - pListNew0 = pListOld1; - pListNew1 = pListOld0; - - if ( p->fMinApl ) - { - AplWeightTotalLev0 = p->pPlanes[lev1].statsCost; - AplWeightTotalLev1 = p->pPlanes[lev0].statsCost; - } - - // set the changes in terms of nodes - nNodesUpMovedDown = p->pPlanes[lev0].statsNodes; - nNodesDownMovedUp = p->pPlanes[lev1].statsNodes; - goto finish; - } - p->Signature++; - - - // two-variable swap is done in three easy steps - // previously I thought that steps (1) and (2) can be merged into one step - // now it is clear that this cannot be done without changing a lot of other stuff... - - // (1) walk through the upper level, find units without cofactors in the lower level - // and move them to the new lower level (while adding to the cache) - // (2) walk through the uppoer level, and tranform all the remaning nodes - // while employing cache for the new lower level - // (3) walk through the old lower level, find those nodes whose ref counters are not zero, - // and move them to the new uppoer level, free other nodes - - // (1) walk through the upper level, find units without cofactors in the lower level - // and move them to the new lower level (while adding to the cache) - for ( pLoop = pListOld0; pLoop; ) - { - pUnit = pLoop; - pLoop = pLoop->Next; - - pUnitE = pUnit->pE; - pUnitER = Unit_Regular(pUnitE); - pUnitT = pUnit->pT; - - if ( pUnitER->lev != lev1 && pUnitT->lev != lev1 ) - { - // before after - // - // <p1> - // 0 / \ 1 - // / \ - // / \ - // / \ <p2n> - // / \ 0 / \ 1 - // / \ / \ - // / \ / \ - // F0 F1 F0 F1 - - // move to plane-2-new - // nothing changes in the process (cofactors, ref counter, APL weight) - pUnit->lev = lev1; - AddToLinkedList( ppListNew1, pUnit ); - if ( p->fMinApl ) - AplWeightTotalLev1 += pUnit->Weight; - - // add to cache - find the cell with different signature (not the current one!) - for ( HKey = hashKey3(p->Signature, pUnitE, pUnitT, p->nTableSize); - p->HTable[HKey].Sign == p->Signature; - HKey = (HKey+1) % p->nTableSize ); - assert( p->HTable[HKey].Sign != p->Signature ); - p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = pUnitE; - p->HTable[HKey].Arg2 = pUnitT; - p->HTable[HKey].Arg3 = pUnit; - - nNodesUpMovedDown++; - - if ( p->fMinWidth ) - { - // update the cofactors's top ref - if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - assert( pUnitER->TopRef == lev1 ); - pUnitER->TopRefNew = lev2; - if ( pUnitER->Sign != p->nSwaps ) - { - pUnitER->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pUnitER; - } - } - if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - assert( pUnitT->TopRef == lev1 ); - pUnitT->TopRefNew = lev2; - if ( pUnitT->Sign != p->nSwaps ) - { - pUnitT->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pUnitT; - } - } - } - } - else - { - // add to the temporary plane - AddToLinkedList( ppListTemp, pUnit ); - } - } - - - // (2) walk through the uppoer level, and tranform all the remaning nodes - // while employing cache for the new lower level - for ( pLoop = pListTemp; pLoop; ) - { - pUnit = pLoop; - pLoop = pLoop->Next; - - pUnitE = pUnit->pE; - pUnitER = Unit_Regular(pUnitE); - pUnitT = pUnit->pT; - fComp = (int)(pUnitER != pUnitE); - - // count the amount of weight to reduce the APL of the children of this node - if ( p->fMinApl ) - AplWeightHalf = 0.5 * pUnit->Weight; - - // determine what situation is this - if ( pUnitER->lev == lev1 && pUnitT->lev == lev1 ) - { - if ( fComp == 0 ) - { - // before after - // - // <p1> <p1n> - // 0 / \ 1 0 / \ 1 - // / \ / \ - // / \ / \ - // <p2> <p2> <p2n> <p2n> - // 0 / \ 1 0 / \ 1 0 / \ 1 0 / \ 1 - // / \ / \ / \ / \ - // / \ / \ / \ / \ - // F0 F1 F2 F3 F0 F2 F1 F3 - // pNew1E pNew1T pNew2E pNew2T - // - pNew1E = pUnitE->pE; // F0 - pNew1T = pUnitT->pE; // F2 - - pNew2E = pUnitE->pT; // F1 - pNew2T = pUnitT->pT; // F3 - } - else - { - // before after - // - // <p1> <p1n> - // 0 . \ 1 0 / \ 1 - // . \ / \ - // . \ / \ - // <p2> <p2> <p2n> <p2n> - // 0 / \ 1 0 / \ 1 0 . \ 1 0 . \ 1 - // / \ / \ . \ . \ - // / \ / \ . \ . \ - // F0 F1 F2 F3 F0 F2 F1 F3 - // pNew1E pNew1T pNew2E pNew2T - // - pNew1E = Unit_Not(pUnitER->pE); // F0 - pNew1T = pUnitT->pE; // F2 - - pNew2E = Unit_Not(pUnitER->pT); // F1 - pNew2T = pUnitT->pT; // F3 - } - // subtract ref counters - on the level P2 - pUnitER->n--; - pUnitT->n--; - - // mark the change in the APL weights - if ( p->fMinApl ) - { - pUnitER->Weight -= AplWeightHalf; - pUnitT->Weight -= AplWeightHalf; - AplWeightAfter -= pUnit->Weight; - } - } - else if ( pUnitER->lev == lev1 ) - { - if ( fComp == 0 ) - { - // before after - // - // <p1> <p1n> - // 0 / \ 1 0 / \ 1 - // / \ / \ - // / \ / \ - // <p2> \ <p2n> <p2n> - // 0 / \ 1 \ 0 / \ 1 0 / \ 1 - // / \ \ / \ / \ - // / \ \ / \ / \ - // F0 F1 F3 F0 F3 F1 F3 - // pNew1E pNew1T pNew2E pNew2T - // - pNew1E = pUnitER->pE; // F0 - pNew1T = pUnitT; // F3 - - pNew2E = pUnitER->pT; // F1 - pNew2T = pUnitT; // F3 - } - else - { - // before after - // - // <p1> <p1n> - // 0 . \ 1 0 / \ 1 - // . \ / \ - // . \ / \ - // <p2> \ <p2n> <p2n> - // 0 / \ 1 \ 0 . \ 1 0 . \ 1 - // / \ \ . \ . \ - // / \ \ . \ . \ - // F0 F1 F3 F0 F3 F1 F3 - // pNew1E pNew1T pNew2E pNew2T - // - pNew1E = Unit_Not(pUnitER->pE); // F0 - pNew1T = pUnitT; // F3 - - pNew2E = Unit_Not(pUnitER->pT); // F1 - pNew2T = pUnitT; // F3 - } - // subtract ref counter - on the level P2 - pUnitER->n--; - // subtract ref counter - on other levels - pUnitT->n--; /// - - // mark the change in the APL weights - if ( p->fMinApl ) - { - pUnitER->Weight -= AplWeightHalf; - AplWeightAfter -= AplWeightHalf; - } - } - else if ( pUnitT->lev == lev1 ) - { - // before after - // - // <p1> <p1n> - // 0 / \ 1 0 / \ 1 - // / \ / \ - // / \ / \ - // / <p2> <p2n> <p2n> - // / 0 / \ 1 0 / \ 1 0 / \ 1 - // / / \ / \ / \ - // / / \ / \ / \ - // F0 F2 F3 F0 F2 F0 F3 - // pNew1E pNew1T pNew2E pNew2T - // - pNew1E = pUnitE; // F0 - pNew1T = pUnitT->pE; // F2 - - pNew2E = pUnitE; // F0 - pNew2T = pUnitT->pT; // F3 - - // subtract incoming edge counter - on the level P2 - pUnitT->n--; - // subtract ref counter - on other levels - pUnitER->n--; /// - - // mark the change in the APL weights - if ( p->fMinApl ) - { - pUnitT->Weight -= AplWeightHalf; - AplWeightAfter -= AplWeightHalf; - } - } - else - { - assert( 0 ); // should never happen - } - - - // consider all the cases except the last one - if ( pNew1E == pNew1T ) - { - pNewPlane20 = pNew1T; - - if ( p->fMinWidth ) - { - // update the cofactors's top ref - if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - pNew1T->TopRefNew = lev1; - if ( pNew1T->Sign != p->nSwaps ) - { - pNew1T->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew1T; - } - } - } - } - else - { - // pNew1T can be complemented - fCompT = Cudd_IsComplement(pNew1T); - if ( fCompT ) - { - pNew1E = Unit_Not(pNew1E); - pNew1T = Unit_Not(pNew1T); - } - - // check the hash-table - fFound = 0; - for ( HKey = hashKey3(p->Signature, pNew1E, pNew1T, p->nTableSize); - p->HTable[HKey].Sign == p->Signature; - HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == pNew1E && p->HTable[HKey].Arg2 == pNew1T ) - { // the entry is present - // assign this entry - pNewPlane20 = p->HTable[HKey].Arg3; - assert( pNewPlane20->lev == lev1 ); - fFound = 1; - p->HashSuccess++; - break; - } - - if ( !fFound ) - { // create the new entry - pNewPlane20 = reoUnitsGetNextUnit( p ); // increments the unit counter - pNewPlane20->pE = pNew1E; - pNewPlane20->pT = pNew1T; - pNewPlane20->n = 0; // ref will be added later - pNewPlane20->lev = lev1; - if ( p->fMinWidth ) - { - pNewPlane20->TopRef = lev1; - pNewPlane20->Sign = 0; - } - // set the weight of this node - if ( p->fMinApl ) - pNewPlane20->Weight = 0.0; - - // increment ref counters of children - pNew1ER = Unit_Regular(pNew1E); - pNew1ER->n++; // - pNew1T->n++; // - - // insert into the data structure - AddToLinkedList( ppListNew1, pNewPlane20 ); - - // add this entry to cache - assert( p->HTable[HKey].Sign != p->Signature ); - p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = pNew1E; - p->HTable[HKey].Arg2 = pNew1T; - p->HTable[HKey].Arg3 = pNewPlane20; - - nNodesUnrefAdded++; - - if ( p->fMinWidth ) - { - // update the cofactors's top ref - if ( pNew1ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - if ( pNew1ER->Sign != p->nSwaps ) - { - pNew1ER->TopRefNew = lev2; - if ( pNew1ER->Sign != p->nSwaps ) - { - pNew1ER->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew1ER; - } - } - // otherwise the level is already set correctly - else - { - assert( pNew1ER->TopRefNew == lev1 || pNew1ER->TopRefNew == lev2 ); - } - } - // update the cofactors's top ref - if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - if ( pNew1T->Sign != p->nSwaps ) - { - pNew1T->TopRefNew = lev2; - if ( pNew1T->Sign != p->nSwaps ) - { - pNew1T->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew1T; - } - } - // otherwise the level is already set correctly - else - { - assert( pNew1T->TopRefNew == lev1 || pNew1T->TopRefNew == lev2 ); - } - } - } - } - - if ( p->fMinApl ) - { - // increment the weight of this node - pNewPlane20->Weight += AplWeightHalf; - // mark the change in the APL weight - AplWeightAfter += AplWeightHalf; - // update the total weight of this level - AplWeightTotalLev1 += AplWeightHalf; - } - - if ( fCompT ) - pNewPlane20 = Unit_Not(pNewPlane20); - } - - if ( pNew2E == pNew2T ) - { - pNewPlane21 = pNew2T; - - if ( p->fMinWidth ) - { - // update the cofactors's top ref - if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - pNew2T->TopRefNew = lev1; - if ( pNew2T->Sign != p->nSwaps ) - { - pNew2T->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew2T; - } - } - } - } - else - { - assert( !Cudd_IsComplement(pNew2T) ); - - // check the hash-table - fFound = 0; - for ( HKey = hashKey3(p->Signature, pNew2E, pNew2T, p->nTableSize); - p->HTable[HKey].Sign == p->Signature; - HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == pNew2E && p->HTable[HKey].Arg2 == pNew2T ) - { // the entry is present - // assign this entry - pNewPlane21 = p->HTable[HKey].Arg3; - assert( pNewPlane21->lev == lev1 ); - fFound = 1; - p->HashSuccess++; - break; - } - - if ( !fFound ) - { // create the new entry - pNewPlane21 = reoUnitsGetNextUnit( p ); // increments the unit counter - pNewPlane21->pE = pNew2E; - pNewPlane21->pT = pNew2T; - pNewPlane21->n = 0; // ref will be added later - pNewPlane21->lev = lev1; - if ( p->fMinWidth ) - { - pNewPlane21->TopRef = lev1; - pNewPlane21->Sign = 0; - } - // set the weight of this node - if ( p->fMinApl ) - pNewPlane21->Weight = 0.0; - - // increment ref counters of children - pNew2ER = Unit_Regular(pNew2E); - pNew2ER->n++; // - pNew2T->n++; // - - // insert into the data structure -// reoUnitsAddUnitToPlane( &P2new, pNewPlane21 ); - AddToLinkedList( ppListNew1, pNewPlane21 ); - - // add this entry to cache - assert( p->HTable[HKey].Sign != p->Signature ); - p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = pNew2E; - p->HTable[HKey].Arg2 = pNew2T; - p->HTable[HKey].Arg3 = pNewPlane21; - - nNodesUnrefAdded++; - - - if ( p->fMinWidth ) - { - // update the cofactors's top ref - if ( pNew2ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - if ( pNew2ER->Sign != p->nSwaps ) - { - pNew2ER->TopRefNew = lev2; - if ( pNew2ER->Sign != p->nSwaps ) - { - pNew2ER->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew2ER; - } - } - // otherwise the level is already set correctly - else - { - assert( pNew2ER->TopRefNew == lev1 || pNew2ER->TopRefNew == lev2 ); - } - } - // update the cofactors's top ref - if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - if ( pNew2T->Sign != p->nSwaps ) - { - pNew2T->TopRefNew = lev2; - if ( pNew2T->Sign != p->nSwaps ) - { - pNew2T->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew2T; - } - } - // otherwise the level is already set correctly - else - { - assert( pNew2T->TopRefNew == lev1 || pNew2T->TopRefNew == lev2 ); - } - } - } - } - - if ( p->fMinApl ) - { - // increment the weight of this node - pNewPlane21->Weight += AplWeightHalf; - // mark the change in the APL weight - AplWeightAfter += AplWeightHalf; - // update the total weight of this level - AplWeightTotalLev1 += AplWeightHalf; - } - } - // in all cases, the node will be added to the plane-1 - // this should be the same node (pUnit) as was originally there - // because it is referenced by the above nodes - - assert( !Cudd_IsComplement(pNewPlane21) ); - // should be the case; otherwise reordering is not a local operation - - pUnit->pE = pNewPlane20; - pUnit->pT = pNewPlane21; - assert( pUnit->lev == lev0 ); - // reference counter remains the same; the APL weight remains the same - - // increment ref counters of children - pNewPlane20R = Unit_Regular(pNewPlane20); - pNewPlane20R->n++; /// - pNewPlane21->n++; /// - - // insert into the data structure - AddToLinkedList( ppListNew0, pUnit ); - if ( p->fMinApl ) - AplWeightTotalLev0 += pUnit->Weight; - } - - // (3) walk through the old lower level, find those nodes whose ref counters are not zero, - // and move them to the new uppoer level, free other nodes - for ( pLoop = pListOld1; pLoop; ) - { - pUnit = pLoop; - pLoop = pLoop->Next; - if ( pUnit->n ) - { - assert( !p->fMinApl || pUnit->Weight > 0.0 ); - // the node should be added to the new level - // no need to check the hash table - pUnit->lev = lev0; - AddToLinkedList( ppListNew0, pUnit ); - if ( p->fMinApl ) - AplWeightTotalLev0 += pUnit->Weight; - - nNodesDownMovedUp++; - - if ( p->fMinWidth ) - { - pUnitER = Unit_Regular(pUnit->pE); - pUnitT = pUnit->pT; - - // update the cofactors's top ref - if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - pUnitER->TopRefNew = lev1; - if ( pUnitER->Sign != p->nSwaps ) - { - pUnitER->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pUnitER; - } - } - if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - pUnitT->TopRefNew = lev1; - if ( pUnitT->Sign != p->nSwaps ) - { - pUnitT->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pUnitT; - } - } - } - } - else - { - assert( !p->fMinApl || pUnit->Weight == 0.0 ); - // decrement reference counters of children - pUnitER = Unit_Regular(pUnit->pE); - pUnitT = pUnit->pT; - pUnitER->n--; /// - pUnitT->n--; /// - // the node should be thrown away - reoUnitsRecycleUnit( p, pUnit ); - nNodesUnrefRemoved++; - } - } - -finish: - - // attach the new levels to the planes - p->pPlanes[lev0].pHead = pListNew0; - p->pPlanes[lev1].pHead = pListNew1; - - // swap the sift status - temp = p->pPlanes[lev0].fSifted; - p->pPlanes[lev0].fSifted = p->pPlanes[lev1].fSifted; - p->pPlanes[lev1].fSifted = temp; - - // swap variables in the variable map - if ( p->pOrderInt ) - { - temp = p->pOrderInt[lev0]; - p->pOrderInt[lev0] = p->pOrderInt[lev1]; - p->pOrderInt[lev1] = temp; - } - - // adjust the node profile - p->pPlanes[lev0].statsNodes -= (nNodesUpMovedDown - nNodesDownMovedUp); - p->pPlanes[lev1].statsNodes -= (nNodesDownMovedUp - nNodesUpMovedDown) + nNodesUnrefRemoved - nNodesUnrefAdded; - p->nNodesCur -= nNodesUnrefRemoved - nNodesUnrefAdded; - - // adjust the node profile on this level - if ( p->fMinWidth ) - { - for ( c = 0; c < nWidthCofs; c++ ) - { - if ( p->pWidthCofs[c]->TopRefNew < p->pWidthCofs[c]->TopRef ) - { - p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew; - nWidthReduction--; - } - else if ( p->pWidthCofs[c]->TopRefNew > p->pWidthCofs[c]->TopRef ) - { - p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew; - nWidthReduction++; - } - } - // verify that the profile is okay - reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 ); - reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 ); - - // compute the total gain in terms of width - nCostGain = (nNodesDownMovedUp - nNodesUpMovedDown + nNodesUnrefRemoved - nNodesUnrefAdded) + nWidthReduction; - // adjust the width on this level - p->pPlanes[lev1].statsWidth -= (int)nCostGain; - // set the cost - p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsWidth; - } - else if ( p->fMinApl ) - { - // compute the total gain in terms of APL - nCostGain = AplWeightPrev - AplWeightAfter; - // make sure that the ALP is updated correctly -// assert( p->pPlanes[lev0].statsCost + p->pPlanes[lev1].statsCost - nCostGain == -// AplWeightTotalLev0 + AplWeightTotalLev1 ); - // adjust the profile - p->pPlanes[lev0].statsApl = AplWeightTotalLev0; - p->pPlanes[lev1].statsApl = AplWeightTotalLev1; - // set the cost - p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsApl; - p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsApl; - } - else - { - // compute the total gain in terms of the number of nodes - nCostGain = nNodesUnrefRemoved - nNodesUnrefAdded; - // adjust the profile (adjusted above) - // set the cost - p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsNodes; - p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsNodes; - } - - return nCostGain; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoTest.c b/src/bdd/reo/reoTest.c deleted file mode 100644 index 82f3d5f5..00000000 --- a/src/bdd/reo/reoTest.c +++ /dev/null @@ -1,251 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoTest.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Various testing procedures (may be outdated).] - - Author [Alan Mishchenko <alanmi@ece.pdx.edu>] - - Affiliation [ECE Department. Portland State University, Portland, Oregon.] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoTest.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reorders the DD using REO and CUDD.] - - Description [This function can be used to test the performance of the reordering package.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderTest( DdManager * dd, DdNode * Func ) -{ - reo_man * pReo; - DdNode * Temp, * Temp1; - int pOrder[1000]; - - pReo = Extra_ReorderInit( 100, 100 ); - -//Extra_DumpDot( dd, &Func, 1, "beforReo.dot", 0 ); - Temp = Extra_Reorder( pReo, dd, Func, pOrder ); Cudd_Ref( Temp ); -//Extra_DumpDot( dd, &Temp, 1, "afterReo.dot", 0 ); - - Temp1 = Extra_ReorderCudd(dd, Func, NULL ); Cudd_Ref( Temp1 ); -printf( "Initial = %d. Final = %d. Cudd = %d.\n", Cudd_DagSize(Func), Cudd_DagSize(Temp), Cudd_DagSize(Temp1) ); - Cudd_RecursiveDeref( dd, Temp1 ); - Cudd_RecursiveDeref( dd, Temp ); - - Extra_ReorderQuit( pReo ); -} - - -/**Function************************************************************* - - Synopsis [Reorders the DD using REO and CUDD.] - - Description [This function can be used to test the performance of the reordering package.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderTestArray( DdManager * dd, DdNode * Funcs[], int nFuncs ) -{ - reo_man * pReo; - DdNode * FuncsRes[1000]; - int pOrder[1000]; - int i; - - pReo = Extra_ReorderInit( 100, 100 ); - Extra_ReorderArray( pReo, dd, Funcs, FuncsRes, nFuncs, pOrder ); - Extra_ReorderQuit( pReo ); - -printf( "Initial = %d. Final = %d.\n", Cudd_SharingSize(Funcs,nFuncs), Cudd_SharingSize(FuncsRes,nFuncs) ); - - for ( i = 0; i < nFuncs; i++ ) - Cudd_RecursiveDeref( dd, FuncsRes[i] ); - -} - -/**Function************************************************************* - - Synopsis [Reorders the DD using CUDD package.] - - Description [Transfers the DD into a temporary manager in such a way - that the level correspondence is preserved. Reorders the manager - and transfers the DD back into the original manager using the topmost - levels of the manager, in such a way that the ordering of levels is - preserved. The resulting permutation is returned in the array - given by the user.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermuteReo[] ) -{ - static DdManager * ddReorder = NULL; - static int * Permute = NULL; - static int * PermuteReo1 = NULL; - static int * PermuteReo2 = NULL; - DdNode * aFuncReorder, * aFuncNew; - int lev, var; - - // start the reordering manager - if ( ddReorder == NULL ) - { - Permute = ALLOC( int, dd->size ); - PermuteReo1 = ALLOC( int, dd->size ); - PermuteReo2 = ALLOC( int, dd->size ); - ddReorder = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynDisable(ddReorder); - } - - // determine the permutation of variable to make sure that var order in bFunc - // will not change when this function is transfered into the new manager - for ( lev = 0; lev < dd->size; lev++ ) - { - Permute[ dd->invperm[lev] ] = ddReorder->invperm[lev]; - PermuteReo1[ ddReorder->invperm[lev] ] = dd->invperm[lev]; - } - // transfer this function into the new manager in such a way that ordering of vars does not change - aFuncReorder = Extra_TransferPermute( dd, ddReorder, aFunc, Permute ); Cudd_Ref( aFuncReorder ); -// assert( Cudd_DagSize(aFunc) == Cudd_DagSize(aFuncReorder) ); - - // perform the reordering -printf( "Nodes before = %d.\n", Cudd_DagSize(aFuncReorder) ); - Cudd_ReduceHeap( ddReorder, CUDD_REORDER_SYMM_SIFT, 1 ); -printf( "Nodes before = %d.\n", Cudd_DagSize(aFuncReorder) ); - - // determine the reverse variable permutation - for ( lev = 0; lev < dd->size; lev++ ) - { - Permute[ ddReorder->invperm[lev] ] = dd->invperm[lev]; - PermuteReo2[ dd->invperm[lev] ] = ddReorder->invperm[lev]; - } - - // transfer this function into the new manager in such a way that ordering of vars does not change - aFuncNew = Extra_TransferPermute( ddReorder, dd, aFuncReorder, Permute ); Cudd_Ref( aFuncNew ); -// assert( Cudd_DagSize(aFuncNew) == Cudd_DagSize(aFuncReorder) ); - Cudd_RecursiveDeref( ddReorder, aFuncReorder ); - - // derive the resulting variable ordering - if ( pPermuteReo ) - for ( var = 0; var < dd->size; var++ ) - pPermuteReo[var] = PermuteReo1[ PermuteReo2[var] ]; - - Cudd_Deref( aFuncNew ); - return aFuncNew; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [Transfers the BDD into another manager minimizes it and - returns the min number of nodes; disposes of the BDD in the new manager. - Useful for debugging or comparing the performance of other reordering - procedures.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_bddReorderTest( DdManager * dd, DdNode * bF ) -{ - static DdManager * s_ddmin; - DdNode * bFmin; - int nNodes; -// int clk1; - - if ( s_ddmin == NULL ) - s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); - -// Cudd_ShuffleHeap( s_ddmin, dd->invperm ); - -// clk1 = clock(); - bFmin = Cudd_bddTransfer( dd, s_ddmin, bF ); Cudd_Ref( bFmin ); - Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SIFT,1); -// Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); - nNodes = Cudd_DagSize( bFmin ); - Cudd_RecursiveDeref( s_ddmin, bFmin ); - -// printf( "Classical variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - return nNodes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Transfers the ADD into another manager minimizes it and - returns the min number of nodes; disposes of the BDD in the new manager. - Useful for debugging or comparing the performance of other reordering - procedures.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_addReorderTest( DdManager * dd, DdNode * aF ) -{ - static DdManager * s_ddmin; - DdNode * bF; - DdNode * bFmin; - DdNode * aFmin; - int nNodesBeg; - int nNodesEnd; - int clk1; - - if ( s_ddmin == NULL ) - s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); - -// Cudd_ShuffleHeap( s_ddmin, dd->invperm ); - - clk1 = clock(); - bF = Cudd_addBddPattern( dd, aF ); Cudd_Ref( bF ); - bFmin = Cudd_bddTransfer( dd, s_ddmin, bF ); Cudd_Ref( bFmin ); - Cudd_RecursiveDeref( dd, bF ); - aFmin = Cudd_BddToAdd( s_ddmin, bFmin ); Cudd_Ref( aFmin ); - Cudd_RecursiveDeref( s_ddmin, bFmin ); - - nNodesBeg = Cudd_DagSize( aFmin ); - Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SIFT,1); -// Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); - nNodesEnd = Cudd_DagSize( aFmin ); - Cudd_RecursiveDeref( s_ddmin, aFmin ); - - printf( "Classical reordering of ADDs: Before = %d. After = %d.\n", nNodesBeg, nNodesEnd ); - printf( "Classical variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - return nNodesEnd; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoTransfer.c b/src/bdd/reo/reoTransfer.c deleted file mode 100644 index 65d31d01..00000000 --- a/src/bdd/reo/reoTransfer.c +++ /dev/null @@ -1,199 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoTransfer.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Transfering a DD from the CUDD manager into REO"s internal data structures and back.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoTransfer.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transfers the DD into the internal reordering data structure.] - - Description [It is important that the hash table is lossless.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ) -{ - DdManager * dd = p->dd; - reo_unit * pUnit; - int HKey, fComp; - - fComp = Cudd_IsComplement(F); - F = Cudd_Regular(F); - - // check the hash-table - if ( F->ref != 1 ) - { - // search cache - use linear probing - for ( HKey = hashKey2(p->Signature,F,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == (reo_unit *)F ) - { - pUnit = p->HTable[HKey].Arg2; - assert( pUnit ); - // increment the edge counter - pUnit->n++; - return Unit_NotCond( pUnit, fComp ); - } - } - // the entry in not found in the cache - - // create a new entry - pUnit = reoUnitsGetNextUnit( p ); - pUnit->n = 1; - if ( cuddIsConstant(F) ) - { - pUnit->lev = REO_CONST_LEVEL; - pUnit->pE = (reo_unit*)((int)(cuddV(F))); - pUnit->pT = NULL; - // check if the diagram that is being reordering has complement edges - if ( F != dd->one ) - p->fThisIsAdd = 1; - // insert the unit into the corresponding plane - reoUnitsAddUnitToPlane( &(p->pPlanes[p->nSupp]), pUnit ); // increments the unit counter - } - else - { - pUnit->lev = p->pMapToPlanes[F->index]; - pUnit->pE = reoTransferNodesToUnits_rec( p, cuddE(F) ); - pUnit->pT = reoTransferNodesToUnits_rec( p, cuddT(F) ); - // insert the unit into the corresponding plane - reoUnitsAddUnitToPlane( &(p->pPlanes[pUnit->lev]), pUnit ); // increments the unit counter - } - - // add to the hash table - if ( F->ref != 1 ) - { - // the next free entry is already found - it is pointed to by HKey - // while we traversed the diagram, the hash entry to which HKey points, - // might have been used. Make sure that its signature is different. - for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); - p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = (reo_unit *)F; - p->HTable[HKey].Arg2 = pUnit; - } - - // increment the counter of nodes - p->nNodesCur++; - return Unit_NotCond( pUnit, fComp ); -} - -/**Function************************************************************* - - Synopsis [Creates the DD from the internal reordering data structure.] - - Description [It is important that the hash table is lossless.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ) -{ - DdManager * dd = p->dd; - DdNode * bRes, * E, * T; - int HKey, fComp; - - fComp = Cudd_IsComplement(pUnit); - pUnit = Unit_Regular(pUnit); - - // check the hash-table - if ( pUnit->n != 1 ) - { - for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == pUnit ) - { - bRes = (DdNode*) p->HTable[HKey].Arg2; - assert( bRes ); - return Cudd_NotCond( bRes, fComp ); - } - } - - // treat the case of constants - if ( Unit_IsConstant(pUnit) ) - { - bRes = cuddUniqueConst( dd, ((double)((int)(pUnit->pE))) ); - cuddRef( bRes ); - } - else - { - // split and recur on children of this node - E = reoTransferUnitsToNodes_rec( p, pUnit->pE ); - if ( E == NULL ) - return NULL; - cuddRef(E); - - T = reoTransferUnitsToNodes_rec( p, pUnit->pT ); - if ( T == NULL ) - { - Cudd_RecursiveDeref(dd, E); - return NULL; - } - cuddRef(T); - - // consider the case when Res0 and Res1 are the same node - assert( E != T ); - assert( !Cudd_IsComplement(T) ); - - bRes = cuddUniqueInter( dd, p->pMapToDdVarsFinal[pUnit->lev], T, E ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,E); - Cudd_RecursiveDeref(dd,T); - return NULL; - } - cuddRef( bRes ); - cuddDeref( E ); - cuddDeref( T ); - } - - // do not keep the result if the ref count is only 1, since it will not be visited again - if ( pUnit->n != 1 ) - { - // while we traversed the diagram, the hash entry to which HKey points, - // might have been used. Make sure that its signature is different. - for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); - p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = pUnit; - p->HTable[HKey].Arg2 = (reo_unit *)bRes; - - // add the DD to the referenced DD list in order to be able to store it in cache - p->pRefNodes[p->nRefNodes++] = bRes; Cudd_Ref( bRes ); - // no need to do this, because the garbage collection will not take bRes away - // it is held by the diagram in the making - } - // increment the counter of nodes - p->nNodesCur++; - cuddDeref( bRes ); - return Cudd_NotCond( bRes, fComp ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoUnits.c b/src/bdd/reo/reoUnits.c deleted file mode 100644 index aa86516e..00000000 --- a/src/bdd/reo/reoUnits.c +++ /dev/null @@ -1,184 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoUnits.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Procedures which support internal data structures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoUnits.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void reoUnitsAddToFreeUnitList( reo_man * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Extract the next unit from the free unit list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -reo_unit * reoUnitsGetNextUnit(reo_man * p ) -{ - reo_unit * pUnit; - // check there are stil units to extract - if ( p->pUnitFreeList == NULL ) - reoUnitsAddToFreeUnitList( p ); - // extract the next unit from the linked list - pUnit = p->pUnitFreeList; - p->pUnitFreeList = pUnit->Next; - p->nUnitsUsed++; - return pUnit; -} - -/**Function************************************************************* - - Synopsis [Returns the unit to the free unit list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit ) -{ - pUnit->Next = p->pUnitFreeList; - p->pUnitFreeList = pUnit; - p->nUnitsUsed--; -} - -/**Function************************************************************* - - Synopsis [Returns the list of units to the free unit list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane ) -{ - reo_unit * pUnit; - reo_unit * pTail; - - if ( pPlane->pHead == NULL ) - return; - - // find the tail - for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) - pTail = pUnit; - pTail->Next = p->pUnitFreeList; - p->pUnitFreeList = pPlane->pHead; - memset( pPlane, 0, sizeof(reo_plane) ); -} - -/**Function************************************************************* - - Synopsis [Stops the unit dispenser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoUnitsStopDispenser( reo_man * p ) -{ - int i; - for ( i = 0; i < p->nMemChunks; i++ ) - free( p->pMemChunks[i] ); -// printf("\nThe number of chunks used is %d, each of them %d units\n", p->nMemChunks, REO_CHUNK_SIZE ); - p->nMemChunks = 0; -} - -/**Function************************************************************* - - Synopsis [Adds one unit to the list of units which constitutes the plane.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit ) -{ - if ( pPlane->pHead == NULL ) - { - pPlane->pHead = pUnit; - pUnit->Next = NULL; - } - else - { - pUnit->Next = pPlane->pHead; - pPlane->pHead = pUnit; - } - pPlane->statsNodes++; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoUnitsAddToFreeUnitList( reo_man * p ) -{ - int c; - // check that we still have chunks left - if ( p->nMemChunks == p->nMemChunksAlloc ) - { - printf( "reoUnitsAddToFreeUnitList(): Memory manager ran out of memory!\n" ); - fflush( stdout ); - return; - } - // allocate the next chunk - assert( p->pUnitFreeList == NULL ); - p->pUnitFreeList = ALLOC( reo_unit, REO_CHUNK_SIZE ); - // split chunks into list-connected units - for ( c = 0; c < REO_CHUNK_SIZE-1; c++ ) - (p->pUnitFreeList + c)->Next = p->pUnitFreeList + c + 1; - // set the last pointer to NULL - (p->pUnitFreeList + REO_CHUNK_SIZE-1)->Next = NULL; - // add the chunk to the array of chunks - p->pMemChunks[p->nMemChunks++] = p->pUnitFreeList; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - |