3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-15 13:28:47 +00:00

Merge remote-tracking branch 'upstream/master' into lackr

This commit is contained in:
Mikolas Janota 2016-01-14 15:25:04 +00:00
commit c6df8b3128
7 changed files with 386 additions and 198 deletions

View file

@ -126,14 +126,27 @@ eautomaton* re2automaton::re2aut(expr* e) {
}
return b.detach();
}
#if 0
else if (u.re.is_loop(e, e1, lo) && (a = re2aut(e1))) {
b = eautomaton::clone(*a);
b->add_final_to_init_moves();
b->add_init_to_final_states();
while (lo > 0) {
b = eautomaton::mk_concat(*a, *b);
--lo;
}
return b.detach();
}
else if (u.re.is_empty(e)) {
return alloc(eautomaton, m);
return alloc(eautomaton, sm);
}
else if (u.re.is_full(e)) {
expr_ref tt(m.mk_true(), m);
sym_expr* _true = sym_expr::mk_pred(tt);
return eautomaton::mk_loop(sm, _true);
}
#if 0
else if (u.re.is_intersect(e, e1, e2)) {
// maybe later
}
#endif
@ -197,7 +210,7 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
case OP_RE_INTERSECT:
return BR_FAILED;
case OP_RE_LOOP:
return BR_FAILED;
return mk_re_loop(num_args, args, result);
case OP_RE_EMPTY_SET:
return BR_FAILED;
case OP_RE_FULL_SET:
@ -687,14 +700,14 @@ br_status seq_rewriter::mk_str_stoi(expr* a, expr_ref& result) {
return BR_FAILED;
}
void seq_rewriter::add_next(u_map<expr*>& next, unsigned idx, expr* cond) {
void seq_rewriter::add_next(u_map<expr*>& next, expr_ref_vector& trail, unsigned idx, expr* cond) {
expr* acc;
if (m().is_true(cond) || !next.find(idx, acc)) {
if (!m().is_true(cond) && next.find(idx, acc)) {
cond = m().mk_or(cond, acc);
}
trail.push_back(cond);
next.insert(idx, cond);
}
else {
next.insert(idx, m().mk_or(cond, acc));
}
}
bool seq_rewriter::is_sequence(eautomaton& aut, expr_ref_vector& seq) {
@ -804,9 +817,10 @@ br_status seq_rewriter::mk_str_in_regexp(expr* a, expr* b, expr_ref& result) {
aut->get_moves_from(state, mvs, false);
for (unsigned j = 0; j < mvs.size(); ++j) {
eautomaton::move const& mv = mvs[j];
SASSERT(mv.t());
if (mv.t()->is_char() && m().is_value(mv.t()->get_char()) && m().is_value(ch)) {
if (mv.t()->get_char() == ch) {
add_next(next, mv.dst(), acc);
add_next(next, trail, mv.dst(), acc);
}
else {
continue;
@ -815,7 +829,7 @@ br_status seq_rewriter::mk_str_in_regexp(expr* a, expr* b, expr_ref& result) {
else {
cond = mv.t()->accept(ch);
if (!m().is_true(acc)) cond = m().mk_and(acc, cond);
add_next(next, mv.dst(), cond);
add_next(next, trail, mv.dst(), cond);
}
}
}
@ -835,12 +849,25 @@ br_status seq_rewriter::mk_str_in_regexp(expr* a, expr* b, expr_ref& result) {
}
}
result = mk_or(ors);
TRACE("seq", tout << result << "\n";);
return BR_REWRITE_FULL;
}
br_status seq_rewriter::mk_str_to_regexp(expr* a, expr_ref& result) {
return BR_FAILED;
}
br_status seq_rewriter::mk_re_concat(expr* a, expr* b, expr_ref& result) {
if (m_util.re.is_full(a) && m_util.re.is_full(b)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_empty(a)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_empty(b)) {
result = b;
return BR_DONE;
}
if (is_epsilon(a)) {
result = b;
return BR_DONE;
@ -861,6 +888,22 @@ br_status seq_rewriter::mk_re_union(expr* a, expr* b, expr_ref& result) {
result = a;
return BR_DONE;
}
if (m_util.re.is_empty(a)) {
result = b;
return BR_DONE;
}
if (m_util.re.is_empty(b)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_full(a)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_full(b)) {
result = b;
return BR_DONE;
}
if (m_util.re.is_star(a) && is_epsilon(b)) {
result = a;
return BR_DONE;
@ -871,6 +914,32 @@ br_status seq_rewriter::mk_re_union(expr* a, expr* b, expr_ref& result) {
}
return BR_FAILED;
}
br_status seq_rewriter::mk_re_loop(unsigned num_args, expr* const* args, expr_ref& result) {
rational n1, n2;
switch (num_args) {
case 1:
break;
case 2:
if (m_autil.is_numeral(args[1], n1) && n1.is_unsigned()) {
result = m_util.re.mk_loop(args[0], n1.get_unsigned());
return BR_DONE;
}
break;
case 3:
if (m_autil.is_numeral(args[1], n1) && n1.is_unsigned() &&
m_autil.is_numeral(args[2], n2) && n2.is_unsigned()) {
result = m_util.re.mk_loop(args[0], n1.get_unsigned(), n2.get_unsigned());
return BR_DONE;
}
break;
default:
break;
}
return BR_FAILED;
}
/*
a** = a*
(a* + b)* = (a + b)*
@ -879,7 +948,7 @@ br_status seq_rewriter::mk_re_union(expr* a, expr* b, expr_ref& result) {
*/
br_status seq_rewriter::mk_re_star(expr* a, expr_ref& result) {
expr* b, *c, *b1, *c1;
if (m_util.re.is_star(a)) {
if (m_util.re.is_star(a) || m_util.re.is_empty(a) || m_util.re.is_full(a)) {
result = a;
return BR_DONE;
}
@ -1127,7 +1196,6 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
if (set_empty(szr, _rs, true, lhs, rhs)) {
lchange |= szr > 1;
change |= szr > 1;
TRACE("seq", tout << lchange << " " << szr << "\n";);
if (szr == 1 && !lchange) {
lhs.reset();
rhs.reset();
@ -1322,23 +1390,20 @@ bool seq_rewriter::is_subsequence(unsigned szl, expr* const* l, unsigned szr, ex
for (unsigned i = 0; i < szl; ++i) {
bool found = false;
unsigned j = 0;
bool is_unit = m_util.str.is_unit(l[i]);
for (; !found && j < szr; ++j) {
found = !rpos.contains(j) && l[i] == r[j];
found = !rpos.contains(j) && (l[i] == r[j] || (is_unit && m_util.str.is_unit(r[j])));
}
if (!found) {
#if 0
std::cout << mk_pp(l[i], m()) << " not found in ";
for (unsigned j = 0; j < szr; ++j) {
std::cout << mk_pp(r[j], m()) << " ";
}
std::cout << "\n";
#endif
return false;
}
SASSERT(0 < j && j <= szr);
rpos.insert(j-1);
}
// if we reach here, then every element of l is contained in r in some position.
// or each non-unit in l is matched by a non-unit in r, and otherwise, the non-units match up.
bool change = false;
ptr_vector<expr> rs;
for (unsigned j = 0; j < szr; ++j) {
if (rpos.contains(j)) {
@ -1348,6 +1413,12 @@ bool seq_rewriter::is_subsequence(unsigned szl, expr* const* l, unsigned szr, ex
is_sat = false;
return true;
}
else {
change = true;
}
}
if (!change) {
return false;
}
SASSERT(szl == rs.size());
if (szl > 0) {

View file

@ -91,6 +91,7 @@ class seq_rewriter {
br_status mk_re_star(expr* a, expr_ref& result);
br_status mk_re_plus(expr* a, expr_ref& result);
br_status mk_re_opt(expr* a, expr_ref& result);
br_status mk_re_loop(unsigned num_args, expr* const* args, expr_ref& result);
bool set_empty(unsigned sz, expr* const* es, bool all, expr_ref_vector& lhs, expr_ref_vector& rhs);
bool is_subsequence(unsigned n, expr* const* l, unsigned m, expr* const* r,
@ -100,7 +101,7 @@ class seq_rewriter {
bool min_length(unsigned n, expr* const* es, unsigned& len);
expr* concat_non_empty(unsigned n, expr* const* es);
void add_next(u_map<expr*>& next, unsigned idx, expr* cond);
void add_next(u_map<expr*>& next, expr_ref_vector& trail, unsigned idx, expr* cond);
bool is_sequence(expr* e, expr_ref_vector& seq);
bool is_sequence(eautomaton& aut, expr_ref_vector& seq);
bool is_epsilon(expr* e) const;

View file

@ -36,18 +36,55 @@ static bool is_hex_digit(char ch, unsigned& d) {
static bool is_escape_char(char const *& s, unsigned& result) {
unsigned d1, d2;
if (*s == '\\' && *(s + 1) == 'x' &&
if (*s != '\\' || *(s + 1) == 0) {
return false;
}
if (*(s + 1) == 'x' &&
is_hex_digit(*(s + 2), d1) && is_hex_digit(*(s + 3), d2)) {
result = d1*16 + d2;
s += 4;
return true;
}
if (*s == '\\' && *(s + 1) == '\\') {
result = '\\';
switch (*(s + 1)) {
case 'a':
result = '\a';
s += 2;
return true;
case 'b':
result = '\b';
s += 2;
return true;
#if 0
case 'e':
result = '\e';
s += 2;
return true;
#endif
case 'f':
result = '\f';
s += 2;
return true;
case 'n':
result = '\n';
s += 2;
return true;
case 'r':
result = '\r';
s += 2;
return true;
case 't':
result = '\t';
s += 2;
return true;
case 'v':
result = '\v';
s += 2;
return true;
default:
result = *(s + 1);
s += 2;
return true;
}
return false;
}
zstring::zstring(encoding enc): m_encoding(enc) {}
@ -127,9 +164,6 @@ std::string zstring::encode() const {
if (0 <= ch && ch < 32) {
strm << esc_table[ch];
}
else if (ch == 127) {
strm << "^?";
}
else {
strm << (char)(ch);
}
@ -211,13 +245,15 @@ seq_decl_plugin::seq_decl_plugin(): m_init(false),
m_stringc_sym("String"),
m_charc_sym("Char"),
m_string(0),
m_char(0) {}
m_char(0),
m_re(0) {}
void seq_decl_plugin::finalize() {
for (unsigned i = 0; i < m_sigs.size(); ++i)
dealloc(m_sigs[i]);
m_manager->dec_ref(m_string);
m_manager->dec_ref(m_char);
m_manager->dec_ref(m_re);
}
bool seq_decl_plugin::is_sort_param(sort* s, unsigned& idx) {
@ -411,9 +447,9 @@ void seq_decl_plugin::init() {
m_sigs[OP_RE_UNION] = alloc(psig, m, "re.union", 1, 2, reAreA, reA);
m_sigs[OP_RE_INTERSECT] = alloc(psig, m, "re.inter", 1, 2, reAreA, reA);
m_sigs[OP_RE_LOOP] = alloc(psig, m, "re.loop", 1, 1, &reA, reA);
m_sigs[OP_RE_EMPTY_SET] = alloc(psig, m, "re-empty-set", 1, 0, 0, reA);
m_sigs[OP_RE_FULL_SET] = alloc(psig, m, "re-full-set", 1, 0, 0, reA);
m_sigs[OP_RE_OF_PRED] = alloc(psig, m, "re-of-pred", 1, 1, &predA, reA);
m_sigs[OP_RE_EMPTY_SET] = alloc(psig, m, "re.empty", 1, 0, 0, reA);
m_sigs[OP_RE_FULL_SET] = alloc(psig, m, "re.all", 1, 0, 0, reA);
m_sigs[OP_RE_OF_PRED] = alloc(psig, m, "re.of.pred", 1, 1, &predA, reA);
m_sigs[OP_SEQ_TO_RE] = alloc(psig, m, "seq.to.re", 1, 1, &seqA, reA);
m_sigs[OP_SEQ_IN_RE] = alloc(psig, m, "seq.in.re", 1, 2, seqAreA, boolT);
m_sigs[OP_STRING_CONST] = 0;
@ -429,6 +465,8 @@ void seq_decl_plugin::init() {
m_sigs[_OP_STRING_SUFFIX] = alloc(psig, m, "str.suffixof", 0, 2, str2T, boolT);
m_sigs[_OP_STRING_IN_REGEXP] = alloc(psig, m, "str.in.re", 0, 2, strTreT, boolT);
m_sigs[_OP_STRING_TO_REGEXP] = alloc(psig, m, "str.to.re", 0, 1, &strT, reT);
m_sigs[_OP_REGEXP_EMPTY] = alloc(psig, m, "re.nostr", 0, 0, 0, reT);
m_sigs[_OP_REGEXP_FULL] = alloc(psig, m, "re.allchar", 0, 0, 0, reT);
m_sigs[_OP_STRING_SUBSTR] = alloc(psig, m, "str.substr", 0, 3, strTint2T, strT);
}
@ -440,6 +478,9 @@ void seq_decl_plugin::set_manager(ast_manager* m, family_id id) {
parameter param(m_char);
m_string = m->mk_sort(symbol("String"), sort_info(m_family_id, SEQ_SORT, 1, &param));
m->inc_ref(m_string);
parameter paramS(m_string);
m_re = m->mk_sort(m_family_id, RE_SORT, 1, &paramS);
m->inc_ref(m_re);
}
sort * seq_decl_plugin::mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters) {
@ -527,13 +568,40 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
match(*m_sigs[k], arity, domain, range, rng);
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, rng, func_decl_info(m_family_id, k));
case OP_RE_LOOP:
case _OP_REGEXP_FULL:
if (!range) {
range = m_re;
}
match(*m_sigs[k], arity, domain, range, rng);
if (num_parameters != 2 || !parameters[0].is_int() || !parameters[1].is_int()) {
return m.mk_func_decl(symbol("re.allchar"), arity, domain, rng, func_decl_info(m_family_id, OP_RE_FULL_SET));
case _OP_REGEXP_EMPTY:
if (!range) {
range = m_re;
}
match(*m_sigs[k], arity, domain, range, rng);
return m.mk_func_decl(symbol("re.nostr"), arity, domain, rng, func_decl_info(m_family_id, OP_RE_EMPTY_SET));
case OP_RE_LOOP:
switch (arity) {
case 1:
match(*m_sigs[k], arity, domain, range, rng);
if (num_parameters == 0 || num_parameters > 2 || !parameters[0].is_int() || (num_parameters == 2 && !parameters[1].is_int())) {
m.raise_exception("Expecting two numeral parameters to function re-loop");
}
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, rng, func_decl_info(m_family_id, k, num_parameters, parameters));
case 2:
if (m_re != domain[0] || !arith_util(m).is_int(domain[1])) {
m.raise_exception("Incorrect type of arguments passed to re.loop. Expecting regular expression and two integer parameters");
}
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, domain[0], func_decl_info(m_family_id, k, num_parameters, parameters));
case 3:
if (m_re != domain[0] || !arith_util(m).is_int(domain[1]) || !arith_util(m).is_int(domain[2])) {
m.raise_exception("Incorrect type of arguments passed to re.loop. Expecting regular expression and two integer parameters");
}
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, domain[0], func_decl_info(m_family_id, k, num_parameters, parameters));
default:
m.raise_exception("Incorrect number of arguments passed to loop. Expected 1 regular expression and two integer parameters");
}
case OP_STRING_CONST:
@ -722,17 +790,37 @@ void seq_util::str::get_concat(expr* e, expr_ref_vector& es) const {
}
}
app* seq_util::re::mk_loop(expr* r, unsigned lo) {
parameter param(lo);
return m.mk_app(m_fid, OP_RE_LOOP, 1, &param, 1, &r);
}
app* seq_util::re::mk_loop(expr* r, unsigned lo, unsigned hi) {
parameter params[2] = { parameter(lo), parameter(hi) };
return m.mk_app(m_fid, OP_RE_LOOP, 2, params, 1, &r);
}
bool seq_util::re::is_loop(expr const* n, expr*& body, unsigned& lo, unsigned& hi) {
if (is_loop(n)) {
app const* a = to_app(n);
SASSERT(a->get_num_args() == 1);
SASSERT(a->get_decl()->get_num_parameters() == 2);
if (a->get_num_args() == 1 && a->get_decl()->get_num_parameters() == 2) {
body = a->get_arg(0);
lo = a->get_decl()->get_parameter(0).get_int();
hi = a->get_decl()->get_parameter(1).get_int();
return true;
}
else {
}
return false;
}
bool seq_util::re::is_loop(expr const* n, expr*& body, unsigned& lo) {
if (is_loop(n)) {
app const* a = to_app(n);
if (a->get_num_args() == 1 && a->get_decl()->get_num_parameters() == 1) {
body = a->get_arg(0);
lo = a->get_decl()->get_parameter(0).get_int();
return true;
}
}
return false;
}

View file

@ -75,6 +75,8 @@ enum seq_op_kind {
_OP_STRING_CHARAT,
_OP_STRING_SUBSTR,
_OP_STRING_STRIDOF,
_OP_REGEXP_EMPTY,
_OP_REGEXP_FULL,
_OP_SEQ_SKOLEM,
LAST_SEQ_OP
};
@ -134,6 +136,7 @@ class seq_decl_plugin : public decl_plugin {
symbol m_charc_sym;
sort* m_string;
sort* m_char;
sort* m_re;
void match(psig& sig, unsigned dsz, sort* const* dom, sort* range, sort_ref& rng);
@ -295,6 +298,8 @@ public:
app* mk_star(expr* r) { return m.mk_app(m_fid, OP_RE_STAR, r); }
app* mk_plus(expr* r) { return m.mk_app(m_fid, OP_RE_PLUS, r); }
app* mk_opt(expr* r) { return m.mk_app(m_fid, OP_RE_OPTION, r); }
app* mk_loop(expr* r, unsigned lo);
app* mk_loop(expr* r, unsigned lo, unsigned hi);
bool is_to_re(expr const* n) const { return is_app_of(n, m_fid, OP_SEQ_TO_RE); }
bool is_concat(expr const* n) const { return is_app_of(n, m_fid, OP_RE_CONCAT); }
@ -316,7 +321,7 @@ public:
MATCH_UNARY(is_plus);
MATCH_UNARY(is_opt);
bool is_loop(expr const* n, expr*& body, unsigned& lo, unsigned& hi);
bool is_loop(expr const* n, expr*& body, unsigned& lo);
};
str str;
re re;

View file

@ -127,11 +127,11 @@ bool simplifier::get_subst(expr * n, expr_ref & r, proof_ref & p) {
return false;
}
void simplifier::reduce_core(expr * n) {
if (!is_cached(n)) {
void simplifier::reduce_core(expr * n1) {
if (!is_cached(n1)) {
// We do not assume m_todo is empty... So, we store the current size of the todo-stack.
unsigned sz = m_todo.size();
m_todo.push_back(n);
m_todo.push_back(n1);
while (m_todo.size() != sz) {
expr * n = m_todo.back();
if (is_cached(n))
@ -142,6 +142,10 @@ void simplifier::reduce_core(expr * n) {
m_todo.pop_back();
reduce1(n);
}
if (m.canceled()) {
cache_result(n1, n1, 0);
break;
}
}
}
}

View file

@ -543,9 +543,17 @@ private:
void add(move const& mv) {
if (!is_duplicate_cheap(mv)) {
m_delta[mv.src()].push_back(mv);
m_delta_inv[mv.dst()].push_back(mv);
}
}
bool is_duplicate_cheap(move const& mv) const {
if (m_delta[mv.src()].empty()) return false;
move const& mv0 = m_delta[mv.src()].back();
return mv0.src() == mv.src() && mv0.dst() == mv.dst() && mv0.t() == mv.t();
}
unsigned find_move(unsigned src, unsigned dst, T* t, moves const& mvs) {

View file

@ -444,7 +444,9 @@ bool theory_seq::check_length_coherence(expr* e) {
propagate_is_conc(e, conc);
assume_equality(tail, emp);
}
if (!get_context().at_base_level()) {
m_trail_stack.push(push_replay(alloc(replay_length_coherence, m, e)));
}
return true;
}
return false;
@ -583,7 +585,7 @@ void theory_seq::propagate_lit(dependency* dep, unsigned n, literal const* _lits
enode_pair_vector eqs;
linearize(dep, eqs, lits);
TRACE("seq", ctx.display_detailed_literal(tout, lit);
tout << " <- "; ctx.display_literals_verbose(tout, lits.size(), lits.c_ptr()); display_deps(tout, dep););
tout << " <- "; ctx.display_literals_verbose(tout, lits.size(), lits.c_ptr()); if (!lits.empty()) tout << "\n"; display_deps(tout, dep););
justification* js =
ctx.mk_justification(
ext_theory_propagation_justification(
@ -598,7 +600,7 @@ void theory_seq::set_conflict(dependency* dep, literal_vector const& _lits) {
enode_pair_vector eqs;
literal_vector lits(_lits);
linearize(dep, eqs, lits);
TRACE("seq", ctx.display_literals_verbose(tout, lits.size(), lits.c_ptr()); display_deps(tout, dep); ;);
TRACE("seq", ctx.display_literals_verbose(tout, lits.size(), lits.c_ptr()); if (!lits.empty()) tout << "\n"; display_deps(tout, dep); ;);
m_new_propagation = true;
ctx.set_conflict(
ctx.mk_justification(
@ -615,7 +617,7 @@ void theory_seq::propagate_eq(dependency* dep, enode* n1, enode* n2) {
enode_pair_vector eqs;
linearize(dep, eqs, lits);
TRACE("seq",
tout << mk_pp(n1->get_owner(), m) << " = " << mk_pp(n2->get_owner(), m) << " <- ";
tout << mk_pp(n1->get_owner(), m) << " = " << mk_pp(n2->get_owner(), m) << " <- \n";
display_deps(tout, dep);
);
@ -652,7 +654,7 @@ bool theory_seq::simplify_eq(expr_ref_vector& ls, expr_ref_vector& rs, dependenc
expr_ref_vector lhs(m), rhs(m);
bool changed = false;
if (!m_seq_rewrite.reduce_eq(ls, rs, lhs, rhs, changed)) {
// equality is inconsistent.x2
// equality is inconsistent.
TRACE("seq", tout << ls << " != " << rs << "\n";);
set_conflict(deps);
return true;
@ -985,6 +987,10 @@ bool theory_seq::solve_ne(unsigned idx) {
}
else if (!change) {
TRACE("seq", tout << "no change " << n.ls(i) << " " << n.rs(i) << "\n";);
if (updated) {
new_ls.push_back(n.ls(i));
new_rs.push_back(n.rs(i));
}
continue;
}
else {
@ -1195,7 +1201,7 @@ void theory_seq::display(std::ostream & out) const {
void theory_seq::display_equations(std::ostream& out) const {
for (unsigned i = 0; i < m_eqs.size(); ++i) {
eq const& e = m_eqs[i];
out << e.ls() << " = " << e.rs() << " <- ";
out << e.ls() << " = " << e.rs() << " <- \n";
display_deps(out, e.dep());
}
}
@ -1229,14 +1235,14 @@ void theory_seq::display_deps(std::ostream& out, dependency* dep) const {
enode_pair_vector eqs;
linearize(dep, eqs, lits);
for (unsigned i = 0; i < eqs.size(); ++i) {
out << "\n " << mk_pp(eqs[i].first->get_owner(), m) << " = " << mk_pp(eqs[i].second->get_owner(), m);
out << " " << mk_pp(eqs[i].first->get_owner(), m) << " = " << mk_pp(eqs[i].second->get_owner(), m) << "\n";
}
for (unsigned i = 0; i < lits.size(); ++i) {
literal lit = lits[i];
get_context().display_literals_verbose(out << "\n ", 1, &lit);
}
get_context().display_literals_verbose(out << " ", 1, &lit);
out << "\n";
}
}
void theory_seq::collect_statistics(::statistics & st) const {
st.update("seq num splits", m_stats.m_num_splits);
@ -1534,7 +1540,7 @@ void theory_seq::propagate() {
}
while (!m_replay.empty() && !ctx.inconsistent()) {
(*m_replay[m_replay.size()-1])(*this);
TRACE("seq", tout << "replay: " << ctx.get_scope_level() << "\n";);
TRACE("seq", tout << "replay at level: " << ctx.get_scope_level() << "\n";);
m_replay.pop_back();
}
if (m_new_solution) {
@ -1716,6 +1722,7 @@ void theory_seq::add_elim_string_axiom(expr* n) {
- len(x) >= 0 otherwise
*/
void theory_seq::add_length_axiom(expr* n) {
context& ctx = get_context();
expr* x;
VERIFY(m_util.str.is_length(n, x));
if (m_util.str.is_concat(x) ||
@ -1726,14 +1733,17 @@ void theory_seq::add_length_axiom(expr* n) {
m_rewrite(len);
SASSERT(n != len);
add_axiom(mk_eq(len, n, false));
if (!ctx.at_base_level()) {
m_trail_stack.push(push_replay(alloc(replay_axiom, m, n)));
}
}
else {
add_axiom(mk_literal(m_autil.mk_ge(n, m_autil.mk_int(0))));
if (!ctx.at_base_level()) {
m_trail_stack.push(push_replay(alloc(replay_axiom, m, n)));
}
}
}
@ -2198,6 +2208,7 @@ void theory_seq::new_diseq_eh(theory_var v1, theory_var v2) {
expr_ref eq(m.mk_eq(e1, e2), m);
m_rewrite(eq);
if (!m.is_false(eq)) {
TRACE("seq", tout << "new disequality: " << eq << "\n";);
literal lit = ~mk_eq(e1, e2, false);
//SASSERT(get_context().get_assignment(lit) == l_true);
dependency* dep = m_dm.mk_leaf(assumption(lit));