3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 05:18:44 +00:00

fix-eq bits and projection

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2014-09-18 14:04:06 -07:00
parent 8384a27eca
commit c2db127a45
2 changed files with 136 additions and 131 deletions

View file

@ -34,35 +34,38 @@ void doc_manager::reset() {
// m.reset(); - not until docs are in small object allocator.
}
doc* doc_manager::allocate() {
return alloc(doc, m.allocate());
return allocate(m.allocate());
}
doc* doc_manager::allocate1() {
return alloc(doc, m.allocate1());
return allocate(m.allocate1());
}
doc* doc_manager::allocate0() {
return alloc(doc, m.allocate0());
return allocate(m.allocate0());
}
doc* doc_manager::allocateX() {
return alloc(doc, m.allocateX());
return allocate(m.allocateX());
}
doc* doc_manager::allocate(doc const& src) {
doc* r = alloc(doc, m.allocate(src.pos()));
doc* r = allocate(m.allocate(src.pos()));
for (unsigned i = 0; i < src.neg().size(); ++i) {
r->neg().push_back(m.allocate(src.neg()[i]));
}
return r;
}
doc* doc_manager::allocate(tbv const& src) {
return allocate(m.allocate(src));
}
doc* doc_manager::allocate(uint64 n) {
return alloc(doc, m.allocate(n));
return allocate(m.allocate(n));
}
doc* doc_manager::allocate(rational const& r) {
return alloc(doc, m.allocate(r));
return allocate(m.allocate(r));
}
doc* doc_manager::allocate(uint64 n, unsigned hi, unsigned lo) {
return alloc(doc, m.allocate(n, hi, lo));
return allocate(m.allocate(n, hi, lo));
}
doc* doc_manager::allocate(doc const& src, unsigned const* permutation) {
doc* r = alloc(doc, m.allocate(src.pos(), permutation));
doc* r = allocate(m.allocate(src.pos(), permutation));
for (unsigned i = 0; i < src.neg().size(); ++i) {
r->neg().push_back(m.allocate(src.neg()[i], permutation));
}
@ -252,143 +255,141 @@ bool doc_manager::merge(doc& d, unsigned idx, subset_ints& equalities, bit_vecto
return true;
}
doc* doc_manager::project(unsigned n, bool const* to_delete, doc const& src) {
tbv* p = tbvm().project(n, to_delete, src.pos());
//
// 1. If n = 0,1: can project directly.
// 2. If tbv_i uses X in all positions with vars or constant where tbv is constant: can project directly.
// 3. Perform resolution on remaining tbv_i
//
// tbv & ~tbv1 & ~tbv2 & .. & ~tbv_n
// Semantics of ~tbv1 is that it is a clause of literals.
// indices where BIT_1 is set are negative.
// indices where BIT_0 is set are positive.
//
doc* doc_manager::project(doc_manager& dstm, unsigned n, bool const* to_delete, doc const& src) {
tbv_manager& dstt = dstm.m;
doc* r = dstm.allocate(dstt.project(n, to_delete, src.pos()));
if (src.neg().is_empty()) {
// build doc from p.
return 0;
return r;
}
NOT_IMPLEMENTED_YET();
if (src.neg().size() == 1) {
r->neg().push_back(dstt.project(n, to_delete, src.neg()[0]));
return r;
}
//
// All negations can be projected if they are sign compatible.
//
tbv_ref bits(tbvm(), tbvm().allocateX());
for (unsigned i = 0; i < src.neg().size(); ++i) {
tbvm().set_and(*bits, src.neg()[i]);
}
bool can_project_all = true;
for (unsigned i = 0; can_project_all && i < n; ++i) {
can_project_all = !to_delete[i] || (*bits)[i] != BIT_z;
}
if (can_project_all) {
for (unsigned i = 0; i < src.neg().size(); ++i) {
r->neg().push_back(dstt.project(n, to_delete, src.neg()[i]));
}
return r;
}
//
// A negation can be projected directly if it does not constrain
// deleted variables.
//
ptr_vector<tbv> todo;
#if 0
// tbv & ~tbv1 & ~tbv2 & ..
// Semantics of ~tbv1 is that it is a clause of literals.
// indices where BIT_1 is set are negative.
// indices where BIT_0 is set are positive.
// The first loop is supposed to project tbv_i directly
// when some safety condition is met.
// The second loop handles the remaining tbv_i that
// don't meet the safety condition.
for (unsigned i = 0; i < src.neg().size(); ++i) {
if (can_project_neg(n, to_delete, src.neg()[i])) {
for (unsigned i = 0; i < src.neg().size(); ++i) {
if (can_project_neg(src.pos(), n, to_delete, src.neg()[i])) {
r->neg().push_back(dstt.project(n, to_delete, src.neg()[i]));
}
else {
todo.push_back(tbvm().allocate(src.neg()[i]));
}
}
#endif
#if 0
// REVIEW: what is the spec for this code?
ternary_diff_bitvector TBV(*this);
if (!TBV.fold_neg())
return false;
std::set<ternary_bitvector*> todo;
cpy_bits_t cpy_bits;
ternary_bitvector newneg;
for (union_ternary_bitvector<ternary_bitvector>::iterator I = TBV.m_neg.begin(),
E = TBV.m_neg.end(); I != E; ++I) {
// check if subtract TBV should be skiped
for (unsigned i = 0; i < delcols.size()-1; ++i) {
unsigned idx = delcols[i];
if (I->get(idx) != TBV.m_pos.get(idx)) { // xx \ 1x
if (analyze_copy_bit(TBV.m_pos, *I, delcols, cpy_bits))
todo.insert(&*I);
goto skip_row;
}
}
newneg.reset();
I->project(delcols, new_size, newneg);
result.m_neg.add_fact(newneg);
skip_row: ;
if (todo.empty()) {
return r;
}
if (!todo.empty()) {
for (std::set<ternary_bitvector*>::iterator I = todo.begin(),
E = todo.end(); I != E; ++I) {
for (unsigned i = 0; i < delcols.size()-1; ++i) {
unsigned idx = delcols[i];
if ((*I)->get(idx) != TBV.m_pos.get(idx)) {
cpy_bits_t::iterator II = cpy_bits.find(idx);
if (II == cpy_bits.end())
goto skip_bv;
unsigned idx_keep = II->second.first;
unsigned cpy_val = II->second.second;
if (!((*I)->get(idx) & cpy_val) || (*I)->get(idx_keep) != BIT_x)
goto skip_bv;
(*I)->set(idx_keep, (*I)->get(idx));
ptr_vector<tbv> pos, neg, new_todo;
tbv_ref t1(tbvm()), t2(tbvm());
for (unsigned i = 0; i < n; ++i) {
if (to_delete[i] && (*bits)[i] == BIT_z) {
new_todo.reset();
for (unsigned j = 0; j < todo.size(); ++j) {
tbv& t = *todo[j];
switch(t[i]) {
case BIT_x: new_todo.push_back(&t); break;
case BIT_0: pos.push_back(&t); break;
case BIT_1: neg.push_back(&t); break;
default: UNREACHABLE(); break;
}
}
newneg.reset();
(*I)->project(delcols, new_size, newneg);
result.m_neg.add_fact(newneg);
skip_bv: ;
if (pos.empty() || neg.empty()) {
continue;
}
for (unsigned j = 0; j < pos.size(); ++j) {
t1 = tbvm().allocate(*pos[j]);
(*t1).set(i, BIT_x);
for (unsigned k = 0; k < neg.size(); ++k) {
if (tbvm().set_and(*t1, *neg[k])) {
new_todo.push_back(t1.detach());
t1 = tbvm().allocate(*pos[j]);
(*t1).set(i, BIT_x);
}
}
}
for (unsigned i = 0; i < pos.size(); ++i) {
tbvm().deallocate(pos[i]);
}
for (unsigned i = 0; i < neg.size(); ++i) {
tbvm().deallocate(neg[i]);
}
std::swap(todo, new_todo);
}
}
return !result.is_empty();
// idx_del -> <idx_keep, val>
// val -> BIT_*
typedef std::map<unsigned, std::pair<unsigned, unsigned char> > cpy_bits_t;
static bool analyze_copy_bit(const ternary_bitvector& pos, const ternary_bitvector& neg,
const unsigned_vector& delcols, cpy_bits_t& cpy_bits) {
unsigned *del = delcols.c_ptr();
bool got_del_col = false, got_keep_col = false;
unsigned del_col = 0, keep_col = 0;
for (unsigned i = 0; i < pos.size(); ++i) {
if (pos.get(i) != neg.get(i)) {
if (*del == i) {
if (got_del_col)
return true;
del_col = i;
got_del_col = true;
} else {
if (got_keep_col)
return true;
keep_col = i;
got_keep_col = true;
}
}
if (i == *del)
++del;
}
if (!got_del_col || !got_keep_col)
return true;
if (neg.get(keep_col) == neg.get(del_col))
return false;
unsigned char val = neg.get(del_col);
cpy_bits_t::iterator I = cpy_bits.find(del_col);
if (I == cpy_bits.end())
cpy_bits[del_col] = std::make_pair(keep_col, val);
else {
// FIXME: eq classes with size > 1 not supported for now
SASSERT(I->second.first == keep_col);
I->second.second |= val;
}
return false;
for (unsigned i = 0; i < todo.size(); ++i) {
r->neg().push_back(dstt.project(n, to_delete, *todo[i]));
tbvm().deallocate(todo[i]);
}
#endif
return 0;
return r;
}
bool doc_manager::can_project_neg(tbv const& pos, unsigned n, bool const* to_delete, tbv const& neg) {
for (unsigned i = 0; i < n; ++i) {
if (to_delete[i] && BIT_x != neg[i] && BIT_x == pos[i]) return false;
}
return true;
}
void doc_manager::complement(doc const& src, ptr_vector<doc>& result) {
NOT_IMPLEMENTED_YET();
result.reset();
if (is_full(src)) {
return;
}
doc* r = allocateX();
r->neg().push_back(m.allocate(src.pos()));
result.push_back(r);
for (unsigned i = 0; i < src.neg().size(); ++i) {
result.push_back(allocate(src.neg()[i]));
}
}
void doc_manager::subtract(doc const& A, doc const& B, ptr_vector<doc>& result) {
NOT_IMPLEMENTED_YET();
doc_ref r(*this), r2(*this);
r = allocate(A);
if (r->neg().insert(m, m.allocate(B.pos()))) {
result.push_back(r.detach());
r = allocate(A);
}
for (unsigned i = 0; i < B.neg().size(); ++i) {
r2 = allocate(B.neg()[i]);
if (set_and(*r, *r2)) {
result.push_back(r.detach());
r = allocate(A);
}
}
}
bool doc_manager::equals(doc const& a, doc const& b) const {
if (!m.equals(a.pos(), b.pos())) return false;

View file

@ -44,6 +44,8 @@ public:
doc* allocate0();
doc* allocateX();
doc* allocate(doc const& src);
doc* allocate(tbv const& src);
doc* allocate(tbv * src);
doc* allocate(uint64 n);
doc* allocate(rational const& r);
doc* allocate(uint64 n, unsigned hi, unsigned lo);
@ -65,13 +67,14 @@ public:
bool contains(doc const& a, doc const& b) const;
std::ostream& display(std::ostream& out, doc const& b) const;
unsigned num_tbits() const { return m.num_tbits(); }
doc* project(unsigned n, bool const* to_delete, doc const& src);
doc* project(doc_manager& dstm, unsigned n, bool const* to_delete, doc const& src);
bool well_formed(doc const& d) const;
bool merge(doc& d, unsigned lo, unsigned length, subset_ints& equalities, bit_vector const& discard_cols);
void set(doc& d, unsigned idx, tbit value);
private:
unsigned diff_by_012(tbv const& pos, tbv const& neg, unsigned& index);
bool merge(doc& d, unsigned idx, subset_ints& equalities, bit_vector const& discard_cols);
bool can_project_neg(tbv const& pos, unsigned n, bool const* to_delete, tbv const& neg);
};
@ -293,6 +296,7 @@ public:
}
doc& operator*() { return *d; }
doc* operator->() { return d; }
doc* detach() { doc* r = d; d = 0; return r; }
};
#endif /* _DOC_H_ */