diff --git a/src/muz/rel/doc.cpp b/src/muz/rel/doc.cpp index 4f950973c..7cad5ffe8 100644 --- a/src/muz/rel/doc.cpp +++ b/src/muz/rel/doc.cpp @@ -119,6 +119,12 @@ bool doc_manager::set_and(doc& dst, doc const& src) { } return (src.neg().is_empty() || fold_neg(dst)); } +bool doc_manager::set_and(doc& dst, tbv const& src) { + // (A \ B) & C = (A & C) \ B + if (!m.set_and(dst.pos(), src)) return false; + dst.neg().intersect(m, src); + return true; +} bool doc_manager::well_formed(doc const& d) const { if (!m.is_well_formed(d.pos())) return false; @@ -404,23 +410,21 @@ void doc_manager::complement(doc const& src, ptr_vector& result) { // (A & !A1 & & !B) | (A & B1 & !A1) // A \ {A1 u B} u (A & B1) \ {A1} void doc_manager::subtract(doc const& A, doc const& B, ptr_vector& result) { - doc_ref r(*this), r2(*this); + doc_ref r(*this); tbv_ref t(m); r = allocate(A); t = m.allocate(B.pos()); if (m.set_and(*t, A.pos()) && r->neg().insert(m, t.detach())) { result.push_back(r.detach()); - r = allocate(A); } else { result.push_back(allocate(A)); } for (unsigned i = 0; i < B.neg().size(); ++i) { - r2 = allocate(B.neg()[i]); - if (set_and(*r, *r2)) { + r = allocate(A); + if (set_and(*r, B.neg()[i])) { result.push_back(r.detach()); } - r = allocate(A); } } bool doc_manager::equals(doc const& a, doc const& b) const { diff --git a/src/muz/rel/doc.h b/src/muz/rel/doc.h index bf2cdc229..3c2b9091d 100644 --- a/src/muz/rel/doc.h +++ b/src/muz/rel/doc.h @@ -59,6 +59,7 @@ public: bool is_full(doc const& src) const; bool is_empty(doc const& src); bool set_and(doc& dst, doc const& src); + bool set_and(doc& dst, tbv const& src); bool fold_neg(doc& dst); bool intersect(doc const& A, doc const& B, doc& result); void complement(doc const& src, ptr_vector& result); diff --git a/src/muz/rel/udoc_relation.cpp b/src/muz/rel/udoc_relation.cpp index 7ef3df3c2..1d0da90dd 100644 --- a/src/muz/rel/udoc_relation.cpp +++ b/src/muz/rel/udoc_relation.cpp @@ -753,16 +753,17 @@ namespace datalog { expr* e1, *e2; if (result.is_empty()) { } + else if (m.is_true(g)) { + } + else if (m.is_false(g)) { + result.reset(dm); + } else if (m.is_and(g)) { for (unsigned i = 0; !result.is_empty() && i < to_app(g)->get_num_args(); ++i) { apply_guard(to_app(g)->get_arg(i), result, equalities, discard_cols); } } else if (m.is_not(g, e1)) { - // REVIEW: (not (= x y)) should not cause - // the equivalence class to collapse. - // It seems the current organization with fix_eq_bits - // will merge the equivalence class as a side-effect. udoc sub; sub.push_back(dm.allocateX()); apply_guard(e1, sub, equalities, discard_cols); @@ -789,11 +790,6 @@ namespace datalog { result.display(dm, tout << "result:") << "\n";); sub.reset(dm); } - else if (m.is_true(g)) { - } - else if (m.is_false(g)) { - result.reset(dm); - } else if (is_var(g)) { SASSERT(m.is_bool(g)); unsigned v = to_var(g)->get_idx(); @@ -885,10 +881,8 @@ namespace datalog { SASSERT(u.well_formed(dm)); u.intersect(dm, m_udoc); SASSERT(u.well_formed(dm)); - if (!m.is_true(m_condition) && !u.is_empty()) { - t.apply_guard(m_condition, u, m_equalities, m_empty_bv); - SASSERT(u.well_formed(dm)); - } + t.apply_guard(m_condition, u, m_equalities, m_empty_bv); + SASSERT(u.well_formed(dm)); u.simplify(dm); SASSERT(u.well_formed(dm)); TRACE("doc", tout << "final size: " << t.get_size_estimate_rows() << '\n';); @@ -1041,10 +1035,8 @@ namespace datalog { SASSERT(u2.well_formed(dm)); u2.merge(dm, m_roots, m_equalities, m_col_list); SASSERT(u2.well_formed(dm)); - if (!m.is_true(m_condition) && !u2.is_empty()) { - t.apply_guard(m_condition, u2, m_equalities, m_col_list); - SASSERT(u2.well_formed(dm)); - } + t.apply_guard(m_condition, u2, m_equalities, m_col_list); + SASSERT(u2.well_formed(dm)); udoc_relation* r = get(t.get_plugin().mk_empty(get_result_signature())); doc_manager& dm2 = r->get_dm(); for (unsigned i = 0; i < u2.size(); ++i) {