3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-22 02:57:50 +00:00

move doc code to rel, adding unit test

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2014-09-19 11:00:30 -07:00
parent cb8ad76677
commit 5679cc7567
12 changed files with 1138 additions and 19 deletions

View file

@ -1,464 +0,0 @@
/*++
Copyright (c) 2014 Microsoft Corporation
Module Name:
doc.cpp
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.
--*/
#include "doc.h"
doc_manager::doc_manager(unsigned n): m(n), m_alloc("doc") {
m_full = m.allocateX();
}
doc_manager::~doc_manager() {
m.deallocate(m_full);
}
doc* doc_manager::allocate() {
return allocate(m.allocate());
}
doc* doc_manager::allocate1() {
return allocate(m.allocate1());
}
doc* doc_manager::allocate0() {
return allocate(m.allocate0());
}
doc* doc_manager::allocateX() {
return allocate(m.allocateX());
}
doc* doc_manager::allocate(doc const& src) {
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* t) {
void* mm = m_alloc.allocate(sizeof(doc));
return new (mm) doc(t);
}
doc* doc_manager::allocate(tbv const& src) {
return allocate(m.allocate(src));
}
doc* doc_manager::allocate(uint64 n) {
return allocate(m.allocate(n));
}
doc* doc_manager::allocate(rational const& r) {
return allocate(m.allocate(r));
}
doc* doc_manager::allocate(uint64 n, unsigned hi, unsigned lo) {
return allocate(m.allocate(n, hi, lo));
}
doc* doc_manager::allocate(doc const& src, unsigned const* 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));
}
return r;
}
void doc_manager::deallocate(doc* src) {
if (!src) return;
m.deallocate(&src->pos());
src->neg().reset(m);
m_alloc.deallocate(sizeof(doc), src);
// dealloc(src);
}
void doc_manager::copy(doc& dst, doc const& src) {
m.copy(dst.pos(), src.pos());
unsigned n = std::min(src.neg().size(), dst.neg().size());
for (unsigned i = 0; i < n; ++i) {
m.copy(dst.neg()[i], src.neg()[i]);
}
for (unsigned i = n; i < dst.neg().size(); ++i) {
dst.neg().erase(m, dst.neg().size()-1);
}
for (unsigned i = n; i < src.neg().size(); ++i) {
dst.neg().push_back(m.allocate(src.neg()[i]));
}
}
doc& doc_manager::fill0(doc& src) {
src.neg().reset(m);
m.fill0(src.pos());
return src;
}
doc& doc_manager::fill1(doc& src) {
src.neg().reset(m);
m.fill1(src.pos());
return src;
}
doc& doc_manager::fillX(doc& src) {
src.neg().reset(m);
m.fillX(src.pos());
return src;
}
bool doc_manager::set_and(doc& dst, doc const& src) {
// (A \ B) & (C \ D) = (A & C) \ (B u D)
if (!m.set_and(dst.pos(), src.pos())) return false;
for (unsigned i = 0; i < dst.neg().size(); ++i) {
if (!m.set_and(dst.neg()[i], dst.pos())) {
dst.neg().erase(m, i);
--i;
}
}
tbv_ref t(m);
for (unsigned i = 0; i < src.neg().size(); ++i) {
t = m.allocate(src.neg()[i]);
if (m.set_and(*t, dst.pos())) {
dst.neg().insert(m, t.detach());
}
}
return (src.neg().is_empty() || fold_neg(dst));
}
bool doc_manager::well_formed(doc const& d) const {
if (!m.is_well_formed(d.pos())) return false;
for (unsigned i = 0; i < d.neg().size(); ++i) {
if (!m.is_well_formed(d.neg()[i])) return false;
if (!m.contains(d.pos(), d.neg()[i])) return false;
}
return true;
}
bool doc_manager::fold_neg(doc& dst) {
start_over:
for (unsigned i = 0; i < dst.neg().size(); ++i) {
unsigned index;
unsigned count = diff_by_012(dst.pos(), dst.neg()[i], index);
if (count != 2) {
if (count == 0) {
return false;
}
else if (count == 3) {
dst.neg().erase(tbvm(), i);
--i;
}
else { // count == 1:
dst.pos().set(index, neg(dst.neg()[i][index]));
dst.neg().erase(tbvm(), i);
goto start_over;
}
}
}
return true;
}
unsigned doc_manager::diff_by_012(tbv const& pos, tbv const& neg, unsigned& index) {
unsigned n = num_tbits();
unsigned count = 0;
for (unsigned i = 0; i < n; ++i) {
tbit b1 = pos[i];
tbit b2 = neg[i];
SASSERT(b1 != BIT_z && b2 != BIT_z);
if (b1 != b2) {
if (count == 1) return 2;
if (b1 == BIT_x) {
index = i;
count = 1;
}
else if (b2 != BIT_x) {
return 3;
}
}
}
return count;
}
void doc_manager::set(doc& d, unsigned idx, tbit value) {
d.pos().set(idx, value);
for (unsigned i = 0; i < d.neg().size(); ++i) {
d.neg()[i].set(idx, value);
}
}
//
// merge range from [lo:lo+length-1] with each index in equivalence class.
// under assumption of equalities and columns that are discarded.
//
bool doc_manager::merge(
doc& d, unsigned lo, unsigned length,
subset_ints& equalities, bit_vector const& discard_cols) {
std::cout << "merge\n";
for (unsigned i = 0; i < length; ++i) {
unsigned idx = lo + i;
if (!merge(d, lo + i, equalities, discard_cols)) return false;
}
return true;
}
bool doc_manager::merge(doc& d, unsigned idx, subset_ints& equalities, bit_vector const& discard_cols) {
unsigned root = equalities.find(idx);
idx = root;
unsigned num_x = 0;
unsigned root1;
tbit value = BIT_x;
do {
switch (d[idx]) {
case BIT_0:
if (value == BIT_1) return false;
value = BIT_0;
break;
case BIT_1:
if (value == BIT_0) return false;
value = BIT_1;
break;
case BIT_x:
if (!discard_cols.get(idx)) {
++num_x;
root1 = idx;
}
break;
default:
break;
}
idx = equalities.next(idx);
}
while (idx != root);
if (num_x == 0) {
// nothing to do.
}
else if (value != BIT_x) {
do {
if (d[idx] == BIT_x) {
set(d, idx, value);
}
idx = equalities.next(idx);
}
while (idx != root);
}
else {
do {
if (!discard_cols.get(idx) && idx != root1) {
tbv* t = tbvm().allocate(d.pos());
std::cout << "insert " << t << "\n";
t->set(idx, BIT_0);
t->set(root1, BIT_1);
d.neg().insert(tbvm(), t);
t = tbvm().allocate(d.pos());
std::cout << "insert " << t << "\n";
t->set(idx, BIT_1);
t->set(root1, BIT_0);
d.neg().insert(tbvm(), t);
}
idx = equalities.next(idx);
}
while (idx != root);
}
return true;
}
//
// 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()) {
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) {
tbvm().set_and(*bits, src.neg()[i]);
}
bool can_project_const = true;
for (unsigned i = 0; can_project_const && i < n; ++i) {
can_project_const = !to_delete[i] || (*bits)[i] == BIT_x;
}
if (can_project_const) {
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;
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]));
}
}
if (todo.empty()) {
return r;
}
ptr_vector<tbv> new_todo;
utbv pos, neg;
tbv_ref t1(tbvm()), t2(tbvm());
for (unsigned i = 0; i < n; ++i) {
if (to_delete[i] && (*bits)[i] != BIT_x) {
TRACE("doc", tout << "delete " << i << " ";
for (unsigned j = 0; j < todo.size(); ++j) {
tbvm().display(tout, *todo[j]) << " ";
}
tout << "\n";);
SASSERT(pos.is_empty());
SASSERT(neg.is_empty());
SASSERT(new_todo.empty());
while (!todo.empty()) {
tbv* t = todo.back();
todo.pop_back();
switch((*t)[i]) {
case BIT_x: new_todo.push_back(t); break;
case BIT_0: neg.push_back(t); break;
case BIT_1: pos.push_back(t); break;
default: UNREACHABLE(); break;
}
}
if (pos.is_empty() || neg.is_empty()) {
std::swap(new_todo, todo);
pos.reset(tbvm());
neg.reset(tbvm());
continue;
}
TRACE("doc",
tout << "pos: ";
for (unsigned i = 0; i < pos.size(); ++i) {
tbvm().display(tout, pos[i]) << " ";
}
tout << "\nneg: ";
for (unsigned i = 0; i < neg.size(); ++i) {
tbvm().display(tout, neg[i]) << " ";
}
tout << "\n";
);
for (unsigned j = 0; j < pos.size(); ++j) {
for (unsigned k = 0; k < neg.size(); ++k) {
t1 = tbvm().allocate(pos[j]);
(*t1).set(i, BIT_x);
if (tbvm().set_and(*t1, neg[k])) {
(*t1).set(i, BIT_x);
new_todo.push_back(t1.detach());
}
}
}
pos.reset(tbvm());
neg.reset(tbvm());
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;
}
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) {
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) {
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;
if (a.neg().size() != b.neg().size()) return false;
for (unsigned i = 0; i < a.neg().size(); ++i) {
if (!m.equals(a.neg()[i], b.neg()[i])) return false;
}
return true;
}
bool doc_manager::is_full(doc const& src) const {
return src.neg().is_empty() && m.equals(src.pos(), *m_full);
}
unsigned doc_manager::hash(doc const& src) const {
unsigned r = 0;
for (unsigned i = 0; i < src.neg().size(); ++i) {
r = 2*r + m.hash(src.neg()[i]);
}
return r + m.hash(src.pos());
}
// approximation
// A \ (A1 u A2) contains B \ (B1 u B2)
// if
// A contains B
// B1 contains A1 or A2
bool doc_manager::contains(doc const& a, doc const& b) const {
if (!m.contains(a.pos(), b.pos())) return false;
for (unsigned i = 0; i < b.neg().size(); ++i) {
bool found = false;
for (unsigned j = 0; !found && j < a.neg().size(); ++j) {
found = m.contains(b.neg()[i],a.neg()[j]);
}
if (!found) return false;
}
return true;
}
std::ostream& doc_manager::display(std::ostream& out, doc const& b) const {
m.display(out, b.pos());
if (b.neg().is_empty()) return out;
out << " \\ {";
for (unsigned i = 0; i < b.neg().size(); ++i) {
m.display(out, b.neg()[i]);
if (i + 1 < b.neg().size()) out << ", ";
}
return out << "}";
}

