diff options
Diffstat (limited to 'src/sat')
52 files changed, 7999 insertions, 288 deletions
diff --git a/src/sat/bmc/bmc.h b/src/sat/bmc/bmc.h index 30538253..a3f353c2 100644 --- a/src/sat/bmc/bmc.h +++ b/src/sat/bmc/bmc.h @@ -164,7 +164,8 @@ extern int Saig_ManBmcScalable( Aig_Man_t * pAig, Saig_ParBmc_t * extern int Gia_ManBmcPerform( Gia_Man_t * p, Bmc_AndPar_t * pPars ); /*=== bmcCexCare.c ==========================================================*/ extern Abc_Cex_t * Bmc_CexCareExtendToObjects( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ); -extern Abc_Cex_t * Bmc_CexCareMinimize( Aig_Man_t * p, Abc_Cex_t * pCex, int fCheck, int fVerbose ); +extern Abc_Cex_t * Bmc_CexCareMinimize( Aig_Man_t * p, int nRealPis, Abc_Cex_t * pCex, int nTryCexes, int fCheck, int fVerbose ); +extern Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, int nRealPis, Abc_Cex_t * pCex, int nTryCexes, int fCheck, int fVerbose ); extern void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, int fVerbose ); /*=== bmcCexCut.c ==========================================================*/ extern Gia_Man_t * Bmc_GiaTargetStates( Gia_Man_t * p, Abc_Cex_t * pCex, int iFrBeg, int iFrEnd, int fCombOnly, int fGenAll, int fAllFrames, int fVerbose ); @@ -172,7 +173,7 @@ extern Aig_Man_t * Bmc_AigTargetStates( Aig_Man_t * p, Abc_Cex_t * pCex, i /*=== bmcCexMin.c ==========================================================*/ extern Abc_Cex_t * Saig_ManCexMinPerform( Aig_Man_t * pAig, Abc_Cex_t * pCex ); /*=== bmcCexTool.c ==========================================================*/ -extern void Bmc_CexPrint( Abc_Cex_t * pCex, int nInputs, int fVerbose ); +extern void Bmc_CexPrint( Abc_Cex_t * pCex, int nRealPis, int fVerbose ); extern int Bmc_CexVerify( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexCare ); /*=== bmcICheck.c ==========================================================*/ extern void Bmc_PerformICheck( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fEmpty, int fVerbose ); diff --git a/src/sat/bmc/bmcBmcAnd.c b/src/sat/bmc/bmcBmcAnd.c index 8087046a..3490d34f 100644 --- a/src/sat/bmc/bmcBmcAnd.c +++ b/src/sat/bmc/bmcBmcAnd.c @@ -986,8 +986,7 @@ int Gia_ManBmcPerformInt( Gia_Man_t * pGia, Bmc_AndPar_t * pPars ) { // p->pFrames = Jf_ManDeriveCnf( pTemp = p->pFrames, 1 ); Gia_ManStop( pTemp ); // p->pCnf = (Cnf_Dat_t *)p->pFrames->pData; p->pFrames->pData = NULL; - extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); - p->pCnf = Mf_ManGenerateCnf( p->pFrames, pPars->nLutSize, 1, 0, pPars->fVerbose ); + p->pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p->pFrames, pPars->nLutSize, 1, 0, 0, pPars->fVerbose ); } Vec_IntFillExtra( p->vId2Var, Gia_ManObjNum(p->pFrames), 0 ); // create clauses for constant node diff --git a/src/sat/bmc/bmcCexCare.c b/src/sat/bmc/bmcCexCare.c index 21fea429..cc3e85ea 100644 --- a/src/sat/bmc/bmcCexCare.c +++ b/src/sat/bmc/bmcCexCare.c @@ -88,7 +88,7 @@ Abc_Cex_t * Bmc_CexCareExtendToObjects( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex /**Function************************************************************* - Synopsis [Backward propagation.] + Synopsis [Forward propagation.] Description [] @@ -97,21 +97,14 @@ Abc_Cex_t * Bmc_CexCareExtendToObjects( Gia_Man_t * p, Abc_Cex_t * pCex, Abc_Cex SeeAlso [] ***********************************************************************/ -void Bmc_CexCarePropagateFwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, int fGrow ) +void Bmc_CexCarePropagateFwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, Vec_Int_t * vPriosIn ) { Gia_Obj_t * pObj; int Prio, Prio0, Prio1; int i, Phase0, Phase1; - if ( (fGrow & 2) ) - { - Gia_ManForEachPi( p, pObj, i ) - pObj->Value = Abc_Var2Lit( f * pCex->nPis + (pCex->nPis-1-i) + 1, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) ); - } - else - { - Gia_ManForEachPi( p, pObj, i ) - pObj->Value = Abc_Var2Lit( f * pCex->nPis + i + 1, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i) ); - } + assert( Vec_IntSize(vPriosIn) == pCex->nPis * (pCex->iFrame + 1) ); + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Vec_IntEntry( vPriosIn, f * pCex->nPis + i ); Gia_ManForEachAnd( p, pObj, i ) { Prio0 = Abc_Lit2Var(Gia_ObjFanin0(pObj)->Value); @@ -119,37 +112,38 @@ void Bmc_CexCarePropagateFwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, int fGr Phase0 = Abc_LitIsCompl(Gia_ObjFanin0(pObj)->Value) ^ Gia_ObjFaninC0(pObj); Phase1 = Abc_LitIsCompl(Gia_ObjFanin1(pObj)->Value) ^ Gia_ObjFaninC1(pObj); if ( Phase0 && Phase1 ) - Prio = (fGrow & 1) ? Abc_MinInt(Prio0, Prio1) : Abc_MaxInt(Prio0, Prio1); - else if ( Phase0 && !Phase1 ) + Prio = Abc_MinInt(Prio0, Prio1); + else if ( Phase0 ) Prio = Prio1; - else if ( !Phase0 && Phase1 ) + else if ( Phase1 ) Prio = Prio0; else // if ( !Phase0 && !Phase1 ) - Prio = (fGrow & 1) ? Abc_MaxInt(Prio0, Prio1) : Abc_MinInt(Prio0, Prio1); - pObj->Value = Abc_Var2Lit( Prio, Phase0 & Phase1 ); + Prio = Abc_MaxInt(Prio0, Prio1); + pObj->Value = Abc_Var2Lit( Prio, Phase0 && Phase1 ); + pObj->fPhase = 0; } Gia_ManForEachCo( p, pObj, i ) pObj->Value = Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); } -void Bmc_CexCarePropagateFwd( Gia_Man_t * p, Abc_Cex_t * pCex, int fGrow, Vec_Int_t * vPrios ) +void Bmc_CexCarePropagateFwd( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vPriosIn, Vec_Int_t * vPriosFf ) { - Gia_Obj_t * pObj, * pObjRo, * pObjRi; - int f, i; - Gia_ManConst0( p )->Value = 0; - Gia_ManForEachRi( p, pObj, i ) - pObj->Value = 0; - Vec_IntClear( vPrios ); + Gia_Obj_t * pObjRo, * pObjRi; + int i, f, ValueMax = Abc_Var2Lit( pCex->nPis * (pCex->iFrame + 1), 0 ); + Gia_ManConst0( p )->Value = ValueMax; + Gia_ManForEachRi( p, pObjRi, i ) + pObjRi->Value = ValueMax; + Vec_IntClear( vPriosFf ); for ( f = 0; f <= pCex->iFrame; f++ ) { Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) - Vec_IntPush( vPrios, (pObjRo->Value = pObjRi->Value) ); - Bmc_CexCarePropagateFwdOne( p, pCex, f, fGrow ); + Vec_IntPush( vPriosFf, (pObjRo->Value = pObjRi->Value) ); + Bmc_CexCarePropagateFwdOne( p, pCex, f, vPriosIn ); } } /**Function************************************************************* - Synopsis [Forward propagation.] + Synopsis [Backward propagation.] Description [] @@ -160,9 +154,9 @@ void Bmc_CexCarePropagateFwd( Gia_Man_t * p, Abc_Cex_t * pCex, int fGrow, Vec_In ***********************************************************************/ void Bmc_CexCarePropagateBwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, Abc_Cex_t * pCexMin ) { - Gia_Obj_t * pObj; + Gia_Obj_t * pObj, * pFan0, * pFan1; int i, Phase0, Phase1; - Gia_ManForEachCand( p, pObj, i ) + Gia_ManForEachCi( p, pObj, i ) pObj->fPhase = 0; Gia_ManForEachCo( p, pObj, i ) if ( pObj->fPhase ) @@ -171,45 +165,60 @@ void Bmc_CexCarePropagateBwdOne( Gia_Man_t * p, Abc_Cex_t * pCex, int f, Abc_Cex { if ( !pObj->fPhase ) continue; - Phase0 = Abc_LitIsCompl(Gia_ObjFanin0(pObj)->Value) ^ Gia_ObjFaninC0(pObj); - Phase1 = Abc_LitIsCompl(Gia_ObjFanin1(pObj)->Value) ^ Gia_ObjFaninC1(pObj); + pFan0 = Gia_ObjFanin0(pObj); + pFan1 = Gia_ObjFanin1(pObj); + Phase0 = Abc_LitIsCompl(pFan0->Value) ^ Gia_ObjFaninC0(pObj); + Phase1 = Abc_LitIsCompl(pFan1->Value) ^ Gia_ObjFaninC1(pObj); if ( Phase0 && Phase1 ) { - Gia_ObjFanin0(pObj)->fPhase = 1; - Gia_ObjFanin1(pObj)->fPhase = 1; + pFan0->fPhase = 1; + pFan1->fPhase = 1; } - else if ( Phase0 && !Phase1 ) - Gia_ObjFanin1(pObj)->fPhase = 1; - else if ( !Phase0 && Phase1 ) - Gia_ObjFanin0(pObj)->fPhase = 1; + else if ( Phase0 ) + pFan1->fPhase = 1; + else if ( Phase1 ) + pFan0->fPhase = 1; else // if ( !Phase0 && !Phase1 ) { - if ( Abc_Lit2Var(Gia_ObjFanin0(pObj)->Value) <= Abc_Lit2Var(Gia_ObjFanin1(pObj)->Value) ) - Gia_ObjFanin0(pObj)->fPhase = 1; + if ( pFan0->fPhase || pFan1->fPhase ) + continue; + if ( Gia_ObjIsPi(p, pFan0) ) + pFan0->fPhase = 1; + else if ( Gia_ObjIsPi(p, pFan1) ) + pFan1->fPhase = 1; +// else if ( Gia_ObjIsAnd(pFan0) && Txs_ObjIsJust(p, pFan0) ) +// pFan0->fPhase = 1; +// else if ( Gia_ObjIsAnd(pFan1) && Txs_ObjIsJust(p, pFan1) ) +// pFan1->fPhase = 1; else - Gia_ObjFanin1(pObj)->fPhase = 1; + { + if ( Abc_Lit2Var(pFan0->Value) > Abc_Lit2Var(pFan1->Value) ) + pFan0->fPhase = 1; + else + pFan1->fPhase = 1; + } } } Gia_ManForEachPi( p, pObj, i ) if ( pObj->fPhase ) Abc_InfoSetBit( pCexMin->pData, pCexMin->nRegs + pCexMin->nPis * f + i ); } -Abc_Cex_t * Bmc_CexCarePropagateBwd( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vPrios, int fGrow ) +Abc_Cex_t * Bmc_CexCarePropagateBwd( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t * vPriosIn, Vec_Int_t * vPriosFf ) { Abc_Cex_t * pCexMin; - Gia_Obj_t * pObj, * pObjRo, * pObjRi; + Gia_Obj_t * pObjRo, * pObjRi; int f, i; pCexMin = Abc_CexAlloc( pCex->nRegs, pCex->nPis, pCex->iFrame + 1 ); pCexMin->iPo = pCex->iPo; pCexMin->iFrame = pCex->iFrame; - Gia_ManForEachCo( p, pObj, i ) - pObj->fPhase = 0; + Gia_ManForEachCo( p, pObjRi, i ) + pObjRi->fPhase = 0; for ( f = pCex->iFrame; f >= 0; f-- ) { Gia_ManPo(p, pCex->iPo)->fPhase = (int)(f == pCex->iFrame); - Gia_ManForEachRo( p, pObj, i ) - pObj->Value = Vec_IntEntry( vPrios, f * pCex->nRegs + i ); - Bmc_CexCarePropagateFwdOne( p, pCex, f, fGrow ); + Gia_ManForEachRo( p, pObjRo, i ) + pObjRo->Value = Vec_IntEntry( vPriosFf, f * pCex->nRegs + i ); + Bmc_CexCarePropagateFwdOne( p, pCex, f, vPriosIn ); Bmc_CexCarePropagateBwdOne( p, pCex, f, pCexMin ); Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) pObjRi->fPhase = pObjRo->fPhase; @@ -228,12 +237,26 @@ Abc_Cex_t * Bmc_CexCarePropagateBwd( Gia_Man_t * p, Abc_Cex_t * pCex, Vec_Int_t SeeAlso [] ***********************************************************************/ -Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck, int fVerbose ) +Abc_Cex_t * Bmc_CexCareTotal( Abc_Cex_t ** pCexes, int nCexes ) { - int nTryCexes = 4; // belongs to range [1;4] + int i, k, nWords = Abc_BitWordNum( pCexes[0]->nBits ); + Abc_Cex_t * pCexMin = Abc_CexAlloc( pCexes[0]->nRegs, pCexes[0]->nPis, pCexes[0]->iFrame + 1 ); + pCexMin->iPo = pCexes[0]->iPo; + pCexMin->iFrame = pCexes[0]->iFrame; + for ( i = 0; i < nWords; i++ ) + { + pCexMin->pData[i] = pCexes[0]->pData[i]; + for ( k = 1; k < nCexes; k++ ) + pCexMin->pData[i] &= pCexes[k]->pData[i]; + } + return pCexMin; +} +Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, int nRealPis, Abc_Cex_t * pCex, int nTryCexes, int fCheck, int fVerbose ) +{ + //int nTryCexes = 4; // belongs to range [1;4] Abc_Cex_t * pCexBest, * pCexMin[4] = {NULL}; - int k, nOnesBest, nOnesCur; - Vec_Int_t * vPrios; + int k, f, i, nOnesBest, nOnesCur, Counter = 0; + Vec_Int_t * vPriosIn, * vPriosFf; if ( pCex->nPis != Gia_ManPiNum(p) ) { printf( "Given CEX does to have same number of inputs as the AIG.\n" ); @@ -255,35 +278,125 @@ Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck, if ( fVerbose ) { printf( "Original : " ); - Bmc_CexPrint( pCex, Gia_ManPiNum(p), 0 ); + Bmc_CexPrint( pCex, nRealPis, 0 ); } - vPrios = Vec_IntAlloc( pCex->nRegs * (pCex->iFrame + 1) ); + vPriosIn = Vec_IntAlloc( pCex->nPis * (pCex->iFrame + 1) ); + vPriosFf = Vec_IntAlloc( pCex->nRegs * (pCex->iFrame + 1) ); for ( k = 0; k < nTryCexes; k++ ) { - Bmc_CexCarePropagateFwd(p, pCex, k, vPrios ); - assert( Vec_IntSize(vPrios) == pCex->nRegs * (pCex->iFrame + 1) ); + Counter = 0; + Vec_IntFill( vPriosIn, pCex->nPis * (pCex->iFrame + 1), 0 ); +/* + if ( k == 0 ) + { + for ( f = 0; f <= pCex->iFrame; f++ ) + for ( i = nRealPis; i < Gia_ManPiNum(p); i++ ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + for ( f = 0; f <= pCex->iFrame; f++ ) + for ( i = 0; i < nRealPis; i++ ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + } + else if ( k == 1 ) + { + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = nRealPis; i < Gia_ManPiNum(p); i++ ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = 0; i < nRealPis; i++ ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + } + else if ( k == 2 ) + { + for ( f = 0; f <= pCex->iFrame; f++ ) + for ( i = Gia_ManPiNum(p) - 1; i >= nRealPis; i-- ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + for ( f = 0; f <= pCex->iFrame; f++ ) + for ( i = nRealPis - 1; i >= 0; i-- ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + } + else if ( k == 3 ) + { + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = Gia_ManPiNum(p) - 1; i >= nRealPis; i-- ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = nRealPis - 1; i >= 0; i-- ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + } + else assert( 0 ); +*/ + if ( k == 0 ) + { + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = Gia_ManPiNum(p) - 1; i >= nRealPis; i-- ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = nRealPis - 1; i >= 0; i-- ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + } + else if ( k == 1 ) + { + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = Gia_ManPiNum(p) - 1; i >= nRealPis; i-- ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = 0; i < nRealPis; i++ ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + } + else if ( k == 2 ) + { + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = nRealPis; i < Gia_ManPiNum(p); i++ ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = nRealPis - 1; i >= 0; i-- ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + } + else if ( k == 3 ) + { + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = nRealPis; i < Gia_ManPiNum(p); i++ ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + for ( f = pCex->iFrame; f >= 0; f-- ) + for ( i = 0; i < nRealPis; i++ ) + Vec_IntWriteEntry( vPriosIn, f * pCex->nPis + i, Abc_Var2Lit(Counter++, Abc_InfoHasBit(pCex->pData, pCex->nRegs + pCex->nPis * f + i)) ); + } + else assert( 0 ); + + assert( Counter == pCex->nPis * (pCex->iFrame + 1) ); + Bmc_CexCarePropagateFwd( p, pCex, vPriosIn, vPriosFf ); + assert( Vec_IntSize(vPriosFf) == pCex->nRegs * (pCex->iFrame + 1) ); if ( !Abc_LitIsCompl(Gia_ManPo(p, pCex->iPo)->Value) ) { printf( "Counter-example is invalid.\n" ); - Vec_IntFree( vPrios ); + Vec_IntFree( vPriosIn ); + Vec_IntFree( vPriosFf ); return NULL; } - pCexMin[k] = Bmc_CexCarePropagateBwd( p, pCex, vPrios, k ); + pCexMin[k] = Bmc_CexCarePropagateBwd( p, pCex, vPriosIn, vPriosFf ); if ( fVerbose ) { - if ( (k & 1) ) - printf( "Decrease : " ); - else - printf( "Increase : " ); - Bmc_CexPrint( pCexMin[k], Gia_ManPiNum(p), 0 ); + if ( k == 0 ) + printf( "PI- PPI-: " ); + else if ( k == 1 ) + printf( "PI+ PPI-: " ); + else if ( k == 2 ) + printf( "PI- PPI+: " ); + else if ( k == 3 ) + printf( "PI+ PPI+: " ); + else assert( 0 ); + Bmc_CexPrint( pCexMin[k], nRealPis, 0 ); } } - Vec_IntFree( vPrios ); + Vec_IntFree( vPriosIn ); + Vec_IntFree( vPriosFf ); // select the best one pCexBest = pCexMin[0]; nOnesBest = Abc_CexCountOnes(pCexMin[0]); for ( k = 1; k < nTryCexes; k++ ) { + if ( pCexMin[k] == NULL ) + continue; nOnesCur = Abc_CexCountOnes(pCexMin[k]); if ( nOnesBest > nOnesCur ) { @@ -291,25 +404,29 @@ Abc_Cex_t * Bmc_CexCareMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fCheck, pCexBest = pCexMin[k]; } } - for ( k = 0; k < nTryCexes; k++ ) - if ( pCexBest != pCexMin[k] ) - Abc_CexFreeP( &pCexMin[k] ); - // verify and return if ( fVerbose ) { + //Abc_Cex_t * pTotal = Bmc_CexCareTotal( pCexMin, nTryCexes ); printf( "Final : " ); - Bmc_CexPrint( pCexBest, Gia_ManPiNum(p), 0 ); + Bmc_CexPrint( pCexBest, nRealPis, 0 ); + //printf( "Total : " ); + //Bmc_CexPrint( pTotal, nRealPis, 0 ); + //Abc_CexFreeP( &pTotal ); } + for ( k = 0; k < nTryCexes; k++ ) + if ( pCexMin[k] && pCexBest != pCexMin[k] ) + Abc_CexFreeP( &pCexMin[k] ); + // verify and return if ( !Bmc_CexVerify( p, pCex, pCexBest ) ) printf( "Counter-example verification has failed.\n" ); else if ( fCheck ) printf( "Counter-example verification succeeded.\n" ); return pCexBest; } -Abc_Cex_t * Bmc_CexCareMinimize( Aig_Man_t * p, Abc_Cex_t * pCex, int fCheck, int fVerbose ) +Abc_Cex_t * Bmc_CexCareMinimize( Aig_Man_t * p, int nRealPis, Abc_Cex_t * pCex, int nTryCexes, int fCheck, int fVerbose ) { Gia_Man_t * pGia = Gia_ManFromAigSimple( p ); - Abc_Cex_t * pCexMin = Bmc_CexCareMinimizeAig( pGia, pCex, fCheck, fVerbose ); + Abc_Cex_t * pCexMin = Bmc_CexCareMinimizeAig( pGia, nRealPis, pCex, nTryCexes, fCheck, fVerbose ); Gia_ManStop( pGia ); return pCexMin; } @@ -341,7 +458,14 @@ void Bmc_CexCareVerify( Aig_Man_t * p, Abc_Cex_t * pCex, Abc_Cex_t * pCexMin, in printf( "Counter-example verification succeeded.\n" ); Gia_ManStop( pGia ); } - +/* + { + Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); + Abc_Cex_t * pCex = Bmc_CexCareMinimize( pAig, 3*Saig_ManPiNum(pAig)/4, 4, pAbc->pCex, 1, 1 ); + Aig_ManStop( pAig ); + Abc_CexFree( pCex ); + } +*/ //////////////////////////////////////////////////////////////////////// /// END OF FILE /// diff --git a/src/sat/bmc/bmcCexTools.c b/src/sat/bmc/bmcCexTools.c index 1c0d798c..9c80b278 100644 --- a/src/sat/bmc/bmcCexTools.c +++ b/src/sat/bmc/bmcCexTools.c @@ -304,10 +304,10 @@ void Bmc_CexBuildNetworkTest( Gia_Man_t * p, Abc_Cex_t * pCex ) SeeAlso [] ***********************************************************************/ -void Bmc_CexPrint( Abc_Cex_t * pCex, int nInputs, int fVerbose ) +void Bmc_CexPrint( Abc_Cex_t * pCex, int nRealPis, int fVerbose ) { int i, k, Count, iBit = pCex->nRegs; - Abc_CexPrintStatsInputs( pCex, nInputs ); + Abc_CexPrintStatsInputs( pCex, nRealPis ); if ( !fVerbose ) return; @@ -315,7 +315,7 @@ void Bmc_CexPrint( Abc_Cex_t * pCex, int nInputs, int fVerbose ) { Count = 0; printf( "%3d : ", i ); - for ( k = 0; k < nInputs; k++ ) + for ( k = 0; k < nRealPis; k++ ) { Count += Abc_InfoHasBit(pCex->pData, iBit); printf( "%d", Abc_InfoHasBit(pCex->pData, iBit++) ); diff --git a/src/sat/bmc/bmcChain.c b/src/sat/bmc/bmcChain.c index 324c7f6d..5af54306 100644 --- a/src/sat/bmc/bmcChain.c +++ b/src/sat/bmc/bmcChain.c @@ -185,10 +185,9 @@ Gia_Man_t * Gia_ManDupPosAndPropagateInit( Gia_Man_t * p ) } sat_solver * Gia_ManDeriveSatSolver( Gia_Man_t * p, Vec_Int_t * vSatIds ) { -// extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); sat_solver * pSat; Aig_Man_t * pAig = Gia_ManToAigSimple( p ); -// Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); +// Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, 0, 0 ); Cnf_Dat_t * pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); // save SAT vars for the primary inputs if ( vSatIds ) diff --git a/src/sat/bmc/bmcClp.c b/src/sat/bmc/bmcClp.c index 8a69fe56..cfc608b1 100644 --- a/src/sat/bmc/bmcClp.c +++ b/src/sat/bmc/bmcClp.c @@ -30,8 +30,6 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -651,7 +649,7 @@ Vec_Str_t * Bmc_CollapseOneInt2( Gia_Man_t * p, int nCubeLim, int nBTLimit, int int iOut = 0, iLit, iVar, status, n, Count, Start; // create SAT solver - Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, 0, 0 ); sat_solver * pSat[3] = { (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0), (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0), @@ -841,7 +839,7 @@ Vec_Str_t * Bmc_CollapseOneOld( Gia_Man_t * p, int nCubeLim, int nBTLimit, int f { int fVeryVerbose = fVerbose; int nVars = Gia_ManCiNum(p); - Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, 0, 0 ); sat_solver * pSat[2] = { (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0), (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0) }; sat_solver * pSatClean[2] = { (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0), (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0) }; Vec_Str_t * vSop[2] = { Vec_StrAlloc(1000), Vec_StrAlloc(1000) }, * vRes = NULL; @@ -1173,7 +1171,7 @@ cleanup: } Vec_Str_t * Bmc_CollapseOne3( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { - Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, 0, 0 ); sat_solver * pSat0 = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); sat_solver * pSat1 = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); sat_solver * pSat2 = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); @@ -1507,7 +1505,7 @@ cleanup: } Vec_Str_t * Bmc_CollapseOne( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { - Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); Vec_Str_t * vSop = Bmc_CollapseOne_int( pSat, Gia_ManCiNum(p), nCubeLim, nBTLimit, fCanon, fReverse, fVerbose ); sat_solver_delete( pSat ); diff --git a/src/sat/bmc/bmcEnum.c b/src/sat/bmc/bmcEnum.c new file mode 100644 index 00000000..45aeb2b3 --- /dev/null +++ b/src/sat/bmc/bmcEnum.c @@ -0,0 +1,223 @@ +/**CFile**************************************************************** + + FileName [bmcEnum.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT-based bounded model checking.] + + Synopsis [Enumeration.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bmcEnum.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bmc.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDeriveOne( Gia_Man_t * p, Vec_Int_t * vValues ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; int i, fPhase0, fPhase1; + assert( Vec_IntSize(vValues) == Gia_ManCiNum(p) ); + // propagate forward + Gia_ManForEachCi( p, pObj, i ) + pObj->fPhase = Vec_IntEntry(vValues, i); + Gia_ManForEachAnd( p, pObj, i ) + { + fPhase0 = Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj); + fPhase1 = Gia_ObjPhase(Gia_ObjFanin1(pObj)) ^ Gia_ObjFaninC1(pObj); + pObj->fPhase = fPhase0 & fPhase1; + } + // propagate backward + Gia_ManCleanMark0(p); + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ManForEachAndReverse( p, pObj, i ) + { + if ( !pObj->fMark0 ) + continue; + fPhase0 = Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj); + fPhase1 = Gia_ObjPhase(Gia_ObjFanin1(pObj)) ^ Gia_ObjFaninC1(pObj); + if ( fPhase0 == fPhase1 ) + { + assert( (int)pObj->fPhase == fPhase0 ); + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + else if ( fPhase0 ) + { + assert( fPhase1 == 0 ); + assert( pObj->fPhase == 0 ); + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + else if ( fPhase1 ) + { + assert( fPhase0 == 0 ); + assert( pObj->fPhase == 0 ); + Gia_ObjFanin0(pObj)->fMark0 = 1; + } + } + // create new + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), !Vec_IntEntry(vValues, i) ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !pObj->fMark0 ) + continue; + fPhase0 = Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj); + fPhase1 = Gia_ObjPhase(Gia_ObjFanin1(pObj)) ^ Gia_ObjFaninC1(pObj); + if ( fPhase0 == fPhase1 ) + { + assert( (int)pObj->fPhase == fPhase0 ); + if ( pObj->fPhase ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); + else + pObj->Value = Gia_ManAppendOr( pNew, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value ); + } + else if ( fPhase0 ) + { + assert( fPhase1 == 0 ); + assert( pObj->fPhase == 0 ); + pObj->Value = Gia_ObjFanin1(pObj)->Value; + } + else if ( fPhase1 ) + { + assert( fPhase0 == 0 ); + assert( pObj->fPhase == 0 ); + pObj->Value = Gia_ObjFanin0(pObj)->Value; + } + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0(pObj)->Value ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManCleanMark0(p); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDeriveOneTest2( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + //Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + pNew = Gia_ManDeriveOne( p, vValues ); + Vec_IntFree( vValues ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDeriveOneTest( Gia_Man_t * p ) +{ + int fVerbose = 1; + Gia_Man_t * pNew; + Gia_Obj_t * pObj, * pRoot; + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, 0, 0 ); + int i, iVar, nIter, iPoVarBeg = pCnf->nVars - Gia_ManCiNum(p); + sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + Vec_IntPush( vLits, Abc_Var2Lit( 1, 1 ) ); + for ( nIter = 0; nIter < 10000; nIter++ ) + { + int status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), 0, 0, 0, 0 ); + if ( status == l_False ) + break; + // derive new set + assert( status == l_True ); + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + { + Vec_IntWriteEntry( vValues, i, sat_solver_var_value(pSat, iPoVarBeg+i) ); + printf( "%d", sat_solver_var_value(pSat, iPoVarBeg+i) ); + } + printf( " : " ); + + pNew = Gia_ManDeriveOne( p, vValues ); + // assign variables + Gia_ManForEachCi( pNew, pObj, i ) + pObj->Value = iPoVarBeg+i; + iVar = sat_solver_nvars(pSat); + Gia_ManForEachAnd( pNew, pObj, i ) + pObj->Value = iVar++; + sat_solver_setnvars( pSat, iVar ); + // create new clauses + Gia_ManForEachAnd( pNew, pObj, i ) + sat_solver_add_and( pSat, pObj->Value, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + // add to the assumptions + pRoot = Gia_ManCo(pNew, 0); + Vec_IntPush( vLits, Abc_Var2Lit(Gia_ObjFanin0(pRoot)->Value, !Gia_ObjFaninC0(pRoot)) ); + if ( fVerbose ) + { + printf( "Iter = %5d : ", nIter ); + printf( "And = %4d ", Gia_ManAndNum(pNew) ); + printf( "\n" ); + } + Gia_ManStop( pNew ); + } + Vec_IntFree( vLits ); + Vec_IntFree( vValues ); + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/src/sat/bmc/bmcExpand.c b/src/sat/bmc/bmcExpand.c index f3ec999e..6c7a5988 100644 --- a/src/sat/bmc/bmcExpand.c +++ b/src/sat/bmc/bmcExpand.c @@ -33,8 +33,6 @@ ABC_NAMESPACE_IMPL_START // iterator thought the cubes #define Bmc_SopForEachCube( pSop, nVars, pCube ) for ( pCube = (pSop); *pCube; pCube += (nVars) + 3 ) -extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -93,7 +91,7 @@ int Abc_ObjExpandCubes( Vec_Str_t * vSop, Gia_Man_t * p, int nVars ) int fReverse = 0; Vec_Int_t * vVars = Vec_IntAlloc( nVars ); - Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); int v, n, iLit, status, nCubesNew, iCiVarBeg = sat_solver_nvars(pSat) - nVars; diff --git a/src/sat/bmc/bmcFault.c b/src/sat/bmc/bmcFault.c index 8dc2a57f..71eef2c4 100644 --- a/src/sat/bmc/bmcFault.c +++ b/src/sat/bmc/bmcFault.c @@ -280,7 +280,7 @@ static inline Cnf_Dat_t * Cnf_DeriveGiaRemapped( Gia_Man_t * p ) pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); Aig_ManStop( pAig ); return pCnf; -// return Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); +// return (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, 0, 0 ); } /**Function************************************************************* diff --git a/src/sat/bmc/bmcFx.c b/src/sat/bmc/bmcFx.c index 9cd37c88..15ea4f05 100644 --- a/src/sat/bmc/bmcFx.c +++ b/src/sat/bmc/bmcFx.c @@ -30,8 +30,6 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -598,7 +596,7 @@ int Bmc_FxCompute( Gia_Man_t * p ) extern Gia_Man_t * Gia_ManDupOnsetOffset( Gia_Man_t * p ); Gia_Man_t * p2 = Gia_ManDupOnsetOffset( p ); // create SAT solver - Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p2, 8, 0, 0, 0 ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p2, 8, 0, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); // compute parameters int nOuts = Gia_ManCoNum(p); @@ -674,7 +672,7 @@ int Bmc_FxComputeOne( Gia_Man_t * p, int nIterMax, int nDiv2Add ) { int Extra = 1000; // create SAT solver - Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); // compute parameters int nCiVars = Gia_ManCiNum(p); // PI count diff --git a/src/sat/bmc/bmcGen.c b/src/sat/bmc/bmcGen.c index 74af1b78..460c9fec 100644 --- a/src/sat/bmc/bmcGen.c +++ b/src/sat/bmc/bmcGen.c @@ -29,8 +29,6 @@ ABC_NAMESPACE_IMPL_START /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// -extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); - //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// @@ -48,13 +46,13 @@ extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfOb ***********************************************************************/ static inline word * Gia_ManMoObj( Gia_Man_t * p, int iObj ) { - return Vec_WrdEntryP( p->vSims, iObj * p->iPatsPi ); + return Vec_WrdEntryP( p->vSims, iObj * p->nSimWords ); } static inline void Gia_ManMoSetCi( Gia_Man_t * p, int iObj ) { int w; word * pSims = Gia_ManMoObj( p, iObj ); - for ( w = 0; w < p->iPatsPi; w++ ) + for ( w = 0; w < p->nSimWords; w++ ) pSims[w] = Gia_ManRandomW( 0 ); } static inline void Gia_ManMoSimAnd( Gia_Man_t * p, int iObj ) @@ -67,19 +65,19 @@ static inline void Gia_ManMoSimAnd( Gia_Man_t * p, int iObj ) if ( Gia_ObjFaninC0(pObj) ) { if ( Gia_ObjFaninC1(pObj) ) - for ( w = 0; w < p->iPatsPi; w++ ) + for ( w = 0; w < p->nSimWords; w++ ) pSims[w] = ~(pSims0[w] | pSims1[w]); else - for ( w = 0; w < p->iPatsPi; w++ ) + for ( w = 0; w < p->nSimWords; w++ ) pSims[w] = ~pSims0[w] & pSims1[w]; } else { if ( Gia_ObjFaninC1(pObj) ) - for ( w = 0; w < p->iPatsPi; w++ ) + for ( w = 0; w < p->nSimWords; w++ ) pSims[w] = pSims0[w] & ~pSims1[w]; else - for ( w = 0; w < p->iPatsPi; w++ ) + for ( w = 0; w < p->nSimWords; w++ ) pSims[w] = pSims0[w] & pSims1[w]; } } @@ -91,12 +89,12 @@ static inline void Gia_ManMoSetCo( Gia_Man_t * p, int iObj ) word * pSims0 = Gia_ManMoObj( p, Gia_ObjFaninId0(pObj, iObj) ); if ( Gia_ObjFaninC0(pObj) ) { - for ( w = 0; w < p->iPatsPi; w++ ) + for ( w = 0; w < p->nSimWords; w++ ) pSims[w] = ~pSims0[w]; } else { - for ( w = 0; w < p->iPatsPi; w++ ) + for ( w = 0; w < p->nSimWords; w++ ) pSims[w] = pSims0[w]; } } @@ -104,7 +102,7 @@ void Gia_ManMoFindSimulate( Gia_Man_t * p, int nWords ) { int i, iObj; Gia_ManRandomW( 1 ); - p->iPatsPi = nWords; + p->nSimWords = nWords; if ( p->vSims ) Vec_WrdFill( p->vSims, nWords * Gia_ManObjNum(p), 0 ); else @@ -131,7 +129,7 @@ void Gia_ManMoFindSimulate( Gia_Man_t * p, int nWords ) int Gia_ManTestSatEnum( Gia_Man_t * p ) { abctime clk = Abc_Clock(), clk2, clkTotal = 0; - Cnf_Dat_t * pCnf = Mf_ManGenerateCnf( p, 8, 0, 0, 0 ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, 0, 0 ); sat_solver * pSat = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); int i, v, status, iLit, nWords = 1, iOutVar = 1, Count = 0; Vec_Int_t * vVars = Vec_IntAlloc( 1000 ); diff --git a/src/sat/bmc/bmcICheck.c b/src/sat/bmc/bmcICheck.c index a779b1ed..8d8c7c6b 100644 --- a/src/sat/bmc/bmcICheck.c +++ b/src/sat/bmc/bmcICheck.c @@ -392,11 +392,10 @@ int Bmc_PerformISearchOne( Gia_Man_t * p, int nFramesMax, int nTimeOut, int fRev pCnf = Cnf_DeriveGiaRemapped( pMiter ); else { - extern Cnf_Dat_t * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ); //pMiter = Jf_ManDeriveCnf( pTemp = pMiter, 0 ); //Gia_ManStop( pTemp ); //pCnf = (Cnf_Dat_t *)pMiter->pData; pMiter->pData = NULL; - pCnf = Mf_ManGenerateCnf( pMiter, 8, 0, 0, 0 ); + pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pMiter, 8, 0, 0, 0, 0 ); } /* // collect positive literals diff --git a/src/sat/bsat/satSolver.c b/src/sat/bsat/satSolver.c index 88a05093..df9ada8e 100644 --- a/src/sat/bsat/satSolver.c +++ b/src/sat/bsat/satSolver.c @@ -151,6 +151,7 @@ static inline void order_update(sat_solver* s, int v) // updateorder i = parent; parent = (i - 1) / 2; } + heap[i] = x; orderpos[x] = i; } @@ -192,11 +193,13 @@ static inline int order_select(sat_solver* s, float random_var_freq) // selectv int i = 0; int child = 1; while (child < size){ + if (child+1 < size && s->activity[heap[child]] < s->activity[heap[child+1]]) child++; assert(child < size); if (s->activity[x] >= s->activity[heap[child]]) break; + heap[i] = heap[child]; orderpos[heap[i]] = i; i = child; @@ -214,138 +217,234 @@ static inline int order_select(sat_solver* s, float random_var_freq) // selectv void sat_solver_set_var_activity(sat_solver* s, int * pVars, int nVars) { int i; + assert( s->VarActType == 1 ); for (i = 0; i < s->size; i++) s->activity[i] = 0; - s->var_inc = 1; + s->var_inc = Abc_Dbl2Word(1); for ( i = 0; i < nVars; i++ ) { int iVar = pVars ? pVars[i] : i; - s->activity[iVar] = nVars-i; + s->activity[iVar] = Abc_Dbl2Word(nVars-i); order_update( s, iVar ); } } //================================================================================================= -// Activity functions: +// variable activities -#ifdef USE_FLOAT_ACTIVITY +static inline void solver_init_activities(sat_solver* s) +{ + // variable activities + s->VarActType = 0; + if ( s->VarActType == 0 ) + { + s->var_inc = (1 << 5); + s->var_decay = -1; + } + else if ( s->VarActType == 1 ) + { + s->var_inc = Abc_Dbl2Word(1.0); + s->var_decay = Abc_Dbl2Word(1.0 / 0.95); + } + else if ( s->VarActType == 2 ) + { + s->var_inc = Xdbl_FromDouble(1.0); + s->var_decay = Xdbl_FromDouble(1.0 / 0.950); + } + else assert(0); -static inline void act_var_rescale(sat_solver* s) { - double* activity = s->activity; - int i; - for (i = 0; i < s->size; i++) - activity[i] *= 1e-100; - s->var_inc *= 1e-100; -} -static inline void act_clause_rescale(sat_solver* s) { -// static abctime Total = 0; - clause** cs = (clause**)veci_begin(&s->learnts); - int i;//, clk = Abc_Clock(); - for (i = 0; i < veci_size(&s->learnts); i++){ - float a = clause_activity(cs[i]); - clause_setactivity(cs[i], a * (float)1e-20); - } - s->cla_inc *= (float)1e-20; - - Total += Abc_Clock() - clk; -// printf( "Rescaling... Cla inc = %10.3f Conf = %10d ", s->cla_inc, s->stats.conflicts ); -// Abc_PrintTime( 1, "Time", Total ); -} -static inline void act_var_bump(sat_solver* s, int v) { - s->activity[v] += s->var_inc; - if (s->activity[v] > 1e100) - act_var_rescale(s); - if (s->orderpos[v] != -1) - order_update(s,v); -} -static inline void act_var_bump_global(sat_solver* s, int v) { - if ( !s->pGlobalVars ) - return; - s->activity[v] += (s->var_inc * 3.0 * s->pGlobalVars[v]); - if (s->activity[v] > 1e100) - act_var_rescale(s); - if (s->orderpos[v] != -1) - order_update(s,v); -} -static inline void act_var_bump_factor(sat_solver* s, int v) { - if ( !s->factors ) - return; - s->activity[v] += (s->var_inc * s->factors[v]); - if (s->activity[v] > 1e100) - act_var_rescale(s); - if (s->orderpos[v] != -1) - order_update(s,v); -} -static inline void act_clause_bump(sat_solver* s, clause *c) { - float a = clause_activity(c) + s->cla_inc; - clause_setactivity(c,a); - if (a > 1e20) act_clause_rescale(s); + // clause activities + s->ClaActType = 0; + if ( s->ClaActType == 0 ) + { + s->cla_inc = (1 << 11); + s->cla_decay = -1; + } + else + { + s->cla_inc = 1; + s->cla_decay = (float)(1 / 0.999); + } } -static inline void act_var_decay(sat_solver* s) { s->var_inc *= s->var_decay; } -static inline void act_clause_decay(sat_solver* s) { s->cla_inc *= s->cla_decay; } - -#else -static inline void act_var_rescale(sat_solver* s) { - unsigned* activity = s->activity; - int i; - for (i = 0; i < s->size; i++) - activity[i] >>= 19; - s->var_inc >>= 19; - s->var_inc = Abc_MaxInt( s->var_inc, (1<<4) ); +static inline void act_var_rescale(sat_solver* s) +{ + if ( s->VarActType == 0 ) + { + word* activity = s->activity; + int i; + for (i = 0; i < s->size; i++) + activity[i] >>= 19; + s->var_inc >>= 19; + s->var_inc = Abc_MaxInt( (unsigned)s->var_inc, (1<<4) ); + } + else if ( s->VarActType == 1 ) + { + double* activity = (double*)s->activity; + int i; + for (i = 0; i < s->size; i++) + activity[i] *= 1e-100; + s->var_inc = Abc_Dbl2Word( Abc_Word2Dbl(s->var_inc) * 1e-100 ); + //printf( "Rescaling var activity...\n" ); + } + else if ( s->VarActType == 2 ) + { + xdbl * activity = s->activity; + int i; + for (i = 0; i < s->size; i++) + activity[i] = Xdbl_Div( activity[i], 200 ); // activity[i] / 2^200 + s->var_inc = Xdbl_Div( s->var_inc, 200 ); + } + else assert(0); } - -static inline void act_clause_rescale(sat_solver* s) { - static abctime Total = 0; - abctime clk = Abc_Clock(); - unsigned* activity = (unsigned *)veci_begin(&s->act_clas); - int i; - for (i = 0; i < veci_size(&s->act_clas); i++) - activity[i] >>= 14; - s->cla_inc >>= 14; - s->cla_inc = Abc_MaxInt( s->cla_inc, (1<<10) ); - Total += Abc_Clock() - clk; -// printf( "Rescaling... Cla inc = %5d Conf = %10d ", s->cla_inc, s->stats.conflicts ); -// Abc_PrintTime( 1, "Time", Total ); -} - -static inline void act_var_bump(sat_solver* s, int v) { - s->activity[v] += s->var_inc; - if (s->activity[v] & 0x80000000) - act_var_rescale(s); - if (s->orderpos[v] != -1) - order_update(s,v); +static inline void act_var_bump(sat_solver* s, int v) +{ + if ( s->VarActType == 0 ) + { + s->activity[v] += s->var_inc; + if ((unsigned)s->activity[v] & 0x80000000) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 1 ) + { + double act = Abc_Word2Dbl(s->activity[v]) + Abc_Word2Dbl(s->var_inc); + s->activity[v] = Abc_Dbl2Word(act); + if (act > 1e100) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 2 ) + { + s->activity[v] = Xdbl_Add( s->activity[v], s->var_inc ); + if (s->activity[v] > ABC_CONST(0x014c924d692ca61b)) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else assert(0); } -static inline void act_var_bump_global(sat_solver* s, int v) { - if ( !s->pGlobalVars ) +static inline void act_var_bump_global(sat_solver* s, int v) +{ + if ( !s->pGlobalVars || !s->pGlobalVars[v] ) return; - s->activity[v] += (int)(s->var_inc * 3 * s->pGlobalVars[v]); - if (s->activity[v] & 0x80000000) - act_var_rescale(s); - if (s->orderpos[v] != -1) - order_update(s,v); + if ( s->VarActType == 0 ) + { + s->activity[v] += (int)((unsigned)s->var_inc * 3); + if (s->activity[v] & 0x80000000) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 1 ) + { + double act = Abc_Word2Dbl(s->activity[v]) + Abc_Word2Dbl(s->var_inc) * 3.0; + s->activity[v] = Abc_Dbl2Word(act); + if ( act > 1e100) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 2 ) + { + s->activity[v] = Xdbl_Add( s->activity[v], Xdbl_Mul(s->var_inc, Xdbl_FromDouble(3.0)) ); + if (s->activity[v] > ABC_CONST(0x014c924d692ca61b)) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else assert( 0 ); } -static inline void act_var_bump_factor(sat_solver* s, int v) { +static inline void act_var_bump_factor(sat_solver* s, int v) +{ if ( !s->factors ) return; - s->activity[v] += (int)(s->var_inc * s->factors[v]); - if (s->activity[v] & 0x80000000) - act_var_rescale(s); - if (s->orderpos[v] != -1) - order_update(s,v); + if ( s->VarActType == 0 ) + { + s->activity[v] += (int)((unsigned)s->var_inc * (float)s->factors[v]); + if (s->activity[v] & 0x80000000) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 1 ) + { + double act = Abc_Word2Dbl(s->activity[v]) + Abc_Word2Dbl(s->var_inc) * s->factors[v]; + s->activity[v] = Abc_Dbl2Word(act); + if ( act > 1e100) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else if ( s->VarActType == 2 ) + { + s->activity[v] = Xdbl_Add( s->activity[v], Xdbl_Mul(s->var_inc, Xdbl_FromDouble(s->factors[v])) ); + if (s->activity[v] > ABC_CONST(0x014c924d692ca61b)) + act_var_rescale(s); + if (s->orderpos[v] != -1) + order_update(s,v); + } + else assert( 0 ); } -static inline void act_clause_bump(sat_solver* s, clause*c) { - unsigned* act = (unsigned *)veci_begin(&s->act_clas) + c->lits[c->size]; - *act += s->cla_inc; - if ( *act & 0x80000000 ) - act_clause_rescale(s); +static inline void act_var_decay(sat_solver* s) +{ + if ( s->VarActType == 0 ) + s->var_inc += (s->var_inc >> 4); + else if ( s->VarActType == 1 ) + s->var_inc = Abc_Dbl2Word( Abc_Word2Dbl(s->var_inc) * Abc_Word2Dbl(s->var_decay) ); + else if ( s->VarActType == 2 ) + s->var_inc = Xdbl_Mul(s->var_inc, s->var_decay); + else assert(0); } -static inline void act_var_decay(sat_solver* s) { s->var_inc += (s->var_inc >> 4); } -static inline void act_clause_decay(sat_solver* s) { s->cla_inc += (s->cla_inc >> 10); } - -#endif +// clause activities +static inline void act_clause_rescale(sat_solver* s) +{ + if ( s->ClaActType == 0 ) + { + unsigned* activity = (unsigned *)veci_begin(&s->act_clas); + int i; + for (i = 0; i < veci_size(&s->act_clas); i++) + activity[i] >>= 14; + s->cla_inc >>= 14; + s->cla_inc = Abc_MaxInt( s->cla_inc, (1<<10) ); + } + else + { + float* activity = (float *)veci_begin(&s->act_clas); + int i; + for (i = 0; i < veci_size(&s->act_clas); i++) + activity[i] *= (float)1e-20; + s->cla_inc *= (float)1e-20; + } +} +static inline void act_clause_bump(sat_solver* s, clause *c) +{ + if ( s->ClaActType == 0 ) + { + unsigned* act = (unsigned *)veci_begin(&s->act_clas) + c->lits[c->size]; + *act += s->cla_inc; + if ( *act & 0x80000000 ) + act_clause_rescale(s); + } + else + { + float* act = (float *)veci_begin(&s->act_clas) + c->lits[c->size]; + *act += s->cla_inc; + if (*act > 1e20) + act_clause_rescale(s); + } +} +static inline void act_clause_decay(sat_solver* s) +{ + if ( s->ClaActType == 0 ) + s->cla_inc += (s->cla_inc >> 10); + else + s->cla_inc *= s->cla_decay; +} //================================================================================================= @@ -447,7 +546,10 @@ int sat_solver_clause_new(sat_solver* s, lit* begin, lit* end, int learnt) assert( clause_id(c) == veci_size(&s->act_clas) ); // veci_push(&s->learned, h); // act_clause_bump(s,clause_read(s, h)); - veci_push(&s->act_clas, (1<<10)); + if ( s->ClaActType == 0 ) + veci_push(&s->act_clas, (1<<10)); + else + veci_push(&s->act_clas, s->cla_inc); s->stats.learnts++; s->stats.learnts_literals += size; } @@ -1037,7 +1139,6 @@ sat_solver* sat_solver_new(void) veci_new(&s->act_clas); veci_new(&s->stack); // veci_new(&s->model); - veci_new(&s->act_vars); veci_new(&s->unit_lits); veci_new(&s->temp_clause); veci_new(&s->conf_final); @@ -1054,15 +1155,10 @@ sat_solver* sat_solver_new(void) s->cap = 0; s->qhead = 0; s->qtail = 0; -#ifdef USE_FLOAT_ACTIVITY - s->var_inc = 1; - s->cla_inc = 1; - s->var_decay = (float)(1 / 0.95 ); - s->cla_decay = (float)(1 / 0.999); -#else - s->var_inc = (1 << 5); - s->cla_inc = (1 << 11); -#endif + + solver_init_activities(s); + veci_new(&s->act_vars); + s->root_level = 0; // s->simpdb_assigns = 0; // s->simpdb_props = 0; @@ -1085,6 +1181,71 @@ sat_solver* sat_solver_new(void) return s; } +sat_solver* zsat_solver_new_seed(double seed) +{ + sat_solver* s = (sat_solver*)ABC_CALLOC( char, sizeof(sat_solver)); + +// Vec_SetAlloc_(&s->Mem, 15); + Sat_MemAlloc_(&s->Mem, 15); + s->hLearnts = -1; + s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 ); + s->binary = clause_read( s, s->hBinary ); + + s->nLearntStart = LEARNT_MAX_START_DEFAULT; // starting learned clause limit + s->nLearntDelta = LEARNT_MAX_INCRE_DEFAULT; // delta of learned clause limit + s->nLearntRatio = LEARNT_MAX_RATIO_DEFAULT; // ratio of learned clause limit + s->nLearntMax = s->nLearntStart; + + // initialize vectors + veci_new(&s->order); + veci_new(&s->trail_lim); + veci_new(&s->tagged); +// veci_new(&s->learned); + veci_new(&s->act_clas); + veci_new(&s->stack); +// veci_new(&s->model); + veci_new(&s->unit_lits); + veci_new(&s->temp_clause); + veci_new(&s->conf_final); + + // initialize arrays + s->wlists = 0; + s->activity = 0; + s->orderpos = 0; + s->reasons = 0; + s->trail = 0; + + // initialize other vars + s->size = 0; + s->cap = 0; + s->qhead = 0; + s->qtail = 0; + + solver_init_activities(s); + veci_new(&s->act_vars); + + s->root_level = 0; +// s->simpdb_assigns = 0; +// s->simpdb_props = 0; + s->random_seed = seed; + s->progress_estimate = 0; +// s->binary = (clause*)ABC_ALLOC( char, sizeof(clause) + sizeof(lit)*2); +// s->binary->size_learnt = (2 << 1); + s->verbosity = 0; + + s->stats.starts = 0; + s->stats.decisions = 0; + s->stats.propagations = 0; + s->stats.inspects = 0; + s->stats.conflicts = 0; + s->stats.clauses = 0; + s->stats.clauses_literals = 0; + s->stats.learnts = 0; + s->stats.learnts_literals = 0; + s->stats.tot_literals = 0; + return s; +} + void sat_solver_setnvars(sat_solver* s,int n) { int var; @@ -1102,12 +1263,8 @@ void sat_solver_setnvars(sat_solver* s,int n) s->polarity = ABC_REALLOC(char, s->polarity, s->cap); s->tags = ABC_REALLOC(char, s->tags, s->cap); s->loads = ABC_REALLOC(char, s->loads, s->cap); -#ifdef USE_FLOAT_ACTIVITY - s->activity = ABC_REALLOC(double, s->activity, s->cap); -#else - s->activity = ABC_REALLOC(unsigned, s->activity, s->cap); - s->activity2 = ABC_REALLOC(unsigned, s->activity2,s->cap); -#endif + s->activity = ABC_REALLOC(word, s->activity, s->cap); + s->activity2 = ABC_REALLOC(word, s->activity2,s->cap); s->pFreqs = ABC_REALLOC(char, s->pFreqs, s->cap); if ( s->factors ) @@ -1126,11 +1283,15 @@ void sat_solver_setnvars(sat_solver* s,int n) veci_new(&s->wlists[2*var]); if ( s->wlists[2*var+1].ptr == NULL ) veci_new(&s->wlists[2*var+1]); -#ifdef USE_FLOAT_ACTIVITY - s->activity[var] = 0; -#else - s->activity[var] = (1<<10); -#endif + + if ( s->VarActType == 0 ) + s->activity[var] = (1<<10); + else if ( s->VarActType == 1 ) + s->activity[var] = 0; + else if ( s->VarActType == 2 ) + s->activity[var] = 0; + else assert(0); + s->pFreqs[var] = 0; if ( s->factors ) s->factors [var] = 0; @@ -1207,7 +1368,6 @@ void sat_solver_restart( sat_solver* s ) s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 ); s->binary = clause_read( s, s->hBinary ); - veci_resize(&s->act_clas, 0); veci_resize(&s->trail_lim, 0); veci_resize(&s->order, 0); for ( i = 0; i < s->size*2; i++ ) @@ -1220,15 +1380,13 @@ void sat_solver_restart( sat_solver* s ) // s->cap = 0; s->qhead = 0; s->qtail = 0; -#ifdef USE_FLOAT_ACTIVITY - s->var_inc = 1; - s->cla_inc = 1; - s->var_decay = (float)(1 / 0.95 ); - s->cla_decay = (float)(1 / 0.999 ); -#else - s->var_inc = (1 << 5); - s->cla_inc = (1 << 11); -#endif + + + // variable activities + solver_init_activities(s); + veci_resize(&s->act_clas, 0); + + s->root_level = 0; // s->simpdb_assigns = 0; // s->simpdb_props = 0; @@ -1248,6 +1406,49 @@ void sat_solver_restart( sat_solver* s ) s->stats.tot_literals = 0; } +void zsat_solver_restart_seed( sat_solver* s, double seed ) +{ + int i; + Sat_MemRestart( &s->Mem ); + s->hLearnts = -1; + s->hBinary = Sat_MemAppend( &s->Mem, NULL, 2, 0, 0 ); + s->binary = clause_read( s, s->hBinary ); + + veci_resize(&s->trail_lim, 0); + veci_resize(&s->order, 0); + for ( i = 0; i < s->size*2; i++ ) + s->wlists[i].size = 0; + + s->nDBreduces = 0; + + // initialize other vars + s->size = 0; +// s->cap = 0; + s->qhead = 0; + s->qtail = 0; + + solver_init_activities(s); + veci_resize(&s->act_clas, 0); + + s->root_level = 0; +// s->simpdb_assigns = 0; +// s->simpdb_props = 0; + s->random_seed = seed; + s->progress_estimate = 0; + s->verbosity = 0; + + s->stats.starts = 0; + s->stats.decisions = 0; + s->stats.propagations = 0; + s->stats.inspects = 0; + s->stats.conflicts = 0; + s->stats.clauses = 0; + s->stats.clauses_literals = 0; + s->stats.learnts = 0; + s->stats.learnts_literals = 0; + s->stats.tot_literals = 0; +} + // returns memory in bytes used by the SAT solver double sat_solver_memory( sat_solver* s ) { @@ -1261,13 +1462,9 @@ double sat_solver_memory( sat_solver* s ) Mem += s->cap * sizeof(char); // ABC_FREE(s->polarity ); Mem += s->cap * sizeof(char); // ABC_FREE(s->tags ); Mem += s->cap * sizeof(char); // ABC_FREE(s->loads ); -#ifdef USE_FLOAT_ACTIVITY - Mem += s->cap * sizeof(double); // ABC_FREE(s->activity ); -#else - Mem += s->cap * sizeof(unsigned); // ABC_FREE(s->activity ); + Mem += s->cap * sizeof(word); // ABC_FREE(s->activity ); if ( s->activity2 ) - Mem += s->cap * sizeof(unsigned); // ABC_FREE(s->activity2); -#endif + Mem += s->cap * sizeof(word); // ABC_FREE(s->activity ); if ( s->factors ) Mem += s->cap * sizeof(double); // ABC_FREE(s->factors ); Mem += s->cap * sizeof(int); // ABC_FREE(s->orderpos ); @@ -1314,7 +1511,7 @@ void sat_solver_reducedb(sat_solver* s) s->nDBreduces++; -// printf( "Calling reduceDB with %d learned clause limit.\n", s->nLearntMax ); + //printf( "Calling reduceDB with %d learned clause limit.\n", s->nLearntMax ); s->nLearntMax = s->nLearntStart + s->nLearntDelta * s->nDBreduces; // return; @@ -1323,8 +1520,11 @@ void sat_solver_reducedb(sat_solver* s) Sat_MemForEachLearned( pMem, c, i, k ) { Id = clause_id(c); - pSortValues[Id] = (((7 - Abc_MinInt(c->lbd, 7)) << 28) | (act_clas[Id] >> 4)); // pSortValues[Id] = act[Id]; + if ( s->ClaActType == 0 ) + pSortValues[Id] = ((7 - Abc_MinInt(c->lbd, 7)) << 28) | (act_clas[Id] >> 4); + else + pSortValues[Id] = ((7 - Abc_MinInt(c->lbd, 7)) << 28);// | (act_clas[Id] >> 4); assert( pSortValues[Id] >= 0 ); } @@ -1430,7 +1630,7 @@ void sat_solver_rollback( sat_solver* s ) if ( s->activity2 ) { s->var_inc = s->var_inc2; - memcpy( s->activity, s->activity2, sizeof(unsigned) * s->iVarPivot ); + memcpy( s->activity, s->activity2, sizeof(word) * s->iVarPivot ); } veci_resize(&s->order, 0); for ( i = 0; i < s->iVarPivot; i++ ) @@ -1479,15 +1679,9 @@ void sat_solver_rollback( sat_solver* s ) // s->cap = 0; s->qhead = 0; s->qtail = 0; -#ifdef USE_FLOAT_ACTIVITY - s->var_inc = 1; - s->cla_inc = 1; - s->var_decay = (float)(1 / 0.95 ); - s->cla_decay = (float)(1 / 0.999 ); -#else - s->var_inc = (1 << 5); - s->cla_inc = (1 << 11); -#endif + + solver_init_activities(s); + s->root_level = 0; s->random_seed = 91648253; s->progress_estimate = 0; diff --git a/src/sat/bsat/satSolver.h b/src/sat/bsat/satSolver.h index 7ef2c9e8..5a8483c1 100644 --- a/src/sat/bsat/satSolver.h +++ b/src/sat/bsat/satSolver.h @@ -30,11 +30,10 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #include "satVec.h" #include "satClause.h" +#include "misc/util/utilDouble.h" ABC_NAMESPACE_HEADER_START -//#define USE_FLOAT_ACTIVITY - //================================================================================================= // Public interface: @@ -42,6 +41,7 @@ struct sat_solver_t; typedef struct sat_solver_t sat_solver; extern sat_solver* sat_solver_new(void); +extern sat_solver* zsat_solver_new_seed(double seed); extern void sat_solver_delete(sat_solver* s); extern int sat_solver_addclause(sat_solver* s, lit* begin, lit* end); @@ -54,6 +54,7 @@ extern int sat_solver_push(sat_solver* s, int p); extern void sat_solver_pop(sat_solver* s); extern void sat_solver_set_resource_limits(sat_solver* s, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, ABC_INT64_T nConfLimitGlobal, ABC_INT64_T nInsLimitGlobal); extern void sat_solver_restart( sat_solver* s ); +extern void zsat_solver_restart_seed( sat_solver* s, double seed ); extern void sat_solver_rollback( sat_solver* s ); extern int sat_solver_nvars(sat_solver* s); @@ -106,7 +107,6 @@ struct sat_solver_t int hBinary; // the special binary clause clause * binary; veci* wlists; // watcher lists - veci act_clas; // contain clause activities // rollback int iVarPivot; // the pivot for variables @@ -114,19 +114,17 @@ struct sat_solver_t int hProofPivot; // the pivot for proof records // activities -#ifdef USE_FLOAT_ACTIVITY - double var_inc; // Amount to bump next variable with. - double var_decay; // INVERSE decay factor for variable activity: stores 1/decay. - float cla_inc; // Amount to bump next clause with. - float cla_decay; // INVERSE decay factor for clause activity: stores 1/decay. - double* activity; // A heuristic measurement of the activity of a variable. -#else - int var_inc; // Amount to bump next variable with. - int var_inc2; // Amount to bump next variable with. - int cla_inc; // Amount to bump next clause with. - unsigned* activity; // A heuristic measurement of the activity of a variable. - unsigned* activity2; // backup variable activity -#endif + int VarActType; + int ClaActType; + word var_inc; // Amount to bump next variable with. + word var_inc2; // Amount to bump next variable with. + word var_decay; // INVERSE decay factor for variable activity: stores 1/decay. + word* activity; // A heuristic measurement of the activity of a variable. + word* activity2; // backup variable activity + unsigned cla_inc; // Amount to bump next clause with. + unsigned cla_decay; // INVERSE decay factor for clause activity: stores 1/decay. + veci act_clas; // contain clause activities + char * pFreqs; // how many times this variable was assigned a value int nVarUsed; @@ -216,9 +214,25 @@ static int sat_solver_var_literal( sat_solver* s, int v ) static void sat_solver_act_var_clear(sat_solver* s) { int i; - for (i = 0; i < s->size; i++) - s->activity[i] = 0; - s->var_inc = 1; + if ( s->VarActType == 0 ) + { + for (i = 0; i < s->size; i++) + s->activity[i] = (1 << 10); + s->var_inc = (1 << 5); + } + else if ( s->VarActType == 1 ) + { + for (i = 0; i < s->size; i++) + s->activity[i] = 0; + s->var_inc = 1; + } + else if ( s->VarActType == 2 ) + { + for (i = 0; i < s->size; i++) + s->activity[i] = Xdbl_Const1(); + s->var_inc = Xdbl_Const1(); + } + else assert(0); } static void sat_solver_compress(sat_solver* s) { @@ -229,7 +243,12 @@ static void sat_solver_compress(sat_solver* s) (void) RetValue; } } - +static void sat_solver_delete_p( sat_solver ** ps ) +{ + if ( *ps ) + sat_solver_delete( *ps ); + *ps = NULL; +} static void sat_solver_clean_polarity(sat_solver* s, int * pVars, int nVars ) { int i; @@ -280,7 +299,7 @@ static inline void sat_solver_bookmark(sat_solver* s) if ( s->activity2 ) { s->var_inc2 = s->var_inc; - memcpy( s->activity2, s->activity, sizeof(unsigned) * s->iVarPivot ); + memcpy( s->activity2, s->activity, sizeof(word) * s->iVarPivot ); } } static inline void sat_solver_set_pivot_variables( sat_solver* s, int * pPivots, int nPivots ) diff --git a/src/sat/cnf/cnfUtil.c b/src/sat/cnf/cnfUtil.c index 96002df8..5ccbeb0d 100644 --- a/src/sat/cnf/cnfUtil.c +++ b/src/sat/cnf/cnfUtil.c @@ -374,7 +374,7 @@ Cnf_Dat_t * Cnf_DataReadFromFile( char * pFileName ) // create pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); pCnf->nVars = nVars; - pCnf->nClauses = nClas; + pCnf->nClauses = Vec_IntSize(vClas)-1; pCnf->nLiterals = Vec_IntSize(vLits); pCnf->pClauses = ABC_ALLOC( int *, Vec_IntSize(vClas) ); pCnf->pClauses[0] = Vec_IntReleaseArray(vLits); diff --git a/src/sat/satoko/LICENSE b/src/sat/satoko/LICENSE new file mode 100644 index 00000000..51938137 --- /dev/null +++ b/src/sat/satoko/LICENSE @@ -0,0 +1,22 @@ +Copyright 2017, Bruno Schmitt - UC Berkeley / UFRGS (bruno@oschmitt.com) + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/sat/satoko/act_clause.h b/src/sat/satoko/act_clause.h new file mode 100644 index 00000000..ade5e569 --- /dev/null +++ b/src/sat/satoko/act_clause.h @@ -0,0 +1,43 @@ +//===--- act_var.h ----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__act_clause_h +#define satoko__act_clause_h + +#include "solver.h" +#include "types.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +static inline void clause_act_rescale(solver_t *s) +{ + unsigned i, cref; + struct clause *clause; + + vec_uint_foreach(s->learnts, cref, i) { + clause = clause_read(s, cref); + clause->data[clause->size].act >>= 10; + } + s->clause_act_inc = stk_uint_max((s->clause_act_inc >> 10), (1 << 11)); +} + +static inline void clause_act_bump(solver_t *s, struct clause *clause) +{ + clause->data[clause->size].act += s->clause_act_inc; + if (clause->data[clause->size].act & 0x80000000) + clause_act_rescale(s); +} + +static inline void clause_act_decay(solver_t *s) +{ + s->clause_act_inc += (s->clause_act_inc >> 10); +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__act_clause_h */ diff --git a/src/sat/satoko/act_var.h b/src/sat/satoko/act_var.h new file mode 100644 index 00000000..6b0ff98a --- /dev/null +++ b/src/sat/satoko/act_var.h @@ -0,0 +1,53 @@ +//===--- act_var.h ----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__act_var_h +#define satoko__act_var_h + +#include "solver.h" +#include "types.h" +#include "utils/heap.h" +#include "utils/sdbl.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +/** Re-scale the activity value for all variables. + */ +static inline void var_act_rescale(solver_t *s) +{ + unsigned i; + act_t *activity = vec_act_data(s->activity); + + for (i = 0; i < vec_sdbl_size(s->activity); i++) + activity[i] = sdbl_div(activity[i], s->opts.var_act_rescale); + s->var_act_inc = sdbl_div(s->var_act_inc, s->opts.var_act_rescale); +} + +/** Increment the activity value of one variable ('var') + */ +static inline void var_act_bump(solver_t *s, unsigned var) +{ + act_t *activity = vec_act_data(s->activity); + + activity[var] = sdbl_add(activity[var], s->var_act_inc); + if (activity[var] > s->opts.var_act_limit) + var_act_rescale(s); + if (heap_in_heap(s->var_order, var)) + heap_decrease(s->var_order, var); +} + +/** Increment the value by which variables activity values are incremented + */ +static inline void var_act_decay(solver_t *s) +{ + s->var_act_inc = sdbl_mult(s->var_act_inc, double2sdbl(1 /s->opts.var_decay)); +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__act_var_h */ diff --git a/src/sat/satoko/cdb.h b/src/sat/satoko/cdb.h new file mode 100644 index 00000000..32b0bf93 --- /dev/null +++ b/src/sat/satoko/cdb.h @@ -0,0 +1,106 @@ +//===--- cdb.h --------------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__cdb_h +#define satoko__cdb_h + +#include "clause.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +/* Clauses DB data structure */ +struct cdb { + unsigned size; + unsigned cap; + unsigned wasted; + unsigned *data; +}; + +//===------------------------------------------------------------------------=== +// Clause DB API +//===------------------------------------------------------------------------=== +static inline struct clause *cdb_handler(struct cdb *p, unsigned cref) +{ + return cref != 0xFFFFFFFF ? (struct clause *)(p->data + cref) : NULL; +} + +static inline unsigned cdb_cref(struct cdb *p, unsigned *clause) +{ + return (unsigned)(clause - &(p->data[0])); +} + +static inline void cdb_grow(struct cdb *p, unsigned cap) +{ + unsigned prev_cap = p->cap; + + if (p->cap >= cap) + return; + while (p->cap < cap) { + unsigned delta = ((p->cap >> 1) + (p->cap >> 3) + 2) & (unsigned)(~1); + p->cap += delta; + assert(p->cap >= prev_cap); + } + assert(p->cap > 0); + p->data = satoko_realloc(unsigned, p->data, p->cap); +} + +static inline struct cdb *cdb_alloc(unsigned cap) +{ + struct cdb *p = satoko_calloc(struct cdb, 1); + if (cap <= 0) + cap = 1024 * 1024; + cdb_grow(p, cap); + return p; +} + +static inline void cdb_free(struct cdb *p) +{ + satoko_free(p->data); + satoko_free(p); +} + +static inline unsigned cdb_append(struct cdb *p, unsigned size) +{ + unsigned prev_size; + assert(size > 0); + cdb_grow(p, p->size + size); + prev_size = p->size; + p->size += size; + assert(p->size > prev_size); + return prev_size; +} + +static inline void cdb_remove(struct cdb *p, struct clause *clause) +{ + p->wasted += clause->size; +} + +static inline void cdb_clear(struct cdb *p) +{ + p->wasted = 0; + p->size = 0; +} + +static inline unsigned cdb_capacity(struct cdb *p) +{ + return p->cap; +} + +static inline unsigned cdb_size(struct cdb *p) +{ + return p->size; +} + +static inline unsigned cdb_wasted(struct cdb *p) +{ + return p->wasted; +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__cdb_h */ diff --git a/src/sat/satoko/clause.h b/src/sat/satoko/clause.h new file mode 100644 index 00000000..2be18cd6 --- /dev/null +++ b/src/sat/satoko/clause.h @@ -0,0 +1,63 @@ +//===--- clause.h -----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__clause_h +#define satoko__clause_h + +#include "types.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +struct clause { + unsigned f_learnt : 1; + unsigned f_mark : 1; + unsigned f_reallocd : 1; + unsigned f_deletable : 1; + unsigned lbd : 28; + unsigned size; + union { + unsigned lit; + clause_act_t act; + } data[0]; +}; + +//===------------------------------------------------------------------------=== +// Clause API +//===------------------------------------------------------------------------=== +static inline int clause_compare(const void *p1, const void *p2) +{ + const struct clause *c1 = (const struct clause *)p1; + const struct clause *c2 = (const struct clause *)p2; + + if (c1->size > 2 && c2->size == 2) + return 1; + if (c1->size == 2 && c2->size > 2) + return 0; + if (c1->size == 2 && c2->size == 2) + return 0; + + if (c1->lbd > c2->lbd) + return 1; + if (c1->lbd < c2->lbd) + return 0; + + return c1->data[c1->size].act < c2->data[c2->size].act; +} + +static inline void clause_print(struct clause *clause) +{ + unsigned i; + printf("{ "); + for (i = 0; i < clause->size; i++) + printf("%u ", clause->data[i].lit); + printf("}\n"); +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__clause_h */ diff --git a/src/sat/satoko/cnf_reader.c b/src/sat/satoko/cnf_reader.c new file mode 100644 index 00000000..adb9a47b --- /dev/null +++ b/src/sat/satoko/cnf_reader.c @@ -0,0 +1,156 @@ +//===--- cnf_reader.h -------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#include <assert.h> +#include <ctype.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "satoko.h" +#include "solver.h" +#include "utils/mem.h" +#include "utils/vec/vec_uint.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_IMPL_START + +/** Read the file into an internal buffer. + * + * This function will receive a file name. The return data is a string ended + * with '\0'. + * + */ +static char * file_open(const char *fname) +{ + FILE *file = fopen(fname, "rb"); + char *buffer; + int sz_file; + int ret; + + if (file == NULL) { + printf("Couldn't open file: %s\n", fname); + return NULL; + } + fseek(file, 0, SEEK_END); + sz_file = ftell(file); + rewind(file); + buffer = satoko_alloc(char, sz_file + 3); + ret = fread(buffer, sz_file, 1, file); + buffer[sz_file + 0] = '\n'; + buffer[sz_file + 1] = '\0'; + return buffer; +} + +static void skip_spaces(char **pos) +{ + assert(pos != NULL); + for (; isspace(**pos); (*pos)++); +} + +static void skip_line(char **pos) +{ + assert(pos != NULL); + for(; **pos != '\n' && **pos != '\r' && **pos != EOF; (*pos)++); + if (**pos != EOF) + (*pos)++; + return; +} + +static int read_int(char **token) +{ + int value = 0; + int neg = 0; + + skip_spaces(token); + if (**token == '-') { + neg = 1; + (*token)++; + } else if (**token == '+') + (*token)++; + + if (!isdigit(**token)) { + printf("Parsing error. Unexpected char: %c.\n", **token); + exit(EXIT_FAILURE); + } + while (isdigit(**token)) { + value = (value * 10) + (**token - '0'); + (*token)++; + } + return neg ? -value : value; +} + +static void read_clause(char **token, vec_uint_t *lits) +{ + int var; + unsigned sign; + + vec_uint_clear(lits); + while (1) { + var = read_int(token); + if (var == 0) + break; + sign = (var > 0); + var = abs(var) - 1; + vec_uint_push_back(lits, var2lit((unsigned) var, (char)!sign)); + } +} + +/** Start the solver and reads the DIMAC file. + * + * Returns false upon immediate conflict. + */ +int satoko_parse_dimacs(char *fname, satoko_t **solver) +{ + satoko_t *p = NULL; + vec_uint_t *lits = NULL; + int n_var; + int n_clause; + char *buffer = file_open(fname); + char *token; + + if (buffer == NULL) + return -1; + + token = buffer; + while (1) { + skip_spaces(&token); + if (*token == 0) + break; + else if (*token == 'c') + skip_line(&token); + else if (*token == 'p') { + token++; + skip_spaces(&token); + for(; !isspace(*token); token++); /* skip 'cnf' */ + + n_var = read_int(&token); + n_clause = read_int(&token); + skip_line(&token); + lits = vec_uint_alloc((unsigned) n_var); + p = satoko_create(); + } else { + if (lits == NULL) { + printf("There is no parameter line.\n"); + satoko_free(buffer); + return -1; + } + read_clause(&token, lits); + if (!satoko_add_clause(p, (int*)vec_uint_data(lits), vec_uint_size(lits))) { + vec_uint_print(lits); + return 0; + } + } + } + vec_uint_free(lits); + satoko_free(buffer); + *solver = p; + return satoko_simplify(p); +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/satoko/module.make b/src/sat/satoko/module.make new file mode 100644 index 00000000..512094ee --- /dev/null +++ b/src/sat/satoko/module.make @@ -0,0 +1,3 @@ +SRC += src/sat/satoko/solver.c \ + src/sat/satoko/solver_api.c \ + src/sat/satoko/cnf_reader.c diff --git a/src/sat/satoko/satoko.h b/src/sat/satoko/satoko.h new file mode 100644 index 00000000..a0c4d216 --- /dev/null +++ b/src/sat/satoko/satoko.h @@ -0,0 +1,114 @@ +//===--- satoko.h -----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__satoko_h +#define satoko__satoko_h + +#include "types.h" +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +/** Return valeus */ +enum { + SATOKO_ERR = 0, + SATOKO_OK = 1 +}; + +enum { + SATOKO_UNDEC = 0, /* Undecided */ + SATOKO_SAT = 1, + SATOKO_UNSAT = -1 +}; + +struct solver_t_; +typedef struct solver_t_ satoko_t; + +typedef struct satoko_opts satoko_opts_t; +struct satoko_opts { + /* Limits */ + long conf_limit; /* Limit on the n.of conflicts */ + long prop_limit; /* Limit on the n.of propagations */ + + /* Constants used for restart heuristic */ + double f_rst; /* Used to force a restart */ + double b_rst; /* Used to block a restart */ + unsigned fst_block_rst; /* Lower bound n.of conflicts for start blocking restarts */ + unsigned sz_lbd_bqueue; /* Size of the moving avarege queue for LBD (force restart) */ + unsigned sz_trail_bqueue; /* Size of the moving avarege queue for Trail size (block restart) */ + + /* Constants used for clause database reduction heuristic */ + unsigned n_conf_fst_reduce; /* N.of conflicts before first clause databese reduction */ + unsigned inc_reduce; /* Increment to reduce */ + unsigned inc_special_reduce; /* Special increment to reduce */ + unsigned lbd_freeze_clause; + float learnt_ratio; /* Percentage of learned clauses to remove */ + + /* VSIDS heuristic */ + double var_decay; + float clause_decay; + unsigned var_act_rescale; + act_t var_act_limit; + + + /* Binary resolution */ + unsigned clause_max_sz_bin_resol; + unsigned clause_min_lbd_bin_resol; + float garbage_max_ratio; + char verbose; +}; + +typedef struct satoko_stats satoko_stats_t; +struct satoko_stats { + unsigned n_starts; + unsigned n_reduce_db; + + long n_decisions; + long n_propagations; + long n_inspects; + long n_conflicts; + + long n_original_lits; + long n_learnt_lits; +}; + + +//===------------------------------------------------------------------------=== +extern satoko_t *satoko_create(void); +extern void satoko_destroy(satoko_t *); +extern void satoko_reset(satoko_t *); + +extern void satoko_default_opts(satoko_opts_t *); +extern void satoko_configure(satoko_t *, satoko_opts_t *); +extern int satoko_parse_dimacs(char *, satoko_t **); +extern int satoko_add_variable(satoko_t *, char); +extern int satoko_add_clause(satoko_t *, int *, int); +extern void satoko_assump_push(satoko_t *s, int); +extern void satoko_assump_pop(satoko_t *s); +extern int satoko_simplify(satoko_t *); +extern int satoko_solve(satoko_t *); +extern void satoko_mark_cone(satoko_t *, int *, int); +extern void satoko_unmark_cone(satoko_t *, int *, int); + +extern void satoko_rollback(satoko_t *); +extern void satoko_bookmark(satoko_t *); +extern void satoko_unbookmark(satoko_t *); +/* If problem is unsatisfiable under assumptions, this function is used to + * obtain the final conflict clause expressed in the assumptions. + * + * - It receives as inputs the solver and a pointer to a array where clause + * will be copied. The memory is allocated by the solver, but must be freed by + * the caller. + * - The return value is either the size of the array or -1 in case the final + * conflict cluase was not generated. + */ +extern int satoko_final_conflict(satoko_t *, unsigned *); + +extern satoko_stats_t satoko_stats(satoko_t *); + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__satoko_h */ diff --git a/src/sat/satoko/solver.c b/src/sat/satoko/solver.c new file mode 100644 index 00000000..af3dcffb --- /dev/null +++ b/src/sat/satoko/solver.c @@ -0,0 +1,718 @@ +//===--- solver.c -----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <math.h> + +#include "act_clause.h" +#include "act_var.h" +#include "solver.h" +#include "utils/heap.h" +#include "utils/mem.h" +#include "utils/sort.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_IMPL_START + +//===------------------------------------------------------------------------=== +// Lit funtions +//===------------------------------------------------------------------------=== +/** + * A literal is said to be redundant in a given clause if and only if all + * variables in its reason are either present in that clause or (recursevely) + * redundant. + */ +static inline int lit_is_removable(solver_t* s, unsigned lit, unsigned min_level) +{ + unsigned top = vec_uint_size(s->tagged); + + assert(lit_reason(s, lit) != UNDEF); + vec_uint_clear(s->stack); + vec_uint_push_back(s->stack, lit2var(lit)); + while (vec_uint_size(s->stack)) { + unsigned i; + unsigned var = vec_uint_pop_back(s->stack); + struct clause *c = clause_read(s, var_reason(s, var)); + unsigned *lits = &(c->data[0].lit); + + assert(var_reason(s, var) != UNDEF); + if (c->size == 2 && lit_value(s, lits[0]) == LIT_FALSE) { + assert(lit_value(s, lits[1]) == LIT_TRUE); + stk_swap(unsigned, lits[0], lits[1]); + } + + /* Check scan the literals of the reason clause. + * The first literal is skiped because is the literal itself. */ + for (i = 1; i < c->size; i++) { + var = lit2var(lits[i]); + + /* Check if the variable has already been seen or if it + * was assinged a value at the decision level 0. In a + * positive case, there is no need to look any further */ + if (vec_char_at(s->seen, var) || var_dlevel(s, var) == 0) + continue; + + /* If the variable has a reason clause and if it was + * assingned at a 'possible' level, then we need to + * check if it is recursively redundant, otherwise the + * literal being checked is not redundant */ + if (var_reason(s, var) != UNDEF && ((1 << (var_dlevel(s, var) & 31)) & min_level)) { + vec_uint_push_back(s->stack, var); + vec_uint_push_back(s->tagged, var); + vec_char_assign(s->seen, var, 1); + } else { + vec_uint_foreach_start(s->tagged, var, i, top) + vec_char_assign(s->seen, var, 0); + vec_uint_shrink(s->tagged, top); + return 0; + } + } + } + return 1; +} + +//===------------------------------------------------------------------------=== +// Clause functions +//===------------------------------------------------------------------------=== +/* Calculate clause LBD (Literal Block Distance): + * - It's the number of variables in the final conflict clause that come from + * different decision levels + */ +static inline unsigned clause_clac_lbd(solver_t *s, unsigned *lits, unsigned size) +{ + unsigned i; + unsigned lbd = 0; + + s->cur_stamp++; + for (i = 0; i < size; i++) { + unsigned level = lit_dlevel(s, lits[i]); + if (vec_uint_at(s->stamps, level) != s->cur_stamp) { + vec_uint_assign(s->stamps, level, s->cur_stamp); + lbd++; + } + } + return lbd; +} + +static inline void clause_bin_resolution(solver_t *s, vec_uint_t *clause_lits) +{ + unsigned *lits = vec_uint_data(clause_lits); + unsigned counter, sz, i; + unsigned lit; + unsigned neg_lit = lit_neg(lits[0]); + struct watcher *w; + + s->cur_stamp++; + vec_uint_foreach(clause_lits, lit, i) + vec_uint_assign(s->stamps, lit2var(lit), s->cur_stamp); + + counter = 0; + watch_list_foreach_bin(s->watches, w, neg_lit) { + unsigned imp_lit = w->blocker; + if (vec_uint_at(s->stamps, lit2var(imp_lit)) == s->cur_stamp && + lit_value(s, imp_lit) == LIT_TRUE) { + counter++; + vec_uint_assign(s->stamps, lit2var(imp_lit), (s->cur_stamp - 1)); + } + } + if (counter > 0) { + sz = vec_uint_size(clause_lits) - 1; + for (i = 1; i < vec_uint_size(clause_lits) - counter; i++) + if (vec_uint_at(s->stamps, lit2var(lits[i])) != s->cur_stamp) { + stk_swap(unsigned, lits[i], lits[sz]); + i--; + sz--; + } + vec_uint_shrink(clause_lits, vec_uint_size(clause_lits) - counter); + } +} + +static inline void clause_minimize(solver_t *s, vec_uint_t *clause_lits) +{ + unsigned i, j; + unsigned *lits = vec_uint_data(clause_lits); + unsigned min_level = 0; + unsigned clause_size; + + for (i = 1; i < vec_uint_size(clause_lits); i++) { + unsigned level = lit_dlevel(s, lits[i]); + min_level |= 1 << (level & 31); + } + + /* Remove reduntant literals */ + vec_uint_foreach(clause_lits, i, j) + vec_uint_push_back(s->tagged, lit2var(i)); + for (i = j = 1; i < vec_uint_size(clause_lits); i++) + if (lit_reason(s, lits[i]) == UNDEF || !lit_is_removable(s, lits[i], min_level)) + lits[j++] = lits[i]; + vec_uint_shrink(clause_lits, j); + + /* Binary Resolution */ + clause_size = vec_uint_size(clause_lits); + if (clause_size <= s->opts.clause_max_sz_bin_resol && + clause_clac_lbd(s, lits, clause_size) <= s->opts.clause_min_lbd_bin_resol) + clause_bin_resolution(s, clause_lits); +} + +static inline void clause_realloc(struct cdb *dest, struct cdb *src, unsigned *cref) +{ + unsigned new_cref; + struct clause *new_clause; + struct clause *old_clause = cdb_handler(src, *cref); + + if (old_clause->f_reallocd) { + *cref = (unsigned) old_clause->size; + return; + } + new_cref = cdb_append(dest, 3 + old_clause->f_learnt + old_clause->size); + new_clause = cdb_handler(dest, new_cref); + memcpy(new_clause, old_clause, (3 + old_clause->f_learnt + old_clause->size) * 4); + old_clause->f_reallocd = 1; + old_clause->size = (unsigned) new_cref; + *cref = new_cref; +} + +//===------------------------------------------------------------------------=== +// Solver internal functions +//===------------------------------------------------------------------------=== +static inline unsigned solver_decide(solver_t *s) +{ + unsigned next_var = UNDEF; + + while (next_var == UNDEF || var_value(s, next_var) != VAR_UNASSING) { + if (heap_size(s->var_order) == 0) { + next_var = UNDEF; + return UNDEF; + } + next_var = heap_remove_min(s->var_order); + if (solver_has_marks(s) && !var_mark(s, next_var)) + next_var = UNDEF; + } + return var2lit(next_var, var_polarity(s, next_var)); +} + +static inline void solver_new_decision(solver_t *s, unsigned lit) +{ + if (solver_has_marks(s) && !var_mark(s, lit2var(lit))) + return; + assert(var_value(s, lit2var(lit)) == VAR_UNASSING); + vec_uint_push_back(s->trail_lim, vec_uint_size(s->trail)); + solver_enqueue(s, lit, UNDEF); +} + +/* Calculate Backtrack Level from the learnt clause */ +static inline unsigned solver_calc_bt_level(solver_t *s, vec_uint_t *learnt) +{ + unsigned i, tmp; + unsigned i_max = 1; + unsigned *lits = vec_uint_data(learnt); + unsigned max = lit_dlevel(s, lits[1]); + + if (vec_uint_size(learnt) == 1) + return 0; + for (i = 2; i < vec_uint_size(learnt); i++) { + if (lit_dlevel(s, lits[i]) > max) { + max = lit_dlevel(s, lits[i]); + i_max = i; + } + } + tmp = lits[1]; + lits[1] = lits[i_max]; + lits[i_max] = tmp; + return lit_dlevel(s, lits[1]); +} + +/** + * Most books and papers explain conflict analysis and the calculation of the + * 1UIP (first Unique Implication Point) using an implication graph. This + * function, however, do not explicity constructs the graph! It inspects the + * trail in reverse and figure out which literals should be added to the + * to-be-learnt clause using the reasons of each assignment. + * + * cur_lit: current literal being analyzed. + * n_paths: number of unprocessed paths from conlfict node to the current + * literal being analyzed (cur_lit). + * + * This functions performs a backward BFS (breadth-first search) for 1UIP node. + * The trail works as the BFS queue. The counter of unprocessed but seen + * variables (n_paths) allows us to identify when 'cur_lit' is the closest + * cause of conflict. + * + * When 'n_paths' reaches zero it means there are no unprocessed reverse paths + * back from the conflict node to 'cur_lit' - meaning it is the 1UIP decision + * variable. + * + */ +static inline void solver_analyze(solver_t *s, unsigned cref, vec_uint_t *learnt, + unsigned *bt_level, unsigned *lbd) +{ + unsigned i; + unsigned *trail = vec_uint_data(s->trail); + unsigned idx = vec_uint_size(s->trail) - 1; + unsigned n_paths = 0; + unsigned p = UNDEF; + unsigned var; + + vec_uint_push_back(learnt, UNDEF); + do { + struct clause *clause; + unsigned *lits; + unsigned j; + + assert(cref != UNDEF); + clause = clause_read(s, cref); + lits = &(clause->data[0].lit); + + if (p != UNDEF && clause->size == 2 && lit_value(s, lits[0]) == LIT_FALSE) { + assert(lit_value(s, lits[1]) == LIT_TRUE); + stk_swap(unsigned, lits[0], lits[1] ); + } + + if (clause->f_learnt) + clause_act_bump(s, clause); + + if (clause->f_learnt && clause->lbd > 2) { + unsigned n_levels = clause_clac_lbd(s, lits, clause->size); + if (n_levels + 1 < clause->lbd) { + if (clause->lbd <= s->opts.lbd_freeze_clause) + clause->f_deletable = 0; + clause->lbd = n_levels; + } + } + + for (j = (p == UNDEF ? 0 : 1); j < clause->size; j++) { + var = lit2var(lits[j]); + if (vec_char_at(s->seen, var) || var_dlevel(s, var) == 0) + continue; + vec_char_assign(s->seen, var, 1); + var_act_bump(s, var); + if (var_dlevel(s, var) == solver_dlevel(s)) { + n_paths++; + if (var_reason(s, var) != UNDEF && clause_read(s, var_reason(s, var))->f_learnt) + vec_uint_push_back(s->last_dlevel, var); + } else + vec_uint_push_back(learnt, lits[j]); + } + + while (!vec_char_at(s->seen, lit2var(trail[idx--]))); + + p = trail[idx + 1]; + cref = lit_reason(s, p); + vec_char_assign(s->seen, lit2var(p), 0); + n_paths--; + } while (n_paths > 0); + + vec_uint_data(learnt)[0] = lit_neg(p); + clause_minimize(s, learnt); + *bt_level = solver_calc_bt_level(s, learnt); + *lbd = clause_clac_lbd(s, vec_uint_data(learnt), vec_uint_size(learnt)); + + if (vec_uint_size(s->last_dlevel) > 0) { + vec_uint_foreach(s->last_dlevel, var, i) { + if (clause_read(s, var_reason(s, var))->lbd < *lbd) + var_act_bump(s, var); + } + vec_uint_clear(s->last_dlevel); + } + vec_uint_foreach(s->tagged, var, i) + vec_char_assign(s->seen, var, 0); + vec_uint_clear(s->tagged); +} + +static inline int solver_rst(solver_t *s) +{ + return b_queue_is_valid(s->bq_lbd) && + (((long)b_queue_avg(s->bq_lbd) * s->opts.f_rst) > (s->sum_lbd / s->stats.n_conflicts)); +} + +static inline int solver_block_rst(solver_t *s) +{ + return s->stats.n_conflicts > (int)s->opts.fst_block_rst && + b_queue_is_valid(s->bq_lbd) && + ((long)vec_uint_size(s->trail) > (s->opts.b_rst * (long)b_queue_avg(s->bq_trail))); +} + +static inline void solver_handle_conflict(solver_t *s, unsigned confl_cref) +{ + unsigned bt_level; + unsigned lbd; + unsigned cref; + + vec_uint_clear(s->temp_lits); + solver_analyze(s, confl_cref, s->temp_lits, &bt_level, &lbd); + s->sum_lbd += lbd; + b_queue_push(s->bq_lbd, lbd); + solver_cancel_until(s, bt_level); + cref = UNDEF; + if (vec_uint_size(s->temp_lits) > 1) { + cref = solver_clause_create(s, s->temp_lits, 1); + clause_watch(s, cref); + } + solver_enqueue(s, vec_uint_at(s->temp_lits, 0), cref); + var_act_decay(s); + clause_act_decay(s); +} + +static inline void solver_analyze_final(solver_t *s, unsigned lit) +{ + int i; + + vec_uint_clear(s->final_conflict); + vec_uint_push_back(s->final_conflict, lit); + if (solver_dlevel(s) == 0) + return; + vec_char_assign(s->seen, lit2var(lit), 1); + for (i = (int) vec_uint_size(s->trail) - 1; i >= (int) vec_uint_at(s->trail_lim, 0); i--) { + unsigned var = lit2var(vec_uint_at(s->trail, i)); + + if (vec_char_at(s->seen, var)) { + unsigned reason = var_reason(s, var); + if (reason == UNDEF) { + assert(var_dlevel(s, var) > 0); + vec_uint_push_back(s->final_conflict, lit_neg(vec_uint_at(s->trail, i))); + } else { + unsigned j; + struct clause *clause = clause_read(s, reason); + for (j = (clause->size == 2 ? 0 : 1); j < clause->size; j++) { + if (lit_dlevel(s, clause->data[j].lit) > 0) + vec_char_assign(s->seen, lit2var(clause->data[j].lit), 1); + } + } + vec_char_assign(s->seen, var, 0); + } + } + vec_char_assign(s->seen, lit2var(lit), 0); +} + +static inline void solver_garbage_collect(solver_t *s) +{ + unsigned i; + unsigned *array; + struct cdb *new_cdb = cdb_alloc(cdb_capacity(s->all_clauses) - cdb_wasted(s->all_clauses)); + + if (s->book_cdb) + s->book_cdb = 0; + + for (i = 0; i < 2 * vec_char_size(s->assigns); i++) { + struct watcher *w; + watch_list_foreach(s->watches, w, i) + clause_realloc(new_cdb, s->all_clauses, &(w->cref)); + } + + /* Update CREFS */ + for (i = 0; i < vec_uint_size(s->trail); i++) + if (lit_reason(s, vec_uint_at(s->trail, i)) != UNDEF) + clause_realloc(new_cdb, s->all_clauses, &(vec_uint_data(s->reasons)[lit2var(vec_uint_at(s->trail, i))])); + + array = vec_uint_data(s->learnts); + for (i = 0; i < vec_uint_size(s->learnts); i++) + clause_realloc(new_cdb, s->all_clauses, &(array[i])); + + array = vec_uint_data(s->originals); + for (i = 0; i < vec_uint_size(s->originals); i++) + clause_realloc(new_cdb, s->all_clauses, &(array[i])); + + cdb_free(s->all_clauses); + s->all_clauses = new_cdb; +} + +static inline void solver_reduce_cdb(solver_t *s) +{ + unsigned i, limit; + unsigned n_learnts = vec_uint_size(s->learnts); + unsigned cref; + struct clause *clause; + struct clause **learnts_cls; + + learnts_cls = satoko_alloc(struct clause *, n_learnts); + vec_uint_foreach_start(s->learnts, cref, i, s->book_cl_lrnt) + learnts_cls[i] = clause_read(s, cref); + + limit = (unsigned)(n_learnts * s->opts.learnt_ratio); + + satoko_sort((void *)learnts_cls, n_learnts, + (int (*)(const void *, const void *)) clause_compare); + + if (learnts_cls[n_learnts / 2]->lbd <= 3) + s->RC2 += s->opts.inc_special_reduce; + if (learnts_cls[n_learnts - 1]->lbd <= 6) + s->RC2 += s->opts.inc_special_reduce; + + vec_uint_clear(s->learnts); + for (i = 0; i < n_learnts; i++) { + clause = learnts_cls[i]; + cref = cdb_cref(s->all_clauses, (unsigned *)clause); + assert(clause->f_mark == 0); + if (clause->f_deletable && clause->lbd > 2 && clause->size > 2 && lit_reason(s, clause->data[0].lit) != cref && (i < limit)) { + clause->f_mark = 1; + s->stats.n_learnt_lits -= clause->size; + clause_unwatch(s, cref); + cdb_remove(s->all_clauses, clause); + } else { + if (!clause->f_deletable) + limit++; + clause->f_deletable = 1; + vec_uint_push_back(s->learnts, cref); + } + } + satoko_free(learnts_cls); + + if (s->opts.verbose) { + printf("reduceDB: Keeping %7d out of %7d clauses (%5.2f %%) \n", + vec_uint_size(s->learnts), n_learnts, + 100.0 * vec_uint_size(s->learnts) / n_learnts); + fflush(stdout); + } + if (cdb_wasted(s->all_clauses) > cdb_size(s->all_clauses) * s->opts.garbage_max_ratio) + solver_garbage_collect(s); +} + +//===------------------------------------------------------------------------=== +// Solver external functions +//===------------------------------------------------------------------------=== +unsigned solver_clause_create(solver_t *s, vec_uint_t *lits, unsigned f_learnt) +{ + struct clause *clause; + unsigned cref; + unsigned n_words; + + assert(vec_uint_size(lits) > 1); + assert(f_learnt == 0 || f_learnt == 1); + + n_words = 3 + f_learnt + vec_uint_size(lits); + cref = cdb_append(s->all_clauses, n_words); + clause = clause_read(s, cref); + clause->f_learnt = f_learnt; + clause->f_mark = 0; + clause->f_reallocd = 0; + clause->f_deletable = f_learnt; + clause->size = vec_uint_size(lits); + memcpy(&(clause->data[0].lit), vec_uint_data(lits), sizeof(unsigned) * vec_uint_size(lits)); + + if (f_learnt) { + vec_uint_push_back(s->learnts, cref); + clause->lbd = clause_clac_lbd(s, vec_uint_data(lits), vec_uint_size(lits)); + clause->data[clause->size].act = 0; + s->stats.n_learnt_lits += vec_uint_size(lits); + clause_act_bump(s, clause); + } else { + vec_uint_push_back(s->originals, cref); + s->stats.n_original_lits += vec_uint_size(lits); + } + return cref; +} + +void solver_cancel_until(solver_t *s, unsigned level) +{ + int i; + + if (solver_dlevel(s) <= level) + return; + for (i = (int) vec_uint_size(s->trail) - 1; i >= (int) vec_uint_at(s->trail_lim, level); i--) { + unsigned var = lit2var(vec_uint_at(s->trail, (unsigned) i)); + + vec_char_assign(s->assigns, var, VAR_UNASSING); + vec_uint_assign(s->reasons, var, UNDEF); + vec_char_assign(s->polarity, var, lit_polarity(vec_uint_at(s->trail, (unsigned) i))); + if (!heap_in_heap(s->var_order, var)) + heap_insert(s->var_order, var); + } + s->i_qhead = vec_uint_at(s->trail_lim, level); + vec_uint_shrink(s->trail, vec_uint_at(s->trail_lim, level)); + vec_uint_shrink(s->trail_lim, level); +} + +unsigned solver_propagate(solver_t *s) +{ + unsigned conf_cref = UNDEF; + unsigned *lits; + unsigned neg_lit; + unsigned n_propagations = 0; + + while (s->i_qhead < vec_uint_size(s->trail)) { + unsigned p = vec_uint_at(s->trail, s->i_qhead++); + struct watch_list *ws; + struct watcher *begin; + struct watcher *end; + struct watcher *i, *j; + + n_propagations++; + watch_list_foreach_bin(s->watches, i, p) { + if (solver_has_marks(s) && !var_mark(s, lit2var(i->blocker))) + continue; + if (var_value(s, lit2var(i->blocker)) == VAR_UNASSING) + solver_enqueue(s, i->blocker, i->cref); + else if (lit_value(s, i->blocker) == LIT_FALSE) + return i->cref; + } + + ws = vec_wl_at(s->watches, p); + begin = watch_list_array(ws); + end = begin + watch_list_size(ws); + for (i = j = begin + ws->n_bin; i < end;) { + struct clause *clause; + struct watcher w; + + if (solver_has_marks(s) && !var_mark(s, lit2var(i->blocker))) { + *j++ = *i++; + continue; + } + if (lit_value(s, i->blocker) == LIT_TRUE) { + *j++ = *i++; + continue; + } + + clause = clause_read(s, i->cref); + lits = &(clause->data[0].lit); + + // Make sure the false literal is data[1]: + neg_lit = lit_neg(p); + if (lits[0] == neg_lit) + stk_swap(unsigned, lits[0], lits[1]); + assert(lits[1] == neg_lit); + + w.cref = i->cref; + w.blocker = lits[0]; + + /* If 0th watch is true, then clause is already satisfied. */ + if (lits[0] != i->blocker && lit_value(s, lits[0]) == LIT_TRUE) + *j++ = w; + else { + /* Look for new watch */ + unsigned k; + for (k = 2; k < clause->size; k++) { + if (lit_value(s, lits[k]) != LIT_FALSE) { + lits[1] = lits[k]; + lits[k] = neg_lit; + watch_list_push(vec_wl_at(s->watches, lit_neg(lits[1])), w, 0); + goto next; + } + } + + *j++ = w; + + /* Clause becomes unit under this assignment */ + if (lit_value(s, lits[0]) == LIT_FALSE) { + conf_cref = i->cref; + s->i_qhead = vec_uint_size(s->trail); + i++; + // Copy the remaining watches: + while (i < end) + *j++ = *i++; + } else + solver_enqueue(s, lits[0], i->cref); + } + next: + i++; + } + + s->stats.n_inspects += j - watch_list_array(ws); + watch_list_shrink(ws, j - watch_list_array(ws)); + } + s->stats.n_propagations += n_propagations; + s->n_props_simplify -= n_propagations; + return conf_cref; +} + +char solver_search(solver_t *s) +{ + s->stats.n_starts++; + while (1) { + unsigned confl_cref = solver_propagate(s); + if (confl_cref != UNDEF) { + s->stats.n_conflicts++; + if (solver_dlevel(s) == 0) + return SATOKO_UNSAT; + /* Restart heuristic */ + b_queue_push(s->bq_trail, vec_uint_size(s->trail)); + if (solver_block_rst(s)) + b_queue_clean(s->bq_lbd); + solver_handle_conflict(s, confl_cref); + } else { + /* No conflict */ + unsigned next_lit; + + if (solver_rst(s)) { + b_queue_clean(s->bq_lbd); + solver_cancel_until(s, 0); + return SATOKO_UNDEC; + } + if (solver_dlevel(s) == 0) + satoko_simplify(s); + + /* Reduce the set of learnt clauses */ + if (s->opts.learnt_ratio && + s->stats.n_conflicts >= s->n_confl_bfr_reduce) { + s->RC1 = (s->stats.n_conflicts / s->RC2) + 1; + solver_reduce_cdb(s); + s->RC2 += s->opts.inc_reduce; + s->n_confl_bfr_reduce = s->RC1 * s->RC2; + } + + /* Make decisions based on user assumptions */ + next_lit = UNDEF; + while (solver_dlevel(s) < vec_uint_size(s->assumptions)) { + unsigned lit = vec_uint_at(s->assumptions, solver_dlevel(s)); + if (lit_value(s, lit) == LIT_TRUE) { + vec_uint_push_back(s->trail_lim, vec_uint_size(s->trail)); + } else if (lit_value(s, lit) == LIT_FALSE) { + solver_analyze_final(s, lit_neg(lit)); + return SATOKO_UNSAT; + } else { + next_lit = lit; + break; + } + + } + if (next_lit == UNDEF) { + s->stats.n_decisions++; + next_lit = solver_decide(s); + if (next_lit == UNDEF) + return SATOKO_SAT; + } + solver_new_decision(s, next_lit); + } + } +} + +//===------------------------------------------------------------------------=== +// Debug procedure +//===------------------------------------------------------------------------=== +void solver_debug_check(solver_t *s, int result) +{ + unsigned cref, i; + unsigned *array; + + printf("Checking for trail(%u) inconsistencies...", vec_uint_size(s->trail)); + array = vec_uint_data(s->trail); + for (i = 1; i < vec_uint_size(s->trail); i++) + if (array[i - 1] == lit_neg(array[i])) { + printf("Inconsistent trail: %u %u\n", array[i - 1], array[i]); + return; + } + printf(" TRAIL OK\n"); + + printf("Checking clauses... \n"); + vec_uint_foreach(s->originals, cref, i) { + unsigned j; + struct clause *clause = clause_read(s, cref); + for (j = 0; j < clause->size; j++) { + if (vec_uint_find(s->trail, clause->data[j].lit)) { + break; + } + } + if (result == SATOKO_SAT && j == clause->size) { + printf("FOUND UNSAT CLAUSE!!!!\n"); + clause_print(clause); + } + } +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/satoko/solver.h b/src/sat/satoko/solver.h new file mode 100644 index 00000000..33f8ce88 --- /dev/null +++ b/src/sat/satoko/solver.h @@ -0,0 +1,254 @@ +//===--- solver.h -----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__solver_h +#define satoko__solver_h + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "clause.h" +#include "cdb.h" +#include "satoko.h" +#include "types.h" +#include "watch_list.h" +#include "utils/b_queue.h" +#include "utils/heap.h" +#include "utils/mem.h" +#include "utils/misc.h" +#include "utils/vec/vec_char.h" +#include "utils/vec/vec_sdbl.h" +#include "utils/vec/vec_uint.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +enum { + LIT_FALSE = 1, + LIT_TRUE = 0, + VAR_UNASSING = 3 +}; + +#define UNDEF 0xFFFFFFFF + +typedef struct solver_t_ solver_t; +struct solver_t_ { + /* User data */ + vec_uint_t *assumptions; + vec_uint_t *final_conflict; + + /* Clauses Database */ + struct cdb *all_clauses; + vec_uint_t *learnts; + vec_uint_t *originals; + vec_wl_t *watches; + + /* Activity heuristic */ + act_t var_act_inc; /* Amount to bump next variable with. */ + clause_act_t clause_act_inc; /* Amount to bump next clause with. */ + + /* Variable Information */ + vec_act_t *activity; /* A heuristic measurement of the activity of a variable. */ + heap_t *var_order; + vec_uint_t *levels; /* Decision level of the current assignment */ + vec_uint_t *reasons; /* Reason (clause) of the current assignment */ + vec_char_t *assigns; + vec_char_t *polarity; + + /* Assignments */ + vec_uint_t *trail; + vec_uint_t *trail_lim; /* Separator indices for different decision levels in 'trail'. */ + unsigned i_qhead; /* Head of propagation queue (as index into the trail). */ + unsigned n_assigns_simplify; /* Number of top-level assignments since + last execution of 'simplify()'. */ + long n_props_simplify; /* Remaining number of propagations that + must be made before next execution of + 'simplify()'. */ + + /* Temporary data used by Analyze */ + vec_uint_t *temp_lits; + vec_char_t *seen; + vec_uint_t *tagged; /* Stack */ + vec_uint_t *stack; + vec_uint_t *last_dlevel; + + /* Temporary data used by Search method */ + b_queue_t *bq_trail; + b_queue_t *bq_lbd; + long RC1; + long RC2; + long n_confl_bfr_reduce; + float sum_lbd; + + /* Misc temporary */ + unsigned cur_stamp; /* Used for marking literals and levels of interest */ + vec_uint_t *stamps; /* Multipurpose stamp used to calculate LBD and + * clauses minimization with binary resolution */ + + /* Bookmark */ + unsigned book_cl_orig; /* Bookmark for orignal problem clauses vector */ + unsigned book_cl_lrnt; /* Bookmark for learnt clauses vector */ + unsigned book_cdb; /* Bookmark clause database size */ + unsigned book_vars; /* Bookmark number of variables */ + unsigned book_trail; /* Bookmark trail size */ + + /* Temporary data used for solving cones */ + vec_char_t *marks; + + struct satoko_stats stats; + struct satoko_opts opts; +}; + +//===------------------------------------------------------------------------=== +extern unsigned solver_clause_create(solver_t *, vec_uint_t *, unsigned); +extern char solver_search(solver_t *); +extern void solver_cancel_until(solver_t *, unsigned); +extern unsigned solver_propagate(solver_t *); +extern void solver_debug_check(solver_t *, int); + +//===------------------------------------------------------------------------=== +// Inline var/lit functions +//===------------------------------------------------------------------------=== +static inline unsigned var2lit(unsigned var, char polarity) +{ + return var + var + ((unsigned) polarity != 0); +} + +static inline unsigned lit2var(unsigned lit) +{ + return lit >> 1; +} +//===------------------------------------------------------------------------=== +// Inline var functions +//===------------------------------------------------------------------------=== +static inline char var_value(solver_t *s, unsigned var) +{ + return vec_char_at(s->assigns, var); +} + +static inline char var_polarity(solver_t *s, unsigned var) +{ + return vec_char_at(s->polarity, var); +} + +static inline unsigned var_dlevel(solver_t *s, unsigned var) +{ + return vec_uint_at(s->levels, var); +} + +static inline unsigned var_reason(solver_t *s, unsigned var) +{ + return vec_uint_at(s->reasons, var); +} +static inline int var_mark(solver_t *s, unsigned var) +{ + return (int)vec_char_at(s->marks, var); +} +static inline void var_set_mark(solver_t *s, unsigned var) +{ + vec_char_assign(s->marks, var, 1); +} +static inline void var_clean_mark(solver_t *s, unsigned var) +{ + vec_char_assign(s->marks, var, 0); +} +//===------------------------------------------------------------------------=== +// Inline lit functions +//===------------------------------------------------------------------------=== +static inline unsigned lit_neg(unsigned lit) +{ + return lit ^ 1; +} + +static inline char lit_polarity(unsigned lit) +{ + return (char)(lit & 1); +} + +static inline char lit_value(solver_t *s, unsigned lit) +{ + return lit_polarity(lit) ^ vec_char_at(s->assigns, lit2var(lit)); +} + +static inline unsigned lit_dlevel(solver_t *s, unsigned lit) +{ + return vec_uint_at(s->levels, lit2var(lit)); +} + +static inline unsigned lit_reason(solver_t *s, unsigned lit) +{ + return vec_uint_at(s->reasons, lit2var(lit)); +} +//===------------------------------------------------------------------------=== +// Inline solver minor functions +//===------------------------------------------------------------------------=== +static inline unsigned solver_check_limits(solver_t *s) +{ + return (s->opts.conf_limit == 0 || s->opts.conf_limit >= s->stats.n_conflicts) && + (s->opts.prop_limit == 0 || s->opts.prop_limit >= s->stats.n_propagations); +} + +/** Returns current decision level */ +static inline unsigned solver_dlevel(solver_t *s) +{ + return vec_uint_size(s->trail_lim); +} + +static inline int solver_enqueue(solver_t *s, unsigned lit, unsigned reason) +{ + unsigned var = lit2var(lit); + + vec_char_assign(s->assigns, var, lit_polarity(lit)); + vec_uint_assign(s->levels, var, solver_dlevel(s)); + vec_uint_assign(s->reasons, var, reason); + vec_uint_push_back(s->trail, lit); + return SATOKO_OK; +} + +static inline int solver_varnum(solver_t *s) +{ + return vec_char_size(s->assigns); +} +static inline int solver_has_marks(solver_t *s) +{ + return (int)(s->marks != NULL); +} + +//===------------------------------------------------------------------------=== +// Inline clause functions +//===------------------------------------------------------------------------=== +static inline struct clause *clause_read(solver_t *s, unsigned cref) +{ + return cdb_handler(s->all_clauses, cref); +} + +static inline void clause_watch(solver_t *s, unsigned cref) +{ + struct clause *clause = cdb_handler(s->all_clauses, cref); + struct watcher w1; + struct watcher w2; + + w1.cref = cref; + w2.cref = cref; + w1.blocker = clause->data[1].lit; + w2.blocker = clause->data[0].lit; + watch_list_push(vec_wl_at(s->watches, lit_neg(clause->data[0].lit)), w1, (clause->size == 2)); + watch_list_push(vec_wl_at(s->watches, lit_neg(clause->data[1].lit)), w2, (clause->size == 2)); +} + +static inline void clause_unwatch(solver_t *s, unsigned cref) +{ + struct clause *clause = cdb_handler(s->all_clauses, cref); + watch_list_remove(vec_wl_at(s->watches, lit_neg(clause->data[0].lit)), cref, (clause->size == 2)); + watch_list_remove(vec_wl_at(s->watches, lit_neg(clause->data[1].lit)), cref, (clause->size == 2)); +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__solver_h */ diff --git a/src/sat/satoko/solver_api.c b/src/sat/satoko/solver_api.c new file mode 100644 index 00000000..3cb9f3d3 --- /dev/null +++ b/src/sat/satoko/solver_api.c @@ -0,0 +1,445 @@ +//===--- solver_api.h -------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <math.h> + +#include "act_var.h" +#include "solver.h" +#include "utils/misc.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_IMPL_START + +//===------------------------------------------------------------------------=== +// Satoko internal functions +//===------------------------------------------------------------------------=== +static inline void solver_rebuild_order(solver_t *s) +{ + unsigned var; + vec_uint_t *vars = vec_uint_alloc(vec_char_size(s->assigns)); + + for (var = 0; var < vec_char_size(s->assigns); var++) + if (var_value(s, var) == VAR_UNASSING) + vec_uint_push_back(vars, var); + heap_build(s->var_order, vars); + vec_uint_free(vars); +} + +static inline int clause_is_satisfied(solver_t *s, struct clause *clause) +{ + unsigned i; + unsigned *lits = &(clause->data[0].lit); + for (i = 0; i < clause->size; i++) + if (lit_value(s, lits[i]) == LIT_TRUE) + return SATOKO_OK; + return SATOKO_ERR; +} + +static inline void print_opts(solver_t *s) +{ + printf( "+-[ BLACK MAGIC - PARAMETERS ]-+\n"); + printf( "| |\n"); + printf( "|--> Restarts heuristic |\n"); + printf( "| * LBD Queue = %6d |\n", s->opts.sz_lbd_bqueue); + printf( "| * Trail Queue = %6d |\n", s->opts.sz_trail_bqueue); + printf( "| * f_rst = %6.2f |\n", s->opts.f_rst); + printf( "| * b_rst = %6.2f |\n", s->opts.b_rst); + printf( "| |\n"); + printf( "|--> Clause DB reduction: |\n"); + printf( "| * First = %6d |\n", s->opts.n_conf_fst_reduce); + printf( "| * Inc = %6d |\n", s->opts.inc_reduce); + printf( "| * Special Inc = %6d |\n", s->opts.inc_special_reduce); + printf( "| * Protected (LBD) < %2d |\n", s->opts.lbd_freeze_clause); + printf( "| |\n"); + printf( "|--> Binary resolution: |\n"); + printf( "| * Clause size < %3d |\n", s->opts.clause_max_sz_bin_resol); + printf( "| * Clause lbd < %3d |\n", s->opts.clause_min_lbd_bin_resol); + printf( "+------------------------------+\n\n"); +} + +static inline void print_stats(solver_t *s) +{ + printf("starts : %10d\n", s->stats.n_starts); + printf("conflicts : %10ld\n", s->stats.n_conflicts); + printf("decisions : %10ld\n", s->stats.n_decisions); + printf("propagations : %10ld\n", s->stats.n_propagations); +} + +//===------------------------------------------------------------------------=== +// Satoko external functions +//===------------------------------------------------------------------------=== +solver_t * satoko_create() +{ + solver_t *s = satoko_calloc(solver_t, 1); + + satoko_default_opts(&s->opts); + /* User data */ + s->assumptions = vec_uint_alloc(0); + s->final_conflict = vec_uint_alloc(0); + /* Clauses Database */ + s->all_clauses = cdb_alloc(0); + s->originals = vec_uint_alloc(0); + s->learnts = vec_uint_alloc(0); + s->watches = vec_wl_alloc(0); + /* Activity heuristic */ + s->var_act_inc = VAR_ACT_INIT_INC; + s->clause_act_inc = CLAUSE_ACT_INIT_INC; + /* Variable Information */ + s->activity = vec_act_alloc(0); + s->var_order = heap_alloc(s->activity); + s->levels = vec_uint_alloc(0); + s->reasons = vec_uint_alloc(0); + s->assigns = vec_char_alloc(0); + s->polarity = vec_char_alloc(0); + /* Assignments */ + s->trail = vec_uint_alloc(0); + s->trail_lim = vec_uint_alloc(0); + /* Temporary data used by Search method */ + s->bq_trail = b_queue_alloc(s->opts.sz_trail_bqueue); + s->bq_lbd = b_queue_alloc(s->opts.sz_lbd_bqueue); + s->n_confl_bfr_reduce = s->opts.n_conf_fst_reduce; + s->RC1 = 1; + s->RC2 = s->opts.n_conf_fst_reduce; + /* Temporary data used by Analyze */ + s->temp_lits = vec_uint_alloc(0); + s->seen = vec_char_alloc(0); + s->tagged = vec_uint_alloc(0); + s->stack = vec_uint_alloc(0); + s->last_dlevel = vec_uint_alloc(0); + /* Misc temporary */ + s->stamps = vec_uint_alloc(0); + return s; +} + +void satoko_destroy(solver_t *s) +{ + vec_uint_free(s->assumptions); + vec_uint_free(s->final_conflict); + cdb_free(s->all_clauses); + vec_uint_free(s->originals); + vec_uint_free(s->learnts); + vec_wl_free(s->watches); + vec_act_free(s->activity); + heap_free(s->var_order); + vec_uint_free(s->levels); + vec_uint_free(s->reasons); + vec_char_free(s->assigns); + vec_char_free(s->polarity); + vec_uint_free(s->trail); + vec_uint_free(s->trail_lim); + b_queue_free(s->bq_lbd); + b_queue_free(s->bq_trail); + vec_uint_free(s->temp_lits); + vec_char_free(s->seen); + vec_uint_free(s->tagged); + vec_uint_free(s->stack); + vec_uint_free(s->last_dlevel); + vec_uint_free(s->stamps); + if (s->marks) + vec_char_free(s->marks); + satoko_free(s); +} + +void satoko_default_opts(satoko_opts_t *opts) +{ + memset(opts, 0, sizeof(satoko_opts_t)); + opts->verbose = 0; + /* Limits */ + opts->conf_limit = 0; + opts->prop_limit = 0; + /* Constants used for restart heuristic */ + opts->f_rst = 0.8; + opts->b_rst = 1.4; + opts->fst_block_rst = 10000; + opts->sz_lbd_bqueue = 50; + opts->sz_trail_bqueue = 5000; + /* Constants used for clause database reduction heuristic */ + opts->n_conf_fst_reduce = 2000; + opts->inc_reduce = 300; + opts->inc_special_reduce = 1000; + opts->lbd_freeze_clause = 30; + opts->learnt_ratio = 0.5; + /* VSIDS heuristic */ + opts->var_act_limit = VAR_ACT_LIMIT; + opts->var_act_rescale = VAR_ACT_RESCALE; + opts->var_decay = 0.95; + opts->clause_decay = (clause_act_t) 0.995; + /* Binary resolution */ + opts->clause_max_sz_bin_resol = 30; + opts->clause_min_lbd_bin_resol = 6; + + opts->garbage_max_ratio = (float) 0.3; +} + +/** + * TODO: sanity check on configuration options + */ +void satoko_configure(satoko_t *s, satoko_opts_t *user_opts) +{ + assert(user_opts); + memcpy(&s->opts, user_opts, sizeof(satoko_opts_t)); +} + +int satoko_simplify(solver_t * s) +{ + unsigned i, j = 0; + unsigned cref; + + assert(solver_dlevel(s) == 0); + if (solver_propagate(s) != UNDEF) + return SATOKO_ERR; + if (s->n_assigns_simplify == vec_uint_size(s->trail) || s->n_props_simplify > 0) + return SATOKO_OK; + + vec_uint_foreach(s->originals, cref, i) { + struct clause *clause = clause_read(s, cref); + + if (clause_is_satisfied(s, clause)) { + clause->f_mark = 1; + s->stats.n_original_lits -= clause->size; + clause_unwatch(s, cref); + } else + vec_uint_assign(s->originals, j++, cref); + } + vec_uint_shrink(s->originals, j); + solver_rebuild_order(s); + s->n_assigns_simplify = vec_uint_size(s->trail); + s->n_props_simplify = s->stats.n_original_lits + s->stats.n_learnt_lits; + return SATOKO_OK; +} + +int satoko_add_variable(solver_t *s, char sign) +{ + unsigned var = vec_act_size(s->activity); + vec_wl_push(s->watches); + vec_wl_push(s->watches); + vec_act_push_back(s->activity, 0); + vec_uint_push_back(s->levels, 0); + vec_char_push_back(s->assigns, VAR_UNASSING); + vec_char_push_back(s->polarity, sign); + vec_uint_push_back(s->reasons, UNDEF); + vec_uint_push_back(s->stamps, 0); + vec_char_push_back(s->seen, 0); + heap_insert(s->var_order, var); + if (s->marks) + vec_char_push_back(s->marks, 0); + return var; +} + +int satoko_add_clause(solver_t *s, int *lits, int size) +{ + unsigned i, j; + unsigned prev_lit; + unsigned max_var; + unsigned cref; + + qsort((void *) lits, size, sizeof(unsigned), stk_uint_compare); + max_var = lit2var(lits[size - 1]); + while (max_var >= vec_act_size(s->activity)) + satoko_add_variable(s, LIT_FALSE); + + vec_uint_clear(s->temp_lits); + j = 0; + prev_lit = UNDEF; + for (i = 0; i < (unsigned)size; i++) { + if ((unsigned)lits[i] == lit_neg(prev_lit) || lit_value(s, lits[i]) == LIT_TRUE) + return SATOKO_OK; + else if ((unsigned)lits[i] != prev_lit && var_value(s, lit2var(lits[i])) == VAR_UNASSING) { + prev_lit = lits[i]; + vec_uint_push_back(s->temp_lits, lits[i]); + } + } + + if (vec_uint_size(s->temp_lits) == 0) + return SATOKO_ERR; + if (vec_uint_size(s->temp_lits) == 1) { + solver_enqueue(s, vec_uint_at(s->temp_lits, 0), UNDEF); + return (solver_propagate(s) == UNDEF); + } + + cref = solver_clause_create(s, s->temp_lits, 0); + clause_watch(s, cref); + return SATOKO_OK; +} + +void satoko_assump_push(solver_t *s, int lit) +{ + vec_uint_push_back(s->assumptions, lit); +} + +void satoko_assump_pop(solver_t *s) +{ + assert(vec_uint_size(s->assumptions) > 0); + vec_uint_pop_back(s->assumptions); + solver_cancel_until(s, vec_uint_size(s->assumptions)); +} + +int satoko_solve(solver_t *s) +{ + char status = SATOKO_UNDEC; + + assert(s); + //if (s->opts.verbose) + // print_opts(s); + + while (status == SATOKO_UNDEC) { + status = solver_search(s); + if (solver_check_limits(s) == 0) + break; + } + if (s->opts.verbose) + print_stats(s); + solver_cancel_until(s, vec_uint_size(s->assumptions)); + return status; +} + +int satoko_final_conflict(solver_t *s, unsigned *out) +{ + if (vec_uint_size(s->final_conflict) == 0) + return -1; + out = satoko_alloc(unsigned, vec_uint_size(s->final_conflict)); + memcpy(out, vec_uint_data(s->final_conflict), + sizeof(unsigned) * vec_uint_size(s->final_conflict)); + return vec_uint_size(s->final_conflict); + +} + +satoko_stats_t satoko_stats(satoko_t *s) +{ + return s->stats; +} + +void satoko_bookmark(satoko_t *s) +{ + assert(solver_dlevel(s) == 0); + s->book_cl_orig = vec_uint_size(s->originals); + s->book_cl_lrnt = vec_uint_size(s->learnts); + s->book_vars = vec_char_size(s->assigns); + s->book_trail = vec_uint_size(s->trail); +} + +void satoko_unbookmark(satoko_t *s) +{ + s->book_cl_orig = 0; + s->book_cl_lrnt = 0; + s->book_cdb = 0; + s->book_vars = 0; + s->book_trail = 0; +} + +void satoko_reset(satoko_t *s) +{ + vec_uint_clear(s->assumptions); + vec_uint_clear(s->final_conflict); + cdb_clear(s->all_clauses); + vec_uint_clear(s->originals); + vec_uint_clear(s->learnts); + vec_wl_clean(s->watches); + vec_act_clear(s->activity); + heap_clear(s->var_order); + vec_uint_clear(s->levels); + vec_uint_clear(s->reasons); + vec_char_clear(s->assigns); + vec_char_clear(s->polarity); + vec_uint_clear(s->trail); + vec_uint_clear(s->trail_lim); + b_queue_clean(s->bq_lbd); + b_queue_clean(s->bq_trail); + vec_uint_clear(s->temp_lits); + vec_char_clear(s->seen); + vec_uint_clear(s->tagged); + vec_uint_clear(s->stack); + vec_uint_clear(s->last_dlevel); + vec_uint_clear(s->stamps); + s->var_act_inc = VAR_ACT_INIT_INC; + s->clause_act_inc = CLAUSE_ACT_INIT_INC; + s->n_confl_bfr_reduce = s->opts.n_conf_fst_reduce; + s->RC1 = 1; + s->RC2 = s->opts.n_conf_fst_reduce; + s->book_cl_orig = 0; + s->book_cl_lrnt = 0; + s->book_cdb = 0; + s->book_vars = 0; + s->book_trail = 0; +} + +void satoko_rollback(satoko_t *s) +{ + unsigned i, cref; + unsigned n_originals = vec_uint_size(s->originals) - s->book_cl_orig; + unsigned n_learnts = vec_uint_size(s->learnts) - s->book_cl_lrnt; + struct clause **cl_to_remove; + + assert(solver_dlevel(s) == 0); + if (!s->book_vars) { + satoko_reset(s); + return; + } + + cl_to_remove = satoko_alloc(struct clause *, n_originals + n_learnts); + /* Mark clauses */ + vec_uint_foreach_start(s->originals, cref, i, s->book_cl_orig) + cl_to_remove[i] = clause_read(s, cref); + vec_uint_foreach_start(s->learnts, cref, i, s->book_cl_lrnt) + cl_to_remove[n_originals + i] = clause_read(s, cref); + for (i = 0; i < n_originals + n_learnts; i++) { + clause_unwatch(s, cdb_cref(s->all_clauses, (unsigned *)cl_to_remove[i])); + cl_to_remove[i]->f_mark = 1; + } + satoko_free(cl_to_remove); + vec_uint_shrink(s->originals, s->book_cl_orig); + vec_uint_shrink(s->learnts, s->book_cl_lrnt); + /* Shrink variable related vectors */ + for (i = s->book_vars; i < 2 * vec_char_size(s->assigns); i++) { + vec_wl_at(s->watches, i)->size = 0; + vec_wl_at(s->watches, i)->n_bin = 0; + } + s->watches->size = s->book_vars; + vec_act_shrink(s->activity, s->book_vars); + vec_uint_shrink(s->levels, s->book_vars); + vec_uint_shrink(s->reasons, s->book_vars); + vec_uint_shrink(s->stamps, s->book_vars); + vec_char_shrink(s->assigns, s->book_vars); + vec_char_shrink(s->seen, s->book_vars); + vec_char_shrink(s->polarity, s->book_vars); + solver_rebuild_order(s); + /* Rewind solver and cancel level 0 assignments to the trail */ + solver_cancel_until(s, 0); + vec_uint_shrink(s->trail, s->book_trail); + if (s->book_cdb) + s->all_clauses->size = s->book_cdb; + s->book_cl_orig = 0; + s->book_cl_lrnt = 0; + s->book_vars = 0; + s->book_trail = 0; +} + +void satoko_mark_cone(satoko_t *s, int * pvars, int n_vars) +{ + int i; + if (!solver_has_marks(s)) + s->marks = vec_char_init(solver_varnum(s), 0); + for (i = 0; i < n_vars; i++) { + var_set_mark(s, pvars[i]); + if (!heap_in_heap(s->var_order, pvars[i])) + heap_insert(s->var_order, pvars[i]); + } +} + +void satoko_unmark_cone(satoko_t *s, int *pvars, int n_vars) +{ + int i; + assert(solver_has_marks(s)); + for (i = 0; i < n_vars; i++) + var_clean_mark(s, pvars[i]); +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/satoko/types.h b/src/sat/satoko/types.h new file mode 100644 index 00000000..06c190ab --- /dev/null +++ b/src/sat/satoko/types.h @@ -0,0 +1,39 @@ +//===--- types.h ------------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__types_h +#define satoko__types_h + +#include "utils/sdbl.h" +#include "utils/vec/vec_sdbl.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +/* In Satoko ABC version this file is useless */ + +#define VAR_ACT_INIT_INC SDBL_CONST1 +#define VAR_ACT_LIMIT ABC_CONST(0x014c924d692ca61b) +#define VAR_ACT_RESCALE 200 +typedef sdbl_t act_t; +typedef vec_sdbl_t vec_act_t ; +#define vec_act_alloc(size) vec_sdbl_alloc(size) +#define vec_act_free(vec) vec_sdbl_free(vec) +#define vec_act_size(vec) vec_sdbl_size(vec) +#define vec_act_data(vec) vec_sdbl_data(vec) +#define vec_act_clear(vec) vec_sdbl_clear(vec) +#define vec_act_shrink(vec, size) vec_sdbl_shrink(vec, size) +#define vec_act_at(vec, idx) vec_sdbl_at(vec, idx) +#define vec_act_push_back(vec, value) vec_sdbl_push_back(vec, value) + + +#define CLAUSE_ACT_INIT_INC (1 << 11) +typedef unsigned clause_act_t; + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__types_h */ diff --git a/src/sat/satoko/utils/b_queue.h b/src/sat/satoko/utils/b_queue.h new file mode 100644 index 00000000..b9b62676 --- /dev/null +++ b/src/sat/satoko/utils/b_queue.h @@ -0,0 +1,81 @@ +//===--- b_queue.h ----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__utils__b_queue_h +#define satoko__utils__b_queue_h + +#include "mem.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +/* Bounded Queue */ +typedef struct b_queue_t_ b_queue_t; +struct b_queue_t_ { + unsigned size; + unsigned cap; + unsigned i_first; + unsigned i_empty; + unsigned long sum; + unsigned *data; +}; + +//===------------------------------------------------------------------------=== +// Bounded Queue API +//===------------------------------------------------------------------------=== +static inline b_queue_t *b_queue_alloc(unsigned cap) +{ + b_queue_t *p = satoko_calloc(b_queue_t, 1); + p->cap = cap; + p->data = satoko_calloc(unsigned, cap); + return p; +} + +static inline void b_queue_free(b_queue_t *p) +{ + satoko_free(p->data); + satoko_free(p); +} + +static inline void b_queue_push(b_queue_t *p, unsigned Value) +{ + if (p->size == p->cap) { + assert(p->i_first == p->i_empty); + p->sum -= p->data[p->i_first]; + p->i_first = (p->i_first + 1) % p->cap; + } else + p->size++; + + p->sum += Value; + p->data[p->i_empty] = Value; + if ((++p->i_empty) == p->cap) { + p->i_empty = 0; + p->i_first = 0; + } +} + +static inline unsigned b_queue_avg(b_queue_t *p) +{ + return (unsigned)(p->sum / ((unsigned long) p->size)); +} + +static inline unsigned b_queue_is_valid(b_queue_t *p) +{ + return (p->cap == p->size); +} + +static inline void b_queue_clean(b_queue_t *p) +{ + p->i_first = 0; + p->i_empty = 0; + p->size = 0; + p->sum = 0; +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__utils__b_queue_h */ diff --git a/src/sat/satoko/utils/heap.h b/src/sat/satoko/utils/heap.h new file mode 100644 index 00000000..391b8a7e --- /dev/null +++ b/src/sat/satoko/utils/heap.h @@ -0,0 +1,178 @@ +//===--- heap.h ----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__utils__heap_h +#define satoko__utils__heap_h + +#include "mem.h" +#include "../types.h" +#include "vec/vec_sdbl.h" +#include "vec/vec_int.h" +#include "vec/vec_uint.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +typedef struct heap_t_ heap_t; +struct heap_t_ { + vec_int_t *indices; + vec_uint_t *data; + vec_act_t *weights; +}; +//===------------------------------------------------------------------------=== +// Heap internal functions +//===------------------------------------------------------------------------=== +static inline unsigned left(unsigned i) { return 2 * i + 1; } +static inline unsigned right(unsigned i) { return (i + 1) * 2; } +static inline unsigned parent(unsigned i) { return (i - 1) >> 1; } + +static inline int compare(heap_t *p, unsigned x, unsigned y) +{ + return vec_act_at(p->weights, x) > vec_act_at(p->weights, y); +} + +static inline void heap_percolate_up(heap_t *h, unsigned i) +{ + unsigned x = vec_uint_at(h->data, i); + unsigned p = parent(i); + + while (i != 0 && compare(h, x, vec_uint_at(h->data, p))) { + vec_uint_assign(h->data, i, vec_uint_at(h->data, p)); + vec_int_assign(h->indices, vec_uint_at(h->data, p), (int) i); + i = p; + p = parent(p); + } + vec_uint_assign(h->data, i, x); + vec_int_assign(h->indices, x, (int) i); +} + +static inline void heap_percolate_down(heap_t *h, unsigned i) +{ + unsigned x = vec_uint_at(h->data, i); + + while (left(i) < vec_uint_size(h->data)) { + unsigned child = right(i) < vec_uint_size(h->data) && + compare(h, vec_uint_at(h->data, right(i)), vec_uint_at(h->data, left(i))) + ? right(i) + : left(i); + + if (!compare(h, vec_uint_at(h->data, child), x)) + break; + + vec_uint_assign(h->data, i, vec_uint_at(h->data, child)); + vec_int_assign(h->indices, vec_uint_at(h->data, i), (int) i); + i = child; + } + vec_uint_assign(h->data, i, x); + vec_int_assign(h->indices, x, (int) i); +} + +//===------------------------------------------------------------------------=== +// Heap API +//===------------------------------------------------------------------------=== +static inline heap_t *heap_alloc(vec_act_t *weights) +{ + heap_t *p = satoko_alloc(heap_t, 1); + p->weights = weights; + p->indices = vec_int_alloc(0); + p->data = vec_uint_alloc(0); + return p; +} + +static inline void heap_free(heap_t *p) +{ + vec_int_free(p->indices); + vec_uint_free(p->data); + satoko_free(p); +} + +static inline unsigned heap_size(heap_t *p) +{ + return vec_uint_size(p->data); +} + +static inline int heap_in_heap(heap_t *p, unsigned entry) +{ + return (entry < vec_int_size(p->indices)) && + (vec_int_at(p->indices, entry) >= 0); +} + +static inline void heap_increase(heap_t *p, unsigned entry) +{ + assert(heap_in_heap(p, entry)); + heap_percolate_down(p, (unsigned) vec_int_at(p->indices, entry)); +} + +static inline void heap_decrease(heap_t *p, unsigned entry) +{ + assert(heap_in_heap(p, entry)); + heap_percolate_up(p, (unsigned) vec_int_at(p->indices, entry)); +} + +static inline void heap_insert(heap_t *p, unsigned entry) +{ + if (vec_int_size(p->indices) < entry + 1) { + unsigned old_size = vec_int_size(p->indices); + unsigned i; + int e; + vec_int_resize(p->indices, entry + 1); + vec_int_foreach_start(p->indices, e, i, old_size) + vec_int_assign(p->indices, i, -1); + } + assert(!heap_in_heap(p, entry)); + vec_int_assign(p->indices, entry, (int) vec_uint_size(p->data)); + vec_uint_push_back(p->data, entry); + heap_percolate_up(p, (unsigned) vec_int_at(p->indices, entry)); +} + +static inline void heap_update(heap_t *p, unsigned i) +{ + if (!heap_in_heap(p, i)) + heap_insert(p, i); + else { + heap_percolate_up(p, (unsigned) vec_int_at(p->indices, i)); + heap_percolate_down(p, (unsigned) vec_int_at(p->indices, i)); + } +} + +static inline void heap_build(heap_t *p, vec_uint_t *entries) +{ + int i; + unsigned j, entry; + + vec_uint_foreach(p->data, entry, j) + vec_int_assign(p->indices, entry, -1); + vec_uint_clear(p->data); + vec_uint_foreach(entries, entry, j) { + vec_int_assign(p->indices, entry, (int) j); + vec_uint_push_back(p->data, entry); + } + for ((i = vec_uint_size(p->data) / 2 - 1); i >= 0; i--) + heap_percolate_down(p, (unsigned) i); +} + +static inline void heap_clear(heap_t *p) +{ + vec_int_clear(p->indices); + vec_uint_clear(p->data); +} + +static inline unsigned heap_remove_min(heap_t *p) +{ + unsigned x = vec_uint_at(p->data, 0); + vec_uint_assign(p->data, 0, vec_uint_at(p->data, vec_uint_size(p->data) - 1)); + vec_int_assign(p->indices, vec_uint_at(p->data, 0), 0); + vec_int_assign(p->indices, x, -1); + vec_uint_pop_back(p->data); + if (vec_uint_size(p->data) > 1) + heap_percolate_down(p, 0); + return x; +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__utils__heap_h */ diff --git a/src/sat/satoko/utils/mem.h b/src/sat/satoko/utils/mem.h new file mode 100755 index 00000000..5ff9873d --- /dev/null +++ b/src/sat/satoko/utils/mem.h @@ -0,0 +1,23 @@ +//===--- mem.h --------------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__utils__mem_h +#define satoko__utils__mem_h + +#include <stdlib.h> + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +#define satoko_alloc(type, n_elements) ((type *) malloc((n_elements) * sizeof(type))) +#define satoko_calloc(type, n_elements) ((type *) calloc((n_elements), sizeof(type))) +#define satoko_realloc(type, ptr, n_elements) ((type *) realloc(ptr, (n_elements) * sizeof(type))) +#define satoko_free(p) do { free(p); p = NULL; } while(0) + +ABC_NAMESPACE_HEADER_END +#endif diff --git a/src/sat/satoko/utils/misc.h b/src/sat/satoko/utils/misc.h new file mode 100755 index 00000000..7205a096 --- /dev/null +++ b/src/sat/satoko/utils/misc.h @@ -0,0 +1,35 @@ +//===--- misc.h -------------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__utils__misc_h +#define satoko__utils__misc_h + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +#define stk_swap(type, a, b) { type t = a; a = b; b = t; } + +static inline unsigned stk_uint_max(unsigned a, unsigned b) +{ + return a > b ? a : b; +} + +static inline int stk_uint_compare(const void *p1, const void *p2) +{ + const unsigned pp1 = *(const unsigned *)p1; + const unsigned pp2 = *(const unsigned *)p2; + + if (pp1 < pp2) + return -1; + if (pp1 > pp2) + return 1; + return 0; +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__utils__misc_h */ diff --git a/src/sat/satoko/utils/sdbl.h b/src/sat/satoko/utils/sdbl.h new file mode 100644 index 00000000..9f90ba02 --- /dev/null +++ b/src/sat/satoko/utils/sdbl.h @@ -0,0 +1,133 @@ +//===--- sdbl.h -------------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +// by Alan Mishchenko +#ifndef satoko__utils__sdbl_h +#define satoko__utils__sdbl_h + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START +/* + The sdbl_t floating-point number is represented as a 64-bit unsigned int. + The number is (2^expt)*mnt, where expt is a 16-bit exponent and mnt is a + 48-bit mantissa. The decimal point is located between the MSB of mnt, + which is always 1, and the remaining 15 digits of mnt. + + Currently, only positive numbers are represented. + + The range of possible values is [1.0; 2^(2^16-1)*1.111111111111111] + that is, the smallest possible number is 1.0 and the largest possible + number is 2^(---16 ones---).(1.---47 ones---) + + Comparison of numbers can be done by comparing the underlying unsigned ints. + + Only addition, multiplication, and division by 2^n are currently implemented. +*/ + +typedef word sdbl_t; + +static sdbl_t SDBL_CONST1 = ABC_CONST(0x0000800000000000); +static sdbl_t SDBL_MAX = ~(sdbl_t)(0); + +union ui64_dbl { word ui64; double dbl; }; + +static inline word sdbl_exp(sdbl_t a) { return a >> 48; } +static inline word sdbl_mnt(sdbl_t a) { return (a << 16) >> 16; } + +static inline double sdbl2double(sdbl_t a) { + union ui64_dbl temp; + assert(sdbl_exp(a) < 1023); + temp.ui64 = ((sdbl_exp(a) + 1023) << 52) | (((a << 17) >> 17) << 5); + return temp.dbl; +} + +static inline sdbl_t double2sdbl(double value) +{ + union ui64_dbl temp; + sdbl_t expt, mnt; + assert(value >= 1.0); + temp.dbl = value; + expt = (temp.ui64 >> 52) - 1023; + mnt = SDBL_CONST1 | ((temp.ui64 << 12) >> 17); + return (expt << 48) + mnt; +} + +static inline sdbl_t sdbl_add(sdbl_t a, sdbl_t b) +{ + sdbl_t expt, mnt; + if (a < b) { + a ^= b; + b ^= a; + a ^= b; + } + assert(a >= b); + expt = sdbl_exp(a); + mnt = sdbl_mnt(a) + (sdbl_mnt(b) >> (sdbl_exp(a) - sdbl_exp(b))); + /* Check for carry */ + if (mnt >> 48) { + expt++; + mnt >>= 1; + } + if (expt >> 16) /* overflow */ + return SDBL_MAX; + return (expt << 48) + mnt; +} + +static inline sdbl_t sdbl_mult(sdbl_t a, sdbl_t b) +{ + sdbl_t expt, mnt; + sdbl_t a_mnt, a_mnt_hi, a_mnt_lo; + sdbl_t b_mnt, b_mnt_hi, b_mnt_lo; + if (a < b) { + a ^= b; + b ^= a; + a ^= b; + } + assert( a >= b ); + a_mnt = sdbl_mnt(a); + b_mnt = sdbl_mnt(b); + a_mnt_hi = a_mnt>>32; + b_mnt_hi = b_mnt>>32; + a_mnt_lo = (a_mnt<<32)>>32; + b_mnt_lo = (b_mnt<<32)>>32; + mnt = ((a_mnt_hi * b_mnt_hi) << 17) + + ((a_mnt_lo * b_mnt_lo) >> 47) + + ((a_mnt_lo * b_mnt_hi) >> 15) + + ((a_mnt_hi * b_mnt_lo) >> 15); + expt = sdbl_exp(a) + sdbl_exp(b); + /* Check for carry */ + if (mnt >> 48) { + expt++; + mnt >>= 1; + } + if (expt >> 16) /* overflow */ + return SDBL_MAX; + return (expt << 48) + mnt; +} + +static inline sdbl_t sdbl_div(sdbl_t a, unsigned deg2) +{ + if (sdbl_exp(a) >= (word)deg2) + return ((sdbl_exp(a) - deg2) << 48) + sdbl_mnt(a); + return SDBL_CONST1; +} + +static inline void sdbl_test() +{ + sdbl_t ten100_ = ABC_CONST(0x014c924d692ca61b); + printf("%f\n", sdbl2double(ten100_)); + printf("%016lX\n", double2sdbl(1 /0.95)); + printf("%016lX\n", SDBL_CONST1); + printf("%f\n", sdbl2double(SDBL_CONST1)); + printf("%f\n", sdbl2double(ABC_CONST(0x000086BCA1AF286B))); + +} + +ABC_NAMESPACE_HEADER_END + +#endif /* satoko__utils__sdbl_h */ diff --git a/src/sat/satoko/utils/sort.h b/src/sat/satoko/utils/sort.h new file mode 100644 index 00000000..285f4b91 --- /dev/null +++ b/src/sat/satoko/utils/sort.h @@ -0,0 +1,65 @@ +//===--- sort.h -------------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__utils__sort_h +#define satoko__utils__sort_h + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +static inline void select_sort(void **data, unsigned size, + int (*comp_fn)(const void *, const void *)) +{ + unsigned i, j, i_best; + void *temp; + + for (i = 0; i < (size - 1); i++) { + i_best = i; + for (j = i + 1; j < size; j++) { + if (comp_fn(data[j], data[i_best])) + i_best = j; + } + temp = data[i]; + data[i] = data[i_best]; + data[i_best] = temp; + } +} + +static void satoko_sort(void **data, unsigned size, + int (*comp_fn)(const void *, const void *)) +{ + if (size <= 15) + select_sort(data, size, comp_fn); + else { + void *pivot = data[size / 2]; + void *temp; + unsigned j = size; + int i = -1; + + for (;;) { + do { + i++; + } while (comp_fn(data[i], pivot)); + do { + j--; + } while (comp_fn(pivot, data[j])); + + if ((unsigned) i >= j) + break; + + temp = data[i]; + data[i] = data[j]; + data[j] = temp; + } + satoko_sort(data, (unsigned) i, comp_fn); + satoko_sort(data + i, (size - (unsigned) i), comp_fn); + } +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__utils__sort_h */ diff --git a/src/sat/satoko/utils/vec/vec_char.h b/src/sat/satoko/utils/vec/vec_char.h new file mode 100644 index 00000000..7d5732ec --- /dev/null +++ b/src/sat/satoko/utils/vec/vec_char.h @@ -0,0 +1,260 @@ +//===--- vec_char.h ---------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__utils__vec__vec_char_h +#define satoko__utils__vec__vec_char_h + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "../mem.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +typedef struct vec_char_t_ vec_char_t; +struct vec_char_t_ { + unsigned cap; + unsigned size; + char *data; +}; + +//===------------------------------------------------------------------------=== +// Vector Macros +//===------------------------------------------------------------------------=== +#define vec_char_foreach(vec, entry, i) \ + for (i = 0; (i < vec_char_size(vec)) && (((entry) = vec_char_at(vec, i)), 1); i++) + +#define vec_char_foreach_start(vec, entry, i, start) \ + for (i = start; (i < vec_char_size(vec)) && (((entry) = vec_char_at(vec, i)), 1); i++) + +#define vec_char_foreach_stop(vec, entry, i, stop) \ + for (i = 0; (i < stop) && (((entry) = vec_char_at(vec, i)), 1); i++) + +//===------------------------------------------------------------------------=== +// Vector API +//===------------------------------------------------------------------------=== +static inline vec_char_t * vec_char_alloc(unsigned cap) +{ + vec_char_t *p = satoko_alloc(vec_char_t, 1); + + if (cap > 0 && cap < 16) + cap = 16; + p->size = 0; + p->cap = cap; + p->data = p->cap ? satoko_alloc(char, p->cap) : NULL; + return p; +} + +static inline vec_char_t * vec_char_alloc_exact(unsigned cap) +{ + vec_char_t *p = satoko_alloc(vec_char_t, 1); + + cap = 0; + p->size = 0; + p->cap = cap; + p->data = p->cap ? satoko_alloc(char, p->cap ) : NULL; + return p; +} + +static inline vec_char_t * vec_char_init(unsigned size, char value) +{ + vec_char_t *p = satoko_alloc(vec_char_t, 1); + + p->cap = size; + p->size = size; + p->data = p->cap ? satoko_alloc(char, p->cap) : NULL; + memset(p->data, value, sizeof(char) * p->size); + return p; +} + +static inline void vec_char_free(vec_char_t *p) +{ + if (p->data != NULL) + satoko_free(p->data); + satoko_free(p); +} + +static inline unsigned vec_char_size(vec_char_t *p) +{ + return p->size; +} + +static inline void vec_char_resize(vec_char_t *p, unsigned new_size) +{ + p->size = new_size; + if (p->cap >= new_size) + return; + p->data = satoko_realloc(char, p->data, new_size); + assert(p->data != NULL); + p->cap = new_size; +} + +static inline void vec_char_shrink(vec_char_t *p, unsigned new_size) +{ + assert(p->cap > new_size); + p->size = new_size; +} + +static inline void vec_char_reserve(vec_char_t *p, unsigned new_cap) +{ + if (p->cap >= new_cap) + return; + p->data = satoko_realloc(char, p->data, new_cap); + assert(p->data != NULL); + p->cap = new_cap; +} + +static inline unsigned vec_char_capacity(vec_char_t *p) +{ + return p->cap; +} + +static inline int vec_char_empty(vec_char_t *p) +{ + return p->size ? 0 : 1; +} + +static inline void vec_char_erase(vec_char_t *p) +{ + satoko_free(p->data); + p->size = 0; + p->cap = 0; +} + +static inline char vec_char_at(vec_char_t *p, unsigned idx) +{ + assert(idx >= 0 && idx < p->size); + return p->data[idx]; +} + +static inline char * vec_char_at_ptr(vec_char_t *p, unsigned idx) +{ + assert(idx >= 0 && idx < p->size); + return p->data + idx; +} + +static inline char * vec_char_data(vec_char_t *p) +{ + assert(p); + return p->data; +} + +static inline void vec_char_duplicate(vec_char_t *dest, const vec_char_t *src) +{ + assert(dest != NULL && src != NULL); + vec_char_resize(dest, src->cap); + memcpy(dest->data, src->data, sizeof(char) * src->cap); + dest->size = src->size; +} + +static inline void vec_char_copy(vec_char_t *dest, const vec_char_t *src) +{ + assert(dest != NULL && src != NULL); + vec_char_resize(dest, src->size); + memcpy(dest->data, src->data, sizeof(char) * src->size); + dest->size = src->size; +} + +static inline void vec_char_push_back(vec_char_t *p, char value) +{ + if (p->size == p->cap) { + if (p->cap < 16) + vec_char_reserve(p, 16); + else + vec_char_reserve(p, 2 * p->cap); + } + p->data[p->size] = value; + p->size++; +} + +static inline char vec_char_pop_back(vec_char_t *p) +{ + assert(p && p->size); + return p->data[--p->size]; +} + +static inline void vec_char_assign(vec_char_t *p, unsigned idx, char value) +{ + assert((idx >= 0) && (idx < vec_char_size(p))); + p->data[idx] = value; +} + +static inline void vec_char_insert(vec_char_t *p, unsigned idx, char value) +{ + assert((idx >= 0) && (idx < vec_char_size(p))); + vec_char_push_back(p, 0); + memmove(p->data + idx + 1, p->data + idx, (p->size - idx - 2) * sizeof(char)); + p->data[idx] = value; +} + +static inline void vec_char_drop(vec_char_t *p, unsigned idx) +{ + assert((idx >= 0) && (idx < vec_char_size(p))); + memmove(p->data + idx, p->data + idx + 1, (p->size - idx - 1) * sizeof(char)); + p->size -= 1; +} + +static inline void vec_char_clear(vec_char_t *p) +{ + p->size = 0; +} + +static inline int vec_char_asc_compare(const void *p1, const void *p2) +{ + const char *pp1 = (const char *)p1; + const char *pp2 = (const char *)p2; + + if (*pp1 < *pp2) + return -1; + if (*pp1 > *pp2) + return 1; + return 0; +} + +static inline int vec_char_desc_compare(const void *p1, const void *p2) +{ + const char *pp1 = (const char *)p1; + const char *pp2 = (const char *)p2; + + if (*pp1 > *pp2) + return -1; + if (*pp1 < *pp2) + return 1; + return 0; +} + +static inline void vec_char_sort(vec_char_t *p, int ascending) +{ + if (ascending) + qsort((void *) p->data, p->size, sizeof(char), + (int (*)(const void *, const void *)) vec_char_asc_compare); + else + qsort((void*) p->data, p->size, sizeof(char), + (int (*)(const void *, const void *)) vec_char_desc_compare); +} + + +static inline long vec_char_memory(vec_char_t *p) +{ + return p == NULL ? 0 : sizeof(char) * p->cap + sizeof(vec_char_t); +} + +static inline void vec_char_print(vec_char_t* p) +{ + unsigned i; + assert(p != NULL); + fprintf(stdout, "Vector has %u(%u) entries: {", p->size, p->cap); + for (i = 0; i < p->size; i++) + fprintf(stdout, " %d", p->data[i]); + fprintf(stdout, " }\n"); +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__utils__vec__vec_char_h */ diff --git a/src/sat/satoko/utils/vec/vec_flt.h b/src/sat/satoko/utils/vec/vec_flt.h new file mode 100644 index 00000000..d7c896d9 --- /dev/null +++ b/src/sat/satoko/utils/vec/vec_flt.h @@ -0,0 +1,246 @@ +//===--- vec_int.h ----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__utils__vec__vec_flt_h +#define satoko__utils__vec__vec_flt_h + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "../mem.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +typedef struct vec_flt_t_ vec_flt_t; +struct vec_flt_t_ { + unsigned cap; + unsigned size; + float *data; +}; + +//===------------------------------------------------------------------------=== +// Vector Macros +//===------------------------------------------------------------------------=== +#define vec_flt_foreach(vec, entry, i) \ + for (i = 0; (i < vec->size) && (((entry) = vec_flt_at(vec, i)), 1); i++) + +#define vec_flt_foreach_start(vec, entry, i, start) \ + for (i = start; (i < vec_flt_size(vec)) && (((entry) = vec_flt_at(vec, i)), 1); i++) + +#define vec_flt_foreach_stop(vec, entry, i, stop) \ + for (i = 0; (i < stop) && (((entry) = vec_flt_at(vec, i)), 1); i++) + +//===------------------------------------------------------------------------=== +// Vector API +//===------------------------------------------------------------------------=== +static inline vec_flt_t *vec_flt_alloc(unsigned cap) +{ + vec_flt_t* p = satoko_alloc(vec_flt_t, 1); + + if (cap > 0 && cap < 16) + cap = 16; + p->size = 0; + p->cap = cap; + p->data = p->cap ? satoko_alloc(float, p->cap) : NULL; + return p; +} + +static inline vec_flt_t *vec_flt_alloc_exact(unsigned cap) +{ + vec_flt_t* p = satoko_alloc(vec_flt_t, 1); + + p->size = 0; + p->cap = cap; + p->data = p->cap ? satoko_alloc(float, p->cap) : NULL; + return p; +} + +static inline vec_flt_t *vec_flt_init(unsigned size, float value) +{ + vec_flt_t* p = satoko_alloc(vec_flt_t, 1); + + p->cap = size; + p->size = size; + p->data = p->cap ? satoko_alloc(float, p->cap) : NULL; + memset(p->data, value, sizeof(float) * p->size); + return p; +} + +static inline void vec_flt_free(vec_flt_t *p) +{ + if (p->data != NULL) + satoko_free(p->data); + satoko_free(p); +} + +static inline unsigned vec_flt_size(vec_flt_t *p) +{ + return p->size; +} + +static inline void vec_flt_resize(vec_flt_t *p, unsigned new_size) +{ + p->size = new_size; + if (p->cap >= new_size) + return; + p->data = satoko_realloc(float, p->data, new_size); + assert(p->data != NULL); + p->cap = new_size; +} + +static inline void vec_flt_reserve(vec_flt_t *p, unsigned new_cap) +{ + if (p->cap >= new_cap) + return; + p->data = satoko_realloc(float, p->data, new_cap); + assert(p->data != NULL); + p->cap = new_cap; +} + +static inline unsigned vec_flt_capacity(vec_flt_t *p) +{ + return p->cap; +} + +static inline int vec_flt_empty(vec_flt_t *p) +{ + return p->size ? 0 : 1; +} + +static inline void vec_flt_erase(vec_flt_t *p) +{ + satoko_free(p->data); + p->size = 0; + p->cap = 0; +} + +static inline float vec_flt_at(vec_flt_t *p, unsigned i) +{ + assert(i >= 0 && i < p->size); + return p->data[i]; +} + +static inline float *vec_flt_at_ptr(vec_flt_t *p, unsigned i) +{ + assert(i >= 0 && i < p->size); + return p->data + i; +} + +static inline float *vec_flt_data(vec_flt_t *p) +{ + assert(p); + return p->data; +} + +static inline void vec_flt_duplicate(vec_flt_t *dest, const vec_flt_t *src) +{ + assert(dest != NULL && src != NULL); + vec_flt_resize(dest, src->cap); + memcpy(dest->data, src->data, sizeof(float) * src->cap); + dest->size = src->size; +} + +static inline void vec_flt_copy(vec_flt_t *dest, const vec_flt_t *src) +{ + assert(dest != NULL && src != NULL); + vec_flt_resize(dest, src->size); + memcpy(dest->data, src->data, sizeof(float) * src->size); + dest->size = src->size; +} + +static inline void vec_flt_push_back(vec_flt_t *p, float value) +{ + if (p->size == p->cap) { + if (p->cap < 16) + vec_flt_reserve(p, 16); + else + vec_flt_reserve(p, 2 * p->cap); + } + p->data[p->size] = value; + p->size++; +} + +static inline void vec_flt_assign(vec_flt_t *p, unsigned i, float value) +{ + assert((i >= 0) && (i < vec_flt_size(p))); + p->data[i] = value; +} + +static inline void vec_flt_insert(vec_flt_t *p, unsigned i, float value) +{ + assert((i >= 0) && (i < vec_flt_size(p))); + vec_flt_push_back(p, 0); + memmove(p->data + i + 1, p->data + i, (p->size - i - 2) * sizeof(float)); + p->data[i] = value; +} + +static inline void vec_flt_drop(vec_flt_t *p, unsigned i) +{ + assert((i >= 0) && (i < vec_flt_size(p))); + memmove(p->data + i, p->data + i + 1, (p->size - i - 1) * sizeof(float)); + p->size -= 1; +} + +static inline void vec_flt_clear(vec_flt_t *p) +{ + p->size = 0; +} + +static inline int vec_flt_asc_compare(const void *p1, const void *p2) +{ + const float *pp1 = (const float *) p1; + const float *pp2 = (const float *) p2; + + if (*pp1 < *pp2) + return -1; + if (*pp1 > *pp2) + return 1; + return 0; +} + +static inline int vec_flt_desc_compare(const void* p1, const void* p2) +{ + const float *pp1 = (const float *) p1; + const float *pp2 = (const float *) p2; + + if (*pp1 > *pp2) + return -1; + if (*pp1 < *pp2) + return 1; + return 0; +} + +static inline void vec_flt_sort(vec_flt_t* p, int ascending) +{ + if (ascending) + qsort((void *) p->data, p->size, sizeof(float), + (int (*)(const void*, const void*)) vec_flt_asc_compare); + else + qsort((void *) p->data, p->size, sizeof(float), + (int (*)(const void*, const void*)) vec_flt_desc_compare); +} + +static inline long vec_flt_memory(vec_flt_t *p) +{ + return p == NULL ? 0 : sizeof(float) * p->cap + sizeof(vec_flt_t); +} + +static inline void vec_flt_print(vec_flt_t *p) +{ + unsigned i; + assert(p != NULL); + fprintf(stdout, "Vector has %u(%u) entries: {", p->size, p->cap); + for (i = 0; i < p->size; i++) + fprintf(stdout, " %f", p->data[i]); + fprintf(stdout, " }\n"); +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__utils__vec__vec_flt_h */ diff --git a/src/sat/satoko/utils/vec/vec_int.h b/src/sat/satoko/utils/vec/vec_int.h new file mode 100755 index 00000000..75c5d134 --- /dev/null +++ b/src/sat/satoko/utils/vec/vec_int.h @@ -0,0 +1,240 @@ +//===--- vec_int.h ----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__utils__vec__vec_int_h +#define satoko__utils__vec__vec_int_h + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "../mem.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +typedef struct vec_int_t_ vec_int_t; +struct vec_int_t_ { + unsigned cap; + unsigned size; + int *data; +}; + +//===------------------------------------------------------------------------=== +// Vector Macros +//===------------------------------------------------------------------------=== +#define vec_int_foreach(vec, entry, i) \ + for (i = 0; (i < vec->size) && (((entry) = vec_int_at(vec, i)), 1); i++) + +#define vec_int_foreach_start(vec, entry, i, start) \ + for (i = start; (i < vec_int_size(vec)) && (((entry) = vec_int_at(vec, i)), 1); i++) + +#define vec_int_foreach_stop(vec, entry, i, stop) \ + for (i = 0; (i < stop) && (((entry) = vec_int_at(vec, i)), 1); i++) + +//===------------------------------------------------------------------------=== +// Vector API +//===------------------------------------------------------------------------=== +static inline vec_int_t *vec_int_alloc(unsigned cap) +{ + vec_int_t* p = satoko_alloc(vec_int_t, 1); + + if (cap > 0 && cap < 16) + cap = 16; + p->size = 0; + p->cap = cap; + p->data = p->cap ? satoko_alloc(int, p->cap) : NULL; + return p; +} + +static inline vec_int_t *vec_int_alloc_exact(unsigned cap) +{ + vec_int_t* p = satoko_alloc(vec_int_t, 1); + + p->size = 0; + p->cap = cap; + p->data = p->cap ? satoko_alloc(int, p->cap) : NULL; + return p; +} + +static inline vec_int_t *vec_int_init(unsigned size, int value) +{ + vec_int_t* p = satoko_alloc(vec_int_t, 1); + + p->cap = size; + p->size = size; + p->data = p->cap ? satoko_alloc(int, p->cap) : NULL; + memset(p->data, value, sizeof(int) * p->size); + return p; +} + +static inline void vec_int_free(vec_int_t *p) +{ + if (p->data != NULL) + satoko_free(p->data); + satoko_free(p); +} + +static inline unsigned vec_int_size(vec_int_t *p) +{ + return p->size; +} + +static inline void vec_int_resize(vec_int_t *p, unsigned new_size) +{ + p->size = new_size; + if (p->cap >= new_size) + return; + p->data = satoko_realloc(int, p->data, new_size); + assert(p->data != NULL); + p->cap = new_size; +} + +static inline void vec_int_reserve(vec_int_t *p, unsigned new_cap) +{ + if (p->cap >= new_cap) + return; + p->data = satoko_realloc(int, p->data, new_cap); + assert(p->data != NULL); + p->cap = new_cap; +} + +static inline unsigned vec_int_capacity(vec_int_t *p) +{ + return p->cap; +} + +static inline int vec_int_empty(vec_int_t *p) +{ + return p->size ? 0 : 1; +} + +static inline void vec_int_erase(vec_int_t *p) +{ + satoko_free(p->data); + p->size = 0; + p->cap = 0; +} + +static inline int vec_int_at(vec_int_t *p, unsigned i) +{ + assert(i >= 0 && i < p->size); + return p->data[i]; +} + +static inline int *vec_int_at_ptr(vec_int_t *p, unsigned i) +{ + assert(i >= 0 && i < p->size); + return p->data + i; +} + +static inline void vec_int_duplicate(vec_int_t *dest, const vec_int_t *src) +{ + assert(dest != NULL && src != NULL); + vec_int_resize(dest, src->cap); + memcpy(dest->data, src->data, sizeof(int) * src->cap); + dest->size = src->size; +} + +static inline void vec_int_copy(vec_int_t *dest, const vec_int_t *src) +{ + assert(dest != NULL && src != NULL); + vec_int_resize(dest, src->size); + memcpy(dest->data, src->data, sizeof(int) * src->size); + dest->size = src->size; +} + +static inline void vec_int_push_back(vec_int_t *p, int value) +{ + if (p->size == p->cap) { + if (p->cap < 16) + vec_int_reserve(p, 16); + else + vec_int_reserve(p, 2 * p->cap); + } + p->data[p->size] = value; + p->size++; +} + +static inline void vec_int_assign(vec_int_t *p, unsigned i, int value) +{ + assert((i >= 0) && (i < vec_int_size(p))); + p->data[i] = value; +} + +static inline void vec_int_insert(vec_int_t *p, unsigned i, int value) +{ + assert((i >= 0) && (i < vec_int_size(p))); + vec_int_push_back(p, 0); + memmove(p->data + i + 1, p->data + i, (p->size - i - 2) * sizeof(int)); + p->data[i] = value; +} + +static inline void vec_int_drop(vec_int_t *p, unsigned i) +{ + assert((i >= 0) && (i < vec_int_size(p))); + memmove(p->data + i, p->data + i + 1, (p->size - i - 1) * sizeof(int)); + p->size -= 1; +} + +static inline void vec_int_clear(vec_int_t *p) +{ + p->size = 0; +} + +static inline int vec_int_asc_compare(const void *p1, const void *p2) +{ + const int *pp1 = (const int *) p1; + const int *pp2 = (const int *) p2; + + if (*pp1 < *pp2) + return -1; + if (*pp1 > *pp2) + return 1; + return 0; +} + +static inline int vec_int_desc_compare(const void* p1, const void* p2) +{ + const int *pp1 = (const int *) p1; + const int *pp2 = (const int *) p2; + + if (*pp1 > *pp2) + return -1; + if (*pp1 < *pp2) + return 1; + return 0; +} + +static inline void vec_int_sort(vec_int_t* p, int ascending) +{ + if (ascending) + qsort((void *) p->data, p->size, sizeof(int), + (int (*)(const void*, const void*)) vec_int_asc_compare); + else + qsort((void *) p->data, p->size, sizeof(int), + (int (*)(const void*, const void*)) vec_int_desc_compare); +} + +static inline long vec_int_memory(vec_int_t *p) +{ + return p == NULL ? 0 : sizeof(int) * p->cap + sizeof(vec_int_t); +} + +static inline void vec_int_print(vec_int_t *p) +{ + unsigned i; + assert(p != NULL); + fprintf(stdout, "Vector has %u(%u) entries: {", p->size, p->cap); + for (i = 0; i < p->size; i++) + fprintf(stdout, " %d", p->data[i]); + fprintf(stdout, " }\n"); +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__utils__vec__vec_int_h */ diff --git a/src/sat/satoko/utils/vec/vec_sdbl.h b/src/sat/satoko/utils/vec/vec_sdbl.h new file mode 100755 index 00000000..ec1c731c --- /dev/null +++ b/src/sat/satoko/utils/vec/vec_sdbl.h @@ -0,0 +1,253 @@ +//===--- vec_int.h ----------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__utils__vec__vec_sdbl_h +#define satoko__utils__vec__vec_sdbl_h + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "../mem.h" +#include "../sdbl.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +typedef struct vec_sdbl_t_ vec_sdbl_t; +struct vec_sdbl_t_ { + unsigned cap; + unsigned size; + sdbl_t *data; +}; + +//===------------------------------------------------------------------------=== +// Vector Macros +//===------------------------------------------------------------------------=== +#define vec_sdbl_foreach(vec, entry, i) \ + for (i = 0; (i < vec->size) && (((entry) = vec_sdbl_at(vec, i)), 1); i++) + +#define vec_sdbl_foreach_start(vec, entry, i, start) \ + for (i = start; (i < vec_sdbl_size(vec)) && (((entry) = vec_sdbl_at(vec, i)), 1); i++) + +#define vec_sdbl_foreach_stop(vec, entry, i, stop) \ + for (i = 0; (i < stop) && (((entry) = vec_sdbl_at(vec, i)), 1); i++) + +//===------------------------------------------------------------------------=== +// Vector API +//===------------------------------------------------------------------------=== +static inline vec_sdbl_t *vec_sdbl_alloc(unsigned cap) +{ + vec_sdbl_t* p = satoko_alloc(vec_sdbl_t, 1); + + if (cap > 0 && cap < 16) + cap = 16; + p->size = 0; + p->cap = cap; + p->data = p->cap ? satoko_alloc(sdbl_t, p->cap) : NULL; + return p; +} + +static inline vec_sdbl_t *vec_sdbl_alloc_exact(unsigned cap) +{ + vec_sdbl_t* p = satoko_alloc(vec_sdbl_t, 1); + + p->size = 0; + p->cap = cap; + p->data = p->cap ? satoko_alloc(sdbl_t, p->cap) : NULL; + return p; +} + +static inline vec_sdbl_t *vec_sdbl_init(unsigned size, sdbl_t value) +{ + vec_sdbl_t* p = satoko_alloc(vec_sdbl_t, 1); + + p->cap = size; + p->size = size; + p->data = p->cap ? satoko_alloc(sdbl_t, p->cap) : NULL; + memset(p->data, value, sizeof(sdbl_t) * p->size); + return p; +} + +static inline void vec_sdbl_free(vec_sdbl_t *p) +{ + if (p->data != NULL) + satoko_free(p->data); + satoko_free(p); +} + +static inline unsigned vec_sdbl_size(vec_sdbl_t *p) +{ + return p->size; +} + +static inline void vec_sdbl_shrink(vec_sdbl_t *p, unsigned new_size) +{ + assert(new_size <= p->cap); + p->size = new_size; +} + +static inline void vec_sdbl_resize(vec_sdbl_t *p, unsigned new_size) +{ + p->size = new_size; + if (p->cap >= new_size) + return; + p->data = satoko_realloc(sdbl_t, p->data, new_size); + assert(p->data != NULL); + p->cap = new_size; +} + +static inline void vec_sdbl_reserve(vec_sdbl_t *p, unsigned new_cap) +{ + if (p->cap >= new_cap) + return; + p->data = satoko_realloc(sdbl_t, p->data, new_cap); + assert(p->data != NULL); + p->cap = new_cap; +} + +static inline unsigned vec_sdbl_capacity(vec_sdbl_t *p) +{ + return p->cap; +} + +static inline int vec_sdbl_empty(vec_sdbl_t *p) +{ + return p->size ? 0 : 1; +} + +static inline void vec_sdbl_erase(vec_sdbl_t *p) +{ + satoko_free(p->data); + p->size = 0; + p->cap = 0; +} + +static inline sdbl_t vec_sdbl_at(vec_sdbl_t *p, unsigned i) +{ + assert(i >= 0 && i < p->size); + return p->data[i]; +} + +static inline sdbl_t *vec_sdbl_at_ptr(vec_sdbl_t *p, unsigned i) +{ + assert(i >= 0 && i < p->size); + return p->data + i; +} + +static inline sdbl_t *vec_sdbl_data(vec_sdbl_t *p) +{ + assert(p); + return p->data; +} + +static inline void vec_sdbl_duplicate(vec_sdbl_t *dest, const vec_sdbl_t *src) +{ + assert(dest != NULL && src != NULL); + vec_sdbl_resize(dest, src->cap); + memcpy(dest->data, src->data, sizeof(sdbl_t) * src->cap); + dest->size = src->size; +} + +static inline void vec_sdbl_copy(vec_sdbl_t *dest, const vec_sdbl_t *src) +{ + assert(dest != NULL && src != NULL); + vec_sdbl_resize(dest, src->size); + memcpy(dest->data, src->data, sizeof(sdbl_t) * src->size); + dest->size = src->size; +} + +static inline void vec_sdbl_push_back(vec_sdbl_t *p, sdbl_t value) +{ + if (p->size == p->cap) { + if (p->cap < 16) + vec_sdbl_reserve(p, 16); + else + vec_sdbl_reserve(p, 2 * p->cap); + } + p->data[p->size] = value; + p->size++; +} + +static inline void vec_sdbl_assign(vec_sdbl_t *p, unsigned i, sdbl_t value) +{ + assert((i >= 0) && (i < vec_sdbl_size(p))); + p->data[i] = value; +} + +static inline void vec_sdbl_insert(vec_sdbl_t *p, unsigned i, sdbl_t value) +{ + assert((i >= 0) && (i < vec_sdbl_size(p))); + vec_sdbl_push_back(p, 0); + memmove(p->data + i + 1, p->data + i, (p->size - i - 2) * sizeof(sdbl_t)); + p->data[i] = value; +} + +static inline void vec_sdbl_drop(vec_sdbl_t *p, unsigned i) +{ + assert((i >= 0) && (i < vec_sdbl_size(p))); + memmove(p->data + i, p->data + i + 1, (p->size - i - 1) * sizeof(sdbl_t)); + p->size -= 1; +} + +static inline void vec_sdbl_clear(vec_sdbl_t *p) +{ + p->size = 0; +} + +static inline int vec_sdbl_asc_compare(const void *p1, const void *p2) +{ + const sdbl_t *pp1 = (const sdbl_t *) p1; + const sdbl_t *pp2 = (const sdbl_t *) p2; + + if (*pp1 < *pp2) + return -1; + if (*pp1 > *pp2) + return 1; + return 0; +} + +static inline int vec_sdbl_desc_compare(const void* p1, const void* p2) +{ + const sdbl_t *pp1 = (const sdbl_t *) p1; + const sdbl_t *pp2 = (const sdbl_t *) p2; + + if (*pp1 > *pp2) + return -1; + if (*pp1 < *pp2) + return 1; + return 0; +} + +static inline void vec_sdbl_sort(vec_sdbl_t* p, int ascending) +{ + if (ascending) + qsort((void *) p->data, p->size, sizeof(sdbl_t), + (int (*)(const void*, const void*)) vec_sdbl_asc_compare); + else + qsort((void *) p->data, p->size, sizeof(sdbl_t), + (int (*)(const void*, const void*)) vec_sdbl_desc_compare); +} + +static inline long vec_sdbl_memory(vec_sdbl_t *p) +{ + return p == NULL ? 0 : sizeof(sdbl_t) * p->cap + sizeof(vec_sdbl_t); +} + +static inline void vec_sdbl_print(vec_sdbl_t *p) +{ + unsigned i; + assert(p != NULL); + fprintf(stdout, "Vector has %u(%u) entries: {", p->size, p->cap); + for (i = 0; i < p->size; i++) + fprintf(stdout, " %f", sdbl2double(p->data[i])); + fprintf(stdout, " }\n"); +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__utils__vec__vec_sdbl_h */ diff --git a/src/sat/satoko/utils/vec/vec_uint.h b/src/sat/satoko/utils/vec/vec_uint.h new file mode 100755 index 00000000..e6719ca3 --- /dev/null +++ b/src/sat/satoko/utils/vec/vec_uint.h @@ -0,0 +1,268 @@ +//===--- vec_uint.h ---------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__utils__vec__vec_uint_h +#define satoko__utils__vec__vec_uint_h + +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "../mem.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +typedef struct vec_uint_t_ vec_uint_t; +struct vec_uint_t_ { + unsigned cap; + unsigned size; + unsigned* data; +}; + +//===------------------------------------------------------------------------=== +// Vector Macros +//===------------------------------------------------------------------------=== +#define vec_uint_foreach(vec, entry, i) \ + for (i = 0; (i < vec_uint_size(vec)) && (((entry) = vec_uint_at(vec, i)), 1); i++) + +#define vec_uint_foreach_start(vec, entry, i, start) \ + for (i = start; (i < vec_uint_size(vec)) && (((entry) = vec_uint_at(vec, i)), 1); i++) + +#define vec_uint_foreach_stop(vec, entry, i, stop) \ + for (i = 0; (i < stop) && (((entry) = vec_uint_at(vec, i)), 1); i++) + +//===------------------------------------------------------------------------=== +// Vector API +//===------------------------------------------------------------------------=== +static inline vec_uint_t * vec_uint_alloc(unsigned cap) +{ + vec_uint_t *p = satoko_alloc(vec_uint_t, 1); + + if (cap > 0 && cap < 16) + cap = 16; + p->size = 0; + p->cap = cap; + p->data = p->cap ? satoko_alloc(unsigned, p->cap) : NULL; + return p; +} + +static inline vec_uint_t * vec_uint_alloc_exact(unsigned cap) +{ + vec_uint_t *p = satoko_alloc(vec_uint_t, 1); + + cap = 0; + p->size = 0; + p->cap = cap; + p->data = p->cap ? satoko_alloc(unsigned, p->cap ) : NULL; + return p; +} + +static inline vec_uint_t * vec_uint_init(unsigned size, unsigned value) +{ + vec_uint_t *p = satoko_alloc(vec_uint_t, 1); + + p->cap = size; + p->size = size; + p->data = p->cap ? satoko_alloc(unsigned, p->cap ) : NULL; + memset(p->data, value, sizeof(unsigned) * p->size); + return p; +} + +static inline void vec_uint_free(vec_uint_t *p) +{ + if (p->data != NULL) + satoko_free(p->data); + satoko_free(p); +} + +static inline unsigned vec_uint_size(vec_uint_t *p) +{ + return p->size; +} + +static inline void vec_uint_resize(vec_uint_t *p, unsigned new_size) +{ + p->size = new_size; + if (p->cap >= new_size) + return; + p->data = satoko_realloc(unsigned, p->data, new_size); + assert(p->data != NULL); + p->cap = new_size; +} + +static inline void vec_uint_shrink(vec_uint_t *p, unsigned new_size) +{ + assert(p->cap >= new_size); + p->size = new_size; +} + +static inline void vec_uint_reserve(vec_uint_t *p, unsigned new_cap) +{ + if (p->cap >= new_cap) + return; + p->data = satoko_realloc(unsigned, p->data, new_cap); + assert(p->data != NULL); + p->cap = new_cap; +} + +static inline unsigned vec_uint_capacity(vec_uint_t *p) +{ + return p->cap; +} + +static inline int vec_uint_empty(vec_uint_t *p) +{ + return p->size ? 0 : 1; +} + +static inline void vec_uint_erase(vec_uint_t *p) +{ + satoko_free(p->data); + p->size = 0; + p->cap = 0; +} + +static inline unsigned vec_uint_at(vec_uint_t *p, unsigned idx) +{ + assert(idx >= 0 && idx < p->size); + return p->data[idx]; +} + +static inline unsigned * vec_uint_at_ptr(vec_uint_t *p, unsigned idx) +{ + assert(idx >= 0 && idx < p->size); + return p->data + idx; +} + +static inline unsigned vec_uint_find(vec_uint_t *p, unsigned entry) +{ + unsigned i; + for (i = 0; i < p->size; i++) + if (p->data[i] == entry) + return 1; + return 0; +} + +static inline unsigned * vec_uint_data(vec_uint_t *p) +{ + assert(p); + return p->data; +} + +static inline void vec_uint_duplicate(vec_uint_t *dest, const vec_uint_t *src) +{ + assert(dest != NULL && src != NULL); + vec_uint_resize(dest, src->cap); + memcpy(dest->data, src->data, sizeof(unsigned) * src->cap); + dest->size = src->size; +} + +static inline void vec_uint_copy(vec_uint_t *dest, const vec_uint_t *src) +{ + assert(dest != NULL && src != NULL); + vec_uint_resize(dest, src->size); + memcpy(dest->data, src->data, sizeof(unsigned) * src->size); + dest->size = src->size; +} + +static inline void vec_uint_push_back(vec_uint_t *p, unsigned value) +{ + if (p->size == p->cap) { + if (p->cap < 16) + vec_uint_reserve(p, 16); + else + vec_uint_reserve(p, 2 * p->cap); + } + p->data[p->size] = value; + p->size++; +} + +static inline unsigned vec_uint_pop_back(vec_uint_t *p) +{ + assert(p && p->size); + return p->data[--p->size]; +} + +static inline void vec_uint_assign(vec_uint_t *p, unsigned idx, unsigned value) +{ + assert((idx >= 0) && (idx < vec_uint_size(p))); + p->data[idx] = value; +} + +static inline void vec_uint_insert(vec_uint_t *p, unsigned idx, unsigned value) +{ + assert((idx >= 0) && (idx < vec_uint_size(p))); + vec_uint_push_back(p, 0); + memmove(p->data + idx + 1, p->data + idx, (p->size - idx - 2) * sizeof(unsigned)); + p->data[idx] = value; +} + +static inline void vec_uint_drop(vec_uint_t *p, unsigned idx) +{ + assert((idx >= 0) && (idx < vec_uint_size(p))); + memmove(p->data + idx, p->data + idx + 1, (p->size - idx - 1) * sizeof(unsigned)); + p->size -= 1; +} + +static inline void vec_uint_clear(vec_uint_t *p) +{ + p->size = 0; +} + +static inline int vec_uint_asc_compare(const void *p1, const void *p2) +{ + const unsigned *pp1 = (const unsigned *) p1; + const unsigned *pp2 = (const unsigned *) p2; + + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) + return 1; + return 0; +} + +static inline int vec_uint_desc_compare(const void *p1, const void *p2) +{ + const unsigned *pp1 = (const unsigned *) p1; + const unsigned *pp2 = (const unsigned *) p2; + + if ( *pp1 > *pp2 ) + return -1; + if ( *pp1 < *pp2 ) + return 1; + return 0; +} + +static inline void vec_uint_sort(vec_uint_t *p, int ascending) +{ + if (ascending) + qsort((void *) p->data, p->size, sizeof(unsigned), + (int (*)(const void *, const void *)) vec_uint_asc_compare); + else + qsort((void*) p->data, p->size, sizeof(unsigned), + (int (*)(const void *, const void *)) vec_uint_desc_compare); +} + +static inline long vec_uint_memory(vec_uint_t *p) +{ + return p == NULL ? 0 : sizeof(unsigned) * p->cap + sizeof(vec_uint_t); +} + +static inline void vec_uint_print(vec_uint_t* p) +{ + unsigned i; + assert(p != NULL); + fprintf(stdout, "Vector has %u(%u) entries: {", p->size, p->cap); + for (i = 0; i < p->size; i++) + fprintf(stdout, " %u", p->data[i]); + fprintf(stdout, " }\n"); +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__utils__vec__vec_uint_h */ diff --git a/src/sat/satoko/watch_list.h b/src/sat/satoko/watch_list.h new file mode 100644 index 00000000..1bcbf3b4 --- /dev/null +++ b/src/sat/satoko/watch_list.h @@ -0,0 +1,203 @@ +//===--- watch_list.h -------------------------------------------------------=== +// +// satoko: Satisfiability solver +// +// This file is distributed under the BSD 2-Clause License. +// See LICENSE for details. +// +//===------------------------------------------------------------------------=== +#ifndef satoko__watch_list_h +#define satoko__watch_list_h + +#include "utils/mem.h" +#include "utils/misc.h" + +#include "misc/util/abc_global.h" +ABC_NAMESPACE_HEADER_START + +struct watcher { + unsigned cref; + unsigned blocker; +}; + +struct watch_list { + unsigned cap; + unsigned size; + unsigned n_bin; + struct watcher *watchers; +}; + +typedef struct vec_wl_t_ vec_wl_t; +struct vec_wl_t_ { + unsigned cap; + unsigned size; + struct watch_list *watch_lists; +}; + +//===------------------------------------------------------------------------=== +// Watch list Macros +//===------------------------------------------------------------------------=== +#define watch_list_foreach(vec, watch, lit) \ + for (watch = watch_list_array(vec_wl_at(vec, lit)); \ + watch < watch_list_array(vec_wl_at(vec, lit)) + watch_list_size(vec_wl_at(vec, lit)); \ + watch++) + +#define watch_list_foreach_bin(vec, watch, lit) \ + for (watch = watch_list_array(vec_wl_at(vec, lit)); \ + watch < watch_list_array(vec_wl_at(vec, lit)) + vec_wl_at(vec, lit)->n_bin; \ + watch++) +//===------------------------------------------------------------------------=== +// Watch list API +//===------------------------------------------------------------------------=== +static inline void watch_list_free(struct watch_list *wl) +{ + if (wl->watchers) + satoko_free(wl->watchers); +} + +static inline unsigned watch_list_size(struct watch_list *wl) +{ + return wl->size; +} + +static inline void watch_list_shrink(struct watch_list *wl, unsigned size) +{ + assert(size <= wl->size); + wl->size = size; +} + +static inline void watch_list_grow(struct watch_list *wl) +{ + unsigned new_size = (wl->cap < 4) ? 4 : (wl->cap / 2) * 3; + struct watcher *watchers = + satoko_realloc(struct watcher, wl->watchers, new_size); + if (watchers == NULL) { + printf("Failed to realloc memory from %.1f MB to %.1f " + "MB.\n", + 1.0 * wl->cap / (1 << 20), + 1.0 * new_size / (1 << 20)); + fflush(stdout); + return; + } + wl->watchers = watchers; + wl->cap = new_size; +} + +static inline void watch_list_push(struct watch_list *wl, struct watcher w, unsigned is_bin) +{ + assert(wl); + if (wl->size == wl->cap) + watch_list_grow(wl); + wl->watchers[wl->size++] = w; + if (is_bin && wl->size > wl->n_bin) { + stk_swap(struct watcher, wl->watchers[wl->n_bin], wl->watchers[wl->size - 1]); + wl->n_bin++; + } +} + +static inline struct watcher *watch_list_array(struct watch_list *wl) +{ + return wl->watchers; +} + +/* TODO: I still have mixed feelings if this change should be done, keeping the + * old code commented after it. */ +static inline void watch_list_remove(struct watch_list *wl, unsigned cref, unsigned is_bin) +{ + struct watcher *watchers = watch_list_array(wl); + unsigned i; + if (is_bin) { + for (i = 0; watchers[i].cref != cref; i++); + assert(i < watch_list_size(wl)); + wl->n_bin--; + memmove((wl->watchers + i), (wl->watchers + i + 1), + (wl->size - i - 1) * sizeof(struct watcher)); + } else { + for (i = wl->n_bin; watchers[i].cref != cref; i++); + assert(i < watch_list_size(wl)); + stk_swap(struct watcher, wl->watchers[i], wl->watchers[wl->size - 1]); + } + wl->size -= 1; +} + +/* +static inline void watch_list_remove(struct watch_list *wl, unsigned cref, unsigned is_bin) +{ + struct watcher *watchers = watch_list_array(wl); + unsigned i; + if (is_bin) { + for (i = 0; watchers[i].cref != cref; i++); + wl->n_bin--; + } else + for (i = wl->n_bin; watchers[i].cref != cref; i++); + assert(i < watch_list_size(wl)); + memmove((wl->watchers + i), (wl->watchers + i + 1), + (wl->size - i - 1) * sizeof(struct watcher)); + wl->size -= 1; +} +*/ + +static inline vec_wl_t *vec_wl_alloc(unsigned cap) +{ + vec_wl_t *vec_wl = satoko_alloc(vec_wl_t, 1); + + if (cap == 0) + vec_wl->cap = 4; + else + vec_wl->cap = cap; + vec_wl->size = 0; + vec_wl->watch_lists = satoko_calloc( + struct watch_list, sizeof(struct watch_list) * vec_wl->cap); + return vec_wl; +} + +static inline void vec_wl_free(vec_wl_t *vec_wl) +{ + unsigned i; + for (i = 0; i < vec_wl->cap; i++) + watch_list_free(vec_wl->watch_lists + i); + satoko_free(vec_wl->watch_lists); + satoko_free(vec_wl); +} + +static inline void vec_wl_clean(vec_wl_t *vec_wl) +{ + unsigned i; + for (i = 0; i < vec_wl->size; i++) { + vec_wl->watch_lists[i].size = 0; + vec_wl->watch_lists[i].n_bin = 0; + } + vec_wl->size = 0; +} + +static inline void vec_wl_push(vec_wl_t *vec_wl) +{ + if (vec_wl->size == vec_wl->cap) { + unsigned new_size = + (vec_wl->cap < 4) ? vec_wl->cap * 2 : (vec_wl->cap / 2) * 3; + + vec_wl->watch_lists = satoko_realloc( + struct watch_list, vec_wl->watch_lists, new_size); + memset(vec_wl->watch_lists + vec_wl->cap, 0, + sizeof(struct watch_list) * (new_size - vec_wl->cap)); + if (vec_wl->watch_lists == NULL) { + printf("failed to realloc memory from %.1f mb to %.1f " + "mb.\n", + 1.0 * vec_wl->cap / (1 << 20), + 1.0 * new_size / (1 << 20)); + fflush(stdout); + } + vec_wl->cap = new_size; + } + vec_wl->size++; +} + +static inline struct watch_list *vec_wl_at(vec_wl_t *vec_wl, unsigned idx) +{ + assert(idx < vec_wl->cap); + assert(idx < vec_wl->size); + return vec_wl->watch_lists + idx; +} + +ABC_NAMESPACE_HEADER_END +#endif /* satoko__watch_list_h */ diff --git a/src/sat/xsat/license b/src/sat/xsat/license new file mode 100644 index 00000000..a6389ab1 --- /dev/null +++ b/src/sat/xsat/license @@ -0,0 +1,39 @@ +xSAT - Copyright (c) 2016, Bruno Schmitt - UC Berkeley / UFRGS (boschmitt@inf.ufrgs.br) + +xSAT is based on Glucose v3(see Glucose copyrights below) and ABC C version of +MiniSat (bsat) developed by Niklas Sorensson and modified by Alan Mishchenko. +Permissions and copyrights of xSAT are exactly the same as Glucose v3/Minisat. +(see below). + +--------------- + +Glucose -- Copyright (c) 2013, Gilles Audemard, Laurent Simon + CRIL - Univ. Artois, France + LRI - Univ. Paris Sud, France + +Glucose sources are based on MiniSat (see below MiniSat copyrights). Permissions +and copyrights of Glucose are exactly the same as Minisat on which it is based +on. (see below). + +--------------- + +Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson +Copyright (c) 2007-2010, Niklas Sorensson + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*******************************************************************************/ diff --git a/src/sat/xsat/module.make b/src/sat/xsat/module.make new file mode 100644 index 00000000..1d7352e2 --- /dev/null +++ b/src/sat/xsat/module.make @@ -0,0 +1,3 @@ +SRC += src/sat/xsat/xsatSolver.c \ + src/sat/xsat/xsatSolverAPI.c \ + src/sat/xsat/xsatCnfReader.c diff --git a/src/sat/xsat/xsat.h b/src/sat/xsat/xsat.h new file mode 100644 index 00000000..b2962d91 --- /dev/null +++ b/src/sat/xsat/xsat.h @@ -0,0 +1,59 @@ +/**CFile**************************************************************** + + FileName [xsat.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [External definitions of the solver.] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ +#ifndef ABC__sat__xSAT__xSAT_h +#define ABC__sat__xSAT__xSAT_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include "misc/util/abc_global.h" +#include "misc/vec/vecInt.h" + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// +struct xSAT_Solver_t_; +typedef struct xSAT_Solver_t_ xSAT_Solver_t; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// +/*=== xsatCnfReader.c ================================================*/ +extern int xSAT_SolverParseDimacs( FILE *, xSAT_Solver_t ** ); + +/*=== xsatSolverAPI.c ================================================*/ +extern xSAT_Solver_t * xSAT_SolverCreate(); +extern void xSAT_SolverDestroy( xSAT_Solver_t * ); + +extern int xSAT_SolverAddClause( xSAT_Solver_t *, Vec_Int_t * ); +extern int xSAT_SolverSimplify( xSAT_Solver_t * ); +extern int xSAT_SolverSolve( xSAT_Solver_t * ); + +extern void xSAT_SolverPrintStats( xSAT_Solver_t * ); + +ABC_NAMESPACE_HEADER_END + +#endif +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/sat/xsat/xsatBQueue.h b/src/sat/xsat/xsatBQueue.h new file mode 100644 index 00000000..f75f3650 --- /dev/null +++ b/src/sat/xsat/xsatBQueue.h @@ -0,0 +1,190 @@ +/**CFile**************************************************************** + + FileName [xsatBQueue.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [Bounded queue implementation.] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ +#ifndef ABC__sat__xSAT__xsatBQueue_h +#define ABC__sat__xSAT__xsatBQueue_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include "misc/util/abc_global.h" + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// +typedef struct xSAT_BQueue_t_ xSAT_BQueue_t; +struct xSAT_BQueue_t_ +{ + int nSize; + int nCap; + int iFirst; + int iEmpty; + word nSum; + unsigned * pData; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline xSAT_BQueue_t * xSAT_BQueueNew( int nCap ) +{ + xSAT_BQueue_t * p = ABC_CALLOC( xSAT_BQueue_t, 1 ); + p->nCap = nCap; + p->pData = ABC_CALLOC( unsigned, nCap ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_BQueueFree( xSAT_BQueue_t * p ) +{ + ABC_FREE( p->pData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_BQueuePush( xSAT_BQueue_t * p, unsigned Value ) +{ + if ( p->nSize == p->nCap ) + { + assert(p->iFirst == p->iEmpty); + p->nSum -= p->pData[p->iFirst]; + p->iFirst = ( p->iFirst + 1 ) % p->nCap; + } + else + p->nSize++; + + p->nSum += Value; + p->pData[p->iEmpty] = Value; + if ( ( ++p->iEmpty ) == p->nCap ) + { + p->iEmpty = 0; + p->iFirst = 0; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int xSAT_BQueuePop( xSAT_BQueue_t * p ) +{ + int RetValue; + assert( p->nSize >= 1 ); + RetValue = p->pData[p->iFirst]; + p->nSum -= RetValue; + p->iFirst = ( p->iFirst + 1 ) % p->nCap; + p->nSize--; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned xSAT_BQueueAvg( xSAT_BQueue_t * p ) +{ + return ( unsigned )( p->nSum / ( ( word ) p->nSize ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int xSAT_BQueueIsValid( xSAT_BQueue_t * p ) +{ + return ( p->nCap == p->nSize ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_BQueueClean( xSAT_BQueue_t * p ) +{ + p->iFirst = 0; + p->iEmpty = 0; + p->nSize = 0; + p->nSum = 0; +} + +ABC_NAMESPACE_HEADER_END + +#endif diff --git a/src/sat/xsat/xsatClause.h b/src/sat/xsat/xsatClause.h new file mode 100644 index 00000000..ef353198 --- /dev/null +++ b/src/sat/xsat/xsatClause.h @@ -0,0 +1,109 @@ +/**CFile**************************************************************** + + FileName [xsatClause.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [Clause data type definition.] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ +#ifndef ABC__sat__xSAT__xsatClause_h +#define ABC__sat__xSAT__xsatClause_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include "misc/util/abc_global.h" + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// +typedef struct xSAT_Clause_t_ xSAT_Clause_t; +struct xSAT_Clause_t_ +{ + unsigned fLearnt : 1; + unsigned fMark : 1; + unsigned fReallocd : 1; + unsigned fCanBeDel : 1; + unsigned nLBD : 28; + int nSize; + union { + int Lit; + unsigned Act; + } pData[0]; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int xSAT_ClauseCompare( const void * p1, const void * p2 ) +{ + xSAT_Clause_t * pC1 = ( xSAT_Clause_t * ) p1; + xSAT_Clause_t * pC2 = ( xSAT_Clause_t * ) p2; + + if ( pC1->nSize > 2 && pC2->nSize == 2 ) + return 1; + if ( pC1->nSize == 2 && pC2->nSize > 2 ) + return 0; + if ( pC1->nSize == 2 && pC2->nSize == 2 ) + return 0; + + if ( pC1->nLBD > pC2->nLBD ) + return 1; + if ( pC1->nLBD < pC2->nLBD ) + return 0; + + return pC1->pData[pC1->nSize].Act < pC2->pData[pC2->nSize].Act; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_ClausePrint( xSAT_Clause_t * pCla ) +{ + int i; + + printf("{ "); + for ( i = 0; i < pCla->nSize; i++ ) + printf("%d ", pCla->pData[i].Lit ); + printf("}\n"); +} + +ABC_NAMESPACE_HEADER_END + +#endif +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/sat/xsat/xsatCnfReader.c b/src/sat/xsat/xsatCnfReader.c new file mode 100644 index 00000000..d23e8a0a --- /dev/null +++ b/src/sat/xsat/xsatCnfReader.c @@ -0,0 +1,236 @@ +/**CFile**************************************************************** + + FileName [xsatCnfReader.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [CNF DIMACS file format parser.] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include <ctype.h> + +#include "misc/util/abc_global.h" +#include "misc/vec/vecInt.h" + +#include "xsatSolver.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Read the file into the internal buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * xSAT_FileRead( FILE * pFile ) +{ + int nFileSize; + char * pBuffer; + int RetValue; + // get the file size, in bytes + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + // move the file current reading position to the beginning + rewind( pFile ); + // load the contents of the file into memory + pBuffer = ABC_ALLOC( char, nFileSize + 3 ); + RetValue = fread( pBuffer, nFileSize, 1, pFile ); + // terminate the string with '\0' + pBuffer[ nFileSize + 0] = '\n'; + pBuffer[ nFileSize + 1] = '\0'; + return pBuffer; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void skipLine( char ** pIn ) +{ + while ( 1 ) + { + if (**pIn == 0) + return; + if (**pIn == '\n') + { + (*pIn)++; + return; + } + (*pIn)++; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int xSAT_ReadInt( char ** pIn ) +{ + int val = 0; + int neg = 0; + + for(; isspace(**pIn); (*pIn)++); + if ( **pIn == '-' ) + neg = 1, + (*pIn)++; + else if ( **pIn == '+' ) + (*pIn)++; + if ( !isdigit(**pIn) ) + fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", **pIn), + exit(1); + while ( isdigit(**pIn) ) + val = val*10 + (**pIn - '0'), + (*pIn)++; + return neg ? -val : val; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void xSAT_ReadClause( char ** pIn, xSAT_Solver_t * p, Vec_Int_t * vLits ) +{ + int token, var, sign; + + Vec_IntClear( vLits ); + while ( 1 ) + { + token = xSAT_ReadInt( pIn ); + if ( token == 0 ) + break; + var = abs(token) - 1; + sign = (token > 0); + Vec_IntPush( vLits, xSAT_Var2Lit( var, !sign ) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int xSAT_ParseDimacs( char * pText, xSAT_Solver_t ** pS ) +{ + xSAT_Solver_t * p = NULL; + Vec_Int_t * vLits = NULL; + char * pIn = pText; + int nVars, nClas; + while ( 1 ) + { + for(; isspace(*pIn); pIn++); + if ( *pIn == 0 ) + break; + else if ( *pIn == 'c' ) + skipLine( &pIn ); + else if ( *pIn == 'p' ) + { + pIn++; + for(; isspace(*pIn); pIn++); + for(; !isspace(*pIn); pIn++); + + nVars = xSAT_ReadInt( &pIn ); + nClas = xSAT_ReadInt( &pIn ); + skipLine( &pIn ); + + /* start the solver */ + p = xSAT_SolverCreate(); + /* allocate the vector */ + vLits = Vec_IntAlloc( nVars ); + } + else + { + if ( p == NULL ) + { + printf( "There is no parameter line.\n" ); + exit(1); + } + xSAT_ReadClause( &pIn, p, vLits ); + if ( !xSAT_SolverAddClause( p, vLits ) ) + { + Vec_IntPrint(vLits); + return 0; + } + } + } + Vec_IntFree( vLits ); + *pS = p; + return xSAT_SolverSimplify( p ); +} + +/**Function************************************************************* + + Synopsis [Starts the solver and reads the DIMAC file.] + + Description [Returns FALSE upon immediate conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int xSAT_SolverParseDimacs( FILE * pFile, xSAT_Solver_t ** p ) +{ + char * pText; + int Value; + pText = xSAT_FileRead( pFile ); + Value = xSAT_ParseDimacs( pText, p ); + ABC_FREE( pText ); + return Value; +} + +ABC_NAMESPACE_IMPL_END + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/sat/xsat/xsatHeap.h b/src/sat/xsat/xsatHeap.h new file mode 100644 index 00000000..409ce460 --- /dev/null +++ b/src/sat/xsat/xsatHeap.h @@ -0,0 +1,330 @@ +/**CFile**************************************************************** + + FileName [xsatHeap.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [Heap implementation.] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ +#ifndef ABC__sat__xSAT__xsatHeap_h +#define ABC__sat__xSAT__xsatHeap_h + +#include "misc/util/abc_global.h" +#include "misc/vec/vecInt.h" + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// +typedef struct xSAT_Heap_t_ xSAT_Heap_t; +struct xSAT_Heap_t_ +{ + Vec_Int_t * vActivity; + Vec_Int_t * vIndices; + Vec_Int_t * vHeap; +}; + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int xSAT_HeapSize( xSAT_Heap_t * h ) +{ + return Vec_IntSize( h->vHeap ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int xSAT_HeapInHeap( xSAT_Heap_t * h, int Var ) +{ + return ( Var < Vec_IntSize( h->vIndices ) ) && ( Vec_IntEntry( h->vIndices, Var ) >= 0 ); +} + +static inline int Left ( int i ) { return 2 * i + 1; } +static inline int Right ( int i ) { return ( i + 1 ) * 2; } +static inline int Parent( int i ) { return ( i - 1 ) >> 1; } +static inline int Compare( xSAT_Heap_t * p, int x, int y ) +{ + return ( unsigned )Vec_IntEntry( p->vActivity, x ) > ( unsigned )Vec_IntEntry( p->vActivity, y ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_HeapPercolateUp( xSAT_Heap_t * h, int i ) +{ + int x = Vec_IntEntry( h->vHeap, i ); + int p = Parent( i ); + + while ( i != 0 && Compare( h, x, Vec_IntEntry( h->vHeap, p ) ) ) + { + Vec_IntWriteEntry( h->vHeap, i, Vec_IntEntry( h->vHeap, p ) ); + Vec_IntWriteEntry( h->vIndices, Vec_IntEntry( h->vHeap, p ), i ); + i = p; + p = Parent(p); + } + Vec_IntWriteEntry( h->vHeap, i, x ); + Vec_IntWriteEntry( h->vIndices, x, i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_HeapPercolateDown( xSAT_Heap_t * h, int i ) +{ + int x = Vec_IntEntry( h->vHeap, i ); + + while ( Left( i ) < Vec_IntSize( h->vHeap ) ) + { + int child = Right( i ) < Vec_IntSize( h->vHeap ) && + Compare( h, Vec_IntEntry( h->vHeap, Right( i ) ), Vec_IntEntry( h->vHeap, Left( i ) ) ) ? + Right( i ) : Left( i ); + + if ( !Compare( h, Vec_IntEntry( h->vHeap, child ), x ) ) + break; + + Vec_IntWriteEntry( h->vHeap, i, Vec_IntEntry( h->vHeap, child ) ); + Vec_IntWriteEntry( h->vIndices, Vec_IntEntry( h->vHeap, i ), i ); + i = child; + } + Vec_IntWriteEntry( h->vHeap, i, x ); + Vec_IntWriteEntry( h->vIndices, x, i ); +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline xSAT_Heap_t * xSAT_HeapAlloc( Vec_Int_t * vActivity ) +{ + xSAT_Heap_t * p = ABC_ALLOC( xSAT_Heap_t, 1 ); + p->vActivity = vActivity; + p->vIndices = Vec_IntAlloc( 0 ); + p->vHeap = Vec_IntAlloc( 0 ); + + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_HeapFree( xSAT_Heap_t * p ) +{ + Vec_IntFree( p->vIndices ); + Vec_IntFree( p->vHeap ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_HeapIncrease( xSAT_Heap_t * h, int e ) +{ + assert( xSAT_HeapInHeap( h, e ) ); + xSAT_HeapPercolateDown( h, Vec_IntEntry( h->vIndices, e ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_HeapDecrease( xSAT_Heap_t * p, int e ) +{ + assert( xSAT_HeapInHeap( p, e ) ); + xSAT_HeapPercolateUp( p , Vec_IntEntry( p->vIndices, e ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_HeapInsert( xSAT_Heap_t * p, int n ) +{ + Vec_IntFillExtra( p->vIndices, n + 1, -1); + assert( !xSAT_HeapInHeap( p, n ) ); + + Vec_IntWriteEntry( p->vIndices, n, Vec_IntSize( p->vHeap ) ); + Vec_IntPush( p->vHeap, n ); + xSAT_HeapPercolateUp( p, Vec_IntEntry( p->vIndices, n ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_HeapUpdate( xSAT_Heap_t * p, int i ) +{ + if ( !xSAT_HeapInHeap( p, i ) ) + xSAT_HeapInsert( p, i ); + else + { + xSAT_HeapPercolateUp( p, Vec_IntEntry( p->vIndices, i ) ); + xSAT_HeapPercolateDown( p, Vec_IntEntry( p->vIndices, i ) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_HeapBuild( xSAT_Heap_t * p, Vec_Int_t * Vars ) +{ + int i, Var; + + Vec_IntForEachEntry( p->vHeap, Var, i ) + Vec_IntWriteEntry( p->vIndices, Var, -1 ); + Vec_IntClear( p->vHeap ); + + Vec_IntForEachEntry( Vars, Var, i ) + { + Vec_IntWriteEntry( p->vIndices, Var, i ); + Vec_IntPush( p->vHeap, Var ); + } + + for ( ( i = Vec_IntSize( p->vHeap ) / 2 - 1 ); i >= 0; i-- ) + xSAT_HeapPercolateDown( p, i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_HeapClear( xSAT_Heap_t * p ) +{ + Vec_IntFill( p->vIndices, Vec_IntSize( p->vIndices ), -1 ); + Vec_IntClear( p->vHeap ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int xSAT_HeapRemoveMin( xSAT_Heap_t * p ) +{ + int x = Vec_IntEntry( p->vHeap, 0 ); + Vec_IntWriteEntry( p->vHeap, 0, Vec_IntEntryLast( p->vHeap ) ); + Vec_IntWriteEntry( p->vIndices, Vec_IntEntry( p->vHeap, 0), 0 ); + Vec_IntWriteEntry( p->vIndices, x, -1 ); + Vec_IntPop( p->vHeap ); + if ( Vec_IntSize( p->vHeap ) > 1 ) + xSAT_HeapPercolateDown( p, 0 ); + return x; +} + +ABC_NAMESPACE_HEADER_END + +#endif diff --git a/src/sat/xsat/xsatMemory.h b/src/sat/xsat/xsatMemory.h new file mode 100644 index 00000000..129c2f50 --- /dev/null +++ b/src/sat/xsat/xsatMemory.h @@ -0,0 +1,222 @@ +/**CFile**************************************************************** + + FileName [xsatMemory.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [Memory management implementation.] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ +#ifndef ABC__sat__xSAT__xsatMemory_h +#define ABC__sat__xSAT__xsatMemory_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include "misc/util/abc_global.h" + +#include "xsatClause.h" + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// +typedef struct xSAT_Mem_t_ xSAT_Mem_t; +struct xSAT_Mem_t_ +{ + unsigned nSize; + unsigned nCap; + unsigned nWasted; + unsigned * pData; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline xSAT_Clause_t * xSAT_MemClauseHand( xSAT_Mem_t * p, int h ) +{ + return h != 0xFFFFFFFF ? ( xSAT_Clause_t * )( p->pData + h ) : NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_MemGrow( xSAT_Mem_t * p, unsigned nCap ) +{ + unsigned nPrevCap = p->nCap; + if ( p->nCap >= nCap ) + return; + while (p->nCap < nCap) + { + unsigned delta = ( ( p->nCap >> 1 ) + ( p->nCap >> 3 ) + 2 ) & ~1; + p->nCap += delta; + assert(p->nCap >= nPrevCap); + } + assert(p->nCap > 0); + p->pData = ABC_REALLOC( unsigned, p->pData, p->nCap ); +} + +/**Function************************************************************* + + Synopsis [Allocating vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline xSAT_Mem_t * xSAT_MemAlloc( int nCap ) +{ + xSAT_Mem_t * p; + p = ABC_CALLOC( xSAT_Mem_t, 1 ); + if (nCap <= 0) + nCap = 1024*1024; + + xSAT_MemGrow(p, nCap); + return p; +} + +/**Function************************************************************* + + Synopsis [Resetting vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_MemRestart( xSAT_Mem_t * p ) +{ + p->nSize = 0; + p->nWasted = 0; +} + +/**Function************************************************************* + + Synopsis [Freeing vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_MemFree( xSAT_Mem_t * p ) +{ + ABC_FREE( p->pData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Creates new clause.] + + Description [The resulting clause is fully initialized.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned xSAT_MemAppend( xSAT_Mem_t * p, int nSize ) +{ + unsigned nPrevSize; + assert(nSize > 0); + xSAT_MemGrow( p, p->nSize + nSize ); + nPrevSize = p->nSize; + p->nSize += nSize; + assert(p->nSize > nPrevSize); + return nPrevSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned xSAT_MemCRef( xSAT_Mem_t * p, unsigned * pC ) +{ + return ( unsigned )( pC - &(p->pData[0]) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned xSAT_MemCap( xSAT_Mem_t * p ) +{ + return p->nCap; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned xSAT_MemWastedCap( xSAT_Mem_t * p ) +{ + return p->nWasted; +} + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/sat/xsat/xsatSolver.c b/src/sat/xsat/xsatSolver.c new file mode 100644 index 00000000..9807e1b7 --- /dev/null +++ b/src/sat/xsat/xsatSolver.c @@ -0,0 +1,1003 @@ +/**CFile**************************************************************** + + FileName [xsatSolver.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [Solver internal functions implementation.] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <math.h> + +#include "xsatHeap.h" +#include "xsatSolver.h" +#include "xsatUtils.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int xSAT_SolverDecide( xSAT_Solver_t * s ) +{ + int NextVar = VarUndef; + + while ( NextVar == VarUndef || Vec_StrEntry( s->vAssigns, NextVar ) != VarX ) + { + if ( xSAT_HeapSize( s->hOrder ) == 0 ) + { + NextVar = VarUndef; + break; + } + else + NextVar = xSAT_HeapRemoveMin( s->hOrder ); + } + return NextVar; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void xSAT_SolverRebuildOrderHeap( xSAT_Solver_t * s ) +{ + Vec_Int_t * vTemp = Vec_IntAlloc( Vec_StrSize( s->vAssigns ) ); + int Var; + + for ( Var = 0; Var < Vec_StrSize( s->vAssigns ); Var++ ) + if ( Vec_StrEntry( s->vAssigns, Var ) == VarX ) + Vec_IntPush( vTemp, Var ); + + xSAT_HeapBuild( s->hOrder, vTemp ); + Vec_IntFree( vTemp ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_SolverVarActRescale( xSAT_Solver_t * s ) +{ + int i; + unsigned * pActivity = ( unsigned * ) Vec_IntArray( s->vActivity ); + + for ( i = 0; i < Vec_IntSize( s->vActivity ); i++ ) + pActivity[i] >>= 19; + + s->nVarActInc >>= 19; + s->nVarActInc = Abc_MaxInt( s->nVarActInc, ( 1 << 5 ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_SolverVarActBump( xSAT_Solver_t * s, int Var ) +{ + unsigned * pActivity = ( unsigned * ) Vec_IntArray( s->vActivity ); + + pActivity[Var] += s->nVarActInc; + if ( pActivity[Var] & 0x80000000 ) + xSAT_SolverVarActRescale( s ); + + if ( xSAT_HeapInHeap( s->hOrder, Var ) ) + xSAT_HeapDecrease( s->hOrder, Var ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_SolverVarActDecay( xSAT_Solver_t * s ) +{ + s->nVarActInc += ( s->nVarActInc >> 4 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_SolverClaActRescale( xSAT_Solver_t * s ) +{ + xSAT_Clause_t * pC; + int i, CRef; + + Vec_IntForEachEntry( s->vLearnts, CRef, i ) + { + pC = xSAT_SolverReadClause( s, ( unsigned ) CRef ); + pC->pData[pC->nSize].Act >>= 14; + } + s->nClaActInc >>= 14; + s->nClaActInc = Abc_MaxInt( s->nClaActInc, ( 1 << 10 ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_SolverClaActBump( xSAT_Solver_t* s, xSAT_Clause_t * pCla ) +{ + pCla->pData[pCla->nSize].Act += s->nClaActInc; + if ( pCla->pData[pCla->nSize].Act & 0x80000000 ) + xSAT_SolverClaActRescale( s ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_SolverClaActDecay( xSAT_Solver_t * s ) +{ + s->nClaActInc += ( s->nClaActInc >> 10 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int xSAT_SolverClaCalcLBD( xSAT_Solver_t * s, xSAT_Clause_t * pCla ) +{ + int i; + int nLBD = 0; + + s->nStamp++; + for ( i = 0; i < pCla->nSize; i++ ) + { + int Level = Vec_IntEntry( s->vLevels, xSAT_Lit2Var( pCla->pData[i].Lit ) ); + if ( ( unsigned ) Vec_IntEntry( s->vStamp, Level ) != s->nStamp ) + { + Vec_IntWriteEntry( s->vStamp, Level, ( int ) s->nStamp ); + nLBD++; + } + } + return nLBD; +} + +static inline int xSAT_SolverClaCalcLBD2( xSAT_Solver_t * s, Vec_Int_t * vLits ) +{ + int i; + int nLBD = 0; + + s->nStamp++; + for ( i = 0; i < Vec_IntSize( vLits ); i++ ) + { + int Level = Vec_IntEntry( s->vLevels, xSAT_Lit2Var( Vec_IntEntry( vLits, i ) ) ); + if ( ( unsigned ) Vec_IntEntry( s->vStamp, Level ) != s->nStamp ) + { + Vec_IntWriteEntry( s->vStamp, Level, ( int ) s->nStamp ); + nLBD++; + } + } + return nLBD; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned xSAT_SolverClaNew( xSAT_Solver_t * s, Vec_Int_t * vLits , int fLearnt ) +{ + unsigned CRef; + xSAT_Clause_t * pCla; + xSAT_Watcher_t w1; + xSAT_Watcher_t w2; + unsigned nWords; + + assert( Vec_IntSize( vLits ) > 1); + assert( fLearnt == 0 || fLearnt == 1 ); + + nWords = 3 + fLearnt + Vec_IntSize( vLits ); + CRef = xSAT_MemAppend( s->pMemory, nWords ); + pCla = xSAT_SolverReadClause( s, CRef ); + pCla->fLearnt = fLearnt; + pCla->fMark = 0; + pCla->fReallocd = 0; + pCla->fCanBeDel = fLearnt; + pCla->nSize = Vec_IntSize( vLits ); + memcpy( &( pCla->pData[0].Lit ), Vec_IntArray( vLits ), sizeof( int ) * Vec_IntSize( vLits ) ); + + if ( fLearnt ) + { + Vec_IntPush( s->vLearnts, CRef ); + pCla->nLBD = xSAT_SolverClaCalcLBD2( s, vLits ); + pCla->pData[pCla->nSize].Act = 0; + s->Stats.nLearntLits += Vec_IntSize( vLits ); + xSAT_SolverClaActBump(s, pCla); + } + else + { + Vec_IntPush( s->vClauses, CRef ); + s->Stats.nClauseLits += Vec_IntSize( vLits ); + } + + w1.CRef = CRef; + w2.CRef = CRef; + w1.Blocker = pCla->pData[1].Lit; + w2.Blocker = pCla->pData[0].Lit; + + if ( Vec_IntSize( vLits ) == 2 ) + { + xSAT_WatchListPush( xSAT_VecWatchListEntry( s->vBinWatches, xSAT_NegLit( pCla->pData[0].Lit ) ), w1 ); + xSAT_WatchListPush( xSAT_VecWatchListEntry( s->vBinWatches, xSAT_NegLit( pCla->pData[1].Lit ) ), w2 ); + } + else + { + xSAT_WatchListPush( xSAT_VecWatchListEntry( s->vWatches, xSAT_NegLit( pCla->pData[0].Lit ) ), w1 ); + xSAT_WatchListPush( xSAT_VecWatchListEntry( s->vWatches, xSAT_NegLit( pCla->pData[1].Lit ) ), w2 ); + } + return CRef; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int xSAT_SolverEnqueue( xSAT_Solver_t * s, int Lit, unsigned Reason ) +{ + int Var = xSAT_Lit2Var( Lit ); + + Vec_StrWriteEntry( s->vAssigns, Var, (char)xSAT_LitSign( Lit ) ); + Vec_IntWriteEntry( s->vLevels, Var, xSAT_SolverDecisionLevel( s ) ); + Vec_IntWriteEntry( s->vReasons, Var, ( int ) Reason ); + Vec_IntPush( s->vTrail, Lit ); + + return true; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_SolverNewDecision( xSAT_Solver_t * s, int Lit ) +{ + assert( Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( Lit ) ) == VarX ); + s->Stats.nDecisions++; + Vec_IntPush( s->vTrailLim, Vec_IntSize( s->vTrail ) ); + xSAT_SolverEnqueue( s, Lit, CRefUndef ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void xSAT_SolverCancelUntil( xSAT_Solver_t * s, int Level ) +{ + int c; + + if ( xSAT_SolverDecisionLevel( s ) <= Level ) + return; + + for ( c = Vec_IntSize( s->vTrail ) - 1; c >= Vec_IntEntry( s->vTrailLim, Level ); c-- ) + { + int Var = xSAT_Lit2Var( Vec_IntEntry( s->vTrail, c ) ); + + Vec_StrWriteEntry( s->vAssigns, Var, VarX ); + Vec_IntWriteEntry( s->vReasons, Var, ( int ) CRefUndef ); + Vec_StrWriteEntry( s->vPolarity, Var, ( char )xSAT_LitSign( Vec_IntEntry( s->vTrail, c ) ) ); + + if ( !xSAT_HeapInHeap( s->hOrder, Var ) ) + xSAT_HeapInsert( s->hOrder, Var ); + } + + s->iQhead = Vec_IntEntry( s->vTrailLim, Level ); + Vec_IntShrink( s->vTrail, Vec_IntEntry( s->vTrailLim, Level ) ); + Vec_IntShrink( s->vTrailLim, Level ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int xSAT_SolverIsLitRemovable( xSAT_Solver_t* s, int Lit, int MinLevel ) +{ + int top = Vec_IntSize( s->vTagged ); + + assert( ( unsigned ) Vec_IntEntry( s->vReasons, xSAT_Lit2Var( Lit ) ) != CRefUndef ); + Vec_IntClear( s->vStack ); + Vec_IntPush( s->vStack, xSAT_Lit2Var( Lit ) ); + + while ( Vec_IntSize( s->vStack ) ) + { + int i; + int v = Vec_IntPop( s->vStack ); + xSAT_Clause_t* c = xSAT_SolverReadClause(s, ( unsigned ) Vec_IntEntry( s->vReasons, v ) ); + int * Lits = &( c->pData[0].Lit ); + + assert( (unsigned) Vec_IntEntry( s->vReasons, v ) != CRefUndef); + if( c->nSize == 2 && Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( Lits[0] ) ) == xSAT_LitSign( xSAT_NegLit( Lits[0] ) ) ) + { + assert( Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( Lits[1] ) ) == xSAT_LitSign( ( Lits[1] ) ) ); + ABC_SWAP( int, Lits[0], Lits[1] ); + } + + for ( i = 1; i < c->nSize; i++ ) + { + int v = xSAT_Lit2Var( Lits[i] ); + if ( !Vec_StrEntry( s->vSeen, v ) && Vec_IntEntry( s->vLevels, v ) ) + { + if ( ( unsigned ) Vec_IntEntry( s->vReasons, v ) != CRefUndef && ( ( 1 << (Vec_IntEntry( s->vLevels, v ) & 31 ) ) & MinLevel ) ) + { + Vec_IntPush( s->vStack, v ); + Vec_IntPush( s->vTagged, Lits[i] ); + Vec_StrWriteEntry( s->vSeen, v, 1 ); + } + else + { + int Lit; + Vec_IntForEachEntryStart( s->vTagged, Lit, i, top ) + Vec_StrWriteEntry( s->vSeen, xSAT_Lit2Var( Lit ), 0 ); + Vec_IntShrink( s->vTagged, top ); + return 0; + } + } + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void xSAT_SolverClaMinimisation( xSAT_Solver_t * s, Vec_Int_t * vLits ) +{ + int * pLits = Vec_IntArray( vLits ); + int MinLevel = 0; + int i, j; + + for ( i = 1; i < Vec_IntSize( vLits ); i++ ) + { + int Level = Vec_IntEntry( s->vLevels, xSAT_Lit2Var( pLits[i] ) ); + MinLevel |= 1 << ( Level & 31 ); + } + + /* Remove reduntant literals */ + Vec_IntAppend( s->vTagged, vLits ); + for ( i = j = 1; i < Vec_IntSize( vLits ); i++ ) + if ( ( unsigned ) Vec_IntEntry( s->vReasons, xSAT_Lit2Var( pLits[i] ) ) == CRefUndef || !xSAT_SolverIsLitRemovable( s, pLits[i], MinLevel ) ) + pLits[j++] = pLits[i]; + Vec_IntShrink( vLits, j ); + + /* Binary Resolution */ + if( Vec_IntSize( vLits ) <= 30 && xSAT_SolverClaCalcLBD2( s, vLits ) <= 6 ) + { + int nb, l; + int Lit; + int FlaseLit = xSAT_NegLit( pLits[0] ); + xSAT_WatchList_t * ws = xSAT_VecWatchListEntry( s->vBinWatches, FlaseLit ); + xSAT_Watcher_t * begin = xSAT_WatchListArray( ws ); + xSAT_Watcher_t * end = begin + xSAT_WatchListSize( ws ); + xSAT_Watcher_t * pWatcher; + + s->nStamp++; + Vec_IntForEachEntry( vLits, Lit, i ) + Vec_IntWriteEntry( s->vStamp, xSAT_Lit2Var( Lit ), ( int ) s->nStamp ); + + nb = 0; + for ( pWatcher = begin; pWatcher < end; pWatcher++ ) + { + int ImpLit = pWatcher->Blocker; + + if ( ( unsigned ) Vec_IntEntry( s->vStamp, xSAT_Lit2Var( ImpLit ) ) == s->nStamp && Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( ImpLit ) ) == xSAT_LitSign( ImpLit ) ) + { + nb++; + Vec_IntWriteEntry( s->vStamp, xSAT_Lit2Var( ImpLit ), ( int )( s->nStamp - 1 ) ); + } + } + + l = Vec_IntSize( vLits ) - 1; + if ( nb > 0 ) + { + for ( i = 1; i < Vec_IntSize( vLits ) - nb; i++ ) + if ( ( unsigned ) Vec_IntEntry( s->vStamp, xSAT_Lit2Var( pLits[i] ) ) != s->nStamp ) + { + int TempLit = pLits[l]; + pLits[l] = pLits[i]; + pLits[i] = TempLit; + i--; l--; + } + + Vec_IntShrink( vLits, Vec_IntSize( vLits ) - nb ); + } + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void xSAT_SolverAnalyze( xSAT_Solver_t* s, unsigned ConfCRef, Vec_Int_t * vLearnt, int * OutBtLevel, unsigned * nLBD ) +{ + int * trail = Vec_IntArray( s->vTrail ); + int Count = 0; + int p = LitUndef; + int Idx = Vec_IntSize( s->vTrail ) - 1; + int * Lits; + int Lit; + int i, j; + + Vec_IntPush( vLearnt, LitUndef ); + do + { + xSAT_Clause_t * pCla; + + assert( ConfCRef != CRefUndef ); + pCla = xSAT_SolverReadClause(s, ConfCRef); + Lits = &( pCla->pData[0].Lit ); + + if( p != LitUndef && pCla->nSize == 2 && Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( Lits[0] ) ) == xSAT_LitSign( xSAT_NegLit( Lits[0] ) ) ) + { + assert( Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( Lits[1] ) ) == xSAT_LitSign( ( Lits[1] ) ) ); + ABC_SWAP( int, Lits[0], Lits[1] ); + } + + if ( pCla->fLearnt ) + xSAT_SolverClaActBump( s, pCla ); + + if ( pCla->fLearnt && pCla->nLBD > 2 ) + { + unsigned int nLevels = xSAT_SolverClaCalcLBD( s, pCla ); + if ( nLevels + 1 < pCla->nLBD ) + { + if ( pCla->nLBD <= s->Config.nLBDFrozenClause ) + pCla->fCanBeDel = 0; + pCla->nLBD = nLevels; + } + } + + for ( j = ( p == LitUndef ? 0 : 1 ); j < pCla->nSize; j++ ) + { + int Var = xSAT_Lit2Var( Lits[j] ); + + if ( Vec_StrEntry( s->vSeen, Var ) == 0 && Vec_IntEntry( s->vLevels, Var ) > 0 ) + { + Vec_StrWriteEntry( s->vSeen, Var, 1 ); + xSAT_SolverVarActBump( s, Var ); + if ( Vec_IntEntry( s->vLevels, Var ) >= xSAT_SolverDecisionLevel( s ) ) + { + Count++; + if ( Vec_IntEntry( s->vReasons, Var ) != CRefUndef && xSAT_SolverReadClause( s, Vec_IntEntry( s->vReasons, Var ) )->fLearnt ) + Vec_IntPush( s->vLastDLevel, Var ); + } + else + Vec_IntPush( vLearnt, Lits[j] ); + } + } + + while ( !Vec_StrEntry( s->vSeen, xSAT_Lit2Var( trail[Idx--] ) ) ); + + // Next clause to look at + p = trail[Idx+1]; + ConfCRef = ( unsigned ) Vec_IntEntry( s->vReasons, xSAT_Lit2Var( p ) ); + Vec_StrWriteEntry( s->vSeen, xSAT_Lit2Var( p ), 0 ); + Count--; + + } while ( Count > 0 ); + + Vec_IntArray( vLearnt )[0] = xSAT_NegLit( p ); + xSAT_SolverClaMinimisation( s, vLearnt ); + + // Find the backtrack level + Lits = Vec_IntArray( vLearnt ); + if ( Vec_IntSize( vLearnt ) == 1 ) + *OutBtLevel = 0; + else + { + int iMax = 1; + int Max = Vec_IntEntry( s->vLevels, xSAT_Lit2Var( Lits[1] ) ); + int Tmp; + + for (i = 2; i < Vec_IntSize( vLearnt ); i++) + if ( Vec_IntEntry( s->vLevels, xSAT_Lit2Var( Lits[i]) ) > Max) + { + Max = Vec_IntEntry( s->vLevels, xSAT_Lit2Var( Lits[i]) ); + iMax = i; + } + + Tmp = Lits[1]; + Lits[1] = Lits[iMax]; + Lits[iMax] = Tmp; + *OutBtLevel = Vec_IntEntry( s->vLevels, xSAT_Lit2Var( Lits[1] ) ); + } + + *nLBD = xSAT_SolverClaCalcLBD2( s, vLearnt ); + if ( Vec_IntSize( s->vLastDLevel ) > 0 ) + { + int Var; + Vec_IntForEachEntry( s->vLastDLevel, Var, i ) + { + if ( xSAT_SolverReadClause( s, Vec_IntEntry( s->vReasons, Var ) )->nLBD < *nLBD ) + xSAT_SolverVarActBump( s, Var ); + } + + Vec_IntClear( s->vLastDLevel ); + } + + Vec_IntForEachEntry( s->vTagged, Lit, i ) + Vec_StrWriteEntry( s->vSeen, xSAT_Lit2Var( Lit ), 0 ); + Vec_IntClear( s->vTagged ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned xSAT_SolverPropagate( xSAT_Solver_t* s ) +{ + unsigned hConfl = CRefUndef; + int * Lits; + int NegLit; + int nProp = 0; + + while ( s->iQhead < Vec_IntSize( s->vTrail ) ) + { + int p = Vec_IntEntry( s->vTrail, s->iQhead++ ); + xSAT_WatchList_t* ws = xSAT_VecWatchListEntry( s->vBinWatches, p ); + xSAT_Watcher_t* begin = xSAT_WatchListArray( ws ); + xSAT_Watcher_t* end = begin + xSAT_WatchListSize( ws ); + xSAT_Watcher_t *i, *j; + + nProp++; + for ( i = begin; i < end; i++ ) + { + if ( Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( i->Blocker ) ) == VarX ) + xSAT_SolverEnqueue( s, i->Blocker, i->CRef ); + else if ( Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( i->Blocker ) ) == xSAT_LitSign( xSAT_NegLit( i->Blocker ) ) ) + return i->CRef; + } + + ws = xSAT_VecWatchListEntry( s->vWatches, p ); + begin = xSAT_WatchListArray( ws ); + end = begin + xSAT_WatchListSize( ws ); + + for ( i = j = begin; i < end; ) + { + xSAT_Clause_t * pCla; + xSAT_Watcher_t w; + if ( Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( i->Blocker ) ) == xSAT_LitSign( i->Blocker ) ) + { + *j++ = *i++; + continue; + } + + pCla = xSAT_SolverReadClause( s, i->CRef ); + Lits = &( pCla->pData[0].Lit ); + + // Make sure the false literal is data[1]: + NegLit = xSAT_NegLit( p ); + if ( Lits[0] == NegLit ) + { + Lits[0] = Lits[1]; + Lits[1] = NegLit; + } + assert( Lits[1] == NegLit ); + + w.CRef = i->CRef; + w.Blocker = Lits[0]; + + // If 0th watch is true, then clause is already satisfied. + if ( Lits[0] != i->Blocker && Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( Lits[0] ) ) == xSAT_LitSign( Lits[0] ) ) + *j++ = w; + else + { + // Look for new watch: + int * stop = Lits + pCla->nSize; + int * k; + for ( k = Lits + 2; k < stop; k++ ) + { + if (Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( *k ) ) != !xSAT_LitSign( *k ) ) + { + Lits[1] = *k; + *k = NegLit; + xSAT_WatchListPush( xSAT_VecWatchListEntry( s->vWatches, xSAT_NegLit( Lits[1] ) ), w ); + goto next; + } + } + + *j++ = w; + + // Clause is unit under assignment: + if (Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( Lits[0] ) ) == xSAT_LitSign( xSAT_NegLit( Lits[0] ) ) ) + { + hConfl = i->CRef; + i++; + s->iQhead = Vec_IntSize( s->vTrail ); + // Copy the remaining watches: + while (i < end) + *j++ = *i++; + } + else + xSAT_SolverEnqueue( s, Lits[0], i->CRef ); + } + next: + i++; + } + + s->Stats.nInspects += j - xSAT_WatchListArray( ws ); + xSAT_WatchListShrink( ws, j - xSAT_WatchListArray( ws ) ); + } + + s->Stats.nPropagations += nProp; + s->nPropSimplify -= nProp; + + return hConfl; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void xSAT_SolverReduceDB( xSAT_Solver_t * s ) +{ + static abctime TimeTotal = 0; + abctime clk = Abc_Clock(); + int nLearnedOld = Vec_IntSize( s->vLearnts ); + int i, limit; + unsigned CRef; + xSAT_Clause_t * pCla; + xSAT_Clause_t ** learnts_cls; + + learnts_cls = ABC_ALLOC( xSAT_Clause_t *, nLearnedOld ); + Vec_IntForEachEntry( s->vLearnts, CRef, i ) + learnts_cls[i] = xSAT_SolverReadClause(s, CRef); + + limit = nLearnedOld / 2; + + xSAT_UtilSort((void *) learnts_cls, nLearnedOld, + (int (*)( const void *, const void * )) xSAT_ClauseCompare); + + if ( learnts_cls[nLearnedOld / 2]->nLBD <= 3 ) + s->nRC2 += s->Config.nSpecialIncReduce; + if ( learnts_cls[nLearnedOld - 1]->nLBD <= 5 ) + s->nRC2 += s->Config.nSpecialIncReduce; + + Vec_IntClear( s->vLearnts ); + for ( i = 0; i < nLearnedOld; i++ ) + { + unsigned CRef; + + pCla = learnts_cls[i]; + CRef = xSAT_MemCRef( s->pMemory, ( unsigned * ) pCla ); + assert( pCla->fMark == 0 ); + if ( pCla->fCanBeDel && pCla->nLBD > 2 && pCla->nSize > 2 && (unsigned) Vec_IntEntry( s->vReasons, xSAT_Lit2Var( pCla->pData[0].Lit ) ) != CRef && ( i < limit ) ) + { + pCla->fMark = 1; + s->Stats.nLearntLits -= pCla->nSize; + xSAT_WatchListRemove( xSAT_VecWatchListEntry( s->vWatches, xSAT_NegLit( pCla->pData[0].Lit ) ), CRef ); + xSAT_WatchListRemove( xSAT_VecWatchListEntry( s->vWatches, xSAT_NegLit( pCla->pData[1].Lit ) ), CRef ); + } + else + { + if ( !pCla->fCanBeDel ) + limit++; + pCla->fCanBeDel = 1; + Vec_IntPush( s->vLearnts, CRef ); + } + } + ABC_FREE( learnts_cls ); + + TimeTotal += Abc_Clock() - clk; + if ( s->Config.fVerbose ) + { + Abc_Print(1, "reduceDB: Keeping %7d out of %7d clauses (%5.2f %%) ", + Vec_IntSize( s->vLearnts ), nLearnedOld, 100.0 * Vec_IntSize( s->vLearnts ) / nLearnedOld ); + Abc_PrintTime( 1, "Time", TimeTotal ); + } + xSAT_SolverGarbageCollect(s); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char xSAT_SolverSearch( xSAT_Solver_t * s ) +{ + iword conflictC = 0; + + s->Stats.nStarts++; + for (;;) + { + unsigned hConfl = xSAT_SolverPropagate( s ); + + if ( hConfl != CRefUndef ) + { + /* Conflict */ + int BacktrackLevel; + unsigned nLBD; + unsigned CRef; + + s->Stats.nConflicts++; + conflictC++; + + if ( xSAT_SolverDecisionLevel( s ) == 0 ) + return LBoolFalse; + + xSAT_BQueuePush( s->bqTrail, Vec_IntSize( s->vTrail ) ); + if ( s->Stats.nConflicts > s->Config.nFirstBlockRestart && xSAT_BQueueIsValid( s->bqLBD ) && ( Vec_IntSize( s->vTrail ) > ( s->Config.R * ( iword ) xSAT_BQueueAvg( s->bqTrail ) ) ) ) + xSAT_BQueueClean(s->bqLBD); + + Vec_IntClear( s->vLearntClause ); + xSAT_SolverAnalyze( s, hConfl, s->vLearntClause, &BacktrackLevel, &nLBD ); + + s->nSumLBD += nLBD; + xSAT_BQueuePush( s->bqLBD, nLBD ); + xSAT_SolverCancelUntil( s, BacktrackLevel ); + + CRef = Vec_IntSize( s->vLearntClause ) == 1 ? CRefUndef : xSAT_SolverClaNew( s, s->vLearntClause , 1 ); + xSAT_SolverEnqueue( s, Vec_IntEntry( s->vLearntClause , 0 ), CRef ); + + xSAT_SolverVarActDecay( s ); + xSAT_SolverClaActDecay( s ); + } + else + { + /* No conflict */ + int NextVar; + if ( xSAT_BQueueIsValid( s->bqLBD ) && ( ( ( iword )xSAT_BQueueAvg( s->bqLBD ) * s->Config.K ) > ( s->nSumLBD / s->Stats.nConflicts ) ) ) + { + xSAT_BQueueClean( s->bqLBD ); + xSAT_SolverCancelUntil( s, 0 ); + return LBoolUndef; + } + + // Simplify the set of problem clauses: + if ( xSAT_SolverDecisionLevel( s ) == 0 ) + xSAT_SolverSimplify( s ); + + // Reduce the set of learnt clauses: + if ( s->Stats.nConflicts >= s->nConfBeforeReduce ) + { + s->nRC1 = ( s->Stats.nConflicts / s->nRC2 ) + 1; + xSAT_SolverReduceDB(s); + s->nRC2 += s->Config.nIncReduce; + s->nConfBeforeReduce = s->nRC1 * s->nRC2; + } + + // New variable decision: + NextVar = xSAT_SolverDecide( s ); + + if ( NextVar == VarUndef ) + return LBoolTrue; + + xSAT_SolverNewDecision( s, xSAT_Var2Lit( NextVar, ( int ) Vec_StrEntry( s->vPolarity, NextVar ) ) ); + } + } + + return LBoolUndef; // cannot happen +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void xSAT_SolverClaRealloc( xSAT_Mem_t * pDest, xSAT_Mem_t * pSrc, unsigned * pCRef ) +{ + unsigned nNewCRef; + xSAT_Clause_t * pNewCla; + xSAT_Clause_t * pOldCla = xSAT_MemClauseHand( pSrc, *pCRef ); + + if ( pOldCla->fReallocd ) + { + *pCRef = ( unsigned ) pOldCla->nSize; + return; + } + nNewCRef = xSAT_MemAppend( pDest, 3 + pOldCla->fLearnt + pOldCla->nSize ); + pNewCla = xSAT_MemClauseHand( pDest, nNewCRef ); + memcpy( pNewCla, pOldCla, ( 3 + pOldCla->fLearnt + pOldCla->nSize ) * 4 ); + pOldCla->fReallocd = 1; + pOldCla->nSize = ( unsigned ) nNewCRef; + *pCRef = nNewCRef; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void xSAT_SolverGarbageCollect( xSAT_Solver_t * s ) +{ + int i; + unsigned * pArray; + xSAT_Mem_t * pNewMemMngr = xSAT_MemAlloc( xSAT_MemCap( s->pMemory ) - xSAT_MemWastedCap( s->pMemory ) ); + + for ( i = 0; i < 2 * Vec_StrSize( s->vAssigns ); i++ ) + { + xSAT_WatchList_t* ws = xSAT_VecWatchListEntry( s->vWatches, i); + xSAT_Watcher_t* begin = xSAT_WatchListArray(ws); + xSAT_Watcher_t* end = begin + xSAT_WatchListSize(ws); + xSAT_Watcher_t *w; + + for ( w = begin; w != end; w++ ) + xSAT_SolverClaRealloc( pNewMemMngr, s->pMemory, &(w->CRef) ); + + ws = xSAT_VecWatchListEntry( s->vBinWatches, i); + begin = xSAT_WatchListArray(ws); + end = begin + xSAT_WatchListSize(ws); + for ( w = begin; w != end; w++ ) + xSAT_SolverClaRealloc( pNewMemMngr, s->pMemory, &(w->CRef) ); + } + + for ( i = 0; i < Vec_IntSize( s->vTrail ); i++ ) + if ( ( unsigned ) Vec_IntEntry( s->vReasons, xSAT_Lit2Var( Vec_IntEntry( s->vTrail, i ) ) ) != CRefUndef ) + xSAT_SolverClaRealloc( pNewMemMngr, s->pMemory, ( unsigned * ) &( Vec_IntArray( s->vReasons )[xSAT_Lit2Var( Vec_IntEntry( s->vTrail, i ) )] ) ); + + pArray = ( unsigned * ) Vec_IntArray( s->vLearnts ); + for ( i = 0; i < Vec_IntSize( s->vLearnts ); i++ ) + xSAT_SolverClaRealloc( pNewMemMngr, s->pMemory, &(pArray[i]) ); + + pArray = ( unsigned * ) Vec_IntArray( s->vClauses ); + for ( i = 0; i < Vec_IntSize( s->vClauses ); i++ ) + xSAT_SolverClaRealloc( pNewMemMngr, s->pMemory, &(pArray[i]) ); + + xSAT_MemFree( s->pMemory ); + s->pMemory = pNewMemMngr; +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/xsat/xsatSolver.h b/src/sat/xsat/xsatSolver.h new file mode 100644 index 00000000..36432e03 --- /dev/null +++ b/src/sat/xsat/xsatSolver.h @@ -0,0 +1,248 @@ +/**CFile**************************************************************** + + FileName [xsatSolver.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [Internal definitions of the solver.] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ +#ifndef ABC__sat__xSAT__xsatSolver_h +#define ABC__sat__xSAT__xsatSolver_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "misc/util/abc_global.h" +#include "misc/vec/vecStr.h" + +#include "xsat.h" +#include "xsatBQueue.h" +#include "xsatClause.h" +#include "xsatHeap.h" +#include "xsatMemory.h" +#include "xsatWatchList.h" + +ABC_NAMESPACE_HEADER_START + +#ifndef __cplusplus +#ifndef false +# define false 0 +#endif +#ifndef true +# define true 1 +#endif +#endif + +enum +{ + Var0 = 1, + Var1 = 0, + VarX = 3 +}; + +enum +{ + LBoolUndef = 0, + LBoolTrue = 1, + LBoolFalse = -1 +}; + +enum +{ + VarUndef = -1, + LitUndef = -2 +}; + +#define CRefUndef 0xFFFFFFFF + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// +typedef struct xSAT_SolverOptions_t_ xSAT_SolverOptions_t; +struct xSAT_SolverOptions_t_ +{ + char fVerbose; + + // Limits + iword nConfLimit; // external limit on the number of conflicts + iword nInsLimit; // external limit on the number of implications + abctime nRuntimeLimit; // external limit on runtime + + // Constants used for restart heuristic + double K; // Forces a restart + double R; // Block a restart + int nFirstBlockRestart; // Lower bound number of conflicts for start blocking restarts + int nSizeLBDQueue; // Size of the moving avarege queue for LBD (force restart) + int nSizeTrailQueue; // Size of the moving avarege queue for Trail size (block restart) + + // Constants used for clause database reduction heuristic + int nConfFirstReduce; // Number of conflicts before first reduction + int nIncReduce; // Increment to reduce + int nSpecialIncReduce; // Special increment to reduce + unsigned nLBDFrozenClause; +}; + +typedef struct xSAT_Stats_t_ xSAT_Stats_t; +struct xSAT_Stats_t_ +{ + unsigned nStarts; + unsigned nReduceDB; + + iword nDecisions; + iword nPropagations; + iword nInspects; + iword nConflicts; + + iword nClauseLits; + iword nLearntLits; +}; + +struct xSAT_Solver_t_ +{ + /* Clauses Database */ + xSAT_Mem_t * pMemory; + Vec_Int_t * vLearnts; + Vec_Int_t * vClauses; + xSAT_VecWatchList_t * vWatches; + xSAT_VecWatchList_t * vBinWatches; + + /* Activity heuristic */ + int nVarActInc; /* Amount to bump next variable with. */ + int nClaActInc; /* Amount to bump next clause with. */ + + /* Variable Information */ + Vec_Int_t * vActivity; /* A heuristic measurement of the activity of a variable. */ + xSAT_Heap_t * hOrder; + Vec_Int_t * vLevels; /* Decision level of the current assignment */ + Vec_Int_t * vReasons; /* Reason (clause) of the current assignment */ + Vec_Str_t * vAssigns; /* Current assignment. */ + Vec_Str_t * vPolarity; + Vec_Str_t * vTags; + + /* Assignments */ + Vec_Int_t * vTrail; + Vec_Int_t * vTrailLim; // Separator indices for different decision levels in 'trail'. + int iQhead; // Head of propagation queue (as index into the trail). + + int nAssignSimplify; /* Number of top-level assignments since last + * execution of 'simplify()'. */ + iword nPropSimplify; /* Remaining number of propagations that must be + * made before next execution of 'simplify()'. */ + + /* Temporary data used by Search method */ + xSAT_BQueue_t * bqTrail; + xSAT_BQueue_t * bqLBD; + float nSumLBD; + int nConfBeforeReduce; + long nRC1; + int nRC2; + + /* Temporary data used by Analyze */ + Vec_Int_t * vLearntClause; + Vec_Str_t * vSeen; + Vec_Int_t * vTagged; + Vec_Int_t * vStack; + Vec_Int_t * vLastDLevel; + + /* Misc temporary */ + unsigned nStamp; + Vec_Int_t * vStamp; /* Multipurpose stamp used to calculate LBD and + * clauses minimization with binary resolution */ + + xSAT_SolverOptions_t Config; + xSAT_Stats_t Stats; +}; + +static inline int xSAT_Var2Lit( int Var, int c ) +{ + return Var + Var + ( c != 0 ); +} + +static inline int xSAT_NegLit( int Lit ) +{ + return Lit ^ 1; +} + +static inline int xSAT_Lit2Var( int Lit ) +{ + return Lit >> 1; +} + +static inline int xSAT_LitSign( int Lit ) +{ + return Lit & 1; +} + +static inline int xSAT_SolverDecisionLevel( xSAT_Solver_t * s ) +{ + return Vec_IntSize( s->vTrailLim ); +} + +static inline xSAT_Clause_t * xSAT_SolverReadClause( xSAT_Solver_t * s, unsigned h ) +{ + return xSAT_MemClauseHand( s->pMemory, h ); +} + +static inline int xSAT_SolverIsClauseSatisfied( xSAT_Solver_t * s, xSAT_Clause_t * pCla ) +{ + int i; + int * Lits = &( pCla->pData[0].Lit ); + + for ( i = 0; i < pCla->nSize; i++ ) + if ( Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( Lits[i] ) ) == xSAT_LitSign( ( Lits[i] ) ) ) + return true; + + return false; +} + +static inline void xSAT_SolverPrintClauses( xSAT_Solver_t * s ) +{ + int i; + unsigned CRef; + + Vec_IntForEachEntry( s->vClauses, CRef, i ) + xSAT_ClausePrint( xSAT_SolverReadClause( s, CRef ) ); +} + +static inline void xSAT_SolverPrintState( xSAT_Solver_t * s ) +{ + printf( "starts : %10d\n", s->Stats.nStarts ); + printf( "conflicts : %10ld\n", s->Stats.nConflicts ); + printf( "decisions : %10ld\n", s->Stats.nDecisions ); + printf( "propagations : %10ld\n", s->Stats.nPropagations ); +} + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// +extern unsigned xSAT_SolverClaNew( xSAT_Solver_t* s, Vec_Int_t * vLits, int fLearnt ); +extern char xSAT_SolverSearch( xSAT_Solver_t * s ); + +extern void xSAT_SolverGarbageCollect( xSAT_Solver_t * s ); + +extern int xSAT_SolverEnqueue( xSAT_Solver_t* s, int Lit, unsigned From ); +extern void xSAT_SolverCancelUntil( xSAT_Solver_t* s, int Level); +extern unsigned xSAT_SolverPropagate( xSAT_Solver_t* s ); +extern void xSAT_SolverRebuildOrderHeap( xSAT_Solver_t* s ); + +ABC_NAMESPACE_HEADER_END + +#endif diff --git a/src/sat/xsat/xsatSolverAPI.c b/src/sat/xsat/xsatSolverAPI.c new file mode 100644 index 00000000..7746dc0b --- /dev/null +++ b/src/sat/xsat/xsatSolverAPI.c @@ -0,0 +1,346 @@ +/**CFile**************************************************************** + + FileName [xsatSolverAPI.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [Solver external API functions implementation.] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <math.h> + +#include "xsatSolver.h" + +ABC_NAMESPACE_IMPL_START + +xSAT_SolverOptions_t DefaultConfig = +{ + 1, //.fVerbose = 1, + + 0, //.nConfLimit = 0, + 0, //.nInsLimit = 0, + 0, //.nRuntimeLimit = 0, + + 0.8, //.K = 0.8, + 1.4, //.R = 1.4, + 10000, //.nFirstBlockRestart = 10000, + 50, //.nSizeLBDQueue = 50, + 5000, //.nSizeTrailQueue = 5000, + + 2000, //.nConfFirstReduce = 2000, + 300, //.nIncReduce = 300, + 1000, //.nSpecialIncReduce = 1000, + + 30 //.nLBDFrozenClause = 30 +}; + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +xSAT_Solver_t* xSAT_SolverCreate() +{ + xSAT_Solver_t * s = (xSAT_Solver_t *) ABC_CALLOC( char, sizeof( xSAT_Solver_t ) ); + s->Config = DefaultConfig; + + s->pMemory = xSAT_MemAlloc(0); + s->vClauses = Vec_IntAlloc(0); + s->vLearnts = Vec_IntAlloc(0); + s->vWatches = xSAT_VecWatchListAlloc( 0 ); + s->vBinWatches = xSAT_VecWatchListAlloc( 0 ); + + s->vTrailLim = Vec_IntAlloc(0); + s->vTrail = Vec_IntAlloc( 0 ); + + s->vActivity = Vec_IntAlloc( 0 ); + s->hOrder = xSAT_HeapAlloc( s->vActivity ); + + s->vPolarity = Vec_StrAlloc( 0 ); + s->vTags = Vec_StrAlloc( 0 ); + s->vAssigns = Vec_StrAlloc( 0 ); + s->vLevels = Vec_IntAlloc( 0 ); + s->vReasons = Vec_IntAlloc( 0 ); + s->vStamp = Vec_IntAlloc( 0 ); + + s->vTagged = Vec_IntAlloc(0); + s->vStack = Vec_IntAlloc(0); + + s->vSeen = Vec_StrAlloc( 0 ); + s->vLearntClause = Vec_IntAlloc(0); + s->vLastDLevel = Vec_IntAlloc(0); + + + s->bqTrail = xSAT_BQueueNew( s->Config.nSizeTrailQueue ); + s->bqLBD = xSAT_BQueueNew( s->Config.nSizeLBDQueue ); + + s->nVarActInc = (1 << 5); + s->nClaActInc = (1 << 11); + + s->nConfBeforeReduce = s->Config.nConfFirstReduce; + s->nRC1 = 1; + s->nRC2 = s->Config.nConfFirstReduce; + return s; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void xSAT_SolverDestroy( xSAT_Solver_t * s ) +{ + xSAT_MemFree( s->pMemory ); + Vec_IntFree( s->vClauses ); + Vec_IntFree( s->vLearnts ); + xSAT_VecWatchListFree( s->vWatches ); + xSAT_VecWatchListFree( s->vBinWatches ); + + xSAT_HeapFree(s->hOrder); + Vec_IntFree( s->vTrailLim ); + Vec_IntFree( s->vTrail ); + Vec_IntFree( s->vTagged ); + Vec_IntFree( s->vStack ); + + Vec_StrFree( s->vSeen ); + Vec_IntFree( s->vLearntClause ); + Vec_IntFree( s->vLastDLevel ); + + Vec_IntFree( s->vActivity ); + Vec_StrFree( s->vPolarity ); + Vec_StrFree( s->vTags ); + Vec_StrFree( s->vAssigns ); + Vec_IntFree( s->vLevels ); + Vec_IntFree( s->vReasons ); + Vec_IntFree( s->vStamp ); + + xSAT_BQueueFree(s->bqLBD); + xSAT_BQueueFree(s->bqTrail); + + ABC_FREE(s); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int xSAT_SolverSimplify( xSAT_Solver_t * s ) +{ + int i, j; + unsigned CRef; + assert( xSAT_SolverDecisionLevel(s) == 0 ); + + if ( xSAT_SolverPropagate(s) != CRefUndef ) + return false; + + if ( s->nAssignSimplify == Vec_IntSize( s->vTrail ) || s->nPropSimplify > 0 ) + return true; + + j = 0; + Vec_IntForEachEntry( s->vClauses, CRef, i ) + { + xSAT_Clause_t * pCla = xSAT_SolverReadClause( s, CRef ); + if ( xSAT_SolverIsClauseSatisfied( s, pCla ) ) + { + pCla->fMark = 1; + s->Stats.nClauseLits -= pCla->nSize; + + if ( pCla->nSize == 2 ) + { + xSAT_WatchListRemove( xSAT_VecWatchListEntry( s->vBinWatches, xSAT_NegLit(pCla->pData[0].Lit) ), CRef ); + xSAT_WatchListRemove( xSAT_VecWatchListEntry( s->vBinWatches, xSAT_NegLit(pCla->pData[1].Lit) ), CRef ); + } + else + { + xSAT_WatchListRemove( xSAT_VecWatchListEntry( s->vWatches, xSAT_NegLit(pCla->pData[0].Lit) ), CRef ); + xSAT_WatchListRemove( xSAT_VecWatchListEntry( s->vWatches, xSAT_NegLit(pCla->pData[1].Lit) ), CRef ); + } + } + else + Vec_IntWriteEntry( s->vClauses, j++, CRef ); + } + Vec_IntShrink( s->vClauses, j ); + xSAT_SolverRebuildOrderHeap( s ); + + s->nAssignSimplify = Vec_IntSize( s->vTrail ); + s->nPropSimplify = s->Stats.nClauseLits + s->Stats.nLearntLits; + + return true; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void xSAT_SolverAddVariable( xSAT_Solver_t* s, int Sign ) +{ + int Var = Vec_IntSize( s->vActivity ); + + xSAT_VecWatchListPush( s->vWatches ); + xSAT_VecWatchListPush( s->vWatches ); + xSAT_VecWatchListPush( s->vBinWatches ); + xSAT_VecWatchListPush( s->vBinWatches ); + + Vec_IntPush( s->vActivity, 0 ); + Vec_IntPush( s->vLevels, 0 ); + Vec_StrPush( s->vAssigns, VarX ); + Vec_StrPush( s->vPolarity, 1 ); + Vec_StrPush( s->vTags, 0 ); + Vec_IntPush( s->vReasons, ( int ) CRefUndef ); + Vec_IntPush( s->vStamp, 0 ); + Vec_StrPush( s->vSeen, 0 ); + + xSAT_HeapInsert( s->hOrder, Var ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int xSAT_SolverAddClause( xSAT_Solver_t * s, Vec_Int_t * vLits ) +{ + int i, j; + int Lit, PrevLit; + int MaxVar; + + Vec_IntSort( vLits, 0 ); + MaxVar = xSAT_Lit2Var( Vec_IntEntryLast( vLits ) ); + while ( MaxVar >= Vec_IntSize( s->vActivity ) ) + xSAT_SolverAddVariable( s, 1 ); + + j = 0; + PrevLit = LitUndef; + Vec_IntForEachEntry( vLits, Lit, i ) + { + if ( Lit == xSAT_NegLit( PrevLit ) || Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( Lit ) ) == xSAT_LitSign( Lit ) ) + return true; + else if ( Lit != PrevLit && Vec_StrEntry( s->vAssigns, xSAT_Lit2Var( Lit ) ) == VarX ) + { + PrevLit = Lit; + Vec_IntWriteEntry( vLits, j++, Lit ); + } + } + Vec_IntShrink( vLits, j ); + + if ( Vec_IntSize( vLits ) == 0 ) + return false; + if ( Vec_IntSize( vLits ) == 1 ) + { + xSAT_SolverEnqueue( s, Vec_IntEntry( vLits, 0 ), CRefUndef ); + return ( xSAT_SolverPropagate( s ) == CRefUndef ); + } + + xSAT_SolverClaNew( s, vLits, 0 ); + return true; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int xSAT_SolverSolve( xSAT_Solver_t* s ) +{ + char status = LBoolUndef; + + assert(s); + if ( s->Config.fVerbose ) + { + printf( "==========================================[ BLACK MAGIC ]================================================\n" ); + printf( "| | | |\n" ); + printf( "| - Restarts: | - Reduce Clause DB: | - Minimize Asserting: |\n" ); + printf( "| * LBD Queue : %6d | * First : %6d | * size < %3d |\n", s->Config.nSizeLBDQueue, s->Config.nConfFirstReduce, 0 ); + printf( "| * Trail Queue : %6d | * Inc : %6d | * lbd < %3d |\n", s->Config.nSizeTrailQueue, s->Config.nIncReduce, 0 ); + printf( "| * K : %6.2f | * Special : %6d | |\n", s->Config.K, s->Config.nSpecialIncReduce ); + printf( "| * R : %6.2f | * Protected : (lbd)< %2d | |\n", s->Config.R, s->Config.nLBDFrozenClause ); + printf( "| | | |\n" ); + printf( "=========================================================================================================\n" ); + } + + while ( status == LBoolUndef ) + status = xSAT_SolverSearch( s ); + + if ( s->Config.fVerbose ) + printf( "=========================================================================================================\n" ); + + xSAT_SolverCancelUntil( s, 0 ); + return status; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void xSAT_SolverPrintStats( xSAT_Solver_t * s ) +{ + printf( "starts : %10d\n", s->Stats.nStarts ); + printf( "conflicts : %10ld\n", s->Stats.nConflicts ); + printf( "decisions : %10ld\n", s->Stats.nDecisions ); + printf( "propagations : %10ld\n", s->Stats.nPropagations ); +} + +ABC_NAMESPACE_IMPL_END diff --git a/src/sat/xsat/xsatUtils.h b/src/sat/xsat/xsatUtils.h new file mode 100644 index 00000000..7f774d85 --- /dev/null +++ b/src/sat/xsat/xsatUtils.h @@ -0,0 +1,106 @@ +/**CFile**************************************************************** + + FileName [xsatUtils.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [Utility functions used in xSAT] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ +#ifndef ABC__sat__xSAT__xsatUtils_h +#define ABC__sat__xSAT__xsatUtils_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include "misc/util/abc_global.h" + +ABC_NAMESPACE_HEADER_START + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_UtilSelectSort( void** pArray, int nSize, int(* CompFnct )( const void *, const void * ) ) +{ + int i, j, iBest; + void* pTmp; + + for ( i = 0; i < ( nSize - 1 ); i++ ) + { + iBest = i; + for ( j = i + 1; j < nSize; j++ ) + { + if ( CompFnct( pArray[j], pArray[iBest] ) ) + iBest = j; + } + pTmp = pArray[i]; + pArray[i] = pArray[iBest]; + pArray[iBest] = pTmp; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void xSAT_UtilSort( void** pArray, int nSize, int(* CompFnct )( const void *, const void *) ) +{ + if ( nSize <= 15 ) + xSAT_UtilSelectSort( pArray, nSize, CompFnct ); + else + { + void* pPivot = pArray[nSize / 2]; + void* pTmp; + int i = -1; + int j = nSize; + + for(;;) + { + do i++; while( CompFnct( pArray[i], pPivot ) ); + do j--; while( CompFnct( pPivot, pArray[j] ) ); + + if ( i >= j ) + break; + + pTmp = pArray[i]; + pArray[i] = pArray[j]; + pArray[j] = pTmp; + } + + xSAT_UtilSort( pArray, i, CompFnct ); + xSAT_UtilSort( pArray + i, ( nSize - i ), CompFnct ); + } +} + +ABC_NAMESPACE_HEADER_END + +#endif +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/src/sat/xsat/xsatWatchList.h b/src/sat/xsat/xsatWatchList.h new file mode 100644 index 00000000..284be100 --- /dev/null +++ b/src/sat/xsat/xsatWatchList.h @@ -0,0 +1,269 @@ +/**CFile**************************************************************** + + FileName [xsatWatchList.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [xSAT - A SAT solver written in C. + Read the license file for more info.] + + Synopsis [Watch list and its related structures implementation] + + Author [Bruno Schmitt <boschmitt@inf.ufrgs.br>] + + Affiliation [UC Berkeley / UFRGS] + + Date [Ver. 1.0. Started - November 10, 2016.] + + Revision [] + +***********************************************************************/ +#ifndef ABC__sat__xSAT__xsatWatchList_h +#define ABC__sat__xSAT__xsatWatchList_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// +#include "misc/util/abc_global.h" + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// +typedef struct xSAT_Watcher_t_ xSAT_Watcher_t; +struct xSAT_Watcher_t_ +{ + unsigned CRef; + int Blocker; +}; + +typedef struct xSAT_WatchList_t_ xSAT_WatchList_t; +struct xSAT_WatchList_t_ +{ + int nCap; + int nSize; + xSAT_Watcher_t * pArray; +}; + +typedef struct xSAT_VecWatchList_t_ xSAT_VecWatchList_t; +struct xSAT_VecWatchList_t_ +{ + int nCap; + int nSize; + xSAT_WatchList_t * pArray; +}; + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_WatchListFree( xSAT_WatchList_t * v ) +{ + if ( v->pArray ) + ABC_FREE( v->pArray ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int xSAT_WatchListSize( xSAT_WatchList_t * v ) +{ + return v->nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_WatchListShrink( xSAT_WatchList_t * v, int k ) +{ + assert(k <= v->nSize); + v->nSize = k; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_WatchListPush( xSAT_WatchList_t * v, xSAT_Watcher_t e ) +{ + assert( v ); + if ( v->nSize == v->nCap ) + { + int newsize = ( v->nCap < 4 ) ? 4 : ( v->nCap / 2 ) * 3; + + v->pArray = ABC_REALLOC( xSAT_Watcher_t, v->pArray, newsize ); + if ( v->pArray == NULL ) + { + printf( "Failed to realloc memory from %.1f MB to %.1f MB.\n", + 1.0 * v->nCap / (1<<20), 1.0 * newsize / (1<<20) ); + fflush( stdout ); + } + v->nCap = newsize; + } + + v->pArray[v->nSize++] = e; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline xSAT_Watcher_t* xSAT_WatchListArray( xSAT_WatchList_t * v ) +{ + return v->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_WatchListRemove( xSAT_WatchList_t * v, unsigned CRef ) +{ + xSAT_Watcher_t* ws = xSAT_WatchListArray(v); + int j = 0; + + for ( ; ws[j].CRef != CRef; j++ ); + assert( j < xSAT_WatchListSize( v ) ); + memmove( v->pArray + j, v->pArray + j + 1, ( v->nSize - j - 1 ) * sizeof( xSAT_Watcher_t ) ); + v->nSize -= 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline xSAT_VecWatchList_t * xSAT_VecWatchListAlloc( int nCap ) +{ + xSAT_VecWatchList_t * v = ABC_ALLOC( xSAT_VecWatchList_t, 1 ); + + v->nCap = 4; + v->nSize = 0; + v->pArray = ( xSAT_WatchList_t * ) ABC_CALLOC(xSAT_WatchList_t, sizeof( xSAT_WatchList_t ) * v->nCap); + return v; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_VecWatchListFree( xSAT_VecWatchList_t* v ) +{ + int i; + for( i = 0; i < v->nSize; i++ ) + xSAT_WatchListFree( v->pArray + i ); + + ABC_FREE( v->pArray ); + ABC_FREE( v ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void xSAT_VecWatchListPush( xSAT_VecWatchList_t* v ) +{ + if ( v->nSize == v->nCap ) + { + int newsize = (v->nCap < 4) ? v->nCap * 2 : (v->nCap / 2) * 3; + + v->pArray = ABC_REALLOC( xSAT_WatchList_t, v->pArray, newsize ); + memset( v->pArray + v->nCap, 0, sizeof( xSAT_WatchList_t ) * ( newsize - v->nCap ) ); + if ( v->pArray == NULL ) + { + printf( "Failed to realloc memory from %.1f MB to %.1f MB.\n", + 1.0 * v->nCap / (1<<20), 1.0 * newsize / (1<<20) ); + fflush( stdout ); + } + v->nCap = newsize; + } + + v->nSize++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline xSAT_WatchList_t * xSAT_VecWatchListEntry( xSAT_VecWatchList_t* v, int iEntry ) +{ + assert( iEntry < v->nCap ); + assert( iEntry < v->nSize ); + return v->pArray + iEntry; +} + +ABC_NAMESPACE_HEADER_END + +#endif |