/*****************************************************************************/ /*! * \file theory_quant.cpp * * Author: Daniel Wichs, Yeting Ge * * Created: Wednesday July 2, 2003 * *
* * License to use, copy, modify, sell and/or distribute this software * and its documentation for any purpose is hereby granted without * royalty, subject to the terms and conditions defined in the \ref * LICENSE file provided with this distribution. * *
* */ /*****************************************************************************/ #include "theory_quant.h" #include "theory_arith.h" #include "theory_array.h" #include "typecheck_exception.h" #include "parser_exception.h" #include "smtlib_exception.h" #include "quant_proof_rules.h" #include "theory_core.h" #include "command_line_flags.h" #include "vcl.h" #include #include #include using namespace std; using namespace CVC3; /////////////////////////////////////////////////////////////////////////////// // TheoryQuant Public Methods // /////////////////////////////////////////////////////////////////////////////// static const Expr null_expr; const int FOUND_FALSE = 1; Trigger::Trigger(TheoryCore* core, Expr e, Polarity pol, std::set boundVars){ trig=e ; polarity=pol; head=null_expr; hasRWOp=false; hasTrans=false; hasT2=false; isSimple=false; isSuperSimple=false; isMulti=false; multiIndex = 99999; multiId = 99999; for(std::set::const_iterator i=boundVars.begin(),iend=boundVars.end(); i!=iend; ++i) bvs.push_back(*i); } bool Trigger::isPos(){ return (Pos==polarity||PosNeg==polarity); } bool Trigger::isNeg(){ return (Neg==polarity || PosNeg==polarity); } std::vector Trigger::getBVs(){ return bvs; } Expr Trigger::getEx(){ return trig; } void Trigger::setHead(Expr h){ head=h; } Expr Trigger::getHead(){ return head; } void Trigger::setRWOp(bool b){ hasRWOp =b ; } bool Trigger::hasRW(){ return hasRWOp; } void Trigger::setTrans(bool b){ hasTrans =b ; } bool Trigger::hasTr(){ return hasTrans; } void Trigger::setTrans2(bool b){ hasT2 =b ; } bool Trigger::hasTr2(){ return hasT2; } void Trigger::setSimp(){ isSimple =true ; } bool Trigger::isSimp(){ return isSimple; } void Trigger::setSuperSimp(){ isSuperSimple =true ; } bool Trigger::isSuperSimp(){ return isSuperSimple; } void Trigger::setMultiTrig(){ isMulti = true ; } bool Trigger::isMultiTrig(){ return isMulti; } dynTrig::dynTrig(Trigger t, ExprMap b, size_t id) :trig(t), univ_id(id), binds(b) {} TheoryQuant::TheoryQuant(TheoryCore* core) //!< Constructor : Theory(core, "Quantified Expressions"), d_univs(core->getCM()->getCurrentContext()), d_rawUnivs(core->getCM()->getCurrentContext()), d_arrayTrigs(core->getCM()->getCurrentContext()), d_lastArrayPos(core->getCM()->getCurrentContext(), 0 , 0), d_lastPredsPos(core->getCM()->getCurrentContext(), 0, 0), d_lastTermsPos(core->getCM()->getCurrentContext(), 0, 0), d_lastPartPredsPos(core->getCM()->getCurrentContext(), 0, 0), d_lastPartTermsPos(core->getCM()->getCurrentContext(), 0, 0), d_univsPartSavedPos(core->getCM()->getCurrentContext(), 0, 0), d_lastPartLevel(core->getCM()->getCurrentContext(), 0, 0), d_usefulGterms(core->getCM()->getCurrentContext()), d_lastUsefulGtermsPos(core->getCM()->getCurrentContext(), 0, 0), d_savedTermsPos(core->getCM()->getCurrentContext(), 0, 0), d_univsSavedPos(core->getCM()->getCurrentContext(), 0, 0), d_rawUnivsSavedPos(core->getCM()->getCurrentContext(), 0, 0), d_univsPosFull(core->getCM()->getCurrentContext(), 0, 0), d_univsContextPos(core->getCM()->getCurrentContext(), 0, 0), d_instCount(core->getCM()->getCurrentContext(), 0,0), d_contextTerms(core->getCM()->getCurrentContext()), d_contextCache(core->getCM()->getCurrentContext()), d_maxQuantInst(&(core->getFlags()["max-quant-inst"].getInt())), d_useNew(&(core->getFlags()["quant-new"].getBool())), d_useLazyInst(&(core->getFlags()["quant-lazy"].getBool())), d_useSemMatch(&(core->getFlags()["quant-sem-match"].getBool())), d_useAtomSem(&(core->getFlags()["quant-const-match"].getBool())), d_translate(&(core->getFlags()["translate"].getBool())), d_useTrigNew(&(core->getFlags()["quant-trig-new"].getBool())), d_usePart(&(core->getFlags()["quant-inst-part"].getBool())), d_useMult(&(core->getFlags()["quant-inst-mult"].getBool())), d_useInstEnd(&(core->getFlags()["quant-inst-end"].getBool())), d_useInstLCache(&(core->getFlags()["quant-inst-lcache"].getBool())), d_useInstGCache(&(core->getFlags()["quant-inst-gcache"].getBool())), d_useInstTrue(&(core->getFlags()["quant-inst-true"].getBool())), d_usePullVar(&(core->getFlags()["quant-pullvar"].getBool())), d_useExprScore(&(core->getFlags()["quant-score"].getBool())), d_useTrigLoop(&(core->getFlags()["quant-trig-loop"].getInt())), d_maxInst(&(core->getFlags()["quant-max-inst"].getInt())), d_useTrans(&(core->getFlags()["quant-trans3"].getBool())), d_useTrans2(&(core->getFlags()["quant-trans2"].getBool())), d_useInstAll(&(core->getFlags()["quant-inst-all"].getBool())), d_usePolarity(&(core->getFlags()["quant-polarity"].getBool())), d_useEqu(&(core->getFlags()["quant-equ"].getBool())), d_maxNaiveCall(&(core->getFlags()["quant-naive-num"].getInt())), d_curMaxExprScore(core->getCM()->getCurrentContext(), (core->getFlags()["quant-max-score"].getInt()),0), d_arrayIndic(core->getCM()->getCurrentContext()), d_exprLastUpdatedPos(core->getCM()->getCurrentContext(),0 ,0), d_trans_found(core->getCM()->getCurrentContext()), d_trans2_found(core->getCM()->getCurrentContext()), null_cdlist(core->getCM()->getCurrentContext()), d_eqs(core->getCM()->getCurrentContext()), d_eqs_pos(core->getCM()->getCurrentContext(), 0, 0), d_allInstCount(core->getStatistics().counter("quantifier instantiations")), d_partCalled(core->getCM()->getCurrentContext(),false,0), d_instHistory(core->getCM()->getCurrentContext()), d_alltrig_list(core->getCM()->getCurrentContext()) { IF_DEBUG(d_univs.setName("CDList[TheoryQuant::d_univs]")); vector kinds; d_instCount = 0; d_cacheThmPos=0; d_trans_num=0; d_trans2_num=0; d_rules=createProofRules(); kinds.push_back(EXISTS); kinds.push_back(FORALL); registerTheory(this, kinds); d_partCalled=false; d_offset_multi_trig=2; d_initMaxScore=(theoryCore()->getFlags()["quant-max-score"].getInt()); for(size_t i=0; inewBoundVarExpr("_genbv", int2string(i), Type::anyType(getEM())); } } //! Destructor TheoryQuant::~TheoryQuant() { if(d_rules != NULL) delete d_rules; for(std::map* ,TypeComp>::iterator it = d_contextMap.begin(), iend = d_contextMap.end(); it!= iend; ++it) { delete it->second; free(it->second); } } int TheoryQuant::getExprScore(const Expr& e){ return theoryCore()->getQuantLevelForTerm(e); } bool isSysPred(const Expr& e){ return ( isLE(e) || isLT(e) || isGE(e) || isGT(e) || e.isEq()); } bool canGetHead(const Expr& e){ return (e.getKind() == APPLY || e.getKind() == READ || e.getKind() == WRITE); } bool isSimpleTrig(const Expr& t){ if(!canGetHead(t)) return false; for(int i = 0; i < t.arity(); i++){ if (t[i].arity()>0 && t[i].containsBoundVar()) return false; if (BOUND_VAR == t[i].getKind()){ for(int j = 0; j < i; j++){ if(t[i] == t[j]) return false; } } } return true; } bool isSuperSimpleTrig(const Expr& t){ if(!isSimpleTrig(t)) return false; for(int i = 0; i < t.arity(); i++){ if (t[i].arity()>0 ) return false; if (BOUND_VAR != t[i].getKind()){ return false; } } return true; } bool usefulInMatch(const Expr& e){ if(e.arity() == 0){ TRACE("usefulInMatch", e.toString()+": ",e.arity(), ""); TRACE("usefulInMatch", e.isRational(), "", ""); } return ( canGetHead(e) || (isSysPred(e) && (!e.isEq()) ) ); } void TheoryQuant::setup(const Expr& e) {} void TheoryQuant::update(const Theorem& t, const Expr& e) { } std::string vectorExpr2string(const std::vector & vec){ std::string buf; for(size_t i=0; i & res) { if(e.getFlag()) return; if(e.isClosure()) return recursiveGetSubTrig(e.getBody(),res); if (e.isApply()|| isSysPred(e)){ res.push_back(e); } else if ( e.isTerm() && (!e.isVar()) && (e.getKind()!=RATIONAL_EXPR) ) { res.push_back(e); } for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { recursiveGetSubTrig(*i,res); } e.setFlag(); return ; } std::vector getSubTrig(const Expr& e){ e.clearFlags(); std::vector res; recursiveGetSubTrig(e,res); e.clearFlags(); TRACE("getsub","e is ", e.toString(),""); TRACE("getsub","have ", res.size()," subterms"); return res; } static void recGetSubTerms(const Expr& e, std::vector & res) { if(e.getFlag()) return; if(e.isClosure()) return recGetSubTerms(e.getBody(),res); for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { recGetSubTerms(*i,res); } res.push_back(e); e.setFlag(); return ; } const std::vector& TheoryQuant::getSubTerms(const Expr& e){ //the last item in res is e itself ExprMap >::iterator iter= d_subTermsMap.find(e); if( d_subTermsMap.end() == iter){ e.clearFlags(); std::vector res; recGetSubTerms(e,res); e.clearFlags(); TRACE("getsubs", "getsubs, e is: ", e, ""); TRACE("getsubs", "e has ", res.size(), " subterms"); d_subTermsMap[e] = res; return d_subTermsMap[e]; } else{ return (*iter).second; } } void TheoryQuant::enqueueInst(const Theorem& univ, const vector& bind, const Expr& gterm){ static int max_score =-1; bool partInst=false; if(bind.size() < univ.getExpr().getVars().size()){ partInst=false; TRACE("sendinst","partinst",partInst,""); } Expr bind_expr(RAW_LIST, bind, getEM()); if (*d_useInstLCache){ const Expr& e = univ.getExpr(); ExprMap*>::iterator iterCache = d_bindHistory.find(e); if (iterCache != d_bindHistory.end()){ CDMap* cache = (*iterCache).second; if(cache->find(bind_expr) !=cache->end()){ return ; } else{ (*cache)[bind_expr] = true; } } else{ CDMap* new_cache = new(true) CDMap (theoryCore()->getCM()->getCurrentContext()); (*new_cache)[bind_expr] = true; } } Theorem thm ; if(null_expr == gterm ){//it is from naive instantiation or multi-inst TRACE("sendinst","gterm",gterm,""); if(partInst) { thm = d_rules->partialUniversalInst(univ, bind, 0); } else{ thm = d_rules->universalInst(univ, bind, 0); } } else{ int gscore = theoryCore()->getQuantLevelForTerm(gterm); if(gscore > max_score){ max_score = gscore; // cout<<"max score "<partialUniversalInst(univ, bind, gscore); } else{ thm = d_rules->universalInst(univ, bind, gscore); } } Theorem simpThm = simplify(thm.getExpr()); if(*d_useInstTrue){ Expr res = simpThm.getRHS(); if(res.isTrue()){ return; } if(res.isFalse() ){ enqueueFact(thm); // setInconsistent(simpThm); d_allInstCount++; d_instThisRound++; throw FOUND_FALSE; } } d_simplifiedThmQueue.push(thm); TRACE("quant sendinst", "=gterm: ",gterm, ""); TRACE("quant sendinst", "==add fact simp =", simplifyExpr(thm.getExpr()), ""); TRACE("quant sendinst", "==add fact org =", thm.getExpr(), ""); TRACE("quant sendinst", "==add fact from= ", univ.getExpr(), "\n===: "+vectorExpr2string(bind)); } void TheoryQuant::enqueueInst(size_t univ_id , const std::vector& bind, const Expr& gterm){ static int max_score =-1; const Theorem& univ = d_univs[univ_id]; bool partInst=false; if(bind.size() < univ.getExpr().getVars().size()){ partInst=false; TRACE("sendinst","partinst",partInst,""); } Expr bind_expr(RAW_LIST, bind, getEM()); if (*d_useInstLCache){ const Expr& e = univ.getExpr(); ExprMap*>::iterator iterCache = d_bindHistory.find(e); if (iterCache != d_bindHistory.end()){ CDMap* cache = (*iterCache).second; if(cache->find(bind_expr) !=cache->end()){ return ; } else{ (*cache)[bind_expr] = true; } } else{ CDMap* new_cache = new(true) CDMap (theoryCore()->getCM()->getCurrentContext()); (*new_cache)[bind_expr] = true; } } Theorem thm ; if(null_expr == gterm ){//it is from naive instantiation or multi-inst TRACE("sendinst","gterm",gterm,""); if(partInst) { thm = d_rules->partialUniversalInst(univ, bind, 0); } else{ thm = d_rules->universalInst(univ, bind, 0); } } else{ int gscore = theoryCore()->getQuantLevelForTerm(gterm); if(gscore > max_score){ max_score = gscore; // cout<<"max score "<partialUniversalInst(univ, bind, gscore); } else{ thm = d_rules->universalInst(univ, bind, gscore); } } Theorem simpThm = simplify(thm.getExpr()); if(*d_useInstTrue){ Expr res = simpThm.getRHS(); if(res.isTrue()){ return; } if(res.isFalse() ){ enqueueFact(thm); // setInconsistent(simpThm); d_allInstCount++; d_instThisRound++; throw FOUND_FALSE; } } d_simplifiedThmQueue.push(thm); // cout<<"enqueue inst"<& binds, const Expr& gterm ) { return enqueueInst(univ,binds,gterm); } int TheoryQuant::sendInstNew(){ int resNum = 0 ; while(!d_simplifiedThmQueue.empty()){ const Theorem thm = d_simplifiedThmQueue.front(); d_simplifiedThmQueue.pop(); d_allInstCount++; d_instThisRound++; resNum++; enqueueFact(thm); } return resNum; } void TheoryQuant::addNotify(const Expr& e){} int recursiveExprScore(const Expr& e) { int res=0; DebugAssert(!(e.isClosure()), "exprScore called on closure"); if(e.arity()== 0){ res = 0; } else{ for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { res += recursiveExprScore(*i); } } res++; return res; } int exprScore(const Expr& e){ return recursiveExprScore(e); } Expr getHeadExpr(const Expr& e){ if (e.getKind() == APPLY){ return e.getOp().getExpr(); } if ( READ == e.getKind() || WRITE == e.getKind() ) { int kind = e[0].getKind(); if (UCONST==kind) { return e[0]; } else if (APPLY==kind || UFUNC == kind || READ == kind || WRITE == kind){ return getHeadExpr(e[0]); } else if(e[0].isSkolem()){ return e[0]; } } return null_expr; } Expr getHead(const Expr& e) { return getHeadExpr(e); } //! get the bound vars in term e, static bool recursiveGetBoundVars(const Expr& e, std::set& result) { bool res(false); if(e.getFlag()){ return e.containsBoundVar(); } else if(e.isClosure()){ res = recursiveGetBoundVars(e.getBody(),result); } else if (BOUND_VAR == e.getKind() ){ result.insert(e); e.setContainsBoundVar(); res = true; } else { res = false; for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i){ if(recursiveGetBoundVars(*i,result)){ res = true; } } } e.setFlag(); if(res) { e.setContainsBoundVar(); } return res; } //! get bound vars in term e, std::set getBoundVars(const Expr& e){ /* // static ExprMap > bvsCache; static std::map > bvsCache; std::map >::iterator iterCache = bvsCache.find(e); //ExprMap >::iterator iterCache = bvsCache.find(e); if (iterCache != bvsCache.end()){ // return iterCache->second; return (*iterCache).second; } */ e.clearFlags(); std::set result ; recursiveGetBoundVars(e,result); e.clearFlags(); // bvsCache[e]=result; return result; } bool isGoodSysPredTrigger(const Expr& e){ if(!isSysPred(e)) return false; if(usefulInMatch(e[0]) || usefulInMatch(e[1])) return true; return false; } bool isGoodFullTrigger(const Expr& e, const std::vector& bVarsThm){ if( !usefulInMatch(e)) return false; const std::set& bvs = getBoundVars(e); if (bvs.size() >= bVarsThm.size()){ for(size_t i=0; i& bVarsThm, int offset){ if( !usefulInMatch(e) ) return false; int bvar_missing = 0; const std::set& bvs = getBoundVars(e); if(bvs.size() <= 0) return false; for(size_t i=0; i& bVarsThm){ if( !usefulInMatch(e) ) return false; size_t bvar_missing = 0; const std::set& bvs = getBoundVars(e); for(size_t i=0; i& res) { if(e.getFlag()) return false; if(e.isClosure()) return recursiveGetPartTriggers(e.getBody(), res); if(0 == e.arity()){ if(BOUND_VAR == e.getKind()){ return false; } else{ return true; } } bool good=true; bool no_bound =true; for(Expr::iterator i=e.begin(), iend=e.end(); i!=iend; ++i) { if(BOUND_VAR == i->getKind()){ no_bound=false; continue; } bool temp = recursiveGetPartTriggers(*i,res); if(false == temp) { good=false; } } e.setFlag(); if(good && no_bound) { return true; } else if(good && !no_bound){ res.push_back(e); return false; } else{ return false; } } std::vector getPartTriggers(const Expr& e){ e.clearFlags(); std::vector res; recursiveGetPartTriggers(e,res); e.clearFlags(); return res; } int trigInitScore(const Expr& e){ if( isSysPred(e) && !isGoodSysPredTrigger(e)){ return 1; } else { return 0; } } void findPolarity(const Expr& e, ExprMap& res, Polarity pol){ if(!e.getType().isBool()) return; //now a AND b will be given a polarity too, this is not necessary. if(res.count(e)>0){ if ((Neg == res[e] && Pos == pol) || (Neg == res[e] && Pos == pol) ){ res[e]=PosNeg; } } else{ res[e]=pol; } if(PosNeg==pol){ for(int i=0; i res; const std::vector& subs=getSubTerms(e); for(size_t i=0; i tp = d_arrayIndic[name]; tp.push_back(index); d_arrayIndic[name]=tp; } else { } } } } void TheoryQuant::registerTrig(ExprMap* >* >& cur_trig_map, Trigger trig, const std::vector thmBVs, size_t univ_id){ { if(trig.hasRWOp){ ExprMap bv_map; dynTrig newDynTrig(trig, bv_map,univ_id); d_arrayTrigs.push_back(newDynTrig); } } ExprMap bv_map; for(size_t i = 0; i* >* >::iterator iter = cur_trig_map.find(head); if(cur_trig_map.end() == iter){ ExprMap* >* new_cd_map= new ExprMap* > ; cur_trig_map[head] = new_cd_map; vector* new_dyntrig_list = new vector; (*new_cd_map)[genTrig] = new_dyntrig_list; (*new_dyntrig_list).push_back(newDynTrig); } else{ ExprMap* >* cd_map = iter->second; ExprMap* >::iterator iter_map = cd_map->find(genTrig); if(cd_map->end() == iter_map){ vector* new_dyntrig_list = new vector; (*cd_map)[genTrig] = new_dyntrig_list; (*new_dyntrig_list).push_back(newDynTrig); } else{ // (*((*cd_map)[generalTrig])).push_back(newDynTrig); (*(iter_map->second)).push_back(newDynTrig); } } } /* void TheoryQuant::registerTrigReal(Trigger trig, const std::vector thmBVs, size_t univ_id){ cout<<"register: "< bv_map; for(size_t i = 0; i* >* >::iterator iter = d_allmap_trigs.find(head); if(d_allmap_trigs.end() == iter){ CDMap* >* new_cd_map= new(true) CDMap* > (theoryCore()->getCM()->getCurrentContext()); d_allmap_trigs[head] = new_cd_map; CDList* new_dyntrig_list = new(true) CDList (theoryCore()->getCM()->getCurrentContext()); (*new_cd_map)[genTrig] = new_dyntrig_list; (*new_dyntrig_list).push_back(newDynTrig); } else{ CDMap* >* cd_map = iter->second; CDMap* >::iterator iter_map = cd_map->find(genTrig); if(cd_map->end() == iter_map){ CDList* new_dyntrig_list = new(true) CDList (theoryCore()->getCM()->getCurrentContext()); (*cd_map)[genTrig] = new_dyntrig_list; (*new_dyntrig_list).push_back(newDynTrig); } else{ // (*((*cd_map)[generalTrig])).push_back(newDynTrig); (*((*iter_map).second)).push_back(newDynTrig); cout<<"once more"<& bvs){ size_t count =1 ; Expr res = recGeneralTrig(trig, bvs, count); getBoundVars(res); return res; } Expr TheoryQuant::recGeneralTrig(const Expr& trig, ExprMap& bvs, size_t& mybvs_count){ if (!trig.containsBoundVar()) return trig; if (BOUND_VAR == trig.getKind()){ if (bvs.find(trig) != bvs.end()){ const Expr& ubv = bvs[trig]; if(null_expr ==ubv){ Expr new_bv = d_mybvs[mybvs_count++]; bvs[trig] = new_bv ; if((mybvs_count) >= MAX_TRIG_BVS ){ throw "general trig error"; } else{ return new_bv; } } else{ return bvs[trig]; } } else{ return d_mybvs[0]; } } else{ vector children; for(Expr::iterator i=trig.begin(), iend=trig.end(); i!=iend; ++i){ Expr repChild; if(i->containsBoundVar()){ repChild = recGeneralTrig(*i, bvs, mybvs_count); } else{ repChild = *i; } children.push_back(repChild); } return Expr(trig.getOp(), children); } } //this function is used to check if two triggers can match with eath other bool TheoryQuant::canMatch(const Expr& t1, const Expr& t2, ExprMap& env){ if(getBaseType(t1) != getBaseType(t2)) return false; if (BOUND_VAR == t1.getKind() || BOUND_VAR == t2.getKind()) { return true; } if ( (t1.arity() != t2.arity()) || (t1.getKind() != t2.getKind() )) { return false; } if (canGetHead(t1) && canGetHead(t2)) { if ( getHead(t1) != getHead(t2) ){ return false; } for(int i=0; i& cur_trig){ if(!(*d_useTrans)){ return false; } if(3==cur_trig.size()){ const Expr& t1=cur_trig[0]; const Expr& t2=cur_trig[1]; const Expr& t3=cur_trig[2]; if ( canGetHead(t1) && canGetHead(t2) && canGetHead(t3) && (getHead(t1) == getHead(t2)) && (getHead(t2) == getHead(t3))){ const std::set& ts1 = getBoundVars(t1); const std::set& ts2 = getBoundVars(t2); const std::set& ts3 = getBoundVars(t3); if ( 2==ts1.size() && 2==ts2.size() && 2==ts2.size() && (ts1 != ts2) && (ts2 != ts3) && (ts3 != ts1)){ std::set all; for(set::const_iterator i=ts1.begin(), iend = ts1.end(); i != iend; i++){ all.insert(*i); } for(set::const_iterator i=ts2.begin(), iend = ts2.end(); i != iend; i++){ all.insert(*i); } for(set::const_iterator i=ts3.begin(), iend = ts3.end(); i != iend; i++){ all.insert(*i); } bool res = true; if(3==all.size()){ for(set::const_iterator i=all.begin(), iend = all.end(); i != iend; i++){ if(!i->isVar()) { res = false; break; } } if(res) { } return res; } } } } return false; } bool TheoryQuant::isTrans2Like (const std::vector& all_terms, const Expr& tr2){ if(!(*d_useTrans2)){ return false; } for(size_t i = 0; i < all_terms.size(); i++){ if(all_terms[i].isEq()){ const Expr& cur = all_terms[i]; if(cur[0] != cur[1] && ( (cur[0]==tr2[0] && cur[1]==tr2[1]) || (cur[0]==tr2[1] && cur[1]==tr2[0]))){ return true; } } } return false; } bool goodMultiTriggers(const std::vector& exprs, const std::vector bVars){ ExprMap bvar_found; for( std::vector::const_iterator i = bVars.begin(), iend= bVars.end(); i!=iend; i++) { bvar_found[*i]=false; } for (size_t i=0; i< exprs.size();i++){ const std::set & bv_in_trig = getBoundVars(exprs[i]); for(std::set::const_iterator j=bv_in_trig.begin(), jend = bv_in_trig.end(); j != jend; j++){ if(bvar_found.find(*j) != bvar_found.end()){ bvar_found[*j]=true; } } } for( std::vector::const_iterator i = bVars.begin(), iend= bVars.end(); i!=iend; i++) { if(false == bvar_found[*i]){ return false ; } } return true; } inline size_t locVar(const vector& bvsThm, const Expr& bv){ for(size_t i=0, iend = bvsThm.size(); i < iend; i++){ if (bvsThm[i] == bv){ return i; } } return 999; //this number should be big enough } void TheoryQuant::setupTriggers(const Theorem& thm, size_t univs_id){ } void TheoryQuant::setupTriggers(ExprMap* >*>& trig_maps, const Theorem& thm, size_t univs_id){ const Expr& e = thm.getExpr(); TRACE("triggers","setup : ",e.toString()," || "); // cout<<"set up "<& bVarsThm = e.getVars(); if (d_hasTriggers.count(e) > 0) { std::vector& new_trigs = d_fullTrigs[e]; for(size_t i=0; i& new_mult_trigs = d_multTrigs[e]; for(size_t j=0; j& subterms = getSubTrig(e); #ifdef DEBUG if( CVC3::debugger.trace("triggers") ){ cout<<"===========all sub terms =========="<getKindName(sub.getKind()) << endl; } } #endif ExprMap exprPol; findPolarity(e, exprPol, Pos); { std::vector trig_cadt; for(std::vector::const_iterator i = subterms.begin(),iend=subterms.end(); i!=iend; i++){ if(isGoodFullTrigger(*i, bVarsThm)) { trig_cadt.push_back(*i); } } std::vector trig_list; std::vector trig_extra; for(size_t iter =0; iter < trig_cadt.size(); iter++) { Expr* i = &(trig_cadt[iter]); bool notfound = true; for(size_t index=0; index< trig_list.size(); index++){ if (i->subExprOf(trig_list[index])) { trig_list[index]=*i; notfound=false; break; } if (trig_list[index].subExprOf(*i)) { notfound=false; break; } } if (notfound) { trig_list.push_back(*i); } } std::vector trig_ex; for (size_t i=0; i< trig_list.size();i++){ const Expr& cur = trig_list[i]; const std::set cur_bvs = getBoundVars(cur); int score = trigInitScore(cur); if(score > 0) continue; //1. test trans2 //2. test whether a trigger can trig a bigger instance of itself, now we have no actions for such case because we use expr score and dynamic loop prevention. for(size_t j=0; j< trig_cadt.size(); j++){ if (trig_list[i] == trig_cadt[j]) continue; ExprMap null; if (canMatch(trig_list[i], trig_cadt[j], null)){ if(exprScore(trig_list[i]) < exprScore(trig_cadt[j])){ } else if(*d_useTrans2 && trig_list.size() == 2 && trig_list[i].arity() == 2 && BOUND_VAR == trig_list[i][0].getKind() && BOUND_VAR == trig_list[i][1].getKind() && BOUND_VAR == trig_cadt[j][0].getKind() && BOUND_VAR == trig_cadt[j][1].getKind() && isTrans2Like(subterms, trig_list[i]) ){ score =0; //useless, to delete; d_trans2_num++; DebugAssert(d_trans2_num<=1, "more than 2 trans2 found"); TRACE("triggers", "trans2 found ", trig_list[i], ""); Trigger t(theoryCore(), cur, Neg, cur_bvs); t.setTrans2(true); t.setHead(getHeadExpr(cur)); if(isSimpleTrig(cur)){ t.setSimp(); } if(isSuperSimpleTrig(cur)){ t.setSuperSimp(); } d_fullTrigs[e].push_back(t); registerTrig(trig_maps,t, bVarsThm, univs_id); return; } else{ score =0; } } } Polarity pol= Ukn; if(cur.getType().isBool()){ DebugAssert(exprPol.count(e)>0,"unknown polarity:"+cur.toString()); pol = exprPol[cur]; } Trigger* t; Trigger* t_ex; //so, if a pred is PosNeg, we actually put two triggers into the list, one pos and the other neg if(PosNeg == pol && *d_usePolarity){ t = new Trigger(theoryCore(), cur, Pos, cur_bvs); t_ex = new Trigger(theoryCore(), cur, Neg, cur_bvs); if(isSimpleTrig(cur)){ t->setSimp(); t_ex->setSimp(); } if(isSuperSimpleTrig(cur)){ t->setSuperSimp(); t_ex->setSuperSimp(); } } else{ t = new Trigger(theoryCore(), cur, pol, cur_bvs); if(isSimpleTrig(cur)){ t->setSimp(); } if(isSuperSimpleTrig(cur)){ t->setSuperSimp(); } t_ex = NULL; } if(canGetHead(cur)) { t->setHead(getHeadExpr(cur)); if(NULL != t_ex){ t_ex->setHead(getHeadExpr(cur)); } } else{ if(!isSysPred(cur)){ // cout<<"cur " << cur <setRWOp(false); if(READ == cur.getKind() || WRITE == cur.getKind()){ arrayIndexName(cur); } if(READ == cur.getKind() && WRITE== cur[0].getKind() && 1 == bVarsThm.size() ){ // cout<trig<setRWOp(true); if(t_ex != NULL) t_ex->setRWOp(true); } if(t_ex != NULL) { trig_ex.push_back(*t_ex); } d_fullTrigs[e].push_back(*t); registerTrig(trig_maps,*t, bVarsThm, univs_id); TRACE("triggers", "new:full triggers:", cur.toString(),""); TRACE("triggers", "new:full trigger score:", score,""); TRACE("triggers", "new:full trigger pol:", pol,""); } for(size_t i=0; i::const_iterator i = subterms.begin(), iend=subterms.end(); i!=iend; i++) { if(isGoodMultiTrigger(*i, bVarsThm, d_offset_multi_trig)) { bool notfound = true; for(size_t index=0; indexsubExprOf(d_multTriggers[e][index])) { (d_multTriggers[e][index])=*i; notfound=false; } } if (notfound){ d_multTriggers[e].push_back(*i); } } } std::vector& cur_trig = d_multTriggers[e]; if (goodMultiTriggers(cur_trig, bVarsThm)){ // cout<<"good multi triggers"<setHead(getHeadExpr(ex)); if(isSimpleTrig(ex)){ trans_trig->setSimp(); } if(isSuperSimpleTrig(ex)){ trans_trig->setSuperSimp(); } trans_trig->setTrans(true); d_fullTrigs[e].push_back(*trans_trig); registerTrig(trig_maps,*trans_trig, bVarsThm, univs_id); cur_trig.clear(); } } //enhanced multi-triggers if(cur_trig.size() >0 ){ // if(cur_trig.size() >0 ){ std::vector posList, negList; for(size_t k=0; k tempList; tempList.clear(); tempList.push_back(cur_trig[i]); tempList.push_back(cur_trig[j]); // cout< bvs = getBoundVars(cur_trig[i]); Trigger trig(theoryCore(), cur_trig[i], Ukn, bvs); // trig.setHead(getHead(cur_trig[i])); trig.setMultiTrig(); trig.multiIndex = i; trig.multiId=d_all_multTrigsInfo.size(); d_multTrigs[e].push_back(trig); registerTrig(trig_maps, trig, bVarsThm, univs_id); } { multTrigsInfo multTrigs; for(size_t i =0, iend = d_multTrigs[e].size(); i& one_set_bvs = d_multTrigs[e][i].bvs; std::vector one_set_pos; for(size_t v = 0, vend = one_set_bvs.size(); v common; std::vector& tar1 = multTrigs.var_pos[0]; std::vector& tar2 = multTrigs.var_pos[1]; vector::iterator t1(tar1.begin()), t2(tar2.begin()); while(t1 != tar1.end() && t2!= tar2.end()){ size_t pos1 = *t1; size_t pos2 = *t2; if( pos1 == pos2 ) { common.push_back(pos1); t1=tar1.erase(t1); t2=tar2.erase(t2); } else if( pos1 > pos2 ){ t2++; } else { t1++; } } multTrigs.common_pos.push_back(common); size_t multi_size = d_multTrigs[e].size(); //should be 2 for(size_t i =0; i< multi_size; i++){ multTrigs.var_binds_found.push_back(new (true) CDMap (theoryCore()->getCM()->getCurrentContext())); } multTrigs.uncomm_list.push_back(new ExprMap* >); multTrigs.uncomm_list.push_back(new ExprMap* >); d_multitrigs_maps[e]=multTrigs; d_all_multTrigsInfo.push_back(multTrigs); } } } //setup partial triggers if(*d_usePart) { std::vector trig_ex; trig_ex.clear(); for( std::vector::const_iterator i = subterms.begin(), iend=subterms.end(); i!=iend; i++) { if(isGoodPartTrigger(*i, bVarsThm)) { bool notfound = true; for(size_t index=0; indexsubExprOf(d_partTriggers[e][index])) { (d_partTriggers[e][index])=*i; notfound=false; } } if (notfound) d_partTriggers[e].push_back(*i); } } for (size_t i=0; i< d_partTriggers[e].size();i++){ TRACE("triggers", "partial triggers:", d_partTriggers[e][i].toString(),""); } for (size_t i=0; i< d_partTriggers[e].size();i++){ Polarity pol= Ukn; const Expr& cur = d_partTriggers[e][i]; const std::set cur_bvs = getBoundVars(cur); if(cur.getType().isBool()){ DebugAssert(exprPol.count(e)>0,"unknown polarity:"+cur.toString()); pol = exprPol[cur]; } Trigger* t; Trigger* t_ex; //so, if a pred is PosNeg, we actually put two triggers into the list, one pos and the other neg if(PosNeg == pol && *d_usePolarity){ t = new Trigger(theoryCore(), cur, Pos, cur_bvs); t_ex = new Trigger(theoryCore(), cur, Neg, cur_bvs); } else{ t = new Trigger(theoryCore(), cur, pol, cur_bvs); t_ex = NULL; } if(canGetHead(cur)) { t->setHead(getHeadExpr(cur)); } if(t_ex != NULL) trig_ex.push_back(*t_ex); d_partTrigs[e].push_back(*t); TRACE("triggers", "new:part trigger pol:", pol,cur.toString()); } for(size_t i=0; i& bvsOutmost = thm.getVars(); const std::set& bvs = getBoundVars(thm); return int(bvs.size()-bvsOutmost.size()); } /*! \brief Theory interface function to assert quantified formulas * * pushes in negations and converts to either universally or existentially * quantified theorems. Universals are stored in a database while * existentials are enqueued to be handled by the search engine. */ void TheoryQuant::assertFact(const Theorem& thm){ if(*d_translate) return; TRACE("quant assertfact", "assertFact => ", thm.toString(), "{"); Theorem rule, result; const Expr& expr = thm.getExpr(); // Ignore existentials if(expr.isExists()) { TRACE("quant assertfact", "assertFact => (ignoring existential) }", expr.toString(), ""); return; } DebugAssert(expr.isForall() || (expr.isNot() && (expr[0].isExists() || expr[0].isForall())), "Theory of quantifiers cannot handle expression " + expr.toString()); if(expr.isNot()) {//find the right rule to eliminate negation if(expr[0].isForall()) { rule = d_rules->rewriteNotForall(expr); } else if(expr[0].isExists()) { rule = d_rules->rewriteNotExists(expr); } result = iffMP(thm, rule); } else{ result = thm; } result = d_rules->boundVarElim(result); //eliminate useless bound variables if(result.getExpr().isForall()){ if(*d_useNew){ if(result.getExpr().getBody().isForall()){ // if it is of the form forall x. forall. y result=d_rules->packVar(result); } result = d_rules->boundVarElim(result); //eliminate useless bound variables int nBVs = hasMoreBVs(result.getExpr()); if( nBVs >= 1){ d_hasMoreBVs[result.getExpr()]=true; } d_rawUnivs.push_back(result); return; /* -------------------------------------- */ // int nBVs = hasMoreBVs(result.getExpr()); if(0 == nBVs){//good TRACE("quant assertfact", "assertFact => forall enqueueing: ", result.toString(), "}"); d_univs.push_back(result); setupTriggers(result, d_univs.size()-1); } else if(1== nBVs){ d_hasMoreBVs[result.getExpr()]=true; const Expr& body = result.getExpr().getBody(); if(*d_usePullVar){ if((body.isAnd() && body[1].isForall()) || (body.isImpl() && body[1].isForall()) ){ result=d_rules->pullVarOut(result); TRACE("quant assertfact", "assertFact => pull-var enqueueing: ", result.toString(), "}"); d_univs.push_back(result); setupTriggers(result, d_univs.size()-1); } } else{ TRACE("quant assertfact", "debug:not recognized case", result.toString(), thm.toString()); d_univs.push_back(result); setupTriggers(result, d_univs.size()-1); return; } } else{ d_hasMoreBVs[result.getExpr()]=true; d_univs.push_back(result); setupTriggers(result, d_univs.size()-1); return; } } else{ TRACE("quant assertfact", "assertFact => old-fashoin enqueueing: ", result.toString(), "}"); // cout<<"error"< non-forall enqueueing: ", result.toString(), "}"); enqueueFact(result); } } void TheoryQuant::recGoodSemMatch(const Expr& e, const std::vector& bVars, std::vector& newInst, std::set >& instSet) { size_t curPos = newInst.size(); if (bVars.size() == curPos) { Expr simpleExpr = simplifyExpr(e.substExpr(bVars,newInst)); if (simpleExpr.hasFind()){ std::vector temp = newInst; instSet.insert(temp); TRACE("quant yeting", "new inst found for ", e.toString()+" ==> ", simpleExpr.toString()); }; } else { Type t = getBaseType(bVars[curPos]); std::vector tyExprs= d_typeExprMap[t]; if (0 == tyExprs.size()) { return;//has some problem } else{ for (size_t i=0;i* >::iterator iter; for(int i=0; i< parent.arity(); i++){ const Expr& child = parent[i]; iter = d_parent_list.find(child); if(d_parent_list.end() == iter){ d_parent_list[child] = new(true) CDList (theoryCore()->getCM()->getCurrentContext()) ; d_parent_list[child]->push_back(parent); } else{ iter->second->push_back(parent); } } } void TheoryQuant::collectChangedTerms(CDList& changed){ ExprMap eqs_hash; ExprMap changed_hash; /* { for(ExprMap* >::iterator iter = d_eq_list.begin(), iter_end=d_eq_list.end(); iter != iter_end; iter++){ CDList* cur_eqs = iter->second; int begin_pos; Expr head = iter->first; if(d_eq_pos.find(head) == d_eq_pos.end()){ begin_pos=0; d_eq_pos[head]= new(true) CDO(theoryCore()->getCM()->getCurrentContext(), 0, 0); } else{ begin_pos = *(d_eq_pos[head]); } for(size_t i=begin_pos; isize(); i++){ eqs_hash[(*cur_eqs)[i]]=true; } (d_eq_pos[head])->set(cur_eqs->size()); } }*/ for(size_t i=d_eqs_pos; i::iterator iter = eqs_hash.begin(), iter_end = eqs_hash.end(); iter != iter_end; iter++){ const Expr& cur_ex = iter->first; ExprMap* >::iterator iter_parent = d_parent_list.find(cur_ex); if(d_parent_list.end() != iter_parent){ CDList* cur_parents = iter_parent->second; for(size_t i=0; isize(); i++){ changed_hash[(*cur_parents)[i]]=true; } } } } { for(ExprMap::iterator iter = changed_hash.begin(), iter_end = changed_hash.end(); iter != iter_end; iter++){ changed.push_back(iter->first); } } } inline bool TheoryQuant::matchChild(const Expr& gterm, const Expr& vterm, ExprMap& env){ if(gterm.arity() != vterm.arity()) { return false; } for(int i = 0 ; i< gterm.arity(); i++){ const Expr& cur_v = vterm[i]; const Expr& cur_g = gterm[i]; if(BOUND_VAR == cur_v.getKind()){ ExprMap::iterator p = env.find(cur_v); if ( p != env.end()){ if (simplifyExpr(cur_g) != simplifyExpr(p->second)){ return false; } } else { env[cur_v] = simplifyExpr(cur_g); } } else if (!cur_v.containsBoundVar()){ if(simplifyExpr(cur_v) != simplifyExpr(cur_g)){ return false; } } else{ if (false == recSynMatch(cur_g, cur_v, env)){ return false; } } } return true; } inline void TheoryQuant::matchChild(const Expr& gterm, const Expr& vterm, vector >& binds){ ExprMap env; if(gterm.arity() != vterm.arity()) { return; } for(int i = 0 ; i< gterm.arity(); i++){ const Expr& cur_v = vterm[i]; const Expr& cur_g = gterm[i]; if(BOUND_VAR == cur_v.getKind()){ ExprMap::iterator p = env.find(cur_v); if ( p != env.end()){ if (simplifyExpr(cur_g) != simplifyExpr(p->second)){ return; } } else { env[cur_v] = simplifyExpr(cur_g); } } else if (!cur_v.containsBoundVar()){ if(simplifyExpr(cur_v) != simplifyExpr(cur_g)){ return ; } } else{ if (false == recSynMatch(cur_g, cur_v, env)){ return; } } } binds.push_back(env); return; } //match a gterm against all the trigs in d_allmap_trigs void TheoryQuant::matchListOld(const CDList& glist, size_t gbegin, size_t gend){ for(size_t g_index = gbegin; g_index < gend; g_index++){ const Expr& gterm = glist[g_index]; if(gterm.isEq()){ continue; // we do not match with equality } Expr head = getHead(gterm); ExprMap* > *>::iterator iter = d_allmap_trigs.find(head); if(d_allmap_trigs.end() == iter) continue; CDMap*>* cd_map = iter->second; // if(cd_map->size()>10){ // cout<<"map size1:"<size()<*>::iterator iter_trig = (*cd_map).begin(); CDMap*>::iterator iter_trig_end = (*cd_map).end(); for(;iter_trig != iter_trig_end; iter_trig++){ CDList* cur_list = (*iter_trig).second; if(1 == cur_list->size() || null_expr == head || gterm.getType().isBool()){ for(size_t cur_index =0; cur_index < cur_list->size(); cur_index++){ const Trigger& cur_trig = (*cur_list)[cur_index].trig; size_t univ_id = (*cur_list)[cur_index].univ_id; vector > binds; const Expr& vterm = cur_trig.trig; if ( d_allout && cur_trig.isSuperSimple && !cur_trig.hasTrans && !cur_trig.isMulti) continue; // if ( d_allout && cur_trig.isSimple ) continue; newTopMatch(gterm, vterm, binds, cur_trig); for(size_t i=0; i& cur_map = binds[i]; vector bind_vec; const vector& bVarsThm = d_univs[univ_id].getExpr().getVars(); for(size_t j=0; j< bVarsThm.size(); j++){ bind_vec.push_back(cur_map[bVarsThm[j]]); } synNewInst(univ_id, bind_vec, gterm, cur_trig); } } } else if ( cur_list->size() > 1){ const Trigger& cur_trig = (*cur_list)[0].trig;//here we have a polarity problem const Expr& general_vterm = (*iter_trig).first; vector > binds; if ( d_allout && cur_trig.isSuperSimple && !cur_trig.hasTrans && !cur_trig.isMulti) continue; //if ( d_allout && cur_trig.isSimple ) continue; newTopMatch(gterm, general_vterm, binds, cur_trig); for(size_t trig_index = 0; trig_index< cur_list->size(); trig_index++){ size_t univ_id = (*cur_list)[trig_index].univ_id; const ExprMap& trig_map = (*cur_list)[trig_index].binds; const Trigger& ind_cur_trig = (*cur_list)[trig_index].trig; for(size_t i=0; i& cur_map = binds[i]; vector bind_vec; const vector& bVarsThm = d_univs[univ_id].getExpr().getVars(); for(size_t j=0; j< bVarsThm.size(); j++){ const Expr& inter=(*(trig_map.find(bVarsThm[j]))).second; const Expr& inter2 = cur_map[inter]; bind_vec.push_back(inter2); } synNewInst(univ_id, bind_vec, gterm, ind_cur_trig); } } } else{ FatalAssert(false, "error in matchlistold"); } }//end of for each trig begins with head }//end of each gterm } void TheoryQuant::delNewTrigs(ExprMap*>*>& new_trigs){ //return; ExprMap*>*>::iterator i = new_trigs.begin(); ExprMap*>*>::iterator iend = new_trigs.end(); for(; i!=iend; i++){ ExprMap*>* cur_new_cd_map = i->second; ExprMap* >::iterator j = cur_new_cd_map->begin(); ExprMap* >::iterator jend = cur_new_cd_map->end(); for(; j!=jend; j++){ Expr general_trig = j->first; vector* trigs = j->second; delete trigs; } delete cur_new_cd_map; } new_trigs.clear(); } void TheoryQuant::combineOldNewTrigs(ExprMap*>*>& new_trigs){ ExprMap*>*>::iterator i = new_trigs.begin(); ExprMap*>*>::iterator iend = new_trigs.end(); for(; i!=iend; i++){ ExprMap*>* cur_new_cd_map = i->second; Expr head = i->first; ExprMap* >* >::iterator old_iter = d_allmap_trigs.find(head); if(d_allmap_trigs.end() == old_iter){ CDMap* >* old_cd_map = // new(true) CDMap* > (theoryCore()->getCM()->getCurrentContext()); new(false) CDMap* > (theoryCore()->getCM()->getCurrentContext()); d_allmap_trigs[head] = old_cd_map; ExprMap* >::iterator j = cur_new_cd_map->begin(); ExprMap* >::iterator jend = cur_new_cd_map->end(); for(; j!=jend; j++){ Expr general_trig = j->first; vector* trigs = j->second; CDList* old_cd_list = //new(true) CDList (theoryCore()->getCM()->getCurrentContext()); new(false) CDList (theoryCore()->getCM()->getCurrentContext()); (*old_cd_map)[general_trig] = old_cd_list; for(size_t k=0; ksize(); k++){ (*old_cd_list).push_back((*trigs)[k]); // cout<<"combined 1 "<<(*trigs)[k].trig.getEx()<* >* old_cd_map = old_iter->second; ExprMap*>::iterator j = cur_new_cd_map->begin(); ExprMap*>::iterator jend = cur_new_cd_map->end(); for(; j!=jend; j++){ Expr general_trig = j->first; vector* trigs = j->second; CDMap* >::iterator old_trigs_iter = old_cd_map->find(general_trig); CDList* old_cd_list; if(old_cd_map->end() == old_trigs_iter){ old_cd_list = //new(true) CDList (theoryCore()->getCM()->getCurrentContext()); new(false) CDList (theoryCore()->getCM()->getCurrentContext()); (*old_cd_map)[general_trig] = old_cd_list; } else{ old_cd_list = (*old_trigs_iter).second; } for(size_t k=0; ksize(); k++){ (*old_cd_list).push_back((*trigs)[k]); // cout<<"combined 2 "<<(*trigs)[k].trig.getEx()<*>*>& new_trigs, const CDList& glist, size_t gbegin, size_t gend){ for(size_t g_index = gbegin; g_index* > *>::iterator iter = new_trigs.find(head); if(new_trigs.end() == iter) continue; ExprMap*>* cd_map = iter->second; // if(cd_map->size()>10){ // cout<<"map size2:"<size()<*>::iterator iter_trig = (*cd_map).begin(); ExprMap*>::iterator iter_trig_end = (*cd_map).end(); for(;iter_trig != iter_trig_end; iter_trig++){ vector* cur_list = (*iter_trig).second; if(1 == cur_list->size() || null_expr == head || gterm.getType().isBool()){ for(size_t cur_index =0; cur_index < cur_list->size(); cur_index++){ const Trigger& cur_trig = (*cur_list)[cur_index].trig; // if ( d_allout && cur_trig.isSuperSimple && !cur_trig.hasTrans) continue; size_t univ_id = (*cur_list)[cur_index].univ_id; vector > binds; const Expr& vterm = cur_trig.trig; newTopMatch(gterm, vterm, binds, cur_trig); for(size_t i=0; i& cur_map = binds[i]; vector bind_vec; const vector& bVarsThm = d_univs[univ_id].getExpr().getVars(); for(size_t j=0; j< bVarsThm.size(); j++){ bind_vec.push_back(cur_map[bVarsThm[j]]); } synNewInst(univ_id, bind_vec, gterm, cur_trig); } } } else if ( cur_list->size() > 1){ const Trigger& cur_trig = (*cur_list)[0].trig;//here we have a polarity problem // if ( d_allout && cur_trig.isSuperSimple && !cur_trig.hasTrans) continue; const Expr& general_vterm = (*iter_trig).first; vector > binds; newTopMatch(gterm, general_vterm, binds, cur_trig); for(size_t trig_index = 0; trig_index< cur_list->size(); trig_index++){ size_t univ_id = (*cur_list)[trig_index].univ_id; const Trigger& ind_cur_trig = (*cur_list)[trig_index].trig; const ExprMap& trig_map = (*cur_list)[trig_index].binds; for(size_t i=0; i& cur_map = binds[i]; vector bind_vec; const vector& bVarsThm = d_univs[univ_id].getExpr().getVars(); for(size_t j=0; j< bVarsThm.size(); j++){ const Expr& inter=(*(trig_map.find(bVarsThm[j]))).second; const Expr& inter2 = cur_map[inter]; bind_vec.push_back(inter2); } synNewInst(univ_id, bind_vec, gterm, ind_cur_trig); } } } else{ FatalAssert(false, "error in matchlistold"); } }//end of for each trig begins with head }// end of each gterm } void TheoryQuant::newTopMatch(const Expr& gterm, const Expr& vterm, vector >& binds, const Trigger& trig){ ExprMap cur_bind; if(trig.isSuperSimple){ for(int i = vterm.arity()-1; i>=0 ; i--){ cur_bind[vterm[i]] = simplifyExpr(gterm[i]); } binds.push_back(cur_bind); return; } if(trig.isSimple){ for(int i = vterm.arity()-1; i>=0 ; i--){ if(BOUND_VAR != vterm[i].getKind()){ if(simplifyExpr(gterm[i]) != simplifyExpr(vterm[i])) { return ; } } else{ cur_bind[vterm[i]] = simplifyExpr(gterm[i]); } } binds.push_back(cur_bind); return; } if(!isSysPred(vterm)){ //then gterm cannot be a syspred if(!gterm.getType().isBool()){ // res2= recSynMatch(gterm, vterm, env); matchChild(gterm, vterm, binds); return; } matchChild(gterm, vterm, binds); return; if(!*d_usePolarity){ // return recSynMatch(gterm, vterm, env); matchChild(gterm, vterm, binds); return; } const bool gtrue = (trueExpr()==findExpr(gterm)); // const bool gtrue = (trueExpr()==simplifyExpr(gterm)); if(gtrue ){ if((Neg==trig.polarity || PosNeg==trig.polarity)) { // return recSynMatch(gterm, vterm, env); matchChild(gterm, vterm, binds); return; } else{ // cout<<"returned 1"<& env){ Expr vterm = trig.getEx(); TRACE("quant toppred", "top pred: gterm:| "+gterm.toString()," vterm:| "+vterm.toString(),""); DebugAssert ((BOUND_VAR != gterm.getKind()),"gound term "+gterm.toString()+" has bound var"); DebugAssert ((BOUND_VAR != vterm.getKind()),"top pred match "+gterm.toString()+" has bound var"); if(gterm.isEq() || vterm.isEq()){ return false; // we do not match with equality } bool res2=false; if(vterm.arity() != gterm.arity()) return false; if(trig.isSuperSimp()){ if(trig.getHead() == getHead(gterm) ){ for(int i = vterm.arity()-1; i>=0 ; i--){ env[vterm[i]] = simplifyExpr(gterm[i]); } return true; } return false; } if(trig.isSimp()){ if(trig.getHead() == getHead(gterm) ){ for(int i = vterm.arity()-1; i>=0 ; i--){ if(BOUND_VAR != vterm[i].getKind()){ if(simplifyExpr(gterm[i]) != simplifyExpr(vterm[i])) { return false; } } } for(int i = vterm.arity()-1; i>=0 ; i--){ if(BOUND_VAR == vterm[i].getKind()){ if(d_allout){ env[vterm[i]] = simplifyExpr(gterm[i]); } else { env[vterm[i]] = simplifyExpr(gterm[i]); } } } return true; } else{ return false; } } if(!(isSysPred(vterm) && isSysPred(gterm))){ if(isSysPred(vterm) || isSysPred(gterm)) { return false; } if(!usefulInMatch(gterm)){ return false; } if(trig.getHead() != getHead(gterm)){ return false; } if(!gterm.getType().isBool()){ // res2= recSynMatch(gterm, vterm, env); res2= matchChild(gterm, vterm, env); return res2; } if(!*d_usePolarity){ // return recSynMatch(gterm, vterm, env); return matchChild(gterm, vterm, env); } const bool gtrue = (trueExpr()==findExpr(gterm)); if(gtrue ){ if(trig.isNeg()) { // return recSynMatch(gterm, vterm, env); return matchChild(gterm, vterm, env); } else{ return false; } } const bool gfalse = (falseExpr()==findExpr(gterm)); if(gfalse){ if (trig.isPos()){ // return recSynMatch(gterm, vterm, env); return matchChild(gterm, vterm, env); } else{ return false; } } else { return false; } } else{ DebugAssert((2==gterm.arity() && 2==vterm.arity()), "impossible situation in top pred"); DebugAssert(!((isLE(gterm) || isLT(gterm)) && !isIntx(gterm[0],0)), "canonical form changed"); #ifdef DEBUG if( CVC3::debugger.trace("quant toppred") ){ cout << "toppred gterm, vterm" << gterm << "::" << vterm << endl; cout << findExpr(gterm) << "::" << trig.isPos() << "|" << trig.isNeg() << endl; } #endif Expr gl = getLeft(gterm[1]); Expr gr = getRight(gterm[1]); if(null_expr == gr || null_expr == gl){ gl = gterm[0]; gr = gterm[1]; } Expr vr, vl; Expr tvr, tvl; tvr=null_expr; tvl=null_expr; if(isGE(vterm) || isGT(vterm)){ vr = vterm[0]; vl = vterm[1]; } else if(isLE(vterm) || isLT(vterm)){ vr = vterm[1]; vl = vterm[0]; } else{ DebugAssert(false, "impossilbe in toppred"); } if(isIntx(vl,0)){ tvl = getLeft(vr); tvr = getRight(vr); } else if(isIntx(vr,0)) { tvl = getLeft(vl); tvr = getRight(vl); } if( (null_expr != tvl) && (null_expr != tvr)){ vl = tvl; vr = tvr; } const bool gtrue = (trueExpr()==findExpr(gterm)); const bool gfalse = (falseExpr()==findExpr(gterm)); TRACE("quant toppred"," vl, gl, vr, gr:", vl.toString()+"::"+gl.toString()+"||", vr.toString()+"::"+gr.toString()); bool res; DebugAssert(!(trig.isNeg() && trig.isPos()), "expr in both pos and neg"); if(!*d_usePolarity){ return (recSynMatch(gl, vl, env) && recSynMatch(gr, vr, env)); } if(trig.isNeg()){ if (( gtrue ) ) { res=(recSynMatch(gl, vl, env) && recSynMatch(gr, vr, env)); } else { res=(recSynMatch(gl, vr, env) && recSynMatch(gr, vl, env)); } } else if(trig.isPos()){ if (( gfalse )) { res=(recSynMatch(gl, vl, env) && recSynMatch(gr, vr, env)); } else { res=(recSynMatch(gl, vr, env) && recSynMatch(gr, vl, env)); } } else { DebugAssert(false, "impossible polarity for trig"); res = false; } #ifdef DEBUG if( CVC3::debugger.trace("quant toppred") ){ cout<<"res| "<< res << " | " << gtrue << " | " << gfalse << endl; } #endif return res; } } */ bool TheoryQuant::recSynMatch(const Expr& gterm, const Expr& vterm, ExprMap& env){ TRACE("quant match", "gterm:| "+gterm.toString()," vterm:| "+vterm.toString(),""); DebugAssert ((BOUND_VAR != gterm.getKind()),"gound term "+gterm.toString()+" has bound var"); if (BOUND_VAR == vterm.getKind() ) { TRACE("quant match", "bound var found;", vterm.toString(),""); ExprMap::iterator p = env.find(vterm); if ( p != env.end()){ if (simplifyExpr(gterm) != simplifyExpr(p->second)){ return false; } else return true; } else { env[vterm] = simplifyExpr(gterm); return true; } } else if (!vterm.containsBoundVar()){ // return true; // cout<<"vterm and gterm"<= 0; i--){ // if (false == recSynMatch(gterm[i], vterm[i] , env)) // return false; // } // return true; } else{ return false; } } if ( (canGetHead(gterm)) && vhead == getHead(gterm)){ // if(gterm.arity() != vterm.arity()){ // return false; // } // for(int i=vterm.arity()-1; i >= 0; i--){ // if (false == recSynMatch(gterm[i], vterm[i] , env)) { // return false; // } // } // return true; return matchChild(gterm, vterm, env); } if(!*d_useEqu){ return false; } // cout<<"==============================="< eq_set; std::map eq_set; eq_set.clear(); eq_set[gterm]=true; std::queue eq_queue; ExprMap* >::iterator iter = d_eq_list.find(gterm); if(iter != d_eq_list.end()){ for(size_t len =0; len< iter->second->size(); len++){ eq_queue.push((*(iter->second))[len]); } int count =0; while(eq_queue.size()>0){ count++; const Expr& cur = eq_queue.front(); eq_queue.pop(); if(eq_set.find(cur) == eq_set.end()){ if(canGetHead(cur) && getHead(cur) == vhead){ // cout<<"VTERM: "<* >::iterator iter = d_eq_list.find(cur); if(iter != d_eq_list.end()){ for(size_t len =0; len< iter->second->size(); len++){ eq_queue.push((*(iter->second))[len]); } } } } } // return false; } */ if( d_same_head_expr.count(vhead) > 0 ) { const Expr& findGterm = simplifyExpr(gterm); //if(isIntx(findGterm,0) || isIntx(findGterm,1)) return false;//special for simplify benchmark TRACE("quant match", "find gterm:", findGterm.toString(),""); CDList* gls = d_same_head_expr[vhead]; /* { int count =0; for(size_t i = 0; isize(); i++){ if (simplifyExpr((*gls)[i]) == findGterm){ count++; } } if(count>1){ cout<<"count " << count << " # " << gls->size() << " | "<size(); i++){ if (simplifyExpr((*gls)[i]) == findGterm){ cout<<"eq "<<(*gls)[i]<size(); i++){ if (simplifyExpr((*gls)[i]) == findGterm){ TRACE("quant match", "find matched gterm:", (*gls)[i].toString(),""); DebugAssert((*gls)[i].arity() == vterm.arity(), "gls has different arity"); const Expr& newgterm = (*gls)[i]; for(int child=vterm.arity()-1; child >= 0 ; child--){ if (false == recSynMatch(newgterm[child], vterm[child] , env)){ TRACE("quant match", "match false", (*gls)[i][child].toString(), vterm[child].toString()); return false; } } TRACE("quant match", "good match, return true:", gterm, vterm.toString()); // cout<<"quant good match: " <0 ){ // for(int child=0; child < vterm.arity() ; child++){ // if (false == recSynMatch(gterm[child], vterm[child] , env)){ // TRACE("quant match", "match false", gterm[child].toString(), vterm[child].toString()); // return false; // } // } // return true; // if( gterm.getKind() == PLUS || gterm.getKind() == MINUS){ // cout<<"g v"<& env){ const Expr vterm = trig.getEx(); TRACE("quant toppred", "top pred: gterm:| "+gterm.toString()," vterm:| "+vterm.toString(),""); DebugAssert ((BOUND_VAR != gterm.getKind()),"gound term "+gterm.toString()+" has bound var"); DebugAssert ((BOUND_VAR != vterm.getKind()),"top pred match "+gterm.toString()+" has bound var"); if(gterm.isEq() || vterm.isEq()){ return false; // we do not match with equality } bool res2=false; // if(vterm.arity() != gterm.arity()) return false; if(trig.isSimp()){ if(trig.getHead() == getHead(gterm) ){ for(int i = vterm.arity()-1; i>=0 ; i--){ if(BOUND_VAR != vterm[i].getKind()){ if(simplifyExpr(gterm[i]) != simplifyExpr(vterm[i])) { return false; } } } for(int i = vterm.arity()-1; i>=0 ; i--){ if(BOUND_VAR == vterm[i].getKind()){ if(d_allout){ env[vterm[i]] = simplifyExpr(gterm[i]); } else { env[vterm[i]] = simplifyExpr(gterm[i]); } } } return true; } else{ return false; } } if(!(isSysPred(vterm) && isSysPred(gterm))){ if(isSysPred(vterm) || isSysPred(gterm)) { return false; } if(!usefulInMatch(gterm)){ return false; } if(trig.getHead() != getHead(gterm)){ return false; } if(!gterm.getType().isBool()){ res2= recSynMatch(gterm, vterm, env); return res2; } if(!*d_usePolarity){ return recSynMatch(gterm, vterm, env); } const bool gtrue = (trueExpr()==findExpr(gterm)); if(gtrue ){ if(trig.isNeg()) { return recSynMatch(gterm, vterm, env); } else{ return false; } } const bool gfalse = (falseExpr()==findExpr(gterm)); if(gfalse){ if (trig.isPos()){ return recSynMatch(gterm, vterm, env); } else{ return false; } } else { return false; } } else{ DebugAssert((2==gterm.arity() && 2==vterm.arity()), "impossible situation in top pred"); DebugAssert(!((isLE(gterm) || isLT(gterm)) && !isIntx(gterm[0],0)), "canonical form changed"); #ifdef DEBUG if( CVC3::debugger.trace("quant toppred") ){ cout << "toppred gterm, vterm" << gterm << "::" << vterm << endl; cout << findExpr(gterm) << "::" << trig.isPos() << "|" << trig.isNeg() << endl; } #endif Expr gl = getLeft(gterm[1]); Expr gr = getRight(gterm[1]); if(null_expr == gr || null_expr == gl){ gl = gterm[0]; gr = gterm[1]; } Expr vr, vl; Expr tvr, tvl; tvr=null_expr; tvl=null_expr; if(isGE(vterm) || isGT(vterm)){ vr = vterm[0]; vl = vterm[1]; } else if(isLE(vterm) || isLT(vterm)){ vr = vterm[1]; vl = vterm[0]; } else{ DebugAssert(false, "impossilbe in toppred"); } if(isIntx(vl,0)){ tvl = getLeft(vr); tvr = getRight(vr); } else if(isIntx(vr,0)) { tvl = getLeft(vl); tvr = getRight(vl); } if( (null_expr != tvl) && (null_expr != tvr)){ vl = tvl; vr = tvr; } const bool gtrue = (trueExpr()==findExpr(gterm)); const bool gfalse = (falseExpr()==findExpr(gterm)); TRACE("quant toppred"," vl, gl, vr, gr:", vl.toString()+"::"+gl.toString()+"||", vr.toString()+"::"+gr.toString()); bool res; DebugAssert(!(trig.isNeg() && trig.isPos()), "expr in both pos and neg"); if(!*d_usePolarity){ return (recSynMatch(gl, vl, env) && recSynMatch(gr, vr, env)); } if(trig.isNeg()){ if (( gtrue ) ) { res=(recSynMatch(gl, vl, env) && recSynMatch(gr, vr, env)); } else { res=(recSynMatch(gl, vr, env) && recSynMatch(gr, vl, env)); } } else if(trig.isPos()){ if (( gfalse )) { res=(recSynMatch(gl, vl, env) && recSynMatch(gr, vr, env)); } else { res=(recSynMatch(gl, vr, env) && recSynMatch(gr, vl, env)); } } else { DebugAssert(false, "impossible polarity for trig"); res = false; } #ifdef DEBUG if( CVC3::debugger.trace("quant toppred") ){ cout<<"res| "<< res << " | " << gtrue << " | " << gfalse << endl; } #endif return res; } } bool TheoryQuant::recSynMatch(const Expr& gterm, const Expr& vterm, ExprMap& env){ TRACE("quant match", "gterm:| "+gterm.toString()," vterm:| "+vterm.toString(),""); DebugAssert ((BOUND_VAR != gterm.getKind()),"gound term "+gterm.toString()+" has bound var"); if (BOUND_VAR == vterm.getKind()) { TRACE("quant match", "bound var found;", vterm.toString(),""); ExprMap::iterator p = env.find(vterm); if ( p != env.end()){ if (simplifyExpr(gterm) != simplifyExpr(p->second)){ return false; } else return true; } else { env[vterm] = simplifyExpr(gterm); return true; } } else if (!vterm.containsBoundVar()){ if(simplifyExpr(vterm) == simplifyExpr(gterm)) { return true; } else{ return false; } } else if(false && isSysPred(vterm) && isSysPred(gterm)){ TRACE("quant syspred"," vterm, gterm ", vterm.toString()+" :|: ", gterm.toString()); TRACE("quant syspred"," simplified vterm, gterm ", simplifyExpr(vterm).toString()+" :|: ", simplifyExpr(gterm).toString()); FatalAssert(false, "should not be here in synmatch"); exit(3); } else{ if(canGetHead(vterm)){ Expr vhead = getHead(vterm); TRACE("quant match", "head vterm:", getHead(vterm), ""); if(vterm.isAtomicFormula()){ if (canGetHead(gterm)) { if ( vhead != getHead(gterm) ){ return false; } for(int i=vterm.arity()-1; i >= 0; i--){ if (false == recSynMatch(gterm[i], vterm[i] , env)) return false; } return true; } else{ return false; } } if ( (canGetHead(gterm)) && vhead == getHead(gterm)){ if(gterm.arity() != vterm.arity()){ return false; } for(int i=vterm.arity()-1; i >= 0; i--){ if (false == recSynMatch(gterm[i], vterm[i] , env)) { return false; } } return true; } if(false && !*d_useEqu){ return false; } if( d_same_head_expr.count(vhead) > 0 ) { const Expr& findGterm = simplifyExpr(gterm); //if(isIntx(findGterm,0) || isIntx(findGterm,1)) return false;//special for simplify benchmark TRACE("quant match", "find gterm:", findGterm.toString(),""); CDList* gls = d_same_head_expr[vhead]; for(size_t i = 0; isize(); i++){ if (simplifyExpr((*gls)[i]) == findGterm){ TRACE("quant match", "find matched gterm:", (*gls)[i].toString(),""); DebugAssert((*gls)[i].arity() == vterm.arity(), "gls has different arity"); for(int child=vterm.arity()-1; child >= 0 ; child--){ const Expr& newgterm = (*gls)[i]; if (false == recSynMatch(newgterm[child], vterm[child] , env)){ TRACE("quant match", "match false", (*gls)[i][child].toString(), vterm[child].toString()); return false; } } TRACE("quant match", "good match, return true:", gterm, vterm.toString()); return true; } }//end of for return false; } else { return false;//end of if } } else{ TRACE("quant match more", "match more", gterm.toString()+" # ", vterm.toString()); if( (gterm.getKind() == vterm.getKind()) && (gterm.arity() == vterm.arity()) && gterm.arity()>0 ){ for(int child=0; child < vterm.arity() ; child++){ if (false == recSynMatch(gterm[child], vterm[child] , env)){ TRACE("quant match", "match false", gterm[child].toString(), vterm[child].toString()); return false; } } return true; } else return false; } } } */ void TheoryQuant::goodSynMatch(const Expr& e, const std::vector & boundVars, std::vector >& instBinds, std::vector& instGterms, const CDList& allterms, size_t tBegin){ for (size_t i=tBegin; i env; env.clear(); bool found = recSynMatch(gterm,e,env); if(found){ TRACE("quant matching found", " good:",gterm.toString()+" to " , e.toString()); TRACE("quant matching found", " simplified good:",simplifyExpr(gterm).toString()+" to " , simplifyExpr(e).toString()); std::vector inst; DebugAssert((boundVars.size() == env.size()),"bound var size != env.size()"); for(size_t i=0; i::iterator p = env.find(boundVars[i]); DebugAssert((p!=env.end()),"bound var cannot be found"); inst.push_back(p->second); } instBinds.push_back(inst); instGterms.push_back(gterm); } else{ TRACE("quant matching", "bad one",gterm.toString()+" to " , e.toString()); } } } } /* void TheoryQuant::goodSynMatchNewTrig(const Trigger& trig, const std::vector & boundVars, std::vector >& instBinds, std::vector& instGterms, const CDList& allterms, size_t tBegin){ for (size_t i=tBegin; i env; env.clear(); bool found = synMatchTopPred(gterm,trig,env); if(found){ //TRACE("quant matching found", " top good:",gterm.toString()+" to " , trig.getEx().toString()); std::vector inst; inst.clear(); DebugAssert((boundVars.size() <= env.size()),"bound var size != env.size()"); for(size_t i=0; i::iterator p = env.find(boundVars[i]); DebugAssert((p!=env.end()),"bound var cannot be found"); inst.push_back(p->second); } instBinds.push_back(inst); instGterms.push_back(gterm); } else{ // TRACE("quant matching", "bad one",gterm.toString()+" to ", trig.getEx().toString()); } } } } */ /* bool TheoryQuant::hasGoodSynInstNewTrigOld(Trigger& trig, std::vector & boundVars, std::vector >& instBinds, std::vector& instGterms, const CDList& allterms, size_t tBegin){ const std::set& bvs = getBoundVars(trig.getEx()); boundVars.clear(); for(std::set::const_iterator i=bvs.begin(),iend=bvs.end(); i!=iend; ++i) boundVars.push_back(*i); instBinds.clear(); goodSynMatchNewTrig(trig, boundVars, instBinds, instGterms, allterms, tBegin); if (instBinds.size() > 0) return true; else return false; } bool TheoryQuant::hasGoodSynInstNewTrig(Trigger& trig, const std::vector& boundVars, std::vector >& instBinds, std::vector& instGterms, const CDList& allterms, size_t tBegin){ // boundVars=trig.getBVs(); // const std::set& bvs = getBoundVars(trig.getEx()); // boundVars.clear(); // for(std::set::const_iterator i=bvs.begin(),iend=bvs.end(); i!=iend; ++i) // boundVars.push_back(*i); instBinds.clear(); goodSynMatchNewTrig(trig, boundVars, instBinds, instGterms, allterms, tBegin); if (instBinds.size() > 0) return true; else return false; } */ int TheoryQuant::loc_gterm(const std::vector& border, const Expr& vterm, int pos){ const std::vector& order = d_mtrigs_bvorder[vterm]; const Expr& var = order[pos]; for(size_t i=0; i& border, const std::vector& mtrigs, int cur_depth, std::vector >& instSet, std::vector& cur_inst ){ int max_dep = mtrigs.size(); if(cur_depth >= max_dep) return; Expr cur_vterm = mtrigs[cur_depth]; //get the current vterm if(d_mtrigs_inst.count(cur_vterm) <=0) return; CDList >* gterm_list = d_mtrigs_inst[cur_vterm]; // get the list of ground term found for cur_vterm for(size_t i=0; i< gterm_list->size(); i++){ const std::vector& cur_gterm = (*gterm_list)[i]; std::vector new_inst(border.size()); //get a new inst array for(size_t j=0; j< border.size(); j++){ new_inst[j]=cur_inst[j]; //copy to cur_int to new_inst } bool has_problem = false;//next, try to put the cur gterm into new_inst for(size_t j=0; j< cur_gterm.size(); j++){ int cur_loc_gterm = loc_gterm(border, cur_vterm, j); if( null_expr == new_inst[cur_loc_gterm]){ new_inst[cur_loc_gterm] = cur_gterm[j]; } else if (new_inst[cur_loc_gterm] != cur_gterm[j]){ has_problem = true; break; } } if (has_problem){ continue; } bool finished = true; for(size_t j=0; j< border.size() ;j++){ if(null_expr == new_inst[j]){ finished = false; break; } } if(finished){ std::vector good_inst; for(size_t j=0; j& border, std::vector >& instSet ){ std::vector dumy(border.size()) ; //use dynamic array here for(size_t j=0; j< border.size() ;j++){ dumy[j]=null_expr; } const std::vector& mtrigs = d_multTriggers[thm]; recSearchCover(border, mtrigs, 0, instSet, dumy); } bool TheoryQuant::hasGoodSynMultiInst(const Expr& thm, std::vector & boundVars, std::vector >& instSet, const CDList& allterms, size_t tBegin){ const std::set& bvs = getBoundVars(thm); boundVars.clear(); for(std::set::const_iterator i=bvs.begin(),iend=bvs.end(); i!=iend; ++i) boundVars.push_back(*i); instSet.clear(); bool new_match = false; //assumption: every trig is different //this is not true later, fix this asap const std::vector& mtrigs = d_multTriggers[thm]; for(std::vector::const_iterator i= mtrigs.begin(), iend = mtrigs.end(); i != iend; i++){ if(d_mtrigs_bvorder[*i].empty()){ //setup an order const std::set& trig_bvs = getBoundVars(*i); for(std::set::const_iterator j= trig_bvs.begin(), jend = trig_bvs.end(); j != jend; j++){ d_mtrigs_bvorder[*i].push_back(*j); } } const std::vector& trig_bvorder = d_mtrigs_bvorder[*i]; // std::set > trig_insts; std::vector > trig_insts; trig_insts.clear(); std::vector gtms; goodSynMatch(*i, trig_bvorder, trig_insts, gtms, allterms, tBegin); if (trig_insts.size() > 0){ new_match=true; if(d_mtrigs_inst.count(*i) <= 0){ d_mtrigs_inst[*i] = new(true) CDList > (theoryCore()->getCM()->getCurrentContext()); } for(std::vector >::const_iterator j = trig_insts.begin(), jend = trig_insts.end(); j != jend; j++){ d_mtrigs_inst[*i]->push_back(*j); for(std::vector::const_iterator k = j->begin(), kend = j->end(); k != kend; k++){ } } } } // end of for for(std::vector::const_iterator i= mtrigs.begin(), iend = mtrigs.end(); i != iend; i++){ if (d_mtrigs_inst.count(*i) <=0 ) continue; for(CDList >::const_iterator j = d_mtrigs_inst[*i]->begin(), jend = d_mtrigs_inst[*i]->end(); j != jend; j++){ for(std::vector::const_iterator k = j->begin(), kend = j->end(); k != kend; k++){ } } } {//code for search a cover if(new_match){ searchCover(thm, boundVars, instSet); } } if(instSet.size() > 0 ) { return true; } else { return false; } } bool inStrCache(std::set cache, std::string str){ return (cache.find(str) != cache.end()); } bool TheoryQuant::hasGoodSemInst(const Expr& e, std::vector & boundVars, std::set >& instSet, size_t tBegin){ return false; } void genPartInstSetThm(const std::vector& bVarsThm, std::vector& bVarsTerm, const std::vector >& termInst, std::vector >& instSetThm){ ExprMap bVmap; for(size_t i=0; i< bVarsThm.size(); ++i) { bVmap[bVarsThm[i]]=true; } std::vector tempBVterm; std::vector locTerm; for (size_t j=0; j 0){ locTerm.push_back(1); tempBVterm.push_back(bVarsTerm[j]); } else{ locTerm.push_back(0); } } DebugAssert(locTerm.size() == bVarsTerm.size(), "locTerm.size !- bVarsTerm.size()"); for(std::vector >::const_iterator i=termInst.begin(), iend=termInst.end();i!=iend; i++) { std::vector buf; buf.clear(); for(size_t j=0; j< bVarsTerm.size(); ++j){ if(locTerm[j]) buf.push_back((*i)[j]); } instSetThm.push_back(buf); } bVarsTerm=tempBVterm; } void genInstSetThm(const std::vector& bVarsThm, const std::vector& bVarsTerm, const std::vector >& termInst, std::vector >& instSetThm){ std::vector bVmap; for(size_t i=0; i< bVarsThm.size(); ++i) { bVmap.push_back(-1); for (size_t j=0; j >::const_iterator i=termInst.begin(), iend=termInst.end();i!=iend; i++) { std::vector buf; buf.clear(); for(size_t j=0; j< bVarsThm.size(); ++j){ buf.push_back((*i)[bVmap[j]]); } instSetThm.push_back(buf); } } /* void TheoryQuant::synInst(const Theorem & univ, const CDList& allterms, size_t tBegin ){ if(d_useFullTrig){ synFullInst(univ, allterms, tBegin); } if(d_useMultTrig){ synMultInst(univ, allterms, tBegin); } if(d_usePartTrig){ synPartInst(univ, allterms, tBegin); } } */ inline bool TheoryQuant::transFound(const Expr& comb){ return (d_trans_found.count(comb) > 0); } inline void TheoryQuant::setTransFound(const Expr& comb){ d_trans_found[comb] = true; } inline bool TheoryQuant::trans2Found(const Expr& comb){ return (d_trans2_found.count(comb) > 0); } inline void TheoryQuant::setTrans2Found(const Expr& comb){ d_trans2_found[comb] = true; } inline CDList & TheoryQuant::backList(const Expr& ex){ if(d_trans_back.count(ex)>0){ return *d_trans_back[ex]; } else{ return null_cdlist; } } inline CDList & TheoryQuant::forwList(const Expr& ex){ if(d_trans_forw.count(ex)>0){ return *d_trans_forw[ex]; } else{ return null_cdlist; } } inline void TheoryQuant::pushBackList(const Expr& node, Expr ex){ if(d_trans_back.count(node)>0){ d_trans_back[node]->push_back(ex); } else{ d_trans_back[node] = new(true) CDList (theoryCore()->getCM()->getCurrentContext()); d_trans_back[node]->push_back(ex); } } inline void TheoryQuant::pushForwList(const Expr& node, Expr ex){ if(d_trans_forw.count(node)>0){ d_trans_forw[node]->push_back(ex); } else{ d_trans_forw[node] = new(true) CDList (theoryCore()->getCM()->getCurrentContext()); d_trans_forw[node]->push_back(ex); } } /* void TheoryQuant::synFullInst(const Theorem & univ, const CDList& allterms, size_t tBegin ){ const Expr& quantExpr = univ.getExpr(); // const std::vector& bVarsThm = quantExpr.getVars(); std::vector bVarsThm = quantExpr.getVars(); TRACE("quant inst", "try full inst with:|", quantExpr.toString() , " "); std::vector > instBindsThm; //set of instantiations for the thm, std::vector > instBindsTerm; //bindings, in the order of bVarsTrig std::vector instGterms; //instGterms are gterms matched, instBindsTerm and instGterms must have the same length std::vector bVarsTrig; if(*d_useTrigNew){ std::vector& new_trigs=d_fullTrigs[quantExpr]; for( size_t i= 0; i bind; bind.clear(); bind.push_back(sr); bind.push_back(dt); enqueueInst(univ, bind, gterm); TRACE("quant inst", "trans pred rule2 ", univ.toString(), " | with bind: "+vectorExpr2string(bind)); TRACE("quant trans", "trans2 ", vectorExpr2string(bind), ""); } } } } } return; } } {//code for trans pred if(trig.hasTr()){ // if(hasGoodSynInstNewTrig(trig, bVarsTrig, instBindsTerm, instGterms, allterms, tBegin)) { if(hasGoodSynInstNewTrig(trig, trig.getBVs(), instBindsTerm, instGterms, allterms, tBegin)) { for(size_t j=0; j& dtForw = forwList(dt); const CDList& srBack = backList(sr); for(size_t k=0; k bind; bind.clear(); bind.push_back(sr); bind.push_back(dt); bind.push_back(dtForw[k]); enqueueInst(univ, bind, gterm); TRACE("quant inst", "trans pred rule", univ.toString(), " | with bind: "+vectorExpr2string(bind)); TRACE("quant trans", "trans res forw: ", vectorExpr2string(bind), ""); } for(size_t k=0; k bind; bind.clear(); bind.push_back(srBack[k]); bind.push_back(sr); bind.push_back(dt); enqueueInst(univ, bind, gterm); TRACE("quant inst", "trans pred rule ", univ.toString(), " | with bind: "+vectorExpr2string(bind)); TRACE("quant trans", "trans res back: ", vectorExpr2string(bind), ""); } pushForwList(sr,dt); pushBackList(dt,sr); } } } } return; } } bool univsHasMoreBVs ; univsHasMoreBVs = (d_hasMoreBVs.count(quantExpr) > 0); // if ( !d_allout || !trig.isSimp() || univsHasMoreBVs || *d_useLazyInst){ // if ( !d_allout || !trig.isSimp() || univsHasMoreBVs || true){ if ( !d_allout || !trig.isSuperSimp() || univsHasMoreBVs ){ // if ( !d_allout || !trig.isSimp() || univsHasMoreBVs ){ */ /* if(hasGoodSynInstNewTrigOld(trig, bVarsTrig, instBindsTerm, instGterms, allterms, tBegin)) { genInstSetThm(bVarsThm, bVarsTrig, instBindsTerm, instBindsThm); for (size_t j = 0; j& binds = instBindsThm[j]; enqueueInst(univ, trig, binds, gterm); TRACE("quant inst", "insert full inst", univ.toString(), " | with bind: "+vectorExpr2string(binds)); } } */ /* bVarsTrig=trig.getBVs();//vVarsTrig is used later, do not forget this. if(hasGoodSynInstNewTrig(trig, bVarsThm, instBindsTerm, instGterms, allterms, tBegin)) { for (size_t j = 0; j& binds = instBindsTerm[j]; enqueueInst(univ, trig, binds, gterm); TRACE("quant inst", "insert full inst", univ.toString(), " | with bind: "+vectorExpr2string(binds)); } } } // if(!d_allout || *d_useLazyInst){ if(!d_allout){ if(trig.hasRW() ){ if(1 == bVarsTrig.size()){ std::vector tp = d_arrayIndic[trig.getHead()]; for(size_t i=0; i tp = d_arrayIndic[trig.getHead()]; Expr index = tp[i]; std::vector temp; temp.clear(); temp.push_back(index); enqueueInst(univ, temp, index); TRACE("quant inst", "read write rule", univ.toString(), " | with bind: "+vectorExpr2string(temp)); } } else{ } } } }//end for each trigger } } */ void TheoryQuant::arrayHeuristic(const Trigger& trig, size_t univ_id){ std::vector tp = d_arrayIndic[trig.head]; for(size_t i=0; i temp; temp.push_back(index); enqueueInst(univ_id, temp, index); // TRACE("quant inst", "read write rule", univ.toString(), " | with bind: "+vectorExpr2string(temp)); } } void TheoryQuant::synNewInst(size_t univ_id, const vector& bind, const Expr& gterm, const Trigger& trig ){ if(trig.isMulti){ const multTrigsInfo& mtriginfo = d_all_multTrigsInfo[trig.multiId]; vector actual_bind; for(size_t i=0, iend=bind.size(); i * cur_cd_map = mtriginfo.var_binds_found[index]; CDMap::iterator cur_iter = cur_cd_map->find(actual_bind_expr); if (cur_cd_map->end() != cur_iter){ return; } (*cur_cd_map)[actual_bind_expr] = true; const vector& comm_pos = mtriginfo.common_pos[0]; size_t comm_pos_size = comm_pos.size(); Expr comm_expr; vector comm_expr_vec; for(size_t i = 0; i < comm_pos_size; i++){ comm_expr_vec.push_back(bind[comm_pos[i]]); // cout<<"bind " < uncomm_expr_vec; const vector& uncomm_pos = mtriginfo.var_pos[index]; size_t uncomm_pos_size = uncomm_pos.size(); for(size_t i = 0; i< uncomm_pos_size; i++){ uncomm_expr_vec.push_back(bind[uncomm_pos[i]]); } uncomm_expr = Expr(RAW_LIST, uncomm_expr_vec); CDList* add_into_list ; CDList* iter_list; ExprMap* >::iterator add_into_iter; ExprMap* >::iterator iter_iter; size_t other_index = 0; if(0 == index){ other_index =1; } else if (1 == index){ other_index = 0; } else{ FatalAssert(false, "wrong "); } // cout<<"comm expr"<find(comm_expr); iter_iter = mtriginfo.uncomm_list[other_index]->find(comm_expr); if(mtriginfo.uncomm_list[index]->end() == add_into_iter){ add_into_list = new (true) CDList (theoryCore()->getCM()->getCurrentContext()); (*mtriginfo.uncomm_list[index])[comm_expr] = add_into_list; } else{ add_into_list = add_into_iter->second; } // cout<<"uncomm expr"<push_back(uncomm_expr); if(mtriginfo.uncomm_list[other_index]->end() == iter_iter){ return; } else{ iter_list = iter_iter->second; } const vector& uncomm_iter_pos = mtriginfo.var_pos[other_index]; size_t uncomm_iter_pos_size = uncomm_iter_pos.size(); for(size_t i =0, iend = iter_list->size(); i new_bind(bind); for(size_t j=0; j actual_bind; for(size_t i=0; i actual_bind; for(size_t i=0; i& dtForw = forwList(dt); const CDList& srBack = backList(sr); for(size_t k=0; k tri_bind; tri_bind.push_back(sr); tri_bind.push_back(dt); tri_bind.push_back(dtForw[k]); enqueueInst(univ_id, tri_bind, gterm); } for(size_t k=0; k tri_bind; tri_bind.push_back(srBack[k]); tri_bind.push_back(sr); tri_bind.push_back(dt); enqueueInst(univ_id, tri_bind, gterm); // TRACE("quant inst", "trans pred rule ", univ.toString(), " | with bind: "+vectorExpr2string(bind)); // TRACE("quant trans", "trans res back: ", vectorExpr2string(bind), ""); } pushForwList(sr,dt); pushBackList(dt,sr); } } return; } } // cout<<"before enqueueisnt"<& bind, const Expr& gterm, const Trigger& trig ){ // cout<<"synnewinst "< actual_bind; for(size_t i=0; i actual_bind; for(size_t i=0; i& dtForw = forwList(dt); const CDList& srBack = backList(sr); for(size_t k=0; k tri_bind; tri_bind.push_back(sr); tri_bind.push_back(dt); tri_bind.push_back(dtForw[k]); enqueueInst(univ_id, tri_bind, gterm); } for(size_t k=0; k tri_bind; tri_bind.push_back(srBack[k]); tri_bind.push_back(sr); tri_bind.push_back(dt); enqueueInst(univ_id, tri_bind, gterm); // TRACE("quant inst", "trans pred rule ", univ.toString(), " | with bind: "+vectorExpr2string(bind)); // TRACE("quant trans", "trans res back: ", vectorExpr2string(bind), ""); } pushForwList(sr,dt); pushBackList(dt,sr); } } return; } } // cout<<"before enqueueisnt"< tp = d_arrayIndic[trig.head]; for(size_t i=0; i tp = d_arrayIndic[trig.head]; Expr index = tp[i]; std::vector temp; temp.clear(); temp.push_back(index); enqueueInst(univ_id, temp, index); // TRACE("quant inst", "read write rule", univ.toString(), " | with bind: "+vectorExpr2string(temp)); } } else{ } } } } */ /* void TheoryQuant::synMultInst(const Theorem & univ, const CDList& allterms, size_t tBegin ){ const Expr& quantExpr = univ.getExpr(); if(d_multTriggers[quantExpr].size() <= 0) return ; TRACE("quant inst", "try muli with:|", quantExpr.toString() , " "); const std::vector& bVarsThm = quantExpr.getVars(); std::vector > instSetThm; //set of instantiations for the thm std::vector > termInst; //terminst are bindings, in the order of bVarsTrig std::vector bVarsTrig; if(hasGoodSynMultiInst(quantExpr, bVarsTrig, termInst, allterms, tBegin)) { genInstSetThm(bVarsThm, bVarsTrig, termInst, instSetThm); } { for(std::vector >::iterator i=instSetThm.begin(), iend=instSetThm.end(); i!=iend; ++i) { enqueueInst(univ, *i, null_expr);//fix the null_expr here asap TRACE("quant inst", "insert mult inst", univ.toString(), " | with bind: "+vectorExpr2string(*i)); } } } */ /* void TheoryQuant::synPartInst(const Theorem & univ, const CDList& allterms, size_t tBegin ){ const Expr& quantExpr = univ.getExpr(); TRACE("quant inst", "try part with ", quantExpr.toString() , " "); const std::vector& triggers = d_partTrigs[quantExpr]; std::vector > instSetThm; //set of instantiations for the thm std::vector > termInst; //terminst are bindings, in the order of bVarsTrig std::vector bVarsTrig; std::vector instGterms; for( std::vector::const_iterator i= triggers.begin(), iend=triggers.end();i!=iend;++i) { Trigger trig = *i; TRACE("quant inst","handle part trigger", trig.getEx().toString(),""); termInst.clear(); bVarsTrig.clear(); instSetThm.clear(); // if(hasGoodSynInstNewTrig(trig, bVarsTrig, termInst, instGterms,allterms, tBegin)) { if(hasGoodSynInstNewTrig(trig, trig.getBVs(), termInst, instGterms,allterms, tBegin)) { TRACE("quant syninst", "has good ", termInst.size(),""); TRACE("quant syninst", "after good ",instSetThm.size(), ""); Theorem newUniv = d_rules->adjustVarUniv(univ, trig.getBVs()); TRACE("quant syninst", " new univ:" ,newUniv.toString(),""); { for(size_t i = 0; i< termInst.size(); i++){ const std::vector& binds = termInst[i]; const Expr& gterm = instGterms[i]; enqueueInst(newUniv, binds, gterm); TRACE("quant yeting inst", "instantiating =========", "" , ""); TRACE("quant yeting inst", "instantiating", newUniv.getExpr().toString(), " | with bind: "+vectorExpr2string(binds)); TRACE("quant yeting inst", "instantiating org ", univ.getExpr().toString(), " | with gterm "+gterm.toString()); } } } } } */ void TheoryQuant::semInst(const Theorem & univ, size_t tBegin){ } void TheoryQuant::checkSat(bool fullEffort){ if(*d_translate) return; if(d_rawUnivs.size() <=0 ) return; DebugAssert(d_univsQueue.size() == 0, "something left in d_univsQueue"); DebugAssert(d_simplifiedThmQueue.size() == 0, "something left in d_univsQueue"); #ifdef DEBUG if(fullEffort){ if( CVC3::debugger.trace("quant assertfact") ){ cout<<"===========all cached univs =========="<::iterator i=d_simpUnivs.begin(), iend=d_simpUnivs.end(); i!=iend; i++){ // cout<<"------------------------------------"<first).toString()<second).getExpr().toString()<*>::iterator i=d_same_head_expr.begin(), iend=d_same_head_expr.end(); i!=iend; i++){ cout<<"------------------------------------"<first)< * terms= i->second; for(size_t i =0; isize(); i++){ cout<<(*terms)[i]<& allpreds = theoryCore()->getPredicates(); cout<<"=========== cur pred & terms =========="<& allterms = theoryCore()->getTerms(); for (size_t i=d_lastTermsPos; i& allpreds = theoryCore()->getPredicates(); cout<<"=========== cur pred equ =========="<& allterms = theoryCore()->getTerms(); for(size_t i=d_lastTermsPos; i0){ d_same_head_expr[getHead(t)]->push_back(t); } else{ d_same_head_expr[getHead(t)]= new(true) CDList (theoryCore()->getCM()->getCurrentContext()) ; d_same_head_expr[getHead(t)]->push_back(t); } } } const CDList& allpreds = theoryCore()->getPredicates(); for(size_t i=d_lastPredsPos; i0){ d_same_head_expr[getHead(t)]->push_back(t); } else{ d_same_head_expr[getHead(t)]= new(true) CDList (theoryCore()->getCM()->getCurrentContext()) ; d_same_head_expr[getHead(t)]->push_back(t); } } } } {//for the equalities list const CDList& allpreds = theoryCore()->getPredicates(); for(size_t i=d_lastPredsPos; i* >::iterator iter = d_eq_list.find(lterm); if(d_eq_list.end() == iter){ d_eq_list[lterm] = new(true) CDList (theoryCore()->getCM()->getCurrentContext()) ; d_eq_list[lterm]->push_back(rterm); } else{ iter->second->push_back(rterm); } // cout<<"LTERM: " < (theoryCore()->getCM()->getCurrentContext()) ; d_eq_list[rterm]->push_back(lterm); } else{ iter->second->push_back(lterm); } // cout<<"RTERM: " <& allterms = theoryCore()->getTerms(); for(size_t i=d_lastTermsPos; i* >* > new_trigs; for(size_t i=d_univs.size(); igetTerms().size()< (size_t)(*d_maxNaiveCall) ) { // cout<<"naive called"<getTerms().size()){ static int counter =0; std::set types; for(size_t i = 0; i cur_vars = cur_quant.getVars(); for(size_t j =0; j::iterator i=types.begin(), iend = types.end(); i != iend; i++){ counter++; std::stringstream tempout; tempout << counter; std::string out_str = base + tempout.str(); Expr newExpr = theoryCore()->getEM()->newVarExpr(out_str); newExpr.setType(Type(*i)); Proof pf; Expr newExpr2 = theoryCore()->getEM()->newVarExpr(out_str+"extra"); newExpr2.setType(Type(*i)); Expr newConstThm; if(Type(*i) == theoryCore()->getEM()->newRatExpr(0).getType()){ //somehow theory_arith will complain if we use expr2 to form the eq here newConstThm = newExpr.eqExpr(theoryCore()->getEM()->newRatExpr(0)); } else{ newConstThm = newExpr.eqExpr(newExpr2); } Theorem newThm = d_rules->addNewConst(newConstThm); enqueueFact(newThm); d_tempBinds.clear(); return; } } naiveCheckSat(fullEffort); } }//end of try catch (int x){ // d_simplifiedThmQueue.clear(); while(!d_simplifiedThmQueue.empty()){ d_simplifiedThmQueue.pop(); } d_tempBinds.clear(); saveContext(); delNewTrigs(new_trigs); return; } if(fullEffort) { sendInstNew(); } combineOldNewTrigs(new_trigs); delNewTrigs(new_trigs); } void TheoryQuant::saveContext(){ d_lastArrayPos.set(d_arrayTrigs.size()); d_univsSavedPos.set(d_univs.size()); d_rawUnivsSavedPos.set(d_rawUnivs.size()); d_lastTermsPos.set(theoryCore()->getTerms().size()); d_lastPredsPos.set(theoryCore()->getPredicates().size()); d_lastUsefulGtermsPos.set(d_usefulGterms.size()); } /*void TheoryQuant::synCheckSat(bool fullEffort){ } */ void TheoryQuant::synCheckSat(ExprMap* >* >& new_trigs, bool fullEffort){ d_allout=false; if(fullEffort) { setIncomplete("Quantifier instantiation"); } size_t uSize = d_univs.size() ; const CDList& allterms = theoryCore()->getTerms(); const CDList& allpreds = theoryCore()->getPredicates(); size_t tSize = allterms.size(); size_t pSize = allpreds.size(); TRACE("quant",uSize, " uSize and univsSavedPOS ", d_univsSavedPos); TRACE("quant",tSize, " tSize and termsLastPos ", d_lastTermsPos); TRACE("quant",pSize, " pSize and predsLastPos ", d_lastPredsPos); TRACE("quant", fullEffort, " fulleffort:scope ",theoryCore()->getCM()->scopeLevel() ); for(size_t i=d_lastTermsPos; i 0){ TRACE("inend", "debug 1", "" ,"" ); return; } d_allout = true; { CDList* changed_terms = new (false) CDList (theoryCore()->getCM()->getCurrentContext()) ; collectChangedTerms(*changed_terms); matchListOld(*changed_terms, 0, changed_terms->size()); matchListNew(new_trigs, *changed_terms, 0 , changed_terms->size()); delete changed_terms; } int n; if( ( n = sendInstNew()) > 0){ TRACE("inend", "debug 2", " # ",n ); return; } d_allout = false; int numNewTerm=0; int oldNum=d_usefulGterms.size(); for(size_t i=0; i d_curMaxExprScore){ if((d_curMaxExprScore + 1) == score){ d_usefulGterms.push_back(cur); add_parent(cur); numNewTerm++; } else{ TRACE("inend", "is this good? ", cur.toString()+" #-# " , score); d_usefulGterms.push_back(cur); add_parent(cur); numNewTerm++; } } } for(size_t i=0; i d_curMaxExprScore){ if((d_curMaxExprScore + 1) == score){ d_usefulGterms.push_back(cur); add_parent(cur); numNewTerm++; } else{ TRACE("inend", "is this good? ", cur.toString()+" #-# " , score); d_usefulGterms.push_back(cur); add_parent(cur); numNewTerm++; } } } if(numNewTerm >0 ){ if(d_curMaxExprScore >=0 ){ d_curMaxExprScore = d_curMaxExprScore+1;; } else { d_curMaxExprScore = d_curMaxExprScore+1; } matchListOld(d_usefulGterms, oldNum, d_usefulGterms.size() ); matchListNew(new_trigs, d_usefulGterms, oldNum, d_usefulGterms.size()); if(sendInstNew() > 0){ TRACE("inend", "debug 3", "" , "" ); return; } } for(size_t array_index = 0; array_index < d_arrayTrigs.size(); array_index++){ arrayHeuristic(d_arrayTrigs[array_index].trig, d_arrayTrigs[array_index].univ_id); } return ; } TRACE("inend", "debug 3 0", "", ""); TRACE("quant","this round; ",d_callThisRound,""); return; } if ((uSize == d_univsSavedPos) && (tSize == d_lastTermsPos) && (pSize == d_lastPredsPos) ) return; matchListOld(d_usefulGterms, d_lastUsefulGtermsPos,d_usefulGterms.size() ); //new terms to old list matchListNew(new_trigs, d_usefulGterms, 0, d_usefulGterms.size() ); //new and old terms to new list for(size_t array_index = d_lastArrayPos; array_index < d_arrayTrigs.size(); array_index++){ arrayHeuristic(d_arrayTrigs[array_index].trig, d_arrayTrigs[array_index].univ_id); } TRACE("quant","this round; ",d_callThisRound,""); return; } void TheoryQuant::semCheckSat(bool fullEffort){ } //the following is old code and I did not modify much, Yeting void TheoryQuant::naiveCheckSat(bool fullEffort){ TRACE("quant", "checkSat ", fullEffort, "{"); IF_DEBUG(int instCount = d_instCount); size_t uSize = d_univs.size(), stSize = d_savedTerms.size(); if(true || (fullEffort && uSize > 0)) { // First of all, this algorithm is incomplete setIncomplete("Quantifier instantiation"); if(d_instCount>=*d_maxQuantInst) return; //first attempt to instantiate with the saved terms //only do this if there are new saved terms or new theroems and // at least some saved terms bool savedOnly = ((uSize > d_univsSavedPos.get() && stSize > 0) || (stSize > d_savedTermsPos.get())); int origCount = d_instCount; if(savedOnly) { TRACE("quant", "checkSat [saved insts]: univs size = ", uSize , " "); for(size_t i=0, pos = d_univsSavedPos.get(); i= *d_maxQuantInst) break; else instantiate(d_univs[i], i>=pos, true, d_savedTermsPos.get()); } d_univsSavedPos.set(d_univs.size()); d_savedTermsPos.set(stSize); } if(!savedOnly || d_instCount == origCount) { //instantiate with context dependent assertions terms TRACE("quant", "checkSat [context insts]: univs size = ", uSize , " "); const CDList& assertions = theoryCore()->getTerms(); int origSize = d_contextTerms.size(); // for(size_t i=0; i= *d_maxQuantInst) break; else instantiate(d_univs[i], i>=pos, false, origSize); } d_univsContextPos.set(d_univs.size()); } TRACE("quant terse", "checkSat total insts: ", d_instCount, ", new "+int2string(d_instCount - instCount)); } TRACE("quant", "checkSat total insts: ", d_instCount, " "); TRACE("quant", "checkSat new insts: ", d_instCount - instCount, " "); TRACE("quant", "checkSat effort:", fullEffort, " }"); } /*! \brief Queues up all possible instantiations of bound * variables. * * The savedMap boolean indicates whether to use savedMap or * d_contextMap the all boolean indicates weather to use all * instantiation or only new ones and newIndex is the index where * new instantiations begin. */ void TheoryQuant::instantiate(Theorem univ, bool all, bool savedMap, size_t newIndex) { if(!all && ((savedMap && newIndex == d_savedTerms.size()) ||(!savedMap && newIndex == d_contextTerms.size()))) return; TRACE("quant", "instanitate", all , "{"); std::vector varReplacements; recInstantiate(univ, all, savedMap, newIndex, varReplacements); TRACE("quant", "instanitate", "", "}"); } //! does most of the work of the instantiate function. void TheoryQuant::recInstantiate(Theorem& univ, bool all, bool savedMap, size_t newIndex, std::vector& varReplacements) { Expr quantExpr = univ.getExpr(); const vector& boundVars = quantExpr.getVars(); size_t curPos = varReplacements.size(); TRACE("quant", "recInstantiate: ", boundVars.size() - curPos, ""); //base case: a full vector of instantiations exists if(curPos == boundVars.size()) { if(!all) return; Theorem t = d_rules->universalInst(univ, varReplacements); d_insts[t.getExpr()] = varReplacements; TRACE("quant", "recInstantiate => " , t.toString(), ""); if(d_instCount< *d_maxQuantInst) { d_instCount=d_instCount+1; enqueueInst(univ, varReplacements, null_expr); // enqueueInst(univ, t); // enqueueFact(t); } return; } //recursively add all possible instantiations in the next //available space of the vector else { Type t = getBaseType(boundVars[curPos]); int iendC=0, iendS=0, iend; std::vector* typeVec = NULL; // = d_savedMap[t]; CDList* typeList = NULL; // = *d_contextMap[t]; if(d_savedMap.count(t) > 0) { typeVec = &(d_savedMap[t]); iendS = typeVec->size(); TRACE("quant", "adding from savedMap: ", iendS, ""); } if(!savedMap) { if(d_contextMap.count(t) > 0) { typeList = d_contextMap[t]; iendC = typeList->size(); TRACE("quant", "adding from contextMap:", iendC , ""); } } iend = iendC + iendS; for(int i =0; i& terms) { Expr trExpr=trueExpr(), flsExpr = falseExpr(); Type boolT = boolType(); if(d_contextMap.count(boolT) == 0) { d_contextMap[boolT] = new(true) CDList(theoryCore()->getCM()->getCurrentContext()); size_t pos = d_contextTerms.size(); d_contextTerms.push_back(trExpr); d_contextTerms.push_back(flsExpr); (*d_contextMap[boolT]).push_back(pos); (*d_contextMap[boolT]).push_back(pos+1); } for(size_t i=0; i0) { return(d_contextCache[e]); } if(e.arity()>0) { for(Expr::iterator it = e.begin(), iend = e.end(); it!=iend; ++it) //maps the children and returns a bool if(recursiveMap(*it) == false) { d_contextCache[e] = false; } } else if(e.getKind() == EXISTS || e.getKind() == FORALL){ //maps the body if(recursiveMap(e.getBody())==false) { d_contextCache[e]=false; } } //found a bound variable in the children if(d_contextCache.count(e)>0) { return false; } if(d_savedCache.count(e) > 0) { return true; } Type type = getBaseType(e); if(!type.isBool() && !(e.getKind()==BOUND_VAR)){ TRACE("quant", "recursiveMap: found ", e.toString() + " of type " + type.toString(), ""); int pos = d_contextTerms.size(); d_contextTerms.push_back(e); if(d_contextMap.count(type)==0) d_contextMap[type] = new(true) CDList(theoryCore()->getCM()->getCurrentContext()); (*d_contextMap[type]).push_back(pos); } if(e.getKind() == BOUND_VAR) { d_contextCache[e] = false; return false; } else { d_contextCache[e] = true; return true; } //need to implement: //insert all instantiations if type is finite and reasonable //also need to implement instantiations of subtypes } /*!\brief Used to notify the quantifier algorithm of possible * instantiations that were used in proving a context inconsistent. */ void TheoryQuant::notifyInconsistent(const Theorem& thm){ #ifdef DEBUG if( CVC3::debugger.trace("quant inscon") ){ cout<<"the one caused incsonsistency"< assump; thm.getLeafAssumptions(assump); cout<<"===========leaf assumptions; =========="<::iterator i=assump.begin(), iend=assump.end(); i!=iend; i++){ cout<<">>"<toString()< 0) { vector& insts = d_insts[e]; int pos; for(vector::iterator it = insts.begin(), iend = insts.end(); it!=iend ; ++it) { if(d_savedCache.count(*it) == 0) { TRACE("quant", "notifyInconsistent: found:", (*it).toString(), ""); d_savedCache[*it] = true; pos = d_savedTerms.size(); d_savedTerms.push_back(*it); d_savedMap[getBaseType(*it)].push_back(pos); } } } if(thm.isAssump()) return; const Assumptions& a = thm.getAssumptionsRef(); for(Assumptions::iterator it =a.begin(), iend = a.end(); it!=iend; ++it){ findInstAssumptions(*it); } } //! computes the type of a quantified term. Always a boolean. void TheoryQuant::computeType(const Expr& e) { switch (e.getKind()) { case FORALL: case EXISTS: { if(!e.getBody().getType().isBool()) throw TypecheckException("Type mismatch for expression:\n\n " + e.getBody().toString() + "\n\nhas the following type:\n\n " + e.getBody().getType().toString() + "\n\nbut the expected type is Boolean:\n\n "); else e.setType(e.getBody().getType()); break; } default: DebugAssert(false,"Unexpected kind in Quantifier Theory: " + e.toString()); break; } } /*! * TCC(forall x.phi(x)) = (forall x. TCC(phi(x))) * OR (exists x. TCC(phi(x)) & !phi(x)) * TCC(exists x.phi(x)) = (forall x. TCC(phi(x))) * OR (exists x. TCC(phi(x)) & phi(x)) */ Expr TheoryQuant::computeTCC(const Expr& e) { DebugAssert(e.isQuantifier(), "Unexpected expression in Quantifier Theory: " + e.toString()); bool forall(e.getKind() == FORALL); const Expr& phi = e.getBody(); Expr tcc_phi = getTCC(phi); Expr forall_tcc = getEM()->newClosureExpr(FORALL, e.getVars(), tcc_phi); Expr exists_tcc = getEM()->newClosureExpr(EXISTS, e.getVars(), tcc_phi && (forall? !phi : phi)); return (forall_tcc || exists_tcc); } ExprStream& TheoryQuant::print(ExprStream& os, const Expr& e) { switch(os.lang()) { case SIMPLIFY_LANG: { switch(e.getKind()){ case FORALL: case EXISTS: { if(!e.isQuantifier()) { e.print(os); break; } os << "(" << ((e.getKind() == FORALL)? "FORALL" : "EXISTS"); const vector& vars = e.getVars(); bool first(true); os << "(" ; for(vector::const_iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) { if(first) first = false; else os << " " ; os << *i; // The quantifier may be in a raw parsed form, in which case // the type is not assigned yet //if(i->isVar()) // simplify do not need type // os << ":" << space << pushdag << (*i).getType() << popdag; } os << ") " << e.getBody() << ")"; } break; default: e.print(os); break; } break; } case PRESENTATION_LANG: { switch(e.getKind()){ case FORALL: case EXISTS: { if(!e.isQuantifier()) { e.print(os); break; } os << "(" << push << ((e.getKind() == FORALL)? "FORALL" : "EXISTS") << space << push; const vector& vars = e.getVars(); bool first(true); os << "(" << push; for(vector::const_iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) { if(first) first = false; else os << push << "," << pop << space; os << *i; // The quantifier may be in a raw parsed form, in which case // the type is not assigned yet // the following lines are changed for a neat output / by yeting if(*d_translate || true){ if(i->isVar()) os << ":" << space << pushdag << (*i).getType() << popdag; } } os << push << "): " << pushdag << push << e.getBody() << push << ")"; } break; default: e.print(os); break; } break; } case SMTLIB_LANG: { d_theoryUsed = true; switch(e.getKind()){ case FORALL: case EXISTS: { if(!e.isQuantifier()) { e.print(os); break; } os << "(" << push << ((e.getKind() == FORALL)? "forall" : "exists") << space; const vector& vars = e.getVars(); bool first(true); // os << "(" << push; for(vector::const_iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) { if(first) first = false; else os << space; os << "(" << push << *i; // The quantifier may be in a raw parsed form, in which case // the type is not assigned yet if(i->isVar()) os << space << pushdag << (*i).getType() << popdag; os << push << ")" << pop << pop; } os << space << pushdag << e.getBody() << push << ")"; break; } default: throw SmtlibException("TheoryQuant::print: SMTLIB_LANG: Unexpected expression: " +getEM()->getKindName(e.getKind())); break; } break; } // End of SMTLIB_LANG case LISP_LANG: { switch(e.getKind()){ case FORALL: case EXISTS: { if(!e.isQuantifier()) { e.print(os); break; } os << "(" << push << ((e.getKind() == FORALL)? "FORALL" : "EXISTS") << space; const vector& vars = e.getVars(); bool first(true); os << "(" << push; for(vector::const_iterator i=vars.begin(), iend=vars.end(); i!=iend; ++i) { if(first) first = false; else os << space; os << "(" << push << *i; // The quantifier may be in a raw parsed form, in which case // the type is not assigned yet if(i->isVar()) os << space << pushdag << (*i).getType() << popdag; os << push << ")" << pop << pop; } os << push << ")" << pop << pop << pushdag << e.getBody() << push << ")"; } break; default: e.print(os); break; } break; } default: e.print(os); break; } return os; } /////////////////////////////////////////////////////////////////////////////// //parseExprOp: //translating special Exprs to regular EXPR?? /////////////////////////////////////////////////////////////////////////////// Expr TheoryQuant::parseExprOp(const Expr& e) { TRACE("parser", "TheoryQuant::parseExprOp(", e, ")"); // If the expression is not a list, it must have been already // parsed, so just return it as is. if(RAW_LIST != e.getKind()) return e; DebugAssert(e.arity() > 0, "TheoryQuant::parseExprOp:\n e = "+e.toString()); const Expr& c1 = e[0][0]; const string& opName(c1.getString()); int kind = getEM()->getKind(opName); switch(kind) { case FORALL: case EXISTS: { // (OP ((v1 ... vn tp1) ...) body) if(!(e.arity() == 3 && e[1].getKind() == RAW_LIST && e[1].arity() > 0)) throw ParserException("Bad "+opName+" expression: "+e.toString()); // Iterate through the groups of bound variables vector > vars; // temporary stack of bound variables for(Expr::iterator i=e[1].begin(), iend=e[1].end(); i!=iend; ++i) { if(i->getKind() != RAW_LIST || i->arity() < 2) throw ParserException("Bad variable declaration block in "+opName +" expression: "+i->toString() +"\n e = "+e.toString()); // Iterate through individual bound vars in the group. The // last element is the type, which we have to rebuild and // parse, since it is used in the creation of bound variables. Type tp(parseExpr((*i)[i->arity()-1])); if (tp == boolType()) { throw ParserException("A quantified variable may not be of type BOOLEAN"); } for(int j=0, jend=i->arity()-1; j