/*****************************************************************************/
/*!
* \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