Skip to content

Commit 6cf7d8e

Browse files
adding div0
Signed-off-by: Nikolaj Bjorner <[email protected]>
1 parent 1048abf commit 6cf7d8e

File tree

6 files changed

+86
-14
lines changed

6 files changed

+86
-14
lines changed

src/ast/arith_decl_plugin.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,11 @@ inline func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, bool is_real) {
362362
case OP_IDIVIDES: UNREACHABLE();
363363
case OP_REM: return m_i_rem_decl;
364364
case OP_MOD: return m_i_mod_decl;
365+
case OP_DIV0: return m_manager->mk_func_decl(symbol("div0"), m_real_decl, m_real_decl, m_real_decl, func_decl_info(m_family_id, OP_DIV0));
366+
case OP_IDIV0: return m_manager->mk_func_decl(symbol("idiv0"), m_real_decl, m_real_decl, m_real_decl, func_decl_info(m_family_id, OP_IDIV0));
367+
case OP_REM0: return m_manager->mk_func_decl(symbol("rem0"), m_real_decl, m_real_decl, m_real_decl, func_decl_info(m_family_id, OP_REM0));
368+
case OP_MOD0: return m_manager->mk_func_decl(symbol("mod0"), m_real_decl, m_real_decl, m_real_decl, func_decl_info(m_family_id, OP_MOD0));
369+
case OP_POWER0: return m_manager->mk_func_decl(symbol("power0"), m_real_decl, m_real_decl, m_real_decl, func_decl_info(m_family_id, OP_POWER0));
365370
case OP_TO_REAL: return m_to_real_decl;
366371
case OP_TO_INT: return m_to_int_decl;
367372
case OP_IS_INT: return m_is_int_decl;
@@ -780,18 +785,31 @@ expr_ref arith_util::mk_add_simplify(unsigned sz, expr* const* args) {
780785
return result;
781786
}
782787

783-
bool arith_util::is_considered_uninterpreted(func_decl* f, unsigned n, expr* const* args) {
788+
bool arith_util::is_considered_uninterpreted(func_decl* f, unsigned n, expr* const* args, func_decl_ref& f_out) {
784789
rational r;
785790
if (is_decl_of(f, m_afid, OP_DIV) && is_numeral(args[1], r) && r.is_zero()) {
791+
sort* rs[2] = { mk_real(), mk_real() };
792+
f_out = m_manager.mk_func_decl(m_afid, OP_DIV0, 0, nullptr, 2, rs, mk_real());
786793
return true;
787794
}
788795
if (is_decl_of(f, m_afid, OP_IDIV) && is_numeral(args[1], r) && r.is_zero()) {
796+
sort* rs[2] = { mk_real(), mk_real() };
797+
f_out = m_manager.mk_func_decl(m_afid, OP_IDIV0, 0, nullptr, 2, rs, mk_real());
789798
return true;
790799
}
791800
if (is_decl_of(f, m_afid, OP_MOD) && is_numeral(args[1], r) && r.is_zero()) {
801+
sort* rs[2] = { mk_real(), mk_real() };
802+
f_out = m_manager.mk_func_decl(m_afid, OP_MOD0, 0, nullptr, 2, rs, mk_real());
792803
return true;
793804
}
794805
if (is_decl_of(f, m_afid, OP_REM) && is_numeral(args[1], r) && r.is_zero()) {
806+
sort* rs[2] = { mk_real(), mk_real() };
807+
f_out = m_manager.mk_func_decl(m_afid, OP_REM0, 0, nullptr, 2, rs, mk_real());
808+
return true;
809+
}
810+
if (is_decl_of(f, m_afid, OP_POWER) && is_numeral(args[1], r) && r.is_zero() && is_numeral(args[0], r) && r.is_zero()) {
811+
sort* rs[2] = { mk_real(), mk_real() };
812+
f_out = m_manager.mk_func_decl(m_afid, OP_POWER0, 0, nullptr, 2, rs, mk_real());
795813
return true;
796814
}
797815
return plugin().is_considered_uninterpreted(f);

src/ast/arith_decl_plugin.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,19 @@ enum arith_op_kind {
4646
OP_MUL,
4747
OP_DIV,
4848
OP_IDIV,
49+
OP_DIV0,
50+
OP_IDIV0,
4951
OP_IDIVIDES,
5052
OP_REM,
5153
OP_MOD,
54+
OP_REM0,
55+
OP_MOD0,
5256
OP_TO_REAL,
5357
OP_TO_INT,
5458
OP_IS_INT,
5559
OP_ABS,
5660
OP_POWER,
61+
OP_POWER0,
5762
// hyperbolic and trigonometric functions
5863
OP_SIN,
5964
OP_COS,
@@ -260,14 +265,21 @@ class arith_recognizers {
260265
bool is_ge(func_decl const * n) const { return is_decl_of(n, m_afid, OP_GE); }
261266
bool is_lt(func_decl const * n) const { return is_decl_of(n, m_afid, OP_LT); }
262267
bool is_gt(func_decl const * n) const { return is_decl_of(n, m_afid, OP_GT); }
268+
269+
bool is_div0(func_decl const * n) const { return is_decl_of(n, m_afid, OP_DIV0); }
270+
bool is_idiv0(func_decl const * n) const { return is_decl_of(n, m_afid, OP_IDIV0); }
271+
bool is_rem0(func_decl const * n) const { return is_decl_of(n, m_afid, OP_REM0); }
272+
bool is_mod0(func_decl const * n) const { return is_decl_of(n, m_afid, OP_MOD0); }
273+
bool is_power0(func_decl const * n) const { return is_decl_of(n, m_afid, OP_POWER0); }
274+
263275
bool is_add(expr const * n) const { return is_app_of(n, m_afid, OP_ADD); }
264276
bool is_sub(expr const * n) const { return is_app_of(n, m_afid, OP_SUB); }
265277
bool is_uminus(expr const * n) const { return is_app_of(n, m_afid, OP_UMINUS); }
266278
bool is_mul(expr const * n) const { return is_app_of(n, m_afid, OP_MUL); }
267279
bool is_div(expr const * n) const { return is_app_of(n, m_afid, OP_DIV); }
268-
//bool is_div0(expr const * n) const { return is_app_of(n, m_afid, OP_DIV_0); }
280+
bool is_div0(expr const * n) const { return is_app_of(n, m_afid, OP_DIV0); }
269281
bool is_idiv(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV); }
270-
//bool is_idiv0(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV_0); }
282+
bool is_idiv0(expr const * n) const { return is_app_of(n, m_afid, OP_IDIV0); }
271283
bool is_mod(expr const * n) const { return is_app_of(n, m_afid, OP_MOD); }
272284
bool is_rem(expr const * n) const { return is_app_of(n, m_afid, OP_REM); }
273285
bool is_to_real(expr const * n) const { return is_app_of(n, m_afid, OP_TO_REAL); }
@@ -395,10 +407,15 @@ class arith_util : public arith_recognizers {
395407
app * mk_idiv(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_IDIV, arg1, arg2); }
396408
app * mk_rem(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_REM, arg1, arg2); }
397409
app * mk_mod(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_MOD, arg1, arg2); }
410+
app * mk_div0(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_DIV0, arg1, arg2); }
411+
app * mk_idiv0(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_IDIV0, arg1, arg2); }
412+
app * mk_rem0(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_REM0, arg1, arg2); }
413+
app * mk_mod0(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_MOD0, arg1, arg2); }
398414
app * mk_to_real(expr * arg1) { return m_manager.mk_app(m_afid, OP_TO_REAL, arg1); }
399415
app * mk_to_int(expr * arg1) { return m_manager.mk_app(m_afid, OP_TO_INT, arg1); }
400416
app * mk_is_int(expr * arg1) { return m_manager.mk_app(m_afid, OP_IS_INT, arg1); }
401417
app * mk_power(expr* arg1, expr* arg2) { return m_manager.mk_app(m_afid, OP_POWER, arg1, arg2); }
418+
app * mk_power0(expr* arg1, expr* arg2) { return m_manager.mk_app(m_afid, OP_POWER0, arg1, arg2); }
402419

403420
app * mk_sin(expr * arg) { return m_manager.mk_app(m_afid, OP_SIN, arg); }
404421
app * mk_cos(expr * arg) { return m_manager.mk_app(m_afid, OP_COS, arg); }
@@ -444,7 +461,7 @@ class arith_util : public arith_recognizers {
444461
expr_ref mk_add_simplify(expr_ref_vector const& args);
445462
expr_ref mk_add_simplify(unsigned sz, expr* const* args);
446463

447-
bool is_considered_uninterpreted(func_decl* f, unsigned n, expr* const* args);
464+
bool is_considered_uninterpreted(func_decl* f, unsigned n, expr* const* args, func_decl_ref& f_out);
448465

449466
};
450467

src/model/model_evaluator.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,21 @@ struct evaluator_cfg : public default_rewriter_cfg {
334334

335335
func_interp * fi = m_model.get_func_interp(f);
336336

337+
338+
func_decl_ref f_ui(m);
339+
if (!fi && m_au.is_considered_uninterpreted(f, num, args, f_ui)) {
340+
if (f_ui) {
341+
fi = m_model.get_func_interp(f);
342+
}
343+
if (!fi) {
344+
result = m_au.mk_numeral(rational(0), f->get_range());
345+
return BR_DONE;
346+
}
347+
}
348+
else if (!fi && m_fpau.is_considered_uninterpreted(f, num, args)) {
349+
result = m.get_some_value(f->get_range());
350+
return BR_DONE;
351+
}
337352
if (fi) {
338353
if (fi->is_partial())
339354
fi->set_else(m.get_some_value(f->get_range()));
@@ -343,14 +358,6 @@ struct evaluator_cfg : public default_rewriter_cfg {
343358
return BR_REWRITE_FULL;
344359
}
345360

346-
if (m_au.is_considered_uninterpreted(f, num, args)) {
347-
result = m_au.mk_numeral(rational(0), f->get_range());
348-
return BR_DONE;
349-
}
350-
else if (m_fpau.is_considered_uninterpreted(f, num, args)) {
351-
result = m.get_some_value(f->get_range());
352-
return BR_DONE;
353-
}
354361
return BR_FAILED;
355362
}
356363

src/muz/rel/dl_base.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,6 @@ namespace datalog {
435435
Since the destructor is protected, we cannot use the \c dealloc macro.
436436
*/
437437
void destroy() {
438-
SASSERT(this != nullptr);
439438
this->~base_ancestor();
440439
memory::deallocate(this);
441440
}

src/smt/theory_arith.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ namespace smt {
440440
arith_eq_solver m_arith_eq_solver;
441441
bool m_found_unsupported_op;
442442
bool m_found_underspecified_op;
443+
ptr_vector<app> m_underspecified_ops;
443444
arith_eq_adapter m_arith_eq_adapter;
444445
vector<row> m_rows;
445446
svector<unsigned> m_dead_rows;
@@ -1077,6 +1078,7 @@ namespace smt {
10771078
//
10781079
// -----------------------------------
10791080
bool get_value(enode * n, expr_ref & r) override;
1081+
bool include_func_interp(func_decl* f) override;
10801082

10811083
bool get_lower(enode* n, expr_ref& r);
10821084
bool get_upper(enode* n, expr_ref& r);

src/smt/theory_arith_core.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ namespace smt {
3939

4040
template<typename Ext>
4141
void theory_arith<Ext>::found_underspecified_op(app * n) {
42+
m_underspecified_ops.push_back(n);
43+
get_context().push_trail(push_back_vector<context, ptr_vector<app>>(m_underspecified_ops));
4244
if (!m_found_underspecified_op) {
4345
TRACE("arith", tout << "found underspecified expression:\n" << mk_pp(n, get_manager()) << "\n";);
4446
get_context().push_trail(value_trail<context, bool>(m_found_underspecified_op));
@@ -388,7 +390,6 @@ namespace smt {
388390
theory_var theory_arith<Ext>::internalize_div(app * n) {
389391
rational r(1);
390392
if (!m_util.is_numeral(n->get_arg(1), r) || r.is_zero()) found_underspecified_op(n);
391-
found_underspecified_op(n);
392393
theory_var s = mk_binary_op(n);
393394
context & ctx = get_context();
394395
if (!ctx.relevancy())
@@ -3271,8 +3272,36 @@ namespace smt {
32713272
if (!m_model_depends_on_computed_epsilon) {
32723273
refine_epsilon();
32733274
}
3275+
for (app* n : m_underspecified_ops) {
3276+
if (m_util.is_div(n)) {
3277+
mk_enode(m_util.mk_div0(n->get_arg(0), n->get_arg(1)));
3278+
}
3279+
else if (m_util.is_idiv(n)) {
3280+
mk_enode(m_util.mk_idiv0(n->get_arg(0), n->get_arg(1)));
3281+
}
3282+
else if (m_util.is_rem(n)) {
3283+
mk_enode(m_util.mk_rem0(n->get_arg(0), n->get_arg(1)));
3284+
}
3285+
else if (m_util.is_mod(n)) {
3286+
mk_enode(m_util.mk_mod0(n->get_arg(0), n->get_arg(1)));
3287+
}
3288+
else if (m_util.is_power(n)) {
3289+
mk_enode(m_util.mk_power0(n->get_arg(0), n->get_arg(1)));
3290+
}
3291+
}
32743292
}
32753293

3294+
template<typename Ext>
3295+
bool theory_arith<Ext>::include_func_interp(func_decl* f) {
3296+
return
3297+
m_util.is_div0(f) ||
3298+
m_util.is_idiv0(f) ||
3299+
m_util.is_power0(f) ||
3300+
m_util.is_rem0(f) ||
3301+
m_util.is_mod0(f);
3302+
}
3303+
3304+
32763305
template<typename Ext>
32773306
model_value_proc * theory_arith<Ext>::mk_value(enode * n, model_generator & mg) {
32783307
theory_var v = n->get_th_var(get_id());

0 commit comments

Comments
 (0)