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

QEL: Fast Approximated Quantifier Elimination (#6820)

* qe_lite: cleanup and comment

no change to code

* mbp_arrays: refactor out partial equality (peq)

Partial array equality, PEQ, is used as an intermediate
expression during MBP for arrays. We need to factor it out
so that it can be shared between MBP-QEL and existing MBP.

Partial array equality (peq) is used in MBP for arrays.
Factoring this out to be used by multiple MBP implementations.

* rewriter: new rewrite rules

These rules are specializes for terms that are created in QEL.
QEL commit is comming later

* datatype_rw: new rewrite rule for ADTs

The rule handles this special case:

    (cons (head x) (tail x)) --> x

* array_rewriter rules for rewriting PEQs

Special rules to simplify PEQs

* th_rewriter: wire PEQ simplifications

* spacer_iuc: avoid terms with default in IUC

Spacer prfers to not have a term representing default value of an array.
This guides IUC from picking such terms in interpolation

* mbp_term_graph: replace root with repr

* mbp_term_graph: formatting

* mbp_term_graph: class_props, getters, setters

Class properties allow to keep information for an equivalence class.

Getters and setters for terms allow accessing information

* mbp_term_graph: auxiliary methods for qel

QEL commit is comming later in the history

* mbp_term_graph: bug fix

* mbp_term_graph: pick, refine repr, compute cgrnd

* mbp_term_graph: internalize deq

* mbp_term_graph: constructor

* mbp_term_graph: optionally internalize equalities

Reperesent equalities explicitly by nodes in the term_graph

* qel

* formatting

* comments on term_lt

* get terms and other api for mbp_qel

* plugins for mbp_qel

* mbp_qel_util: utilities for mbp_qel

* qe_mbp: QEL-based mbp

* qel: expose QEL API

* spacer: replace qe_lite in qe_project_spacer by qel

This changes the default projection engine that spacer uses.

* cmd_context: debug commands for qel and mbp_qel

New commands are

  mbp-qel -- MBP with term graphs
  qel     -- QEL with term graphs
  qe-lite -- older qelite

* qe_mbp: model-based rewriters for arrays

* qe_mbp: QEL-based projection functions

* qsat: wire in QEL-based mbp

* qsat: debug code

* qsat: maybe a bug fix

Changed the code to follow the paper by adding all predicates above a given
level, not just predicates of immediately preceding level.

* chore: use new api to create solver in qsat

* mbp_term_graph use all_of idiom

* feat: solver for integer multiplication

* array_peq: formatting, no change to code

* mbp_qel_util: block comment + format

* mbt_term_graph: clang-format

* bug fix. Move dt rewrite to qe_mbp

* array_peq: add header

* run clang format on mbp plugins

* clang format on mul solver

* format do-while

* format

* format do-while

* update release notes

---------

Co-authored-by: hgvk94 <hgvk94@gmail.com>
Co-authored-by: Isabel Garcia <igarciac@uwaterloo.ca>
This commit is contained in:
Arie Gurfinkel 2023-08-02 12:34:06 -04:00 committed by GitHub
parent 5b2519d7a3
commit 51d3c279d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 4170 additions and 1517 deletions

View file

@ -16,6 +16,7 @@ Notes:
--*/
#include<iomanip>
#include "ast/ast.h"
#include "cmd_context/cmd_context.h"
#include "cmd_context/cmd_util.h"
#include "ast/rewriter/rewriter.h"
@ -34,7 +35,9 @@ Notes:
#include "qe/qe_mbp.h"
#include "qe/qe_mbi.h"
#include "qe/mbp/mbp_term_graph.h"
#include "qe/mbp/mbp_qel.h"
#include "qe/lite/qe_lite_tactic.h"
#include "qe/lite/qel.h"
BINARY_SYM_CMD(get_quantifier_body_cmd,
"dbg-get-qbody",
@ -369,7 +372,7 @@ public:
}
vars.push_back(to_app(v));
}
qe::mbproj mbp(m);
qe::mbproj mbp(m, gparams::get_module("smt"));
expr_ref fml(m_fml, m);
mbp.spacer(vars, *mdl.get(), fml);
ctx.regular_stream() << fml << "\n";
@ -572,8 +575,192 @@ public:
};
class mbp_qel_cmd : public cmd {
unsigned m_arg_index;
ptr_vector<expr> m_lits;
ptr_vector<expr> m_vars;
void install_dbg_cmds(cmd_context & ctx) {
public:
mbp_qel_cmd() : cmd("mbp-qel"){};
char const *get_usage() const override { return "(exprs) (vars)"; }
char const *get_descr(cmd_context &ctx) const override {
return "Model based projection using e-graphs";
}
unsigned get_arity() const override { return 2; }
cmd_arg_kind next_arg_kind(cmd_context &ctx) const override {
return CPK_EXPR_LIST;
}
void set_next_arg(cmd_context &ctx, unsigned num,
expr *const *args) override {
if (m_arg_index == 0) {
m_lits.append(num, args);
m_arg_index = 1;
}
else { m_vars.append(num, args); }
}
void prepare(cmd_context &ctx) override {
m_arg_index = 0;
m_lits.reset();
m_vars.reset();
}
void execute(cmd_context &ctx) override {
ast_manager &m = ctx.m();
app_ref_vector vars(m);
expr_ref fml(m);
expr_ref_vector lits(m);
for (expr *v : m_vars) vars.push_back(to_app(v));
for (expr *e : m_lits) lits.push_back(e);
fml = mk_and(lits);
solver_factory &sf = ctx.get_solver_factory();
params_ref pa;
solver_ref s = sf(m, pa, false, true, true, symbol::null);
s->assert_expr(fml);
lbool r = s->check_sat();
if (r != l_true) return;
model_ref mdl;
s->get_model(mdl);
mbp::mbp_qel mbptg(m, pa);
mbptg(vars, fml, *mdl.get());
ctx.regular_stream() << "------------------------------ " << std::endl;
ctx.regular_stream() << "Orig tg: " << mk_and(lits) << std::endl;
ctx.regular_stream() << "To elim: ";
for (expr *v : m_vars) {
ctx.regular_stream() << to_app(v)->get_decl()->get_name() << " ";
}
ctx.regular_stream() << std::endl;
ctx.regular_stream() << "output " << fml << std::endl;
}
};
class qel_cmd : public cmd {
unsigned m_arg_index;
ptr_vector<expr> m_lits;
ptr_vector<func_decl> m_vars;
public:
qel_cmd() : cmd("qel"){};
char const *get_usage() const override { return "(lits) (vars)"; }
char const *get_descr(cmd_context &ctx) const override {
return "QE lite over e-graphs";
}
unsigned get_arity() const override { return 2; }
cmd_arg_kind next_arg_kind(cmd_context &ctx) const override {
if (m_arg_index == 0) return CPK_EXPR_LIST;
return CPK_FUNC_DECL_LIST;
}
void set_next_arg(cmd_context &ctx, unsigned num,
expr *const *args) override {
m_lits.append(num, args);
m_arg_index = 1;
}
void set_next_arg(cmd_context &ctx, unsigned num,
func_decl *const *ts) override {
m_vars.append(num, ts);
}
void prepare(cmd_context &ctx) override {
m_arg_index = 0;
m_lits.reset();
m_vars.reset();
}
void execute(cmd_context &ctx) override {
ast_manager &m = ctx.m();
func_decl_ref_vector vars(m);
app_ref_vector vars_apps(m);
expr_ref_vector lits(m);
ctx.regular_stream() << "------------------------------ " << std::endl;
for (func_decl *v : m_vars) {
vars.push_back(v);
vars_apps.push_back(m.mk_const(v));
}
for (expr *e : m_lits) lits.push_back(e);
expr_ref fml(m.mk_and(lits), m);
ctx.regular_stream() << "[tg] Before: " << fml << std::endl
<< "[tg] Vars: ";
for (app *a : vars_apps) ctx.regular_stream() << app_ref(a, m) << " ";
ctx.regular_stream() << std::endl;
params_ref pa;
// the following is the same code as in qe_mbp in spacer
qel qe(m, pa);
qe(vars_apps, fml);
ctx.regular_stream() << "[tg] After: " << fml << std::endl
<< "[tg] Vars: ";
for (app *a : vars_apps) ctx.regular_stream() << app_ref(a, m) << " ";
ctx.regular_stream() << std::endl;
}
};
class qe_lite_cmd : public cmd {
unsigned m_arg_index;
ptr_vector<expr> m_lits;
ptr_vector<func_decl> m_vars;
public:
qe_lite_cmd() : cmd("qe-lite"){};
char const *get_usage() const override { return "(lits) (vars)"; }
char const *get_descr(cmd_context &ctx) const override {
return "QE lite over e-graphs";
}
unsigned get_arity() const override { return 2; }
cmd_arg_kind next_arg_kind(cmd_context &ctx) const override {
if (m_arg_index == 0) return CPK_EXPR_LIST;
return CPK_FUNC_DECL_LIST;
}
void set_next_arg(cmd_context &ctx, unsigned num,
expr *const *args) override {
m_lits.append(num, args);
m_arg_index = 1;
}
void set_next_arg(cmd_context &ctx, unsigned num,
func_decl *const *ts) override {
m_vars.append(num, ts);
}
void prepare(cmd_context &ctx) override {
m_arg_index = 0;
m_lits.reset();
m_vars.reset();
}
void execute(cmd_context &ctx) override {
ast_manager &m = ctx.m();
func_decl_ref_vector vars(m);
app_ref_vector vars_apps(m);
expr_ref_vector lits(m);
ctx.regular_stream() << "------------------------------ " << std::endl;
for (func_decl *v : m_vars) {
vars.push_back(v);
vars_apps.push_back(m.mk_const(v));
}
for (expr *e : m_lits) lits.push_back(e);
expr_ref fml(m.mk_and(lits), m);
ctx.regular_stream() << "[der] Before: " << fml << std::endl
<< "[der] Vars: ";
for (app *a : vars_apps) ctx.regular_stream() << app_ref(a, m) << " ";
ctx.regular_stream() << std::endl;
params_ref pa;
// the following is the same code as in qe_mbp in spacer
qe_lite qe(m, pa, false);
qe(vars_apps, fml);
ctx.regular_stream() << "[der] After: " << fml << std::endl
<< "[der] Vars: ";
for (app *a : vars_apps) ctx.regular_stream() << app_ref(a, m) << " ";
ctx.regular_stream() << std::endl;
}
};
void install_dbg_cmds(cmd_context &ctx) {
ctx.insert(alloc(print_dimacs_cmd));
ctx.insert(alloc(get_quantifier_body_cmd));
ctx.insert(alloc(set_cmd));
@ -598,7 +785,10 @@ void install_dbg_cmds(cmd_context & ctx) {
ctx.insert(alloc(set_next_id));
ctx.insert(alloc(get_interpolant_cmd));
ctx.insert(alloc(mbp_cmd));
ctx.insert(alloc(mbp_qel_cmd));
ctx.insert(alloc(mbi_cmd));
ctx.insert(alloc(euf_project_cmd));
ctx.insert(alloc(eufi_cmd));
ctx.insert(alloc(qel_cmd));
ctx.insert(alloc(qe_lite_cmd));
}