Skip to content

Commit 228d68f

Browse files
enhance ackermannize for constant arguments
Signed-off-by: Nikolaj Bjorner <[email protected]>
1 parent 18ba14c commit 228d68f

File tree

7 files changed

+86
-59
lines changed

7 files changed

+86
-59
lines changed

src/ackermannization/ackermannize_bv_tactic.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ class ackermannize_bv_tactic : public tactic {
2525
public:
2626
ackermannize_bv_tactic(ast_manager& m, params_ref const& p)
2727
: m(m), m_p(p)
28-
{}
28+
{
29+
updt_params(p);
30+
}
2931

3032
~ackermannize_bv_tactic() override { }
3133

src/ackermannization/ackr_bound_probe.cpp

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,29 +53,9 @@ class ackr_bound_probe : public probe {
5353

5454
void operator()(quantifier *) {}
5555
void operator()(var *) {}
56-
void operator()(app * a) {
57-
if (a->get_num_args() == 0) return;
56+
void operator()(app * a) {
5857
m_ackr_helper.mark_non_select(a, m_non_select);
59-
app_set* ts = nullptr;
60-
if (m_ackr_helper.is_select(a)) {
61-
app* sel = to_app(a->get_arg(0));
62-
if (!m_sel2terms.find(sel, ts)) {
63-
ts = alloc(app_set);
64-
m_sel2terms.insert(sel, ts);
65-
}
66-
}
67-
else if (m_ackr_helper.is_uninterp_fn(a)) {
68-
func_decl* const fd = a->get_decl();
69-
if (!m_fun2terms.find(fd, ts)) {
70-
ts = alloc(app_set);
71-
m_fun2terms.insert(fd, ts);
72-
}
73-
}
74-
else {
75-
return;
76-
}
77-
78-
ts->insert(a);
58+
m_ackr_helper.insert(m_fun2terms, m_sel2terms, a);
7959
}
8060
};
8161

src/ackermannization/ackr_helper.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919
double ackr_helper::calculate_lemma_bound(fun2terms_map const& occs1, sel2terms_map const& occs2) {
2020
double total = 0;
2121
for (auto const& kv : occs1) {
22-
total += n_choose_2_chk(kv.m_value->size());
22+
total += n_choose_2_chk(kv.m_value->var_args.size());
23+
total += kv.m_value->const_args.size() * kv.m_value->var_args.size();
2324
}
2425
for (auto const& kv : occs2) {
25-
total += n_choose_2_chk(kv.m_value->size());
26+
total += n_choose_2_chk(kv.m_value->var_args.size());
27+
total += kv.m_value->const_args.size() * kv.m_value->var_args.size();
2628
}
2729
return total;
2830
}

src/ackermannization/ackr_helper.h

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@
2222

2323
class ackr_helper {
2424
public:
25-
typedef obj_hashtable<app> app_set;
25+
struct app_occ {
26+
obj_hashtable<app> const_args;
27+
obj_hashtable<app> var_args;
28+
};
29+
typedef app_occ app_set;
2630
typedef obj_map<func_decl, app_set*> fun2terms_map;
27-
typedef obj_map<app, app_set*> sel2terms_map;
31+
typedef obj_map<app, app_set*> sel2terms_map;
2832

2933
ackr_helper(ast_manager& m) : m_bvutil(m), m_autil(m) {}
3034

@@ -88,13 +92,48 @@ class ackr_helper {
8892
static double calculate_lemma_bound(fun2terms_map const& occs1, sel2terms_map const& occs2);
8993

9094
/** \brief Calculate n choose 2. **/
91-
inline static unsigned n_choose_2(unsigned n) { return n & 1 ? (n * (n >> 1)) : (n >> 1) * (n - 1); }
95+
inline static unsigned n_choose_2(unsigned n) { return (n & 1) ? (n * (n >> 1)) : (n >> 1) * (n - 1); }
9296

9397
/** \brief Calculate n choose 2 guarded for overflow. Returns infinity if unsafe. **/
9498
inline static double n_choose_2_chk(unsigned n) {
9599
SASSERT(std::numeric_limits<unsigned>().max() & 32);
96100
return n & (1 << 16) ? std::numeric_limits<double>().infinity() : n_choose_2(n);
97101
}
102+
103+
void insert(fun2terms_map& f2t, sel2terms_map& s2t, app* a) {
104+
if (a->get_num_args() == 0) return;
105+
ast_manager& m = m_bvutil.get_manager();
106+
app_set* ts = nullptr;
107+
bool is_const_args = true;
108+
if (is_select(a)) {
109+
app* sel = to_app(a->get_arg(0));
110+
if (!s2t.find(sel, ts)) {
111+
ts = alloc(app_set);
112+
s2t.insert(sel, ts);
113+
}
114+
}
115+
else if (is_uninterp_fn(a)) {
116+
func_decl* const fd = a->get_decl();
117+
if (!f2t.find(fd, ts)) {
118+
ts = alloc(app_set);
119+
f2t.insert(fd, ts);
120+
}
121+
is_const_args = m.is_value(a->get_arg(0));
122+
}
123+
else {
124+
return;
125+
}
126+
for (unsigned i = 1; is_const_args && i < a->get_num_args(); ++i) {
127+
is_const_args &= m.is_value(a->get_arg(i));
128+
}
129+
130+
if (is_const_args) {
131+
ts->const_args.insert(a);
132+
}
133+
else {
134+
ts->var_args.insert(a);
135+
}
136+
}
98137

99138
private:
100139
bv_util m_bvutil;

src/ackermannization/lackr.cpp

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -153,38 +153,57 @@ void lackr::eager_enc() {
153153
}
154154

155155
void lackr::ackr(app_set const* ts) {
156-
const app_set::iterator r = ts->end();
157-
for (app_set::iterator j = ts->begin(); j != r; ++j) {
156+
auto r = ts->var_args.end();
157+
for (auto j = ts->var_args.begin(); j != r; ++j) {
158158
app * const t1 = *j;
159-
app_set::iterator k = j;
159+
auto k = j;
160160
++k;
161161
for (; k != r; ++k) {
162162
app * const t2 = *k;
163163
if (t1 != t2) {
164164
ackr(t1, t2);
165165
}
166166
}
167+
for (app* t2 : ts->const_args) {
168+
ackr(t1, t2);
169+
}
167170
}
168171
}
169172

170-
171-
void lackr::abstract() {
172-
for (auto const& kv : m_fun2terms) {
173+
void lackr::abstract_fun(fun2terms_map const& apps) {
174+
for (auto const& kv : apps) {
173175
func_decl* fd = kv.m_key;
174-
for (app * t : *kv.m_value) {
176+
for (app * t : kv.m_value->var_args) {
177+
app * fc = m.mk_fresh_const(fd->get_name(), m.get_sort(t));
178+
SASSERT(t->get_decl() == fd);
179+
m_info->set_abstr(t, fc);
180+
}
181+
for (app * t : kv.m_value->const_args) {
175182
app * fc = m.mk_fresh_const(fd->get_name(), m.get_sort(t));
176183
SASSERT(t->get_decl() == fd);
177184
m_info->set_abstr(t, fc);
178185
}
179186
}
180187

181-
for (auto& kv : m_sel2terms) {
188+
}
189+
190+
void lackr::abstract_sel(sel2terms_map const& apps) {
191+
for (auto const& kv : apps) {
182192
func_decl * fd = kv.m_key->get_decl();
183-
for (app * t : *kv.m_value) {
193+
for (app * t : kv.m_value->const_args) {
194+
app * fc = m.mk_fresh_const(fd->get_name(), m.get_sort(t));
195+
m_info->set_abstr(t, fc);
196+
}
197+
for (app * t : kv.m_value->var_args) {
184198
app * fc = m.mk_fresh_const(fd->get_name(), m.get_sort(t));
185199
m_info->set_abstr(t, fc);
186200
}
187201
}
202+
}
203+
204+
void lackr::abstract() {
205+
abstract_fun(m_fun2terms);
206+
abstract_sel(m_sel2terms);
188207
m_info->seal();
189208
// perform abstraction of the formulas
190209
for (expr * f : m_formulas) {
@@ -194,28 +213,7 @@ void lackr::abstract() {
194213
}
195214

196215
void lackr::add_term(app* a) {
197-
app_set* ts = nullptr;
198-
if (a->get_num_args() == 0)
199-
return;
200-
if (m_ackr_helper.is_select(a)) {
201-
app* sel = to_app(a->get_arg(0));
202-
if (!m_sel2terms.find(sel, ts)) {
203-
ts = alloc(app_set);
204-
m_sel2terms.insert(sel, ts);
205-
}
206-
}
207-
else if (m_ackr_helper.is_uninterp_fn(a)) {
208-
func_decl* const fd = a->get_decl();
209-
if (!m_fun2terms.find(fd, ts)) {
210-
ts = alloc(app_set);
211-
m_fun2terms.insert(fd, ts);
212-
}
213-
}
214-
else {
215-
return;
216-
}
217-
TRACE("ackermannize", tout << "term(" << mk_ismt2_pp(a, m, 2) << ")\n";);
218-
ts->insert(a);
216+
m_ackr_helper.insert(m_fun2terms, m_sel2terms, a);
219217
}
220218

221219
void lackr::push_abstraction() {

src/ackermannization/lackr.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,9 @@ class lackr {
123123
// Collect all uninterpreted terms, skipping 0-arity.
124124
//
125125
bool collect_terms();
126+
127+
void abstract_sel(sel2terms_map const& apps);
128+
void abstract_fun(fun2terms_map const& apps);
129+
126130
};
127131
#endif /* LACKR_H_ */

src/opt/opt_context.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Module Name:
3838
#include "tactic/arith/eq2bv_tactic.h"
3939
#include "tactic/bv/dt2bv_tactic.h"
4040
#include "tactic/generic_model_converter.h"
41+
#include "ackermannization/ackermannize_bv_tactic.h"
4142
#include "sat/sat_solver/inc_sat_solver.h"
4243
#include "qe/qsat.h"
4344
#include "opt/opt_context.h"
@@ -804,6 +805,7 @@ namespace opt {
804805
and_then(mk_simplify_tactic(m, m_params),
805806
mk_propagate_values_tactic(m),
806807
mk_solve_eqs_tactic(m),
808+
mk_ackermannize_bv_tactic(m, m_params),
807809
// NB: mk_elim_uncstr_tactic(m) is not sound with soft constraints
808810
mk_simplify_tactic(m));
809811
opt_params optp(m_params);

0 commit comments

Comments
 (0)