blob: 247c3dad5a2f1460987f7f8bd1e3e0b88a39def7 [file] [log] [blame]
/**CFile****************************************************************
FileName [giaQbf.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Scalable AIG package.]
Synopsis [QBF solver.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - October 18, 2014.]
Revision [$Id: giaQbf.c,v 1.00 2014/10/18 00:00:00 alanmi Exp $]
***********************************************************************/
#include "gia.h"
#include "sat/cnf/cnf.h"
#include "sat/bsat/satStore.h"
#include "misc/extra/extra.h"
#include "sat/glucose/AbcGlucose.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Qbf_Man_t_ Qbf_Man_t;
struct Qbf_Man_t_
{
Gia_Man_t * pGia; // original miter
int nPars; // parameter variables
int nVars; // functional variables
int fVerbose; // verbose flag
// internal variables
int iParVarBeg; // SAT var ID of the first par variable in the ver solver
sat_solver * pSatVer; // verification instance
sat_solver * pSatSyn; // synthesis instance
bmcg_sat_solver*pSatSynG; // synthesis instance
Vec_Int_t * vValues; // variable values
Vec_Int_t * vParMap; // parameter mapping
Vec_Int_t * vLits; // literals for the SAT solver
abctime clkStart; // global timeout
abctime clkSat; // SAT solver time
};
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Generating QBF miter to solve the induction problem.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_GenCollectFlopIndexes( char * pStr, int nLutNum, int nLutSize, int nFlops )
{
int nDups;
char * pTemp;
Vec_Int_t * vFlops;
assert( nLutSize * nLutNum <= nFlops );
if ( pStr == NULL )
return Vec_IntStartNatural( nLutNum * nLutSize );
vFlops = Vec_IntAlloc( nLutNum * nLutSize );
pTemp = strtok( pStr, ", " );
while ( pTemp )
{
int iFlop = atoi(pTemp);
if ( iFlop >= nFlops )
{
printf( "Flop index (%d) exceeds the number of flops (%d).\n", iFlop, nFlops );
break;
}
Vec_IntPush( vFlops, iFlop );
pTemp = strtok( NULL, ", " );
}
if ( Vec_IntSize(vFlops) != nLutNum * nLutSize )
{
printf( "Gia_GenCollectFlopIndexes: Expecting %d flop indexes (instead of %d).\n", nLutNum * nLutSize, Vec_IntSize(vFlops) );
Vec_IntFree( vFlops );
return NULL;
}
nDups = Vec_IntCountDuplicates(vFlops);
if ( nDups )
{
printf( "Gia_GenCollectFlopIndexes: There are %d duplicated flops in the list.\n", nDups );
Vec_IntFree( vFlops );
return NULL;
}
return vFlops;
}
int Gia_GenCreateMux_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift )
{
int iLit0, iLit1;
if ( nCtrl == 0 )
return Vec_IntEntry( vData, Shift );
iLit0 = Gia_GenCreateMux_rec( pNew, pCtrl, nCtrl-1, vData, Shift );
iLit1 = Gia_GenCreateMux_rec( pNew, pCtrl, nCtrl-1, vData, Shift + (1<<(nCtrl-1)) );
return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 );
}
Vec_Int_t * Gia_GenCreateMuxes( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vFlops, int nLutNum, int nLutSize, Vec_Int_t * vParLits, int fUseRi )
{
Vec_Int_t * vLits = Vec_IntAlloc( nLutNum );
int i, k, iMux, iFlop, pCtrl[16];
// add MUXes for each group of flops
assert( Vec_IntSize(vFlops) == nLutNum * nLutSize );
for ( i = 0; i < nLutNum; i++ )
{
for ( k = 0; k < nLutSize; k++ )
{
iFlop = Vec_IntEntry(vFlops, i * nLutSize + k);
assert( iFlop >= 0 && iFlop < Gia_ManRegNum(p) );
if ( fUseRi )
pCtrl[k] = Gia_ManRi(p, iFlop)->Value;
else
pCtrl[k] = Gia_ManRo(p, iFlop)->Value;
}
iMux = Gia_GenCreateMux_rec( pNew, pCtrl, nLutSize, vParLits, i * (1 << nLutSize) );
Vec_IntPush( vLits, iMux );
}
return vLits;
}
Gia_Man_t * Gia_GenQbfMiter( Gia_Man_t * p, int nFrames, int nLutNum, int nLutSize, char * pStr, int fVerbose )
{
Gia_Obj_t * pObj;
Gia_Man_t * pTemp, * pNew;
int i, iMiter, nPars = nLutNum * (1 << nLutSize);
Vec_Int_t * vLits0, * vLits1, * vParLits;
Vec_Int_t * vFlops = Gia_GenCollectFlopIndexes( pStr, nLutNum, nLutSize, Gia_ManRegNum(p) );
// collect parameter literals (data vars)
vParLits = Vec_IntAlloc( nPars );
for ( i = 0; i < nPars; i++ )
Vec_IntPush( vParLits, i ? Abc_Var2Lit(i+1, 0) : 1 );
// create new manager
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
Gia_ManHashAlloc( pNew );
Gia_ManConst0(p)->Value = 0;
for ( i = 0; i < nPars; i++ )
Gia_ManAppendCi( pNew );
Gia_ManForEachCi( p, pObj, i )
pObj->Value = Gia_ManAppendCi( pNew );
Gia_ManForEachAnd( p, pObj, i )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
Gia_ManForEachCo( p, pObj, i )
pObj->Value = Gia_ObjFanin0Copy(pObj);
vLits0 = Gia_GenCreateMuxes( p, pNew, vFlops, nLutNum, nLutSize, vParLits, 0 );
vLits1 = Gia_GenCreateMuxes( p, pNew, vFlops, nLutNum, nLutSize, vParLits, 1 );
// create miter output
iMiter = Gia_ManHashAnd( pNew, Vec_IntEntry(vLits0, 0), Abc_LitNot(Vec_IntEntry(vLits1, 0)) );
iMiter = Gia_ManHashAnd( pNew, Abc_LitNot(iMiter), Abc_Var2Lit(1, 0) );
Gia_ManAppendCo( pNew, iMiter );
// cleanup
Vec_IntFree( vLits0 );
Vec_IntFree( vLits1 );
Vec_IntFree( vFlops );
Vec_IntFree( vParLits );
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManStop( pTemp );
return pNew;
}
/**Function*************************************************************
Synopsis [Naive way to enumerate SAT assignments.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManSatEnum( Gia_Man_t * pGia, int nConfLimit, int nTimeOut, int fVerbose )
{
Cnf_Dat_t * pCnf;
sat_solver * pSat;
Vec_Int_t * vLits;
int i, iLit, iParVarBeg, Iter;
int nSolutions = 0, RetValue = 0;
abctime clkStart = Abc_Clock();
pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 );
pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
iParVarBeg = pCnf->nVars - Gia_ManPiNum(pGia);// - 1;
Cnf_DataFree( pCnf );
// iterate through the SAT assignment
vLits = Vec_IntAlloc( Gia_ManPiNum(pGia) );
for ( Iter = 1 ; ; Iter++ )
{
int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 );
if ( status == l_False ) { RetValue = 1; break; }
if ( status == l_Undef ) { RetValue = 0; break; }
nSolutions++;
// extract SAT assignment
Vec_IntClear( vLits );
for ( i = 0; i < Gia_ManPiNum(pGia); i++ )
Vec_IntPush( vLits, Abc_Var2Lit(iParVarBeg+i, sat_solver_var_value(pSat, iParVarBeg+i)) );
if ( fVerbose )
{
printf( "%5d : ", Iter );
Vec_IntForEachEntry( vLits, iLit, i )
printf( "%d", !Abc_LitIsCompl(iLit) );
printf( "\n" );
}
// add clause
if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) )
{ RetValue = 1; break; }
if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; }
}
sat_solver_delete( pSat );
Vec_IntFree( vLits );
if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut )
printf( "Enumerated %d assignments when timeout (%d sec) was reached. ", nSolutions, nTimeOut );
else if ( nConfLimit && !RetValue )
printf( "Enumerated %d assignments when conflict limit (%d) was reached. ", nSolutions, nConfLimit );
else
printf( "Enumerated the complete set of %d assignments. ", nSolutions );
Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
return RetValue;
}
/**Function*************************************************************
Synopsis [Dumps the original problem in QDIMACS format.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_QbfDumpFile( Gia_Man_t * pGia, int nPars )
{
// original problem: \exists p \forall x \exists y. M(p,x,y)
// negated problem: \forall p \exists x \exists y. !M(p,x,y)
Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 );
Vec_Int_t * vVarMap, * vForAlls, * vExists;
Gia_Obj_t * pObj;
char * pFileName;
int i, Entry;
// create var map
vVarMap = Vec_IntStart( pCnf->nVars );
Gia_ManForEachCi( pGia, pObj, i )
if ( i < nPars )
Vec_IntWriteEntry( vVarMap, pCnf->pVarNums[Gia_ManCiIdToId(pGia, i)], 1 );
// create various maps
vForAlls = Vec_IntAlloc( nPars );
vExists = Vec_IntAlloc( Gia_ManCiNum(pGia) - nPars );
Vec_IntForEachEntry( vVarMap, Entry, i )
if ( Entry )
Vec_IntPush( vForAlls, i );
else
Vec_IntPush( vExists, i );
// generate CNF
pFileName = Extra_FileNameGenericAppend( pGia->pSpec, ".qdimacs" );
Cnf_DataWriteIntoFile( pCnf, pFileName, 0, vForAlls, vExists );
Cnf_DataFree( pCnf );
Vec_IntFree( vForAlls );
Vec_IntFree( vExists );
Vec_IntFree( vVarMap );
printf( "The 2QBF formula was written into file \"%s\".\n", pFileName );
}
/**Function*************************************************************
Synopsis [Generate one SAT assignment of the problem.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Qbf_Man_t * Gia_QbfAlloc( Gia_Man_t * pGia, int nPars, int fGlucose, int fVerbose )
{
Qbf_Man_t * p;
Cnf_Dat_t * pCnf;
Gia_ObjFlipFaninC0( Gia_ManPo(pGia, 0) );
pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 );
Gia_ObjFlipFaninC0( Gia_ManPo(pGia, 0) );
p = ABC_CALLOC( Qbf_Man_t, 1 );
p->clkStart = Abc_Clock();
p->pGia = pGia;
p->nPars = nPars;
p->nVars = Gia_ManPiNum(pGia) - nPars;
p->fVerbose = fVerbose;
p->iParVarBeg = pCnf->nVars - Gia_ManPiNum(pGia);// - 1;
p->pSatVer = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
p->pSatSyn = sat_solver_new();
p->pSatSynG = fGlucose ? bmcg_sat_solver_start() : NULL;
p->vValues = Vec_IntAlloc( Gia_ManPiNum(pGia) );
p->vParMap = Vec_IntStartFull( nPars );
p->vLits = Vec_IntAlloc( nPars );
sat_solver_setnvars( p->pSatSyn, nPars );
if ( p->pSatSynG ) bmcg_sat_solver_set_nvars( p->pSatSynG, nPars );
Cnf_DataFree( pCnf );
return p;
}
void Gia_QbfFree( Qbf_Man_t * p )
{
sat_solver_delete( p->pSatVer );
sat_solver_delete( p->pSatSyn );
if ( p->pSatSynG ) bmcg_sat_solver_stop( p->pSatSynG );
Vec_IntFree( p->vLits );
Vec_IntFree( p->vValues );
Vec_IntFree( p->vParMap );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Create and add one cofactor.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_QbfQuantifyOne( Gia_Man_t * p, int iVar, int fAndAll, int fOrAll )
{
Gia_Man_t * pNew, * pTemp;
Gia_Obj_t * pObj;
Vec_Int_t * vCofs;
int i, c;
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
Gia_ManHashAlloc( pNew );
Gia_ManFillValue( p );
Gia_ManConst0(p)->Value = 0;
Gia_ManForEachPi( p, pObj, i )
pObj->Value = Gia_ManAppendCi(pNew);
// compute cofactors
vCofs = Vec_IntAlloc( 2 * Gia_ManPoNum(p) );
for ( c = 0; c < 2; c++ )
{
Gia_ManPi(p, iVar)->Value = c;
Gia_ManForEachAnd( p, pObj, i )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
Gia_ManForEachPo( p, pObj, i )
Vec_IntPush( vCofs, Gia_ObjFanin0Copy(pObj) );
}
if ( fAndAll )
{
for ( i = 0; i < Gia_ManPoNum(p); i++ )
Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, Vec_IntEntry(vCofs, i), Vec_IntEntry(vCofs, Gia_ManPoNum(p)+i)) );
}
else if ( fOrAll )
{
for ( i = 0; i < Gia_ManPoNum(p); i++ )
Gia_ManAppendCo( pNew, Gia_ManHashOr(pNew, Vec_IntEntry(vCofs, i), Vec_IntEntry(vCofs, Gia_ManPoNum(p)+i)) );
}
else
{
Vec_IntForEachEntry( vCofs, c, i )
Gia_ManAppendCo( pNew, c );
}
Vec_IntFree( vCofs );
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManStop( pTemp );
return pNew;
}
Gia_Man_t * Gia_QbfQuantifyAll( Gia_Man_t * p, int nPars, int fAndAll, int fOrAll )
{
Gia_Man_t * pNew, * pTemp; int v;
pNew = Gia_ManDup( p );
for ( v = Gia_ManPiNum(p) - 1; v >= nPars; v-- )
{
pNew = Gia_QbfQuantifyOne( pTemp = pNew, v, fAndAll, fOrAll );
Gia_ManStop( pTemp );
}
return pNew;
}
/**Function*************************************************************
Synopsis [Create and add one cofactor.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Gia_Man_t * Gia_QbfCofactor( Gia_Man_t * p, int nPars, Vec_Int_t * vValues, Vec_Int_t * vParMap )
{
Gia_Man_t * pNew, * pTemp;
Gia_Obj_t * pObj; int i;
assert( Gia_ManPiNum(p) == nPars + Vec_IntSize(vValues) );
pNew = Gia_ManStart( Gia_ManObjNum(p) );
pNew->pName = Abc_UtilStrsav( p->pName );
Gia_ManHashAlloc( pNew );
Gia_ManConst0(p)->Value = 0;
Gia_ManForEachPi( p, pObj, i )
if ( i < nPars )
{
pObj->Value = Gia_ManAppendCi(pNew);
if ( Vec_IntEntry(vParMap, i) != -1 )
pObj->Value = Vec_IntEntry(vParMap, i);
}
else
pObj->Value = Vec_IntEntry(vValues, i - nPars);
Gia_ManForEachAnd( p, pObj, i )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
Gia_ManForEachCo( p, pObj, i )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManStop( pTemp );
assert( Gia_ManPiNum(pNew) == nPars );
return pNew;
}
/*
int Gia_QbfAddCofactor( Qbf_Man_t * p, Gia_Man_t * pCof )
{
Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCof, 8, 0, 1, 0, 0 );
int i, iFirstVar = sat_solver_nvars(p->pSatSyn) + pCnf->nVars - Gia_ManPiNum(pCof);// - 1;
pCnf->pMan = NULL;
Cnf_DataLift( pCnf, sat_solver_nvars(p->pSatSyn) );
for ( i = 0; i < pCnf->nClauses; i++ )
if ( !sat_solver_addclause( p->pSatSyn, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
{
Cnf_DataFree( pCnf );
return 0;
}
Cnf_DataFree( pCnf );
// add connection clauses
for ( i = 0; i < Gia_ManPiNum(p->pGia); i++ )
if ( !sat_solver_add_buffer( p->pSatSyn, i, iFirstVar+i, 0 ) )
return 0;
return 1;
}
*/
void Cnf_SpecialDataLift( Cnf_Dat_t * p, int nVarsPlus, int firstPiVar, int lastPiVar)
{
int v, var;
for ( v = 0; v < p->nLiterals; v++ )
{
var = p->pClauses[0][v] / 2;
if (var < firstPiVar || var >= lastPiVar)
p->pClauses[0][v] += 2*nVarsPlus;
else
p->pClauses[0][v] -= 2*firstPiVar;
}
}
int Gia_QbfAddCofactor( Qbf_Man_t * p, Gia_Man_t * pCof )
{
Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCof, 8, 0, 1, 0, 0 );
int i, useold = 0;
int iFirstVar = useold ? sat_solver_nvars(p->pSatSyn) + pCnf->nVars - Gia_ManPiNum(pCof) : pCnf->nVars - Gia_ManPiNum(pCof); //-1
pCnf->pMan = NULL;
if (useold)
Cnf_DataLift( pCnf, sat_solver_nvars(p->pSatSyn) );
else
Cnf_SpecialDataLift( pCnf, sat_solver_nvars(p->pSatSyn), iFirstVar, iFirstVar + Gia_ManPiNum(p->pGia) );
for ( i = 0; i < pCnf->nClauses; i++ )
if ( !sat_solver_addclause( p->pSatSyn, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
{
Cnf_DataFree( pCnf );
return 0;
}
Cnf_DataFree( pCnf );
// add connection clauses
if (useold)
for ( i = 0; i < Gia_ManPiNum(p->pGia); i++ )
if ( !sat_solver_add_buffer( p->pSatSyn, i, iFirstVar+i, 0 ) )
return 0;
return 1;
}
int Gia_QbfAddCofactorG( Qbf_Man_t * p, Gia_Man_t * pCof )
{
Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCof, 8, 0, 1, 0, 0 );
int i, iFirstVar = pCnf->nVars - Gia_ManPiNum(pCof); //-1
pCnf->pMan = NULL;
Cnf_SpecialDataLift( pCnf, bmcg_sat_solver_varnum(p->pSatSynG), iFirstVar, iFirstVar + Gia_ManPiNum(p->pGia) );
for ( i = 0; i < pCnf->nClauses; i++ )
if ( !bmcg_sat_solver_addclause( p->pSatSynG, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) )
{
Cnf_DataFree( pCnf );
return 0;
}
Cnf_DataFree( pCnf );
return 1;
}
/**Function*************************************************************
Synopsis [Extract SAT assignment.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_QbfOnePattern( Qbf_Man_t * p, Vec_Int_t * vValues )
{
int i;
Vec_IntClear( vValues );
for ( i = 0; i < p->nPars; i++ )
Vec_IntPush( vValues, p->pSatSynG ? bmcg_sat_solver_read_cex_varvalue(p->pSatSynG, i) : sat_solver_var_value(p->pSatSyn, i) );
}
void Gia_QbfPrint( Qbf_Man_t * p, Vec_Int_t * vValues, int Iter )
{
printf( "%5d : ", Iter );
assert( Vec_IntSize(vValues) == p->nVars );
Vec_IntPrintBinary( vValues ); printf( " " );
printf( "Var =%7d ", p->pSatSynG ? bmcg_sat_solver_varnum(p->pSatSynG) : sat_solver_nvars(p->pSatSyn) );
printf( "Cla =%7d ", p->pSatSynG ? bmcg_sat_solver_clausenum(p->pSatSynG) : sat_solver_nclauses(p->pSatSyn) );
printf( "Conf =%9d ", p->pSatSynG ? bmcg_sat_solver_conflictnum(p->pSatSynG) : sat_solver_nconflicts(p->pSatSyn) );
Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
}
/**Function*************************************************************
Synopsis [Generate one SAT assignment in terms of functional vars.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_QbfVerify( Qbf_Man_t * p, Vec_Int_t * vValues )
{
int i, Entry, RetValue;
assert( Vec_IntSize(vValues) == p->nPars );
Vec_IntClear( p->vLits );
Vec_IntForEachEntry( vValues, Entry, i )
Vec_IntPush( p->vLits, Abc_Var2Lit(p->iParVarBeg+i, !Entry) );
RetValue = sat_solver_solve( p->pSatVer, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits), 0, 0, 0, 0 );
if ( RetValue == l_True )
{
Vec_IntClear( vValues );
for ( i = 0; i < p->nVars; i++ )
Vec_IntPush( vValues, sat_solver_var_value(p->pSatVer, p->iParVarBeg+p->nPars+i) );
}
return RetValue == l_True ? 1 : 0;
}
/**Function*************************************************************
Synopsis [Constraint learning.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Gia_QbfAddSpecialConstr( Qbf_Man_t * p )
{
int i, status, Lits[2];
for ( i = 0; i < 4*11; i++ )
if ( i % 4 == 0 )
{
assert( Vec_IntEntry(p->vParMap, i) == -1 );
Vec_IntWriteEntry( p->vParMap, i, (i % 4) == 3 );
Lits[0] = Abc_Var2Lit( i, (i % 4) != 3 );
status = sat_solver_addclause( p->pSatSyn, Lits, Lits+1 );
assert( status );
}
}
void Gia_QbfLearnConstraint( Qbf_Man_t * p, Vec_Int_t * vValues )
{
int i, status, Entry, Lits[2];
assert( Vec_IntSize(vValues) == p->nPars );
printf( " Pattern " );
Vec_IntPrintBinary( vValues );
printf( "\n" );
Vec_IntForEachEntry( vValues, Entry, i )
{
Lits[0] = Abc_Var2Lit( i, Entry );
status = sat_solver_solve( p->pSatSyn, Lits, Lits+1, 0, 0, 0, 0 );
printf( " Var =%4d ", i );
if ( status != l_True )
{
printf( "UNSAT\n" );
Lits[0] = Abc_LitNot(Lits[0]);
status = sat_solver_addclause( p->pSatSyn, Lits, Lits+1 );
assert( status );
continue;
}
Gia_QbfOnePattern( p, p->vLits );
Vec_IntPrintBinary( p->vLits );
printf( "\n" );
}
assert( Vec_IntSize(vValues) == p->nPars );
}
/**Function*************************************************************
Synopsis [Performs QBF solving using an improved algorithm.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_QbfSolve( Gia_Man_t * pGia, int nPars, int nIterLimit, int nConfLimit, int nTimeOut, int fGlucose, int fVerbose )
{
Qbf_Man_t * p = Gia_QbfAlloc( pGia, nPars, fGlucose, fVerbose );
Gia_Man_t * pCof;
int i, status, RetValue = 0;
abctime clk;
// Gia_QbfAddSpecialConstr( p );
if ( fVerbose )
printf( "Solving QBF for \"%s\" with %d parameters, %d variables and %d AIG nodes.\n",
Gia_ManName(pGia), p->nPars, p->nVars, Gia_ManAndNum(pGia) );
assert( Gia_ManRegNum(pGia) == 0 );
Vec_IntFill( p->vValues, nPars, 0 );
for ( i = 0; Gia_QbfVerify(p, p->vValues); i++ )
{
// generate next constraint
assert( Vec_IntSize(p->vValues) == p->nVars );
pCof = Gia_QbfCofactor( pGia, nPars, p->vValues, p->vParMap );
status = p->pSatSynG ? Gia_QbfAddCofactorG( p, pCof ) : Gia_QbfAddCofactor( p, pCof );
Gia_ManStop( pCof );
if ( status == 0 ) { RetValue = 1; break; }
// synthesize next assignment
clk = Abc_Clock();
if ( p->pSatSynG )
status = bmcg_sat_solver_solve( p->pSatSynG, NULL, 0 );
else
status = sat_solver_solve( p->pSatSyn, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 );
p->clkSat += Abc_Clock() - clk;
if ( fVerbose )
Gia_QbfPrint( p, p->vValues, i );
if ( status == l_False ) { RetValue = 1; break; }
if ( status == l_Undef ) { RetValue = -1; break; }
// extract SAT assignment
Gia_QbfOnePattern( p, p->vValues );
assert( Vec_IntSize(p->vValues) == p->nPars );
// examine variables
// Gia_QbfLearnConstraint( p, p->vValues );
// Vec_IntPrintBinary( p->vValues ); printf( "\n" );
if ( nIterLimit && i+1 == nIterLimit ) { RetValue = -1; break; }
if ( nTimeOut && (Abc_Clock() - p->clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = -1; break; }
}
if ( RetValue == 0 )
{
int nZeros = Vec_IntCountZero( p->vValues );
printf( "Parameters: " );
assert( Vec_IntSize(p->vValues) == nPars );
Vec_IntPrintBinary( p->vValues );
printf( " Statistics: 0=%d 1=%d\n", nZeros, Vec_IntSize(p->vValues) - nZeros );
}
if ( RetValue == -1 && nTimeOut && (Abc_Clock() - p->clkStart)/CLOCKS_PER_SEC >= nTimeOut )
printf( "The problem timed out after %d sec. ", nTimeOut );
else if ( RetValue == -1 && nConfLimit )
printf( "The problem aborted after %d conflicts. ", nConfLimit );
else if ( RetValue == -1 && nIterLimit )
printf( "The problem aborted after %d iterations. ", nIterLimit );
else if ( RetValue == 1 )
printf( "The problem is UNSAT after %d iterations. ", i );
else
printf( "The problem is SAT after %d iterations. ", i );
if ( fVerbose )
{
printf( "\n" );
Abc_PrintTime( 1, "SAT ", p->clkSat );
Abc_PrintTime( 1, "Other", Abc_Clock() - p->clkStart - p->clkSat );
Abc_PrintTime( 1, "TOTAL", Abc_Clock() - p->clkStart );
}
else
Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
Gia_QbfFree( p );
return RetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END