3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 16:45:31 +00:00

more ddnf

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2014-08-21 21:57:44 -07:00
parent b596828d23
commit 34aa06b5a3
3 changed files with 199 additions and 135 deletions

View file

@ -93,6 +93,10 @@ namespace datalog {
return bit_vector::operator==(other);
}
unsigned get_hash() const {
return bit_vector::get_hash();
}
void resize(unsigned n, unsigned val) {
while (size() < n) {
bit_vector::push_back((val & 2) != 0);
@ -100,8 +104,6 @@ namespace datalog {
}
}
bool empty() const { return false; } // TBD
bool is_subset(tbv const& other) const {
SASSERT(size() == other.size());
return other.contains(*this);
@ -134,6 +136,8 @@ namespace datalog {
}
}
}
friend bool intersect(tbv const& a, tbv const& b, tbv& result);
private:
void set(unsigned index, unsigned value) {
@ -146,16 +150,29 @@ namespace datalog {
index *= 2;
return (bit_vector::get(index) << 1) | (unsigned)bit_vector::get(index+1);
}
};
bool intersect(tbv const& a, tbv const& b, tbv& result) {
result = a;
result &= b;
for (unsigned i = 0; i < result.size(); ++i) {
if (result.get(i) == BIT_z) return false;
}
return true;
}
class dot {
tbv m_pos;
vector<tbv> m_negs;
public:
dot() {}
dot(tbv const& pos, vector<tbv> const& negs):
m_pos(pos), m_negs(negs) {}
tbv const& pos() const { return m_pos; }
tbv neg(unsigned i) const { return m_negs[i]; }
unsigned size() const { return m_negs.size(); }
bool operator==(dot const& other) const {
if (m_pos != other.m_pos) return false;
if (m_negs.size() != other.m_negs.size()) return false;
@ -164,6 +181,7 @@ namespace datalog {
}
return true;
}
void display(std::ostream& out) {
out << "<";
m_pos.display(out);
@ -174,6 +192,28 @@ namespace datalog {
}
out << ">";
}
struct eq {
bool operator()(dot const& d1, dot const& d2) const {
if (d1.pos() != d2.pos()) return false;
if (d1.size() != d2.size()) return false;
for (unsigned i = 0; i < d1.size(); ++i) {
if (d1.neg(i) != d2.neg(i)) return false;
}
return true;
}
};
struct hash {
unsigned operator()(dot const& d) const {
unsigned h = d.pos().get_hash();
for (unsigned i = 0; i < d.size(); ++i) {
h ^= d.neg(i).get_hash();
}
return h;
}
};
};
class ddnf_mgr;
@ -186,28 +226,53 @@ namespace datalog {
vector<dot> m_pos;
vector<dot> m_neg;
unsigned m_refs;
unsigned m_id;
friend class ddnf_mgr;
public:
ddnf_node(ddnf_mgr& m, tbv const& tbv):
ddnf_node(ddnf_mgr& m, tbv const& tbv, unsigned id):
m_tbv(tbv),
m_children(m),
m_refs(0) {
m_refs(0),
m_id(id) {
}
~ddnf_node() {}
unsigned inc_ref() {
return ++m_refs;
}
unsigned dec_ref() {
void dec_ref() {
SASSERT(m_refs > 0);
return --m_refs;
--m_refs;
if (m_refs == 0) {
dealloc(this);
}
}
struct eq {
bool operator()(ddnf_node* n1, ddnf_node* n2) const {
return n1->get_tbv() == n2->get_tbv();
}
};
struct hash {
unsigned operator()(ddnf_node* n) const {
return n->get_tbv().get_hash();
}
};
unsigned get_id() const { return m_id; }
unsigned num_children() const { return m_children.size(); }
ddnf_node* operator[](unsigned index) { return m_children[index].get(); }
tbv const& get_tbv() const { return m_tbv; }
vector<dot> const& pos() const { return m_pos; }
vector<dot> const& neg() const { return m_neg; }
void add_child(ddnf_node* n);
@ -215,17 +280,40 @@ namespace datalog {
bool contains_child(ddnf_node* n) const;
ddnf_node* add_pos(dot const& d) { m_pos.push_back(d); return this; }
ddnf_node* add_neg(dot const& d) { m_neg.push_back(d); return this; }
void display(std::ostream& out) const {
out << "node[";
m_tbv.display(out);
for (unsigned i = 0; i < m_children.size(); ++i) {
out << " " << m_children[i]->get_id();
}
out << "]";
}
};
class ddnf_mgr {
typedef ptr_hashtable<ddnf_node, ddnf_node::hash, ddnf_node::eq> ddnf_nodes;
class ddnf_mgr {
unsigned m_num_bits;
ddnf_node* m_root;
ddnf_node_vector m_nodes;
vector<dot> m_dots;
ddnf_node_vector m_noderefs;
ddnf_nodes m_nodes;
ptr_vector<ddnf_nodes> m_tables;
map<dot, ddnf_nodes*, dot::hash, dot::eq> m_dots;
bool m_internalized;
public:
ddnf_mgr(unsigned n): m_num_bits(n), m_nodes(*this) {
m_root = alloc(ddnf_node, *this, tbv(n, BIT_x));
m_nodes.push_back(m_root);
ddnf_mgr(unsigned n): m_num_bits(n), m_noderefs(*this), m_internalized(false) {
m_root = alloc(ddnf_node, *this, tbv(n, BIT_x), m_nodes.size());
m_noderefs.push_back(m_root);
m_nodes.insert(m_root);
}
~ddnf_mgr() {
m_noderefs.reset();
std::for_each(m_tables.begin(), m_tables.end(), delete_proc<ddnf_nodes>());
}
void inc_ref(ddnf_node* n) {
@ -233,38 +321,84 @@ namespace datalog {
}
void dec_ref(ddnf_node* n) {
unsigned count = n->dec_ref();
NOT_IMPLEMENTED_YET();
n->dec_ref();
}
void insert(dot const& d) {
SASSERT(!m_internalized);
if (m_dots.contains(d)) return;
ddnf_nodes* ns = alloc(ddnf_nodes);
m_tables.push_back(ns);
m_dots.insert(d, ns);
insert(d.pos())->add_pos(d);
for (unsigned i = 0; i < d.size(); ++i) {
insert(d.neg(i))->add_neg(d);
}
}
void display(std::ostream& out) const {
for (unsigned i = 0; i < m_noderefs.size(); ++i) {
m_noderefs[i]->display(out);
out << "\n";
}
}
private:
void insert_new(ddnf_node& root, ddnf_node* new_n,
ptr_vector<tbv>& new_intersections) {
SASSERT(root.get_tbv().is_superset(new_n->get_tbv()));
// if (root == *new_n) return;
ddnf_node* insert(tbv const& t) {
vector<tbv> new_tbvs;
new_tbvs.push_back(t);
for (unsigned i = 0; i < new_tbvs.size(); ++i) {
tbv const& nt = new_tbvs[i];
if (contains(nt)) continue;
ddnf_node* n = alloc(ddnf_node, *this, nt, m_noderefs.size());
m_noderefs.push_back(n);
m_nodes.insert(n);
insert(*m_root, n, new_tbvs);
}
return find(t);
}
ddnf_node* find(tbv const& t) {
ddnf_node dummy(*this, t, 0);
return *(m_nodes.find(&dummy));
}
bool contains(tbv const& t) {
ddnf_node dummy(*this, t, 0);
return m_nodes.contains(&dummy);
}
void insert(ddnf_node& root, ddnf_node* new_n, vector<tbv>& new_intersections) {
tbv const& new_tbv = new_n->get_tbv();
SASSERT(new_tbv.is_subset(root.get_tbv()));
if (&root == new_n) return;
bool inserted = false;
for (unsigned i = 0; i < root.num_children(); ++i) {
ddnf_node& child = *(root[i]);
if (child.get_tbv().is_superset(new_n->get_tbv())) {
if (child.get_tbv().is_superset(new_tbv)) {
inserted = true;
insert_new(child, new_n, new_intersections);
insert(child, new_n, new_intersections);
}
}
if (inserted) return;
if (inserted) {
return;
}
ddnf_node_vector subset_children(*this);
tbv intr;
for (unsigned i = 0; i < root.num_children(); ++i) {
ddnf_node& child = *(root[i]);
// cannot be superset
SASSERT(!child.get_tbv().is_superset(new_tbv));
// checking for subset
if (child.get_tbv().is_subset(new_n->get_tbv())) {
if (child.get_tbv().is_subset(new_tbv)) {
subset_children.push_back(&child);
}
// this means there is a non-full intersection
else {
tbv intr;
// TBD intersect(child.get_tbv(), new_n->get_tbv(), intr);
if (!intr.empty()) {
// TBD new_intersections.push_back(intr);
if (intersect(child.get_tbv(), new_tbv, intr)) {
new_intersections.push_back(intr);
}
}
}
@ -275,125 +409,49 @@ namespace datalog {
root.add_child(new_n);
}
#if 0
DDNFNode InsertTBV(TernaryBitVector aTbv)
{
foreach (DDNFNode node in allNodes)
{
if (node.tbv.IsEqualset(aTbv))
{
return node;
}
}
DDNFNode newNode = new DDNFNode(aTbv);
this.allNodes.Add(newNode);
List<TernaryBitVector> newIntersections = new List<TernaryBitVector>();
InsertNewNode(this.root, newNode, newIntersections);
// add the TBVs corresponding to new intersections
foreach (TernaryBitVector newIntr in newIntersections)
{
// this assert guarantees termination since you can only
// insert smaller tbvs recursively
Debug.Assert(!newIntr.IsSupset(aTbv));
InsertTBV(newIntr);
}
return newNode;
}
public void InsertDot(DOT aDot)
{
this.allDots.Add(aDot);
DDNFNode posNode = InsertTBV(aDot.pos);
List<DDNFNode> negNodes = new List<DDNFNode>();
foreach (TernaryBitVector neg in aDot.negs)
{
negNodes.Add(InsertTBV(neg));
}
posNode.posDots.Add(aDot);
foreach (DDNFNode negNode in negNodes)
{
negNode.negDots.Add(aDot);
void internalize() {
// create map: dot |-> ddnf_node set
if (!m_internalized) {
vector<dot> dots1, dots2;
add_pos(*m_root, dots1);
del_neg(*m_root, dots2);
m_internalized = true;
}
}
// remove all negNodes for each dot in dot2Nodes
void RemoveNegNodesForAllDots(DDNFNode aNode, HashSet<DOT> activeDots,
ref Dictionary<DOT, HashSet<DDNFNode>> dot2Nodes)
{
foreach (DOT negDot in aNode.negDots)
{
activeDots.Add(negDot);
}
foreach (DOT activeDot in activeDots)
{
dot2Nodes[activeDot].Remove(aNode);
}
foreach (DDNFNode child in aNode.children)
{
RemoveNegNodesForAllDots(child, new HashSet<DOT>(activeDots), ref dot2Nodes);
}
ddnf_nodes const& lookup(dot const& d) const {
return *m_dots.find(d);
}
// add all posNodes for each dot in dot2Nodes
void AddPosNodesForAllDots(DDNFNode aNode, HashSet<DOT> activeDots,
ref Dictionary<DOT, HashSet<DDNFNode>> dot2Nodes)
{
foreach (DOT posDot in aNode.posDots)
{
activeDots.Add(posDot);
void add_pos(ddnf_node& n, vector<dot>& active) {
for (unsigned i = 0; i < n.pos().size(); ++i) {
active.push_back(n.pos()[i]);
// TBD: Garvit; prove (or disprove): there are no repetitions.
// the argument may be that the sub-expressions are
// traversed in DFS order, and that repeated dots
// cannot occur below each-other.
}
foreach (DOT activeDot in activeDots)
{
dot2Nodes[activeDot].Add(aNode);
}
foreach (DDNFNode child in aNode.children)
{
AddPosNodesForAllDots(child, new HashSet<DOT>(activeDots), ref dot2Nodes);
for (unsigned i = 0; i < active.size(); ++i) {
m_dots.find(active[i])->insert(&n);
}
for (unsigned i = 0; i < n.num_children(); ++i) {
vector<dot> active1(active);
add_pos(*n[i], active1);
}
}
public Dictionary<DOT, HashSet<DDNFNode>> NodesForAllDots()
{
Dictionary<DOT, HashSet<DDNFNode>> dot2Nodes =
new Dictionary<DOT, HashSet<DDNFNode>>();
foreach (DOT dot in allDots)
{
dot2Nodes[dot] = new HashSet<DDNFNode>();
void del_neg(ddnf_node& n, vector<dot>& active) {
for (unsigned i = 0; i < n.neg().size(); ++i) {
active.push_back(n.neg()[i]);
}
AddPosNodesForAllDots(this.root, new HashSet<DOT>(), ref dot2Nodes);
RemoveNegNodesForAllDots(this.root, new HashSet<DOT>(), ref dot2Nodes);
return dot2Nodes;
}
public string PrintNodes()
{
StringBuilder retVal = new StringBuilder();
retVal.Append("<DDNF: ");
foreach (DDNFNode node in allNodes)
{
retVal.Append("\n").Append(node.ToString());
for (unsigned i = 0; i < active.size(); ++i) {
m_dots.find(active[i])->remove(&n);
}
return retVal.Append(">").ToString();
}
}
}
#endif
for (unsigned i = 0; i < n.num_children(); ++i) {
vector<dot> active1(active);
del_neg(*n[i], active1);
}
}
};

View file

@ -224,6 +224,10 @@ bool bit_vector::contains(bit_vector const& other) const {
return (m_data[n-1] & other_data) == other_data;
}
unsigned bit_vector::get_hash() const {
return string_hash(reinterpret_cast<char const* const>(m_data), size()/8, 0);
}
void fr_bit_vector::reset() {
unsigned sz = size();
unsigned_vector::const_iterator it = m_one_idxs.begin();

View file

@ -125,6 +125,8 @@ public:
unsigned get_word(unsigned word_idx) const {
return m_data[word_idx];
}
unsigned get_hash() const;
bool get(unsigned bit_idx) const {
SASSERT(bit_idx < size());