z3-z3-4.13.0.src.muz.rel.doc.h Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2014 Microsoft Corporation
Module Name:
doc.h
Abstract:
difference of cubes.
Author:
Nuno Lopes (a-nlopes) 2013-03-01
Nikolaj Bjorner (nbjorner) 2014-09-15
Revision History:
Based on ternary_diff_bitvector by Nuno Lopes.
--*/
#pragma once
#include "util/tbv.h"
#include "util/union_find.h"
#include "util/buffer.h"
#include "ast/ast.h"
class doc;
template class union_bvec;
typedef union_find<> subset_ints;
typedef union_bvec utbv;
typedef buffer tbv_vector;
typedef buffer doc_vector;
class doc_manager {
tbv_manager m;
tbv* m_full;
small_object_allocator m_alloc;
enum project_action_t {
project_is_empty,
project_done,
project_monolithic,
project_neg,
project_pos,
project_resolve
};
project_action_t pick_resolvent(
tbv const& pos, tbv_vector const& neg, bit_vector const& to_delete, unsigned& idx);
public:
doc_manager(unsigned num_bits);
~doc_manager();
tbv_manager& tbvm() { return m; }
tbv_manager const& tbvm() const { return m; }
doc* allocate();
doc* allocate1();
doc* allocate0();
doc* allocateX();
doc* allocate(doc const& src);
doc* allocate(tbv const& src);
doc* allocate(tbv * src);
doc* allocate(uint64_t n);
doc* allocate(rational const& r);
doc* allocate(uint64_t n, unsigned hi, unsigned lo);
doc* allocate(doc const& src, unsigned const* permutation);
void deallocate(doc* src);
void copy(doc& dst, doc const& src);
doc& reset(doc& src) { return fill0(src); }
doc& fill0(doc& src);
doc& fill1(doc& src);
doc& fillX(doc& src);
bool is_full(doc const& src) const;
bool is_empty_complete(ast_manager& m, 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, doc_vector& result);
void subtract(doc const& A, doc const& B, doc_vector& result);
bool equals(doc const& a, doc const& b) const;
unsigned hash(doc const& src) const;
bool contains(doc const& a, doc const& b) const;
bool contains(doc const& a, unsigned_vector const& colsa,
doc const& b, unsigned_vector const& colsb) 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;
unsigned num_tbits() const { return m.num_tbits(); }
unsigned get_size_estimate_bytes(const doc& d) const;
doc* project(doc_manager& dstm, bit_vector const& to_delete, doc const& src);
bool well_formed(doc const& d) const;
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);
doc* join(const doc& a, const doc& b, doc_manager& dm1,
const unsigned_vector& cols1, const unsigned_vector& cols2);
void verify_project(ast_manager& m, doc_manager& dstm, bit_vector const& to_delete, doc const& src, doc const& dst);
private:
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);
void project_rename(expr_ref& fml, bit_vector 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, tbv const& src);
expr_ref mk_var(ast_manager& m, unsigned i);
void check_equiv(ast_manager& m, expr* fml1, expr* fml2);
};
// union of tbv*, union of doc*
template
class union_bvec {
buffer m_elems; // TBD: reuse allocator of M
enum fix_bit_result_t {
e_row_removed, // = 1
e_duplicate_row, // = 2
e_fixed
};
public:
unsigned size() const { return m_elems.size(); }
T& operator[](unsigned idx) const { return *m_elems[idx]; }
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 contains(M& m, T& t) const {
for (unsigned i = 0; i < size(); ++i) {
if (m.contains(*m_elems[i], t)) return true;
}
return false;
}
std::ostream& display(M const& m, std::ostream& out) const {
if (m.num_tbits() == 0) return out << "[]";
return display(m, out, m.num_tbits()-1, 0);
}
std::ostream& display(M const& m, std::ostream& out, unsigned hi, unsigned lo) const {
out << "{";
if (size() + m.num_tbits() > 10) out << "\n ";
for (unsigned i = 0; i < size(); ++i) {
m.display(out, *m_elems[i], hi, lo);
if (i + 1 < size()) out << ", ";
if (i + 1 < size() && m.num_tbits() > 10) out << "\n ";
}
return out << "}";
}
void push_back(T* t) {
SASSERT(t);
m_elems.push_back(t);
}
void erase(M& m, unsigned idx) {
m.deallocate(m_elems[idx]);
unsigned sz = m_elems.size();
for (unsigned i = idx+1; i < sz; ++i) {
m_elems[i-1] = m_elems[i];
}
m_elems.resize(sz-1);
}
void reset(M& m) {
for (unsigned i = 0; i < m_elems.size(); ++i) {
m.deallocate(m_elems[i]);
}
m_elems.reset();
}
bool insert(M& m, T* t) {
SASSERT(t);
unsigned sz = size(), j = 0;
bool found = false;
unsigned i = 0;
for ( ; i < sz; ++i, ++j) {
if (m.contains(*m_elems[i], *t)) {
found = true;
}
else if (m.contains(*t, *m_elems[i])) {
m.deallocate(m_elems[i]);
--j;
continue;
}
if (i != j) {
m_elems[j] = m_elems[i];
}
}
if (j != sz) m_elems.resize(j);
if (found) {
m.deallocate(t);
}
else {
m_elems.push_back(t);
}
return !found;
}
void intersect(M& m, T const& t) {
unsigned sz = size();
unsigned j = 0;
for (unsigned i = 0; i < sz; ++i, ++j) {
if (!m.set_and(*m_elems[i], t)) {
m.deallocate(m_elems[i]);
--j;
}
else if (i != j) {
m_elems[j] = m_elems[i];
}
}
if (j != sz) m_elems.resize(j);
}
void insert(M& m, union_bvec const& other) {
for (unsigned i = 0; i < other.size(); ++i) {
insert(m, &other[i]);
}
}
void intersect(M& m, union_bvec const& other) {
unsigned sz = other.size();
union_bvec tmp, result;
for (unsigned i = 0; i < sz; ++i) {
tmp.copy(m, *this);
tmp.intersect(m, other[i]);
for (unsigned j = 0; j < tmp.size(); ++j) {
result.push_back(tmp.m_elems[j]);
}
tmp.m_elems.reset();
}
std::swap(*this, result);
result.reset(m);
}
void subtract(M& m, union_bvec const& other) {
unsigned sz = other.size();
for (unsigned i = 0; !is_empty() && i < sz; ++i) {
subtract(m, other[i]);
}
// TBD compress?
}
void subtract(M& m, T& t) {
unsigned sz = size();
union_bvec result;
for (unsigned i = 0; i < sz; ++i) {
m.subtract(*m_elems[i], t, result.m_elems);
}
std::swap(m_elems, result.m_elems);
result.reset(m);
}
void complement(M& m, union_bvec& result) const {
union_bvec negated;
result.reset(m);
result.push_back(m.allocateX());
unsigned sz = size();
for (unsigned i = 0; !is_empty() && i < sz; ++i) {
m.complement(*m_elems[i], negated.m_elems);
result.intersect(m, negated);
negated.reset(m);
}
}
void copy(M& m, union_bvec const& other) {
reset(m);
for (unsigned i = 0; i < other.size(); ++i) {
push_back(m.allocate(other[i]));
}
}
void simplify(M& m) {
union_bvec result;
for (unsigned i = 0; i < size(); ++i) {
if (m.fold_neg(*m_elems[i])) {
result.insert(m, m_elems[i]);
}
else {
m.deallocate(m_elems[i]);
}
}
std::swap(*this, result);
}
bool well_formed(M& m) const {
for (unsigned i = 0; i < size(); ++i) {
if (!m.well_formed(*m_elems[i])) return false;
}
return true;
}
void merge(M& m, unsigned lo, unsigned length, subset_ints const& equalities, bit_vector const& discard_cols) {
unsigned j = 0;
unsigned sz = size();
for (unsigned i = 0; i < sz; ++i, ++j) {
if (!m.merge(*m_elems[i], lo, length, equalities, discard_cols)) {
--j;
m.deallocate(m_elems[i]);
}
else if (i != j) {
m_elems[j] = m_elems[i];
}
}
if (j != sz) m_elems.resize(j);
}
void merge(M& m, unsigned lo1, unsigned lo2, unsigned length, bit_vector const& discard_cols) {
union_find_default_ctx union_ctx;
subset_ints equalities(union_ctx);
for (unsigned i = 0; i < discard_cols.size(); ++i) {
equalities.mk_var();
}
for (unsigned j = 0; j < length; ++j) {
equalities.merge(lo1 + j, lo2 + j);
}
merge(m, lo1, length, equalities, discard_cols);
}
void merge(M& m, unsigned_vector const& roots, subset_ints const& equalities,
bit_vector const& discard_cols) {
for (unsigned i = 0; i < roots.size(); ++i) {
merge(m, roots[i], 1, equalities, discard_cols);
}
}
void join(const union_bvec& d1, const union_bvec& d2, M& dm, M& dm1,
const unsigned_vector& cols1, const unsigned_vector& cols2) {
for (unsigned i = 0; i < d1.size(); ++i) {
for (unsigned j = 0; j < d2.size(); ++j) {
if (T *d = dm.join(d1[i], d2[j], dm1, cols1, cols2))
insert(dm, d);
}
}
}
unsigned get_size_estimate_bytes(const M& m) const {
unsigned sz = sizeof(T*) * size();
for (unsigned i = 0; i < size(); ++i) {
sz += m.get_size_estimate_bytes(*m_elems[i]);
}
return sz;
}
};
class doc {
// pos \ (neg_0 \/ ... \/ neg_n)
friend class doc_manager;
tbv* m_pos;
utbv m_neg;
public:
struct eq {
doc_manager& m;
eq(doc_manager& m):m(m) {}
bool operator()(doc const& d1, doc const& d2) const {
return m.equals(d1, d2);
}
};
struct hash {
doc_manager& m;
hash(doc_manager& m):m(m) {}
unsigned operator()(doc const& d) const {
return m.hash(d);
}
};
doc(tbv* t): m_pos(t) {}
tbv& pos() { return *m_pos; }
utbv& neg() { return m_neg; }
tbv const& pos() const { return *m_pos; }
utbv const& neg() const { return m_neg; }
tbit operator[](unsigned idx) const { return pos()[idx]; }
};
typedef union_bvec udoc;
class doc_ref {
doc_manager& dm;
doc* d;
public:
doc_ref(doc_manager& dm):dm(dm),d(nullptr) {}
doc_ref(doc_manager& dm, doc* d):dm(dm),d(d) {}
~doc_ref() {
if (d) dm.deallocate(d);
}
doc_ref& operator=(doc* d2) {
if (d) dm.deallocate(d);
d = d2;
return *this;
}
doc& operator*() { return *d; }
doc* operator->() { return d; }
doc* detach() { doc* r = d; d = nullptr; return r; }
operator bool() const { return d != nullptr; }
};