bool InequalitySolver::isInequalityOnly(TNode node) { if (node.getKind() == kind::NOT) { node = node[0]; } if (node.getAttribute(IneqOnlyComputedAttribute())) { return node.getAttribute(IneqOnlyAttribute()); } if (node.getKind() != kind::EQUAL && node.getKind() != kind::BITVECTOR_ULT && node.getKind() != kind::BITVECTOR_ULE && node.getKind() != kind::CONST_BITVECTOR && node.getKind() != kind::SELECT && node.getKind() != kind::STORE && node.getMetaKind() != kind::metakind::VARIABLE) { // not worth caching return false; } bool res = true; for (unsigned i = 0; res && i < node.getNumChildren(); ++i) { res = res && isInequalityOnly(node[i]); } node.setAttribute(IneqOnlyComputedAttribute(), true); node.setAttribute(IneqOnlyAttribute(), res); return res; }
RewriteResponse QuantifiersRewriter::postRewrite(TNode in) { Trace("quantifiers-rewrite-debug") << "post-rewriting " << in << " " << in.hasAttribute(NestedQuantAttribute()) << std::endl; if( in.getKind()==kind::EXISTS || in.getKind()==kind::FORALL ){ RewriteStatus status = REWRITE_DONE; Node ret = in; //get the arguments std::vector< Node > args; for( int i=0; i<(int)in[0].getNumChildren(); i++ ){ args.push_back( in[0][i] ); } //get the instantiation pattern list Node ipl; if( in.getNumChildren()==3 ){ ipl = in[2]; } //get the body if( in.getKind()==EXISTS ){ std::vector< Node > children; children.push_back( in[0] ); children.push_back( in[1].negate() ); if( in.getNumChildren()==3 ){ children.push_back( in[2] ); } ret = NodeManager::currentNM()->mkNode( FORALL, children ); ret = ret.negate(); status = REWRITE_AGAIN_FULL; }else{ bool isNested = in.hasAttribute(NestedQuantAttribute()); for( int op=0; op<COMPUTE_LAST; op++ ){ if( doOperation( in, isNested, op ) ){ ret = computeOperation( in, op ); if( ret!=in ){ status = REWRITE_AGAIN_FULL; break; } } } } //print if changed if( in!=ret ){ if( in.hasAttribute(NestedQuantAttribute()) ){ setNestedQuantifiers( ret, in.getAttribute(NestedQuantAttribute()) ); } Trace("quantifiers-rewrite") << "*** rewrite " << in << std::endl; Trace("quantifiers-rewrite") << " to " << std::endl; Trace("quantifiers-rewrite") << ret << std::endl; } return RewriteResponse( status, ret ); } return RewriteResponse(REWRITE_DONE, in); }
void TheoryUFTim::merge() { while(d_currentPendingIdx < d_pending.size() ) { Node assertion = d_pending[d_currentPendingIdx]; d_currentPendingIdx = d_currentPendingIdx + 1; TNode x = assertion[0]; TNode y = assertion[1]; ECData* tmpX = x.getAttribute(ECAttr()); ECData* tmpY = y.getAttribute(ECAttr()); ECData* ecX = ccFind(tmpX); ECData* ecY = ccFind(tmpY); if(ecX == ecY) continue; Debug("uf") << "merging equivalence classes for " << std::endl; Debug("uf") << "left equivalence class :" << (ecX->getRep()) << std::endl; Debug("uf") << "right equivalence class :" << (ecY->getRep()) << std::endl; Debug("uf") << std::endl; ccUnion(ecX, ecY); } }
RewriteResponse QuantifiersRewriter::preRewrite(TNode in) { Trace("quantifiers-rewrite-debug") << "pre-rewriting " << in << " " << in.hasAttribute(NestedQuantAttribute()) << std::endl; if( in.getKind()==kind::EXISTS || in.getKind()==kind::FORALL ){ if( !in.hasAttribute(NestedQuantAttribute()) ){ setNestedQuantifiers( in[ 1 ], in ); } std::vector< Node > args; for( int i=0; i<(int)in[0].getNumChildren(); i++ ){ args.push_back( in[0][i] ); } Node body = in[1]; bool doRewrite = false; while( body.getNumChildren()>=2 && body.getKind()==in.getKind() ){ for( int i=0; i<(int)body[0].getNumChildren(); i++ ){ args.push_back( body[0][i] ); } body = body[1]; doRewrite = true; } if( doRewrite ){ std::vector< Node > children; children.push_back( NodeManager::currentNM()->mkNode(kind::BOUND_VAR_LIST,args) ); children.push_back( body ); if( in.getNumChildren()==3 ){ children.push_back( in[2] ); } Node n = NodeManager::currentNM()->mkNode( in.getKind(), children ); if( in!=n ){ if( in.hasAttribute(NestedQuantAttribute()) ){ setNestedQuantifiers( n, in.getAttribute(NestedQuantAttribute()) ); } Trace("quantifiers-pre-rewrite") << "*** pre-rewrite " << in << std::endl; Trace("quantifiers-pre-rewrite") << " to " << std::endl; Trace("quantifiers-pre-rewrite") << n << std::endl; } return RewriteResponse(REWRITE_DONE, n); } } return RewriteResponse(REWRITE_DONE, in); }
void TheoryUFTim::registerTerm(TNode n) { Debug("uf") << "uf: begin registerTerm(" << n << ")" << std::endl; d_registered.push_back(n); ECData* ecN; if(n.getAttribute(ECAttr(), ecN)) { /* registerTerm(n) is only called when a node has not been seen in the * current context. ECAttr() is not a context-dependent attribute. * When n.hasAttribute(ECAttr(),...) is true on a registerTerm(n) call, * then it must be the case that this attribute was created in a previous * and no longer valid context. Because of this we have to reregister the * predecessors lists. * Also we do not have to worry about duplicates because all of the Link* * setup before are removed when the context n was setup in was popped out * of. All we are going to do here are sanity checks. */ /* * Consider the following chain of events: * 1) registerTerm(n) is called on node n where n : f(m) in context level X, * 2) A new ECData is created on the heap, ecN, * 3) n is added to the predessecor list of m in context level X, * 4) We pop out of X, * 5) n is removed from the predessecor list of m because this is context * dependent, the Link* will be destroyed and pointers to the Link * structs in the ECData objects will be updated. * 6) registerTerm(n) is called on node n in context level Y, * 7) If n.hasAttribute(ECAttr(), &ecN), then ecN is still around, * but the predecessor list is not * * The above assumes that the code is working correctly. */ Assert(ecN->getFirst() == NULL, "Equivalence class data exists for the node being registered. " "Expected getFirst() == NULL. " "This data is either already in use or was not properly maintained " "during backtracking"); /*Assert(ecN->getLast() == NULL, "Equivalence class data exists for the node being registered. " "Expected getLast() == NULL. " "This data is either already in use or was not properly maintained " "during backtracking.");*/ Assert(ecN->isClassRep(), "Equivalence class data exists for the node being registered. " "Expected isClassRep() to be true. " "This data is either already in use or was not properly maintained " "during backtracking"); Assert(ecN->getWatchListSize() == 0, "Equivalence class data exists for the node being registered. " "Expected getWatchListSize() == 0. " "This data is either already in use or was not properly maintained " "during backtracking"); } else { //The attribute does not exist, so it is created and set ecN = new (true) ECData(getContext(), n); n.setAttribute(ECAttr(), ecN); } /* If the node is an APPLY_UF, we need to add it to the predecessor list * of its children. */ if(n.getKind() == APPLY_UF) { TNode::iterator cIter = n.begin(); for(; cIter != n.end(); ++cIter) { TNode child = *cIter; /* Because this can be called after nodes have been merged, we need * to lookup the representative in the UnionFind datastructure. */ ECData* ecChild = ccFind(child.getAttribute(ECAttr())); /* Because this can be called after nodes have been merged we may need * to be merged with other predecessors of the equivalence class. */ for(Link* Px = ecChild->getFirst(); Px != NULL; Px = Px->d_next ) { if(equiv(n, Px->d_data)) { Node pend = n.eqNode(Px->d_data); d_pending.push_back(pend); } } ecChild->addPredecessor(n); } } Debug("uf") << "uf: end registerTerm(" << n << ")" << std::endl; }
bool TheoryUFTim::sameCongruenceClass(TNode x, TNode y) { return ccFind(x.getAttribute(ECAttr())) == ccFind(y.getAttribute(ECAttr())); }
PreprocessingPassResult SynthRewRulesPass::applyInternal( AssertionPipeline* assertionsToPreprocess) { Trace("synth-rr-pass") << "Synthesize rewrite rules from assertions..." << std::endl; std::vector<Node>& assertions = assertionsToPreprocess->ref(); // compute the variables we will be sampling std::vector<Node> vars; unsigned nsamples = options::sygusSamples(); Options& nodeManagerOptions = NodeManager::currentNM()->getOptions(); // attribute to mark processed terms SynthRrComputedAttribute srrca; // initialize the candidate rewrite std::unique_ptr<theory::quantifiers::CandidateRewriteDatabaseGen> crdg; std::unordered_map<TNode, bool, TNodeHashFunction> visited; std::unordered_map<TNode, bool, TNodeHashFunction>::iterator it; std::vector<TNode> visit; // two passes: the first collects the variables, the second registers the // terms for (unsigned r = 0; r < 2; r++) { visited.clear(); visit.clear(); TNode cur; for (const Node& a : assertions) { visit.push_back(a); do { cur = visit.back(); visit.pop_back(); it = visited.find(cur); // if already processed, ignore if (cur.getAttribute(SynthRrComputedAttribute())) { Trace("synth-rr-pass-debug") << "...already processed " << cur << std::endl; } else if (it == visited.end()) { Trace("synth-rr-pass-debug") << "...preprocess " << cur << std::endl; visited[cur] = false; Kind k = cur.getKind(); bool isQuant = k == kind::FORALL || k == kind::EXISTS || k == kind::LAMBDA || k == kind::CHOICE; // we recurse on this node if it is not a quantified formula if (!isQuant) { visit.push_back(cur); for (const Node& cc : cur) { visit.push_back(cc); } } } else if (!it->second) { Trace("synth-rr-pass-debug") << "...postprocess " << cur << std::endl; // check if all of the children are valid // this ensures we do not register terms that have e.g. quantified // formulas as subterms bool childrenValid = true; for (const Node& cc : cur) { Assert(visited.find(cc) != visited.end()); if (!visited[cc]) { childrenValid = false; } } if (childrenValid) { Trace("synth-rr-pass-debug") << "...children are valid, check rewrites..." << std::endl; if (r == 0) { if (cur.isVar()) { vars.push_back(cur); } } else { Trace("synth-rr-pass-debug") << "Add term " << cur << std::endl; // mark as processed cur.setAttribute(srrca, true); bool ret = crdg->addTerm(cur, *nodeManagerOptions.getOut()); Trace("synth-rr-pass-debug") << "...return " << ret << std::endl; // if we want only rewrites of minimal size terms, we would set // childrenValid to false if ret is false here. } } visited[cur] = childrenValid; } } while (!visit.empty()); } if (r == 0) { Trace("synth-rr-pass-debug") << "Initialize with " << nsamples << " samples and variables : " << vars << std::endl; crdg = std::unique_ptr<theory::quantifiers::CandidateRewriteDatabaseGen>( new theory::quantifiers::CandidateRewriteDatabaseGen(vars, nsamples)); } } Trace("synth-rr-pass") << "...finished " << std::endl; return PreprocessingPassResult::NO_CONFLICT; }
uint64_t getMostFrequentValueCount(TNode store) { return store.getAttribute(ArrayConstantMostFrequentValueCountAttr()); }
Node getMostFrequentValue(TNode store) { return store.getAttribute(ArrayConstantMostFrequentValueAttr()); }