3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 22:23:22 +00:00

DoC: add slow path to emptiness detection that uses SMT solving

Signed-off-by: Nuno Lopes <a-nlopes@microsoft.com>
This commit is contained in:
Nuno Lopes 2014-09-30 15:58:38 +01:00
parent 938a5adafa
commit 1606359dc9
6 changed files with 25 additions and 43 deletions

View file

@ -307,7 +307,7 @@ namespace datalog {
idx_vector::const_iterator end=m_controls.end(); idx_vector::const_iterator end=m_controls.end();
for(; it != end; ++it) { for(; it != end; ++it) {
reg_idx r = *it; reg_idx r = *it;
if (ctx.reg(r) && !ctx.reg(r)->empty()) { if (ctx.reg(r) && !ctx.reg(r)->fast_empty()) {
return false; return false;
} }
} }

View file

@ -122,7 +122,7 @@ namespace datalog {
relation_map::iterator it = m_relations.begin(); relation_map::iterator it = m_relations.begin();
relation_map::iterator end = m_relations.end(); relation_map::iterator end = m_relations.end();
for(; it!=end; ++it) { for(; it!=end; ++it) {
if(!it->m_value->empty()) { if(!it->m_value->fast_empty()) {
res.insert(it->m_key); res.insert(it->m_key);
} }
} }

View file

@ -83,7 +83,6 @@ void doc_manager::deallocate(doc* src) {
m.deallocate(&src->pos()); m.deallocate(&src->pos());
src->neg().reset(m); src->neg().reset(m);
m_alloc.deallocate(sizeof(doc), src); m_alloc.deallocate(sizeof(doc), src);
// dealloc(src);
} }
void doc_manager::copy(doc& dst, doc const& src) { void doc_manager::copy(doc& dst, doc const& src) {
m.copy(dst.pos(), src.pos()); m.copy(dst.pos(), src.pos());
@ -118,7 +117,6 @@ bool doc_manager::set_and(doc& dst, doc const& src) {
dst.neg().insert(m, t.detach()); dst.neg().insert(m, t.detach());
} }
} }
SASSERT(well_formed(dst));
return fold_neg(dst); return fold_neg(dst);
} }
bool doc_manager::set_and(doc& dst, tbv const& src) { bool doc_manager::set_and(doc& dst, tbv const& src) {
@ -498,33 +496,19 @@ bool doc_manager::equals(doc const& a, doc const& b) const {
bool doc_manager::is_full(doc const& src) const { bool doc_manager::is_full(doc const& src) const {
return src.neg().is_empty() && m.equals(src.pos(), *m_full); return src.neg().is_empty() && m.equals(src.pos(), *m_full);
} }
bool doc_manager::is_empty(doc const& src) { bool doc_manager::is_empty_complete(ast_manager& m, doc const& src) {
if (src.neg().size() == 0) return false; if (src.neg().size() == 0) return false;
return false;
#if 0 smt_params fp;
// buggy: smt::kernel s(m, fp);
tbv_ref pos(m, m.allocate(src.pos())); expr_ref fml = to_formula(m, src);
for (unsigned i = 0; i < src.neg().size(); ++i) { s.assert_expr(fml);
bool found = false; lbool res = s.check();
for (unsigned j = 0; !found && j < num_tbits(); ++j) { if (res == l_true) {
tbit b1 = (*pos)[j]; return false;
tbit b2 = src.neg()[i][j];
found = (b1 != BIT_x && b2 != BIT_x && b1 != b2);
}
for (unsigned j = 0; !found && j < num_tbits(); ++j) {
tbit b1 = (*pos)[j];
tbit b2 = src.neg()[i][j];
found = (b1 == BIT_x && b2 != BIT_x);
if (found) {
m.set(*pos, j, neg(b2));
}
}
if (!found) {
return false; // TBD make complete SAT check.
}
} }
SASSERT(res == l_false);
return true; return true;
#endif
} }
unsigned doc_manager::hash(doc const& src) const { unsigned doc_manager::hash(doc const& src) const {

View file

@ -72,7 +72,7 @@ public:
doc& fill1(doc& src); doc& fill1(doc& src);
doc& fillX(doc& src); doc& fillX(doc& src);
bool is_full(doc const& src) const; bool is_full(doc const& src) const;
bool is_empty(doc const& src); bool is_empty_complete(ast_manager& m, doc const& src);
bool set_and(doc& dst, doc const& src); bool set_and(doc& dst, doc const& src);
bool set_and(doc& dst, tbv const& src); bool set_and(doc& dst, tbv const& src);
bool fold_neg(doc& dst); bool fold_neg(doc& dst);
@ -120,9 +120,16 @@ public:
unsigned size() const { return m_elems.size(); } unsigned size() const { return m_elems.size(); }
T& operator[](unsigned idx) const { return *m_elems[idx]; } T& operator[](unsigned idx) const { return *m_elems[idx]; }
bool is_empty() const { return m_elems.empty(); } bool is_empty() const { return m_elems.empty(); }
bool is_empty_complete(ast_manager& m, doc_manager& dm) const {
for (unsigned i = 0; i < size(); ++i) {
if (!dm.is_empty_complete(m, *m_elems[i]))
return false;
}
return true;
}
bool is_full(M& m) const { return size() == 1 && m.is_full(*m_elems[0]); } bool is_full(M& m) const { return size() == 1 && m.is_full(*m_elems[0]); }
bool contains(M& m, T& t) const { bool contains(M& m, T& t) const {
for (unsigned i = 0; i < m_elems.size(); ++i) { for (unsigned i = 0; i < size(); ++i) {
if (m.contains(*m_elems[i], t)) return true; if (m.contains(*m_elems[i], t)) return true;
} }
return false; return false;

View file

@ -375,7 +375,7 @@ namespace datalog {
for (; it != end; ++it) { for (; it != end; ++it) {
func_decl* pred = *it; func_decl* pred = *it;
relation_base & rel = get_relation(pred); relation_base & rel = get_relation(pred);
if (!rel.empty()) { if (!rel.fast_empty()) {
non_empty = true; non_empty = true;
break; break;
} }
@ -449,7 +449,7 @@ namespace datalog {
bool rel_context::is_empty_relation(func_decl* pred) const { bool rel_context::is_empty_relation(func_decl* pred) const {
relation_base* rb = try_get_relation(pred); relation_base* rb = try_get_relation(pred);
return !rb || rb->empty(); return !rb || rb->fast_empty();
} }
relation_manager & rel_context::get_rmanager() { return m_rmanager; } relation_manager & rel_context::get_rmanager() { return m_rmanager; }

View file

@ -21,10 +21,6 @@ Revision History:
Notes: Notes:
Current pending items: Current pending items:
- Fix the incomplete non-emptiness check in doc.cpp
It can fall back to a sat_solver call in the worst case.
The sat_solver.h interface gives a way to add clauses to a sat solver
and check for satisfiability. It can be used from scratch each time.
- Profile and fix bottlnecks: - Profile and fix bottlnecks:
- Potential bottleneck in projection exercised in some benchmarks. - Potential bottleneck in projection exercised in some benchmarks.
Projection is asymptotically very expensive. We are here interested in Projection is asymptotically very expensive. We are here interested in
@ -127,12 +123,7 @@ namespace datalog {
m_elems.push_back(fact2doc(f)); m_elems.push_back(fact2doc(f));
} }
bool udoc_relation::empty() const { bool udoc_relation::empty() const {
if (m_elems.is_empty()) return true; return m_elems.is_empty_complete(get_plugin().m, dm);
// TBD: make this a complete check
for (unsigned i = 0; i < m_elems.size(); ++i) {
if (!dm.is_empty(m_elems[i])) return false;
}
return true;
} }
bool udoc_relation::contains_fact(const relation_fact & f) const { bool udoc_relation::contains_fact(const relation_fact & f) const {
doc_ref d(dm, fact2doc(f)); doc_ref d(dm, fact2doc(f));