From: Andrew Reynolds Date: Fri, 13 May 2022 00:57:01 +0000 (-0500) Subject: Minor refactoring for sep theory (#8753) X-Git-Tag: cvc5-1.0.1~140 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=36892a5bb9ad1bf2145912700f5998f971bb167a;p=cvc5.git Minor refactoring for sep theory (#8753) Work towards fixing #8659. --- diff --git a/src/theory/sep/theory_sep.cpp b/src/theory/sep/theory_sep.cpp index bc65f3451..2c5cdf029 100644 --- a/src/theory/sep/theory_sep.cpp +++ b/src/theory/sep/theory_sep.cpp @@ -377,56 +377,25 @@ void TheorySep::reduceFact(TNode atom, bool polarity, TNode fact) // make conclusion based on type of assertion if (satom.getKind() == SEP_STAR || satom.getKind() == SEP_WAND) { - std::vector children; - std::vector c_lems; TypeNode tn = getReferenceType(); if (d_reference_bound_max.find(tn) != d_reference_bound_max.end()) { - c_lems.push_back( - nm->mkNode(SET_SUBSET, slbl, d_reference_bound_max[tn])); + Node blem = nm->mkNode(SET_SUBSET, slbl, d_reference_bound_max[tn]); + d_im.lemma(blem, InferenceId::SEP_LABEL_DEF); } + std::vector children; std::vector labels; getLabelChildren(satom, slbl, children, labels); Node empSet = nm->mkConst(EmptySet(slbl.getType())); Assert(children.size() > 1); if (satom.getKind() == SEP_STAR) { - // reduction for heap : union, pairwise disjoint - Node ulem = nm->mkNode(SET_UNION, labels[0], labels[1]); - size_t lsize = labels.size(); - for (size_t i = 2; i < lsize; i++) - { - ulem = nm->mkNode(SET_UNION, ulem, labels[i]); - } - ulem = slbl.eqNode(ulem); - Trace("sep-lemma-debug") - << "Sep::Lemma : star reduction, union : " << ulem << std::endl; - c_lems.push_back(ulem); - for (size_t i = 0; i < lsize; i++) - { - for (size_t j = (i + 1); j < lsize; j++) - { - Node s = nm->mkNode(SET_INTER, labels[i], labels[j]); - Node ilem = s.eqNode(empSet); - Trace("sep-lemma-debug") - << "Sep::Lemma : star reduction, disjoint : " << ilem - << std::endl; - c_lems.push_back(ilem); - } - } + // make disjoint heap + makeDisjointHeap(slbl, labels); } else { - Node ulem = nm->mkNode(SET_UNION, slbl, labels[0]); - ulem = ulem.eqNode(labels[1]); - Trace("sep-lemma-debug") - << "Sep::Lemma : wand reduction, union : " << ulem << std::endl; - c_lems.push_back(ulem); - Node s = nm->mkNode(SET_INTER, slbl, labels[0]); - Node ilem = s.eqNode(empSet); - Trace("sep-lemma-debug") - << "Sep::Lemma : wand reduction, disjoint : " << ilem << std::endl; - c_lems.push_back(ilem); + Assert (satom.getKind()==SEP_WAND); // nil does not occur in labels[0] Node nr = getNilRef(tn); Node nrlem = nm->mkNode(SET_MEMBER, nr, labels[0]).negate(); @@ -434,12 +403,8 @@ void TheorySep::reduceFact(TNode atom, bool polarity, TNode fact) << "Sep::Lemma: sep.nil not in wand antecedant heap : " << nrlem << std::endl; d_im.lemma(nrlem, InferenceId::SEP_NIL_NOT_IN_HEAP); - } - // send out definitional lemmas for introduced sets - for (const Node& clem : c_lems) - { - Trace("sep-lemma") << "Sep::Lemma : definition : " << clem << std::endl; - d_im.lemma(clem, InferenceId::SEP_LABEL_DEF); + // make disjoint heap + makeDisjointHeap(labels[1], {slbl, labels[0]}); } conc = nm->mkNode(AND, children); } @@ -1335,16 +1300,101 @@ Node TheorySep::getLabel( Node atom, int child, Node lbl ) { std::stringstream ss; ss << "__Lc" << child; TypeNode ltn = NodeManager::currentNM()->mkSetType(refType); - //TypeNode ltn = NodeManager::currentNM()->mkSetType(NodeManager::currentNM()->mkRefType(refType)); Node n_lbl = sm->mkDummySkolem(ss.str(), ltn, "sep label"); d_label_map[atom][lbl][child] = n_lbl; - d_label_map_parent[n_lbl] = lbl; return n_lbl; }else{ return (*it).second; } } + +void TheorySep::makeDisjointHeap(Node parent, const std::vector& children) +{ + Assert(children.size() >= 2); + // remember parent relationships + for (const Node& c : children) + { + Assert(c.getType() == parent.getType()); + d_parentMap[c].push_back(parent); + } + // make the disjointness constraints + NodeManager* nm = NodeManager::currentNM(); + std::vector lems; + Node ulem = nm->mkNode(SET_UNION, children[0], children[1]); + size_t lsize = children.size(); + for (size_t i = 2; i < lsize; i++) + { + ulem = nm->mkNode(SET_UNION, ulem, children[i]); + } + ulem = parent.eqNode(ulem); + lems.push_back(ulem); + Node empSet = nm->mkConst(EmptySet(parent.getType())); + for (size_t i = 0; i < lsize; i++) + { + for (size_t j = (i + 1); j < lsize; j++) + { + Node s = nm->mkNode(SET_INTER, children[i], children[j]); + Node ilem = s.eqNode(empSet); + lems.push_back(ilem); + } + } + // send out definitional lemmas for introduced sets + for (const Node& clem : lems) + { + d_im.lemma(clem, InferenceId::SEP_LABEL_DEF); + } +} + +std::vector TheorySep::getRootLabels(Node p) const +{ + std::vector roots; + std::unordered_set visited; + std::unordered_set::iterator it; + std::vector visit; + std::map >::const_iterator itp; + Node cur; + visit.push_back(p); + do + { + cur = visit.back(); + visit.pop_back(); + it = visited.find(cur); + if (it == visited.end()) + { + visited.insert(cur); + itp = d_parentMap.find(cur); + if (itp == d_parentMap.end()) + { + roots.push_back(cur); + } + else + { + visit.insert(visit.end(), itp->second.begin(), itp->second.end()); + } + } + } while (!visit.empty()); + return roots; +} + +bool TheorySep::sharesRootLabel(Node p, Node q) const +{ + if (p == q) + { + return true; + } + std::vector rp = getRootLabels(p); + std::vector rq = getRootLabels(q); + for (const Node& r : rp) + { + if (std::find(rq.begin(), rq.end(), r) != rq.end()) + { + return true; + } + } + return false; +} + Node TheorySep::applyLabel( Node n, Node lbl, std::map< Node, Node >& visited ) { Assert(n.getKind() != kind::SEP_LABEL); NodeManager* nm = NodeManager::currentNM(); diff --git a/src/theory/sep/theory_sep.h b/src/theory/sep/theory_sep.h index b7db57b5c..f01057cfb 100644 --- a/src/theory/sep/theory_sep.h +++ b/src/theory/sep/theory_sep.h @@ -246,7 +246,29 @@ class TheorySep : public Theory { std::map< TypeNode, Node > d_emp_arg; //map from ( atom, label, child index ) -> label std::map< Node, std::map< Node, std::map< int, Node > > > d_label_map; - std::map< Node, Node > d_label_map_parent; + + /** + * Maps label sets to their direct parents. A set may have multiple parents + * if sep.wand constraints are present. + */ + std::map > d_parentMap; + + /** + * This sends the lemmas: + * parent = (set.union children) + * (set.inter children_i children_j) = empty, for each i != j + * It also stores these relationships in d_parentMap. + */ + void makeDisjointHeap(Node parent, const std::vector& children); + /** + * Get the sets that are parents of p and are roots in the graph induced + * by d_parentMap. + */ + std::vector getRootLabels(Node p) const; + /** + * Do p and q have a root label in common? + */ + bool sharesRootLabel(Node p, Node q) const; //term model std::map< Node, Node > d_tmodel;