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

Merge branch 'opt' of https://git01.codeplex.com/z3 into opt

This commit is contained in:
Nikolaj Bjorner 2014-10-01 13:49:36 -07:00
commit 985e48c66a
19 changed files with 295 additions and 183 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());
@ -110,23 +109,21 @@ doc& doc_manager::fillX(doc& src) {
bool doc_manager::set_and(doc& dst, doc const& src) { bool doc_manager::set_and(doc& dst, doc const& src) {
// (A \ B) & (C \ D) = (A & C) \ (B u D) // (A \ B) & (C \ D) = (A & C) \ (B u D)
if (!m.set_and(dst.pos(), src.pos())) return false; if (!m.set_and(dst.pos(), src.pos())) return false;
dst.neg().intersect(m, dst.pos()); dst.neg().intersect(m, dst.pos());
tbv_ref t(m); tbv_ref t(m);
for (unsigned i = 0; i < src.neg().size(); ++i) { for (unsigned i = 0; i < src.neg().size(); ++i) {
t = m.allocate(src.neg()[i]); t = m.allocate(src.neg()[i]);
if (m.set_and(*t, dst.pos())) { if (m.set_and(*t, dst.pos())) {
if (m.equals(*t, dst.pos())) return false;
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) {
// (A \ B) & C = (A & C) \ B // (A \ B) & C = (A & C) \ (B & C)
if (!m.set_and(dst.pos(), src)) return false; if (!m.set_and(dst.pos(), src)) return false;
dst.neg().intersect(m, src); dst.neg().intersect(m, src);
return true; return fold_neg(dst);
} }
bool doc_manager::well_formed(doc const& d) const { bool doc_manager::well_formed(doc const& d) const {
@ -141,6 +138,9 @@ bool doc_manager::well_formed(doc const& d) const {
bool doc_manager::fold_neg(doc& dst) { bool doc_manager::fold_neg(doc& dst) {
start_over: start_over:
for (unsigned i = 0; i < dst.neg().size(); ++i) { for (unsigned i = 0; i < dst.neg().size(); ++i) {
if (m.contains(dst.neg()[i], dst.pos()))
return false;
unsigned index; unsigned index;
unsigned count = diff_by_012(dst.pos(), dst.neg()[i], index); unsigned count = diff_by_012(dst.pos(), dst.neg()[i], index);
if (count != 2) { if (count != 2) {
@ -280,7 +280,7 @@ bool doc_manager::intersect(doc const& A, doc const& B, doc& result) {
// indices where BIT_0 is set are positive. // indices where BIT_0 is set are positive.
// //
doc* doc_manager::project(doc_manager& dstm, unsigned n, bool const* to_delete, doc const& src) { doc* doc_manager::project(doc_manager& dstm, unsigned n, bit_vector const& to_delete, doc const& src) {
tbv_manager& dstt = dstm.m; tbv_manager& dstt = dstm.m;
tbv_ref t(dstt); tbv_ref t(dstt);
t = dstt.project(n, to_delete, src.pos()); t = dstt.project(n, to_delete, src.pos());
@ -391,7 +391,7 @@ doc* doc_manager::project(doc_manager& dstm, unsigned n, bool const* to_delete,
doc_manager::project_action_t doc_manager::project_action_t
doc_manager::pick_resolvent( doc_manager::pick_resolvent(
tbv const& pos, tbv_vector const& neg, bool const* to_delete, unsigned& idx) { tbv const& pos, tbv_vector const& neg, bit_vector const& to_delete, unsigned& idx) {
if (neg.empty()) return project_done; if (neg.empty()) return project_done;
for (unsigned j = 0; j < neg.size(); ++j) { for (unsigned j = 0; j < neg.size(); ++j) {
if (m.equals(pos, *neg[j])) return project_is_empty; if (m.equals(pos, *neg[j])) return project_is_empty;
@ -401,7 +401,7 @@ doc_manager::pick_resolvent(
unsigned best_neg = UINT_MAX; unsigned best_neg = UINT_MAX;
unsigned best_idx = UINT_MAX; unsigned best_idx = UINT_MAX;
for (unsigned i = 0; i < num_tbits(); ++i) { for (unsigned i = 0; i < num_tbits(); ++i) {
if (!to_delete[i]) continue; if (!to_delete.get(i)) continue;
if (pos[i] != BIT_x) continue; if (pos[i] != BIT_x) continue;
unsigned num_pos = 0, num_neg = 0; unsigned num_pos = 0, num_neg = 0;
tbit b1 = (*neg[0])[i]; tbit b1 = (*neg[0])[i];
@ -472,12 +472,12 @@ void doc_manager::subtract(doc const& A, doc const& B, doc_vector& result) {
tbv_ref t(m); tbv_ref t(m);
r = allocate(A); r = allocate(A);
t = m.allocate(B.pos()); t = m.allocate(B.pos());
if (m.set_and(*t, A.pos()) && r->neg().insert(m, t.detach())) { if (m.set_and(*t, A.pos())) {
r->neg().insert(m, t.detach());
}
if (fold_neg(*r))
result.push_back(r.detach()); result.push_back(r.detach());
}
else {
result.push_back(allocate(A));
}
for (unsigned i = 0; i < B.neg().size(); ++i) { for (unsigned i = 0; i < B.neg().size(); ++i) {
r = allocate(A); r = allocate(A);
if (set_and(*r, B.neg()[i])) { if (set_and(*r, B.neg()[i])) {
@ -496,36 +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;
if (src.neg().size() == 1) {
return m.equals(src.pos(), src.neg()[0]); smt_params fp;
} smt::kernel s(m, fp);
return false; expr_ref fml = to_formula(m, src);
#if 0 s.assert_expr(fml);
// buggy: lbool res = s.check();
tbv_ref pos(m, m.allocate(src.pos())); if (res == l_true) {
for (unsigned i = 0; i < src.neg().size(); ++i) { return false;
bool found = false;
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 && 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 {
@ -553,16 +536,15 @@ bool doc_manager::contains(doc const& a, doc const& b) const {
return true; return true;
} }
bool doc_manager::contains( bool doc_manager::contains(doc const& a, unsigned_vector const& colsa,
unsigned offset_a, doc const& a, doc const& b, unsigned_vector const& colsb) const {
doc_manager const& dm_b, if (!m.contains(a.pos(), colsa, b.pos(), colsb))
unsigned offset_b, doc const& b, return false;
unsigned length) const {
if (!m.contains(offset_a, a.pos(), dm_b.tbvm(), offset_b, b.pos(), length)) return false;
for (unsigned i = 0; i < a.neg().size(); ++i) { for (unsigned i = 0; i < a.neg().size(); ++i) {
bool found = false; bool found = false;
for (unsigned j = 0; !found && j < b.neg().size(); ++j) { for (unsigned j = 0; !found && j < b.neg().size(); ++j) {
found = dm_b.tbvm().contains(offset_b, b.neg()[j], tbvm(), offset_a, a.neg()[i], length); found = m.contains(b.neg()[j], colsb, a.neg()[i], colsa);
} }
if (!found) return false; if (!found) return false;
} }
@ -583,7 +565,7 @@ std::ostream& doc_manager::display(std::ostream& out, doc const& b, unsigned hi,
} }
void doc_manager::verify_project(ast_manager& m, doc_manager& dstm, bool const* to_delete, doc const& src, doc const& dst) { void doc_manager::verify_project(ast_manager& m, doc_manager& dstm, bit_vector const& to_delete, doc const& src, doc const& dst) {
expr_ref fml1 = to_formula(m, src); expr_ref fml1 = to_formula(m, src);
expr_ref fml2 = dstm.to_formula(m, dst); expr_ref fml2 = dstm.to_formula(m, dst);
project_rename(fml2, to_delete); project_rename(fml2, to_delete);
@ -620,11 +602,11 @@ expr_ref doc_manager::to_formula(ast_manager& m, doc const& src) {
return result; return result;
} }
void doc_manager::project_expand(expr_ref& fml, bool const* to_delete) { void doc_manager::project_expand(expr_ref& fml, bit_vector const& to_delete) {
ast_manager& m = fml.get_manager(); ast_manager& m = fml.get_manager();
expr_ref tmp1(m), tmp2(m); expr_ref tmp1(m), tmp2(m);
for (unsigned i = 0; i < num_tbits(); ++i) { for (unsigned i = 0; i < num_tbits(); ++i) {
if (to_delete[i]) { if (to_delete.get(i)) {
expr_safe_replace rep1(m), rep2(m); expr_safe_replace rep1(m), rep2(m);
rep1.insert(tbvm().mk_var(m, i), m.mk_true()); rep1.insert(tbvm().mk_var(m, i), m.mk_true());
rep1(fml, tmp1); rep1(fml, tmp1);
@ -640,11 +622,11 @@ void doc_manager::project_expand(expr_ref& fml, bool const* to_delete) {
} }
} }
void doc_manager::project_rename(expr_ref& fml, bool const* to_delete) { void doc_manager::project_rename(expr_ref& fml, bit_vector const& to_delete) {
ast_manager& m = fml.get_manager(); ast_manager& m = fml.get_manager();
expr_safe_replace rep(m); expr_safe_replace rep(m);
for (unsigned i = 0, j = 0; i < num_tbits(); ++i) { for (unsigned i = 0, j = 0; i < num_tbits(); ++i) {
if (!to_delete[i]) { if (!to_delete.get(i)) {
rep.insert(tbvm().mk_var(m, j), tbvm().mk_var(m, i)); rep.insert(tbvm().mk_var(m, j), tbvm().mk_var(m, i));
++j; ++j;
} }

View file

@ -48,7 +48,7 @@ class doc_manager {
project_resolve project_resolve
}; };
project_action_t pick_resolvent( project_action_t pick_resolvent(
tbv const& pos, tbv_vector const& neg, bool const* to_delete, unsigned& idx); tbv const& pos, tbv_vector const& neg, bit_vector const& to_delete, unsigned& idx);
public: public:
doc_manager(unsigned num_bits); doc_manager(unsigned num_bits);
~doc_manager(); ~doc_manager();
@ -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);
@ -82,23 +82,22 @@ public:
bool equals(doc const& a, doc const& b) const; bool equals(doc const& a, doc const& b) const;
unsigned hash(doc const& src) const; unsigned hash(doc const& src) const;
bool contains(doc const& a, doc const& b) const; bool contains(doc const& a, doc const& b) const;
bool contains(unsigned offset_a, doc const& a, bool contains(doc const& a, unsigned_vector const& colsa,
doc_manager const& dm_b, unsigned offset_b, doc const& b, doc const& b, unsigned_vector const& colsb) const;
unsigned length) const;
std::ostream& display(std::ostream& out, doc const& b) const; std::ostream& display(std::ostream& out, doc const& b) const;
std::ostream& display(std::ostream& out, doc const& b, unsigned hi, unsigned lo) const; std::ostream& display(std::ostream& out, doc const& b, unsigned hi, unsigned lo) const;
unsigned num_tbits() const { return m.num_tbits(); } unsigned num_tbits() const { return m.num_tbits(); }
doc* project(doc_manager& dstm, unsigned n, bool const* to_delete, doc const& src); doc* project(doc_manager& dstm, unsigned n, bit_vector const& to_delete, doc const& src);
bool well_formed(doc const& d) const; bool well_formed(doc const& d) const;
bool merge(doc& d, unsigned lo, unsigned length, subset_ints const& equalities, bit_vector const& discard_cols); bool merge(doc& d, unsigned lo, unsigned length, subset_ints const& equalities, bit_vector const& discard_cols);
void set(doc& d, unsigned idx, tbit value); void set(doc& d, unsigned idx, tbit value);
void verify_project(ast_manager& m, doc_manager& dstm, bool const* to_delete, doc const& src, doc const& dst); void verify_project(ast_manager& m, doc_manager& dstm, bit_vector const& to_delete, doc const& src, doc const& dst);
private: private:
unsigned diff_by_012(tbv const& pos, tbv const& neg, unsigned& index); unsigned diff_by_012(tbv const& pos, tbv const& neg, unsigned& index);
bool merge(doc& d, unsigned idx, subset_ints const& equalities, bit_vector const& discard_cols); bool merge(doc& d, unsigned idx, subset_ints const& equalities, bit_vector const& discard_cols);
void project_rename(expr_ref& fml, bool const* to_delete); void project_rename(expr_ref& fml, bit_vector const& to_delete);
void project_expand(expr_ref& fml, bool const* to_delete); void project_expand(expr_ref& fml, bit_vector const& to_delete);
expr_ref to_formula(ast_manager& m, doc const& src); expr_ref to_formula(ast_manager& m, doc const& src);
void check_equiv(ast_manager& m, expr* fml1, expr* fml2); void check_equiv(ast_manager& m, expr* fml1, expr* fml2);
}; };
@ -119,10 +118,17 @@ class union_bvec {
public: 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;
@ -164,11 +170,13 @@ public:
SASSERT(t); SASSERT(t);
unsigned sz = size(), j = 0; unsigned sz = size(), j = 0;
bool found = false; bool found = false;
for (unsigned i = 0; i < sz; ++i, ++j) { unsigned i = 0;
for ( ; i < sz; ++i, ++j) {
if (m.contains(*m_elems[i], *t)) { if (m.contains(*m_elems[i], *t)) {
found = true; found = true;
break;
} }
if (!found && m.contains(*t, *m_elems[i])) { if (m.contains(*t, *m_elems[i])) {
m.deallocate(m_elems[i]); m.deallocate(m_elems[i]);
--j; --j;
} }
@ -178,6 +186,7 @@ public:
} }
if (j != sz) m_elems.resize(j); if (j != sz) m_elems.resize(j);
if (found) { if (found) {
SASSERT(j == i);
m.deallocate(t); m.deallocate(t);
} }
else { else {

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

@ -99,11 +99,11 @@ tbv* tbv_manager::allocate(tbv const& bv, unsigned const* permutation) {
} }
return r; return r;
} }
tbv* tbv_manager::project(unsigned n, bool const* to_delete, tbv const& src) { tbv* tbv_manager::project(unsigned n, bit_vector const& to_delete, tbv const& src) {
tbv* r = allocate(); tbv* r = allocate();
unsigned i, j; unsigned i, j;
for (i = 0, j = 0; i < n; ++i) { for (i = 0, j = 0; i < n; ++i) {
if (!to_delete[i]) { if (!to_delete.get(i)) {
set(*r, j, src[i]); set(*r, j, src[i]);
++j; ++j;
} }
@ -245,18 +245,12 @@ bool tbv_manager::contains(tbv const& a, tbv const& b) const {
return m.contains(a, b); return m.contains(a, b);
} }
bool tbv_manager::contains(unsigned offset_a, tbv const& a, bool tbv_manager::contains(tbv const& a, unsigned_vector const& colsa,
tbv_manager const& dm_b, unsigned offset_b, tbv const& b, tbv const& b, unsigned_vector const& colsb) const {
unsigned length) const { for (unsigned i = 0; i < colsa.size(); ++i) {
if (this == &dm_b && length == num_tbits()) { tbit bit_a = a[colsa[i]];
SASSERT(offset_a == 0);
SASSERT(offset_b == 0);
return m.contains(a, b);
}
for (unsigned i = 0; i < length; ++i) {
tbit bit_a = a[offset_a + i];
if (bit_a == BIT_x) continue; if (bit_a == BIT_x) continue;
if (bit_a != b[offset_b + i]) return false; if (bit_a != b[colsb[i]]) return false;
} }
return true; return true;
} }
@ -268,7 +262,7 @@ bool tbv_manager::intersect(tbv const& a, tbv const& b, tbv& result) {
std::ostream& tbv_manager::display(std::ostream& out, tbv const& b, unsigned hi, unsigned lo) const { std::ostream& tbv_manager::display(std::ostream& out, tbv const& b, unsigned hi, unsigned lo) const {
SASSERT(lo <= hi && hi < num_tbits()); SASSERT(lo <= hi && hi < num_tbits());
for (unsigned i = lo; i <= hi; ++i) { for (unsigned i = hi+1; i-- > lo; ) {
switch (b.get(i)) { switch (b.get(i)) {
case BIT_0: case BIT_0:
out << '0'; out << '0';

View file

@ -70,13 +70,12 @@ public:
bool equals(tbv const& a, tbv const& b) const; bool equals(tbv const& a, tbv const& b) const;
unsigned hash(tbv const& src) const; unsigned hash(tbv const& src) const;
bool contains(tbv const& a, tbv const& b) const; bool contains(tbv const& a, tbv const& b) const;
bool contains(unsigned offset_a, tbv const& a, bool contains(tbv const& a, unsigned_vector const& colsa,
tbv_manager const& dm_b, unsigned offset_b, tbv const& b, tbv const& b, unsigned_vector const& colsb) const;
unsigned length) const;
bool intersect(tbv const& a, tbv const& b, tbv& result); bool intersect(tbv const& a, tbv const& b, tbv& result);
std::ostream& display(std::ostream& out, tbv const& b) const; std::ostream& display(std::ostream& out, tbv const& b) const;
std::ostream& display(std::ostream& out, tbv const& b, unsigned hi, unsigned lo) const; std::ostream& display(std::ostream& out, tbv const& b, unsigned hi, unsigned lo) const;
tbv* project(unsigned n, bool const* to_delete, tbv const& src); tbv* project(unsigned n, bit_vector const& to_delete, tbv const& src);
bool is_well_formed(tbv const& b) const; // - does not contain BIT_z; bool is_well_formed(tbv const& b) const; // - does not contain BIT_z;
void set(tbv& dst, uint64 n, unsigned hi, unsigned lo); void set(tbv& dst, uint64 n, unsigned hi, unsigned lo);
void set(tbv& dst, rational const& r, unsigned hi, unsigned lo); void set(tbv& dst, rational const& r, unsigned hi, unsigned lo);

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
@ -58,9 +54,6 @@ Notes:
return tgt \ join_project(tgt, neg, c1, .., cN, d1, .. , dN) return tgt \ join_project(tgt, neg, c1, .., cN, d1, .. , dN)
We have most of the facilities required for a join project operation. We have most of the facilities required for a join project operation.
For example, the filter_project function uses both equalities and deleted columns. For example, the filter_project function uses both equalities and deleted columns.
- Lipstick service:
- filter_proj_fn uses both a bit_vector and a svector<bool> for representing removed bits.
This is due to underlying routines using different types for the same purpose.
--*/ --*/
#include "udoc_relation.h" #include "udoc_relation.h"
#include "dl_relation_manager.h" #include "dl_relation_manager.h"
@ -127,12 +120,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));
@ -482,7 +470,7 @@ namespace datalog {
} }
class udoc_plugin::project_fn : public convenient_relation_project_fn { class udoc_plugin::project_fn : public convenient_relation_project_fn {
svector<bool> m_to_delete; bit_vector m_to_delete;
public: public:
project_fn(udoc_relation const & t, unsigned removed_col_cnt, const unsigned * removed_cols) project_fn(udoc_relation const & t, unsigned removed_col_cnt, const unsigned * removed_cols)
: convenient_relation_project_fn(t.get_signature(), removed_col_cnt, removed_cols) { : convenient_relation_project_fn(t.get_signature(), removed_col_cnt, removed_cols) {
@ -490,7 +478,7 @@ namespace datalog {
unsigned n = t.get_dm().num_tbits(); unsigned n = t.get_dm().num_tbits();
m_to_delete.resize(n, false); m_to_delete.resize(n, false);
for (unsigned i = 0; i < m_removed_cols.size(); ++i) { for (unsigned i = 0; i < m_removed_cols.size(); ++i) {
m_to_delete[m_removed_cols[i]] = true; m_to_delete.set(m_removed_cols[i], true);
} }
} }
@ -505,7 +493,7 @@ namespace datalog {
udoc const& ud1 = t.get_udoc(); udoc const& ud1 = t.get_udoc();
udoc& ud2 = r->get_udoc(); udoc& ud2 = r->get_udoc();
for (unsigned i = 0; i < ud1.size(); ++i) { for (unsigned i = 0; i < ud1.size(); ++i) {
d2 = dm1.project(dm2, m_to_delete.size(), m_to_delete.c_ptr(), ud1[i]); d2 = dm1.project(dm2, m_to_delete.size(), m_to_delete, ud1[i]);
ud2.push_back(d2.detach()); ud2.push_back(d2.detach());
} }
TRACE("doc", tout << "final size: " << r->get_size_estimate_rows() << '\n';); TRACE("doc", tout << "final size: " << r->get_size_estimate_rows() << '\n';);
@ -1076,14 +1064,16 @@ namespace datalog {
// 4. Unit/stress test cases are needed. // 4. Unit/stress test cases are needed.
// //
class udoc_plugin::negation_filter_fn : public relation_intersection_filter_fn { class udoc_plugin::negation_filter_fn : public relation_intersection_filter_fn {
const unsigned_vector m_t_cols; unsigned_vector m_t_cols;
const unsigned_vector m_neg_cols; unsigned_vector m_neg_cols;
public: public:
negation_filter_fn(const udoc_relation & r, const udoc_relation & neg, unsigned joined_col_cnt, negation_filter_fn(const udoc_relation & r, const udoc_relation & neg, unsigned joined_col_cnt,
const unsigned *t_cols, const unsigned *neg_cols) const unsigned *t_cols, const unsigned *neg_cols)
: m_t_cols(joined_col_cnt, t_cols), m_neg_cols(joined_col_cnt, neg_cols) { : m_t_cols(joined_col_cnt, t_cols), m_neg_cols(joined_col_cnt, neg_cols) {
SASSERT(joined_col_cnt > 0); SASSERT(joined_col_cnt > 0);
r.expand_column_vector(m_t_cols);
neg.expand_column_vector(m_neg_cols);
} }
virtual void operator()(relation_base& tb, const relation_base& negb) { virtual void operator()(relation_base& tb, const relation_base& negb) {
@ -1098,30 +1088,16 @@ namespace datalog {
udoc result; udoc result;
for (unsigned i = 0; i < dst.size(); ++i) { for (unsigned i = 0; i < dst.size(); ++i) {
bool subsumed = false;
for (unsigned j = 0; j < neg.size(); ++j) { for (unsigned j = 0; j < neg.size(); ++j) {
for (unsigned c = 0; c < m_t_cols.size(); ++c) { if (dmn.contains(neg[j], m_neg_cols, dst[i], m_t_cols)) {
unsigned t_col = m_t_cols[c]; dmt.deallocate(&dst[i]);
unsigned n_col = m_neg_cols[c]; subsumed = true;
unsigned num_bits = t.column_num_bits(t_col); break;
SASSERT(num_bits == n.column_num_bits(n_col));
unsigned t_idx = t.column_idx(t_col);
unsigned n_idx = n.column_idx(n_col);
bool cont = dmn.contains(n_idx, neg[j], dmt, t_idx, dst[i], num_bits);
IF_VERBOSE(
3,
dmt.display(verbose_stream() << "dst:", dst[i], t_idx+num_bits-1,t_idx) << "\n";
dmn.display(verbose_stream() << "neg:", neg[j], n_idx+num_bits-1,n_idx) << "\n";
verbose_stream() << "contains: " << (cont?"true":"false") << "\n";);
if (!cont) {
goto next_neg_disj;
}
} }
dmt.deallocate(&dst[i]);
goto next_disj;
next_neg_disj:;
} }
result.push_back(&dst[i]); if (!subsumed)
next_disj:; result.push_back(&dst[i]);
} }
std::swap(dst, result); std::swap(dst, result);
if (dst.is_empty()) { if (dst.is_empty()) {
@ -1207,8 +1183,7 @@ namespace datalog {
expr_ref m_reduced_condition; expr_ref m_reduced_condition;
udoc m_udoc; udoc m_udoc;
udoc m_udoc2; udoc m_udoc2;
bit_vector m_col_list; // map: col idx -> bool (whether the column is to be removed) bit_vector m_to_delete; // map: col idx -> bool (whether the column is to be removed)
svector<bool> m_to_delete; // same
subset_ints m_equalities; subset_ints m_equalities;
unsigned_vector m_roots; unsigned_vector m_roots;
@ -1222,19 +1197,17 @@ namespace datalog {
m_equalities(union_ctx) { m_equalities(union_ctx) {
unsigned num_bits = t.get_num_bits(); unsigned num_bits = t.get_num_bits();
t.expand_column_vector(m_removed_cols); t.expand_column_vector(m_removed_cols);
m_col_list.resize(num_bits, false);
m_to_delete.resize(num_bits, false); m_to_delete.resize(num_bits, false);
for (unsigned i = 0; i < num_bits; ++i) { for (unsigned i = 0; i < num_bits; ++i) {
m_equalities.mk_var(); m_equalities.mk_var();
} }
for (unsigned i = 0; i < m_removed_cols.size(); ++i) { for (unsigned i = 0; i < m_removed_cols.size(); ++i) {
m_col_list.set(m_removed_cols[i], true); m_to_delete.set(m_removed_cols[i], true);
m_to_delete[m_removed_cols[i]] = true;
} }
expr_ref guard(m), non_eq_cond(condition, m); expr_ref guard(m), non_eq_cond(condition, m);
t.extract_equalities(condition, non_eq_cond, m_equalities, m_roots); t.extract_equalities(condition, non_eq_cond, m_equalities, m_roots);
t.extract_guard(non_eq_cond, guard, m_reduced_condition); t.extract_guard(non_eq_cond, guard, m_reduced_condition);
t.compile_guard(guard, m_udoc, m_col_list); t.compile_guard(guard, m_udoc, m_to_delete);
} }
virtual ~filter_proj_fn() { virtual ~filter_proj_fn() {
@ -1247,13 +1220,13 @@ namespace datalog {
ast_manager& m = m_reduced_condition.get_manager(); ast_manager& m = m_reduced_condition.get_manager();
m_udoc2.copy(dm, u1); m_udoc2.copy(dm, u1);
m_udoc2.intersect(dm, m_udoc); m_udoc2.intersect(dm, m_udoc);
t.apply_guard(m_reduced_condition, m_udoc2, m_equalities, m_col_list); t.apply_guard(m_reduced_condition, m_udoc2, m_equalities, m_to_delete);
m_udoc2.merge(dm, m_roots, m_equalities, m_col_list); m_udoc2.merge(dm, m_roots, m_equalities, m_to_delete);
SASSERT(m_udoc2.well_formed(dm)); SASSERT(m_udoc2.well_formed(dm));
udoc_relation* r = get(t.get_plugin().mk_empty(get_result_signature())); udoc_relation* r = get(t.get_plugin().mk_empty(get_result_signature()));
doc_manager& dm2 = r->get_dm(); doc_manager& dm2 = r->get_dm();
for (unsigned i = 0; i < m_udoc2.size(); ++i) { for (unsigned i = 0; i < m_udoc2.size(); ++i) {
doc* d = dm.project(dm2, m_to_delete.size(), m_to_delete.c_ptr(), m_udoc2[i]); doc* d = dm.project(dm2, m_to_delete.size(), m_to_delete, m_udoc2[i]);
r->get_udoc().insert(dm2, d); r->get_udoc().insert(dm2, d);
SASSERT(r->get_udoc().well_formed(dm2)); SASSERT(r->get_udoc().well_formed(dm2));
} }

View file

@ -64,6 +64,11 @@ namespace sat {
m_bin_clauses.push_back(cls); m_bin_clauses.push_back(cls);
register_clause(cls); register_clause(cls);
} }
TRACE("sat",
for (unsigned i = 0; i < m_clauses.size(); ++i) {
clause const* cls = m_clauses[i];
if (cls) tout << *cls << "\n";
});
} }
void bceq::pure_decompose() { void bceq::pure_decompose() {
@ -109,7 +114,7 @@ namespace sat {
m_L_blits.resize(sz1+delta1, lit); m_L_blits.resize(sz1+delta1, lit);
m_R_blits.resize(sz2+delta2, ~lit); m_R_blits.resize(sz2+delta2, ~lit);
} }
std::cout << lit << " " << "pos: " << delta1 << " " << "neg: " << delta2 << "\n"; TRACE("bceq", tout << lit << " " << "pos: " << delta1 << " " << "neg: " << delta2 << "\n";);
} }
void bceq::pure_decompose(clause_use_list& uses, svector<clause*>& clauses) { void bceq::pure_decompose(clause_use_list& uses, svector<clause*>& clauses) {
@ -134,24 +139,88 @@ namespace sat {
for (unsigned i = 0; i < m_L.size(); ++i) { for (unsigned i = 0; i < m_L.size(); ++i) {
ul.insert(*m_L[i]); ul.insert(*m_L[i]);
} }
#define MOVE_R_TO_L \
// cheap pass: add clauses from R in order
// such that they are blocked with respect to
// predecessors.
m_removed.reset();
for (unsigned i = 0; i < m_R.size(); ++i) { for (unsigned i = 0; i < m_R.size(); ++i) {
literal lit = find_blocked(*m_R[i]); literal lit = find_blocked(*m_R[i]);
if (lit != null_literal) { if (lit != null_literal) {
m_L.push_back(m_R[i]); m_L.push_back(m_R[i]);
m_L_blits.push_back(lit); m_L_blits.push_back(lit);
ul.insert(*m_R[i]); ul.insert(*m_R[i]);
m_R[i] = m_R.back();
m_R_blits[i] = m_R_blits.back();
m_R.pop_back();
m_R_blits.pop_back();
--i;
}
}
// expensive pass: add clauses from R as long
// as BCE produces the empty set of clauses.
for (unsigned i = 0; i < m_R.size(); ++i) {
if (bce(*m_R[i])) {
m_R[i] = m_R.back(); m_R[i] = m_R.back();
m_R_blits[i] = m_R_blits.back(); m_R_blits[i] = m_R_blits.back();
m_R.pop_back(); m_R.pop_back();
m_R_blits.pop_back(); m_R_blits.pop_back();
--i; --i;
} }
} }
m_use_list = save; m_use_list = save;
} }
bool bceq::bce(clause& cls) {
svector<bool> live_clauses;
use_list ul;
use_list* save = m_use_list;
m_use_list = &ul;
ul.init(m_solver.num_vars());
for (unsigned i = 0; i < m_L.size(); ++i) {
ul.insert(*m_L[i]);
}
ul.insert(cls);
svector<clause*> clauses(m_L), new_clauses;
literal_vector blits(m_L_blits), new_blits;
clauses.push_back(&cls);
blits.push_back(null_literal);
bool removed = false;
m_removed.reset();
do {
removed = false;
for (unsigned i = 0; i < clauses.size(); ++i) {
clause& cls = *clauses[i];
literal lit = find_blocked(cls);
if (lit != null_literal) {
m_removed.setx(cls.id(), true, false);
new_clauses.push_back(&cls);
new_blits.push_back(lit);
removed = true;
clauses[i] = clauses.back();
blits[i] = blits.back();
clauses.pop_back();
blits.pop_back();
--i;
}
}
}
while (removed);
if (clauses.empty()) {
m_L.reset();
m_L_blits.reset();
new_clauses.reverse();
new_blits.reverse();
m_L.append(new_clauses);
m_L_blits.append(new_blits);
}
std::cout << "Number left after BCE: " << clauses.size() << "\n";
return clauses.empty();
}
literal bceq::find_blocked(clause const& cls) { literal bceq::find_blocked(clause const& cls) {
std::cout << "find blocker for: " << cls << "\n"; TRACE("bceq", tout << cls << "\n";);
unsigned sz = cls.size(); unsigned sz = cls.size();
for (unsigned i = 0; i < sz; ++i) { for (unsigned i = 0; i < sz; ++i) {
@ -161,7 +230,7 @@ namespace sat {
for (unsigned i = 0; i < sz; ++i) { for (unsigned i = 0; i < sz; ++i) {
literal lit = cls[i]; literal lit = cls[i];
if (is_blocked(lit)) { if (is_blocked(lit)) {
std::cout << "is blocked " << lit << " : " << cls << "\n"; TRACE("bceq", tout << "is blocked " << lit << " : " << cls << "\n";);
result = lit; result = lit;
break; break;
} }
@ -178,12 +247,12 @@ namespace sat {
while (!it.at_end()) { while (!it.at_end()) {
clause const& cls = it.curr(); clause const& cls = it.curr();
unsigned sz = cls.size(); unsigned sz = cls.size();
bool is_axiom = false; bool is_axiom = m_removed.get(cls.id(), false);
for (unsigned i = 0; !is_axiom && i < sz; ++i) { for (unsigned i = 0; !is_axiom && i < sz; ++i) {
is_axiom = m_marked[cls[i].index()] && cls[i] != ~lit; is_axiom = m_marked[cls[i].index()] && cls[i] != ~lit;
} }
std::cout << "resolvent " << lit << " : " << cls << " " << (is_axiom?"axiom":"non-axiom") << "\n"; TRACE("bceq", tout << "resolvent " << lit << " : " << cls << " " << (is_axiom?"axiom":"non-axiom") << "\n";);
if (!is_axiom) { if (!is_axiom) {
return false; return false;
} }
@ -231,8 +300,6 @@ namespace sat {
clause const& cls = *m_rstack[i]; clause const& cls = *m_rstack[i];
literal block_lit = m_bstack[i]; literal block_lit = m_bstack[i];
uint64 b = eval_clause(cls); uint64 b = eval_clause(cls);
// std::cout << "Eval: " << block_lit << " " << std::hex << " ";
// std::cout << m_rbits[block_lit.var()] << " " << b << std::dec << "\n";
// v = 0, b = 0 -> v := 1 // v = 0, b = 0 -> v := 1
// v = 0, b = 1 -> v := 0 // v = 0, b = 1 -> v := 0
// v = 1, b = 0 -> v := 0 // v = 1, b = 0 -> v := 0
@ -278,7 +345,7 @@ namespace sat {
table.insert(val, i); table.insert(val, i);
} }
} }
union_find.display(std::cout); TRACE("sat", union_find.display(tout););
// //
// Preliminary version: // Preliminary version:
@ -305,7 +372,7 @@ namespace sat {
} }
void bceq::check_equality(unsigned v1, unsigned v2) { void bceq::check_equality(unsigned v1, unsigned v2) {
std::cout << "check: " << v1 << " = " << v2 << "\n"; TRACE("sat", tout << "check: " << v1 << " = " << v2 << "\n";);
uint64 val1 = m_rbits[v1]; uint64 val1 = m_rbits[v1];
uint64 val2 = m_rbits[v2]; uint64 val2 = m_rbits[v2];
literal l1 = literal(v1, false); literal l1 = literal(v1, false);
@ -315,7 +382,7 @@ namespace sat {
l2.neg(); l2.neg();
} }
if (is_equiv(l1, l2)) { if (is_equiv(l1, l2)) {
std::cout << "Already equivalent: " << l1 << " " << l2 << "\n"; TRACE("sat", tout << "Already equivalent: " << l1 << " " << l2 << "\n";);
return; return;
} }
@ -329,10 +396,10 @@ namespace sat {
is_sat = m_s->check(2, lits); is_sat = m_s->check(2, lits);
} }
if (is_sat == l_false) { if (is_sat == l_false) {
std::cout << "Found equivalent: " << l1 << " " << l2 << "\n"; TRACE("sat", tout << "Found equivalent: " << l1 << " " << l2 << "\n";);
} }
else { else {
std::cout << "Not equivalent\n"; TRACE("sat", tout << "Not equivalent: " << l1 << " " << l2 << "\n";);
} }
} }
@ -344,7 +411,7 @@ namespace sat {
found = w.is_binary_clause() && w.get_literal() == ~l2; found = w.is_binary_clause() && w.get_literal() == ~l2;
} }
if (!found) return false; if (!found) return false;
found = true; found = false;
watch_list const& w2 = m_solver.get_wlist(~l1); watch_list const& w2 = m_solver.get_wlist(~l1);
for (unsigned i = 0; !found && i < w2.size(); ++i) { for (unsigned i = 0; !found && i < w2.size(); ++i) {
watched const& w = w2[i]; watched const& w = w2[i];
@ -361,6 +428,8 @@ namespace sat {
void bceq::operator()() { void bceq::operator()() {
if (!m_solver.m_config.m_bcd) return;
flet<bool> _disable_bcd(m_solver.m_config.m_bcd, false);
use_list ul; use_list ul;
solver s(m_solver.m_params, 0); solver s(m_solver.m_params, 0);
m_use_list = &ul; m_use_list = &ul;
@ -369,7 +438,20 @@ namespace sat {
init(); init();
pure_decompose(); pure_decompose();
post_decompose(); post_decompose();
std::cout << m_L.size() << " vs " << m_R.size() << "\n"; std::cout << "Decomposed set " << m_L.size() << "\n";
TRACE("sat",
tout << "Decomposed set " << m_L.size() << "\n";
for (unsigned i = 0; i < m_L.size(); ++i) {
clause const* cls = m_L[i];
if (cls) tout << *cls << "\n";
}
tout << "remainder " << m_R.size() << "\n";
for (unsigned i = 0; i < m_R.size(); ++i) {
clause const* cls = m_R[i];
if (cls) tout << *cls << "\n";
}
);
sat_sweep(); sat_sweep();
extract_partition(); extract_partition();
cleanup(); cleanup();

View file

@ -45,6 +45,7 @@ namespace sat {
svector<clause*> m_rstack; // stack of blocked clauses svector<clause*> m_rstack; // stack of blocked clauses
literal_vector m_bstack; // stack of blocking literals literal_vector m_bstack; // stack of blocking literals
svector<bool> m_marked; svector<bool> m_marked;
svector<bool> m_removed; // set of clauses removed (not considered in clause set during BCE)
union_find_default_ctx m_union_find_ctx; union_find_default_ctx m_union_find_ctx;
void init(); void init();
@ -55,6 +56,7 @@ namespace sat {
void pure_decompose(clause_use_list& uses, svector<clause*>& clauses); void pure_decompose(clause_use_list& uses, svector<clause*>& clauses);
void post_decompose(); void post_decompose();
literal find_blocked(clause const& cls); literal find_blocked(clause const& cls);
bool bce(clause& cls);
bool is_blocked(literal lit) const; bool is_blocked(literal lit) const;
void init_rbits(); void init_rbits();
void init_reconstruction_stack(); void init_reconstruction_stack();

View file

@ -107,6 +107,7 @@ namespace sat {
m_minimize_core = p.minimize_core(); m_minimize_core = p.minimize_core();
m_minimize_core_partial = p.minimize_core_partial(); m_minimize_core_partial = p.minimize_core_partial();
m_optimize_model = p.optimize_model(); m_optimize_model = p.optimize_model();
m_bcd = p.bcd();
m_dyn_sub_res = p.dyn_sub_res(); m_dyn_sub_res = p.dyn_sub_res();
} }

View file

@ -71,6 +71,7 @@ namespace sat {
bool m_minimize_core; bool m_minimize_core;
bool m_minimize_core_partial; bool m_minimize_core_partial;
bool m_optimize_model; bool m_optimize_model;
bool m_bcd;
symbol m_always_true; symbol m_always_true;

View file

@ -21,4 +21,5 @@ def_module_params('sat',
('minimize_core', BOOL, False, 'minimize computed core'), ('minimize_core', BOOL, False, 'minimize computed core'),
('minimize_core_partial', BOOL, False, 'apply partial (cheap) core minimization'), ('minimize_core_partial', BOOL, False, 'apply partial (cheap) core minimization'),
('optimize_model', BOOL, False, 'enable optimization of soft constraints'), ('optimize_model', BOOL, False, 'enable optimization of soft constraints'),
('bcd', BOOL, False, 'enable blocked clause decomposition for equality extraction'),
('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks'))) ('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks')))

View file

@ -157,7 +157,7 @@ namespace sat {
if (!learned && (m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls)) if (!learned && (m_elim_blocked_clauses || m_elim_blocked_clauses_at == m_num_calls))
elim_blocked_clauses(); elim_blocked_clauses();
#if 0 #if 1
// experiment is disabled. // experiment is disabled.
if (!learned) { // && m_equality_inference if (!learned) { // && m_equality_inference
bceq bc(s); bceq bc(s);

View file

@ -20,6 +20,7 @@ Revision History:
#include"sat_integrity_checker.h" #include"sat_integrity_checker.h"
#include"luby.h" #include"luby.h"
#include"trace.h" #include"trace.h"
#include"sat_bceq.h"
// define to update glue during propagation // define to update glue during propagation
#define UPDATE_GLUE #define UPDATE_GLUE
@ -959,6 +960,7 @@ namespace sat {
m_stopwatch.start(); m_stopwatch.start();
m_core.reset(); m_core.reset();
TRACE("sat", display(tout);); TRACE("sat", display(tout););
} }
/** /**

View file

@ -73,23 +73,24 @@ static void tst_doc1(unsigned n) {
m.display(std::cout, *d1) << "\n"; m.display(std::cout, *d1) << "\n";
svector<bool> to_delete(n, false); bit_vector to_delete;
to_delete[1] = true; to_delete.resize(n, false);
to_delete[3] = true; to_delete.set(1);
to_delete.set(3);
doc_manager m1(n-2); doc_manager m1(n-2);
doc_ref d1_1(m1, m.project(m1, n, to_delete.c_ptr(), *d1)); doc_ref d1_1(m1, m.project(m1, n, to_delete, *d1));
doc_ref d1_2(m1, m1.allocate1()); doc_ref d1_2(m1, m1.allocate1());
m.display(std::cout, *d1) << " -> "; m.display(std::cout, *d1) << " -> ";
m1.display(std::cout, *d1_1) << "\n"; m1.display(std::cout, *d1_1) << "\n";
SASSERT(m1.equals(*d1_1,*d1_2)); SASSERT(m1.equals(*d1_1,*d1_2));
m.set(*d1,2,BIT_x); m.set(*d1,2,BIT_x);
m.set(*d1,4,BIT_x); m.set(*d1,4,BIT_x);
d1_1 = m.project(m1, n, to_delete.c_ptr(), *d1); d1_1 = m.project(m1, n, to_delete, *d1);
m.display(std::cout, *d1) << " -> "; m.display(std::cout, *d1) << " -> ";
m1.display(std::cout, *d1_1) << "\n"; m1.display(std::cout, *d1_1) << "\n";
d1->neg().push_back(m.tbvm().allocate1()); d1->neg().push_back(m.tbvm().allocate1());
SASSERT(m.well_formed(*d1)); SASSERT(m.well_formed(*d1));
d1_1 = m.project(m1, n, to_delete.c_ptr(), *d1); d1_1 = m.project(m1, n, to_delete, *d1);
m.display(std::cout, *d1) << " -> "; m.display(std::cout, *d1) << " -> ";
m1.display(std::cout, *d1_1) << "\n"; m1.display(std::cout, *d1_1) << "\n";
} }
@ -216,11 +217,11 @@ class test_doc_cls {
return result; return result;
} }
void project(doc const& d, doc_manager& m2, bool const* to_delete, doc_ref& result) { void project(doc const& d, doc_manager& m2, const bit_vector& to_delete, doc_ref& result) {
result = dm.project(m2, m_vars.size(), to_delete, d); result = dm.project(m2, m_vars.size(), to_delete, d);
TRACE("doc", TRACE("doc",
for (unsigned i = 0; i < m_vars.size(); ++i) { for (unsigned i = 0; i < m_vars.size(); ++i) {
tout << (to_delete[i]?"0":"1"); tout << (to_delete.get(i)?"0":"1");
} }
tout << " "; tout << " ";
dm.display(tout, d) << " -> "; dm.display(tout, d) << " -> ";
@ -234,28 +235,29 @@ class test_doc_cls {
d = mk_rand_doc(3); d = mk_rand_doc(3);
expr_ref fml1(m), fml2(m), fml3(m), tmp1(m), tmp2(m), fml(m); expr_ref fml1(m), fml2(m), fml3(m), tmp1(m), tmp2(m), fml(m);
fml1 = to_formula(*d, dm); fml1 = to_formula(*d, dm);
svector<bool> to_delete(m_vars.size(), false); bit_vector to_delete;
to_delete.reserve(m_vars.size(), false);
unsigned num_bits = 1; unsigned num_bits = 1;
for (unsigned i = 1; i < to_delete.size(); ++i) { for (unsigned i = 1; i < to_delete.size(); ++i) {
to_delete[i] = (m_ran(2) == 0); to_delete.set(i, m_ran(2) == 0);
if (!to_delete[i]) ++num_bits; if (!to_delete.get(i)) ++num_bits;
} }
doc_manager m2(num_bits); doc_manager m2(num_bits);
doc_ref result(m2); doc_ref result(m2);
project(*d, m2, to_delete.c_ptr(), result); project(*d, m2, to_delete, result);
TRACE("doc", TRACE("doc",
dm.display(tout, *d) << "\n"; dm.display(tout, *d) << "\n";
m2.display(tout, *result) << "\n";); m2.display(tout, *result) << "\n";);
fml2 = to_formula(*result, m2); fml2 = to_formula(*result, m2);
project_expand(fml1, to_delete.c_ptr()); project_expand(fml1, to_delete);
project_rename(fml2, to_delete.c_ptr()); project_rename(fml2, to_delete);
check_equiv(fml1, fml2); check_equiv(fml1, fml2);
} }
void project_expand(expr_ref& fml, bool const* to_delete) { void project_expand(expr_ref& fml, bit_vector const& to_delete) {
expr_ref tmp1(m), tmp2(m); expr_ref tmp1(m), tmp2(m);
for (unsigned i = 0; i < m_vars.size(); ++i) { for (unsigned i = 0; i < m_vars.size(); ++i) {
if (to_delete[i]) { if (to_delete.get(i)) {
expr_safe_replace rep1(m), rep2(m); expr_safe_replace rep1(m), rep2(m);
rep1.insert(m_vars[i].get(), m.mk_true()); rep1.insert(m_vars[i].get(), m.mk_true());
rep1(fml, tmp1); rep1(fml, tmp1);
@ -271,10 +273,10 @@ class test_doc_cls {
} }
} }
void project_rename(expr_ref& fml, bool const* to_delete) { void project_rename(expr_ref& fml, bit_vector const& to_delete) {
expr_safe_replace rep(m); expr_safe_replace rep(m);
for (unsigned i = 0, j = 0; i < m_vars.size(); ++i) { for (unsigned i = 0, j = 0; i < m_vars.size(); ++i) {
if (!to_delete[i]) { if (!to_delete.get(i)) {
rep.insert(m_vars[j].get(), m_vars[i].get()); rep.insert(m_vars[j].get(), m_vars[i].get());
++j; ++j;
} }
@ -293,7 +295,7 @@ class test_doc_cls {
d->neg().push_back(t); d->neg().push_back(t);
} }
fml1 = mk_and(m, fmls.size(), fmls.c_ptr()); fml1 = mk_and(m, fmls.size(), fmls.c_ptr());
svector<bool> to_merge(N, false), to_delete(N, false); svector<bool> to_merge(N, false);
bit_vector discard_cols; bit_vector discard_cols;
discard_cols.resize(N, false); discard_cols.resize(N, false);
unsigned num_bits = 1; unsigned num_bits = 1;
@ -371,17 +373,18 @@ public:
dm.tbvm().set(*t, 0, BIT_0); dm.tbvm().set(*t, 0, BIT_0);
d->neg().push_back(t.detach()); d->neg().push_back(t.detach());
unsigned num_bits = dm.num_tbits(); unsigned num_bits = dm.num_tbits();
svector<bool> to_delete(num_bits, false); bit_vector to_delete;
to_delete.reserve(num_bits, false);
fml1 = to_formula(*d, dm); fml1 = to_formula(*d, dm);
to_delete[0] = true; to_delete.set(0, true);
doc_manager m2(num_bits-1); doc_manager m2(num_bits-1);
doc_ref result(m2); doc_ref result(m2);
project(*d, m2, to_delete.c_ptr(), result); project(*d, m2, to_delete, result);
dm.display(std::cout, *d) << "\n"; dm.display(std::cout, *d) << "\n";
m2.display(std::cout, *result) << "\n"; m2.display(std::cout, *result) << "\n";
fml2 = to_formula(*result, m2); fml2 = to_formula(*result, m2);
project_rename(fml2, to_delete.c_ptr()); project_rename(fml2, to_delete);
project_expand(fml1, to_delete.c_ptr()); project_expand(fml1, to_delete);
std::cout << fml1 << " " << fml2 << "\n"; std::cout << fml1 << " " << fml2 << "\n";
check_equiv(fml1, fml2); check_equiv(fml1, fml2);
} }

View file

@ -25,13 +25,14 @@ static void tst1(unsigned num_bits) {
SASSERT(m.equals(*b0, *bN)); SASSERT(m.equals(*b0, *bN));
VERIFY(!m.intersect(*b0,*b1,*bN)); VERIFY(!m.intersect(*b0,*b1,*bN));
m.fill1(*b1); m.fill1(*b1);
svector<bool> to_delete(num_bits, false); bit_vector to_delete;
to_delete.reserve(num_bits, false);
tbv_manager m2(num_bits-2); tbv_manager m2(num_bits-2);
to_delete[1] = true; to_delete.set(1);
to_delete[3] = true; to_delete.set(3);
m.set(*b1, 2, BIT_0); m.set(*b1, 2, BIT_0);
m.set(*b1, 4, BIT_x); m.set(*b1, 4, BIT_x);
tbv_ref b2(m2, m2.project(num_bits, to_delete.c_ptr(), *b1)); tbv_ref b2(m2, m2.project(num_bits, to_delete, *b1));
m.display(std::cout, *b1) << " -> "; m.display(std::cout, *b1) << " -> ";
m2.display(std::cout, *b2) << "\n"; m2.display(std::cout, *b2) << "\n";
m.deallocate(b0); m.deallocate(b0);

View file

@ -148,6 +148,7 @@ public:
test_rename(); test_rename();
test_filter_neg(); test_filter_neg();
test_filter_neg2();
// empty // empty
@ -551,6 +552,55 @@ public:
t2->deallocate(); t2->deallocate();
} }
void test_filter_neg2() {
// filter_by_negation
relation_signature sig4;
sig4.push_back(bv.mk_sort(1));
sig4.push_back(bv.mk_sort(1));
sig4.push_back(bv.mk_sort(1));
unsigned_vector cols, allcols;
cols.push_back(0);
cols.push_back(2);
allcols.push_back(0);
allcols.push_back(1);
allcols.push_back(2);
/// xxx \ 1x0
udoc_relation* t1 = mk_full(sig4);
{
udoc_relation* neg = mk_full(sig4);
doc& n = neg->get_udoc()[0];
neg->get_dm().set(n, 0, BIT_1);
neg->get_dm().set(n, 2, BIT_0);
apply_filter_neg(*t1, *neg, allcols, allcols);
neg->deallocate();
}
/// xxx \ (1x1 u 0x0)
udoc_relation* t2 = mk_full(sig4);
{
udoc_relation* neg = mk_full(sig4);
doc& n = neg->get_udoc()[0];
neg->get_dm().set(n, 0, BIT_0);
neg->get_dm().set(n, 2, BIT_0);
apply_filter_neg(*t2, *neg, allcols, allcols);
neg->deallocate();
}
{
udoc_relation* neg = mk_full(sig4);
doc& n = neg->get_udoc()[0];
neg->get_dm().set(n, 0, BIT_1);
neg->get_dm().set(n, 2, BIT_1);
apply_filter_neg(*t2, *neg, allcols, allcols);
neg->deallocate();
}
apply_filter_neg(*t2, *t1, cols, cols);
t1->deallocate();
t2->deallocate();
}
void set_random(udoc_relation& r, unsigned num_vals) { void set_random(udoc_relation& r, unsigned num_vals) {
unsigned num_bits = r.get_dm().num_tbits(); unsigned num_bits = r.get_dm().num_tbits();
udoc_relation* full = mk_full(r.get_signature()); udoc_relation* full = mk_full(r.get_signature());

View file

@ -132,6 +132,18 @@ public:
CASSERT("union_find", check_invariant()); CASSERT("union_find", check_invariant());
} }
// dissolve equivalence class of v
// this method cannot be used with backtracking.
void dissolve(unsigned v) {
do {
w = next(v);
m_size[v] = 1;
m_find[v] = v;
m_next[v] = v;
}
while (w != v);
}
void display(std::ostream & out) const { void display(std::ostream & out) const {
unsigned num = get_num_vars(); unsigned num = get_num_vars();
for (unsigned v = 0; v < num; v++) { for (unsigned v = 0; v < num; v++) {