summaryrefslogtreecommitdiffstats
path: root/src/aig/gia/giaCSat3.c
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2021-10-09 15:16:18 -0700
committerAlan Mishchenko <alanmi@berkeley.edu>2021-10-09 15:16:18 -0700
commitd514029e342f3ed72459fccce89666049e62867c (patch)
tree5ed771fcc01c70121554751e0b19a3e882582e9b /src/aig/gia/giaCSat3.c
parent1afd156dbdf4a0845610bbfd2159e930944b1f57 (diff)
downloadabc-d514029e342f3ed72459fccce89666049e62867c.tar.gz
abc-d514029e342f3ed72459fccce89666049e62867c.tar.bz2
abc-d514029e342f3ed72459fccce89666049e62867c.zip
Experiments with SAT solving.
Diffstat (limited to 'src/aig/gia/giaCSat3.c')
-rw-r--r--src/aig/gia/giaCSat3.c1365
1 files changed, 1365 insertions, 0 deletions
diff --git a/src/aig/gia/giaCSat3.c b/src/aig/gia/giaCSat3.c
new file mode 100644
index 00000000..c34c84ca
--- /dev/null
+++ b/src/aig/gia/giaCSat3.c
@@ -0,0 +1,1365 @@
+/**CFile****************************************************************
+
+ FileName [giaCSat.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Scalable AIG package.]
+
+ Synopsis [A simple circuit-based solver.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+
+ABC_NAMESPACE_IMPL_START
+
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+typedef struct Cbs3_Par_t_ Cbs3_Par_t;
+struct Cbs3_Par_t_
+{
+ // conflict limits
+ int nBTLimit; // limit on the number of conflicts
+ int nJustLimit; // limit on the size of justification queue
+ int nRestLimit; // limit on the number of restarts
+ // current parameters
+ int nBTThis; // number of conflicts
+ int nJustThis; // max size of the frontier
+ int nBTTotal; // total number of conflicts
+ int nJustTotal; // total size of the frontier
+ // other
+ int fVerbose;
+};
+
+typedef struct Cbs3_Que_t_ Cbs3_Que_t;
+struct Cbs3_Que_t_
+{
+ int iHead; // beginning of the queue
+ int iTail; // end of the queue
+ int nSize; // allocated size
+ int * pData; // nodes stored in the queue
+};
+
+typedef struct Cbs3_Man_t_ Cbs3_Man_t;
+struct Cbs3_Man_t_
+{
+ Cbs3_Par_t Pars; // parameters
+ Gia_Man_t * pAig; // AIG manager
+ Cbs3_Que_t pProp; // propagation queue
+ Cbs3_Que_t pJust; // justification queue
+ Cbs3_Que_t pClauses; // clause queue
+ Vec_Int_t * vModel; // satisfying assignment
+ Vec_Int_t * vTemp; // temporary storage
+ // circuit structure
+ int nVars;
+ int nVarsAlloc;
+ int var_inc;
+ Vec_Int_t vMap;
+ Vec_Int_t vRef;
+ Vec_Int_t vFans;
+ Vec_Wec_t vImps;
+ // internal data
+ Vec_Str_t vAssign;
+ Vec_Str_t vMark;
+ Vec_Int_t vLevReason;
+ Vec_Int_t vActs;
+ Vec_Int_t vWatches;
+ Vec_Int_t vWatchUpds;
+ // SAT calls statistics
+ int nSatUnsat; // the number of proofs
+ int nSatSat; // the number of failure
+ int nSatUndec; // the number of timeouts
+ int nSatTotal; // the number of calls
+ // conflicts
+ int nConfUnsat; // conflicts in unsat problems
+ int nConfSat; // conflicts in sat problems
+ int nConfUndec; // conflicts in undec problems
+ // runtime stats
+ abctime timeJFront;
+ abctime timeSatLoad; // SAT solver loading time
+ abctime timeSatUnsat; // unsat
+ abctime timeSatSat; // sat
+ abctime timeSatUndec; // undecided
+ abctime timeTotal; // total runtime
+ // other statistics
+ int nPropCalls[3];
+ int nFails[2];
+ int nClauseConf;
+ int nDecs;
+};
+
+static inline int Cbs3_VarUnused( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry(&p->vLevReason, 3*iVar) == -1; }
+static inline void Cbs3_VarSetUnused( Cbs3_Man_t * p, int iVar ) { Vec_IntWriteEntry(&p->vLevReason, 3*iVar, -1); }
+
+static inline int Cbs3_VarMark0( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vMark, iVar); }
+static inline void Cbs3_VarSetMark0( Cbs3_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vMark, iVar, (char)Value); }
+
+static inline int Cbs3_VarIsAssigned( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar) < 2; }
+static inline void Cbs3_VarUnassign( Cbs3_Man_t * p, int iVar ) { assert( Cbs3_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)(2+Vec_StrEntry(&p->vAssign, iVar))); Cbs3_VarSetUnused(p, iVar); }
+
+static inline int Cbs3_VarValue( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar); }
+static inline void Cbs3_VarSetValue( Cbs3_Man_t * p, int iVar, int v ) { assert( !Cbs3_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)v); }
+
+static inline int Cbs3_VarLit0( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 0) ); }
+static inline int Cbs3_VarLit1( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 1) ); }
+static inline int Cbs3_VarIsPi( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 0) ) == 0; }
+static inline int Cbs3_VarIsJust( Cbs3_Man_t * p, int iVar ) { int * pLits = Vec_IntEntryP(&p->vFans, Abc_Var2Lit(iVar, 0)); return pLits[0] > 0 && Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])) >= 2 && Cbs3_VarValue(p, Abc_Lit2Var(pLits[1])) >= 2; }
+
+static inline int Cbs3_VarDecLevel( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar); }
+static inline int Cbs3_VarReason0( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+1); }
+static inline int Cbs3_VarReason1( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+2); }
+static inline int * Cbs3_VarReasonP( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntryP(&p->vLevReason, 3*iVar+1); }
+static inline int Cbs3_ClauseDecLevel( Cbs3_Man_t * p, int hClause ) { return Cbs3_VarDecLevel( p, p->pClauses.pData[hClause] ); }
+
+static inline int Cbs3_ClauseSize( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData[hClause]; }
+static inline int * Cbs3_ClauseLits( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+1; }
+static inline int Cbs3_ClauseLit( Cbs3_Man_t * p, int hClause, int i ) { return p->pClauses.pData[hClause+1+i]; }
+static inline int * Cbs3_ClauseNext1p( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+Cbs3_ClauseSize(p, hClause)+2; }
+
+static inline void Cbs3_ClauseSetSize( Cbs3_Man_t * p, int hClause, int x ) { p->pClauses.pData[hClause] = x; }
+static inline void Cbs3_ClauseSetLit( Cbs3_Man_t * p, int hClause, int i, int x ) { p->pClauses.pData[hClause+i+1] = x; }
+static inline void Cbs3_ClauseSetNext( Cbs3_Man_t * p, int hClause, int n, int x ){ p->pClauses.pData[hClause+Cbs3_ClauseSize(p, hClause)+1+n] = x; }
+
+
+#define Cbs3_QueForEachEntry( Que, iObj, i ) \
+ for ( i = (Que).iHead; (i < (Que).iTail) && ((iObj) = (Que).pData[i]); i++ )
+
+#define Cbs3_ClauseForEachEntry( p, hClause, iObj, i ) \
+ for ( i = 1; i <= Cbs3_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ )
+#define Cbs3_ClauseForEachEntry1( p, hClause, iObj, i ) \
+ for ( i = 2; i <= Cbs3_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Sets default values of the parameters.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cbs3_SetDefaultParams( Cbs3_Par_t * pPars )
+{
+ memset( pPars, 0, sizeof(Cbs3_Par_t) );
+ pPars->nBTLimit = 1000; // limit on the number of conflicts
+ pPars->nJustLimit = 500; // limit on the size of justification queue
+ pPars->nRestLimit = 10; // limit on the number of restarts
+ pPars->fVerbose = 1; // print detailed statistics
+}
+void Cbs3_ManSetConflictNum( Cbs3_Man_t * p, int Num )
+{
+ p->Pars.nBTLimit = Num;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Cbs3_Man_t * Cbs3_ManAlloc( Gia_Man_t * pGia )
+{
+ Cbs3_Man_t * p;
+ p = ABC_CALLOC( Cbs3_Man_t, 1 );
+ p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000;
+ p->pProp.pData = ABC_ALLOC( int, p->pProp.nSize );
+ p->pJust.pData = ABC_ALLOC( int, p->pJust.nSize );
+ p->pClauses.pData = ABC_ALLOC( int, p->pClauses.nSize );
+ p->pClauses.iHead = p->pClauses.iTail = 1;
+ p->vModel = Vec_IntAlloc( 1000 );
+ p->vTemp = Vec_IntAlloc( 1000 );
+ p->pAig = pGia;
+ Cbs3_SetDefaultParams( &p->Pars );
+ // circuit structure
+ Vec_IntPush( &p->vMap, -1 );
+ Vec_IntPush( &p->vRef, -1 );
+ Vec_IntPushTwo( &p->vFans, -1, -1 );
+ Vec_WecPushLevel( &p->vImps );
+ Vec_WecPushLevel( &p->vImps );
+ p->nVars = 1;
+ // internal data
+ p->nVarsAlloc = 1000;
+ Vec_StrFill( &p->vAssign, p->nVarsAlloc, 2 );
+ Vec_StrFill( &p->vMark, p->nVarsAlloc, 0 );
+ Vec_IntFill( &p->vLevReason, 3*p->nVarsAlloc, -1 );
+ Vec_IntFill( &p->vActs, p->nVarsAlloc, 0 );
+ Vec_IntFill( &p->vWatches, 2*p->nVarsAlloc, 0 );
+ Vec_IntGrow( &p->vWatchUpds, 1000 );
+ return p;
+}
+static inline void Cbs3_ManReset( Cbs3_Man_t * p )
+{
+ assert( p->nVars == Vec_IntSize(&p->vMap) );
+ Vec_IntShrink( &p->vMap, 1 );
+ Vec_IntShrink( &p->vRef, 1 );
+ Vec_IntShrink( &p->vFans, 2 );
+ Vec_WecShrink( &p->vImps, 2 );
+ p->nVars = 1;
+}
+static inline void Cbs3_ManGrow( Cbs3_Man_t * p )
+{
+ if ( p->nVarsAlloc < p->nVars )
+ {
+ p->nVarsAlloc = 2*p->nVars;
+ Vec_StrFill( &p->vAssign, p->nVarsAlloc, 2 );
+ Vec_StrFill( &p->vMark, p->nVarsAlloc, 0 );
+ Vec_IntFill( &p->vLevReason, 3*p->nVarsAlloc, -1 );
+ Vec_IntFill( &p->vActs, p->nVarsAlloc, 0 );
+ Vec_IntFill( &p->vWatches, 2*p->nVarsAlloc, 0 );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cbs3_ManStop( Cbs3_Man_t * p )
+{
+ // circuit structure
+ Vec_IntErase( &p->vMap );
+ Vec_IntErase( &p->vRef );
+ Vec_IntErase( &p->vFans );
+ Vec_WecErase( &p->vImps );
+ // internal data
+ Vec_StrErase( &p->vAssign );
+ Vec_StrErase( &p->vMark );
+ Vec_IntErase( &p->vLevReason );
+ Vec_IntErase( &p->vActs );
+ Vec_IntErase( &p->vWatches );
+ Vec_IntErase( &p->vWatchUpds );
+ Vec_IntFree( p->vModel );
+ Vec_IntFree( p->vTemp );
+ ABC_FREE( p->pClauses.pData );
+ ABC_FREE( p->pProp.pData );
+ ABC_FREE( p->pJust.pData );
+ ABC_FREE( p );
+}
+int Cbs3_ManMemory( Cbs3_Man_t * p )
+{
+ int nMem = sizeof(Cbs3_Man_t);
+ nMem += (int)Vec_IntMemory( &p->vMap );
+ nMem += (int)Vec_IntMemory( &p->vRef );
+ nMem += (int)Vec_IntMemory( &p->vFans );
+ nMem += (int)Vec_WecMemory( &p->vImps );
+ nMem += (int)Vec_StrMemory( &p->vAssign );
+ nMem += (int)Vec_StrMemory( &p->vMark );
+ nMem += (int)Vec_IntMemory( &p->vActs );
+ nMem += (int)Vec_IntMemory( &p->vWatches );
+ nMem += (int)Vec_IntMemory( &p->vWatchUpds );
+ nMem += (int)Vec_IntMemory( p->vModel );
+ nMem += (int)Vec_IntMemory( p->vTemp );
+ nMem += 4*p->pClauses.nSize;
+ nMem += 4*p->pProp.nSize;
+ nMem += 4*p->pJust.nSize;
+ return nMem;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns satisfying assignment.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Cbs3_ReadModel( Cbs3_Man_t * p )
+{
+ return p->vModel;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Activity.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+//#define USE_ACTIVITY
+
+#ifdef USE_ACTIVITY
+static inline void Cbs3_ActReset( Cbs3_Man_t * p )
+{
+ int i, * pAct = Vec_IntArray(&p->vActs);
+ for ( i = 0; i < p->nVars; i++ )
+ pAct[i] = (1 << 10);
+ p->var_inc = (1 << 5);
+}
+static inline void Cbs3_ActRescale( Cbs3_Man_t * p )
+{
+ int i, * pAct = Vec_IntArray(&p->vActs);
+ for ( i = 0; i < p->nVars; i++ )
+ pAct[i] >>= 19;
+ p->var_inc >>= 19;
+ p->var_inc = Abc_MaxInt( (unsigned)p->var_inc, (1<<5) );
+}
+static inline void Cbs3_ActBumpVar( Cbs3_Man_t * p, int iVar )
+{
+ int * pAct = Vec_IntArray(&p->vActs);
+ pAct[iVar] += p->var_inc;
+ if ((unsigned)pAct[iVar] & 0x80000000)
+ Cbs3_ActRescale(p);
+}
+static inline void Cbs3_ActDecay( Cbs3_Man_t * p )
+{
+ p->var_inc += (p->var_inc >> 4);
+}
+#else
+static inline void Cbs3_ActReset( Cbs3_Man_t * p ) {}
+static inline void Cbs3_ActRescale( Cbs3_Man_t * p ) {}
+static inline void Cbs3_ActBumpVar( Cbs3_Man_t * p, int iVar ) {}
+static inline void Cbs3_ActDecay( Cbs3_Man_t * p ) {}
+#endif
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the solver is out of limits.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cbs3_ManCheckLimits( Cbs3_Man_t * p )
+{
+ p->nFails[0] += p->Pars.nJustThis > p->Pars.nJustLimit;
+ p->nFails[1] += p->Pars.nBTThis > p->Pars.nBTLimit;
+ return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Saves the satisfying assignment as an array of literals.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cbs3_ManSaveModel( Cbs3_Man_t * p, Vec_Int_t * vCex )
+{
+ int i, iLit;
+ Vec_IntClear( vCex );
+ p->pProp.iHead = 0;
+ Cbs3_QueForEachEntry( p->pProp, iLit, i )
+ if ( Cbs3_VarIsPi(p, Abc_Lit2Var(iLit)) )
+ Vec_IntPush( vCex, Abc_Lit2LitV(Vec_IntArray(&p->vMap), iLit)-2 );
+}
+static inline void Cbs3_ManSaveModelAll( Cbs3_Man_t * p, Vec_Int_t * vCex )
+{
+ int i, iLit;
+ Vec_IntClear( vCex );
+ p->pProp.iHead = 0;
+ Cbs3_QueForEachEntry( p->pProp, iLit, i )
+ {
+ int iVar = Abc_Lit2Var(iLit);
+ Vec_IntPush( vCex, Abc_Var2Lit(iVar, !Cbs3_VarValue(p, iVar)) );
+ }
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cbs3_QueIsEmpty( Cbs3_Que_t * p )
+{
+ return p->iHead == p->iTail;
+}
+static inline int Cbs3_QueSize( Cbs3_Que_t * p )
+{
+ return p->iTail - p->iHead;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cbs3_QuePush( Cbs3_Que_t * p, int iObj )
+{
+ if ( p->iTail == p->nSize )
+ {
+ p->nSize *= 2;
+ p->pData = ABC_REALLOC( int, p->pData, p->nSize );
+ }
+ p->pData[p->iTail++] = iObj;
+}
+static inline void Cbs3_QueGrow( Cbs3_Que_t * p, int Plus )
+{
+ if ( p->iTail + Plus > p->nSize )
+ {
+ p->nSize *= 2;
+ p->pData = ABC_REALLOC( int, p->pData, p->nSize );
+ }
+ assert( p->iTail + Plus <= p->nSize );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns 1 if the object in the queue.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cbs3_QueHasNode( Cbs3_Que_t * p, int iObj )
+{
+ int i, iTemp;
+ Cbs3_QueForEachEntry( *p, iTemp, i )
+ if ( iTemp == iObj )
+ return 1;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cbs3_QueStore( Cbs3_Que_t * p, int * piHeadOld, int * piTailOld )
+{
+ int i;
+ *piHeadOld = p->iHead;
+ *piTailOld = p->iTail;
+ for ( i = *piHeadOld; i < *piTailOld; i++ )
+ Cbs3_QuePush( p, p->pData[i] );
+ p->iHead = *piTailOld;
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cbs3_QueRestore( Cbs3_Que_t * p, int iHeadOld, int iTailOld )
+{
+ p->iHead = iHeadOld;
+ p->iTail = iTailOld;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Find variable with the highest ID.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cbs3_ManDecide( Cbs3_Man_t * p )
+{
+ int i, iObj, iObjMax = 0;
+#ifdef USE_ACTIVITY
+ Cbs3_QueForEachEntry( p->pJust, iObj, i )
+ if ( iObjMax == 0 ||
+ Vec_IntEntry(&p->vActs, iObjMax) < Vec_IntEntry(&p->vActs, iObj) ||
+ (Vec_IntEntry(&p->vActs, iObjMax) == Vec_IntEntry(&p->vActs, iObj) && Vec_IntEntry(&p->vMap, iObjMax) < Vec_IntEntry(&p->vMap, iObj)) )
+ iObjMax = iObj;
+#else
+ Cbs3_QueForEachEntry( p->pJust, iObj, i )
+// if ( iObjMax == 0 || iObjMax < iObj )
+ if ( iObjMax == 0 || Vec_IntEntry(&p->vMap, iObjMax) < Vec_IntEntry(&p->vMap, iObj) )
+ iObjMax = iObj;
+#endif
+ return iObjMax;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cbs3_ManCancelUntil( Cbs3_Man_t * p, int iBound )
+{
+ int i, iLit;
+ assert( iBound <= p->pProp.iTail );
+ p->pProp.iHead = iBound;
+ Cbs3_QueForEachEntry( p->pProp, iLit, i )
+ Cbs3_VarUnassign( p, Abc_Lit2Var(iLit) );
+ p->pProp.iTail = iBound;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Assigns the variables a value.]
+
+ Description [Returns 1 if conflict; 0 if no conflict.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cbs3_ManAssign( Cbs3_Man_t * p, int iLit, int Level, int iRes0, int iRes1 )
+{
+ int iObj = Abc_Lit2Var(iLit);
+ assert( Cbs3_VarUnused(p, iObj) );
+ assert( !Cbs3_VarIsAssigned(p, iObj) );
+ Cbs3_VarSetValue( p, iObj, !Abc_LitIsCompl(iLit) );
+ Cbs3_QuePush( &p->pProp, iLit );
+ Vec_IntWriteEntry( &p->vLevReason, 3*iObj, Level );
+ Vec_IntWriteEntry( &p->vLevReason, 3*iObj+1, iRes0 );
+ Vec_IntWriteEntry( &p->vLevReason, 3*iObj+2, iRes1 );
+}
+
+
+
+
+/**Function*************************************************************
+
+ Synopsis [Prints conflict clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cbs3_ManPrintClause( Cbs3_Man_t * p, int Level, int hClause )
+{
+ int i, iLit;
+ assert( Cbs3_QueIsEmpty( &p->pClauses ) );
+ printf( "Level %2d : ", Level );
+ Cbs3_ClauseForEachEntry( p, hClause, iLit, i )
+ printf( "%c%d ", Abc_LitIsCompl(iLit) ? '-':'+', Abc_Lit2Var(iLit) );
+// printf( "%d=%d(%d) ", iObj, Cbs3_VarValue(p, Abc_Lit2Var(iLit)), Cbs3_VarDecLevel(p, Abc_Lit2Var(iLit)) );
+ printf( "\n" );
+}
+static inline void Cbs3_ManPrintCube( Cbs3_Man_t * p, int Level, int hClause )
+{
+ int i, iObj;
+ assert( Cbs3_QueIsEmpty( &p->pClauses ) );
+ printf( "Level %2d : ", Level );
+ Cbs3_ClauseForEachEntry( p, hClause, iObj, i )
+ printf( "%c%d ", Cbs3_VarValue(p, iObj)? '+':'-', iObj );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Finalized the clause.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cbs3_ManCleanWatch( Cbs3_Man_t * p )
+{
+ int i, iLit;
+ Vec_IntForEachEntry( &p->vWatchUpds, iLit, i )
+ Vec_IntWriteEntry( &p->vWatches, iLit, 0 );
+ Vec_IntClear( &p->vWatchUpds );
+ //Vec_IntForEachEntry( &p->vWatches, iLit, i )
+ // assert( iLit == 0 );
+}
+static inline void Cbs3_ManWatchClause( Cbs3_Man_t * p, int hClause, int Lit )
+{
+ int * pLits = Cbs3_ClauseLits( p, hClause );
+ int * pPlace = Vec_IntEntryP( &p->vWatches, Abc_LitNot(Lit) );
+ if ( *pPlace == 0 )
+ Vec_IntPush( &p->vWatchUpds, Abc_LitNot(Lit) );
+/*
+ if ( pClause->pLits[0] == Lit )
+ pClause->pNext0 = p->pWatches[lit_neg(Lit)];
+ else
+ {
+ assert( pClause->pLits[1] == Lit );
+ pClause->pNext1 = p->pWatches[lit_neg(Lit)];
+ }
+ p->pWatches[lit_neg(Lit)] = pClause;
+*/
+ assert( Lit == pLits[0] || Lit == pLits[1] );
+ Cbs3_ClauseSetNext( p, hClause, Lit == pLits[1], *pPlace );
+ *pPlace = hClause;
+}
+static inline int Cbs3_QueFinish( Cbs3_Man_t * p, int Level )
+{
+ Cbs3_Que_t * pQue = &(p->pClauses);
+ int i, iObj, hClauseC, hClause = pQue->iHead, Size = pQue->iTail - pQue->iHead - 1;
+ assert( pQue->iHead+1 < pQue->iTail );
+ Cbs3_ClauseSetSize( p, pQue->iHead, Size );
+ hClauseC = pQue->iHead = pQue->iTail;
+ //printf( "Adding cube: " ); Cbs3_ManPrintCube(p, Level, hClause);
+ if ( Size == 1 )
+ return hClause;
+ // create watched clause
+ pQue->iHead = hClause;
+ Cbs3_QueForEachEntry( p->pClauses, iObj, i )
+ {
+ if ( i == hClauseC )
+ break;
+ else if ( i == hClause ) // nlits
+ Cbs3_QuePush( pQue, iObj );
+ else // literals
+ Cbs3_QuePush( pQue, Abc_Var2Lit(iObj, Cbs3_VarValue(p, iObj)) ); // complement
+ }
+ Cbs3_QuePush( pQue, 0 ); // next0
+ Cbs3_QuePush( pQue, 0 ); // next1
+ pQue->iHead = pQue->iTail;
+ Cbs3_ManWatchClause( p, hClauseC, Cbs3_ClauseLit(p, hClauseC, 0) );
+ Cbs3_ManWatchClause( p, hClauseC, Cbs3_ClauseLit(p, hClauseC, 1) );
+ //printf( "Adding clause %d: ", hClauseC ); Cbs3_ManPrintClause(p, Level, hClauseC);
+ Cbs3_ActDecay( p );
+ return hClause;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Returns conflict clause.]
+
+ Description [Performs conflict analysis.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cbs3_ManDeriveReason( Cbs3_Man_t * p, int Level )
+{
+ Cbs3_Que_t * pQue = &(p->pClauses);
+ int i, k, iObj, iLitLevel, * pReason;
+ assert( pQue->pData[pQue->iHead] == 0 );
+ assert( pQue->pData[pQue->iHead+1] == 0 );
+ assert( pQue->iHead + 2 < pQue->iTail );
+ //for ( i = pQue->iHead + 2; i < pQue->iTail; i++ )
+ // assert( !Cbs3_VarMark0(p, pQue->pData[i]) );
+ // compact literals
+ Vec_IntClear( p->vTemp );
+ for ( i = k = pQue->iHead + 2; i < pQue->iTail; i++ )
+ {
+ iObj = pQue->pData[i];
+ if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again
+ continue;
+ //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 )
+ // Vec_IntPush( &p->vActStore, iObj );
+ //Vec_IntAddToEntry( &p->vActivity, iObj, 1 );
+ // assigned - seen first time
+ Cbs3_VarSetMark0(p, iObj, 1);
+ Cbs3_ActBumpVar(p, iObj);
+ Vec_IntPush( p->vTemp, iObj );
+ // check decision level
+ iLitLevel = Cbs3_VarDecLevel( p, iObj );
+ if ( iLitLevel < Level )
+ {
+ pQue->pData[k++] = iObj;
+ continue;
+ }
+ assert( iLitLevel == Level );
+ pReason = Cbs3_VarReasonP( p, iObj );
+ if ( pReason[0] == 0 && pReason[1] == 0 ) // no reason
+ {
+ assert( pQue->pData[pQue->iHead+1] == 0 );
+ pQue->pData[pQue->iHead+1] = iObj;
+ }
+ else if ( pReason[0] != 0 ) // circuit reason
+ {
+ Cbs3_QuePush( pQue, pReason[0] );
+ if ( pReason[1] )
+ Cbs3_QuePush( pQue, pReason[1] );
+ }
+ else // clause reason
+ {
+ int i, * pLits, nLits = Cbs3_ClauseSize( p, pReason[1] );
+ assert( pReason[1] );
+ Cbs3_QueGrow( pQue, nLits );
+ pLits = Cbs3_ClauseLits( p, pReason[1] );
+ assert( iObj == Abc_Lit2Var(pLits[0]) );
+ for ( i = 1; i < nLits; i++ )
+ Cbs3_QuePush( pQue, Abc_Lit2Var(pLits[i]) );
+ }
+ }
+ assert( pQue->pData[pQue->iHead] == 0 );
+ assert( pQue->pData[pQue->iHead+1] != 0 );
+ pQue->iTail = k;
+ // clear the marks
+ Vec_IntForEachEntry( p->vTemp, iObj, i )
+ Cbs3_VarSetMark0(p, iObj, 0);
+ return Cbs3_QueFinish( p, Level );
+}
+static inline int Cbs3_ManAnalyze( Cbs3_Man_t * p, int Level, int iVar, int iFan0, int iFan1 )
+{
+ Cbs3_Que_t * pQue = &(p->pClauses);
+ assert( Cbs3_VarIsAssigned(p, iVar) );
+ assert( Cbs3_QueIsEmpty( pQue ) );
+ Cbs3_QuePush( pQue, 0 );
+ Cbs3_QuePush( pQue, 0 );
+ if ( iFan0 ) // circuit conflict
+ {
+ assert( Cbs3_VarIsAssigned(p, iFan0) );
+ assert( iFan1 == 0 || Cbs3_VarIsAssigned(p, iFan1) );
+ Cbs3_QuePush( pQue, iVar );
+ Cbs3_QuePush( pQue, iFan0 );
+ if ( iFan1 )
+ Cbs3_QuePush( pQue, iFan1 );
+ }
+ else // clause conflict
+ {
+ int i, * pLits, nLits = Cbs3_ClauseSize( p, iFan1 );
+ assert( iFan1 );
+ Cbs3_QueGrow( pQue, nLits );
+ pLits = Cbs3_ClauseLits( p, iFan1 );
+ assert( iVar == Abc_Lit2Var(pLits[0]) );
+ assert( Cbs3_VarValue(p, iVar) == Abc_LitIsCompl(pLits[0]) );
+ for ( i = 0; i < nLits; i++ )
+ Cbs3_QuePush( pQue, Abc_Lit2Var(pLits[i]) );
+ }
+ return Cbs3_ManDeriveReason( p, Level );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Propagate one assignment.]
+
+ Description [Returns handle of the conflict clause, if conflict occurs.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cbs3_ManPropagateClauses( Cbs3_Man_t * p, int Level, int Lit )
+{
+ int i, Value, Cur, LitF = Abc_LitNot(Lit);
+ int * pPrev = Vec_IntEntryP( &p->vWatches, Lit );
+ //for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev )
+ for ( Cur = *pPrev; Cur; Cur = *pPrev )
+ {
+ int nLits = Cbs3_ClauseSize( p, Cur );
+ int * pLits = Cbs3_ClauseLits( p, Cur );
+ p->nPropCalls[1]++;
+//printf( " Watching literal %c%d on level %d.\n", Abc_LitIsCompl(Lit) ? '-':'+', Abc_Lit2Var(Lit), Level );
+ // make sure the false literal is in the second literal of the clause
+ //if ( pCur->pLits[0] == LitF )
+ if ( pLits[0] == LitF )
+ {
+ //pCur->pLits[0] = pCur->pLits[1];
+ pLits[0] = pLits[1];
+ //pCur->pLits[1] = LitF;
+ pLits[1] = LitF;
+ //pTemp = pCur->pNext0;
+ //pCur->pNext0 = pCur->pNext1;
+ //pCur->pNext1 = pTemp;
+ ABC_SWAP( int, pLits[nLits], pLits[nLits+1] );
+ }
+ //assert( pCur->pLits[1] == LitF );
+ assert( pLits[1] == LitF );
+
+ // if the first literal is true, the clause is satisfied
+ //if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] )
+ if ( Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])) == !Abc_LitIsCompl(pLits[0]) )
+ {
+ //ppPrev = &pCur->pNext1;
+ pPrev = Cbs3_ClauseNext1p(p, Cur);
+ continue;
+ }
+
+ // look for a new literal to watch
+ for ( i = 2; i < nLits; i++ )
+ {
+ // skip the case when the literal is false
+ //if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] )
+ if ( Cbs3_VarValue(p, Abc_Lit2Var(pLits[i])) == Abc_LitIsCompl(pLits[i]) )
+ continue;
+ // the literal is either true or unassigned - watch it
+ //pCur->pLits[1] = pCur->pLits[i];
+ //pCur->pLits[i] = LitF;
+ pLits[1] = pLits[i];
+ pLits[i] = LitF;
+ // remove this clause from the watch list of Lit
+ //*ppPrev = pCur->pNext1;
+ *pPrev = *Cbs3_ClauseNext1p(p, Cur);
+ // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1])
+ //Intb_ManWatchClause( p, pCur, pCur->pLits[1] );
+ Cbs3_ManWatchClause( p, Cur, Cbs3_ClauseLit(p, Cur, 1) );
+ break;
+ }
+ if ( i < nLits ) // found new watch
+ continue;
+
+ // clause is unit - enqueue new implication
+ //if ( Inta_ManEnqueue(p, pCur->pLits[0], pCur) )
+ //{
+ // ppPrev = &pCur->pNext1;
+ // continue;
+ //}
+
+ // clause is unit - enqueue new implication
+ Value = Cbs3_VarValue(p, Abc_Lit2Var(pLits[0]));
+ if ( Value >= 2 ) // unassigned
+ {
+ Cbs3_ManAssign( p, pLits[0], Level, 0, Cur );
+ pPrev = Cbs3_ClauseNext1p(p, Cur);
+ continue;
+ }
+
+ // conflict detected - return the conflict clause
+ //return pCur;
+ if ( Value == Abc_LitIsCompl(pLits[0]) )
+ {
+ p->nClauseConf++;
+ return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(pLits[0]), 0, Cur );
+ }
+ }
+ return 0;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Performs resolution of two clauses.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cbs3_ManResolve( Cbs3_Man_t * p, int Level, int hClause0, int hClause1 )
+{
+ Cbs3_Que_t * pQue = &(p->pClauses);
+ int i, iObj, LevelMax = -1, LevelCur;
+ assert( pQue->pData[hClause0+1] != 0 );
+ assert( pQue->pData[hClause0+1] == pQue->pData[hClause1+1] );
+ //Cbs3_ClauseForEachEntry1( p, hClause0, iObj, i )
+ // assert( !Cbs3_VarMark0(p, iObj) );
+ //Cbs3_ClauseForEachEntry1( p, hClause1, iObj, i )
+ // assert( !Cbs3_VarMark0(p, iObj) );
+ assert( Cbs3_QueIsEmpty( pQue ) );
+ Cbs3_QuePush( pQue, 0 );
+ Cbs3_QuePush( pQue, 0 );
+// for ( i = hClause0 + 1; (iObj = pQue->pData[i]); i++ )
+ Cbs3_ClauseForEachEntry1( p, hClause0, iObj, i )
+ {
+ if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again
+ continue;
+ //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 )
+ // Vec_IntPush( &p->vActStore, iObj );
+ //Vec_IntAddToEntry( &p->vActivity, iObj, 1 );
+ // assigned - seen first time
+ Cbs3_VarSetMark0(p, iObj, 1);
+ Cbs3_ActBumpVar(p, iObj);
+ Cbs3_QuePush( pQue, iObj );
+ LevelCur = Cbs3_VarDecLevel( p, iObj );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+// for ( i = hClause1 + 1; (iObj = pQue->pData[i]); i++ )
+ Cbs3_ClauseForEachEntry1( p, hClause1, iObj, i )
+ {
+ if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again
+ continue;
+ //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 )
+ // Vec_IntPush( &p->vActStore, iObj );
+ //Vec_IntAddToEntry( &p->vActivity, iObj, 1 );
+ // assigned - seen first time
+ Cbs3_VarSetMark0(p, iObj, 1);
+ Cbs3_ActBumpVar(p, iObj);
+ Cbs3_QuePush( pQue, iObj );
+ LevelCur = Cbs3_VarDecLevel( p, iObj );
+ if ( LevelMax < LevelCur )
+ LevelMax = LevelCur;
+ }
+ for ( i = pQue->iHead + 2; i < pQue->iTail; i++ )
+ Cbs3_VarSetMark0(p, pQue->pData[i], 0);
+ return Cbs3_ManDeriveReason( p, LevelMax );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Propagates a variable.]
+
+ Description [Returns clause handle if conflict; 0 if no conflict.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cbs3_ManUpdateJFrontier( Cbs3_Man_t * p )
+{
+ //abctime clk = Abc_Clock();
+ int iVar, iLit, i, k = p->pJust.iTail;
+ Cbs3_QueGrow( &p->pJust, Cbs3_QueSize(&p->pJust) + Cbs3_QueSize(&p->pProp) );
+ Cbs3_QueForEachEntry( p->pJust, iVar, i )
+ if ( Cbs3_VarIsJust(p, iVar) )
+ p->pJust.pData[k++] = iVar;
+ Cbs3_QueForEachEntry( p->pProp, iLit, i )
+ if ( Cbs3_VarIsJust(p, Abc_Lit2Var(iLit)) )
+ p->pJust.pData[k++] = Abc_Lit2Var(iLit);
+ p->pJust.iHead = p->pJust.iTail;
+ p->pJust.iTail = k;
+ //p->timeJFront += Abc_Clock() - clk;
+}
+int Cbs3_ManPropagateNew( Cbs3_Man_t * p, int Level )
+{
+ int i, k, iLit, hClause, nLits, * pLits;
+ p->nPropCalls[0]++;
+ Cbs3_QueForEachEntry( p->pProp, iLit, i )
+ {
+ if ( (hClause = Cbs3_ManPropagateClauses(p, Level, iLit)) )
+ return hClause;
+ p->nPropCalls[2]++;
+ nLits = Vec_IntSize(Vec_WecEntry(&p->vImps, iLit));
+ pLits = Vec_IntArray(Vec_WecEntry(&p->vImps, iLit));
+ for ( k = 0; k < nLits; k += 2 )
+ {
+ int Value0 = Cbs3_VarValue(p, Abc_Lit2Var(pLits[k]));
+ int Value1 = pLits[k+1] ? Cbs3_VarValue(p, Abc_Lit2Var(pLits[k+1])) : -1;
+ if ( Value1 == -1 || Value1 == Abc_LitIsCompl(pLits[k+1]) ) // pLits[k+1] is false
+ {
+ if ( Value0 >= 2 ) // pLits[k] is unassigned
+ Cbs3_ManAssign( p, pLits[k], Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k+1]) );
+ else if ( Value0 == Abc_LitIsCompl(pLits[k]) ) // pLits[k] is false
+ return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]), Abc_Lit2Var(pLits[k+1]) );
+ }
+ if ( Value1 != -1 && Value0 == Abc_LitIsCompl(pLits[k]) ) // pLits[k] is false
+ {
+ if ( Value1 >= 2 ) // pLits[k+1] is unassigned
+ Cbs3_ManAssign( p, pLits[k+1], Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]) );
+ else if ( Value1 == Abc_LitIsCompl(pLits[k+1]) ) // pLits[k+1] is false
+ return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]), Abc_Lit2Var(pLits[k+1]) );
+ }
+ }
+ }
+ Cbs3_ManUpdateJFrontier( p );
+ // finalize propagation queue
+ p->pProp.iHead = p->pProp.iTail;
+ return 0;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Solve the problem recursively.]
+
+ Description [Returns learnt clause if unsat, NULL if sat or undecided.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Cbs3_ManSolve2_rec( Cbs3_Man_t * p, int Level )
+{
+ Cbs3_Que_t * pQue = &(p->pClauses);
+ int iPropHead, iJustHead, iJustTail;
+ int hClause, hLearn0, hLearn1, iVar, iDecLit;
+ int nRef0, nRef1;
+ // propagate assignments
+ assert( !Cbs3_QueIsEmpty(&p->pProp) );
+ //if ( (hClause = Cbs3_ManPropagate( p, Level )) )
+ if ( (hClause = Cbs3_ManPropagateNew( p, Level )) )
+ return hClause;
+ // check for satisfying assignment
+ assert( Cbs3_QueIsEmpty(&p->pProp) );
+ if ( Cbs3_QueIsEmpty(&p->pJust) )
+ return 0;
+ // quit using resource limits
+ p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead );
+ if ( Cbs3_ManCheckLimits( p ) )
+ return 0;
+ // remember the state before branching
+ iPropHead = p->pProp.iHead;
+ iJustHead = p->pJust.iHead;
+ iJustTail = p->pJust.iTail;
+ // find the decision variable
+ p->nDecs++;
+ iVar = Cbs3_ManDecide( p );
+ assert( !Cbs3_VarIsPi(p, iVar) );
+ assert( Cbs3_VarIsJust(p, iVar) );
+ // chose decision variable using fanout count
+ nRef0 = Vec_IntEntry(&p->vRef, Abc_Lit2Var(Cbs3_VarLit0(p, iVar)));
+ nRef1 = Vec_IntEntry(&p->vRef, Abc_Lit2Var(Cbs3_VarLit1(p, iVar)));
+// if ( nRef0 >= nRef1 || (nRef0 == nRef1) && (Abc_Random(0) & 1) )
+ if ( nRef0 >= nRef1 )
+ iDecLit = Abc_LitNot(Cbs3_VarLit0(p, iVar));
+ else
+ iDecLit = Abc_LitNot(Cbs3_VarLit1(p, iVar));
+ // decide on first fanin
+ Cbs3_ManAssign( p, iDecLit, Level+1, 0, 0 );
+ if ( !(hLearn0 = Cbs3_ManSolve2_rec( p, Level+1 )) )
+ return 0;
+ if ( pQue->pData[hLearn0+1] != Abc_Lit2Var(iDecLit) )
+ return hLearn0;
+ Cbs3_ManCancelUntil( p, iPropHead );
+ Cbs3_QueRestore( &p->pJust, iJustHead, iJustTail );
+ // decide on second fanin
+ Cbs3_ManAssign( p, Abc_LitNot(iDecLit), Level+1, 0, 0 );
+ if ( !(hLearn1 = Cbs3_ManSolve2_rec( p, Level+1 )) )
+ return 0;
+ if ( pQue->pData[hLearn1+1] != Abc_Lit2Var(iDecLit) )
+ return hLearn1;
+ hClause = Cbs3_ManResolve( p, Level, hLearn0, hLearn1 );
+ p->Pars.nBTThis++;
+ return hClause;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Looking for a satisfying assignment of the node.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cbs3_ManSolveInt( Cbs3_Man_t * p, int iLit )
+{
+ int RetValue = 0;
+ assert( !p->pProp.iHead && !p->pProp.iTail );
+ assert( !p->pJust.iHead && !p->pJust.iTail );
+ p->Pars.nBTThis = p->Pars.nJustThis = 0;
+ Cbs3_ManAssign( p, iLit, 0, 0, 0 );
+ if ( !Cbs3_ManSolve2_rec(p, 0) && !Cbs3_ManCheckLimits(p) )
+ Cbs3_ManSaveModel( p, p->vModel );
+ else
+ RetValue = 1;
+ Cbs3_ManCancelUntil( p, 0 );
+ p->pJust.iHead = p->pJust.iTail = 0;
+ p->Pars.nBTTotal += p->Pars.nBTThis;
+ p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis );
+ if ( Cbs3_ManCheckLimits( p ) )
+ RetValue = -1;
+ return RetValue;
+}
+int Cbs3_ManSolve( Cbs3_Man_t * p, int iLit, int nRestarts )
+{
+ int i, RetValue = -1;
+ assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 );
+ for ( i = 0; i < nRestarts; i++ )
+ if ( (RetValue = Cbs3_ManSolveInt(p, iLit)) != -1 )
+ break;
+ Cbs3_ManCleanWatch( p );
+ p->pClauses.iHead = p->pClauses.iTail = 1;
+ return RetValue;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Prints statistics of the manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Cbs3_ManSatPrintStats( Cbs3_Man_t * p )
+{
+ printf( "CO = %8d ", Gia_ManCoNum(p->pAig) );
+ printf( "AND = %8d ", Gia_ManAndNum(p->pAig) );
+ printf( "Conf = %6d ", p->Pars.nBTLimit );
+ printf( "Restart = %2d ", p->Pars.nRestLimit );
+ printf( "JustMax = %5d ", p->Pars.nJustLimit );
+ printf( "\n" );
+ printf( "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ",
+ p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 );
+ ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal );
+ printf( "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ",
+ p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 );
+ ABC_PRTP( "Time", p->timeSatSat, p->timeTotal );
+ printf( "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ",
+ p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 );
+ ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal );
+ ABC_PRT( "Total time", p->timeTotal );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Cbs3_ManAddVar( Cbs3_Man_t * p, int iGiaObj )
+{
+ assert( Vec_IntSize(&p->vMap) == p->nVars );
+ Vec_IntPush( &p->vMap, iGiaObj );
+ Vec_IntPush( &p->vRef, Gia_ObjRefNumId(p->pAig, iGiaObj) );
+ Vec_IntPushTwo( &p->vFans, 0, 0 );
+ Vec_WecPushLevel(&p->vImps);
+ Vec_WecPushLevel(&p->vImps);
+ return Abc_Var2Lit( p->nVars++, 0 );
+}
+static inline void Cbs3_ManAddConstr( Cbs3_Man_t * p, int x, int x0, int x1 )
+{
+ Vec_WecPushTwo( &p->vImps, x , x0, 0 ); // ~x + x0
+ Vec_WecPushTwo( &p->vImps, x , x1, 0 ); // ~x + x1
+ Vec_WecPushTwo( &p->vImps, 1^x0, 1^x , 0 ); // ~x + x0
+ Vec_WecPushTwo( &p->vImps, 1^x1, 1^x , 0 ); // ~x + x1
+ Vec_WecPushTwo( &p->vImps, 1^x , 1^x0, 1^x1 ); // x + ~x0 + ~x1
+ Vec_WecPushTwo( &p->vImps, x0, x , 1^x1 ); // x + ~x0 + ~x1
+ Vec_WecPushTwo( &p->vImps, x1, x , 1^x0 ); // x + ~x0 + ~x1
+}
+static inline void Cbs3_ManAddAnd( Cbs3_Man_t * p, int x, int x0, int x1 )
+{
+ assert( x > 0 && x0 > 0 && x1 > 0 );
+ Vec_IntWriteEntry( &p->vFans, x, x0 );
+ Vec_IntWriteEntry( &p->vFans, x+1, x1 );
+ Cbs3_ManAddConstr( p, x, x0, x1 );
+}
+static inline int Cbs3_ManToSolver1_rec( Cbs3_Man_t * pSol, Gia_Man_t * p, int iObj, int Depth )
+{
+ Gia_Obj_t * pObj = Gia_ManObj(p, iObj); int Lit0, Lit1;
+ if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) )
+ return pObj->Value;
+ pObj->Value = Cbs3_ManAddVar( pSol, iObj );
+ if ( Gia_ObjIsCi(pObj) || Depth == 0 )
+ return pObj->Value;
+ assert( Gia_ObjIsAnd(pObj) );
+ Lit0 = Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId0(pObj, iObj), Depth - Gia_ObjFaninC0(pObj) );
+ Lit1 = Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId1(pObj, iObj), Depth - Gia_ObjFaninC1(pObj) );
+ Cbs3_ManAddAnd( pSol, pObj->Value, Lit0 ^ Gia_ObjFaninC0(pObj), Lit1 ^ Gia_ObjFaninC1(pObj) );
+ return pObj->Value;
+}
+static inline int Cbs3_ManToSolver1( Cbs3_Man_t * pSol, Gia_Man_t * p, Gia_Obj_t * pRoot, int nRestarts, int Depth )
+{
+ //abctime clk = Abc_Clock();
+ assert( Gia_ObjIsCo(pRoot) );
+ Cbs3_ManReset( pSol );
+ Gia_ManIncrementTravId( p );
+ Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId0p(p, pRoot), Depth );
+ Cbs3_ManGrow( pSol );
+ Cbs3_ActReset( pSol );
+ //pSol->timeSatLoad += Abc_Clock() - clk;
+ return Cbs3_ManSolve( pSol, Gia_ObjFanin0Copy(pRoot), nRestarts );
+}
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Cbs3_ManPrepare( Cbs3_Man_t * p )
+{
+ int x, x0, x1;
+ Vec_WecInit( &p->vImps, Abc_Var2Lit(p->nVars, 0) );
+ Vec_IntForEachEntryDoubleStart( &p->vFans, x0, x1, x, 2 )
+ if ( x0 ) Cbs3_ManAddConstr( p, x, x0, x1 );
+}
+static inline int Cbs3_ManAddNode( Cbs3_Man_t * p, int iGiaObj, int iLit0, int iLit1 )
+{
+ assert( Vec_IntSize(&p->vMap) == p->nVars );
+ Vec_IntPush( &p->vMap, iGiaObj );
+ Vec_IntPush( &p->vRef, Gia_ObjRefNumId(p->pAig, iGiaObj) );
+ Vec_IntPushTwo( &p->vFans, iLit0, iLit1 );
+ return Abc_Var2Lit( p->nVars++, 0 );
+}
+static inline int Cbs3_ManToSolver2_rec( Cbs3_Man_t * pSol, Gia_Man_t * p, int iObj, int Depth )
+{
+ Gia_Obj_t * pObj = Gia_ManObj(p, iObj); int Lit0, Lit1;
+ if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) )
+ return pObj->Value;
+ if ( Gia_ObjIsCi(pObj) || Depth == 0 )
+ return pObj->Value = Cbs3_ManAddNode(pSol, iObj, 0, 0);
+ assert( Gia_ObjIsAnd(pObj) );
+ Lit0 = Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId0(pObj, iObj), Depth - Gia_ObjFaninC0(pObj) );
+ Lit1 = Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId1(pObj, iObj), Depth - Gia_ObjFaninC1(pObj) );
+ return pObj->Value = Cbs3_ManAddNode(pSol, iObj, Lit0 ^ Gia_ObjFaninC0(pObj), Lit1 ^ Gia_ObjFaninC1(pObj));
+}
+static inline int Cbs3_ManToSolver2( Cbs3_Man_t * pSol, Gia_Man_t * p, Gia_Obj_t * pRoot, int nRestarts, int Depth )
+{
+ //abctime clk = Abc_Clock();
+ assert( Gia_ObjIsCo(pRoot) );
+ Cbs3_ManReset( pSol );
+ Gia_ManIncrementTravId( p );
+ Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId0p(p, pRoot), Depth );
+ Cbs3_ManGrow( pSol );
+ Cbs3_ManPrepare( pSol );
+ Cbs3_ActReset( pSol );
+ //pSol->timeSatLoad += Abc_Clock() - clk;
+ return Cbs3_ManSolve( pSol, Gia_ObjFanin0Copy(pRoot), nRestarts );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Procedure to test the new SAT solver.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Vec_Int_t * Cbs3_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, int nRestarts, Vec_Str_t ** pvStatus, int fVerbose )
+{
+ extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out );
+ Cbs3_Man_t * p;
+ Vec_Int_t * vCex, * vVisit, * vCexStore;
+ Vec_Str_t * vStatus;
+ Gia_Obj_t * pRoot;
+ int i, status; // 1 = unsat, 0 = sat, -1 = undec
+ abctime clk, clkTotal = Abc_Clock();
+ //assert( Gia_ManRegNum(pAig) == 0 );
+ Gia_ManCreateRefs( pAig );
+ //Gia_ManLevelNum( pAig );
+ // create logic network
+ p = Cbs3_ManAlloc( pAig );
+ p->Pars.nBTLimit = nConfs;
+ p->Pars.nRestLimit = nRestarts;
+ // create resulting data-structures
+ vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) );
+ vCexStore = Vec_IntAlloc( 10000 );
+ vVisit = Vec_IntAlloc( 100 );
+ vCex = Cbs3_ReadModel( p );
+ // solve for each output
+ Gia_ManForEachCo( pAig, pRoot, i )
+ {
+ if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) )
+ {
+ Vec_IntClear( vCex );
+ Vec_StrPush( vStatus, (char)(!Gia_ObjFaninC0(pRoot)) );
+ if ( Gia_ObjFaninC0(pRoot) ) // const1
+ Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example
+ continue;
+ }
+ clk = Abc_Clock();
+ status = Cbs3_ManToSolver2( p, pAig, pRoot, p->Pars.nRestLimit, 10000 );
+ Vec_StrPush( vStatus, (char)status );
+ if ( status == -1 )
+ {
+ p->nSatUndec++;
+ p->nConfUndec += p->Pars.nBTThis;
+ Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout
+ p->timeSatUndec += Abc_Clock() - clk;
+ continue;
+ }
+ if ( status == 1 )
+ {
+ p->nSatUnsat++;
+ p->nConfUnsat += p->Pars.nBTThis;
+ p->timeSatUnsat += Abc_Clock() - clk;
+ continue;
+ }
+ p->nSatSat++;
+ p->nConfSat += p->Pars.nBTThis;
+ //Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit );
+ Cec_ManSatAddToStore( vCexStore, vCex, i );
+ p->timeSatSat += Abc_Clock() - clk;
+ }
+ Vec_IntFree( vVisit );
+ p->nSatTotal = Gia_ManPoNum(pAig);
+ p->timeTotal = Abc_Clock() - clkTotal;
+ if ( fVerbose )
+ Cbs3_ManSatPrintStats( p );
+ if ( fVerbose )
+ {
+ printf( "Prop1 = %d. Prop2 = %d. Prop3 = %d. ClaConf = %d. FailJ = %d. FailC = %d. ", p->nPropCalls[0], p->nPropCalls[1], p->nPropCalls[2], p->nClauseConf, p->nFails[0], p->nFails[1] );
+ printf( "Mem usage %.2f MB.\n", 1.0*Cbs3_ManMemory(p)/(1<<20) );
+ //Abc_PrintTime( 1, "JFront", p->timeJFront );
+ //Abc_PrintTime( 1, "Loading", p->timeSatLoad );
+ //printf( "Decisions = %d.\n", p->nDecs );
+ }
+ Cbs3_ManStop( p );
+ *pvStatus = vStatus;
+ return vCexStore;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+