From 0752b1385c090a2aba82bc47392402943917a9be Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 13 Jul 2021 14:22:58 +0200 Subject: [PATCH] add length axioms Signed-off-by: Nikolaj Bjorner --- src/ast/rewriter/seq_axioms.cpp | 26 ++++++++++++++++++++++++-- src/ast/rewriter/seq_axioms.h | 1 + src/smt/seq_axioms.h | 1 + src/smt/theory_seq.cpp | 25 +++++++++++++++++-------- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/ast/rewriter/seq_axioms.cpp b/src/ast/rewriter/seq_axioms.cpp index afd1c5239..c255c7140 100644 --- a/src/ast/rewriter/seq_axioms.cpp +++ b/src/ast/rewriter/seq_axioms.cpp @@ -786,15 +786,37 @@ namespace seq { unsigned sz = bv.get_bv_size(b); expr_ref_vector es(m); expr_ref bb(b, m), ten(bv.mk_numeral(10, sz), m); - for (unsigned i = 0; i < k; ++i) { + pow = 1; + for (unsigned i = 0; i <= k; ++i) { + if (pow > 1) + bb = bv.mk_bv_udiv(b, bv.mk_numeral(pow, bv_sort)); es.push_back(seq.str.mk_unit(m_sk.mk_ubv2ch(bv.mk_bv_urem(bb, ten)))); - bb = bv.mk_bv_udiv(bb, ten); + pow *= 10; } es.reverse(); eq = m.mk_eq(seq.str.mk_ubv2s(b), seq.str.mk_concat(es, seq.str.mk_string_sort())); add_clause(~ge10k, ge10k1, eq); } + /* + * len(ubv2s(b)) = k => 10^k-1 <= b < 10^{k} k > 1 + * len(ubv2s(b)) = 1 => b < 10^{1} k = 1 + */ + void axioms::ubv2s_len_axiom(expr* b, unsigned k) { + expr_ref ge10k(m), ge10k1(m), eq(m); + bv_util bv(m); + sort* bv_sort = b->get_sort(); + rational pow(1); + for (unsigned i = 1; i < k; ++i) + pow *= 10; + ge10k = bv.mk_ule(bv.mk_numeral(pow, bv_sort), b); + ge10k1 = bv.mk_ule(bv.mk_numeral(pow * 10, bv_sort), b); + eq = m.mk_eq(seq.str.mk_length(seq.str.mk_ubv2s(b)), a.mk_int(k)); + add_clause(~eq, ~ge10k1); + if (k > 1) + add_clause(~eq, ge10k); + } + void axioms::ubv2ch_axiom(sort* bv_sort) { bv_util bv(m); expr_ref eq(m); diff --git a/src/ast/rewriter/seq_axioms.h b/src/ast/rewriter/seq_axioms.h index 8c2af65e4..c9cdbfc9a 100644 --- a/src/ast/rewriter/seq_axioms.h +++ b/src/ast/rewriter/seq_axioms.h @@ -95,6 +95,7 @@ namespace seq { void stoi_axiom(expr* e, unsigned k); void itos_axiom(expr* s, unsigned k); void ubv2s_axiom(expr* b, unsigned k); + void ubv2s_len_axiom(expr* b, unsigned k); void ubv2ch_axiom(sort* bv_sort); void lt_axiom(expr* n); void le_axiom(expr* n); diff --git a/src/smt/seq_axioms.h b/src/smt/seq_axioms.h index 16091fcf4..c5aa68e0a 100644 --- a/src/smt/seq_axioms.h +++ b/src/smt/seq_axioms.h @@ -80,6 +80,7 @@ namespace smt { void add_stoi_axiom(expr* e, unsigned k) { m_ax.stoi_axiom(e, k); } void add_itos_axiom(expr* s, unsigned k) { m_ax.itos_axiom(s, k); } void add_ubv2s_axiom(expr* b, unsigned k) { m_ax.ubv2s_axiom(b, k); } + void add_ubv2s_len_axiom(expr* b, unsigned k) { m_ax.ubv2s_len_axiom(b, k); } void add_ubv2ch_axioms(sort* s) { m_ax.ubv2ch_axiom(s); } void add_lt_axiom(expr* n) { m_ax.lt_axiom(n); } void add_le_axiom(expr* n) { m_ax.le_axiom(n); } diff --git a/src/smt/theory_seq.cpp b/src/smt/theory_seq.cpp index 599646b5b..436752aa7 100644 --- a/src/smt/theory_seq.cpp +++ b/src/smt/theory_seq.cpp @@ -1532,8 +1532,19 @@ bool theory_seq::add_length_to_eqc(expr* e) { } void theory_seq::add_ubv_string(expr* e) { + bool has_sort = false; + expr* b = nullptr; + VERIFY(m_util.str.is_ubv2s(e, b)); + for (auto* e2 : m_ubv_string) { + expr* b2 = nullptr; + VERIFY(m_util.str.is_ubv2s(e2, b2)); + has_sort |= b2->get_sort() == b->get_sort(); + } + if (!has_sort) + m_ax.add_ubv2ch_axioms(b->get_sort()); m_ubv_string.push_back(e); m_trail_stack.push(push_back_vector(m_ubv_string)); + add_length_to_eqc(e); } bool theory_seq::check_ubv_string() { @@ -1554,6 +1565,11 @@ bool theory_seq::check_ubv_string(expr* e) { expr* b = nullptr; bv_util bv(m); VERIFY(m_util.str.is_ubv2s(e, b)); + rational len; + if (get_length(e, len) && len.is_unsigned()) + m_ax.add_ubv2s_len_axiom(b, len.get_unsigned()); + + unsigned sz = bv.get_bv_size(b); rational value(0); bool all_bits_assigned = true; @@ -1579,14 +1595,7 @@ bool theory_seq::check_ubv_string(expr* e) { k++; value = div(value, rational(10)); } - bool has_sort = false; - for (auto* e2 : m_has_ubv_axiom) { - expr* b2 = nullptr; - VERIFY(m_util.str.is_ubv2s(e2, b2)); - has_sort |= b2->get_sort() == b->get_sort(); - } - if (!has_sort) - m_ax.add_ubv2ch_axioms(b->get_sort()); + m_has_ubv_axiom.insert(e); m_trail_stack.push(insert_obj_trail(m_has_ubv_axiom, e)); m_ax.add_ubv2s_axiom(b, k);