From 6205eaaee3a840dd076f9baaac67720d85d6a680 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Thu, 13 Mar 2008 08:01:00 -0700 Subject: Version abc80313 --- src/aig/bdc/bdc.h | 2 +- src/aig/bdc/bdcCore.c | 128 ++++++++++++---- src/aig/bdc/bdcDec.c | 407 +++++++++++++++++++++++++++++++++++-------------- src/aig/bdc/bdcInt.h | 31 ++-- src/aig/bdc/bdcTable.c | 24 ++- 5 files changed, 432 insertions(+), 160 deletions(-) (limited to 'src/aig/bdc') diff --git a/src/aig/bdc/bdc.h b/src/aig/bdc/bdc.h index 71875edb..e0c35773 100644 --- a/src/aig/bdc/bdc.h +++ b/src/aig/bdc/bdc.h @@ -58,7 +58,7 @@ struct Bdc_Par_t_ /*=== bdcCore.c ==========================================================*/ extern Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ); extern void Bdc_ManFree( Bdc_Man_t * p ); -extern int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesLimit ); +extern int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesMax ); #ifdef __cplusplus diff --git a/src/aig/bdc/bdcCore.c b/src/aig/bdc/bdcCore.c index 157927b1..f0b0f3bc 100644 --- a/src/aig/bdc/bdcCore.c +++ b/src/aig/bdc/bdcCore.c @@ -42,15 +42,12 @@ Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ) { Bdc_Man_t * p; - unsigned * pData; - int i, k, nBits; p = ALLOC( Bdc_Man_t, 1 ); memset( p, 0, sizeof(Bdc_Man_t) ); assert( pPars->nVarsMax > 3 && pPars->nVarsMax < 16 ); p->pPars = pPars; p->nWords = Kit_TruthWordNum( pPars->nVarsMax ); p->nDivsLimit = 200; - p->nNodesLimit = 0; // will be set later // memory p->vMemory = Vec_IntStart( 1 << 16 ); // internal nodes @@ -62,22 +59,11 @@ Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ) memset( p->pTable, 0, sizeof(Bdc_Fun_t *) * p->nTableSize ); p->vSpots = Vec_IntAlloc( 256 ); // truth tables - p->vTruths = Vec_PtrAllocSimInfo( pPars->nVarsMax + 5, p->nWords ); - // set elementary truth tables - nBits = (1 << pPars->nVarsMax); - Kit_TruthFill( Vec_PtrEntry(p->vTruths, 0), p->nVars ); - for ( k = 0; k < pPars->nVarsMax; k++ ) - { - pData = Vec_PtrEntry( p->vTruths, k+1 ); - Kit_TruthClear( pData, p->nVars ); - for ( i = 0; i < nBits; i++ ) - if ( i & (1 << k) ) - pData[i>>5] |= (1 << (i&31)); - } - p->puTemp1 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 1 ); - p->puTemp2 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 2 ); - p->puTemp3 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 3 ); - p->puTemp4 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 4 ); + p->vTruths = Vec_PtrAllocTruthTables( p->pPars->nVarsMax ); + p->puTemp1 = ALLOC( unsigned, 4 * p->nWords ); + p->puTemp2 = p->puTemp1 + p->nWords; + p->puTemp3 = p->puTemp2 + p->nWords; + p->puTemp4 = p->puTemp3 + p->nWords; // start the internal ISFs p->pIsfOL = &p->IsfOL; Bdc_IsfStart( p, p->pIsfOL ); p->pIsfOR = &p->IsfOR; Bdc_IsfStart( p, p->pIsfOR ); @@ -102,6 +88,7 @@ void Bdc_ManFree( Bdc_Man_t * p ) Vec_IntFree( p->vMemory ); Vec_IntFree( p->vSpots ); Vec_PtrFree( p->vTruths ); + free( p->puTemp1 ); free( p->pNodes ); free( p->pTable ); free( p ); @@ -126,16 +113,25 @@ void Bdc_ManPrepare( Bdc_Man_t * p, Vec_Ptr_t * vDivs ) Bdc_TableClear( p ); Vec_IntClear( p->vMemory ); // add constant 1 and elementary vars - p->nNodes = p->nNodesNew = 0; - for ( i = 0; i <= p->pPars->nVarsMax; i++ ) + p->nNodes = 0; + p->nNodesNew = - 1 - p->nVars - (vDivs? Vec_PtrSize(vDivs) : 0); + // add constant 1 + pNode = Bdc_FunNew( p ); + pNode->Type = BDC_TYPE_CONST1; + pNode->puFunc = NULL; + pNode->uSupp = 0; + Bdc_TableAdd( p, pNode ); + // add variables + for ( i = 0; i < p->nVars; i++ ) { pNode = Bdc_FunNew( p ); pNode->Type = BDC_TYPE_PI; pNode->puFunc = Vec_PtrEntry( p->vTruths, i ); - pNode->uSupp = i? (1 << (i-1)) : 0; + pNode->uSupp = (1 << i); Bdc_TableAdd( p, pNode ); } // add the divisors + if ( vDivs ) Vec_PtrForEachEntry( vDivs, puTruth, i ) { pNode = Bdc_FunNew( p ); @@ -146,6 +142,40 @@ void Bdc_ManPrepare( Bdc_Man_t * p, Vec_Ptr_t * vDivs ) if ( i == p->nDivsLimit ) break; } + assert( p->nNodesNew == 0 ); +} + +/**Function************************************************************* + + Synopsis [Clears the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_ManDecPrint( Bdc_Man_t * p ) +{ + Bdc_Fun_t * pNode; + int i; + printf( " 0 : Const 1\n" ); + for ( i = 1; i < p->nNodes; i++ ) + { + printf( " %d : ", i ); + pNode = p->pNodes + i; + if ( pNode->Type == BDC_TYPE_PI ) + printf( "PI " ); + else + { + printf( "%s%d &", Bdc_IsComplement(pNode->pFan0)? "-":"", Bdc_FunId(p,Bdc_Regular(pNode->pFan0)) ); + printf( " %s%d ", Bdc_IsComplement(pNode->pFan1)? "-":"", Bdc_FunId(p,Bdc_Regular(pNode->pFan1)) ); + } + Extra_PrintBinary( stdout, pNode->puFunc, (1<nVars) ); + printf( "\n" ); + } + printf( "Root = %s%d.\n", Bdc_IsComplement(p->pRoot)? "-":"", Bdc_FunId(p,Bdc_Regular(p->pRoot)) ); } /**Function************************************************************* @@ -162,25 +192,67 @@ void Bdc_ManPrepare( Bdc_Man_t * p, Vec_Ptr_t * vDivs ) int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesMax ) { Bdc_Isf_t Isf, * pIsf = &Isf; + assert( nVars <= p->pPars->nVarsMax ); // set current manager parameters p->nVars = nVars; p->nWords = Kit_TruthWordNum( nVars ); + p->nNodesMax = nNodesMax; Bdc_ManPrepare( p, vDivs ); - p->nNodesLimit = (p->nNodes + nNodesMax < p->nNodesAlloc)? p->nNodes + nNodesMax : p->nNodesAlloc; // copy the function Bdc_IsfStart( p, pIsf ); - Bdc_IsfClean( pIsf ); - pIsf->uSupp = Kit_TruthSupport( puFunc, p->nVars ) | Kit_TruthSupport( puCare, p->nVars ); - Kit_TruthAnd( pIsf->puOn, puCare, puFunc, p->nVars ); - Kit_TruthSharp( pIsf->puOff, puCare, puFunc, p->nVars ); - // call decomposition + if ( puCare ) + { + Kit_TruthAnd( pIsf->puOn, puCare, puFunc, p->nVars ); + Kit_TruthSharp( pIsf->puOff, puCare, puFunc, p->nVars ); + } + else + { + Kit_TruthCopy( pIsf->puOn, puFunc, p->nVars ); + Kit_TruthNot( pIsf->puOff, puFunc, p->nVars ); + } Bdc_SuppMinimize( p, pIsf ); + // call decomposition p->pRoot = Bdc_ManDecompose_rec( p, pIsf ); if ( p->pRoot == NULL ) return -1; return p->nNodesNew; } +/**Function************************************************************* + + Synopsis [Performs decomposition of one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_ManDecomposeTest( unsigned uTruth, int nVars ) +{ + static int Counter = 0; + static int Total = 0; + Bdc_Par_t Pars = {0}, * pPars = &Pars; + Bdc_Man_t * p; + int RetValue; +// unsigned uCare = ~0x888f888f; + unsigned uCare = ~0; +// unsigned uFunc = 0x88888888; +// unsigned uFunc = 0xf888f888; +// unsigned uFunc = 0x117e117e; +// unsigned uFunc = 0x018b018b; + unsigned uFunc = uTruth; + + pPars->nVarsMax = 8; + p = Bdc_ManAlloc( pPars ); + RetValue = Bdc_ManDecompose( p, &uFunc, &uCare, nVars, NULL, 1000 ); + Total += RetValue; + printf( "%5d : Nodes = %5d. Total = %8d.\n", ++Counter, RetValue, Total ); +// Bdc_ManDecPrint( p ); + Bdc_ManFree( p ); +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/aig/bdc/bdcDec.c b/src/aig/bdc/bdcDec.c index 747fcb14..13a33196 100644 --- a/src/aig/bdc/bdcDec.c +++ b/src/aig/bdc/bdcDec.c @@ -24,73 +24,10 @@ /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -static Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ); -static int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, unsigned * puTruth, Bdc_Type_t Type ); - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// -/**Function************************************************************* - - Synopsis [Performs one step of bi-decomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) -{ - Bdc_Fun_t * pFunc; - Bdc_Isf_t IsfL, * pIsfL = &IsfL; - Bdc_Isf_t IsfB, * pIsfR = &IsfB; - // check computed results - if ( pFunc = Bdc_TableLookup( p, pIsf ) ) - return pFunc; - // decide on the decomposition type - pFunc = Bdc_FunNew( p ); - if ( pFunc == NULL ) - return NULL; - pFunc->Type = Bdc_DecomposeStep( p, pIsf, pIsfL, pIsfR ); - // decompose the left branch - pFunc->pFan0 = Bdc_ManDecompose_rec( p, pIsfL ); - if ( pFunc->pFan0 == NULL ) - return NULL; - // decompose the right branch - if ( Bdc_DecomposeUpdateRight( p, pIsf, pIsfL, pIsfR, pFunc->pFan0->puFunc, pFunc->Type ) ) - { - p->nNodes--; - return pFunc->pFan0; - } - pFunc->pFan1 = Bdc_ManDecompose_rec( p, pIsfL ); - if ( pFunc->pFan1 == NULL ) - return NULL; - // compute the function of node - pFunc->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); - if ( pFunc->Type == BDC_TYPE_AND ) - Kit_TruthAnd( pFunc->puFunc, pFunc->pFan0->puFunc, pFunc->pFan1->puFunc, p->nVars ); - else if ( pFunc->Type == BDC_TYPE_OR ) - Kit_TruthOr( pFunc->puFunc, pFunc->pFan0->puFunc, pFunc->pFan1->puFunc, p->nVars ); - else - assert( 0 ); - // verify correctness - assert( Bdc_TableCheckContainment(p, pIsf, pFunc->puFunc) ); - // convert from OR to AND - if ( pFunc->Type == BDC_TYPE_OR ) - { - pFunc->Type = BDC_TYPE_AND; - pFunc->pFan0 = Bdc_Not(pFunc->pFan0); - pFunc->pFan1 = Bdc_Not(pFunc->pFan1); - Kit_TruthNot( pFunc->puFunc, pFunc->puFunc, p->nVars ); - pFunc = Bdc_Not(pFunc); - } - Bdc_TableAdd( p, Bdc_Regular(pFunc) ); - return pFunc; -} - /**Function************************************************************* Synopsis [Updates the ISF of the right after the left was decompoosed.] @@ -102,8 +39,15 @@ Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) SeeAlso [] ***********************************************************************/ -int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, unsigned * puTruth, Bdc_Type_t Type ) +int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, Bdc_Fun_t * pFunc0, Bdc_Type_t Type ) { + unsigned * puTruth = p->puTemp1; + // get the truth table of the left branch + if ( Bdc_IsComplement(pFunc0) ) + Kit_TruthNot( puTruth, Bdc_Regular(pFunc0)->puFunc, p->nVars ); + else + Kit_TruthCopy( puTruth, pFunc0->puFunc, p->nVars ); + // split into parts if ( Type == BDC_TYPE_OR ) { // Right.Q = bdd_appex( Q, CompSpecLeftF, bddop_diff, setRightRes ); @@ -118,8 +62,9 @@ int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL // return (int)( pR->Q == b0 ); Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars ); - Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp ); - Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uSupp ); + Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uUniq ); + Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uUniq ); +// assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); return Kit_TruthIsConst0(pIsfR->puOn, p->nVars); } @@ -136,11 +81,12 @@ int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL // assert( pR->Q != b0 ); // return (int)( pR->R == b0 ); - Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars ); - Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp ); - Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uSupp ); - assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); - return Kit_TruthIsConst0(pIsfR->puOn, p->nVars); + Kit_TruthAnd( pIsfR->puOff, pIsf->puOff, puTruth, p->nVars ); + Kit_TruthExistSet( pIsfR->puOff, pIsfR->puOff, p->nVars, pIsfL->uUniq ); + Kit_TruthExistSet( pIsfR->puOn, pIsf->puOn, p->nVars, pIsfL->uUniq ); +// assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); + assert( !Kit_TruthIsConst0(pIsfR->puOn, p->nVars) ); + return Kit_TruthIsConst0(pIsfR->puOff, p->nVars); } return 0; } @@ -201,10 +147,8 @@ int Bdc_DecomposeFindInitialVarSet( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pVars[End] ); if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp1, p->puTemp2, p->nVars) ) { - pIsfL->uSupp = (1 << Beg); - pIsfR->uSupp = (1 << End); - pIsfL->Var = Beg; - pIsfR->Var = End; + pIsfL->uUniq = (1 << pVars[Beg]); + pIsfR->uUniq = (1 << pVars[End]); return 1; } } @@ -229,15 +173,17 @@ int Bdc_DecomposeWeakOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc for ( v = 0; v < p->nVars; v++ ) { - Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, v ); + if ( (pIsf->uSupp & (1 << v)) == 0 ) + continue; // if ( (Q & !bdd_exist( R, VarSetXa )) != bddfalse ) // Exist = Cudd_bddExistAbstract( dd, pF->R, Var ); Cudd_Ref( Exist ); // if ( Cudd_bddIteConstant( dd, pF->Q, Cudd_Not(Exist), b0 ) != b0 ) + + Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, v ); if ( !Kit_TruthIsImply( pIsf->puOn, p->puTemp1, p->nVars ) ) { // measure the cost of this variable // VarCost = bdd_satcountset( bdd_forall( Q, VarSetXa ), VarCube ); - // Univ = Cudd_bddUnivAbstract( dd, pF->Q, Var ); Cudd_Ref( Univ ); // VarCost = Kit_TruthCountOnes( Univ, p->nVars ); // Cudd_RecursiveDeref( dd, Univ ); @@ -258,7 +204,6 @@ int Bdc_DecomposeWeakOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc if ( VarCostBest ) { // funQLeftRes = Q & bdd_exist( R, setRightORweak ); - // Temp = Cudd_bddExistAbstract( dd, pF->R, VarBest ); Cudd_Ref( Temp ); // pL->Q = Cudd_bddAnd( dd, pF->Q, Temp ); Cudd_Ref( pL->Q ); // Cudd_RecursiveDeref( dd, Temp ); @@ -269,11 +214,13 @@ int Bdc_DecomposeWeakOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc // pL->R = pF->R; Cudd_Ref( pL->R ); // pL->V = VarBest; Cudd_Ref( pL->V ); Kit_TruthCopy( pIsfL->puOff, pIsf->puOff, p->nVars ); - pIsfL->Var = VarBest; + pIsfL->uUniq = (1 << VarBest); + pIsfR->uUniq = 0; // assert( pL->Q != b0 ); // assert( pL->R != b0 ); // assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); +// assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) ); // express cost in percents of the covered boolean space Cost = VarCostBest * BDC_SCALE / (1<nVars); @@ -297,23 +244,25 @@ int Bdc_DecomposeWeakOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc ***********************************************************************/ int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) { - unsigned uSuppRem; + unsigned uSupportRem; int v, nLeftVars = 1, nRightVars = 1; // clean the var sets - Bdc_IsfClean( pIsfL ); - Bdc_IsfClean( pIsfR ); + Bdc_IsfStart( p, pIsfL ); + Bdc_IsfStart( p, pIsfR ); + // check that the support is correct + assert( Kit_TruthSupport(pIsf->puOn, p->nVars) == Kit_TruthSupport(pIsf->puOff, p->nVars) ); + assert( pIsf->uSupp == Kit_TruthSupport(pIsf->puOn, p->nVars) ); // find initial variable sets if ( !Bdc_DecomposeFindInitialVarSet( p, pIsf, pIsfL, pIsfR ) ) return Bdc_DecomposeWeakOr( p, pIsf, pIsfL, pIsfR ); // prequantify the variables in the offset - Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pIsfL->Var ); - Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pIsfR->Var ); + Kit_TruthExistSet( p->puTemp1, pIsf->puOff, p->nVars, pIsfL->uUniq ); + Kit_TruthExistSet( p->puTemp2, pIsf->puOff, p->nVars, pIsfR->uUniq ); // go through the remaining variables - uSuppRem = pIsf->uSupp & ~pIsfL->uSupp & ~pIsfR->uSupp; - assert( Kit_WordCountOnes(uSuppRem) > 0 ); + uSupportRem = pIsf->uSupp & ~pIsfL->uUniq & ~pIsfR->uUniq; for ( v = 0; v < p->nVars; v++ ) { - if ( (uSuppRem & (1 << v)) == 0 ) + if ( (uSupportRem & (1 << v)) == 0 ) continue; // prequantify this variable Kit_TruthExistNew( p->puTemp3, p->puTemp1, p->nVars, v ); @@ -325,15 +274,17 @@ int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) ) { // pL->V &= VarNew; - pIsfL->uSupp |= (1 << v); + pIsfL->uUniq |= (1 << v); nLeftVars++; + Kit_TruthCopy( p->puTemp1, p->puTemp3, p->nVars ); } // else if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse ) else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) ) { // pR->V &= VarNew; - pIsfR->uSupp |= (1 << v); + pIsfR->uUniq |= (1 << v); nRightVars++; + Kit_TruthCopy( p->puTemp2, p->puTemp4, p->nVars ); } } else @@ -342,15 +293,17 @@ int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) ) { // pR->V &= VarNew; - pIsfR->uSupp |= (1 << v); + pIsfR->uUniq |= (1 << v); nRightVars++; + Kit_TruthCopy( p->puTemp2, p->puTemp4, p->nVars ); } // else if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse ) else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) ) { // pL->V &= VarNew; - pIsfL->uSupp |= (1 << v); + pIsfL->uUniq |= (1 << v); nLeftVars++; + Kit_TruthCopy( p->puTemp1, p->puTemp3, p->nVars ); } } } @@ -365,28 +318,32 @@ int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf // pL->R = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( pL->R ); Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars ); - Kit_TruthExistSet( pIsfL->puOn, pIsfL->puOn, p->nVars, pIsfR->uSupp ); + Kit_TruthExistSet( pIsfL->puOn, pIsfL->puOn, p->nVars, pIsfR->uUniq ); Kit_TruthCopy( pIsfL->puOff, p->puTemp2, p->nVars ); +// assert( pL->Q != b0 ); +// assert( pL->R != b0 ); +// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); + assert( !Kit_TruthIsConst0(pIsfL->puOn, p->nVars) ); + assert( !Kit_TruthIsConst0(pIsfL->puOff, p->nVars) ); +// assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) ); + // derive the functions Q and R for the right branch // Temp = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( Temp ); // pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pL->V ); Cudd_Ref( pR->Q ); // Cudd_RecursiveDeref( dd, Temp ); // pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R ); -/* Kit_TruthAnd( pIsfR->puOn, pIsf->puOn, p->puTemp2, p->nVars ); - Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp ); + Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uUniq ); Kit_TruthCopy( pIsfR->puOff, p->puTemp1, p->nVars ); -*/ -// assert( pL->Q != b0 ); -// assert( pL->R != b0 ); -// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); - assert( !Kit_TruthIsConst0(pIsfL->puOn, p->nVars) ); - assert( !Kit_TruthIsConst0(pIsfL->puOff, p->nVars) ); - assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) ); + assert( !Kit_TruthIsConst0(pIsfR->puOn, p->nVars) ); + assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); +// assert( Kit_TruthIsDisjoint(pIsfR->puOn, pIsfR->puOff, p->nVars) ); + assert( pIsfL->uUniq ); + assert( pIsfR->uUniq ); return Bdc_DecomposeGetCost( p, nLeftVars, nRightVars ); } @@ -403,7 +360,7 @@ int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf ***********************************************************************/ Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) { - int CostOr, CostAnd, CostOrL, CostOrR, CostAndL, CostAndR; + int WeightOr, WeightAnd, WeightOrL, WeightOrR, WeightAndL, WeightAndR; Bdc_IsfClean( p->pIsfOL ); Bdc_IsfClean( p->pIsfOR ); @@ -411,33 +368,61 @@ Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL Bdc_IsfClean( p->pIsfAR ); // perform OR decomposition - CostOr = Bdc_DecomposeOr( p, pIsf, p->pIsfOL, p->pIsfOR ); + WeightOr = Bdc_DecomposeOr( p, pIsf, p->pIsfOL, p->pIsfOR ); // perform AND decomposition Bdc_IsfNot( pIsf ); - CostAnd = Bdc_DecomposeOr( p, pIsf, p->pIsfAL, p->pIsfAR ); + WeightAnd = Bdc_DecomposeOr( p, pIsf, p->pIsfAL, p->pIsfAR ); Bdc_IsfNot( pIsf ); Bdc_IsfNot( p->pIsfAL ); Bdc_IsfNot( p->pIsfAR ); + // check the case when decomposition does not exist + if ( WeightOr == 0 && WeightAnd == 0 ) + { + Bdc_IsfCopy( pIsfL, p->pIsfOL ); + Bdc_IsfCopy( pIsfR, p->pIsfOR ); + return BDC_TYPE_MUX; + } // check the hash table - Bdc_SuppMinimize( p, p->pIsfOL ); - CostOrL = (Bdc_TableLookup(p, p->pIsfOL) != NULL); - Bdc_SuppMinimize( p, p->pIsfOR ); - CostOrR = (Bdc_TableLookup(p, p->pIsfOR) != NULL); - Bdc_SuppMinimize( p, p->pIsfAL ); - CostAndL = (Bdc_TableLookup(p, p->pIsfAL) != NULL); - Bdc_SuppMinimize( p, p->pIsfAR ); - CostAndR = (Bdc_TableLookup(p, p->pIsfAR) != NULL); + assert( WeightOr || WeightAnd ); + WeightOrL = WeightOrR = 0; + if ( WeightOr ) + { + if ( p->pIsfOL->uUniq ) + { + Bdc_SuppMinimize( p, p->pIsfOL ); + WeightOrL = (Bdc_TableLookup(p, p->pIsfOL) != NULL); + } + if ( p->pIsfOR->uUniq ) + { + Bdc_SuppMinimize( p, p->pIsfOR ); + WeightOrR = (Bdc_TableLookup(p, p->pIsfOR) != NULL); + } + } + WeightAndL = WeightAndR = 0; + if ( WeightAnd ) + { + if ( p->pIsfAL->uUniq ) + { + Bdc_SuppMinimize( p, p->pIsfAL ); + WeightAndL = (Bdc_TableLookup(p, p->pIsfAL) != NULL); + } + if ( p->pIsfAR->uUniq ) + { + Bdc_SuppMinimize( p, p->pIsfAR ); + WeightAndR = (Bdc_TableLookup(p, p->pIsfAR) != NULL); + } + } // check if there is any reuse for the components - if ( CostOrL + CostOrR < CostAndL + CostAndR ) + if ( WeightOrL + WeightOrR > WeightAndL + WeightAndR ) { Bdc_IsfCopy( pIsfL, p->pIsfOL ); Bdc_IsfCopy( pIsfR, p->pIsfOR ); return BDC_TYPE_OR; } - if ( CostOrL + CostOrR > CostAndL + CostAndR ) + if ( WeightOrL + WeightOrR < WeightAndL + WeightAndR ) { Bdc_IsfCopy( pIsfL, p->pIsfAL ); Bdc_IsfCopy( pIsfR, p->pIsfAR ); @@ -445,15 +430,207 @@ Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL } // compare the two-component costs - if ( CostOr < CostAnd ) + if ( WeightOr > WeightAnd ) { Bdc_IsfCopy( pIsfL, p->pIsfOL ); Bdc_IsfCopy( pIsfR, p->pIsfOR ); return BDC_TYPE_OR; } + Bdc_IsfCopy( pIsfL, p->pIsfAL ); + Bdc_IsfCopy( pIsfR, p->pIsfAR ); return BDC_TYPE_AND; } +/**Function************************************************************* + + Synopsis [Find variable that leads to minimum sum of support sizes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_DecomposeStepMux( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) +{ + int Var, VarMin, nSuppMin, nSuppCur; + unsigned uSupp0, uSupp1; + VarMin = -1; + nSuppMin = 1000; + for ( Var = 0; Var < p->nVars; Var++ ) + { + if ( (pIsf->uSupp & (1 << Var)) == 0 ) + continue; + Kit_TruthCofactor0New( pIsfL->puOn, pIsf->puOn, p->nVars, Var ); + Kit_TruthCofactor0New( pIsfL->puOff, pIsf->puOff, p->nVars, Var ); + Kit_TruthCofactor1New( pIsfR->puOn, pIsf->puOn, p->nVars, Var ); + Kit_TruthCofactor1New( pIsfR->puOff, pIsf->puOff, p->nVars, Var ); + uSupp0 = Kit_TruthSupport( pIsfL->puOn, p->nVars ) & Kit_TruthSupport( pIsfL->puOff, p->nVars ); + uSupp1 = Kit_TruthSupport( pIsfR->puOn, p->nVars ) & Kit_TruthSupport( pIsfR->puOff, p->nVars ); + nSuppCur = Kit_WordCountOnes(uSupp0) + Kit_WordCountOnes(uSupp1); + if ( nSuppMin > nSuppCur ) + { + nSuppMin = nSuppCur; + VarMin = Var; +// break; + } + } + if ( VarMin >= 0 ) + { + Kit_TruthCofactor0New( pIsfL->puOn, pIsf->puOn, p->nVars, VarMin ); + Kit_TruthCofactor0New( pIsfL->puOff, pIsf->puOff, p->nVars, VarMin ); + Kit_TruthCofactor1New( pIsfR->puOn, pIsf->puOn, p->nVars, VarMin ); + Kit_TruthCofactor1New( pIsfR->puOff, pIsf->puOff, p->nVars, VarMin ); + Bdc_SuppMinimize( p, pIsfL ); + Bdc_SuppMinimize( p, pIsfR ); + } + return VarMin; +} + +/**Function************************************************************* + + Synopsis [Creates gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_ManNodeVerify( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Fun_t * pFunc ) +{ + unsigned * puTruth = p->puTemp1; + if ( Bdc_IsComplement(pFunc) ) + Kit_TruthNot( puTruth, Bdc_Regular(pFunc)->puFunc, p->nVars ); + else + Kit_TruthCopy( puTruth, pFunc->puFunc, p->nVars ); + return Bdc_TableCheckContainment( p, pIsf, puTruth ); +} + +/**Function************************************************************* + + Synopsis [Creates gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bdc_Fun_t * Bdc_ManCreateGate( Bdc_Man_t * p, Bdc_Fun_t * pFunc0, Bdc_Fun_t * pFunc1, Bdc_Type_t Type ) +{ + Bdc_Fun_t * pFunc; + pFunc = Bdc_FunNew( p ); + if ( pFunc == NULL ) + return NULL; + pFunc->Type = Type; + pFunc->pFan0 = pFunc0; + pFunc->pFan1 = pFunc1; + pFunc->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); + // get the truth table of the left branch + if ( Bdc_IsComplement(pFunc0) ) + Kit_TruthNot( p->puTemp1, Bdc_Regular(pFunc0)->puFunc, p->nVars ); + else + Kit_TruthCopy( p->puTemp1, pFunc0->puFunc, p->nVars ); + // get the truth table of the right branch + if ( Bdc_IsComplement(pFunc1) ) + Kit_TruthNot( p->puTemp2, Bdc_Regular(pFunc1)->puFunc, p->nVars ); + else + Kit_TruthCopy( p->puTemp2, pFunc1->puFunc, p->nVars ); + // compute the function of node + if ( pFunc->Type == BDC_TYPE_AND ) + { + Kit_TruthAnd( pFunc->puFunc, p->puTemp1, p->puTemp2, p->nVars ); + } + else if ( pFunc->Type == BDC_TYPE_OR ) + { + Kit_TruthOr( pFunc->puFunc, p->puTemp1, p->puTemp2, p->nVars ); + // transform to AND gate + pFunc->Type = BDC_TYPE_AND; + pFunc->pFan0 = Bdc_Not(pFunc->pFan0); + pFunc->pFan1 = Bdc_Not(pFunc->pFan1); + Kit_TruthNot( pFunc->puFunc, pFunc->puFunc, p->nVars ); + pFunc = Bdc_Not(pFunc); + } + else + assert( 0 ); + // add to table + Bdc_Regular(pFunc)->uSupp = Kit_TruthSupport( Bdc_Regular(pFunc)->puFunc, p->nVars ); + Bdc_TableAdd( p, Bdc_Regular(pFunc) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Performs one step of bi-decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) +{ + int static Counter = 0; + int LocalCounter = Counter++; + Bdc_Type_t Type; + Bdc_Fun_t * pFunc, * pFunc0, * pFunc1; + Bdc_Isf_t IsfL, * pIsfL = &IsfL; + Bdc_Isf_t IsfB, * pIsfR = &IsfB; +/* +printf( "Init function (%d):\n", LocalCounter ); +Extra_PrintBinary( stdout, pIsf->puOn, 1<<4 );printf("\n"); +Extra_PrintBinary( stdout, pIsf->puOff, 1<<4 );printf("\n"); +*/ + // check computed results + assert( Kit_TruthIsDisjoint(pIsf->puOn, pIsf->puOff, p->nVars) ); + if ( pFunc = Bdc_TableLookup( p, pIsf ) ) + return pFunc; + // decide on the decomposition type + Type = Bdc_DecomposeStep( p, pIsf, pIsfL, pIsfR ); + if ( Type == BDC_TYPE_MUX ) + { + int iVar = Bdc_DecomposeStepMux( p, pIsf, pIsfL, pIsfR ); + pFunc0 = Bdc_ManDecompose_rec( p, pIsfL ); + pFunc1 = Bdc_ManDecompose_rec( p, pIsfR ); + if ( pFunc0 == NULL || pFunc1 == NULL ) + return NULL; + pFunc = Bdc_FunWithId( p, iVar + 1 ); + pFunc0 = Bdc_ManCreateGate( p, Bdc_Not(pFunc), pFunc0, BDC_TYPE_AND ); + pFunc1 = Bdc_ManCreateGate( p, pFunc, pFunc1, BDC_TYPE_AND ); + if ( pFunc0 == NULL || pFunc1 == NULL ) + return NULL; + pFunc = Bdc_ManCreateGate( p, pFunc0, pFunc1, BDC_TYPE_OR ); + } + else + { + pFunc0 = Bdc_ManDecompose_rec( p, pIsfL ); + if ( pFunc0 == NULL ) + return NULL; + // decompose the right branch + if ( Bdc_DecomposeUpdateRight( p, pIsf, pIsfL, pIsfR, pFunc0, Type ) ) + { + p->nNodesNew--; + return pFunc0; + } + Bdc_SuppMinimize( p, pIsfR ); + pFunc1 = Bdc_ManDecompose_rec( p, pIsfR ); + if ( pFunc1 == NULL ) + return NULL; + // create new gate + pFunc = Bdc_ManCreateGate( p, pFunc0, pFunc1, Type ); + } + if ( pFunc == NULL ) + return NULL; + assert( Bdc_ManNodeVerify( p, pIsf, pFunc ) ); + return pFunc; +} + //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// diff --git a/src/aig/bdc/bdcInt.h b/src/aig/bdc/bdcInt.h index 5f7b1186..5fda4301 100644 --- a/src/aig/bdc/bdcInt.h +++ b/src/aig/bdc/bdcInt.h @@ -36,7 +36,7 @@ extern "C" { /// PARAMETERS /// //////////////////////////////////////////////////////////////////////// -#define BDC_SCALE 100 // value used to compute the cost +#define BDC_SCALE 1000 // value used to compute the cost //////////////////////////////////////////////////////////////////////// /// BASIC TYPES /// @@ -47,11 +47,11 @@ typedef enum { BDC_TYPE_NONE = 0, // 0: unknown BDC_TYPE_CONST1, // 1: constant 1 BDC_TYPE_PI, // 2: primary input - BDC_TYPE_AND, // 4: AND-gate - BDC_TYPE_OR, // 5: OR-gate (temporary) - BDC_TYPE_XOR, // 6: XOR-gate - BDC_TYPE_MUX, // 7: MUX-gate - BDC_TYPE_OTHER // 8: unused + BDC_TYPE_AND, // 3: AND-gate + BDC_TYPE_OR, // 4: OR-gate (temporary) + BDC_TYPE_XOR, // 5: XOR-gate + BDC_TYPE_MUX, // 6: MUX-gate + BDC_TYPE_OTHER // 7: unused } Bdc_Type_t; typedef struct Bdc_Fun_t_ Bdc_Fun_t; @@ -60,7 +60,6 @@ struct Bdc_Fun_t_ int Type; // Const1, PI, AND, XOR, MUX Bdc_Fun_t * pFan0; // fanin of the given node Bdc_Fun_t * pFan1; // fanin of the given node - Bdc_Fun_t * pFan2; // fanin of the given node unsigned uSupp; // bit mask of current support unsigned * puFunc; // the function of the node Bdc_Fun_t * pNext; // next function with same support @@ -70,8 +69,8 @@ struct Bdc_Fun_t_ typedef struct Bdc_Isf_t_ Bdc_Isf_t; struct Bdc_Isf_t_ { - int Var; // the first variable assigned - unsigned uSupp; // the current support + unsigned uSupp; // the complete support of this component + unsigned uUniq; // the unique variables of this component unsigned * puOn; // on-set unsigned * puOff; // off-set }; @@ -82,13 +81,13 @@ struct Bdc_Man_t_ Bdc_Par_t * pPars; // parameter set int nVars; // the number of variables int nWords; // the number of words - int nNodesLimit; // the limit on the number of new nodes + int nNodesMax; // the limit on the number of new nodes int nDivsLimit; // the limit on the number of divisors // internal nodes Bdc_Fun_t * pNodes; // storage for decomposition nodes - int nNodes; // the number of nodes used - int nNodesNew; // the number of nodes used int nNodesAlloc; // the number of nodes allocated + int nNodes; // the number of all nodes created so far + int nNodesNew; // the number of new AND nodes created so far Bdc_Fun_t * pRoot; // the root node // resub candidates Bdc_Fun_t ** pTable; // hash table of candidates @@ -115,9 +114,11 @@ static inline Bdc_Fun_t * Bdc_Regular( Bdc_Fun_t * p ) { return static inline Bdc_Fun_t * Bdc_Not( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((PORT_PTRUINT_T)p ^ (PORT_PTRUINT_T)01); } static inline Bdc_Fun_t * Bdc_NotCond( Bdc_Fun_t * p, int c ) { return (Bdc_Fun_t *)((PORT_PTRUINT_T)p ^ (PORT_PTRUINT_T)(c!=0)); } -static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes == p->nNodesLimit ) return NULL; pRes = p->pNodes + p->nNodes++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); p->nNodesNew++; return pRes; } -static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); } -static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->Var = 0; } +static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes >= p->nNodesAlloc || p->nNodesNew >= p->nNodesMax ) return NULL; pRes = p->pNodes + p->nNodes++; p->nNodesNew++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); return pRes; } +static inline Bdc_Fun_t * Bdc_FunWithId( Bdc_Man_t * p, int Id ) { assert( Id < p->nNodes ); return p->pNodes + Id; } +static inline int Bdc_FunId( Bdc_Man_t * p, Bdc_Fun_t * pFun ) { return pFun - p->pNodes; } +static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->uSupp = 0; pF->uUniq = 0; pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); } +static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->uUniq = 0; } static inline void Bdc_IsfCopy( Bdc_Isf_t * p, Bdc_Isf_t * q ) { Bdc_Isf_t T = *p; *p = *q; *q = T; } static inline void Bdc_IsfNot( Bdc_Isf_t * p ) { unsigned * puT = p->puOn; p->puOn = p->puOff; p->puOff = puT; } diff --git a/src/aig/bdc/bdcTable.c b/src/aig/bdc/bdcTable.c index d86a938d..b7f10344 100644 --- a/src/aig/bdc/bdcTable.c +++ b/src/aig/bdc/bdcTable.c @@ -42,6 +42,9 @@ void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) { int v; + // compute support + pIsf->uSupp = Kit_TruthSupport( pIsf->puOn, p->nVars ) | + Kit_TruthSupport( pIsf->puOff, p->nVars ); // go through the support variables for ( v = 0; v < p->nVars; v++ ) { @@ -72,7 +75,7 @@ void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth ) { return Kit_TruthIsImply( pIsf->puOn, puTruth, p->nVars ) && - Kit_TruthIsDisjoint( pIsf->puOff, puTruth, p->nVars ); + Kit_TruthIsDisjoint( puTruth, pIsf->puOff, p->nVars ); } /**Function************************************************************* @@ -88,10 +91,29 @@ int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTru ***********************************************************************/ Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) { + int fDisableCache = 0; Bdc_Fun_t * pFunc; + if ( fDisableCache && Kit_WordCountOnes(pIsf->uSupp) > 1 ) + return NULL; + if ( pIsf->uSupp == 0 ) + { + assert( p->pTable[pIsf->uSupp] == p->pNodes ); + if ( Kit_TruthIsConst1( pIsf->puOn, p->nVars ) ) + return p->pNodes; + assert( Kit_TruthIsConst1( pIsf->puOff, p->nVars ) ); + return Bdc_Not(p->pNodes); + } for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext ) if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) ) return pFunc; + Bdc_IsfNot( pIsf ); + for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext ) + if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) ) + { + Bdc_IsfNot( pIsf ); + return Bdc_Not(pFunc); + } + Bdc_IsfNot( pIsf ); return NULL; } -- cgit v1.2.3