mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 00:55:31 +00:00
integrate lambda expressions
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
bf4edef761
commit
520ce9a5ee
139 changed files with 2243 additions and 1506 deletions
|
@ -2269,8 +2269,7 @@ namespace qe {
|
|||
bound.push_back(m.mk_fresh_const("bound", fv[i]));
|
||||
}
|
||||
var_subst subst(m);
|
||||
subst(fml, bound.size(), bound.c_ptr(), tmp);
|
||||
fml = tmp;
|
||||
fml = subst(fml, bound.size(), bound.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2291,7 +2290,7 @@ namespace qe {
|
|||
}
|
||||
expr* const* exprs = (expr* const*)(vars.c_ptr());
|
||||
var_subst subst(m);
|
||||
subst(new_body, vars.size(), exprs, tmp);
|
||||
tmp = subst(new_body, vars.size(), exprs);
|
||||
inv_var_shifter shift(m);
|
||||
shift(tmp, vars.size(), new_body);
|
||||
}
|
||||
|
@ -2337,13 +2336,18 @@ namespace qe {
|
|||
case AST_QUANTIFIER: {
|
||||
app_ref_vector vars(m);
|
||||
quantifier* q = to_quantifier(e);
|
||||
bool is_fa = q->is_forall();
|
||||
tmp = q->get_expr();
|
||||
extract_vars(q, tmp, vars);
|
||||
elim(tmp);
|
||||
init_qe();
|
||||
m_qe->set_assumption(m_assumption);
|
||||
m_qe->eliminate(is_fa, vars.size(), vars.c_ptr(), tmp);
|
||||
if (is_lambda(q)) {
|
||||
tmp = e;
|
||||
}
|
||||
else {
|
||||
bool is_fa = is_forall(q);
|
||||
tmp = q->get_expr();
|
||||
extract_vars(q, tmp, vars);
|
||||
elim(tmp);
|
||||
init_qe();
|
||||
m_qe->set_assumption(m_assumption);
|
||||
m_qe->eliminate(is_fa, vars.size(), vars.c_ptr(), tmp);
|
||||
}
|
||||
m_trail.push_back(tmp);
|
||||
m_visited.insert(e, tmp);
|
||||
todo.pop_back();
|
||||
|
@ -2593,6 +2597,9 @@ namespace qe {
|
|||
)
|
||||
{
|
||||
|
||||
if (is_lambda(old_q)) {
|
||||
return false;
|
||||
}
|
||||
// bool is_forall = old_q->is_forall();
|
||||
app_ref_vector vars(m);
|
||||
TRACE("qe", tout << "simplifying" << mk_pp(new_body, m) << "\n";);
|
||||
|
@ -2600,11 +2607,11 @@ namespace qe {
|
|||
extract_vars(old_q, result, vars);
|
||||
TRACE("qe", tout << "variables extracted" << mk_pp(result, m) << "\n";);
|
||||
|
||||
if (old_q->is_forall()) {
|
||||
if (is_forall(old_q)) {
|
||||
result = mk_not(m, result);
|
||||
}
|
||||
m_ctx.solve(result, vars);
|
||||
if (old_q->is_forall()) {
|
||||
if (is_forall(old_q)) {
|
||||
expr* e = nullptr;
|
||||
result = m.is_not(result, e)?e:mk_not(m, result);
|
||||
}
|
||||
|
@ -2619,7 +2626,7 @@ namespace qe {
|
|||
names.push_back(vars[i]->get_decl()->get_name());
|
||||
}
|
||||
if (!vars.empty()) {
|
||||
result = m.mk_quantifier(old_q->is_forall(), vars.size(), sorts.c_ptr(), names.c_ptr(), result, 1);
|
||||
result = m.mk_quantifier(old_q->get_kind(), vars.size(), sorts.c_ptr(), names.c_ptr(), result, 1);
|
||||
}
|
||||
result_pr = nullptr;
|
||||
return true;
|
||||
|
|
|
@ -327,8 +327,8 @@ namespace eq {
|
|||
|
||||
void flatten_args(quantifier* q, unsigned& num_args, expr*const*& args) {
|
||||
expr * e = q->get_expr();
|
||||
if ((q->is_forall() && m.is_or(e)) ||
|
||||
(q->is_exists() && m.is_and(e))) {
|
||||
if ((is_forall(q) && m.is_or(e)) ||
|
||||
(is_exists(q) && m.is_and(e))) {
|
||||
num_args = to_app(e)->get_num_args();
|
||||
args = to_app(e)->get_args();
|
||||
}
|
||||
|
@ -356,27 +356,29 @@ namespace eq {
|
|||
}
|
||||
|
||||
expr_ref t(m);
|
||||
if (q->is_forall()) {
|
||||
switch (q->get_kind()) {
|
||||
case forall_k:
|
||||
rw.mk_or(m_new_args.size(), m_new_args.c_ptr(), t);
|
||||
}
|
||||
else {
|
||||
break;
|
||||
case exists_k:
|
||||
rw.mk_and(m_new_args.size(), m_new_args.c_ptr(), t);
|
||||
break;
|
||||
default:
|
||||
t = e;
|
||||
break;
|
||||
}
|
||||
expr_ref new_e(m);
|
||||
m_subst(t, new_e);
|
||||
expr_ref new_e = m_subst(t, m_subst_map.size(), m_subst_map.c_ptr());
|
||||
|
||||
// don't forget to update the quantifier patterns
|
||||
expr_ref_buffer new_patterns(m);
|
||||
expr_ref_buffer new_no_patterns(m);
|
||||
for (unsigned j = 0; j < q->get_num_patterns(); j++) {
|
||||
expr_ref new_pat(m);
|
||||
m_subst(q->get_pattern(j), new_pat);
|
||||
expr_ref new_pat = m_subst(q->get_pattern(j), m_subst_map.size(), m_subst_map.c_ptr());
|
||||
new_patterns.push_back(new_pat);
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < q->get_num_no_patterns(); j++) {
|
||||
expr_ref new_nopat(m);
|
||||
m_subst(q->get_no_pattern(j), new_nopat);
|
||||
expr_ref new_nopat = m_subst(q->get_no_pattern(j), m_subst_map.size(), m_subst_map.c_ptr());
|
||||
new_no_patterns.push_back(new_nopat);
|
||||
}
|
||||
|
||||
|
@ -390,12 +392,17 @@ namespace eq {
|
|||
set_is_variable_proc(is_v);
|
||||
unsigned num_args = 1;
|
||||
expr* const* args = &e;
|
||||
if (is_lambda(q)) {
|
||||
r = q;
|
||||
pr = 0;
|
||||
return;
|
||||
}
|
||||
flatten_args(q, num_args, args);
|
||||
|
||||
unsigned def_count = 0;
|
||||
unsigned largest_vinx = 0;
|
||||
|
||||
find_definitions(num_args, args, q->is_exists(), def_count, largest_vinx);
|
||||
find_definitions(num_args, args, is_exists(q), def_count, largest_vinx);
|
||||
|
||||
if (def_count > 0) {
|
||||
get_elimination_order();
|
||||
|
@ -423,7 +430,7 @@ namespace eq {
|
|||
if (is_quantifier(r)) {
|
||||
quantifier * q = to_quantifier(r);
|
||||
|
||||
::elim_unused_vars(m, q, m_params, r);
|
||||
r = ::elim_unused_vars(m, q, m_params);
|
||||
if (m.proofs_enabled()) {
|
||||
proof * p1 = m.mk_elim_unused_vars(q, r);
|
||||
pr = m.mk_transitivity(pr, p1);
|
||||
|
@ -624,7 +631,7 @@ namespace eq {
|
|||
expr_ref r(m), new_r(m);
|
||||
r = m.mk_and(conjs.size(), conjs.c_ptr());
|
||||
create_substitution(largest_vinx + 1);
|
||||
m_subst(r, new_r);
|
||||
new_r = m_subst(r, m_subst_map.size(), m_subst_map.c_ptr());
|
||||
m_rewriter(new_r);
|
||||
conjs.reset();
|
||||
flatten_and(new_r, conjs);
|
||||
|
@ -1756,16 +1763,12 @@ namespace fm {
|
|||
// x_cost_lt is not a total order on variables
|
||||
std::stable_sort(x_cost_vector.begin(), x_cost_vector.end(), x_cost_lt(m_is_int));
|
||||
TRACE("qe_lite",
|
||||
svector<x_cost>::iterator it2 = x_cost_vector.begin();
|
||||
svector<x_cost>::iterator end2 = x_cost_vector.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
tout << "(" << mk_ismt2_pp(m_var2expr.get(it2->first), m) << " " << it2->second << ") ";
|
||||
for (auto const& kv : x_cost_vector) {
|
||||
tout << "(" << mk_ismt2_pp(m_var2expr.get(kv.first), m) << " " << kv.second << ") ";
|
||||
}
|
||||
tout << "\n";);
|
||||
svector<x_cost>::iterator it2 = x_cost_vector.begin();
|
||||
svector<x_cost>::iterator end2 = x_cost_vector.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
xs.push_back(it2->first);
|
||||
for (auto const& kv : x_cost_vector) {
|
||||
xs.push_back(kv.first);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1802,11 +1805,9 @@ namespace fm {
|
|||
void analyze(constraints const & cs, var x, bool & all_int, bool & unit_coeff) const {
|
||||
all_int = true;
|
||||
unit_coeff = true;
|
||||
constraints::const_iterator it = cs.begin();
|
||||
constraints::const_iterator end = cs.end();
|
||||
for (; it != end; ++it) {
|
||||
for (constraint const* c : cs) {
|
||||
bool curr_unit_coeff;
|
||||
analyze(*(*it), x, all_int, curr_unit_coeff);
|
||||
analyze(*c, x, all_int, curr_unit_coeff);
|
||||
if (!all_int)
|
||||
return;
|
||||
if (!curr_unit_coeff)
|
||||
|
@ -1830,10 +1831,8 @@ namespace fm {
|
|||
}
|
||||
|
||||
void copy_constraints(constraints const & s, clauses & t) {
|
||||
constraints::const_iterator it = s.begin();
|
||||
constraints::const_iterator end = s.end();
|
||||
for (; it != end; ++it) {
|
||||
app * c = to_expr(*(*it));
|
||||
for (constraint const* cns : s) {
|
||||
app * c = to_expr(*cns);
|
||||
t.push_back(c);
|
||||
}
|
||||
}
|
||||
|
@ -1842,10 +1841,8 @@ namespace fm {
|
|||
void save_constraints(var x) { }
|
||||
|
||||
void mark_constraints_dead(constraints const & cs) {
|
||||
constraints::const_iterator it = cs.begin();
|
||||
constraints::const_iterator end = cs.end();
|
||||
for (; it != end; ++it)
|
||||
(*it)->m_dead = true;
|
||||
for (constraint* c : cs)
|
||||
c->m_dead = true;
|
||||
}
|
||||
|
||||
void mark_constraints_dead(var x) {
|
||||
|
@ -2094,14 +2091,8 @@ namespace fm {
|
|||
}
|
||||
|
||||
void copy_remaining(vector<constraints> & v2cs) {
|
||||
vector<constraints>::iterator it = v2cs.begin();
|
||||
vector<constraints>::iterator end = v2cs.end();
|
||||
for (; it != end; ++it) {
|
||||
constraints & cs = *it;
|
||||
constraints::iterator it2 = cs.begin();
|
||||
constraints::iterator end2 = cs.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
constraint * c = *it2;
|
||||
for (constraints& cs : v2cs) {
|
||||
for (constraint* c : cs) {
|
||||
if (!c->m_dead) {
|
||||
c->m_dead = true;
|
||||
expr * new_f = to_expr(*c);
|
||||
|
@ -2170,11 +2161,8 @@ namespace fm {
|
|||
}
|
||||
|
||||
void display_constraints(std::ostream & out, constraints const & cs) const {
|
||||
constraints::const_iterator it = cs.begin();
|
||||
constraints::const_iterator end = cs.end();
|
||||
for (; it != end; ++it) {
|
||||
out << " ";
|
||||
display(out, *(*it));
|
||||
for (constraint const* c : cs) {
|
||||
display(out << " ", *c);
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
@ -2215,7 +2203,9 @@ public:
|
|||
for (unsigned i = 0; i < q->get_num_decls(); ++i) {
|
||||
indices.insert(i);
|
||||
}
|
||||
m_imp(indices, true, result);
|
||||
if (q->get_kind() != lambda_k) {
|
||||
m_imp(indices, true, result);
|
||||
}
|
||||
if (is_forall(q)) {
|
||||
result = push_not(result);
|
||||
}
|
||||
|
@ -2295,7 +2285,7 @@ public:
|
|||
tmp = to_quantifier(tmp)->get_expr();
|
||||
used.process(tmp);
|
||||
var_subst vs(m, true);
|
||||
vs(tmp, vars.size(), (expr*const*)vars.c_ptr(), fml);
|
||||
fml = vs(tmp, vars.size(), (expr*const*)vars.c_ptr());
|
||||
// collect set of variables that were used.
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
|
|
|
@ -31,6 +31,7 @@ Revision History:
|
|||
#include "qe/qe_arrays.h"
|
||||
#include "qe/qe_datatypes.h"
|
||||
#include "qe/qe_lite.h"
|
||||
#include "model/model_pp.h"
|
||||
#include "model/model_evaluator.h"
|
||||
|
||||
|
||||
|
@ -616,7 +617,7 @@ public:
|
|||
qe::array_project_plugin ap(m);
|
||||
ap(mdl, array_vars, fml, vars, m_reduce_all_selects);
|
||||
SASSERT (array_vars.empty ());
|
||||
m_rw(fml);
|
||||
m_rw (fml);
|
||||
SASSERT (!m.is_false (fml));
|
||||
|
||||
TRACE ("qe",
|
||||
|
@ -650,9 +651,9 @@ public:
|
|||
// substitute any remaining other vars
|
||||
if (!m_dont_sub && !other_vars.empty ()) {
|
||||
subst_vars (eval, other_vars, fml);
|
||||
TRACE ("qe", tout << "After substituting remaining other vars:\n" << fml << "\n";);
|
||||
// an extra round of simplification because subst_vars is not simplifying
|
||||
m_rw(fml);
|
||||
TRACE ("qe", tout << "After substituting remaining other vars:\n" << fml << "\n";);
|
||||
other_vars.reset();
|
||||
}
|
||||
|
||||
|
|
|
@ -989,9 +989,10 @@ namespace qe {
|
|||
break;
|
||||
}
|
||||
case AST_QUANTIFIER: {
|
||||
SASSERT(!is_lambda(e));
|
||||
app_ref_vector vars(m);
|
||||
quantifier* q = to_quantifier(e);
|
||||
bool is_fa = q->is_forall();
|
||||
bool is_fa = ::is_forall(q);
|
||||
tmp = q->get_expr();
|
||||
extract_vars(q, tmp, vars);
|
||||
TRACE("qe", tout << vars << " " << mk_pp(q, m) << " " << tmp << "\n";);
|
||||
|
@ -1235,6 +1236,9 @@ namespace qe {
|
|||
fml = push_not(fml);
|
||||
}
|
||||
hoist(fml);
|
||||
if (!is_ground(fml)) {
|
||||
throw tactic_exception("formula is not hoistable");
|
||||
}
|
||||
m_pred_abs.abstract_atoms(fml, defs);
|
||||
fml = m_pred_abs.mk_abstract(fml);
|
||||
m_ex.assert_expr(mk_and(defs));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue