Skip to content

Commit 1e0c1ce

Browse files
add definitions for under-specified cases of arithmetic operators #2663 #2676 #2679
Signed-off-by: Nikolaj Bjorner <[email protected]>
1 parent 6cf7d8e commit 1e0c1ce

13 files changed

+59
-20
lines changed

src/ast/arith_decl_plugin.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ 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));
365+
case OP_DIV0: return m_manager->mk_func_decl(symbol("/0"), m_real_decl, m_real_decl, m_real_decl, func_decl_info(m_family_id, OP_DIV0));
366366
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));
367367
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));
368368
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));
@@ -788,8 +788,7 @@ expr_ref arith_util::mk_add_simplify(unsigned sz, expr* const* args) {
788788
bool arith_util::is_considered_uninterpreted(func_decl* f, unsigned n, expr* const* args, func_decl_ref& f_out) {
789789
rational r;
790790
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());
791+
f_out = mk_div0();
793792
return true;
794793
}
795794
if (is_decl_of(f, m_afid, OP_IDIV) && is_numeral(args[1], r) && r.is_zero()) {
@@ -814,3 +813,8 @@ bool arith_util::is_considered_uninterpreted(func_decl* f, unsigned n, expr* con
814813
}
815814
return plugin().is_considered_uninterpreted(f);
816815
}
816+
817+
func_decl* arith_util::mk_div0() {
818+
sort* rs[2] = { mk_real(), mk_real() };
819+
return m_manager.mk_func_decl(m_afid, OP_DIV0, 0, nullptr, 2, rs, mk_real());
820+
}