View file

@ -1,305 +0,0 @@
/*++
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.
--*/
#ifndef _DOC_H_
#define _DOC_H_
#include "tbv.h"
#include "union_find.h"
class doc;
template<typename M, typename T> class union_bvec;
typedef union_find<> subset_ints;
class doc_manager {
tbv_manager m;
tbv* m_full;
small_object_allocator m_alloc;
public:
doc_manager(unsigned num_bits);
~doc_manager();
tbv_manager& tbvm() { 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 n);
doc* allocate(rational const& r);
doc* allocate(uint64 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 set_and(doc& dst, doc const& src);
bool fold_neg(doc& dst);
bool intersect(doc const& A, doc const& B, doc& result) const;
void complement(doc const& src, ptr_vector<doc>& result);
void subtract(doc const& A, doc const& B, ptr_vector<doc>& 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;
std::ostream& display(std::ostream& out, doc const& b) const;
unsigned num_tbits() const { return m.num_tbits(); }
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);
};
// union of tbv*, union of doc*
template<typename M, typename T>
class union_bvec {
ptr_vector<T> 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_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 < m_elems.size(); ++i) {
if (m.contains(*m_elems[i], t)) return true;
}
return false;
}
std::ostream& display(M& m, std::ostream& out) const {
for (unsigned i = 0; i < size(); ++i) {
m.display(out, *m_elems[i]);
if (i + 1 < size()) out << ", ";
}
return out << "\n";
}
void push_back(T* t) {
m_elems.push_back(t);
}
void erase(M& m, unsigned idx) {
T* t = m_elems[idx];
m_elems.erase(t);
m.deallocate(t);
}
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) {
unsigned sz = size(), j = 0;
bool found = false;
for (unsigned i = 0; i < sz; ++i, ++j) {
if (!found && m.contains(*t, *m_elems[i])) {
m.deallocate(m_elems[i]);
--j;
}
else {
if (m.contains(*m_elems[i], *t)) {
found = true;
}
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& 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[i] = m_elems[j];
}
}
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) {
union_bvec result;
unsigned sz1 = size();
unsigned sz2 = other.size();
T* inter = m.allocate();
for (unsigned i = 0; i < sz1; ++i) {
for (unsigned j = 0; j < sz2; ++j) {
if (m.intersect(*m_elems[i], other[j], *inter)) {
result.push_back(inter);
inter = m.allocate();
}
}
}
m.deallocate(inter);
std::swap(result, *this);
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();
bool found = false;
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 merge(M& m, unsigned lo, unsigned length, subset_ints & equalities, bit_vector const& discard_cols) {
for (unsigned i = 0; i < size(); ++i) {
if (!m.merge(*m_elems[i], lo, length, equalities, discard_cols)) {
erase(m, i);
--i;
}
}
}
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);
}
private:
};
typedef union_bvec<tbv_manager, tbv> utbv;
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<doc_manager, doc> udoc;
class doc_ref {
doc_manager& dm;
doc* d;
public:
doc_ref(doc_manager& dm):dm(dm),d(0) {}
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 = 0; return r; }
};
#endif /* _DOC_H_ */

