/**CFile**************************************************************** FileName [aigRepar.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [AIG package.] Synopsis [Interpolation-based reparametrization.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - April 28, 2007.] Revision [$Id: aigRepar.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] ***********************************************************************/ #include "aig.h" #include "sat/cnf/cnf.h" #include "sat/bsat/satSolver2.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Adds buffer to the solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Aig_ManInterAddBuffer( sat_solver2 * pSat, int iVarA, int iVarB, int fCompl, int fMark ) { lit Lits[2]; int Cid; assert( iVarA >= 0 && iVarB >= 0 ); Lits[0] = toLitCond( iVarA, 0 ); Lits[1] = toLitCond( iVarB, !fCompl ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); Lits[0] = toLitCond( iVarA, 1 ); Lits[1] = toLitCond( iVarB, fCompl ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); } /**Function************************************************************* Synopsis [Adds constraints for the two-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Aig_ManInterAddXor( sat_solver2 * pSat, int iVarA, int iVarB, int iVarC, int fCompl, int fMark ) { lit Lits[3]; int Cid; assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 ); Lits[0] = toLitCond( iVarA, !fCompl ); Lits[1] = toLitCond( iVarB, 1 ); Lits[2] = toLitCond( iVarC, 1 ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); Lits[0] = toLitCond( iVarA, !fCompl ); Lits[1] = toLitCond( iVarB, 0 ); Lits[2] = toLitCond( iVarC, 0 ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); Lits[0] = toLitCond( iVarA, fCompl ); Lits[1] = toLitCond( iVarB, 1 ); Lits[2] = toLitCond( iVarC, 0 ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); Lits[0] = toLitCond( iVarA, fCompl ); Lits[1] = toLitCond( iVarB, 0 ); Lits[2] = toLitCond( iVarC, 1 ); Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); if ( fMark ) clause2_set_partA( pSat, Cid, 1 ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManInterTest( Aig_Man_t * pMan, int fVerbose ) { sat_solver2 * pSat; // Aig_Man_t * pInter; word * pInter; Vec_Int_t * vVars; Cnf_Dat_t * pCnf; Aig_Obj_t * pObj; int Lit, Cid, Var, status, i; clock_t clk = clock(); assert( Aig_ManRegNum(pMan) == 0 ); assert( Aig_ManCoNum(pMan) == 1 ); // derive CNFs pCnf = Cnf_Derive( pMan, 1 ); // start the solver pSat = sat_solver2_new(); sat_solver2_setnvars( pSat, 2*pCnf->nVars+1 ); // set A-variables (all used except PI/PO) Aig_ManForEachObj( pMan, pObj, i ) { if ( pCnf->pVarNums[pObj->Id] < 0 ) continue; if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsCo(pObj) ) var_set_partA( pSat, pCnf->pVarNums[pObj->Id], 1 ); } // add clauses of A for ( i = 0; i < pCnf->nClauses; i++ ) { Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); clause2_set_partA( pSat, Cid, 1 ); } // add clauses of B Cnf_DataLift( pCnf, pCnf->nVars ); for ( i = 0; i < pCnf->nClauses; i++ ) sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); Cnf_DataLift( pCnf, -pCnf->nVars ); // add PI equality clauses vVars = Vec_IntAlloc( Aig_ManCoNum(pMan)+1 ); Aig_ManForEachCi( pMan, pObj, i ) { if ( Aig_ObjRefs(pObj) == 0 ) continue; Var = pCnf->pVarNums[pObj->Id]; Aig_ManInterAddBuffer( pSat, Var, pCnf->nVars + Var, 0, 0 ); Vec_IntPush( vVars, Var ); } // add an XOR clause in the end Var = pCnf->pVarNums[Aig_ManCo(pMan,0)->Id]; Aig_ManInterAddXor( pSat, Var, pCnf->nVars + Var, 2*pCnf->nVars, 0, 0 ); Vec_IntPush( vVars, Var ); // solve the problem Lit = toLitCond( 2*pCnf->nVars, 0 ); status = sat_solver2_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 ); assert( status == l_False ); Sat_Solver2PrintStats( stdout, pSat ); // derive interpolant // pInter = Sat_ProofInterpolant( pSat, vVars ); // Aig_ManPrintStats( pInter ); // Aig_ManDumpBlif( pInter, "int.blif", NULL, NULL ); //pInter = Sat_ProofInterpolantTruth( pSat, vVars ); pInter = NULL; // Extra_PrintHex( stdout, pInter, Vec_IntSize(vVars) ); printf( "\n" ); // clean up // Aig_ManStop( pInter ); ABC_FREE( pInter ); Vec_IntFree( vVars ); Cnf_DataFree( pCnf ); sat_solver2_delete( pSat ); ABC_PRT( "Total interpolation time", clock() - clk ); } /**Function************************************************************* Synopsis [Duplicates AIG while mapping PIs into the given array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_ManAppend( Aig_Man_t * pBase, Aig_Man_t * pNew ) { Aig_Obj_t * pObj; int i; assert( Aig_ManCoNum(pNew) == 1 ); assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(pBase) ); // create the PIs Aig_ManCleanData( pNew ); Aig_ManConst1(pNew)->pData = Aig_ManConst1(pBase); Aig_ManForEachCi( pNew, pObj, i ) pObj->pData = Aig_IthVar(pBase, i); // duplicate internal nodes Aig_ManForEachNode( pNew, pObj, i ) pObj->pData = Aig_And( pBase, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); // add one PO to base pObj = Aig_ManCo( pNew, 0 ); Aig_ObjCreateCo( pBase, Aig_ObjChild0Copy(pObj) ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Aig_ManInterRepar( Aig_Man_t * pMan, int fVerbose ) { Aig_Man_t * pAigTemp, * pInter, * pBase = NULL; sat_solver2 * pSat; Vec_Int_t * vVars; Cnf_Dat_t * pCnf, * pCnfInter; Aig_Obj_t * pObj; int nOuts = Aig_ManCoNum(pMan); int ShiftP[2], ShiftCnf[2], ShiftOr[2], ShiftAssume; int Cid, Lit, status, i, k, c; clock_t clk = clock(); assert( Aig_ManRegNum(pMan) == 0 ); // derive CNFs pCnf = Cnf_Derive( pMan, nOuts ); // start the solver pSat = sat_solver2_new(); sat_solver2_setnvars( pSat, 4*pCnf->nVars + 6*nOuts ); // vars: pGlobal + (p0 + A1 + A2 + or0) + (p1 + B1 + B2 + or1) + pAssume; ShiftP[0] = nOuts; ShiftP[1] = 2*pCnf->nVars + 3*nOuts; ShiftCnf[0] = ShiftP[0] + nOuts; ShiftCnf[1] = ShiftP[1] + nOuts; ShiftOr[0] = ShiftCnf[0] + 2*pCnf->nVars; ShiftOr[1] = ShiftCnf[1] + 2*pCnf->nVars; ShiftAssume = ShiftOr[1] + nOuts; assert( ShiftAssume + nOuts == pSat->size ); // mark variables of A for ( i = ShiftCnf[0]; i < ShiftP[1]; i++ ) var_set_partA( pSat, i, 1 ); // add clauses of A, then B vVars = Vec_IntAlloc( 2*nOuts ); for ( k = 0; k < 2; k++ ) { // copy A1 Cnf_DataLift( pCnf, ShiftCnf[k] ); for ( i = 0; i < pCnf->nClauses; i++ ) { Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); clause2_set_partA( pSat, Cid, k==0 ); } // add equality p[k] == A1/B1 Aig_ManForEachCo( pMan, pObj, i ) Aig_ManInterAddBuffer( pSat, ShiftP[k] + i, pCnf->pVarNums[pObj->Id], k==1, k==0 ); // copy A2 Cnf_DataLift( pCnf, pCnf->nVars ); for ( i = 0; i < pCnf->nClauses; i++ ) { Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); clause2_set_partA( pSat, Cid, k==0 ); } // add comparator (!p[k] ^ A2/B2) == or[k] Vec_IntClear( vVars ); Aig_ManForEachCo( pMan, pObj, i ) { Aig_ManInterAddXor( pSat, ShiftP[k] + i, pCnf->pVarNums[pObj->Id], ShiftOr[k] + i, k==1, k==0 ); Vec_IntPush( vVars, toLitCond(ShiftOr[k] + i, 1) ); } Cid = sat_solver2_addclause( pSat, Vec_IntArray(vVars), Vec_IntArray(vVars) + Vec_IntSize(vVars), 0 ); clause2_set_partA( pSat, Cid, k==0 ); // return to normal Cnf_DataLift( pCnf, -ShiftCnf[k]-pCnf->nVars ); } // add clauses to constrain p[0] and p[1] for ( k = 0; k < nOuts; k++ ) Aig_ManInterAddXor( pSat, ShiftP[0] + k, ShiftP[1] + k, ShiftAssume + k, 0, 0 ); // start the interpolant pBase = Aig_ManStart( 1000 ); pBase->pName = Abc_UtilStrsav( "repar" ); for ( k = 0; k < 2*nOuts; k++ ) Aig_IthVar(pBase, i); // start global variables (pGlobal and p[0]) Vec_IntClear( vVars ); for ( k = 0; k < 2*nOuts; k++ ) Vec_IntPush( vVars, k ); // perform iterative solving // vars: pGlobal + (p0 + A1 + A2 + or0) + (p1 + B1 + B2 + or1) + pAssume; for ( k = 0; k < nOuts; k++ ) { // swap k-th variables int Temp = Vec_IntEntry( vVars, k ); Vec_IntWriteEntry( vVars, k, Vec_IntEntry(vVars, nOuts+k) ); Vec_IntWriteEntry( vVars, nOuts+k, Temp ); // solve incrementally Lit = toLitCond( ShiftAssume + k, 1 ); // XOR output is 0 ==> p1 == p2 status = sat_solver2_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 ); assert( status == l_False ); Sat_Solver2PrintStats( stdout, pSat ); // derive interpolant pInter = (Aig_Man_t *)Sat_ProofInterpolant( pSat, vVars ); Aig_ManPrintStats( pInter ); // make sure interpolant does not depend on useless vars Aig_ManForEachCi( pInter, pObj, i ) assert( i <= k || Aig_ObjRefs(pObj) == 0 ); // simplify pInter = Dar_ManRwsat( pAigTemp = pInter, 1, 0 ); Aig_ManStop( pAigTemp ); // add interpolant to the solver pCnfInter = Cnf_Derive( pInter, 1 ); Cnf_DataLift( pCnfInter, pSat->size ); sat_solver2_setnvars( pSat, pSat->size + 2*pCnfInter->nVars ); for ( i = 0; i < pCnfInter->nVars; i++ ) var_set_partA( pSat, pSat->size-2*pCnfInter->nVars + i, 1 ); for ( c = 0; c < 2; c++ ) { if ( c == 1 ) Cnf_DataLift( pCnfInter, pCnfInter->nVars ); // add to A for ( i = 0; i < pCnfInter->nClauses; i++ ) { Cid = sat_solver2_addclause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1], 0 ); clause2_set_partA( pSat, Cid, c==0 ); } // connect to the inputs Aig_ManForEachCi( pInter, pObj, i ) if ( i <= k ) Aig_ManInterAddBuffer( pSat, i, pCnf->pVarNums[pObj->Id], 0, c==0 ); // connect to the outputs pObj = Aig_ManCo(pInter, 0); Aig_ManInterAddBuffer( pSat, ShiftP[c] + k, pCnf->pVarNums[pObj->Id], 0, c==0 ); if ( c == 1 ) Cnf_DataLift( pCnfInter, -pCnfInter->nVars ); } Cnf_DataFree( pCnfInter ); // accumulate Aig_ManAppend( pBase, pInter ); Aig_ManStop( pInter ); // update global variables Temp = Vec_IntEntry( vVars, k ); Vec_IntWriteEntry( vVars, k, Vec_IntEntry(vVars, nOuts+k) ); Vec_IntWriteEntry( vVars, nOuts+k, Temp ); } Vec_IntFree( vVars ); Cnf_DataFree( pCnf ); sat_solver2_delete( pSat ); ABC_PRT( "Reparameterization time", clock() - clk ); return pBase; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END