/********************* */ /*! \file bitblaster.h ** \verbatim ** Original author: Liana Hadarean ** Major contributors: none ** Minor contributors (to current version): lianah, Morgan Deters, Dejan Jovanovic ** This file is part of the CVC4 project. ** Copyright (c) 2009-2013 New York University and The University of Iowa ** See the file COPYING in the top-level source directory for licensing ** information.\endverbatim ** ** \brief Wrapper around the SAT solver used for bitblasting ** ** Wrapper around the SAT solver used for bitblasting. **/ #include "cvc4_private.h" #ifndef __CVC4__BITBLASTER_TEMPLATE_H #define __CVC4__BITBLASTER_TEMPLATE_H #include "expr/node.h" #include #include #include "context/cdhashmap.h" #include "bitblast_strategies_template.h" #include "prop/sat_solver.h" #include "theory/valuation.h" class Abc_Obj_t_; typedef Abc_Obj_t_ Abc_Obj_t; class Abc_Ntk_t_; typedef Abc_Ntk_t_ Abc_Ntk_t; class Abc_Aig_t_; typedef Abc_Aig_t_ Abc_Aig_t; class Cnf_Dat_t_; typedef Cnf_Dat_t_ Cnf_Dat_t; namespace CVC4 { namespace prop { class CnfStream; class BVSatSolverInterface; class NullRegistrar; } namespace theory { class OutputChannel; class TheoryModel; namespace bv { class BitblastingRegistrar; typedef __gnu_cxx::hash_set NodeSet; class AbstractionModule; /** * The Bitblaster that manages the mapping between Nodes * and their bitwise definition * */ template class TBitblaster { protected: typedef std::vector Bits; typedef __gnu_cxx::hash_map TermDefMap; typedef __gnu_cxx::hash_set AtomSet; typedef void (*TermBBStrategy) (TNode, Bits&, TBitblaster*); typedef T (*AtomBBStrategy) (TNode, TBitblaster*); // caches and mappings TermDefMap d_termCache; void initAtomBBStrategies(); void initTermBBStrategies(); protected: /// function tables for the various bitblasting strategies indexed by node kind TermBBStrategy d_termBBStrategies[kind::LAST_KIND]; AtomBBStrategy d_atomBBStrategies[kind::LAST_KIND]; public: TBitblaster(); virtual ~TBitblaster() {} virtual void bbAtom(TNode node) = 0; virtual void bbTerm(TNode node, Bits& bits) = 0; virtual void makeVariable(TNode node, Bits& bits) = 0; virtual T getBBAtom(TNode atom) const = 0; virtual bool hasBBAtom(TNode atom) const = 0; virtual void storeBBAtom(TNode atom, T atom_bb) = 0; bool hasBBTerm(TNode node) const; void getBBTerm(TNode node, Bits& bits) const; void storeBBTerm(TNode term, const Bits& bits); }; class TheoryBV; class TLazyBitblaster : public TBitblaster { typedef std::vector Bits; typedef __gnu_cxx::hash_set VarSet; typedef __gnu_cxx::hash_set AtomSet; typedef context::CDList AssertionList; typedef context::CDHashMap , prop::SatLiteralHashFunction> ExplanationMap; /** This class gets callbacks from minisat on propagations */ class MinisatNotify : public prop::BVSatSolverInterface::Notify { prop::CnfStream* d_cnf; TheoryBV *d_bv; TLazyBitblaster* d_lazyBB; public: MinisatNotify(prop::CnfStream* cnf, TheoryBV *bv, TLazyBitblaster* lbv) : d_cnf(cnf) , d_bv(bv) , d_lazyBB(lbv) {} bool notify(prop::SatLiteral lit); void notify(prop::SatClause& clause); void safePoint(); }; TheoryBV *d_bv; context::Context* d_ctx; prop::NullRegistrar* d_nullRegistrar; context::Context* d_nullContext; // sat solver used for bitblasting and associated CnfStream prop::BVSatSolverInterface* d_satSolver; prop::CnfStream* d_cnfStream; AssertionList d_assertedAtoms; /**< context dependent list storing the atoms currently asserted by the DPLL SAT solver. */ ExplanationMap d_explanations; /**< context dependent list of explanations for the propagated literals. Only used when bvEagerPropagate option enabled. */ VarSet d_variables; AtomSet d_bbAtoms; AbstractionModule* d_abstraction; bool d_emptyNotify; void addAtom(TNode atom); bool hasValue(TNode a); public: void bbTerm(TNode node, Bits& bits); void bbAtom(TNode node); Node getBBAtom(TNode atom) const; void storeBBAtom(TNode atom, Node atom_bb); bool hasBBAtom(TNode atom) const; TLazyBitblaster(context::Context* c, bv::TheoryBV* bv, const std::string name="", bool emptyNotify = false); ~TLazyBitblaster(); /** * Pushes the assumption literal associated with node to the SAT * solver assumption queue. * * @param node assumption * @param propagate run bcp or not * * @return false if a conflict detected */ bool assertToSat(TNode node, bool propagate = true); bool propagate(); bool solve(); prop::SatValue solveWithBudget(unsigned long conflict_budget); void getConflict(std::vector& conflict); void explain(TNode atom, std::vector& explanation); void setAbstraction(AbstractionModule* abs); theory::EqualityStatus getEqualityStatus(TNode a, TNode b); /** * Return a constant Node representing the value of a variable * in the current model. * @param a * * @return */ Node getVarValue(TNode a, bool fullModel=true); /** * Adds a constant value for each bit-blasted variable in the model. * * @param m the model * @param fullModel whether to create a "full model," i.e., add * constants to equivalence classes that don't already have them */ void collectModelInfo(TheoryModel* m, bool fullModel); typedef VarSet::const_iterator vars_iterator; vars_iterator beginVars() { return d_variables.begin(); } vars_iterator endVars() { return d_variables.end(); } /** * Creates the bits corresponding to the variable (or non-bv term). * * @param var */ void makeVariable(TNode var, Bits& bits); bool isSharedTerm(TNode node); uint64_t computeAtomWeight(TNode node, NodeSet& seen); /** * Deletes SatSolver and CnfCache, but maintains bit-blasting * terms cache. * */ void clearSolver(); private: class Statistics { public: IntStat d_numTermClauses, d_numAtomClauses; IntStat d_numTerms, d_numAtoms; IntStat d_numExplainedPropagations; IntStat d_numBitblastingPropagations; TimerStat d_bitblastTimer; Statistics(const std::string& name); ~Statistics(); }; std::string d_name; Statistics d_statistics; }; class MinisatEmptyNotify : public prop::BVSatSolverInterface::Notify { public: MinisatEmptyNotify() {} bool notify(prop::SatLiteral lit) { return true; } void notify(prop::SatClause& clause) { } void safePoint() {} }; class EagerBitblaster : public TBitblaster { typedef __gnu_cxx::hash_set TNodeSet; // sat solver used for bitblasting and associated CnfStream prop::BVSatSolverInterface* d_satSolver; BitblastingRegistrar* d_bitblastingRegistrar; context::Context* d_nullContext; prop::CnfStream* d_cnfStream; TNodeSet d_bbAtoms; public: void addAtom(TNode atom); void makeVariable(TNode node, Bits& bits); void bbTerm(TNode node, Bits& bits); void bbAtom(TNode node); Node getBBAtom(TNode node) const; bool hasBBAtom(TNode atom) const; void bbFormula(TNode formula); void storeBBAtom(TNode atom, Node atom_bb); EagerBitblaster(); ~EagerBitblaster(); bool assertToSat(TNode node, bool propagate = true); bool solve(); }; class AigBitblaster : public TBitblaster { typedef std::hash_map TNodeAigMap; typedef std::hash_map NodeAigMap; static Abc_Ntk_t* abcAigNetwork; context::Context* d_nullContext; prop::BVSatSolverInterface* d_satSolver; TNodeAigMap d_aigCache; NodeAigMap d_bbAtoms; NodeAigMap d_nodeToAigInput; // the thing we are checking for sat Abc_Obj_t* d_aigOutputNode; void addAtom(TNode atom); void simplifyAig(); void storeBBAtom(TNode atom, Abc_Obj_t* atom_bb); Abc_Obj_t* getBBAtom(TNode atom) const; bool hasBBAtom(TNode atom) const; void cacheAig(TNode node, Abc_Obj_t* aig); bool hasAig(TNode node); Abc_Obj_t* getAig(TNode node); Abc_Obj_t* mkInput(TNode input); bool hasInput(TNode input); void convertToCnfAndAssert(); void assertToSatSolver(Cnf_Dat_t* pCnf); public: AigBitblaster(); ~AigBitblaster(); void makeVariable(TNode node, Bits& bits); void bbTerm(TNode node, Bits& bits); void bbAtom(TNode node); Abc_Obj_t* bbFormula(TNode formula); bool solve(TNode query); static Abc_Aig_t* currentAigM(); static Abc_Ntk_t* currentAigNtk(); private: class Statistics { public: IntStat d_numClauses; IntStat d_numVariables; TimerStat d_simplificationTime; TimerStat d_cnfConversionTime; TimerStat d_solveTime; Statistics(); ~Statistics(); }; Statistics d_statistics; }; // Bitblaster implementation template void TBitblaster::initAtomBBStrategies() { for (int i = 0 ; i < kind::LAST_KIND; ++i ) { d_atomBBStrategies[i] = UndefinedAtomBBStrategy; } /// setting default bb strategies for atoms d_atomBBStrategies [ kind::EQUAL ] = DefaultEqBB; d_atomBBStrategies [ kind::BITVECTOR_ULT ] = DefaultUltBB; d_atomBBStrategies [ kind::BITVECTOR_ULE ] = DefaultUleBB; d_atomBBStrategies [ kind::BITVECTOR_UGT ] = DefaultUgtBB; d_atomBBStrategies [ kind::BITVECTOR_UGE ] = DefaultUgeBB; d_atomBBStrategies [ kind::BITVECTOR_SLT ] = DefaultSltBB; d_atomBBStrategies [ kind::BITVECTOR_SLE ] = DefaultSleBB; d_atomBBStrategies [ kind::BITVECTOR_SGT ] = DefaultSgtBB; d_atomBBStrategies [ kind::BITVECTOR_SGE ] = DefaultSgeBB; } template void TBitblaster::initTermBBStrategies() { for (int i = 0 ; i < kind::LAST_KIND; ++i ) { d_termBBStrategies[i] = DefaultVarBB; } /// setting default bb strategies for terms: d_termBBStrategies [ kind::CONST_BITVECTOR ] = DefaultConstBB; d_termBBStrategies [ kind::BITVECTOR_NOT ] = DefaultNotBB; d_termBBStrategies [ kind::BITVECTOR_CONCAT ] = DefaultConcatBB; d_termBBStrategies [ kind::BITVECTOR_AND ] = DefaultAndBB; d_termBBStrategies [ kind::BITVECTOR_OR ] = DefaultOrBB; d_termBBStrategies [ kind::BITVECTOR_XOR ] = DefaultXorBB; d_termBBStrategies [ kind::BITVECTOR_XNOR ] = DefaultXnorBB; d_termBBStrategies [ kind::BITVECTOR_NAND ] = DefaultNandBB; d_termBBStrategies [ kind::BITVECTOR_NOR ] = DefaultNorBB; d_termBBStrategies [ kind::BITVECTOR_COMP ] = DefaultCompBB; d_termBBStrategies [ kind::BITVECTOR_MULT ] = DefaultMultBB; d_termBBStrategies [ kind::BITVECTOR_PLUS ] = DefaultPlusBB; d_termBBStrategies [ kind::BITVECTOR_SUB ] = DefaultSubBB; d_termBBStrategies [ kind::BITVECTOR_NEG ] = DefaultNegBB; d_termBBStrategies [ kind::BITVECTOR_UDIV ] = UndefinedTermBBStrategy; d_termBBStrategies [ kind::BITVECTOR_UREM ] = UndefinedTermBBStrategy; d_termBBStrategies [ kind::BITVECTOR_UDIV_TOTAL ] = DefaultUdivBB; d_termBBStrategies [ kind::BITVECTOR_UREM_TOTAL ] = DefaultUremBB; d_termBBStrategies [ kind::BITVECTOR_SDIV ] = UndefinedTermBBStrategy; d_termBBStrategies [ kind::BITVECTOR_SREM ] = UndefinedTermBBStrategy; d_termBBStrategies [ kind::BITVECTOR_SMOD ] = UndefinedTermBBStrategy; d_termBBStrategies [ kind::BITVECTOR_SHL ] = DefaultShlBB; d_termBBStrategies [ kind::BITVECTOR_LSHR ] = DefaultLshrBB; d_termBBStrategies [ kind::BITVECTOR_ASHR ] = DefaultAshrBB; d_termBBStrategies [ kind::BITVECTOR_EXTRACT ] = DefaultExtractBB; d_termBBStrategies [ kind::BITVECTOR_REPEAT ] = DefaultRepeatBB; d_termBBStrategies [ kind::BITVECTOR_ZERO_EXTEND ] = DefaultZeroExtendBB; d_termBBStrategies [ kind::BITVECTOR_SIGN_EXTEND ] = DefaultSignExtendBB; d_termBBStrategies [ kind::BITVECTOR_ROTATE_RIGHT ] = DefaultRotateRightBB; d_termBBStrategies [ kind::BITVECTOR_ROTATE_LEFT ] = DefaultRotateLeftBB; } template TBitblaster::TBitblaster() : d_termCache() { initAtomBBStrategies(); initTermBBStrategies(); } template bool TBitblaster::hasBBTerm(TNode node) const { return d_termCache.find(node) != d_termCache.end(); } template void TBitblaster::getBBTerm(TNode node, Bits& bits) const { Assert (hasBBTerm(node)); bits = d_termCache.find(node)->second; } template void TBitblaster::storeBBTerm(TNode node, const Bits& bits) { d_termCache.insert(std::make_pair(node, bits)); } } /* bv namespace */ } /* theory namespace */ } /* CVC4 namespace */ #endif /* __CVC4__BITBLASTER_H */