View file

@ -1,247 +0,0 @@
/*++
Copyright (c) 2014 Microsoft Corporation
Module Name:
tbv.cpp
Abstract:
ternary bit-vector utilities.
Author:
Nikolaj Bjorner (nbjorner) 2014-09-15
Revision History:
--*/
#include "tbv.h"
#include "hashtable.h"
//#define _DEBUG_MEM 1
#define _DEBUG_MEM 0
tbv_manager::~tbv_manager() {
#if _DEBUG_MEM
ptr_vector<tbv>::iterator it = allocated_tbvs.begin(), end = allocated_tbvs.end();
for (; it != end; ++it) {
std::cout << "dangling: " << (*it) << "\n";
}
#endif
}
void tbv_manager::reset() {
m.reset();
}
tbv* tbv_manager::allocate() {
tbv* r = reinterpret_cast<tbv*>(m.allocate());
#if _DEBUG_MEM
std::cout << allocated_tbvs.size() << " " << r << "\n";
allocated_tbvs.insert(r);
#endif
return r;
}
tbv* tbv_manager::allocate1() {
tbv* v = allocate();
fill1(*v);
return v;
}
tbv* tbv_manager::allocate0() {
tbv* v = allocate();
fill0(*v);
return v;
}
tbv* tbv_manager::allocateX() {
tbv* v = allocate();
fillX(*v);
return v;
}
tbv* tbv_manager::allocate(tbv const& bv) {
tbv* r = allocate();
copy(*r, bv);
return r;
}
tbv* tbv_manager::allocate(uint64 val) {
tbv* v = allocate0();
for (unsigned bit = num_tbits(); bit > 0;) {
--bit;
if (val & (1ULL << bit)) {
v->set(bit, BIT_1);
} else {
v->set(bit, BIT_0);
}
}
return v;
}
tbv* tbv_manager::allocate(uint64 val, unsigned hi, unsigned lo) {
tbv* v = allocateX();
SASSERT(64 >= num_tbits() && num_tbits() > hi && hi >= lo);
v->set(val, hi, lo);
return v;
}
tbv* tbv_manager::allocate(tbv const& bv, unsigned const* permutation) {
tbv* r = allocate();
for (unsigned i = 0; i < num_tbits(); ++i) {
r->set(permutation[i], bv[i]);
}
return r;
}
tbv* tbv_manager::project(unsigned n, bool const* to_delete, tbv const& src) {
tbv* r = allocate();
unsigned i, j;
for (i = 0, j = 0; i < n; ++i) {
if (!to_delete[i]) {
r->set(j, src[i]);
++j;
}
}
SASSERT(num_tbits() == j);
return r;
}
void tbv::set(uint64 val, unsigned hi, unsigned lo) {
for (unsigned i = 0; i < hi - lo + 1; ++i) {
set(lo + i, (val & (1ULL << i))?BIT_1:BIT_0);
}
}
void tbv::set(rational const& r, unsigned hi, unsigned lo) {
if (r.is_uint64()) {
set(r.get_uint64(), hi, lo);
return;
}
for (unsigned i = 0; i < hi - lo + 1; ++i) {
if (bitwise_and(r, rational::power_of_two(i)).is_zero())
set(lo + i, BIT_0);
else
set(lo + i, BIT_1);
}
}
void tbv::set(tbv const& other, unsigned hi, unsigned lo) {
for (unsigned i = 0; i < hi - lo + 1; ++i) {
set(lo + i, other[i]);
}
}
tbv* tbv_manager::allocate(rational const& r) {
if (r.is_uint64()) {
return allocate(r.get_uint64());
}
tbv* v = allocate0();
for (unsigned bit = num_tbits(); bit > 0; ) {
--bit;
if (bitwise_and(r, rational::power_of_two(bit)).is_zero()) {
v->set(bit, BIT_0);
} else {
v->set(bit, BIT_1);
}
}
return v;
}
void tbv_manager::deallocate(tbv* bv) {
#if _DEBUG_MEM
if (!allocated_tbvs.contains(bv)) {
std::cout << "double deallocate: " << bv << "\n";
UNREACHABLE();
}
std::cout << "deallocate: " << bv << "\n";
allocated_tbvs.erase(bv);
#endif
m.deallocate(bv);
}
void tbv_manager::copy(tbv& dst, tbv const& src) const {
m.copy(dst, src);
}
tbv& tbv_manager::fill0(tbv& bv) const {
// 10101010 = 2 + 8 + 32 + 128
memset(bv.m_data, 2 + 8 + 32 + 128, m.num_bytes());
return bv;
}
tbv& tbv_manager::fill1(tbv& bv) const {
// 01010101 = 1 + 4 + 16 + 64
memset(bv.m_data, 1 + 4 + 16 + 64, m.num_bytes());
return bv;
}
tbv& tbv_manager::fillX(tbv& bv) const {
m.fill1(bv);
return bv;
}
tbv& tbv_manager::set_or(tbv& dst, tbv const& src) const {
m.set_or(dst, src);
return dst;
}
bool tbv_manager::set_and(tbv& dst, tbv const& src) const {
m.set_and(dst, src);
return is_well_formed(dst);
}
bool tbv_manager::is_well_formed(tbv const& dst) const {
for (unsigned i = 0; i < num_tbits(); ++i) {
if (dst[i] == BIT_z) return false;
}
return true;
}
void tbv_manager::complement(tbv const& src, ptr_vector<tbv>& result) {
tbv* r;
unsigned n = num_tbits();
for (unsigned i = 0; i < n; ++i) {
switch (src.get(i)) {
case BIT_0:
r = allocate(src);
r->set(i, BIT_1);
result.push_back(r);
break;
case BIT_1:
r = allocate(src);
r->set(i, BIT_0);
result.push_back(r);
break;
default:
break;
}
}
}
bool tbv_manager::equals(tbv const& a, tbv const& b) const {
return m.equals(a, b);
}
unsigned tbv_manager::hash(tbv const& src) const {
return m.hash(src);
}
bool tbv_manager::contains(tbv const& a, tbv const& b) const {
return m.contains(a, b);
}
bool tbv_manager::intersect(tbv const& a, tbv const& b, tbv& result) {
copy(result, a);
return set_and(result, b);
}
std::ostream& tbv_manager::display(std::ostream& out, tbv const& b) const {
for (unsigned i = 0; i < num_tbits(); ++i) {
switch (b.get(i)) {
case BIT_0:
out << '0';
break;
case BIT_1:
out << '1';
break;
case BIT_x:
out << 'x';
break;
case BIT_z:
out << 'z';
break;
default:
UNREACHABLE();
}
}
return out;
}