src/ast/arith_decl_plugin.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ class arith_decl_plugin : public decl_plugin {
213213
case OP_NEG_ROOT:
214214
case OP_U_ASIN:
215215
case OP_U_ACOS:
216+
case OP_DIV0:
217+
case OP_IDIV0:
218+
case OP_REM0:
219+
case OP_MOD0:
220+
case OP_POWER0:
216221
return true;
217222
default:
218223
return false;
@@ -362,6 +367,9 @@ class arith_util : public arith_recognizers {
362367
sort * mk_int() { return m_manager.mk_sort(m_afid, INT_SORT); }
363368
sort * mk_real() { return m_manager.mk_sort(m_afid, REAL_SORT); }
364369

370+
func_decl* mk_div0();
371+
372+
365373
app * mk_numeral(rational const & val, bool is_int) const {
366374
return plugin().mk_numeral(val, is_int);
367375
}

src/ast/ast_smt_pp.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ class smt_printer {
841841
else {
842842
m_out << "(declare-sort ";
843843
visit_sort(s);
844-
m_out << ")";
844+
m_out << " 0)";
845845
newline();
846846
}
847847
mark.mark(s, true);

src/model/model_evaluator.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,11 +334,10 @@ struct evaluator_cfg : public default_rewriter_cfg {
334334

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

337-
338337
func_decl_ref f_ui(m);
339338
if (!fi && m_au.is_considered_uninterpreted(f, num, args, f_ui)) {
340339
if (f_ui) {
341-
fi = m_model.get_func_interp(f);
340+
fi = m_model.get_func_interp(f_ui);
342341
}
343342
if (!fi) {
344343
result = m_au.mk_numeral(rational(0), f->get_range());

src/muz/base/dl_context.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -765,10 +765,15 @@ namespace datalog {
765765
ast_manager& m;
766766
arith_util a;
767767
datatype_util dt;
768+
bv_util bv;
768769
DL_ENGINE m_engine_type;
769770

771+
bool is_large_bv(sort* s) {
772+
return false;
773+
}
774+
770775
public:
771-
engine_type_proc(ast_manager& m): m(m), a(m), dt(m), m_engine_type(DATALOG_ENGINE) {}
776+
engine_type_proc(ast_manager& m): m(m), a(m), dt(m), bv(m), m_engine_type(DATALOG_ENGINE) {}
772777

773778
DL_ENGINE get_engine() const { return m_engine_type; }
774779

@@ -782,6 +787,9 @@ namespace datalog {
782787
else if (dt.is_datatype(m.get_sort(e))) {
783788
m_engine_type = SPACER_ENGINE;
784789
}
790+
else if (is_large_bv(m.get_sort(e))) {
791+
m_engine_type = SPACER_ENGINE;
792+
}
785793
}
786794
};
787795

src/muz/fp/dl_cmds.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,6 @@ class dl_query_cmd : public parametric_cmd {
305305

306306
case datalog::OK:
307307
(void)query_exn;
308-
SASSERT(query_exn);
309308
break;
310309

311310
case datalog::CANCELED:

src/muz/spacer/spacer_context.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3800,6 +3800,7 @@ bool context::create_children(pob& n, datalog::rule const& r,
38003800

38013801
void context::collect_statistics(statistics& st) const
38023802
{
3803+
// m_params is not necessarily live when collect_statistics is called.
38033804
m_pool0->collect_statistics(st);
38043805
m_pool1->collect_statistics(st);
38053806
m_pool2->collect_statistics(st);
@@ -3841,7 +3842,6 @@ void context::collect_statistics(statistics& st) const
38413842
// -- time in creating new predecessors
38423843
st.update ("time.spacer.solve.reach.children",
38433844
m_create_children_watch.get_seconds ());
3844-
st.update("spacer.random_seed", m_params.spacer_random_seed());
38453845
st.update("spacer.lemmas_imported", m_stats.m_num_lemmas_imported);
38463846
st.update("spacer.lemmas_discarded", m_stats.m_num_lemmas_discarded);
38473847

src/smt/params/theory_array_params.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@ void theory_array_params::display(std::ostream & out) const {
3737
DISPLAY_PARAM(m_array_always_prop_upward);
3838
DISPLAY_PARAM(m_array_lazy_ieq);
3939
DISPLAY_PARAM(m_array_lazy_ieq_delay);
40-
}
40+
}

src/smt/smt_context.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3318,6 +3318,7 @@ namespace smt {
33183318
\brief Execute some finalization code after performing the search.
33193319
*/
33203320
lbool context::check_finalize(lbool r) {
3321+
if (r == l_undef) std::cout << m_unknown << "\n";
33213322
TRACE("after_search", display(tout << "result: " << r << "\n"););
33223323
display_profile(verbose_stream());
33233324
if (r == l_true && get_cancel_flag()) {

src/smt/smt_context.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ namespace smt {
7474

7575
std::ostream& display_last_failure(std::ostream& out) const;
7676
std::string last_failure_as_string() const;
77-
void set_reason_unknown(char const* msg) { m_unknown = msg; }
77+
void set_reason_unknown(char const* msg) { m_unknown = msg; std::cout << m_unknown << "\n"; }
7878
void set_progress_callback(progress_callback *callback);
7979

8080

@@ -1009,14 +1009,15 @@ namespace smt {
10091009
}
10101010
#endif
10111011

1012+
void add_eq(enode * n1, enode * n2, eq_justification js);
1013+
10121014
protected:
10131015
void push_new_th_eq(theory_id th, theory_var lhs, theory_var rhs);
10141016

10151017
void push_new_th_diseq(theory_id th, theory_var lhs, theory_var rhs);
10161018

10171019
friend class add_eq_trail;
10181020

1019-
void add_eq(enode * n1, enode * n2, eq_justification js);
10201021

10211022
void remove_parents_from_cg_table(enode * r1);
10221023

src/smt/smt_enode.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ namespace smt {
201201
return m_root;
202202
}
203203

204+
void set_root(enode* r) {
205+
m_root = r;
206+
}
207+
204208
enode * get_next() const {
205209
return m_next;
206210
}

src/smt/theory_arith_core.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ Revision History:
1919
#ifndef THEORY_ARITH_CORE_H_
2020
#define THEORY_ARITH_CORE_H_
2121

22-
#include "smt/smt_context.h"
23-
#include "smt/theory_arith.h"
2422
#include "ast/ast_pp.h"
2523
#include "ast/ast_ll_pp.h"
26-
#include "smt/smt_model_generator.h"
2724
#include "ast/ast_smt2_pp.h"
25+
#include "smt/smt_context.h"
26+
#include "smt/theory_arith.h"
27+
#include "smt/smt_model_generator.h"
2828

2929
namespace smt {
3030

@@ -3266,27 +3266,33 @@ namespace smt {
32663266
template<typename Ext>
32673267
void theory_arith<Ext>::init_model(model_generator & m) {
32683268
TRACE("theory_arith", tout << "init model invoked...\n";);
3269+
context& ctx = get_context();
32693270
m_factory = alloc(arith_factory, get_manager());
32703271
m.register_factory(m_factory);
32713272
compute_epsilon();
32723273
if (!m_model_depends_on_computed_epsilon) {
32733274
refine_epsilon();
32743275
}
32753276
for (app* n : m_underspecified_ops) {
3277+
enode* e = nullptr;
32763278
if (m_util.is_div(n)) {
3277-
mk_enode(m_util.mk_div0(n->get_arg(0), n->get_arg(1)));
3279+
e = mk_enode(m_util.mk_div0(n->get_arg(0), n->get_arg(1)));
32783280
}
32793281
else if (m_util.is_idiv(n)) {
3280-
mk_enode(m_util.mk_idiv0(n->get_arg(0), n->get_arg(1)));
3282+
e = mk_enode(m_util.mk_idiv0(n->get_arg(0), n->get_arg(1)));
32813283
}
32823284
else if (m_util.is_rem(n)) {
3283-
mk_enode(m_util.mk_rem0(n->get_arg(0), n->get_arg(1)));
3285+
e = mk_enode(m_util.mk_rem0(n->get_arg(0), n->get_arg(1)));
32843286
}
32853287
else if (m_util.is_mod(n)) {
3286-
mk_enode(m_util.mk_mod0(n->get_arg(0), n->get_arg(1)));
3288+
e = mk_enode(m_util.mk_mod0(n->get_arg(0), n->get_arg(1)));
32873289
}
32883290
else if (m_util.is_power(n)) {
3289-
mk_enode(m_util.mk_power0(n->get_arg(0), n->get_arg(1)));
3291+
e = mk_enode(m_util.mk_power0(n->get_arg(0), n->get_arg(1)));
3292+
}
3293+
if (e) {
3294+
ctx.mark_as_relevant(e);
3295+
ctx.add_eq(e, ctx.get_enode(n), eq_justification());
32903296
}
32913297
}
32923298
}

src/tactic/arith/purify_arith_tactic.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,15 @@ struct purify_arith_proc {
795795
SASSERT(is_uninterp_const(v));
796796
fmc->hide(v->get_decl());
797797
}
798+
if (!divs.empty()) {
799+
expr_ref body(u().mk_real(0), m());
800+
expr_ref v0(m().mk_var(0, u().mk_real()), m());
801+
expr_ref v1(m().mk_var(1, u().mk_real()), m());
802+
for (auto const& p : divs) {
803+
body = m().mk_ite(m().mk_and(m().mk_eq(v0, p.x), m().mk_eq(v1, p.y)), p.d, body);
804+
}
805+
fmc->add(u().mk_div0(), body);
806+
}
798807
}
799808
if (produce_models && !m_sin_cos.empty()) {
800809
generic_model_converter* emc = alloc(generic_model_converter, m(), "purify_sin_cos");

0 commit comments

Comments
 (0)