Node CVC4::theory::bv::mergeExplanations(const std::vector<Node>& expls) { TNodeSet literals; for (unsigned i = 0; i < expls.size(); ++i) { TNode expl = expls[i]; Assert (expl.getType().isBoolean()); if (expl.getKind() == kind::AND) { for (unsigned i = 0; i < expl.getNumChildren(); ++i) { TNode child = expl[i]; if (child == utils::mkTrue()) continue; literals.insert(child); } } else if (expl != utils::mkTrue()) { literals.insert(expl); } } if (literals.size() == 0) return utils::mkTrue(); if (literals.size() == 1) return *literals.begin(); NodeBuilder<> nb(kind::AND); for (TNodeSet::const_iterator it = literals.begin(); it!= literals.end(); ++it) { nb << *it; } return nb; }
void AbstractionModule::collectArguments(TNode node, TNode signature, std::vector<Node>& args, TNodeSet& seen) { if (seen.find(node)!= seen.end()) return; if (node.getKind() == kind::VARIABLE || node.getKind() == kind::CONST_BITVECTOR) { // a constant in the node can either map to an argument of the abstraction // or can be hard-coded and part of the abstraction if (signature.getKind() == kind::SKOLEM) { args.push_back(node); seen.insert(node); } else { Assert (signature.getKind() == kind::CONST_BITVECTOR); } // return; } Assert (node.getKind() == signature.getKind() && node.getNumChildren() == signature.getNumChildren()); for (unsigned i = 0; i < node.getNumChildren(); ++i) { collectArguments(node[i], signature[i], args, seen); seen.insert(node); } }
TNodeSet PhiNode::getRealValues() { TNodeSet values; for (std::size_t i = 0; i < m_incomingList.size(); i++) { if (PhiNode* const phi = m_incomingList[i].node->cast<PhiNode>()) { const TNodeSet& realValues = phi->getRealValues(); values.insert(realValues.begin(), realValues.end()); } else { values.insert(m_incomingList[i].node); } } return values; }
void AbstractionModule::collectArgumentTypes(TNode sig, std::vector<TypeNode>& types, TNodeSet& seen) { if (seen.find(sig) != seen.end()) return; if (sig.getKind() == kind::SKOLEM) { types.push_back(sig.getType()); seen.insert(sig); return; } for (unsigned i = 0; i < sig.getNumChildren(); ++i) { collectArgumentTypes(sig[i], types, seen); seen.insert(sig); } }
void ArithStaticLearner::staticLearning(TNode n, NodeBuilder<>& learned){ vector<TNode> workList; workList.push_back(n); TNodeSet processed; //Contains an underapproximation of nodes that must hold. TNodeSet defTrue; defTrue.insert(n); while(!workList.empty()) { n = workList.back(); bool unprocessedChildren = false; for(TNode::iterator i = n.begin(), iend = n.end(); i != iend; ++i) { if(processed.find(*i) == processed.end()) { // unprocessed child workList.push_back(*i); unprocessedChildren = true; } } if(n.getKind() == AND && defTrue.find(n) != defTrue.end() ){ for(TNode::iterator i = n.begin(), iend = n.end(); i != iend; ++i) { defTrue.insert(*i); } } if(unprocessedChildren) { continue; } workList.pop_back(); // has node n been processed in the meantime ? if(processed.find(n) != processed.end()) { continue; } processed.insert(n); process(n,learned, defTrue); } }
void ExtractSkolemizer::collectExtracts(TNode node, TNodeSet& seen) { if (seen.find(node) != seen.end()) { return; } if (node.getKind() == kind::BITVECTOR_EXTRACT && node[0].getMetaKind() == kind::metakind::VARIABLE) { unsigned high = utils::getExtractHigh(node); unsigned low = utils::getExtractLow(node); TNode var = node[0]; storeExtract(var, high, low); seen.insert(node); return; } if (node.getNumChildren() == 0) return; for (unsigned i = 0; i < node.getNumChildren(); ++i) { collectExtracts(node[i], seen); } seen.insert(node); }
bool AbstractionModule::isConjunctionOfAtomsRec(TNode node, TNodeSet& seen) { if (seen.find(node)!= seen.end()) return true; if (!node.getType().isBitVector()) { return (node.getKind() == kind::AND || utils::isBVPredicate(node)); } if (node.getNumChildren() == 0) return true; for (unsigned i = 0; i < node.getNumChildren(); ++i) { if (!isConjunctionOfAtomsRec(node[i], seen)) return false; } seen.insert(node); return true; }
unsigned QuickXPlain::selectUnsatCore(unsigned low, unsigned high, std::vector<TNode>& conflict) { Assert(!d_solver->getConflict().isNull() && d_solver->inConflict()); Node query_confl = d_solver->getConflict(); // conflict wasn't actually minimized if (query_confl.getNumChildren() == high - low + 1) { return high; } TNodeSet nodes; for (unsigned i = low; i <= high; i++) { nodes.insert(conflict[i]); } unsigned write = low; for (unsigned i = 0; i < query_confl.getNumChildren(); ++i) { TNode current = query_confl[i]; // the conflict can have nodes in lower decision levels if (nodes.find(current) != nodes.end()) { conflict[write++] = current; nodes.erase(nodes.find(current)); } } // if all of the nodes in the conflict were on a lower level if (write == low) { return low; } Assert (write != 0); unsigned new_high = write - 1; for (TNodeSet::const_iterator it = nodes.begin(); it != nodes.end(); ++it) { conflict[write++] = *it; } Assert (write -1 == high); Assert (new_high <= high); return new_high; }
bool hasExpensiveBVOperatorsRec(TNode fact, TNodeSet& seen) { if (fact.getKind() == kind::BITVECTOR_MULT || fact.getKind() == kind::BITVECTOR_UDIV_TOTAL || fact.getKind() == kind::BITVECTOR_UREM_TOTAL) { return true; } if (seen.find(fact) != seen.end()) return false; if (fact.getNumChildren() == 0) return false; for (unsigned i = 0; i < fact.getNumChildren(); ++i) { bool difficult = hasExpensiveBVOperatorsRec(fact[i], seen); if (difficult) return true; } seen.insert(fact); return false; }
ControlNode* GraphLinker::optimizePhi(PhiNode* phi) { TNodeSet incomingValues; const PhiNode::TIncomingList& incomings = phi->getIncomingList(); assert(incomings.size() > 1); // Phi should have at least two incoming edges for (size_t index = 0; index < incomings.size(); index++) incomingValues.insert(incomings[index].node); assert(incomingValues.size()); if (traces_enabled) std::printf("GraphLinker::optimizePhi : phi node %u has %u unique incoming values\n", phi->getIndex(), incomingValues.size()); if (incomingValues.size() > 1) return phi; // Phi is ok, no need to optimize. Leave everything as is. // It seem that phi node is redundant becasue all of it's incomings link to the same value. // This may happen in a diamond-shaped reference diagram if incoming value stored in the top // domain and consumed in the bottom one. Left and right domains are not affected. // We may safely remove the phi because incoming value dominates it's consumer. if (traces_enabled) std::printf("GraphLinker::optimizePhi : phi node %u is redundant and may be removed\n", phi->getIndex()); // This is the real value that should be returned ControlNode* const value = *incomingValues.begin(); // Unlink and erase phi value->removeConsumer(phi); value->removeEdge(phi); m_graph->eraseNode(phi); return value; }
void CoreSolver::buildModel() { Debug("bv-core") << "CoreSolver::buildModel() \n"; d_modelValues.clear(); TNodeSet constants; TNodeSet constants_in_eq_engine; // collect constants in equality engine eq::EqClassesIterator eqcs_i = eq::EqClassesIterator(&d_equalityEngine); while (!eqcs_i.isFinished()) { TNode repr = *eqcs_i; if (repr.getKind() == kind::CONST_BITVECTOR) { // must check if it's just the constant eq::EqClassIterator it(repr, &d_equalityEngine); if (!(++it).isFinished() || true) { constants.insert(repr); constants_in_eq_engine.insert(repr); } } ++eqcs_i; } // build repr to value map eqcs_i = eq::EqClassesIterator(&d_equalityEngine); while (!eqcs_i.isFinished()) { TNode repr = *eqcs_i; ++eqcs_i; if (repr.getKind() != kind::VARIABLE && repr.getKind() != kind::SKOLEM && repr.getKind() != kind::CONST_BITVECTOR && !d_bv->isSharedTerm(repr)) { continue; } TypeNode type = repr.getType(); if (type.isBitVector() && repr.getKind()!= kind::CONST_BITVECTOR) { Debug("bv-core-model") << " processing " << repr <<"\n"; // we need to assign a value for it TypeEnumerator te(type); Node val; do { val = *te; ++te; // Debug("bv-core-model") << " trying value " << val << "\n"; // Debug("bv-core-model") << " is in set? " << constants.count(val) << "\n"; // Debug("bv-core-model") << " enumerator done? " << te.isFinished() << "\n"; } while (constants.count(val) != 0 && !(te.isFinished())); if (te.isFinished() && constants.count(val) != 0) { // if we cannot enumerate anymore values we just return the lemma stating that // at least two of the representatives are equal. std::vector<TNode> representatives; representatives.push_back(repr); for (TNodeSet::const_iterator it = constants_in_eq_engine.begin(); it != constants_in_eq_engine.end(); ++it) { TNode constant = *it; if (utils::getSize(constant) == utils::getSize(repr)) { representatives.push_back(constant); } } for (ModelValue::const_iterator it = d_modelValues.begin(); it != d_modelValues.end(); ++it) { representatives.push_back(it->first); } std::vector<Node> equalities; for (unsigned i = 0; i < representatives.size(); ++i) { for (unsigned j = i + 1; j < representatives.size(); ++j) { TNode a = representatives[i]; TNode b = representatives[j]; if (a.getKind() == kind::CONST_BITVECTOR && b.getKind() == kind::CONST_BITVECTOR) { Assert (a != b); continue; } if (utils::getSize(a) == utils::getSize(b)) { equalities.push_back(utils::mkNode(kind::EQUAL, a, b)); } } } // better off letting the SAT solver split on values if (equalities.size() > d_lemmaThreshold) { d_isComplete = false; return; } Node lemma = utils::mkOr(equalities); d_bv->lemma(lemma); Debug("bv-core") << " lemma: " << lemma << "\n"; return; } Debug("bv-core-model") << " " << repr << " => " << val <<"\n" ; constants.insert(val); d_modelValues[repr] = val; } } }