View file

@ -1,140 +0,0 @@
/*++
Copyright (c) 2014 Microsoft Corporation
Module Name:
tbv.h
Abstract:
ternary bit-vector utilities.
Author:
Nikolaj Bjorner (nbjorner) 2014-09-15
Revision History:
--*/
#ifndef _TBV_H_
#define _TBV_H_
#include "fixed_bit_vector.h"
#include "rational.h"
class tbv;
enum tbit {
BIT_z = 0x0,
BIT_0 = 0x1,
BIT_1 = 0x2,
BIT_x = 0x3
};
inline tbit neg(tbit t) {
return (tbit)(t ^ 0x3);
}
class tbv_manager {
friend class tbv;
fixed_bit_vector_manager m;
ptr_vector<tbv> allocated_tbvs;
public:
tbv_manager(unsigned n): m(2*n) {}
~tbv_manager();
void reset();
tbv* allocate();
tbv* allocate1();
tbv* allocate0();
tbv* allocateX();
tbv* allocate(tbv const& bv);
tbv* allocate(uint64 n);
tbv* allocate(rational const& r);
tbv* allocate(uint64 n, unsigned hi, unsigned lo);
tbv* allocate(tbv const& bv, unsigned const* permutation);
void deallocate(tbv* bv);
void copy(tbv& dst, tbv const& src) const;
unsigned num_tbits() const { return m.num_bits()/2; }
tbv& reset(tbv& bv) const { return fill0(bv); }
tbv& fill0(tbv& bv) const;
tbv& fill1(tbv& bv) const;
tbv& fillX(tbv& bv) const;
bool set_and(tbv& dst, tbv const& src) const;
tbv& set_or(tbv& dst, tbv const& src) const;
void complement(tbv const& src, ptr_vector<tbv>& result);
bool equals(tbv const& a, tbv const& b) const;
unsigned hash(tbv const& src) const;
bool contains(tbv const& a, tbv const& b) const;
bool intersect(tbv const& a, tbv const& b, tbv& result);
std::ostream& display(std::ostream& out, tbv const& b) const;
tbv* project(unsigned n, bool const* to_delete, tbv const& src);
bool is_well_formed(tbv const& b) const; // - does not contain BIT_z;
};
class tbv: private fixed_bit_vector {
friend class fixed_bit_vector_manager;
friend class tbv_manager;
public:
struct eq {
tbv_manager& m;
eq(tbv_manager& m):m(m) {}
bool operator()(tbv const& d1, tbv const& d2) const {
return m.equals(d1, d2);
}
};
struct hash {
tbv_manager& m;
hash(tbv_manager& m):m(m) {}
unsigned operator()(tbv const& d) const {
return m.hash(d);
}
};
void set(uint64 n, unsigned hi, unsigned lo);
void set(rational const& r, unsigned hi, unsigned lo);
void set(tbv const& other, unsigned hi, unsigned lo);
tbit operator[](unsigned idx) const { return (tbit)get(idx); }
void set(unsigned index, tbit value) {
SASSERT(value <= 3);
fixed_bit_vector::set(2*index, (value & 2) != 0);
fixed_bit_vector::set(2*index+1, (value & 1) != 0);
}
private:
unsigned get(unsigned index) const {
index *= 2;
return (fixed_bit_vector::get(index) << 1) | (unsigned)fixed_bit_vector::get(index+1);
}
};
class tbv_ref {
tbv_manager& mgr;
tbv* d;
public:
tbv_ref(tbv_manager& mgr):mgr(mgr),d(0) {}
tbv_ref(tbv_manager& mgr, tbv* d):mgr(mgr),d(d) {}
~tbv_ref() {
if (d) mgr.deallocate(d);
}
tbv_ref& operator=(tbv* d2) {
if (d) mgr.deallocate(d);
d = d2;
return *this;
}
tbv& operator*() { return *d; }
tbv* get() { return d; }
tbv* detach() { tbv* result = d; d = 0; return result; }
};
#endif /* _TBV_H_ */

