mirror of
https://github.com/Z3Prover/z3
synced 2025-06-11 08:33:25 +00:00
Merge branch 'master' of https://github.com/z3prover/z3
This commit is contained in:
commit
edb26e7be7
15 changed files with 63 additions and 37 deletions
|
@ -599,6 +599,7 @@ namespace z3 {
|
||||||
iterator begin() const noexcept { return iterator(this, 0); }
|
iterator begin() const noexcept { return iterator(this, 0); }
|
||||||
iterator end() const { return iterator(this, size()); }
|
iterator end() const { return iterator(this, size()); }
|
||||||
friend std::ostream & operator<<(std::ostream & out, ast_vector_tpl const & v) { out << Z3_ast_vector_to_string(v.ctx(), v); return out; }
|
friend std::ostream & operator<<(std::ostream & out, ast_vector_tpl const & v) { out << Z3_ast_vector_to_string(v.ctx(), v); return out; }
|
||||||
|
std::string to_string() const { return std::string(Z3_ast_vector_to_string(ctx(), m_vector)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ void array_rewriter::updt_params(params_ref const & _p) {
|
||||||
m_expand_store_eq = p.expand_store_eq();
|
m_expand_store_eq = p.expand_store_eq();
|
||||||
m_expand_nested_stores = p.expand_nested_stores();
|
m_expand_nested_stores = p.expand_nested_stores();
|
||||||
m_blast_select_store = p.blast_select_store();
|
m_blast_select_store = p.blast_select_store();
|
||||||
m_expand_select_ite = false;
|
m_expand_select_ite = p.expand_select_ite();
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_rewriter::get_param_descrs(param_descrs & r) {
|
void array_rewriter::get_param_descrs(param_descrs & r) {
|
||||||
|
@ -226,8 +226,7 @@ br_status array_rewriter::mk_select_core(unsigned num_args, expr * const * args,
|
||||||
result = subst(q->get_expr(), _args.size(), _args.data());
|
result = subst(q->get_expr(), _args.size(), _args.data());
|
||||||
inv_var_shifter invsh(m());
|
inv_var_shifter invsh(m());
|
||||||
invsh(result, _args.size(), result);
|
invsh(result, _args.size(), result);
|
||||||
return BR_REWRITE_FULL;
|
return BR_REWRITE_FULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_util.is_map(args[0])) {
|
if (m_util.is_map(args[0])) {
|
||||||
|
@ -698,7 +697,7 @@ br_status array_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result)
|
||||||
if (m_util.is_const(lhs, v) && m_util.is_store(rhs)) {
|
if (m_util.is_const(lhs, v) && m_util.is_store(rhs)) {
|
||||||
unsigned n = to_app(rhs)->get_num_args();
|
unsigned n = to_app(rhs)->get_num_args();
|
||||||
result = m().mk_and(m().mk_eq(lhs, to_app(rhs)->get_arg(0)),
|
result = m().mk_and(m().mk_eq(lhs, to_app(rhs)->get_arg(0)),
|
||||||
m().mk_eq(v, to_app(rhs)->get_arg(n - 1)));
|
m().mk_eq(v, to_app(rhs)->get_arg(n - 1)));
|
||||||
return BR_REWRITE2;
|
return BR_REWRITE2;
|
||||||
}
|
}
|
||||||
if (m_util.is_const(lhs, v) && m_util.is_const(rhs, w)) {
|
if (m_util.is_const(lhs, v) && m_util.is_const(rhs, w)) {
|
||||||
|
|
|
@ -4,5 +4,6 @@ def_module_params(module_name='rewriter',
|
||||||
params=(("expand_select_store", BOOL, False, "conservatively replace a (select (store ...) ...) term by an if-then-else term"),
|
params=(("expand_select_store", BOOL, False, "conservatively replace a (select (store ...) ...) term by an if-then-else term"),
|
||||||
("blast_select_store", BOOL, False, "eagerly replace all (select (store ..) ..) term by an if-then-else term"),
|
("blast_select_store", BOOL, False, "eagerly replace all (select (store ..) ..) term by an if-then-else term"),
|
||||||
("expand_nested_stores", BOOL, False, "replace nested stores by a lambda expression"),
|
("expand_nested_stores", BOOL, False, "replace nested stores by a lambda expression"),
|
||||||
|
("expand_select_ite", BOOL, False, "expand select over ite expressions"),
|
||||||
("expand_store_eq", BOOL, False, "reduce (store ...) = (store ...) with a common base into selects"),
|
("expand_store_eq", BOOL, False, "reduce (store ...) = (store ...) with a common base into selects"),
|
||||||
("sort_store", BOOL, False, "sort nested stores when the indices are known to be different")))
|
("sort_store", BOOL, False, "sort nested stores when the indices are known to be different")))
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace arith {
|
||||||
void solver::init_internalize() {
|
void solver::init_internalize() {
|
||||||
force_push();
|
force_push();
|
||||||
// initialize 0, 1 variables:
|
// initialize 0, 1 variables:
|
||||||
|
|
||||||
if (!m_internalize_initialized) {
|
if (!m_internalize_initialized) {
|
||||||
get_one(true);
|
get_one(true);
|
||||||
get_one(false);
|
get_one(false);
|
||||||
|
@ -484,10 +485,10 @@ namespace arith {
|
||||||
return st.vars()[0];
|
return st.vars()[0];
|
||||||
}
|
}
|
||||||
else if (is_one(st) && a.is_numeral(term)) {
|
else if (is_one(st) && a.is_numeral(term)) {
|
||||||
return get_one(a.is_int(term));
|
return lp().local_to_external(get_one(a.is_int(term)));
|
||||||
}
|
}
|
||||||
else if (is_zero(st) && a.is_numeral(term)) {
|
else if (is_zero(st) && a.is_numeral(term)) {
|
||||||
return get_zero(a.is_int(term));
|
return lp().local_to_external(get_zero(a.is_int(term)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
init_left_side(st);
|
init_left_side(st);
|
||||||
|
|
|
@ -451,6 +451,7 @@ namespace array {
|
||||||
expr_ref alpha(a.mk_select(args), m);
|
expr_ref alpha(a.mk_select(args), m);
|
||||||
expr_ref beta(alpha);
|
expr_ref beta(alpha);
|
||||||
rewrite(beta);
|
rewrite(beta);
|
||||||
|
TRACE("array", tout << alpha << " == " << beta << "\n";);
|
||||||
return ctx.propagate(e_internalize(alpha), e_internalize(beta), array_axiom());
|
return ctx.propagate(e_internalize(alpha), e_internalize(beta), array_axiom());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -342,7 +342,9 @@ namespace euf {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (m.is_bool(n->get_expr()) && th_id != m.get_basic_family_id())
|
||||||
|
return true;
|
||||||
|
|
||||||
for (enode* parent : euf::enode_parents(n)) {
|
for (enode* parent : euf::enode_parents(n)) {
|
||||||
app* p = to_app(parent->get_expr());
|
app* p = to_app(parent->get_expr());
|
||||||
family_id fid = p->get_family_id();
|
family_id fid = p->get_family_id();
|
||||||
|
|
|
@ -300,7 +300,7 @@ namespace euf {
|
||||||
size_t* c = to_ptr(l);
|
size_t* c = to_ptr(l);
|
||||||
SASSERT(is_literal(c));
|
SASSERT(is_literal(c));
|
||||||
SASSERT(l == get_literal(c));
|
SASSERT(l == get_literal(c));
|
||||||
if (n->value_conflict()) {
|
if (n->value_conflict()) {
|
||||||
euf::enode* nb = sign ? mk_false() : mk_true();
|
euf::enode* nb = sign ? mk_false() : mk_true();
|
||||||
euf::enode* r = n->get_root();
|
euf::enode* r = n->get_root();
|
||||||
euf::enode* rb = sign ? mk_true() : mk_false();
|
euf::enode* rb = sign ? mk_true() : mk_false();
|
||||||
|
@ -458,6 +458,8 @@ namespace euf {
|
||||||
give_up = true;
|
give_up = true;
|
||||||
|
|
||||||
unsigned num_nodes = m_egraph.num_nodes();
|
unsigned num_nodes = m_egraph.num_nodes();
|
||||||
|
if (merge_shared_bools())
|
||||||
|
cont = true;
|
||||||
for (auto* e : m_solvers) {
|
for (auto* e : m_solvers) {
|
||||||
if (!m.inc())
|
if (!m.inc())
|
||||||
return sat::check_result::CR_GIVEUP;
|
return sat::check_result::CR_GIVEUP;
|
||||||
|
@ -485,6 +487,24 @@ namespace euf {
|
||||||
return sat::check_result::CR_DONE;
|
return sat::check_result::CR_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool solver::merge_shared_bools() {
|
||||||
|
bool merged = false;
|
||||||
|
for (unsigned i = m_egraph.nodes().size(); i-- > 0; ) {
|
||||||
|
euf::enode* n = m_egraph.nodes()[i];
|
||||||
|
if (!is_shared(n) || !m.is_bool(n->get_expr()))
|
||||||
|
continue;
|
||||||
|
if (n->value() == l_true && !m.is_true(n->get_root()->get_expr())) {
|
||||||
|
m_egraph.merge(n, mk_true(), to_ptr(sat::literal(n->bool_var())));
|
||||||
|
merged = true;
|
||||||
|
}
|
||||||
|
if (n->value() == l_false && !m.is_false(n->get_root()->get_expr())) {
|
||||||
|
m_egraph.merge(n, mk_false(), to_ptr(~sat::literal(n->bool_var())));
|
||||||
|
merged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return merged;
|
||||||
|
}
|
||||||
|
|
||||||
void solver::push() {
|
void solver::push() {
|
||||||
si.push();
|
si.push();
|
||||||
scope s;
|
scope s;
|
||||||
|
|
|
@ -165,6 +165,7 @@ namespace euf {
|
||||||
bool is_self_propagated(th_eq const& e);
|
bool is_self_propagated(th_eq const& e);
|
||||||
void get_antecedents(literal l, constraint& j, literal_vector& r, bool probing);
|
void get_antecedents(literal l, constraint& j, literal_vector& r, bool probing);
|
||||||
void new_diseq(enode* a, enode* b, literal lit);
|
void new_diseq(enode* a, enode* b, literal lit);
|
||||||
|
bool merge_shared_bools();
|
||||||
|
|
||||||
// proofs
|
// proofs
|
||||||
void log_antecedents(std::ostream& out, literal l, literal_vector const& r);
|
void log_antecedents(std::ostream& out, literal l, literal_vector const& r);
|
||||||
|
@ -286,6 +287,7 @@ namespace euf {
|
||||||
|
|
||||||
void propagate(literal lit, th_explain* p) { propagate(lit, p->to_index()); }
|
void propagate(literal lit, th_explain* p) { propagate(lit, p->to_index()); }
|
||||||
bool propagate(enode* a, enode* b, th_explain* p) { return propagate(a, b, p->to_index()); }
|
bool propagate(enode* a, enode* b, th_explain* p) { return propagate(a, b, p->to_index()); }
|
||||||
|
size_t* to_justification(sat::literal l) { return to_ptr(l); }
|
||||||
void set_conflict(th_explain* p) { set_conflict(p->to_index()); }
|
void set_conflict(th_explain* p) { set_conflict(p->to_index()); }
|
||||||
|
|
||||||
bool set_root(literal l, literal r) override;
|
bool set_root(literal l, literal r) override;
|
||||||
|
|
|
@ -181,23 +181,25 @@ namespace q {
|
||||||
while (!todo.empty()) {
|
while (!todo.empty()) {
|
||||||
expr* t = todo.back();
|
expr* t = todo.back();
|
||||||
SASSERT(!is_ground(t) || ctx.get_egraph().find(t));
|
SASSERT(!is_ground(t) || ctx.get_egraph().find(t));
|
||||||
if (is_ground(t) || (has_quantifiers(t) && !has_free_vars(t))) {
|
|
||||||
m_mark.mark(t);
|
|
||||||
m_eval.setx(t->get_id(), ctx.get_egraph().find(t), nullptr);
|
|
||||||
if (!m_eval[t->get_id()])
|
|
||||||
return nullptr;
|
|
||||||
todo.pop_back();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (m_mark.is_marked(t)) {
|
if (m_mark.is_marked(t)) {
|
||||||
todo.pop_back();
|
todo.pop_back();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (is_var(t)) {
|
if (is_ground(t) || (has_quantifiers(t) && !has_free_vars(t))) {
|
||||||
|
m_eval.setx(t->get_id(), ctx.get_egraph().find(t), nullptr);
|
||||||
|
if (!m_eval[t->get_id()])
|
||||||
|
return nullptr;
|
||||||
m_mark.mark(t);
|
m_mark.mark(t);
|
||||||
|
todo.pop_back();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_var(t)) {
|
||||||
if (to_var(t)->get_idx() >= n)
|
if (to_var(t)->get_idx() >= n)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
m_eval.setx(t->get_id(), binding[n - 1 - to_var(t)->get_idx()], nullptr);
|
m_eval.setx(t->get_id(), binding[n - 1 - to_var(t)->get_idx()], nullptr);
|
||||||
|
if (!m_eval[t->get_id()])
|
||||||
|
return nullptr;
|
||||||
|
m_mark.mark(t);
|
||||||
todo.pop_back();
|
todo.pop_back();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3745,7 +3745,7 @@ namespace q {
|
||||||
// However, the simplifier may turn a non-ground pattern into a ground one.
|
// However, the simplifier may turn a non-ground pattern into a ground one.
|
||||||
// So, we should check it again here.
|
// So, we should check it again here.
|
||||||
for (expr* arg : *mp)
|
for (expr* arg : *mp)
|
||||||
if (is_ground(arg))
|
if (is_ground(arg) || has_quantifiers(arg))
|
||||||
return; // ignore multi-pattern containing ground pattern.
|
return; // ignore multi-pattern containing ground pattern.
|
||||||
update_filters(qa, mp);
|
update_filters(qa, mp);
|
||||||
m_new_patterns.push_back(qp_pair(qa, mp));
|
m_new_patterns.push_back(qp_pair(qa, mp));
|
||||||
|
|
|
@ -251,7 +251,7 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
n -= m_num_scopes;
|
n -= m_num_scopes;
|
||||||
m_num_scopes = 0;
|
m_num_scopes = 0;
|
||||||
m_map.pop(n);
|
m_map.pop(n);
|
||||||
unsigned k = m_cache_lim[m_cache_lim.size() - n];
|
unsigned k = m_cache_lim[m_cache_lim.size() - n];
|
||||||
for (unsigned i = m_cache_trail.size(); i-- > k; ) {
|
for (unsigned i = m_cache_trail.size(); i-- > k; ) {
|
||||||
|
@ -284,7 +284,7 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
||||||
m_cache_trail.push_back(t);
|
m_cache_trail.push_back(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void convert_atom(expr * t, bool root, bool sign) {
|
void convert_atom(expr * t, bool root, bool sign) {
|
||||||
SASSERT(m.is_bool(t));
|
SASSERT(m.is_bool(t));
|
||||||
sat::literal l;
|
sat::literal l;
|
||||||
sat::bool_var v = m_map.to_bool_var(t);
|
sat::bool_var v = m_map.to_bool_var(t);
|
||||||
|
@ -954,9 +954,11 @@ struct goal2sat::imp : public sat::sat_internalizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
void user_push() {
|
void user_push() {
|
||||||
|
push();
|
||||||
}
|
}
|
||||||
|
|
||||||
void user_pop(unsigned n) {
|
void user_pop(unsigned n) {
|
||||||
|
pop(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -1010,15 +1012,7 @@ void goal2sat::operator()(goal const & g, params_ref const & p, sat::solver_core
|
||||||
for (unsigned i = 0; i < m_scopes; ++i)
|
for (unsigned i = 0; i < m_scopes; ++i)
|
||||||
m_imp->user_push();
|
m_imp->user_push();
|
||||||
}
|
}
|
||||||
(*m_imp)(g);
|
(*m_imp)(g);
|
||||||
|
|
||||||
if (!t.get_extension() && m_imp->interpreted_funs().empty()) {
|
|
||||||
dealloc(m_imp);
|
|
||||||
m_imp = nullptr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_scopes = 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void goal2sat::get_interpreted_funs(func_decl_ref_vector& funs) {
|
void goal2sat::get_interpreted_funs(func_decl_ref_vector& funs) {
|
||||||
|
|
|
@ -371,7 +371,7 @@ namespace smt {
|
||||||
case l_true:
|
case l_true:
|
||||||
if (!m_proto_model->eval(n, res, false))
|
if (!m_proto_model->eval(n, res, false))
|
||||||
return true;
|
return true;
|
||||||
CTRACE("model", !m.is_true(res), tout << n << " evaluates to " << res << "\n";);
|
CTRACE("model", !m.is_true(res), tout << n << " evaluates to " << res << "\n" << *m_proto_model << "\n";);
|
||||||
if (m.is_false(res)) {
|
if (m.is_false(res)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -379,7 +379,7 @@ namespace smt {
|
||||||
case l_false:
|
case l_false:
|
||||||
if (!m_proto_model->eval(n, res, false))
|
if (!m_proto_model->eval(n, res, false))
|
||||||
return true;
|
return true;
|
||||||
CTRACE("model", !m.is_false(res), tout << n << " evaluates to " << res << "\n";);
|
CTRACE("model", !m.is_false(res), tout << n << " evaluates to " << res << "\n" << *m_proto_model << "\n";);
|
||||||
if (m.is_true(res)) {
|
if (m.is_true(res)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -807,10 +807,10 @@ class theory_lra::imp {
|
||||||
return st.vars()[0];
|
return st.vars()[0];
|
||||||
}
|
}
|
||||||
else if (is_one(st) && a.is_numeral(term)) {
|
else if (is_one(st) && a.is_numeral(term)) {
|
||||||
return get_one(a.is_int(term));
|
return lp().local_to_external(get_one(a.is_int(term)));
|
||||||
}
|
}
|
||||||
else if (is_zero(st) && a.is_numeral(term)) {
|
else if (is_zero(st) && a.is_numeral(term)) {
|
||||||
return get_zero(a.is_int(term));
|
return lp().local_to_external(get_zero(a.is_int(term)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
init_left_side(st);
|
init_left_side(st);
|
||||||
|
|
|
@ -532,14 +532,14 @@ void asserted_formulas::propagate_values() {
|
||||||
flush_cache();
|
flush_cache();
|
||||||
|
|
||||||
unsigned num_prop = 0;
|
unsigned num_prop = 0;
|
||||||
unsigned delta_prop = m_formulas.size();
|
unsigned sz = m_formulas.size();
|
||||||
while (!inconsistent() && m_formulas.size()/20 < delta_prop) {
|
unsigned delta_prop = sz;
|
||||||
|
while (!inconsistent() && sz/20 < delta_prop) {
|
||||||
m_expr2depth.reset();
|
m_expr2depth.reset();
|
||||||
m_scoped_substitution.push();
|
m_scoped_substitution.push();
|
||||||
unsigned prop = num_prop;
|
unsigned prop = num_prop;
|
||||||
TRACE("propagate_values", display(tout << "before:\n"););
|
TRACE("propagate_values", display(tout << "before:\n"););
|
||||||
unsigned i = m_qhead;
|
unsigned i = m_qhead;
|
||||||
unsigned sz = m_formulas.size();
|
|
||||||
for (; i < sz; i++) {
|
for (; i < sz; i++) {
|
||||||
prop += propagate_values(i);
|
prop += propagate_values(i);
|
||||||
}
|
}
|
||||||
|
@ -558,6 +558,9 @@ void asserted_formulas::propagate_values() {
|
||||||
TRACE("propagate_values", tout << "after:\n"; display(tout););
|
TRACE("propagate_values", tout << "after:\n"; display(tout););
|
||||||
delta_prop = prop - num_prop;
|
delta_prop = prop - num_prop;
|
||||||
num_prop = prop;
|
num_prop = prop;
|
||||||
|
if (sz <= m_formulas.size())
|
||||||
|
break;
|
||||||
|
sz = m_formulas.size();
|
||||||
}
|
}
|
||||||
TRACE("asserted_formulas", tout << num_prop << "\n";);
|
TRACE("asserted_formulas", tout << num_prop << "\n";);
|
||||||
if (num_prop > 0)
|
if (num_prop > 0)
|
||||||
|
|
|
@ -19,7 +19,7 @@ class tactic;
|
||||||
tactic * mk_solver_subsumption_tactic(ast_manager & m, params_ref const & p = params_ref());
|
tactic * mk_solver_subsumption_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ADD_TACTIC("solver_subsumption", "remove assertions that are subsumed.", "mk_solver_subsumption_tactic(m, p)")
|
ADD_TACTIC("solver-subsumption", "remove assertions that are subsumed.", "mk_solver_subsumption_tactic(m, p)")
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue