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:
commit
09dc5cd0f8
118 changed files with 2238 additions and 5701 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -526,7 +526,7 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
}
|
||||
pp.display(out, m.mk_true());
|
||||
pp.display_smt2(out, m.mk_true());
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue