Skip to content

Commit

Permalink
add min/max diff in final check
Browse files Browse the repository at this point in the history
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
  • Loading branch information
NikolajBjorner committed May 4, 2022
1 parent c29cfa8 commit 367bfed
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 23 deletions.
51 changes: 35 additions & 16 deletions src/ast/seq_decl_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,6 @@ void seq_decl_plugin::init() {
sort* boolT = m.mk_bool_sort();
sort* intT = arith_util(m).mk_int();
sort* predA = autil.mk_array_sort(A, boolT);
sort* arrAB = autil.mk_array_sort(A, B);
sort* arrIAB = autil.mk_array_sort(intT, A, B);
sort* arrBAB = autil.mk_array_sort(B, A, B);
sort* arrIBAB = autil.mk_array_sort(intT, B, A, B);
sort* seqAseqAseqA[3] = { seqA, seqA, seqA };
sort* seqAreAseqA[3] = { seqA, reA, seqA };
sort* seqAseqA[2] = { seqA, seqA };
Expand All @@ -217,10 +213,6 @@ void seq_decl_plugin::init() {
sort* str2TintT[3] = { strT, strT, intT };
sort* seqAintT[2] = { seqA, intT };
sort* seq3A[3] = { seqA, seqA, seqA };
sort* arrABseqA[2] = { arrAB, seqA };
sort* arrIABintTseqA[3] = { arrIAB, intT, seqA };
sort* arrBAB_BseqA[3] = { arrBAB, B,seqA };
sort* arrIBABintTBseqA[4] = { arrIBAB, intT, B, seqA };

m_sigs.resize(LAST_SEQ_OP);
// TBD: have (par ..) construct and load parameterized signature from premable.
Expand All @@ -239,10 +231,6 @@ void seq_decl_plugin::init() {
m_sigs[OP_SEQ_NTH_I] = alloc(psig, m, "seq.nth_i", 1, 2, seqAintT, A);
m_sigs[OP_SEQ_NTH_U] = alloc(psig, m, "seq.nth_u", 1, 2, seqAintT, A);
m_sigs[OP_SEQ_LENGTH] = alloc(psig, m, "seq.len", 1, 1, &seqA, intT);
m_sigs[OP_SEQ_MAP] = alloc(psig, m, "seq.map", 2, 2, arrABseqA, seqB);
m_sigs[OP_SEQ_MAPI] = alloc(psig, m, "seq.mapi", 2, 3, arrIABintTseqA, seqB);
m_sigs[OP_SEQ_FOLDL] = alloc(psig, m, "seq.fold_left", 2, 3, arrBAB_BseqA, B);
m_sigs[OP_SEQ_FOLDLI] = alloc(psig, m, "seq.fold_leftli", 2, 4, arrIBABintTBseqA, B);
m_sigs[OP_RE_PLUS] = alloc(psig, m, "re.+", 1, 1, &reA, reA);
m_sigs[OP_RE_STAR] = alloc(psig, m, "re.*", 1, 1, &reA, reA);
m_sigs[OP_RE_OPTION] = alloc(psig, m, "re.opt", 1, 1, &reA, reA);
Expand Down Expand Up @@ -290,6 +278,7 @@ void seq_decl_plugin::init() {
m_sigs[_OP_STRING_SUBSTR] = alloc(psig, m, "str.substr", 0, 3, strTint2T, strT);
}


sort* seq_decl_plugin::mk_reglan() {
if (!m_reglan) {
ast_manager& m = *m_manager;
Expand Down Expand Up @@ -603,7 +592,8 @@ func_decl* seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
case OP_SEQ_MAPI:
case OP_SEQ_FOLDL:
case OP_SEQ_FOLDLI:
return mk_str_fun(k, arity, domain, range, k);
add_map_sig();
return mk_str_fun(k, arity, domain, range, k);

case OP_SEQ_TO_RE:
m_has_re = true;
Expand Down Expand Up @@ -648,13 +638,42 @@ func_decl* seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
}
}

void seq_decl_plugin::add_map_sig() {
if (m_sigs[OP_SEQ_MAP])
return;
ast_manager& m = *m_manager;
array_util autil(m);
sort* A = m.mk_uninterpreted_sort(symbol(0u));
sort* B = m.mk_uninterpreted_sort(symbol(1u));
parameter paramA(A);
parameter paramB(B);
sort* seqA = m.mk_sort(m_family_id, SEQ_SORT, 1, &paramA);
sort* seqB = m.mk_sort(m_family_id, SEQ_SORT, 1, &paramB);
sort* intT = arith_util(m).mk_int();
sort* arrAB = autil.mk_array_sort(A, B);
sort* arrIAB = autil.mk_array_sort(intT, A, B);
sort* arrBAB = autil.mk_array_sort(B, A, B);
sort* arrIBAB = autil.mk_array_sort(intT, B, A, B);
sort* arrABseqA[2] = { arrAB, seqA };
sort* arrIABintTseqA[3] = { arrIAB, intT, seqA };
sort* arrBAB_BseqA[3] = { arrBAB, B,seqA };
sort* arrIBABintTBseqA[4] = { arrIBAB, intT, B, seqA };
m_sigs[OP_SEQ_MAP] = alloc(psig, m, "seq.map", 2, 2, arrABseqA, seqB);
m_sigs[OP_SEQ_MAPI] = alloc(psig, m, "seq.mapi", 2, 3, arrIABintTseqA, seqB);
m_sigs[OP_SEQ_FOLDL] = alloc(psig, m, "seq.fold_left", 2, 3, arrBAB_BseqA, B);
m_sigs[OP_SEQ_FOLDLI] = alloc(psig, m, "seq.fold_leftli", 2, 4, arrIBABintTBseqA, B);
}

void seq_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
init();
for (unsigned i = 0; i < m_sigs.size(); ++i) {
if (m_sigs[i]) {
op_names.push_back(builtin_name(m_sigs[i]->m_name.str(), i));
}
if (m_sigs[i])
op_names.push_back(builtin_name(m_sigs[i]->m_name.str(), i));
}
op_names.push_back(builtin_name("seq.map", OP_SEQ_MAP));
op_names.push_back(builtin_name("seq.mapi", OP_SEQ_MAPI));
op_names.push_back(builtin_name("seq.foldl", OP_SEQ_FOLDL));
op_names.push_back(builtin_name("seq.foldli", OP_SEQ_FOLDLI));
op_names.push_back(builtin_name("str.in.re", _OP_STRING_IN_REGEXP));
op_names.push_back(builtin_name("str.in-re", _OP_STRING_IN_REGEXP));
op_names.push_back(builtin_name("str.to.re", _OP_STRING_TO_REGEXP));
Expand Down
3 changes: 3 additions & 0 deletions src/ast/seq_decl_plugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ class seq_decl_plugin : public decl_plugin {
bool m_has_seq;
char_decl_plugin* m_char_plugin { nullptr };


void add_map_sig();

void match(psig& sig, unsigned dsz, sort* const* dom, sort* range, sort_ref& rng);

void match_assoc(psig& sig, unsigned dsz, sort* const* dom, sort* range, sort_ref& rng);
Expand Down
27 changes: 25 additions & 2 deletions src/sat/smt/array_axioms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ namespace array {
return assert_extensionality(r.n->get_expr(), r.select->get_expr());
case axiom_record::kind_t::is_diff:
return assert_diff(r.n->get_app());
case axiom_record::kind_t::is_diffselect:
return assert_diff_select(r.n->get_app(), r.select->get_app());
case axiom_record::kind_t::is_congruence:
return assert_congruent_axiom(r.n->get_expr(), r.select->get_expr());
default:
Expand Down Expand Up @@ -294,7 +296,7 @@ namespace array {
* a = c and a[i] != b[i] => i <= md(b, c) or default(b) != default(c)
* where ai = a[i], md = md(b, c)
*/
bool solver::assert_diff_select(app* ai, app* md) {
bool solver::assert_diff_select(app* md, app* ai) {
SASSERT(a.is_select(ai));
SASSERT(ai->get_num_args() == 2);
expr* A = ai->get_arg(0);
Expand All @@ -303,7 +305,7 @@ namespace array {
expr* C = md->get_arg(1);
literal eq_default = eq_internalize(a.mk_default(B), a.mk_default(C));
arith_util autil(m);
literal ineq = mk_literal(autil.mk_le(i, md));
literal ineq = mk_literal(a.is_maxdiff(md) ? autil.mk_le(i, md) : autil.mk_le(md, i));
bool is_new = false;
if (ctx.get_enode(A)->get_root() == ctx.get_enode(B)->get_root()) {
literal eq_ab = eq_internalize(A, B);
Expand Down Expand Up @@ -714,5 +716,26 @@ namespace array {
return false;
}

bool solver::add_diff_select_axioms() {
bool added = false;

auto add_diff_select = [&](euf::enode* md, euf::enode* a) {
var_data const& d = get_var_data(find(get_th_var(a)));
for (euf::enode* select : d.m_parent_selects) {
if (assert_diff_select(md->get_app(), select->get_app()))
added = true;
}
};
for (euf::enode* md : m_minmaxdiffs) {
euf::enode* a = md->get_arg(0);
euf::enode* b = md->get_arg(1);
add_diff_select(md, a);
add_diff_select(md, b);
}
return added;
}



}

2 changes: 2 additions & 0 deletions src/sat/smt/array_internalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ namespace array {
case OP_ARRAY_MINDIFF:
case OP_ARRAY_MAXDIFF:
push_axiom(diff_axiom(n));
m_minmaxdiffs.push_back(n);
ctx.push(push_back_vector(m_minmaxdiffs));
break;
case OP_ARRAY_DEFAULT:
add_parent_default(find(n->get_arg(0)), n);
Expand Down
7 changes: 6 additions & 1 deletion src/sat/smt/array_solver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,14 @@ namespace array {
else if (!turn[idx] && add_interface_equalities())
return sat::check_result::CR_CONTINUE;
}
if (m_delay_qhead < m_axiom_trail.size())

if (add_diff_select_axioms())
return sat::check_result::CR_CONTINUE;

if (m_delay_qhead < m_axiom_trail.size())
return sat::check_result::CR_CONTINUE;


// validate_check();
return sat::check_result::CR_DONE;
}
Expand Down
10 changes: 6 additions & 4 deletions src/sat/smt/array_solver.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ namespace array {
axiom_record::eq m_eq;
axiom_table_t m_axioms;
svector<axiom_record> m_axiom_trail;
unsigned m_qhead { 0 };
unsigned m_delay_qhead { 0 };
bool m_enable_delay { true };
unsigned m_qhead = 0;
unsigned m_delay_qhead = 0;
bool m_enable_delay = true;
struct reset_new;
void push_axiom(axiom_record const& r);
bool propagate_axiom(unsigned idx);
Expand All @@ -166,7 +166,8 @@ namespace array {
axiom_record extensionality_axiom(euf::enode* x, euf::enode* y) { return axiom_record(axiom_record::kind_t::is_extensionality, x, y); }
axiom_record congruence_axiom(euf::enode* a, euf::enode* b) { return axiom_record(axiom_record::kind_t::is_congruence, a, b); }
axiom_record diff_axiom(euf::enode* md) { return axiom_record(axiom_record::kind_t::is_diff, md); }
axiom_record diff_select_axiom(euf::enode* ai, euf::enode* md) { return axiom_record(axiom_record::kind_t::is_diffselect, ai, md); }
euf::enode_vector m_minmaxdiffs;
axiom_record diff_select_axiom(euf::enode* md, euf::enode* ai) { return axiom_record(axiom_record::kind_t::is_diffselect, md, ai); }

scoped_ptr<sat::constraint_base> m_constraint;

Expand All @@ -187,6 +188,7 @@ namespace array {
bool assert_congruent_axiom(expr* e1, expr* e2);
bool add_delayed_axioms();
bool add_as_array_eqs(euf::enode* n);
bool add_diff_select_axioms();
expr_ref apply_map(app* map, unsigned n, expr* const* args);
bool is_map_combinator(expr* e) const;

Expand Down

0 comments on commit 367bfed

Please sign in to comment.