mirror of
https://github.com/Z3Prover/z3
synced 2025-06-27 00:18:45 +00:00
fix-eq bits and projection
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
8384a27eca
commit
c2db127a45
2 changed files with 136 additions and 131 deletions
|
@ -34,35 +34,38 @@ void doc_manager::reset() {
|
||||||
// m.reset(); - not until docs are in small object allocator.
|
// m.reset(); - not until docs are in small object allocator.
|
||||||
}
|
}
|
||||||
doc* doc_manager::allocate() {
|
doc* doc_manager::allocate() {
|
||||||
return alloc(doc, m.allocate());
|
return allocate(m.allocate());
|
||||||
}
|
}
|
||||||
doc* doc_manager::allocate1() {
|
doc* doc_manager::allocate1() {
|
||||||
return alloc(doc, m.allocate1());
|
return allocate(m.allocate1());
|
||||||
}
|
}
|
||||||
doc* doc_manager::allocate0() {
|
doc* doc_manager::allocate0() {
|
||||||
return alloc(doc, m.allocate0());
|
return allocate(m.allocate0());
|
||||||
}
|
}
|
||||||
doc* doc_manager::allocateX() {
|
doc* doc_manager::allocateX() {
|
||||||
return alloc(doc, m.allocateX());
|
return allocate(m.allocateX());
|
||||||
}
|
}
|
||||||
doc* doc_manager::allocate(doc const& src) {
|
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) {
|
for (unsigned i = 0; i < src.neg().size(); ++i) {
|
||||||
r->neg().push_back(m.allocate(src.neg()[i]));
|
r->neg().push_back(m.allocate(src.neg()[i]));
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
doc* doc_manager::allocate(tbv const& src) {
|
||||||
|
return allocate(m.allocate(src));
|
||||||
|
}
|
||||||
doc* doc_manager::allocate(uint64 n) {
|
doc* doc_manager::allocate(uint64 n) {
|
||||||
return alloc(doc, m.allocate(n));
|
return allocate(m.allocate(n));
|
||||||
}
|
}
|
||||||
doc* doc_manager::allocate(rational const& r) {
|
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) {
|
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* 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) {
|
for (unsigned i = 0; i < src.neg().size(); ++i) {
|
||||||
r->neg().push_back(m.allocate(src.neg()[i], permutation));
|
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;
|
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.
|
||||||
if (src.neg().is_empty()) {
|
// 2. If tbv_i uses X in all positions with vars or constant where tbv is constant: can project directly.
|
||||||
// build doc from p.
|
// 3. Perform resolution on remaining tbv_i
|
||||||
return 0;
|
//
|
||||||
}
|
// tbv & ~tbv1 & ~tbv2 & .. & ~tbv_n
|
||||||
NOT_IMPLEMENTED_YET();
|
|
||||||
ptr_vector<tbv> todo;
|
|
||||||
#if 0
|
|
||||||
// tbv & ~tbv1 & ~tbv2 & ..
|
|
||||||
// Semantics of ~tbv1 is that it is a clause of literals.
|
// Semantics of ~tbv1 is that it is a clause of literals.
|
||||||
// indices where BIT_1 is set are negative.
|
// indices where BIT_1 is set are negative.
|
||||||
// indices where BIT_0 is set are positive.
|
// 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
|
doc* doc_manager::project(doc_manager& dstm, unsigned n, bool const* to_delete, doc const& src) {
|
||||||
// don't meet the safety condition.
|
tbv_manager& dstt = dstm.m;
|
||||||
|
doc* r = dstm.allocate(dstt.project(n, to_delete, src.pos()));
|
||||||
|
|
||||||
|
if (src.neg().is_empty()) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
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) {
|
for (unsigned i = 0; i < src.neg().size(); ++i) {
|
||||||
if (can_project_neg(n, to_delete, src.neg()[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;
|
||||||
}
|
}
|
||||||
#endif
|
if (can_project_all) {
|
||||||
#if 0
|
for (unsigned i = 0; i < src.neg().size(); ++i) {
|
||||||
// REVIEW: what is the spec for this code?
|
r->neg().push_back(dstt.project(n, to_delete, src.neg()[i]));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
newneg.reset();
|
//
|
||||||
I->project(delcols, new_size, newneg);
|
// A negation can be projected directly if it does not constrain
|
||||||
result.m_neg.add_fact(newneg);
|
// deleted variables.
|
||||||
skip_row: ;
|
//
|
||||||
|
ptr_vector<tbv> todo;
|
||||||
|
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]));
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newneg.reset();
|
|
||||||
(*I)->project(delcols, new_size, newneg);
|
|
||||||
result.m_neg.add_fact(newneg);
|
|
||||||
skip_bv: ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
else {
|
||||||
// FIXME: eq classes with size > 1 not supported for now
|
todo.push_back(tbvm().allocate(src.neg()[i]));
|
||||||
SASSERT(I->second.first == keep_col);
|
}
|
||||||
I->second.second |= val;
|
}
|
||||||
|
if (todo.empty()) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < todo.size(); ++i) {
|
||||||
|
r->neg().push_back(dstt.project(n, to_delete, *todo[i]));
|
||||||
|
tbvm().deallocate(todo[i]);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void doc_manager::complement(doc const& src, ptr_vector<doc>& result) {
|
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) {
|
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 {
|
bool doc_manager::equals(doc const& a, doc const& b) const {
|
||||||
if (!m.equals(a.pos(), b.pos())) return false;
|
if (!m.equals(a.pos(), b.pos())) return false;
|
||||||
|
|
|
@ -44,6 +44,8 @@ public:
|
||||||
doc* allocate0();
|
doc* allocate0();
|
||||||
doc* allocateX();
|
doc* allocateX();
|
||||||
doc* allocate(doc const& src);
|
doc* allocate(doc const& src);
|
||||||
|
doc* allocate(tbv const& src);
|
||||||
|
doc* allocate(tbv * src);
|
||||||
doc* allocate(uint64 n);
|
doc* allocate(uint64 n);
|
||||||
doc* allocate(rational const& r);
|
doc* allocate(rational const& r);
|
||||||
doc* allocate(uint64 n, unsigned hi, unsigned lo);
|
doc* allocate(uint64 n, unsigned hi, unsigned lo);
|
||||||
|
@ -65,13 +67,14 @@ public:
|
||||||
bool contains(doc const& a, doc const& b) const;
|
bool contains(doc const& a, doc const& b) const;
|
||||||
std::ostream& display(std::ostream& out, doc const& b) const;
|
std::ostream& display(std::ostream& out, doc const& b) const;
|
||||||
unsigned num_tbits() const { return m.num_tbits(); }
|
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 well_formed(doc const& d) const;
|
||||||
bool merge(doc& d, unsigned lo, unsigned length, subset_ints& equalities, bit_vector const& discard_cols);
|
bool merge(doc& d, unsigned lo, unsigned length, subset_ints& equalities, bit_vector const& discard_cols);
|
||||||
void set(doc& d, unsigned idx, tbit value);
|
void set(doc& d, unsigned idx, tbit value);
|
||||||
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& equalities, bit_vector const& discard_cols);
|
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* operator->() { return d; }
|
doc* operator->() { return d; }
|
||||||
|
doc* detach() { doc* r = d; d = 0; return r; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _DOC_H_ */
|
#endif /* _DOC_H_ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue