3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-27 05:26:01 +00:00

Merge branch 'develop' into regex-develop

This commit is contained in:
Murphy Berzish 2018-01-03 16:12:33 -05:00
commit 09dc5cd0f8
118 changed files with 2238 additions and 5701 deletions

View file

@ -131,6 +131,7 @@ void asserted_formulas::set_eliminate_and(bool flag) {
p.set_bool("gcd_rounding", true);
p.set_bool("expand_select_store", true);
p.set_bool("bv_sort_ac", true);
p.set_bool("som", true);
m_rewriter.updt_params(p);
flush_cache();
}

View file

@ -188,7 +188,7 @@ namespace smt {
1) Variables: (f ... X ...)
2) Ground terms: (f ... t ...)
3) depth 2 joint: (f ... (g ... X ...) ...)
Joint2 stores the declartion g, and the position of variable X, and its idx.
Joint2 stores the declaration g, and the position of variable X, and its idx.
\remark Z3 has no support for depth 3 joints (f ... (g ... (h ... X ...) ...) ....)
*/
@ -211,7 +211,7 @@ namespace smt {
approx_set m_lbl_set; // singleton set containing m_label
/*
The following field is an array of tagged pointers.
Each positon contains:
Each position contains:
1- null (no joint), NULL_TAG
2- a boxed integer (i.e., register that contains the variable bind) VAR_TAG
3- an enode pointer (ground term) GROUND_TERM_TAG

View file

@ -74,7 +74,7 @@ def_module_params(module_name='smt',
('str.fast_length_tester_cache', BOOL, False, 'cache length tester constants instead of regenerating them'),
('str.fast_value_tester_cache', BOOL, True, 'cache value tester constants instead of regenerating them'),
('str.string_constant_cache', BOOL, True, 'cache all generated string constants generated from anywhere in theory_str'),
('str.use_binary_search', BOOL, True, 'use a binary search heuristic for finding concrete length values for free variables in theory_str (set to False to use linear search)'),
('str.use_binary_search', BOOL, False, 'use a binary search heuristic for finding concrete length values for free variables in theory_str (set to False to use linear search)'),
('str.binary_search_start', UINT, 64, 'initial upper bound for theory_str binary search'),
('theory_aware_branching', BOOL, False, 'Allow the context to use extra information from theory solvers regarding literal branching prioritization.'),
('str.finite_overlap_models', BOOL, False, 'attempt a finite model search for overlapping variables instead of completely giving up on the arrangement'),

View file

@ -3202,10 +3202,8 @@ namespace smt {
});
validate_unsat_core();
// theory validation of unsat core
ptr_vector<theory>::iterator th_it = m_theory_set.begin();
ptr_vector<theory>::iterator th_end = m_theory_set.end();
for (; th_it != th_end; ++th_it) {
lbool theory_result = (*th_it)->validate_unsat_core(m_unsat_core);
for (theory* th : m_theory_set) {
lbool theory_result = th->validate_unsat_core(m_unsat_core);
if (theory_result == l_undef) {
return l_undef;
}
@ -3296,10 +3294,8 @@ namespace smt {
#ifndef _EXTERNAL_RELEASE
if (m_fparams.m_display_installed_theories) {
std::cout << "(theories";
ptr_vector<theory>::iterator it = m_theory_set.begin();
ptr_vector<theory>::iterator end = m_theory_set.end();
for (; it != end; ++it) {
std::cout << " " << (*it)->get_name();
for (theory* th : m_theory_set) {
std::cout << " " << th->get_name();
}
std::cout << ")" << std::endl;
}
@ -3316,17 +3312,13 @@ namespace smt {
m_fparams.m_relevancy_lemma = false;
// setup all the theories
ptr_vector<theory>::iterator it = m_theory_set.begin();
ptr_vector<theory>::iterator end = m_theory_set.end();
for (; it != end; ++it)
(*it)->setup();
for (theory* th : m_theory_set)
th->setup();
}
void context::add_theory_assumptions(expr_ref_vector & theory_assumptions) {
ptr_vector<theory>::iterator it = m_theory_set.begin();
ptr_vector<theory>::iterator end = m_theory_set.end();
for (; it != end; ++it) {
(*it)->add_theory_assumptions(theory_assumptions);
for (theory* th : m_theory_set) {
th->add_theory_assumptions(theory_assumptions);
}
}
@ -3342,18 +3334,7 @@ namespace smt {
if (!check_preamble(reset_cancel))
return l_undef;
expr_ref_vector all_assumptions(m_manager, ext_num_assumptions, ext_assumptions);
if (!already_did_theory_assumptions) {
add_theory_assumptions(all_assumptions);
}
unsigned num_assumptions = all_assumptions.size();
expr * const * assumptions = all_assumptions.c_ptr();
if (!validate_assumptions(num_assumptions, assumptions))
return l_undef;
TRACE("check_bug", tout << "inconsistent: " << inconsistent() << ", m_unsat_core.empty(): " << m_unsat_core.empty() << "\n";);
TRACE("unsat_core_bug", for (unsigned i = 0; i < num_assumptions; i++) { tout << mk_pp(assumptions[i], m_manager) << "\n";});
pop_to_base_lvl();
TRACE("before_search", display(tout););
SASSERT(at_base_level());
@ -3363,6 +3344,18 @@ namespace smt {
}
else {
setup_context(false);
expr_ref_vector all_assumptions(m_manager, ext_num_assumptions, ext_assumptions);
if (!already_did_theory_assumptions) {
add_theory_assumptions(all_assumptions);
}
unsigned num_assumptions = all_assumptions.size();
expr * const * assumptions = all_assumptions.c_ptr();
if (!validate_assumptions(num_assumptions, assumptions))
return l_undef;
TRACE("unsat_core_bug", tout << all_assumptions << "\n";);
internalize_assertions();
TRACE("after_internalize_assertions", display(tout););
if (m_asserted_formulas.inconsistent()) {
@ -3551,10 +3544,9 @@ namespace smt {
pop_scope(m_scope_lvl - curr_lvl);
SASSERT(at_search_level());
}
ptr_vector<theory>::iterator it = m_theory_set.begin();
ptr_vector<theory>::iterator end = m_theory_set.end();
for (; it != end && !inconsistent(); ++it)
(*it)->restart_eh();
for (theory* th : m_theory_set) {
if (!inconsistent()) th->restart_eh();
}
TRACE("mbqi_bug_detail", tout << "before instantiating quantifiers...\n";);
if (!inconsistent()) {
m_qmanager->restart_eh();
@ -4070,10 +4062,7 @@ namespace smt {
bool include = false;
if (at_lbls) {
// include if there is a label with the '@' sign.
buffer<symbol>::const_iterator it = lbls.begin();
buffer<symbol>::const_iterator end = lbls.end();
for (; it != end; ++it) {
symbol const & s = *it;
for (symbol const& s : lbls) {
if (s.contains('@')) {
include = true;
break;

View file

@ -369,7 +369,7 @@ namespace smt {
else {
TRACE("internalize_bug", tout << "creating enode for #" << n->get_id() << "\n";);
mk_enode(to_app(n),
true, /* supress arguments, we not not use CC for this kind of enode */
true, /* suppress arguments, we not not use CC for this kind of enode */
true, /* bool enode must be merged with true/false, since it is not in the context of a gate */
false /* CC is not enabled */ );
set_enode_flag(v, false);
@ -453,7 +453,7 @@ namespace smt {
// must be associated with an enode.
if (!e_internalized(n)) {
mk_enode(to_app(n),
true, /* supress arguments, we not not use CC for this kind of enode */
true, /* suppress arguments, we not not use CC for this kind of enode */
true /* bool enode must be merged with true/false, since it is not in the context of a gate */,
false /* CC is not enabled */);
}
@ -739,7 +739,7 @@ namespace smt {
app_ref eq1(mk_eq_atom(n, t), m_manager);
app_ref eq2(mk_eq_atom(n, e), m_manager);
mk_enode(n,
true /* supress arguments, I don't want to apply CC on ite terms */,
true /* suppress arguments, I don't want to apply CC on ite terms */,
false /* it is a term, so it should not be merged with true/false */,
false /* CC is not enabled */);
internalize(c, true);
@ -797,7 +797,7 @@ namespace smt {
}
enode * e = mk_enode(n,
false, /* do not supress args */
false, /* do not suppress args */
false, /* it is a term, so it should not be merged with true/false */
true);
apply_sort_cnstr(n, e);
@ -1506,7 +1506,7 @@ namespace smt {
relevancy_eh * eh = m_relevancy_propagator->mk_and_relevancy_eh(n);
unsigned num = n->get_num_args();
for (unsigned i = 0; i < num; i++) {
// if one child is assigned to false, the the and-parent must be notified
// if one child is assigned to false, the and-parent must be notified
literal l = get_literal(n->get_arg(i));
add_rel_watch(~l, eh);
}
@ -1518,7 +1518,7 @@ namespace smt {
relevancy_eh * eh = m_relevancy_propagator->mk_or_relevancy_eh(n);
unsigned num = n->get_num_args();
for (unsigned i = 0; i < num; i++) {
// if one child is assigned to true, the the or-parent must be notified
// if one child is assigned to true, the or-parent must be notified
literal l = get_literal(n->get_arg(i));
add_rel_watch(l, eh);
}

View file

@ -537,7 +537,7 @@ namespace smt {
}
}
// For each instantiation_set, reemove entries that do not evaluate to values.
// For each instantiation_set, remove entries that do not evaluate to values.
void cleanup_instantiation_sets() {
ptr_vector<expr> to_delete;
for (node * curr : m_nodes) {
@ -735,7 +735,7 @@ namespace smt {
}
}
// TBD: add support for the else of bitvectors.
// Idea: get the term t with the minimal interpreation and use t - 1.
// Idea: get the term t with the minimal interpretation and use t - 1.
}
n->set_else((*(elems.begin())).m_key);
}
@ -955,7 +955,7 @@ namespace smt {
if (elems.empty()) {
// The method get_some_value cannot be used if n->get_sort() is an uninterpreted sort or is a sort built using uninterpreted sorts
// (e.g., (Array S S) where S is uninterpreted). The problem is that these sorts do not have a fixed interpretation.
// Moreover, a model assigns an arbitrary intepretation to these sorts using "model_values" a model value.
// Moreover, a model assigns an arbitrary interpretation to these sorts using "model_values" a model value.
// If these module values "leak" inside the logical context, they may affect satisfiability.
//
sort * ns = n->get_sort();
@ -1007,7 +1007,7 @@ namespace smt {
This may happen because the evaluator uses model_completion.
In the beginning of fix_model() we collected all f with
partial interpretations. During the process of computing the
projections we used the evalutator with model_completion,
projections we used the evaluator with model_completion,
and it may have fixed the "else" case of some partial interpretations.
This is ok, because in the "limit" the "else" of the interpretation
is irrelevant after the projections are applied.
@ -1570,7 +1570,7 @@ namespace smt {
ast_manager & m = ctx->get_manager();
sort * s = q->get_decl_sort(num_vars - m_var_i - 1);
if (m.is_uninterp(s)) {
// For uninterpreted sorst, we add all terms in the context.
// For uninterpreted sorts, we add all terms in the context.
// See Section 4.1 in the paper "Complete Quantifier Instantiation"
node * S_q_i = slv.get_uvar(q, m_var_i);
ptr_vector<enode>::const_iterator it = ctx->begin_enodes();
@ -1741,7 +1741,7 @@ namespace smt {
if (has_quantifiers(q->get_expr())) {
static bool displayed_flat_msg = false;
if (!displayed_flat_msg) {
// [Leo]: This warning message is not usefult.
// [Leo]: This warning message is not useful.
// warning_msg("For problems containing quantifiers, the model finding capabilities of Z3 work better when the formula does not contain nested quantifiers. You can use PULL_NESTED_QUANTIFIERS=true to eliminate nested quantifiers.");
displayed_flat_msg = true;
}
@ -2104,7 +2104,7 @@ namespace smt {
}
/**
\brief Process unintrepreted applications.
\brief Process uninterpreted applications.
*/
void process_u_app(app * t) {
unsigned num_args = t->get_num_args();
@ -2130,7 +2130,7 @@ namespace smt {
/**
\brief A term \c t is said to be a auf_select if
it is of ther form
it is of the form
(select a i) Where:
@ -2151,7 +2151,7 @@ namespace smt {
}
/**
\brief Process intrepreted applications.
\brief Process interpreted applications.
*/
void process_i_app(app * t) {
if (is_auf_select(t)) {
@ -2272,10 +2272,9 @@ namespace smt {
process_literal(atom, pol == NEG);
}
void process_or(app * n, polarity p) {
unsigned num_args = n->get_num_args();
for (unsigned i = 0; i < num_args; i++)
visit_formula(n->get_arg(i), p);
void process_and_or(app * n, polarity p) {
for (expr* arg : *n)
visit_formula(arg, p);
}
void process_ite(app * n, polarity p) {
@ -2306,13 +2305,13 @@ namespace smt {
if (is_app(curr)) {
if (to_app(curr)->get_family_id() == m_manager.get_basic_family_id() && m_manager.is_bool(curr)) {
switch (static_cast<basic_op_kind>(to_app(curr)->get_decl_kind())) {
case OP_AND:
case OP_IMPLIES:
case OP_XOR:
UNREACHABLE(); // simplifier eliminated ANDs, IMPLIEs, and XORs
break;
case OP_OR:
process_or(to_app(curr), pol);
case OP_AND:
process_and_or(to_app(curr), pol);
break;
case OP_NOT:
visit_formula(to_app(curr)->get_arg(0), neg(pol));
@ -2513,7 +2512,7 @@ namespace smt {
SASSERT(f_else != 0);
// Remark: I can ignore the conditions of m because
// I know the (partial) interpretation of f satisfied the ground part.
// MBQI will force extra instantiations if the the (partial) interpretation of f
// MBQI will force extra instantiations if the (partial) interpretation of f
// does not satisfy the quantifier.
// In all other cases the "else" of f will satisfy the quantifier.
set_else_interp(f, f_else);
@ -2938,7 +2937,7 @@ namespace smt {
}
/**
\brief Use m_fs to set the interpreation of the function symbols that were used to satisfy the
\brief Use m_fs to set the interpretation of the function symbols that were used to satisfy the
quantifiers in m_satisfied.
*/
void set_interp() {

View file

@ -152,7 +152,7 @@ namespace smt {
virtual bool mbqi_enabled(quantifier *q) const {return true;}
/**
\brief Give a change to the plugin to adjust the interpretation of unintepreted functions.
\brief Give a change to the plugin to adjust the interpretation of uninterpreted functions.
It can basically change the "else" of each uninterpreted function.
*/
virtual void adjust_model(proto_model * m) = 0;

View file

@ -968,7 +968,7 @@ namespace smt {
if (st.num_theories() == 2 && st.has_uf() && is_arith(st)) {
if (!st.m_has_real)
setup_QF_UFLIA(st);
else if (!st.m_has_int)
else if (!st.m_has_int && st.m_num_non_linear == 0)
setup_QF_UFLRA();
else
setup_unknown();

View file

@ -660,7 +660,7 @@ namespace smt {
satisfy their respective constraints. However, when they
do that the may create inconsistencies in the other
modules. I use m_liberal_final_check to avoid infinite
loops where the modules keep changing the assigment and no
loops where the modules keep changing the assignment and no
progress is made. If m_liberal_final_check is set to false,
these modules will avoid mutating the assignment to satisfy
constraints.

View file

@ -711,6 +711,7 @@ namespace smt {
if (ctx.is_relevant(get_enode(*it)) && !check_monomial_assignment(*it, computed_epsilon)) {
TRACE("non_linear_failed", tout << "check_monomial_assignment failed for:\n" << mk_ismt2_pp(var2expr(*it), get_manager()) << "\n";
display_var(tout, *it););
return false;
}
}

View file

@ -526,7 +526,7 @@ namespace smt {
}
}
}
pp.display(out, m.mk_true());
pp.display_smt2(out, m.mk_true());
}
template<typename Ext>

View file

@ -1916,7 +1916,7 @@ namespace smt {
lp::var_index vi = m_theory_var2var_index[v];
SASSERT(m_solver->is_term(vi));
lp::lar_term const& term = m_solver->get_term(vi);
for (auto const coeff : term.m_coeffs) {
for (auto const& coeff : term.m_coeffs) {
lp::var_index wi = coeff.first;
lp::constraint_index ci;
rational value;

View file

@ -397,15 +397,13 @@ bool theory_seq::branch_binary_variable(eq const& e) {
expr_ref Y1(mk_skolem(symbol("seq.left"), x, y), m);
expr_ref Y2(mk_skolem(symbol("seq.right"), x, y), m);
ys.push_back(Y1);
expr_ref ysY1(m_util.str.mk_concat(ys.size(), ys.c_ptr()), m);
expr_ref xsE(m_util.str.mk_concat(xs.size(), xs.c_ptr()), m);
expr_ref Y1Y2(m_util.str.mk_concat(Y1, Y2), m);
literal_vector lits;
lits.push_back(~lit);
expr_ref ysY1(mk_concat(ys));
expr_ref xsE(mk_concat(xs));
expr_ref Y1Y2(mk_concat(Y1, Y2));
dependency* dep = e.dep();
propagate_eq(dep, lits, x, ysY1, true);
propagate_eq(dep, lits, y, Y1Y2, true);
propagate_eq(dep, lits, Y2, xsE, true);
propagate_eq(dep, ~lit, x, ysY1);
propagate_eq(dep, ~lit, y, Y1Y2);
propagate_eq(dep, ~lit, Y2, xsE);
}
else {
ctx.mark_as_relevant(lit);
@ -471,9 +469,7 @@ void theory_seq::branch_unit_variable(dependency* dep, expr* X, expr_ref_vector
literal lit = mk_eq(m_autil.mk_int(lX), m_util.str.mk_length(X), false);
if (l_true == ctx.get_assignment(lit)) {
expr_ref R(m_util.str.mk_concat(lX, units.c_ptr()), m);
literal_vector lits;
lits.push_back(lit);
propagate_eq(dep, lits, X, R, true);
propagate_eq(dep, lit, X, R);
TRACE("seq", tout << "propagate " << mk_pp(X, m) << " " << R << "\n";);
}
else {
@ -506,11 +502,10 @@ bool theory_seq::branch_variable_mb() {
for (unsigned j = 0; j < len2.size(); ++j) l2 += len2[j];
if (l1 != l2) {
TRACE("seq", tout << "lengths are not compatible\n";);
expr_ref l = mk_concat(e.ls().size(), e.ls().c_ptr());
expr_ref r = mk_concat(e.rs().size(), e.rs().c_ptr());
expr_ref l = mk_concat(e.ls());
expr_ref r = mk_concat(e.rs());
expr_ref lnl(m_util.str.mk_length(l), m), lnr(m_util.str.mk_length(r), m);
literal_vector lits;
propagate_eq(e.dep(), lits, lnl, lnr, false);
propagate_eq(e.dep(), lnl, lnr, false);
change = true;
continue;
}
@ -626,8 +621,8 @@ bool theory_seq::split_lengths(dependency* dep,
SASSERT(is_var(Y));
expr_ref Y1(mk_skolem(symbol("seq.left"), X, b, Y), m);
expr_ref Y2(mk_skolem(symbol("seq.right"), X, b, Y), m);
expr_ref bY1(m_util.str.mk_concat(b, Y1), m);
expr_ref Y1Y2(m_util.str.mk_concat(Y1, Y2), m);
expr_ref bY1 = mk_concat(b, Y1);
expr_ref Y1Y2 = mk_concat(Y1, Y2);
propagate_eq(dep, lits, X, bY1, true);
propagate_eq(dep, lits, Y, Y1Y2, true);
}
@ -1317,6 +1312,18 @@ void theory_seq::propagate_eq(dependency* dep, enode* n1, enode* n2) {
enforce_length_coherence(n1, n2);
}
void theory_seq::propagate_eq(dependency* dep, expr* e1, expr* e2, bool add_eq) {
literal_vector lits;
propagate_eq(dep, lits, e1, e2, add_eq);
}
void theory_seq::propagate_eq(dependency* dep, literal lit, expr* e1, expr* e2, bool add_to_eqs) {
literal_vector lits;
lits.push_back(lit);
propagate_eq(dep, lits, e1, e2, add_to_eqs);
}
void theory_seq::enforce_length_coherence(enode* n1, enode* n2) {
expr* o1 = n1->get_owner();
expr* o2 = n2->get_owner();
@ -1662,19 +1669,18 @@ bool theory_seq::reduce_length(unsigned i, unsigned j, bool front, expr_ref_vect
}
SASSERT(0 < l1 && l1 < ls.size());
SASSERT(0 < r1 && r1 < rs.size());
expr_ref l(m_util.str.mk_concat(l1, ls1), m);
expr_ref r(m_util.str.mk_concat(r1, rs1), m);
expr_ref l = mk_concat(l1, ls1);
expr_ref r = mk_concat(r1, rs1);
expr_ref lenl(m_util.str.mk_length(l), m);
expr_ref lenr(m_util.str.mk_length(r), m);
literal lit = mk_eq(lenl, lenr, false);
if (ctx.get_assignment(lit) == l_true) {
literal_vector lits;
expr_ref_vector lhs(m), rhs(m);
lhs.append(l2, ls2);
rhs.append(r2, rs2);
deps = mk_join(deps, lit);
m_eqs.push_back(eq(m_eq_id++, lhs, rhs, deps));
propagate_eq(deps, lits, l, r, true);
propagate_eq(deps, l, r, true);
TRACE("seq", tout << "propagate eq\nlhs: " << lhs << "\nrhs: " << rhs << "\n";);
return true;
}
@ -3212,9 +3218,10 @@ void theory_seq::add_indexof_axiom(expr* i) {
literal t_eq_empty = mk_eq_empty(t);
// |t| = 0 => |s| = 0 or indexof(t,s,offset) = -1
// ~contains(t,s) => indexof(t,s,offset) = -1
// ~contains(t,s) <=> indexof(t,s,offset) = -1
add_axiom(cnt, i_eq_m1);
// add_axiom(~cnt, ~i_eq_m1);
add_axiom(~t_eq_empty, s_eq_empty, i_eq_m1);
if (!offset || (m_autil.is_numeral(offset, r) && r.is_zero())) {
@ -3227,6 +3234,7 @@ void theory_seq::add_indexof_axiom(expr* i) {
add_axiom(~s_eq_empty, i_eq_0);
add_axiom(~cnt, s_eq_empty, mk_seq_eq(t, xsy));
add_axiom(~cnt, s_eq_empty, mk_eq(i, lenx, false));
add_axiom(~cnt, mk_literal(m_autil.mk_ge(i, zero)));
tightest_prefix(s, x);
}
else {
@ -3661,7 +3669,6 @@ void theory_seq::add_extract_axiom(expr* e) {
literal ls_le_i = mk_simplified_literal(m_autil.mk_le(mk_sub(i, ls), zero));
literal li_ge_ls = mk_simplified_literal(m_autil.mk_ge(ls_minus_i_l, zero));
literal l_ge_zero = mk_simplified_literal(m_autil.mk_ge(l, zero));
literal l_le_zero = mk_simplified_literal(m_autil.mk_le(l, zero));
literal ls_le_0 = mk_simplified_literal(m_autil.mk_le(ls, zero));
add_axiom(~i_ge_0, ~ls_le_i, mk_seq_eq(xey, s));

View file

@ -410,6 +410,8 @@ namespace smt {
expr_ref mk_empty(sort* s) { return expr_ref(m_util.str.mk_empty(s), m); }
expr_ref mk_concat(unsigned n, expr*const* es) { return expr_ref(m_util.str.mk_concat(n, es), m); }
expr_ref mk_concat(expr_ref_vector const& es, sort* s) { if (es.empty()) return mk_empty(s); return mk_concat(es.size(), es.c_ptr()); }
expr_ref mk_concat(expr_ref_vector const& es) { SASSERT(!es.empty()); return mk_concat(es.size(), es.c_ptr()); }
expr_ref mk_concat(ptr_vector<expr> const& es) { SASSERT(!es.empty()); return mk_concat(es.size(), es.c_ptr()); }
expr_ref mk_concat(expr* e1, expr* e2) { return expr_ref(m_util.str.mk_concat(e1, e2), m); }
expr_ref mk_concat(expr* e1, expr* e2, expr* e3) { return expr_ref(m_util.str.mk_concat(e1, e2, e3), m); }
bool solve_nqs(unsigned i);
@ -436,7 +438,9 @@ namespace smt {
void propagate_lit(dependency* dep, unsigned n, literal const* lits, literal lit);
void propagate_eq(dependency* dep, enode* n1, enode* n2);
void propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs);
void propagate_eq(dependency* dep, literal_vector const& lits, expr* e1, expr* e2, bool add_to_eqs);
void propagate_eq(dependency* dep, literal_vector const& lits, expr* e1, expr* e2, bool add_to_eqs = true);
void propagate_eq(dependency* dep, expr* e1, expr* e2, bool add_to_eqs = true);
void propagate_eq(dependency* dep, literal lit, expr* e1, expr* e2, bool add_to_eqs = true);
void set_conflict(dependency* dep, literal_vector const& lits = literal_vector());
u_map<unsigned> m_branch_start;

View file

@ -1474,7 +1474,7 @@ namespace smt {
// pos < strlen(base)
// --> pos + -1*strlen(base) < 0
argumentsValid_terms.push_back(mk_not(m, m_autil.mk_ge(
m_autil.mk_add(substrPos, m_autil.mk_mul(minusOne, substrLen)),
m_autil.mk_add(substrPos, m_autil.mk_mul(minusOne, mk_strlen(substrBase))),
zero)));
// len >= 0