View file

@ -146,7 +146,7 @@ namespace datalog {
}
void udoc_relation::display(std::ostream& out) const {
m_elems.display(dm, out);
m_elems.display(dm, out << "{") << "}";
}
// -------------

View file

@ -1,135 +0,0 @@
/*++
Copyright (c) 2014 Microsoft Corporation
Module Name:
udoc_relation.h
Abstract:
Relation based on union of DOCs.
Author:
Nuno Lopes (a-nlopes) 2013-03-01
Nikolaj Bjorner (nbjorner) 2014-09-15
Revision History:
--*/
#ifndef _UDOC_RELATION_H_
#define _UDOC_RELATION_H_
#include "doc.h"
#include "dl_base.h"
namespace datalog {
class udoc_plugin;
class udoc_relation;
class udoc_relation : public relation_base {
friend class udoc_plugin;
doc_manager& dm;
udoc m_elems;
unsigned_vector m_column_info;
doc* fact2doc(relation_fact const& f) const;
expr_ref to_formula(tbv const& t) const;
expr_ref to_formula(doc const& d) const;
public:
udoc_relation(udoc_plugin& p, relation_signature const& s);
virtual ~udoc_relation();
virtual void reset();
virtual void add_fact(const relation_fact & f);
virtual bool contains_fact(const relation_fact & f) const;
virtual udoc_relation * clone() const;
virtual udoc_relation * complement(func_decl*) const;
virtual void to_formula(expr_ref& fml) const;
udoc_plugin& get_plugin() const;
virtual bool empty() const { return m_elems.is_empty(); }
virtual void display(std::ostream& out) const;
virtual bool is_precise() const { return true; }
virtual unsigned get_size_estimate_rows() const { return m_elems.size(); }
doc_manager& get_dm() const { return dm; }
udoc const& get_udoc() const { return m_elems; }
udoc& get_udoc() { return m_elems; }
unsigned get_num_records() const { return m_elems.size(); }
unsigned get_num_bits() const { return m_column_info.back(); }
unsigned get_num_cols() const { return m_column_info.size()-1; }
unsigned column_idx(unsigned col) const { return m_column_info[col]; }
unsigned column_num_bits(unsigned col) const { return m_column_info[col+1] - m_column_info[col]; }
void expand_column_vector(unsigned_vector& v, udoc_relation* other = 0) const;
void extract_guard(expr* condition, expr_ref& guard, expr_ref& rest) const;
bool is_guard(expr* g) const;
bool is_guard(unsigned n, expr* const *g) const;
void compile_guard(expr* g, udoc& result, bit_vector const& discard_cols) const;
void apply_guard(expr* g, udoc& result, bit_vector const& discard_cols) const;
void apply_guard(expr* g, udoc& result, subset_ints& equalities, bit_vector const& discard_cols) const;
bool apply_eq(expr* g, udoc& result, var* v, unsigned hi, unsigned lo, expr* c) const;
};
class udoc_plugin : public relation_plugin {
friend class udoc_relation;
class join_fn;
class project_fn;
class union_fn;
class rename_fn;
class filter_equal_fn;
class filter_identical_fn;
class filter_interpreted_fn;
class filter_by_negation_fn;
class filter_by_union_fn;
class filter_proj_fn;
class negation_filter_fn;
ast_manager& m;
bv_util bv;
dl_decl_util dl;
u_map<doc_manager*> m_dms;
doc_manager& dm(unsigned sz);
doc_manager& dm(relation_signature const& sig);
static udoc_relation& get(relation_base& r);
static udoc_relation* get(relation_base* r);
static udoc_relation const & get(relation_base const& r);
void mk_union(doc_manager& dm, udoc& dst, udoc const& src, udoc* delta);
bool is_numeral(expr* e, rational& r, unsigned& num_bits);
unsigned num_sort_bits(expr* e) const { return num_sort_bits(get_ast_manager().get_sort(e)); }
unsigned num_sort_bits(sort* s) const;
bool is_finite_sort(sort* s) const;
unsigned num_signature_bits(relation_signature const& sig);
expr* mk_numeral(rational const& r, sort* s);
public:
udoc_plugin(relation_manager& rm);
~udoc_plugin();
virtual bool can_handle_signature(const relation_signature & s);
static symbol get_name() { return symbol("doc"); }
virtual relation_base * mk_empty(const relation_signature & s);
virtual relation_base * mk_full(func_decl* p, const relation_signature & s);
virtual relation_join_fn * mk_join_fn(const relation_base & t1, const relation_base & t2,
unsigned col_cnt, const unsigned * cols1, const unsigned * cols2);
virtual relation_transformer_fn * mk_project_fn(const relation_base & t, unsigned col_cnt,
const unsigned * removed_cols);
virtual relation_transformer_fn * mk_rename_fn(const relation_base & t, unsigned permutation_cycle_len,
const unsigned * permutation_cycle);
virtual relation_union_fn * mk_union_fn(const relation_base & tgt, const relation_base & src,
const relation_base * delta);
virtual relation_union_fn * mk_widen_fn(const relation_base & tgt, const relation_base & src,
const relation_base * delta);
virtual relation_mutator_fn * mk_filter_identical_fn(const relation_base & t, unsigned col_cnt,
const unsigned * identical_cols);
virtual relation_mutator_fn * mk_filter_equal_fn(const relation_base & t, const relation_element & value,
unsigned col);
virtual relation_mutator_fn * mk_filter_interpreted_fn(const relation_base & t, app * condition);
virtual relation_intersection_filter_fn * udoc_plugin::mk_filter_by_negation_fn(
const relation_base& t,
const relation_base& neg, unsigned joined_col_cnt, const unsigned *t_cols,
const unsigned *negated_cols);
virtual relation_transformer_fn * mk_filter_interpreted_and_project_fn(
const relation_base & t, app * condition,
unsigned removed_col_cnt, const unsigned * removed_cols);
};
};
#endif /* _UDOC_RELATION_H_ */