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; }
void BitblastSolver::preRegister(TNode node) { if ((node.getKind() == kind::EQUAL || node.getKind() == kind::BITVECTOR_ULT || node.getKind() == kind::BITVECTOR_ULE || node.getKind() == kind::BITVECTOR_SLT || node.getKind() == kind::BITVECTOR_SLE) && !d_bitblaster->hasBBAtom(node)) { CodeTimer weightComputationTime(d_bv->d_statistics.d_weightComputationTimer); d_bitblastQueue.push_back(node); if ((options::decisionUseWeight() || options::decisionThreshold() != 0) && !node.hasAttribute(decision::DecisionWeightAttr())) { node.setAttribute(decision::DecisionWeightAttr(),computeAtomWeight(node)); } } }
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; }
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; }
void setMostFrequentValueCount(TNode store, uint64_t count) { return store.setAttribute(ArrayConstantMostFrequentValueCountAttr(), count); }
void setMostFrequentValue(TNode store, TNode value) { return store.setAttribute(ArrayConstantMostFrequentValueAttr(), value); }