/**CFile**************************************************************** FileName [bmcClp.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [SAT-based bounded model checking.] Synopsis [INT-FX: Interpolation-based logic sharing extraction.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: bmcClp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "bmc.h" #include "misc/vec/vecWec.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [For a given random pattern, compute output change.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_ComputeSimDiff( Gia_Man_t * p, Vec_Int_t * vPat, Vec_Int_t * vPat2 ) { Gia_Obj_t * pObj; int i, Id; word Sim, Sim0, Sim1; Gia_ManForEachCiId( p, Id, i ) { Sim = Vec_IntEntry(vPat, i) ? ~(word)0 : 0; Sim ^= (word)1 << (i + 1); Vec_WrdWriteEntry( p->vSims, Id, Sim ); } Gia_ManForEachAnd( p, pObj, i ) { Sim0 = Vec_WrdEntry( p->vSims, Gia_ObjFaninId0(pObj, i) ); Sim1 = Vec_WrdEntry( p->vSims, Gia_ObjFaninId1(pObj, i) ); Sim0 = Gia_ObjFaninC0(pObj) ? ~Sim0 : Sim0; Sim1 = Gia_ObjFaninC1(pObj) ? ~Sim1 : Sim1; Vec_WrdWriteEntry( p->vSims, i, Sim0 & Sim1 ); } Gia_ManForEachCo( p, pObj, i ) { Id = Gia_ObjId( p, pObj ); Sim0 = Vec_WrdEntry( p->vSims, Gia_ObjFaninId0(pObj, Id) ); Sim0 = Gia_ObjFaninC0(pObj) ? ~Sim0 : Sim0; Vec_WrdWriteEntry( p->vSims, Id, Sim0 ); } pObj = Gia_ManCo( p, 0 ); Sim = Vec_WrdEntry( p->vSims, Gia_ObjId(p, pObj) ); Vec_IntClear( vPat2 ); for ( i = 1; i <= Gia_ManCiNum(p); i++ ) Vec_IntPush( vPat2, (int)((Sim & 1) ^ ((Sim >> i) & 1)) ); return (int)(Sim & 1); } void Bmc_ComputeSimTest( Gia_Man_t * p ) { int i, v, w, Res, Bit, Bit2, nPats = 256; int Count[2][64][64] = {{{0}}}; int PatCount[64][2][2] = {{{0}}}; int DiffCount[64] = {0}; Vec_Int_t * vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); Vec_Int_t * vPat2 = Vec_IntAlloc( Gia_ManCiNum(p) ); Vec_WrdFreeP( &p->vSims ); p->vSims = Vec_WrdStart( Gia_ManObjNum(p) ); printf( "Number of patterns = %d.\n", nPats ); for ( i = 0; i < nPats; i++ ) { Vec_IntClear( vPat ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) Vec_IntPush( vPat, rand() & 1 ); // Vec_IntForEachEntry( vPat, Bit, v ) // printf( "%d", Bit ); // printf( " " ); Res = Bmc_ComputeSimDiff( p, vPat, vPat2 ); // printf( "%d ", Res ); // Vec_IntForEachEntry( vPat2, Bit, v ) // printf( "%d", Bit ); // printf( "\n" ); Vec_IntForEachEntry( vPat, Bit, v ) PatCount[v][Res][Bit]++; Vec_IntForEachEntry( vPat2, Bit, v ) { if ( Bit ) DiffCount[v]++; Vec_IntForEachEntryStart( vPat2, Bit2, w, v + 1 ) if ( Bit && Bit2 ) Count[Res][v][w]++; } } Vec_IntFree( vPat ); Vec_IntFree( vPat2 ); Vec_WrdFreeP( &p->vSims ); printf( "\n" ); printf( " " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3c ", 'a'+v ); printf( "\n" ); printf( "Off0 " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3d ", PatCount[v][0][0] ); printf( "\n" ); printf( "Off1 " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3d ", PatCount[v][0][1] ); printf( "\n" ); printf( "On0 " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3d ", PatCount[v][1][0] ); printf( "\n" ); printf( "On1 " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3d ", PatCount[v][1][1] ); printf( "\n" ); printf( "\n" ); printf( "Diff " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3d ", DiffCount[v] ); printf( "\n" ); printf( "\n" ); for ( i = 0; i < 2; i++ ) { printf( " " ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) printf( "%3c ", 'a'+v ); printf( "\n" ); for ( v = 0; v < Gia_ManCiNum(p); v++ ) { printf( " %c ", 'a'+v ); for ( w = 0; w < Gia_ManCiNum(p); w++ ) { if ( Count[i][v][w] ) printf( "%3d ", Count[i][v][w] ); else printf( " . " ); } printf( "\n" ); } printf( "\n" ); } } static abctime clkCheck1 = 0; static abctime clkCheck2 = 0; static abctime clkCheckS = 0; static abctime clkCheckU = 0; // iterator thought the cubes #define Bmc_SopForEachCube( pSop, nVars, pCube ) for ( pCube = (pSop); *pCube; pCube += (nVars) + 3 ) /**Function************************************************************* Synopsis [Perform approximate irredundant step on the cover.] Description [Iterate through the cubes in the reverse order and check if each cube is contained in the previously seen cubes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_CollapseIrredundant( Vec_Str_t * vSop, int nCubes, int nVars ) { int nBTLimit = 0; sat_solver * pSat; int i, k, status, iLit, nRemoved = 0; Vec_Int_t * vLits = Vec_IntAlloc(nVars); // collect cubes char * pCube, * pSop = Vec_StrArray(vSop); Vec_Ptr_t * vCubes = Vec_PtrAlloc(nCubes); assert( Vec_StrSize(vSop) == nCubes * (nVars + 3) + 1 ); Bmc_SopForEachCube( pSop, nVars, pCube ) Vec_PtrPush( vCubes, pCube ); // create SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, nVars ); // iterate through cubes in the reverse order Vec_PtrForEachEntryReverse( char *, vCubes, pCube, i ) { // collect literals Vec_IntClear( vLits ); for ( k = 0; k < nVars; k++ ) if ( pCube[k] != '-' ) Vec_IntPush( vLits, Abc_Var2Lit(k, pCube[k] == '1') ); // check if this cube intersects with the complement of other cubes in the solver // if it does not intersect, then it is redundant and can be skipped // if it does, then it should be added status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) // timeout break; if ( status == l_False ) // unsat { Vec_PtrWriteEntry( vCubes, i, NULL ); nRemoved++; continue; } assert( status == l_True ); // make a clause out of the cube by complementing its literals Vec_IntForEachEntry( vLits, iLit, k ) Vec_IntWriteEntry( vLits, k, Abc_LitNot(iLit) ); // add it to the solver status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); assert( status == 1 ); } //printf( "Approximate irrendundant reduced %d cubes (out of %d).\n", nRemoved, nCubes ); // cleanup cover if ( i == -1 && nRemoved > 0 ) // finished without timeout and removed some cubes { int j = 0; Vec_PtrForEachEntry( char *, vCubes, pCube, i ) if ( pCube != NULL ) for ( k = 0; k < nVars + 3; k++ ) Vec_StrWriteEntry( vSop, j++, pCube[k] ); Vec_StrWriteEntry( vSop, j++, '\0' ); Vec_StrShrink( vSop, j ); } sat_solver_delete( pSat ); Vec_PtrFree( vCubes ); Vec_IntFree( vLits ); return i == -1 ? 1 : 0; } /**Function************************************************************* Synopsis [Perform full irredundant step on the cover.] Description [Iterate through the cubes in the direct order and check if each cube is contained in all other cubes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_CollapseIrredundantFull( Vec_Str_t * vSop, int nCubes, int nVars ) { int nBTLimit = 0; sat_solver * pSat; int i, k, status, nRemoved = 0; Vec_Int_t * vLits = Vec_IntAlloc(nVars+nCubes); // collect cubes char * pCube, * pSop = Vec_StrArray(vSop); Vec_Ptr_t * vCubes = Vec_PtrAlloc(nCubes); assert( Vec_StrSize(vSop) == nCubes * (nVars + 3) + 1 ); Bmc_SopForEachCube( pSop, nVars, pCube ) Vec_PtrPush( vCubes, pCube ); // create SAT solver pSat = sat_solver_new(); sat_solver_setnvars( pSat, nVars + nCubes ); // add cubes Vec_PtrForEachEntry( char *, vCubes, pCube, i ) { // collect literals Vec_IntFill( vLits, 1, Abc_Var2Lit(nVars + i, 1) ); // neg literal for ( k = 0; k < nVars; k++ ) if ( pCube[k] != '-' ) Vec_IntPush( vLits, Abc_Var2Lit(k, pCube[k] == '0') ); // add it to the solver status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); assert( status == 1 ); } // iterate through cubes in the direct order Vec_PtrForEachEntry( char *, vCubes, pCube, i ) { // collect literals Vec_IntClear( vLits ); for ( k = 0; k < nCubes; k++ ) if ( k != i && Vec_PtrEntry(vCubes, k) ) // skip this cube and already removed cubes Vec_IntPush( vLits, Abc_Var2Lit(nVars + k, 0) ); // pos literal // collect cube for ( k = 0; k < nVars; k++ ) if ( pCube[k] != '-' ) Vec_IntPush( vLits, Abc_Var2Lit(k, pCube[k] == '1') ); // check if this cube intersects with the complement of other cubes in the solver // if it does not intersect, then it is redundant and can be skipped status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) // timeout break; if ( status == l_False ) // unsat { Vec_PtrWriteEntry( vCubes, i, NULL ); nRemoved++; continue; } assert( status == l_True ); } //printf( "Approximate irrendundant reduced %d cubes (out of %d).\n", nRemoved, nCubes ); // cleanup cover if ( i == Vec_PtrSize(vCubes) && nRemoved > 0 ) // finished without timeout and removed some cubes { int j = 0; Vec_PtrForEachEntry( char *, vCubes, pCube, i ) if ( pCube != NULL ) for ( k = 0; k < nVars + 3; k++ ) Vec_StrWriteEntry( vSop, j++, pCube[k] ); Vec_StrWriteEntry( vSop, j++, '\0' ); Vec_StrShrink( vSop, j ); } sat_solver_delete( pSat ); Vec_PtrFree( vCubes ); Vec_IntFree( vLits ); return i == -1 ? 1 : 0; } /**Function************************************************************* Synopsis [Performs one round of removing literals.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_CollapseExpandRound2( sat_solver * pSat, Vec_Int_t * vLits, Vec_Int_t * vTemp, int nBTLimit, int fOnOffSetLit ) { // put into new array int i, iLit, nLits; Vec_IntClear( vTemp ); Vec_IntForEachEntry( vLits, iLit, i ) if ( iLit != -1 ) Vec_IntPush( vTemp, iLit ); assert( Vec_IntSize(vTemp) > 0 ); // assume condition literal if ( fOnOffSetLit >= 0 ) sat_solver_push( pSat, fOnOffSetLit ); // minimize nLits = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vTemp), Vec_IntSize(vTemp), nBTLimit ); Vec_IntShrink( vTemp, nLits ); // assume conditional literal if ( fOnOffSetLit >= 0 ) sat_solver_pop( pSat ); // modify output literas Vec_IntForEachEntry( vLits, iLit, i ) if ( iLit != -1 && Vec_IntFind(vTemp, iLit) == -1 ) Vec_IntWriteEntry( vLits, i, -1 ); return 0; } int Bmc_CollapseExpandRound( sat_solver * pSat, sat_solver * pSatOn, Vec_Int_t * vLits, Vec_Int_t * vNums, Vec_Int_t * vTemp, int nBTLimit, int fCanon, int fOnOffSetLit ) { int fProfile = 0; int k, n, iLit, status; abctime clk; //return Bmc_CollapseExpandRound2( pSat, vLits, vTemp, nBTLimit, fOnOffSetLit ); // try removing one literal at a time for ( k = Vec_IntSize(vLits) - 1; k >= 0; k-- ) { int Save = Vec_IntEntry( vLits, k ); if ( Save == -1 ) continue; // check if this literal when expanded overlaps with the on-set if ( pSatOn ) { assert( fOnOffSetLit == -1 ); // it is ok to skip the first round if the literal is positive if ( fCanon && !Abc_LitIsCompl(Save) ) continue; // put into new array Vec_IntClear( vTemp ); Vec_IntForEachEntry( vLits, iLit, n ) if ( iLit != -1 ) Vec_IntPush( vTemp, Abc_LitNotCond(iLit, k==n) ); // check against onset if ( fProfile ) clk = Abc_Clock(); status = sat_solver_solve( pSatOn, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), nBTLimit, 0, 0, 0 ); if ( fProfile ) clkCheck1 += Abc_Clock() - clk; if ( status == l_Undef ) return -1; //printf( "%d", status == l_True ); if ( status == l_False ) { if ( fProfile ) clkCheckU += Abc_Clock() - clk; continue; } if ( fProfile ) clkCheckS += Abc_Clock() - clk; // otherwise keep trying to remove it } Vec_IntWriteEntry( vLits, k, -1 ); // put into new array Vec_IntClear( vTemp ); if ( fOnOffSetLit >= 0 ) Vec_IntPush( vTemp, fOnOffSetLit ); Vec_IntForEachEntry( vLits, iLit, n ) if ( iLit != -1 ) Vec_IntPush( vTemp, iLit ); // check against offset if ( fProfile ) clk = Abc_Clock(); status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), nBTLimit, 0, 0, 0 ); if ( fProfile ) clkCheck2 += Abc_Clock() - clk; // if ( fOnOffSetLit >= 0 ) // Vec_IntPop( vTemp ); if ( status == l_Undef ) return -1; if ( status == l_True ) { Vec_IntWriteEntry( vLits, k, Save ); if ( fProfile ) clkCheckS += Abc_Clock() - clk; } else if ( fProfile ) clkCheckU += Abc_Clock() - clk; } // if ( pSatOn ) // printf( "\n" ); return 0; } /**Function************************************************************* Synopsis [Expends minterm into a cube.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_CollapseExpand( sat_solver * pSat, sat_solver * pSatOn, Vec_Int_t * vLits, Vec_Int_t * vNums, Vec_Int_t * vTemp, int nBTLimit, int fCanon, int fOnOffSetLit ) { // perform one quick reduction if it is non-canonical if ( !fCanon ) { int i, k, iLit, status, nFinal, * pFinal; // check against offset if ( fOnOffSetLit >= 0 ) Vec_IntPush( vLits, fOnOffSetLit ); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), nBTLimit, 0, 0, 0 ); if ( fOnOffSetLit >= 0 ) Vec_IntPop( vLits ); if ( status == l_Undef ) return -1; assert( status == l_False ); // get subset of literals nFinal = sat_solver_final( pSat, &pFinal ); // mark unused literals Vec_IntForEachEntry( vLits, iLit, i ) { for ( k = 0; k < nFinal; k++ ) if ( iLit == Abc_LitNot(pFinal[k]) ) break; if ( k == nFinal ) Vec_IntWriteEntry( vLits, i, -1 ); } if ( Bmc_CollapseExpandRound( pSat, NULL, vLits, vNums, vTemp, nBTLimit, fCanon, fOnOffSetLit ) == -1 ) return -1; } else { if ( Bmc_CollapseExpandRound( pSat, pSatOn, vLits, vNums, vTemp, nBTLimit, fCanon, -1 ) == -1 ) return -1; if ( Bmc_CollapseExpandRound( pSat, NULL, vLits, vNums, vTemp, nBTLimit, fCanon, -1 ) == -1 ) return -1; } { // put into new array int i, iLit; Vec_IntClear( vNums ); Vec_IntForEachEntry( vLits, iLit, i ) if ( iLit != -1 ) Vec_IntPush( vNums, i ); } return 0; } int Bmc_CollapseExpand2( sat_solver * pSat, sat_solver * pSatOn, Vec_Int_t * vLits, Vec_Int_t * vNums, Vec_Int_t * vTemp, int nBTLimit, int fCanon, int fOnOffSetLit ) { // perform one quick reduction if it is non-canonical if ( !fCanon ) { int i, k, iLit, j, iNum, status, nFinal, * pFinal; // check against offset if ( fOnOffSetLit >= 0 ) Vec_IntPush( vLits, fOnOffSetLit ); status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), nBTLimit, 0, 0, 0 ); if ( fOnOffSetLit >= 0 ) Vec_IntPop( vLits ); if ( status == l_Undef ) return -1; assert( status == l_False ); // get subset of literals nFinal = sat_solver_final( pSat, &pFinal ); Vec_IntClear( vNums ); Vec_IntClear( vTemp ); if ( fOnOffSetLit >= 0 ) { //Vec_IntPush( vNums, -1 ); Vec_IntPush( vTemp, fOnOffSetLit ); } Vec_IntForEachEntry( vLits, iLit, i ) { for ( k = 0; k < nFinal; k++ ) if ( iLit == Abc_LitNot(pFinal[k]) ) break; if ( k == nFinal ) continue; Vec_IntPush( vNums, i ); Vec_IntPush( vTemp, iLit ); } // check against offset status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) return -1; assert( status == l_False ); // get subset of literals nFinal = sat_solver_final( pSat, &pFinal ); j = 0; Vec_IntForEachEntry( vTemp, iLit, i ) { if ( iLit == fOnOffSetLit ) continue; for ( k = 0; k < nFinal; k++ ) if ( iLit == Abc_LitNot(pFinal[k]) ) break; if ( k == nFinal ) continue; Vec_IntWriteEntry( vNums, j++, Vec_IntEntry(vNums, i) ); } Vec_IntShrink( vNums, j ); // try removing each literal for ( i = 0; i < Vec_IntSize(vNums); i++ ) { Vec_IntClear( vTemp ); if ( fOnOffSetLit >= 0 ) Vec_IntPush( vTemp, fOnOffSetLit ); Vec_IntForEachEntry( vNums, iNum, k ) if ( k != i ) Vec_IntPush( vTemp, Vec_IntEntry(vLits, iNum) ); // check against offset status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) return -1; if ( status == l_True ) continue; // remove literal Vec_IntDrop( vNums, i ); i--; } } else { if ( Bmc_CollapseExpandRound( pSat, pSatOn, vLits, vNums, vTemp, nBTLimit, fCanon, -1 ) == -1 ) return -1; if ( Bmc_CollapseExpandRound( pSat, NULL, vLits, vNums, vTemp, nBTLimit, fCanon, -1 ) == -1 ) return -1; } /* { // put into new array int i, iLit; Vec_IntClear( vNums ); Vec_IntForEachEntry( vLits, iLit, i ) if ( iLit != -1 ) Vec_IntPush( vNums, i ); //printf( "%d(%d) ", Vec_IntSize(vNums), Vec_IntSize(vLits) ); } */ return 0; } /**Function************************************************************* Synopsis [Returns SAT solver in the 'sat' state with the given assignment.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Bmc_ComputeCanonical2( sat_solver * pSat, Vec_Int_t * vLits, Vec_Int_t * vTemp, int nBTLimit ) { int i, k, iLit, status = l_Undef; for ( i = 0; i < Vec_IntSize(vLits); i++ ) { // copy the first i+1 literals Vec_IntClear( vTemp ); Vec_IntForEachEntryStop( vLits, iLit, k, i+1 ) Vec_IntPush( vTemp, iLit ); // check if it satisfies the on-set status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntLimit(vTemp), nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) return l_Undef; if ( status == l_True ) continue; // if it is UNSAT, try the opposite literal iLit = Vec_IntEntry( vLits, i ); // if literal is positive, there is no way to flip it if ( !Abc_LitIsCompl(iLit) ) return l_False; Vec_IntWriteEntry( vLits, i, Abc_LitNot(iLit) ); Vec_IntForEachEntryStart( vLits, iLit, k, i+1 ) Vec_IntWriteEntry( vLits, k, Abc_LitNot(Abc_LitRegular(iLit)) ); // recheck i--; } assert( status == l_True ); return status; } int Bmc_ComputeCanonical( sat_solver * pSat, Vec_Int_t * vLits, Vec_Int_t * vTemp, int nBTLimit ) { sat_solver_set_resource_limits( pSat, nBTLimit, 0, 0, 0 ); return sat_solver_solve_lexsat( pSat, Vec_IntArray(vLits), Vec_IntSize(vLits) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Bmc_CollapseOneInt2( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose, int fCompl ) { int fPrintMinterm = 0; int nVars = Gia_ManCiNum(p); Vec_Int_t * vVars = Vec_IntAlloc( nVars ); Vec_Int_t * vLits = Vec_IntAlloc( nVars ); Vec_Int_t * vLitsC= Vec_IntAlloc( nVars ); Vec_Int_t * vNums = Vec_IntAlloc( nVars ); Vec_Int_t * vCube = Vec_IntAlloc( nVars ); Vec_Str_t * vSop = Vec_StrAlloc( 100 ); int iOut = 0, iLit, iVar, status, n, Count, Start; // create SAT solver 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), fCanon ? (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0) : NULL }; // collect CI variables int iCiVarBeg = pCnf->nVars - nVars;// - 1; if ( fReverse ) for ( n = nVars - 1; n >= 0; n-- ) Vec_IntPush( vVars, iCiVarBeg + n ); else for ( n = 0; n < nVars; n++ ) Vec_IntPush( vVars, iCiVarBeg + n ); // start with all negative literals Vec_IntForEachEntry( vVars, iVar, n ) Vec_IntPush( vLitsC, Abc_Var2Lit(iVar, 1) ); // check that on-set/off-set is sat for ( n = 0; n < 2 + fCanon; n++ ) { iLit = Abc_Var2Lit( iOut + 1, n&1 ); // n=0 => F=1 n=1 => F=0 status = sat_solver_addclause( pSat[n], &iLit, &iLit + 1 ); if ( status == 0 ) { Vec_StrPrintStr( vSop, ((n&1) ^ fCompl) ? " 1\n" : " 0\n" ); Vec_StrPush( vSop, '\0' ); goto cleanup; // const0/1 } status = sat_solver_solve( pSat[n], NULL, NULL, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) { Vec_StrFreeP( &vSop ); goto cleanup; // timeout } if ( status == l_False ) { Vec_StrPrintStr( vSop, ((n&1) ^ fCompl) ? " 1\n" : " 0\n" ); Vec_StrPush( vSop, '\0' ); goto cleanup; // const0/1 } } Vec_StrPush( vSop, '\0' ); // prepare on-set for solving // if ( fCanon ) // sat_solver_prepare_enum( pSat[0], Vec_IntArray(vVars), Vec_IntSize(vVars) ); Count = 0; while ( 1 ) { // get the assignment if ( fCanon ) status = Bmc_ComputeCanonical( pSat[0], vLitsC, vCube, nBTLimit ); else { sat_solver_clean_polarity( pSat[0], Vec_IntArray(vVars), Vec_IntSize(vVars) ); status = sat_solver_solve( pSat[0], NULL, NULL, 0, 0, 0, 0 ); } if ( status == l_Undef ) { Vec_StrFreeP( &vSop ); goto cleanup; // timeout } if ( status == l_False ) break; // check number of cubes if ( nCubeLim > 0 && Count == nCubeLim ) { //printf( "The number of cubes exceeded the limit (%d).\n", nCubeLim ); Vec_StrFreeP( &vSop ); goto cleanup; // cube out } // collect values Vec_IntClear( vLits ); Vec_IntClear( vLitsC ); Vec_IntForEachEntry( vVars, iVar, n ) { iLit = Abc_Var2Lit(iVar, !sat_solver_var_value(pSat[0], iVar)); Vec_IntPush( vLits, iLit ); Vec_IntPush( vLitsC, iLit ); } // print minterm if ( fPrintMinterm ) { printf( "Mint: " ); Vec_IntForEachEntry( vLits, iLit, n ) printf( "%d", !Abc_LitIsCompl(iLit) ); printf( "\n" ); } // expand the values status = Bmc_CollapseExpand( pSat[1], fCanon ? pSat[2] : pSat[0], vLits, vNums, vCube, nBTLimit, fCanon, -1 ); if ( status < 0 ) { Vec_StrFreeP( &vSop ); goto cleanup; // timeout } // collect cube Vec_StrPop( vSop ); Start = Vec_StrSize( vSop ); Vec_StrFillExtra( vSop, Start + nVars + 4, '-' ); Vec_StrWriteEntry( vSop, Start + nVars + 0, ' ' ); Vec_StrWriteEntry( vSop, Start + nVars + 1, (char)(fCompl ? '0' : '1') ); Vec_StrWriteEntry( vSop, Start + nVars + 2, '\n' ); Vec_StrWriteEntry( vSop, Start + nVars + 3, '\0' ); Vec_IntClear( vCube ); Vec_IntForEachEntry( vNums, iVar, n ) { iLit = Vec_IntEntry( vLits, iVar ); Vec_IntPush( vCube, Abc_LitNot(iLit) ); if ( fReverse ) Vec_StrWriteEntry( vSop, Start + nVars - iVar - 1, (char)('0' + !Abc_LitIsCompl(iLit)) ); else Vec_StrWriteEntry( vSop, Start + iVar, (char)('0' + !Abc_LitIsCompl(iLit)) ); } //if ( fVerbose ) // printf( "Cube %4d: %s", Count, Vec_StrArray(vSop) + Start ); Count++; // add cube status = sat_solver_addclause( pSat[0], Vec_IntArray(vCube), Vec_IntLimit(vCube) ); if ( status == 0 ) break; // add cube if ( fCanon ) status = sat_solver_addclause( pSat[2], Vec_IntArray(vCube), Vec_IntLimit(vCube) ); assert( status == 1 ); } //printf( "Finished enumerating %d assignments.\n", Count ); cleanup: Vec_IntFree( vVars ); Vec_IntFree( vLits ); Vec_IntFree( vLitsC ); Vec_IntFree( vNums ); Vec_IntFree( vCube ); sat_solver_delete( pSat[0] ); sat_solver_delete( pSat[1] ); if ( fCanon ) sat_solver_delete( pSat[2] ); Cnf_DataFree( pCnf ); // quickly reduce contained cubes if ( vSop != NULL ) Bmc_CollapseIrredundant( vSop, Vec_StrSize(vSop)/(nVars +3), nVars ); return vSop; } Vec_Str_t * Bmc_CollapseOneOld2( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { Vec_Str_t * vSopOn, * vSopOff; int nCubesOn = ABC_INFINITY; int nCubesOff = ABC_INFINITY; vSopOn = Bmc_CollapseOneInt2( p, nCubeLim, nBTLimit, fCanon, fReverse, fVerbose, 0 ); if ( vSopOn ) nCubesOn = Vec_StrCountEntry(vSopOn,'\n'); Gia_ObjFlipFaninC0( Gia_ManPo(p, 0) ); vSopOff = Bmc_CollapseOneInt2( p, Abc_MinInt(nCubeLim, nCubesOn), nBTLimit, fCanon, fReverse, fVerbose, 1 ); Gia_ObjFlipFaninC0( Gia_ManPo(p, 0) ); if ( vSopOff ) nCubesOff = Vec_StrCountEntry(vSopOff,'\n'); if ( vSopOn == NULL ) return vSopOff; if ( vSopOff == NULL ) return vSopOn; if ( nCubesOn <= nCubesOff ) { Vec_StrFree( vSopOff ); return vSopOn; } else { Vec_StrFree( vSopOn ); return vSopOff; } } /**Function************************************************************* Synopsis [This code computes on-set and off-set simultaneously.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Bmc_CollapseOneOld( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { int fVeryVerbose = fVerbose; int nVars = Gia_ManCiNum(p); 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; Vec_Int_t * vLitsC[2] = { Vec_IntAlloc(nVars), Vec_IntAlloc(nVars) }; Vec_Int_t * vVars = Vec_IntAlloc( nVars ); Vec_Int_t * vLits = Vec_IntAlloc( nVars ); Vec_Int_t * vNums = Vec_IntAlloc( nVars ); Vec_Int_t * vCube = Vec_IntAlloc( nVars ); int n, v, iVar, iLit, iCiVarBeg, iCube = 0, Start, status; abctime clk = 0, Time[2][2] = {{0}}; int fComplete[2] = {0}; // collect CI variables iCiVarBeg = pCnf->nVars - nVars;// - 1; if ( fReverse ) for ( v = nVars - 1; v >= 0; v-- ) Vec_IntPush( vVars, iCiVarBeg + v ); else for ( v = 0; v < nVars; v++ ) Vec_IntPush( vVars, iCiVarBeg + v ); // check that on-set/off-set is sat for ( n = 0; n < 2; n++ ) { iLit = Abc_Var2Lit( 1, n ); // n=0 => F=1 n=1 => F=0 status = sat_solver_solve( pSat[n], &iLit, &iLit + 1, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { Vec_StrClear( vSop[0] ); Vec_StrPrintStr( vSop[0], n ? " 1\n" : " 0\n" ); Vec_StrPush( vSop[0], '\0' ); fComplete[0] = 1; goto cleanup; // const0/1 } // start with all negative literals Vec_IntForEachEntry( vVars, iVar, v ) Vec_IntPush( vLitsC[n], Abc_Var2Lit(iVar, 1) ); // add literals to the solver status = sat_solver_addclause( pSat[n], &iLit, &iLit + 1 ); assert( status ); status = sat_solver_addclause( pSatClean[n], &iLit, &iLit + 1 ); assert( status ); // start cover Vec_StrPush( vSop[n], '\0' ); } // compute cube pairs for ( iCube = 0; nCubeLim == 0 || iCube < nCubeLim; iCube++ ) { for ( n = 0; n < 2; n++ ) { if ( fVeryVerbose ) clk = Abc_Clock(); // get the assignment if ( fCanon ) status = Bmc_ComputeCanonical( pSat[n], vLitsC[n], vCube, nBTLimit ); else { sat_solver_clean_polarity( pSat[n], Vec_IntArray(vVars), Vec_IntSize(vVars) ); status = sat_solver_solve( pSat[n], NULL, NULL, 0, 0, 0, 0 ); } if ( fVeryVerbose ) Time[n][0] += Abc_Clock() - clk; if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { fComplete[n] = 1; break; } // collect values Vec_IntClear( vLits ); Vec_IntClear( vLitsC[n] ); Vec_IntForEachEntry( vVars, iVar, v ) { iLit = Abc_Var2Lit(iVar, !sat_solver_var_value(pSat[n], iVar)); Vec_IntPush( vLits, iLit ); Vec_IntPush( vLitsC[n], iLit ); } // expand the values if ( fVeryVerbose ) clk = Abc_Clock(); status = Bmc_CollapseExpand( pSatClean[!n], pSat[n], vLits, vNums, vCube, nBTLimit, fCanon, -1 ); if ( fVeryVerbose ) Time[n][1] += Abc_Clock() - clk; if ( status < 0 ) goto cleanup; // timeout // collect cube Vec_StrPop( vSop[n] ); Start = Vec_StrSize( vSop[n] ); Vec_StrFillExtra( vSop[n], Start + nVars + 4, '-' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 0, ' ' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 1, (char)(n ? '0' : '1') ); Vec_StrWriteEntry( vSop[n], Start + nVars + 2, '\n' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 3, '\0' ); Vec_IntClear( vCube ); Vec_IntForEachEntry( vNums, iVar, v ) { iLit = Vec_IntEntry( vLits, iVar ); Vec_IntPush( vCube, Abc_LitNot(iLit) ); if ( fReverse ) Vec_StrWriteEntry( vSop[n], Start + nVars - iVar - 1, (char)('0' + !Abc_LitIsCompl(iLit)) ); else Vec_StrWriteEntry( vSop[n], Start + iVar, (char)('0' + !Abc_LitIsCompl(iLit)) ); } // add cube status = sat_solver_addclause( pSat[n], Vec_IntArray(vCube), Vec_IntLimit(vCube) ); if ( status == 0 ) { fComplete[n] = 1; break; } assert( status == 1 ); } if ( fComplete[0] || fComplete[1] ) break; } cleanup: Vec_IntFree( vVars ); Vec_IntFree( vLits ); Vec_IntFree( vLitsC[0] ); Vec_IntFree( vLitsC[1] ); Vec_IntFree( vNums ); Vec_IntFree( vCube ); Cnf_DataFree( pCnf ); sat_solver_delete( pSat[0] ); sat_solver_delete( pSat[1] ); sat_solver_delete( pSatClean[0] ); sat_solver_delete( pSatClean[1] ); assert( !fComplete[0] || !fComplete[1] ); if ( fComplete[0] || fComplete[1] ) // one of the cover is computed { vRes = vSop[fComplete[1]]; vSop[fComplete[1]] = NULL; if ( iCube > 1 ) // Bmc_CollapseIrredundant( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); Bmc_CollapseIrredundantFull( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); } if ( fVeryVerbose ) { int fProfile = 0; printf( "Processed output with %d supp vars. ", nVars ); if ( vRes == NULL ) printf( "The resulting SOP exceeded %d cubes.\n", nCubeLim ); else printf( "The best cover contains %d cubes.\n", Vec_StrSize(vRes)/(nVars +3) ); Abc_PrintTime( 1, "Onset minterm", Time[0][0] ); Abc_PrintTime( 1, "Onset expand ", Time[0][1] ); Abc_PrintTime( 1, "Offset minterm", Time[1][0] ); Abc_PrintTime( 1, "Offset expand ", Time[1][1] ); if ( fProfile ) { Abc_PrintTime( 1, "Expand check1 ", clkCheck1 ); clkCheck1 = 0; Abc_PrintTime( 1, "Expand check2 ", clkCheck2 ); clkCheck2 = 0; Abc_PrintTime( 1, "Expand sat ", clkCheckS ); clkCheckS = 0; Abc_PrintTime( 1, "Expand unsat ", clkCheckU ); clkCheckU = 0; } } Vec_StrFreeP( &vSop[0] ); Vec_StrFreeP( &vSop[1] ); return vRes; } /**Function************************************************************* Synopsis [This code computes on-set and off-set simultaneously.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Bmc_CollapseOne_int3( sat_solver * pSat0, sat_solver * pSat1, sat_solver * pSat2, sat_solver * pSat3, int nVars, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { int fVeryVerbose = fVerbose; sat_solver * pSat[2] = { pSat0, pSat1 }; sat_solver * pSatClean[2] = { pSat2, pSat3 }; Vec_Str_t * vSop[2] = { Vec_StrAlloc(1000), Vec_StrAlloc(1000) }, * vRes = NULL; Vec_Int_t * vLitsC[2] = { Vec_IntAlloc(nVars), Vec_IntAlloc(nVars) }; Vec_Int_t * vVars = Vec_IntAlloc( nVars ); Vec_Int_t * vLits = Vec_IntAlloc( nVars ); Vec_Int_t * vNums = Vec_IntAlloc( nVars ); Vec_Int_t * vCube = Vec_IntAlloc( nVars ); int n, v, iVar, iLit, iCiVarBeg, iCube = 0, Start, status; abctime clk = 0, Time[2][2] = {{0}}; int fComplete[2] = {0}; // collect CI variables // iCiVarBeg = pCnf->nVars - nVars;// - 1; iCiVarBeg = sat_solver_nvars(pSat0) - nVars; if ( fReverse ) for ( v = nVars - 1; v >= 0; v-- ) Vec_IntPush( vVars, iCiVarBeg + v ); else for ( v = 0; v < nVars; v++ ) Vec_IntPush( vVars, iCiVarBeg + v ); // check that on-set/off-set is sat for ( n = 0; n < 2; n++ ) { iLit = Abc_Var2Lit( 1, n ); // n=0 => F=1 n=1 => F=0 status = sat_solver_solve( pSat[n], &iLit, &iLit + 1, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { Vec_StrClear( vSop[0] ); Vec_StrPrintStr( vSop[0], n ? " 1\n" : " 0\n" ); Vec_StrPush( vSop[0], '\0' ); fComplete[0] = 1; goto cleanup; // const0/1 } // start with all negative literals Vec_IntForEachEntry( vVars, iVar, v ) Vec_IntPush( vLitsC[n], Abc_Var2Lit(iVar, 1) ); // add literals to the solver status = sat_solver_addclause( pSat[n], &iLit, &iLit + 1 ); assert( status ); status = sat_solver_addclause( pSatClean[n], &iLit, &iLit + 1 ); assert( status ); // start cover Vec_StrPush( vSop[n], '\0' ); } // compute cube pairs for ( iCube = 0; nCubeLim == 0 || iCube < nCubeLim; iCube++ ) { for ( n = 0; n < 2; n++ ) { if ( fVeryVerbose ) clk = Abc_Clock(); // get the assignment if ( fCanon ) status = Bmc_ComputeCanonical( pSat[n], vLitsC[n], vCube, nBTLimit ); else { sat_solver_clean_polarity( pSat[n], Vec_IntArray(vVars), Vec_IntSize(vVars) ); status = sat_solver_solve( pSat[n], NULL, NULL, 0, 0, 0, 0 ); } if ( fVeryVerbose ) Time[n][0] += Abc_Clock() - clk; if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { fComplete[n] = 1; break; } // collect values Vec_IntClear( vLits ); Vec_IntClear( vLitsC[n] ); Vec_IntForEachEntry( vVars, iVar, v ) { iLit = Abc_Var2Lit(iVar, !sat_solver_var_value(pSat[n], iVar)); Vec_IntPush( vLits, iLit ); Vec_IntPush( vLitsC[n], iLit ); } // expand the values if ( fVeryVerbose ) clk = Abc_Clock(); status = Bmc_CollapseExpand( pSatClean[!n], pSat[n], vLits, vNums, vCube, nBTLimit, fCanon, -1 ); if ( fVeryVerbose ) Time[n][1] += Abc_Clock() - clk; if ( status < 0 ) goto cleanup; // timeout // collect cube Vec_StrPop( vSop[n] ); Start = Vec_StrSize( vSop[n] ); Vec_StrFillExtra( vSop[n], Start + nVars + 4, '-' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 0, ' ' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 1, (char)(n ? '0' : '1') ); Vec_StrWriteEntry( vSop[n], Start + nVars + 2, '\n' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 3, '\0' ); Vec_IntClear( vCube ); Vec_IntForEachEntry( vNums, iVar, v ) { iLit = Vec_IntEntry( vLits, iVar ); Vec_IntPush( vCube, Abc_LitNot(iLit) ); if ( fReverse ) Vec_StrWriteEntry( vSop[n], Start + nVars - iVar - 1, (char)('0' + !Abc_LitIsCompl(iLit)) ); else Vec_StrWriteEntry( vSop[n], Start + iVar, (char)('0' + !Abc_LitIsCompl(iLit)) ); } // add cube status = sat_solver_addclause( pSat[n], Vec_IntArray(vCube), Vec_IntLimit(vCube) ); if ( status == 0 ) { fComplete[n] = 1; break; } assert( status == 1 ); } if ( fComplete[0] || fComplete[1] ) break; } cleanup: Vec_IntFree( vVars ); Vec_IntFree( vLits ); Vec_IntFree( vLitsC[0] ); Vec_IntFree( vLitsC[1] ); Vec_IntFree( vNums ); Vec_IntFree( vCube ); assert( !fComplete[0] || !fComplete[1] ); if ( fComplete[0] || fComplete[1] ) // one of the cover is computed { vRes = vSop[fComplete[1]]; vSop[fComplete[1]] = NULL; if ( iCube > 1 ) // Bmc_CollapseIrredundant( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); Bmc_CollapseIrredundantFull( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); } if ( fVeryVerbose ) { int fProfile = 0; printf( "Processed output with %d supp vars. ", nVars ); if ( vRes == NULL ) printf( "The resulting SOP exceeded %d cubes.\n", nCubeLim ); else printf( "The best cover contains %d cubes.\n", Vec_StrSize(vRes)/(nVars +3) ); Abc_PrintTime( 1, "Onset minterm", Time[0][0] ); Abc_PrintTime( 1, "Onset expand ", Time[0][1] ); Abc_PrintTime( 1, "Offset minterm", Time[1][0] ); Abc_PrintTime( 1, "Offset expand ", Time[1][1] ); if ( fProfile ) { Abc_PrintTime( 1, "Expand check1 ", clkCheck1 ); clkCheck1 = 0; Abc_PrintTime( 1, "Expand check2 ", clkCheck2 ); clkCheck2 = 0; Abc_PrintTime( 1, "Expand sat ", clkCheckS ); clkCheckS = 0; Abc_PrintTime( 1, "Expand unsat ", clkCheckU ); clkCheckU = 0; } } Vec_StrFreeP( &vSop[0] ); Vec_StrFreeP( &vSop[1] ); return vRes; } Vec_Str_t * Bmc_CollapseOne3( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { 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); sat_solver * pSat3 = (sat_solver *)Cnf_DataWriteIntoSolver(pCnf, 1, 0); Vec_Str_t * vSop = Bmc_CollapseOne_int3( pSat0, pSat1, pSat2, pSat3, Gia_ManCiNum(p), nCubeLim, nBTLimit, fCanon, fReverse, fVerbose ); sat_solver_delete( pSat0 ); sat_solver_delete( pSat1 ); sat_solver_delete( pSat2 ); sat_solver_delete( pSat3 ); Cnf_DataFree( pCnf ); return vSop; } /**Function************************************************************* Synopsis [This code computes on-set and off-set simultaneously.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Bmc_CollapseOne_int2( sat_solver * pSat1, sat_solver * pSat2, int nVars, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { int fVeryVerbose = fVerbose; sat_solver * pSat[2] = { pSat1, pSat2 }; Vec_Str_t * vSop[2] = { Vec_StrAlloc(1000), Vec_StrAlloc(1000) }, * vRes = NULL; Vec_Int_t * vVars = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vLits = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vNums = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vCube = Vec_IntAlloc( nVars+1 ); int n, v, iVar, pLits[2], iCube = 0, Start, status; abctime clk = 0, Time[2][2] = {{0}}; int fComplete[2] = {0}; // variables int iOutVar = 2; int iOOVars[2] = {0, 1}; // int iOutVar = 1; // int iOOVars[2] = {sat_solver_nvars(pSat) - 5, sat_solver_nvars(pSat) - 5 + 1}; // collect CI variables (0 = onset enable, 1 = offset enable, 2 = output) int iCiVarBeg = 3; // int iCiVarBeg = sat_solver_nvars(pSat) - 5 - nVars; if ( fReverse ) for ( v = nVars - 1; v >= 0; v-- ) Vec_IntPush( vVars, iCiVarBeg + v ); else for ( v = 0; v < nVars; v++ ) Vec_IntPush( vVars, iCiVarBeg + v ); // check that on-set/off-set is sat for ( n = 0; n < 2; n++ ) { pLits[0] = Abc_Var2Lit( iOutVar, n ); // n=0 => F=1 n=1 => F=0 status = sat_solver_solve( pSat[n], pLits, pLits + 1, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { Vec_StrClear( vSop[0] ); Vec_StrPrintStr( vSop[0], n ? " 1\n" : " 0\n" ); Vec_StrPush( vSop[0], '\0' ); fComplete[0] = 1; goto cleanup; // const0/1 } // add literals to the solver status = sat_solver_addclause( pSat[n], pLits, pLits + 1 ); assert( status ); // start cover Vec_StrPush( vSop[n], '\0' ); } // compute cube pairs for ( iCube = 0; nCubeLim == 0 || iCube < nCubeLim; iCube++ ) { for ( n = 0; n < 2; n++ ) { if ( fVeryVerbose ) clk = Abc_Clock(); // get the assignment sat_solver_clean_polarity( pSat[n], Vec_IntArray(vVars), Vec_IntSize(vVars) ); pLits[0] = Abc_Var2Lit( iOOVars[n], 1 ); // enable clauses // pLits[1] = Abc_Var2Lit( iOutVar, n ); // set output // status = sat_solver_solve( pSat, pLits, pLits + 2, 0, 0, 0, 0 ); status = sat_solver_solve( pSat[n], pLits, pLits + 1, 0, 0, 0, 0 ); if ( fVeryVerbose ) Time[n][0] += Abc_Clock() - clk; if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { fComplete[n] = 1; break; } // collect values Vec_IntClear( vLits ); Vec_IntForEachEntry( vVars, iVar, v ) Vec_IntPush( vLits, Abc_Var2Lit(iVar, !sat_solver_var_value(pSat[n], iVar)) ); // expand the values if ( fVeryVerbose ) clk = Abc_Clock(); // status = Bmc_CollapseExpand( pSat, NULL, vLits, vNums, vCube, nBTLimit, fCanon, Abc_Var2Lit(iOutVar, !n) ); status = Bmc_CollapseExpand( pSat[!n], NULL, vLits, vNums, vCube, nBTLimit, fCanon, -1 ); if ( fVeryVerbose ) Time[n][1] += Abc_Clock() - clk; if ( status < 0 ) goto cleanup; // timeout // collect cube Vec_StrPop( vSop[n] ); Start = Vec_StrSize( vSop[n] ); Vec_StrFillExtra( vSop[n], Start + nVars + 4, '-' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 0, ' ' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 1, (char)(n ? '0' : '1') ); Vec_StrWriteEntry( vSop[n], Start + nVars + 2, '\n' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 3, '\0' ); Vec_IntClear( vCube ); Vec_IntPush( vCube, Abc_Var2Lit( iOOVars[n], 0 ) ); Vec_IntForEachEntry( vNums, iVar, v ) { int iLit = Vec_IntEntry( vLits, iVar ); Vec_IntPush( vCube, Abc_LitNot(iLit) ); if ( fReverse ) Vec_StrWriteEntry( vSop[n], Start + nVars - iVar - 1, (char)('0' + !Abc_LitIsCompl(iLit)) ); else Vec_StrWriteEntry( vSop[n], Start + iVar, (char)('0' + !Abc_LitIsCompl(iLit)) ); } // add cube // status = sat_solver_addclause( pSat, Vec_IntArray(vCube), Vec_IntLimit(vCube) ); status = sat_solver_addclause( pSat[n], Vec_IntArray(vCube), Vec_IntLimit(vCube) ); if ( status == 0 ) { fComplete[n] = 1; break; } assert( status == 1 ); } if ( fComplete[0] || fComplete[1] ) break; } cleanup: Vec_IntFree( vVars ); Vec_IntFree( vLits ); Vec_IntFree( vNums ); Vec_IntFree( vCube ); assert( !fComplete[0] || !fComplete[1] ); if ( fComplete[0] || fComplete[1] ) // one of the cover is computed { vRes = vSop[fComplete[1]]; vSop[fComplete[1]] = NULL; if ( iCube > 1 ) // Bmc_CollapseIrredundant( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); Bmc_CollapseIrredundantFull( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); } if ( fVeryVerbose ) { int fProfile = 0; printf( "Processed output with %d supp vars. ", nVars ); if ( vRes == NULL ) printf( "The resulting SOP exceeded %d cubes.\n", nCubeLim ); else printf( "The best cover contains %d cubes.\n", Vec_StrSize(vRes)/(nVars +3) ); Abc_PrintTime( 1, "Onset minterm", Time[0][0] ); Abc_PrintTime( 1, "Onset expand ", Time[0][1] ); Abc_PrintTime( 1, "Offset minterm", Time[1][0] ); Abc_PrintTime( 1, "Offset expand ", Time[1][1] ); if ( fProfile ) { Abc_PrintTime( 1, "Expand check1 ", clkCheck1 ); clkCheck1 = 0; Abc_PrintTime( 1, "Expand check2 ", clkCheck2 ); clkCheck2 = 0; Abc_PrintTime( 1, "Expand sat ", clkCheckS ); clkCheckS = 0; Abc_PrintTime( 1, "Expand unsat ", clkCheckU ); clkCheckU = 0; } } Vec_StrFreeP( &vSop[0] ); Vec_StrFreeP( &vSop[1] ); return vRes; } /**Function************************************************************* Synopsis [This code computes on-set and off-set simultaneously.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Str_t * Bmc_CollapseOne_int( sat_solver * pSat, int nVars, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { int fVeryVerbose = fVerbose; Vec_Str_t * vSop[2] = { Vec_StrAlloc(1000), Vec_StrAlloc(1000) }, * vRes = NULL; Vec_Int_t * vVars = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vLits = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vNums = Vec_IntAlloc( nVars+1 ); Vec_Int_t * vCube = Vec_IntAlloc( nVars+1 ); int n, v, iVar, pLits[2], iCube = 0, Start, status; abctime clk = 0, Time[2][2] = {{0}}; int fComplete[2] = {0}; // variables int iOutVar = 2; int iOOVars[2] = {0, 1}; // int iOutVar = 1; // int iOOVars[2] = {sat_solver_nvars(pSat) - 5, sat_solver_nvars(pSat) - 5 + 1}; // collect CI variables (0 = onset enable, 1 = offset enable, 2 = output) int iCiVarBeg = 3; // int iCiVarBeg = sat_solver_nvars(pSat) - 5 - nVars; if ( fReverse ) for ( v = nVars - 1; v >= 0; v-- ) Vec_IntPush( vVars, iCiVarBeg + v ); else for ( v = 0; v < nVars; v++ ) Vec_IntPush( vVars, iCiVarBeg + v ); // check that on-set/off-set is sat for ( n = 0; n < 2; n++ ) { pLits[0] = Abc_Var2Lit( iOutVar, n ); // n=0 => F=1 n=1 => F=0 status = sat_solver_solve( pSat, pLits, pLits + 1, nBTLimit, 0, 0, 0 ); if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { Vec_StrClear( vSop[0] ); Vec_StrPrintStr( vSop[0], n ? " 1\n" : " 0\n" ); Vec_StrPush( vSop[0], '\0' ); fComplete[0] = 1; goto cleanup; // const0/1 } // start cover Vec_StrPush( vSop[n], '\0' ); } // compute cube pairs for ( iCube = 0; nCubeLim == 0 || iCube < nCubeLim; iCube++ ) { for ( n = 0; n < 2; n++ ) { if ( fVeryVerbose ) clk = Abc_Clock(); // get the assignment sat_solver_clean_polarity( pSat, Vec_IntArray(vVars), Vec_IntSize(vVars) ); pLits[0] = Abc_Var2Lit( iOutVar, n ); // set output pLits[1] = Abc_Var2Lit( iOOVars[n], 1 ); // enable clauses status = sat_solver_solve( pSat, pLits, pLits + 2, 0, 0, 0, 0 ); if ( fVeryVerbose ) Time[n][0] += Abc_Clock() - clk; if ( status == l_Undef ) goto cleanup; // timeout if ( status == l_False ) { fComplete[n] = 1; break; } // collect values Vec_IntClear( vLits ); Vec_IntForEachEntry( vVars, iVar, v ) Vec_IntPush( vLits, Abc_Var2Lit(iVar, !sat_solver_var_value(pSat, iVar)) ); // expand the values if ( fVeryVerbose ) clk = Abc_Clock(); status = Bmc_CollapseExpand( pSat, NULL, vLits, vNums, vCube, nBTLimit, fCanon, Abc_Var2Lit(iOutVar, !n) ); if ( fVeryVerbose ) Time[n][1] += Abc_Clock() - clk; if ( status < 0 ) goto cleanup; // timeout // collect cube Vec_StrPop( vSop[n] ); Start = Vec_StrSize( vSop[n] ); Vec_StrFillExtra( vSop[n], Start + nVars + 4, '-' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 0, ' ' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 1, (char)(n ? '0' : '1') ); Vec_StrWriteEntry( vSop[n], Start + nVars + 2, '\n' ); Vec_StrWriteEntry( vSop[n], Start + nVars + 3, '\0' ); Vec_IntClear( vCube ); Vec_IntPush( vCube, Abc_Var2Lit( iOOVars[n], 0 ) ); Vec_IntForEachEntry( vNums, iVar, v ) { int iLit = Vec_IntEntry( vLits, iVar ); Vec_IntPush( vCube, Abc_LitNot(iLit) ); if ( fReverse ) Vec_StrWriteEntry( vSop[n], Start + nVars - iVar - 1, (char)('0' + !Abc_LitIsCompl(iLit)) ); else Vec_StrWriteEntry( vSop[n], Start + iVar, (char)('0' + !Abc_LitIsCompl(iLit)) ); } // add cube status = sat_solver_addclause( pSat, Vec_IntArray(vCube), Vec_IntLimit(vCube) ); if ( status == 0 ) { fComplete[n] = 1; break; } assert( status == 1 ); } if ( fComplete[0] || fComplete[1] ) break; } cleanup: Vec_IntFree( vVars ); Vec_IntFree( vLits ); Vec_IntFree( vNums ); Vec_IntFree( vCube ); assert( !fComplete[0] || !fComplete[1] ); if ( fComplete[0] || fComplete[1] ) // one of the cover is computed { vRes = vSop[fComplete[1]]; vSop[fComplete[1]] = NULL; if ( iCube > 1 ) // Bmc_CollapseIrredundant( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); Bmc_CollapseIrredundantFull( vRes, Vec_StrSize(vRes)/(nVars +3), nVars ); } if ( fVeryVerbose ) { int fProfile = 0; printf( "Processed output with %d supp vars. ", nVars ); if ( vRes == NULL ) printf( "The resulting SOP exceeded %d cubes.\n", nCubeLim ); else printf( "The best cover contains %d cubes.\n", Vec_StrSize(vRes)/(nVars +3) ); Abc_PrintTime( 1, "Onset minterm", Time[0][0] ); Abc_PrintTime( 1, "Onset expand ", Time[0][1] ); Abc_PrintTime( 1, "Offset minterm", Time[1][0] ); Abc_PrintTime( 1, "Offset expand ", Time[1][1] ); if ( fProfile ) { Abc_PrintTime( 1, "Expand check1 ", clkCheck1 ); clkCheck1 = 0; Abc_PrintTime( 1, "Expand check2 ", clkCheck2 ); clkCheck2 = 0; Abc_PrintTime( 1, "Expand sat ", clkCheckS ); clkCheckS = 0; Abc_PrintTime( 1, "Expand unsat ", clkCheckU ); clkCheckU = 0; } } Vec_StrFreeP( &vSop[0] ); Vec_StrFreeP( &vSop[1] ); return vRes; } Vec_Str_t * Bmc_CollapseOne( Gia_Man_t * p, int nCubeLim, int nBTLimit, int fCanon, int fReverse, int fVerbose ) { 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 ); Cnf_DataFree( pCnf ); return vSop; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END