Skip to content

Commit 9f378bb

Browse files
1 parent a884201 commit 9f378bb

File tree

3 files changed

+227
-6
lines changed

3 files changed

+227
-6
lines changed

src/smt/theory_array.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ namespace smt {
5353
var_data * d2 = m_var_data[v2];
5454
if (!d1->m_prop_upward && d2->m_prop_upward)
5555
set_prop_upward(v1);
56-
for (enode* n : d2->m_stores)
57-
add_store(v1, n);
58-
for (enode* n : d2->m_parent_stores)
59-
add_parent_store(v1, n);
60-
for (enode* n : d2->m_parent_selects)
61-
add_parent_select(v1, n);
56+
for (unsigned i = 0; i < d2->m_stores.size(); ++i)
57+
add_store(v1, d2->m_stores[i]);
58+
for (unsigned i = 0; i < d2->m_parent_stores.size(); ++i)
59+
add_parent_store(v1, d2->m_parent_stores[i]);
60+
for (unsigned i = 0; i < d2->m_parent_selects.size(); ++i)
61+
add_parent_select(v1, d2->m_parent_selects[i]);
6262
TRACE("array", tout << "after merge\n"; display_var(tout, v1););
6363
}
6464

src/smt/value_generator.cpp

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
#include "smt/value_generator.h"
2+
#include <math>
3+
4+
5+
class datatype_value_generator : public value_generator_core {
6+
ast_manager& m;
7+
value_generator& g;
8+
datatype_util dt;
9+
sort_ref_vector m_sorts;
10+
obj_map<sort, expr_ref_vector*> m_values;
11+
obj_map<func_decl, unsigned> m_constr2seen;
12+
13+
/*
14+
\brief inverse of the Cantor function.
15+
It converts an unsigned into a pair of unsigned numbers that are not
16+
bigger (and only equal for values 0, 1).
17+
*/
18+
void inverse_cantor(unsigned z, unsigned& x, unsigned& y) {
19+
unsigned w = (sqrt(8*z + 1) - 1)/2;
20+
unsigned t = (w*w + 2)/2;
21+
y = z - t;
22+
x = w - y;
23+
}
24+
25+
unsigned_vector inf;
26+
void index2vector(unsigned z, func_decl* c, unsigned_vector& v) {
27+
unsigned arity = c->get_arity();
28+
v.resize(arity);
29+
inf.reset();
30+
for (unsigned i = 0; i < arity; ++i) {
31+
sort* s = c->get_domain(i);
32+
sort_size const& sz = s->get_num_elements();
33+
if (sz.is_finite() && sz.size() < (UINT_MAX >> 12)) {
34+
v[i] = z % sz.size();
35+
z /= sz.size();
36+
}
37+
else {
38+
inf.push_back(i);
39+
}
40+
}
41+
// fill in values for large domains
42+
for (unsigned i = 0; i + 1 < inf.size(); ++i) {
43+
inverse_cantor(z, v[inf[i]], z);
44+
}
45+
if (!inf.empty()) {
46+
v[inf.back()] = z;
47+
}
48+
}
49+
50+
public:
51+
datatype_value_generator(value_generator& g, ast_manager& m):
52+
m(m), g(g), dt(m), m_values(m) {}
53+
54+
~datatype_value_generator() {
55+
for (auto& kv : m_values) dealloc(kv.m_value);
56+
}
57+
58+
family_id get_fid() const override {
59+
return dt.get_family_id();
60+
}
61+
62+
expr* get_value(sort* s, unsigned index) override {
63+
expr_ref_vector* vp = nullptr;
64+
if (!m_values.contains(s, vp)) {
65+
vp = allocate(expr_ref_vector, m);
66+
for (auto* c : *dt.get_datatype_constructors(s)) {
67+
if (c->get_arity() == 0)
68+
vp->push_back(m.mk_app(c));
69+
}
70+
m_values.insert(s, vp);
71+
}
72+
auto& v = *vp;
73+
expr_ref_vector args(m);
74+
bool some_valid = true;
75+
while (v.size() <= index && some_valid) {
76+
some_valid = false;
77+
for (auto* c : *dt.get_datatype_constructors(s)) {
78+
unsigned arity = c->get_arity();
79+
if (arity == 0)
80+
continue;
81+
args.resize(c->get_arity());
82+
unsigned j = 0;
83+
m_constr2seen.find(c, j);
84+
m_constr2seen.insert(c, j+1);
85+
if (beyond_domain_size(j, c))
86+
continue;
87+
index2vector(j, c, indices);
88+
bool valid = true;
89+
// still does not ensure non-termination when
90+
// 0 is used on a left-recursive datatype constructor
91+
for (unsigned i = 0; valid && i < args.size(); ++i) {
92+
args[i] = g.get_value(c->get_domain(i), indices[i]);
93+
valid &= args.get(i) != nullptr;
94+
}
95+
if (valid) {
96+
v.push_back(m.mk_app(c, args));
97+
some_valid = true;
98+
}
99+
}
100+
}
101+
return v.get(index, nullptr);
102+
}
103+
};
104+
105+
106+
class arith_value_generator : public value_generator_core {
107+
ast_manager& m;
108+
arith_util a;
109+
int u2i(unsigned u) {
110+
if (0 == (u % 2))
111+
return u/2;
112+
else
113+
return -((u+1)/2);
114+
}
115+
public:
116+
arith_value_generator(ast_manager& m): m(m), a(m) {}
117+
118+
family_id get_fid() const override {
119+
return a.get_family_id();
120+
}
121+
122+
expr* get_value(sort* s, unsigned index) override {
123+
if (a.is_int(s)) {
124+
return a.mk_int(u2i(index));
125+
}
126+
if (index == 0)
127+
return a.mk_real(rational(0));
128+
unsigned x, y;
129+
// still imperfect as y could divide x
130+
inverse_cantor(index/2, x, y);
131+
x++;
132+
y++;
133+
if (index % 2 == 0) x = -x;
134+
return a.mk_real(rational(x, y));
135+
}
136+
};
137+
138+
class bv_value_generator : public value_generator_core {
139+
ast_manager& m;
140+
bv_util bv;
141+
public:
142+
bv_value_generator(ast_manager& m): m(m), bv(m) {}
143+
144+
family_id get_fid() const override {
145+
return bv.get_family_id();
146+
}
147+
148+
expr* get_value(sort* s, unsigned index) override {
149+
unsigned sz = 0;
150+
bv.get_bv_size(s, sz);
151+
if (sz < 30 && index >= (1 << sz))
152+
return nullptr;
153+
return bv.mk_numeral(index, s);
154+
}
155+
};
156+
157+
class bool_value_generator : public value_generator_core {
158+
ast_manager& m;
159+
public:
160+
bool_value_generator(ast_manager& m): m(m) {}
161+
162+
family_id get_fid() const override {
163+
return m.get_family_id();
164+
}
165+
166+
expr* get_value(sort* s, unsigned index) override {
167+
if (!m.is_bool(s))
168+
return nullptr;
169+
if (index == 0)
170+
return m.mk_false();
171+
if (index == 1)
172+
return m.mk_true();
173+
return nullptr;
174+
}
175+
};
176+
177+
178+
value_generator::value_generator(ast_manager& m): m(m) {
179+
}
180+
181+
void value_generator::init() {
182+
if (!m_plugins.empty())
183+
return;
184+
add_plugin(alloc(datatype_value_generator, *this, m));
185+
add_plugin(alloc(arith_value_generator, m));
186+
add_plugin(alloc(bv_value_generator, m));
187+
add_plugin(alloc(bool_value_generator, m));
188+
// seq_value_generator
189+
// fp_value_generator
190+
// array_value_generator
191+
// uninterp_sort_value_generator
192+
}
193+
194+
void value_generator::add_plugin(value_generator_core* v) {
195+
m_plugins.reserve(v->get_fid() + 1);
196+
m_plugins.set(v->get_fid(), v);
197+
}
198+
199+
expr* value_generator::get_value(sort* s, unsigned index) {
200+
init();
201+
famiily_id fid = s->get_family_id();
202+
auto* p = m_plugins.get(fid, nullptr);
203+
return p ? p->get_value(s, index) : nullptr;
204+
}

src/smt/value_generator.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
3+
namespace smt {
4+
5+
class value_generator_core {
6+
public:
7+
virtual expr* get_value(sort* s, unsigned index) = 0;
8+
};
9+
10+
class value_generator {
11+
scoped_ptr_vector<value_generator_core> m_plugins;
12+
public:
13+
value_generator(ast_manager& m);
14+
expr* get_value(sort* s, unsigned index);
15+
16+
};
17+
}

0 commit comments

Comments
 (0)