mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
Merge branch 'master' into polysat
This commit is contained in:
commit
59c3234fb8
196 changed files with 4705 additions and 4168 deletions
|
@ -370,7 +370,7 @@ inline func_decl * arith_decl_plugin::mk_func_decl(decl_kind k, bool is_real) {
|
|||
if (is_real) {
|
||||
return m_manager->mk_func_decl(symbol("^0"), m_real_decl, m_real_decl, m_real_decl, func_decl_info(m_family_id, OP_POWER0));
|
||||
}
|
||||
return m_manager->mk_func_decl(symbol("^0"), m_int_decl, m_int_decl, m_int_decl, func_decl_info(m_family_id, OP_POWER0));
|
||||
return m_manager->mk_func_decl(symbol("^0"), m_int_decl, m_int_decl, m_real_decl, func_decl_info(m_family_id, OP_POWER0));
|
||||
case OP_TO_REAL: return m_to_real_decl;
|
||||
case OP_TO_INT: return m_to_int_decl;
|
||||
case OP_IS_INT: return m_is_int_decl;
|
||||
|
@ -834,7 +834,7 @@ bool arith_util::is_considered_uninterpreted(func_decl* f, unsigned n, expr* con
|
|||
func_decl* arith_util::mk_ipower0() {
|
||||
sort* s = mk_int();
|
||||
sort* rs[2] = { s, s };
|
||||
return m_manager.mk_func_decl(arith_family_id, OP_POWER0, 0, nullptr, 2, rs, s);
|
||||
return m_manager.mk_func_decl(arith_family_id, OP_POWER0, 0, nullptr, 2, rs, mk_real());
|
||||
}
|
||||
|
||||
func_decl* arith_util::mk_rpower0() {
|
||||
|
|
|
@ -1378,6 +1378,7 @@ void ast_manager::init() {
|
|||
ENSURE(model_value_family_id == mk_family_id("model-value"));
|
||||
ENSURE(user_sort_family_id == mk_family_id("user-sort"));
|
||||
ENSURE(arith_family_id == mk_family_id("arith"));
|
||||
ENSURE(poly_family_id == mk_family_id("polymorphic"));
|
||||
basic_decl_plugin * plugin = alloc(basic_decl_plugin);
|
||||
register_plugin(basic_family_id, plugin);
|
||||
m_bool_sort = plugin->mk_bool_sort();
|
||||
|
@ -2019,6 +2020,11 @@ sort * ast_manager::mk_uninterpreted_sort(symbol const & name, unsigned num_para
|
|||
return plugin->mk_sort(kind, num_parameters, parameters);
|
||||
}
|
||||
|
||||
sort * ast_manager::mk_type_var(symbol const& name) {
|
||||
sort_info si(poly_family_id, 0);
|
||||
return mk_sort(name, &si);
|
||||
}
|
||||
|
||||
func_decl * ast_manager::mk_func_decl(symbol const & name, unsigned arity, sort * const * domain, sort * range,
|
||||
bool assoc, bool comm, bool inj) {
|
||||
func_decl_info info(null_family_id, null_decl_kind);
|
||||
|
|
|
@ -85,6 +85,7 @@ const family_id user_sort_family_id = 4;
|
|||
const family_id last_builtin_family_id = 4;
|
||||
|
||||
const family_id arith_family_id = 5;
|
||||
const family_id poly_family_id = 6;
|
||||
|
||||
// -----------------------------------
|
||||
//
|
||||
|
@ -622,6 +623,7 @@ public:
|
|||
sort_size const & get_num_elements() const { return get_info()->get_num_elements(); }
|
||||
void set_num_elements(sort_size const& s) { get_info()->set_num_elements(s); }
|
||||
unsigned get_size() const { return get_obj_size(); }
|
||||
bool is_type_var() const { return get_family_id() == poly_family_id; }
|
||||
};
|
||||
|
||||
// -----------------------------------
|
||||
|
@ -1709,6 +1711,8 @@ public:
|
|||
|
||||
sort * mk_uninterpreted_sort(symbol const & name) { return mk_uninterpreted_sort(name, 0, nullptr); }
|
||||
|
||||
sort * mk_type_var(symbol const& name);
|
||||
|
||||
sort * mk_sort(symbol const & name, sort_info const & info) {
|
||||
if (info.get_family_id() == null_family_id) {
|
||||
return mk_uninterpreted_sort(name);
|
||||
|
|
|
@ -651,7 +651,7 @@ func_decl * bv_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
|
|||
for (unsigned i = 0; i < num_args; ++i) {
|
||||
if (args[i]->get_sort() != r->get_domain(i)) {
|
||||
std::ostringstream buffer;
|
||||
buffer << "Argument " << mk_pp(args[i], m) << " at position " << i << " has sort " << mk_pp(args[i]->get_sort(), m) << " it does does not match declaration " << mk_pp(r, m);
|
||||
buffer << "Argument " << mk_pp(args[i], m) << " at position " << i << " has sort " << mk_pp(args[i]->get_sort(), m) << " it does not match declaration " << mk_pp(r, m);
|
||||
m.raise_exception(buffer.str());
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ enum bv_op_kind {
|
|||
OP_BUMUL_OVFL, // unsigned multiplication overflow predicate (negation of OP_BUMUL_NO_OVFL)
|
||||
OP_BSMUL_OVFL, // signed multiplication over/underflow predicate
|
||||
|
||||
OP_BSDIV_OVFL, // signed division overflow perdicate
|
||||
OP_BSDIV_OVFL, // signed division overflow predicate
|
||||
|
||||
OP_BNEG_OVFL, // negation overflow predicate
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ Module Name:
|
|||
|
||||
Abstract:
|
||||
|
||||
char_plugin for unicode suppport
|
||||
char_plugin for unicode support
|
||||
|
||||
Author:
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ Module Name:
|
|||
|
||||
Abstract:
|
||||
|
||||
char_plugin for unicode suppport
|
||||
char_plugin for unicode support
|
||||
|
||||
Author:
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
*
|
||||
* x = t -> fresh
|
||||
* x := if(fresh, t, diff(t))
|
||||
* where diff is a diagnonalization function available in domains of size > 1.
|
||||
* where diff is a diagonalization function available in domains of size > 1.
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -807,7 +807,7 @@ bool iexpr_inverter::uncnstr(unsigned num, expr * const * args) const {
|
|||
|
||||
/**
|
||||
\brief Create a fresh variable for abstracting (f args[0] ... args[num-1])
|
||||
Return true if it a new variable was created, and false if the variable already existed for this
|
||||
Return true if a new variable was created, and false if the variable already existed for this
|
||||
application. Store the variable in v
|
||||
*/
|
||||
void iexpr_inverter::mk_fresh_uncnstr_var_for(sort * s, expr_ref & v) {
|
||||
|
|
|
@ -275,7 +275,7 @@ namespace datatype {
|
|||
}
|
||||
parameter const & name = parameters[0];
|
||||
if (!name.is_symbol()) {
|
||||
TRACE("datatype", tout << "expected symol parameter at position " << 0 << " got: " << name << "\n";);
|
||||
TRACE("datatype", tout << "expected symbol parameter at position " << 0 << " got: " << name << "\n";);
|
||||
throw invalid_datatype();
|
||||
}
|
||||
for (unsigned i = 1; i < num_parameters; ++i) {
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace datatype {
|
|||
class accessor {
|
||||
symbol m_name;
|
||||
sort_ref m_range;
|
||||
unsigned m_index; // reference to recursive data-type may only get resolved after all mutually recursive data-types are procssed.
|
||||
unsigned m_index; // reference to recursive data-type may only get resolved after all mutually recursive data-types are processed.
|
||||
constructor* m_constructor{ nullptr };
|
||||
public:
|
||||
accessor(ast_manager& m, symbol const& n, sort* range):
|
||||
|
|
|
@ -19,7 +19,7 @@ Notes:
|
|||
- data structures form the (legacy) SMT solver.
|
||||
- it still uses eager path compression.
|
||||
|
||||
NB. The worklist is in reality inheritied from the legacy SMT solver.
|
||||
NB. The worklist is in reality inherited from the legacy SMT solver.
|
||||
It is claimed to have the same effect as delayed congruence table reconstruction from egg.
|
||||
Similar to the legacy solver, parents are partially deduplicated.
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ Author:
|
|||
Notes:
|
||||
|
||||
- congruence closure justifications are given a timestamp so it is easy to sort them.
|
||||
See the longer descriptoin in euf_proof_checker.cpp
|
||||
See the longer description in euf_proof_checker.cpp
|
||||
|
||||
--*/
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ bool macro_finder::is_arith_macro(expr * n, proof * pr, bool deps_valid, expr_de
|
|||
// functions introduced within macros are Skolem functions
|
||||
// To avoid unsound expansion of these as macros (because they
|
||||
// appear in model conversions and are therefore not fully
|
||||
// replacable) we prevent these from being treated as macro functions.
|
||||
// replaceable) we prevent these from being treated as macro functions.
|
||||
if (m_macro_manager.contains(f) || f->is_skolem())
|
||||
return false;
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ Revision History:
|
|||
where T[X] does not contain f.
|
||||
|
||||
This class is responsible for storing macros and expanding them.
|
||||
It has support for backtracking and tagging declarations in an expression as forbidded for being macros.
|
||||
It has support for backtracking and tagging declarations in an expression as forbidden for being macros.
|
||||
*/
|
||||
class macro_manager {
|
||||
ast_manager & m;
|
||||
|
|
|
@ -207,7 +207,7 @@ void defined_names::impl::mk_definition(expr * e, app * n, sort_ref_buffer & var
|
|||
// the instantiation rules for store(a, i, v) are:
|
||||
// store(a, i, v)[j] = if i = j then v else a[j] with patterns {a[j], store(a, i, v)} { store(a, i, v)[j] }
|
||||
// The first pattern is not included.
|
||||
// TBD use a model-based scheme for exracting instantiations instead of
|
||||
// TBD use a model-based scheme for extracting instantiations instead of
|
||||
// using multi-patterns.
|
||||
//
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ pattern_inference_cfg::pattern_inference_cfg(ast_manager & m, pattern_inference_
|
|||
m_le(),
|
||||
m_nested_arith_only(true),
|
||||
m_block_loop_patterns(params.m_pi_block_loop_patterns),
|
||||
m_decompose_patterns(params.m_pi_decompose_patterns),
|
||||
m_candidates(m),
|
||||
m_pattern_weight_lt(m_candidates_info),
|
||||
m_collect(m, *this),
|
||||
|
@ -407,6 +408,9 @@ bool pattern_inference_cfg::pattern_weight_lt::operator()(expr * n1, expr * n2)
|
|||
|
||||
|
||||
app* pattern_inference_cfg::mk_pattern(app* candidate) {
|
||||
if (!m_decompose_patterns)
|
||||
return m.mk_pattern(candidate);
|
||||
|
||||
auto has_var_arg = [&](expr* e) {
|
||||
if (!is_app(e))
|
||||
return false;
|
||||
|
|
|
@ -20,6 +20,7 @@ Revision History:
|
|||
|
||||
#include "ast/ast.h"
|
||||
#include "ast/rewriter/rewriter.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "params/pattern_inference_params.h"
|
||||
#include "util/vector.h"
|
||||
#include "util/uint_set.h"
|
||||
|
@ -69,6 +70,7 @@ class pattern_inference_cfg : public default_rewriter_cfg {
|
|||
expr * const * m_no_patterns;
|
||||
bool m_nested_arith_only;
|
||||
bool m_block_loop_patterns;
|
||||
bool m_decompose_patterns;
|
||||
|
||||
struct info {
|
||||
uint_set m_free_vars;
|
||||
|
|
|
@ -260,7 +260,7 @@ class reduce_hypotheses {
|
|||
{ cls.push_back(cls_fact->get_arg(i)); }
|
||||
} else { cls.push_back(cls_fact); }
|
||||
|
||||
// construct new resovent
|
||||
// construct new resolvent
|
||||
ptr_buffer<expr> new_fact_cls;
|
||||
bool found;
|
||||
// XXX quadratic
|
||||
|
@ -604,7 +604,7 @@ public:
|
|||
// -- otherwise, the fact has not changed. nothing to simplify
|
||||
SASSERT(m.get_fact(tmp) == m.get_fact(m.get_parent(p, i)));
|
||||
parents.push_back(tmp);
|
||||
// remember that we have this derivation while we have not poped the trail
|
||||
// remember that we have this derivation while we have not popped the trail
|
||||
// but only if the proof is closed (i.e., a real unit)
|
||||
if (is_closed(tmp) && !m_units.contains(m.get_fact(tmp))) {
|
||||
m_units.insert(m.get_fact(tmp), tmp);
|
||||
|
|
|
@ -1121,7 +1121,7 @@ bool arith_rewriter::divides(expr* num, expr* den, expr_ref& result) {
|
|||
if (m_util.is_numeral(arg, num_r)) num_e = arg;
|
||||
}
|
||||
for (expr* arg : args2) {
|
||||
// dont remove divisor on (div (* -1 x) (* -1 y)) because rewriting would diverge.
|
||||
// don't remove divisor on (div (* -1 x) (* -1 y)) because rewriting would diverge.
|
||||
if (mark.is_marked(arg) && (!m_util.is_numeral(arg, num_r) || !num_r.is_minus_one())) {
|
||||
result = remove_divisor(arg, num, den);
|
||||
return true;
|
||||
|
@ -1569,21 +1569,48 @@ br_status arith_rewriter::mk_to_real_core(expr * arg, expr_ref & result) {
|
|||
}
|
||||
|
||||
br_status arith_rewriter::mk_is_int(expr * arg, expr_ref & result) {
|
||||
numeral a;
|
||||
if (m_util.is_numeral(arg, a)) {
|
||||
result = a.is_int() ? m.mk_true() : m.mk_false();
|
||||
numeral n;
|
||||
|
||||
if (m_util.is_numeral(arg, n)) {
|
||||
result = n.is_int() ? m.mk_true() : m.mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
else if (m_util.is_to_real(arg)) {
|
||||
|
||||
if (m_util.is_to_real(arg)) {
|
||||
result = m.mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
else {
|
||||
result = m.mk_eq(m.mk_app(get_fid(), OP_TO_REAL,
|
||||
m.mk_app(get_fid(), OP_TO_INT, arg)),
|
||||
arg);
|
||||
return BR_REWRITE3;
|
||||
|
||||
ptr_buffer<expr> todo;
|
||||
todo.push_back(arg);
|
||||
expr_fast_mark1 mark;
|
||||
for (unsigned i = 0; i < todo.size(); ++i) {
|
||||
expr* e = todo[i];
|
||||
if (mark.is_marked(e))
|
||||
continue;
|
||||
mark.mark(e, true);
|
||||
if (m_util.is_to_real(e))
|
||||
continue;
|
||||
if (m_util.is_numeral(e, n)) {
|
||||
if (n.is_int())
|
||||
continue;
|
||||
goto bail;
|
||||
}
|
||||
if (m_util.is_mul(e) || m_util.is_add(e) || m_util.is_sub(e) || m_util.is_uminus(e)) {
|
||||
for (expr* a : *to_app(e))
|
||||
todo.push_back(a);
|
||||
continue;
|
||||
}
|
||||
goto bail;
|
||||
}
|
||||
result = m.mk_true();
|
||||
return BR_DONE;
|
||||
|
||||
bail:
|
||||
result = m.mk_eq(m.mk_app(get_fid(), OP_TO_REAL,
|
||||
m.mk_app(get_fid(), OP_TO_INT, arg)),
|
||||
arg);
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
br_status arith_rewriter::mk_abs_core(expr * arg, expr_ref & result) {
|
||||
|
@ -1592,7 +1619,7 @@ br_status arith_rewriter::mk_abs_core(expr * arg, expr_ref & result) {
|
|||
}
|
||||
|
||||
|
||||
// Return true if t is of the form c*Pi where c is a numeral.
|
||||
// Return true if t is of the form c*Pi where c is a numeral.
|
||||
// Store c into k
|
||||
bool arith_rewriter::is_pi_multiple(expr * t, rational & k) {
|
||||
if (m_util.is_pi(t)) {
|
||||
|
@ -1603,7 +1630,7 @@ bool arith_rewriter::is_pi_multiple(expr * t, rational & k) {
|
|||
return m_util.is_mul(t, a, b) && m_util.is_pi(b) && m_util.is_numeral(a, k);
|
||||
}
|
||||
|
||||
// Return true if t is of the form (+ s c*Pi) where c is a numeral.
|
||||
// Return true if t is of the form (+ s c*Pi) where c is a numeral.
|
||||
// Store c into k, and c*Pi into m.
|
||||
bool arith_rewriter::is_pi_offset(expr * t, rational & k, expr * & m) {
|
||||
if (m_util.is_add(t)) {
|
||||
|
@ -1916,7 +1943,7 @@ br_status arith_rewriter::mk_tan_core(expr * arg, expr_ref & result) {
|
|||
br_status arith_rewriter::mk_asin_core(expr * arg, expr_ref & result) {
|
||||
// Remark: we assume that ForAll x : asin(-x) == asin(x).
|
||||
// Mathematica uses this as an axiom. Although asin is an underspecified function for x < -1 or x > 1.
|
||||
// Actually, in Mathematica, asin(x) is a total function that returns a complex number fo x < -1 or x > 1.
|
||||
// Actually, in Mathematica, asin(x) is a total function that returns a complex number for x < -1 or x > 1.
|
||||
rational k;
|
||||
if (is_numeral(arg, k)) {
|
||||
if (k.is_zero()) {
|
||||
|
|
|
@ -26,6 +26,7 @@ Notes:
|
|||
void bool_rewriter::updt_params(params_ref const & _p) {
|
||||
bool_rewriter_params p(_p);
|
||||
m_flat_and_or = p.flat_and_or();
|
||||
m_sort_disjunctions = p.sort_disjunctions();
|
||||
m_elim_and = p.elim_and();
|
||||
m_elim_ite = p.elim_ite();
|
||||
m_local_ctx = p.local_ctx();
|
||||
|
@ -183,7 +184,7 @@ br_status bool_rewriter::mk_flat_and_core(unsigned num_args, expr * const * args
|
|||
}
|
||||
|
||||
br_status bool_rewriter::mk_nflat_or_core(unsigned num_args, expr * const * args, expr_ref & result) {
|
||||
bool s = false;
|
||||
bool s = false; // whether we have canceled some disjuncts or found some out or order
|
||||
ptr_buffer<expr> buffer;
|
||||
expr_fast_mark1 neg_lits;
|
||||
expr_fast_mark2 pos_lits;
|
||||
|
@ -292,8 +293,10 @@ br_status bool_rewriter::mk_nflat_or_core(unsigned num_args, expr * const * args
|
|||
return st;
|
||||
#endif
|
||||
if (s) {
|
||||
ast_lt lt;
|
||||
std::sort(buffer.begin(), buffer.end(), lt);
|
||||
if (m_sort_disjunctions) {
|
||||
ast_lt lt;
|
||||
std::sort(buffer.begin(), buffer.end(), lt);
|
||||
}
|
||||
result = m().mk_or(sz, buffer.data());
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -329,7 +332,7 @@ br_status bool_rewriter::mk_flat_or_core(unsigned num_args, expr * const * args,
|
|||
}
|
||||
}
|
||||
if (mk_nflat_or_core(flat_args.size(), flat_args.data(), result) == BR_FAILED) {
|
||||
if (!ordered) {
|
||||
if (m_sort_disjunctions && !ordered) {
|
||||
ast_lt lt;
|
||||
std::sort(flat_args.begin(), flat_args.end(), lt);
|
||||
}
|
||||
|
@ -662,12 +665,19 @@ br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result)
|
|||
SASSERT(m().is_value(val));
|
||||
|
||||
if (m().are_distinct(val, e)) {
|
||||
mk_eq(t, val, result);
|
||||
if (get_depth(t) < 500)
|
||||
mk_eq(t, val, result);
|
||||
else
|
||||
result = m().mk_eq(t, val);
|
||||
|
||||
result = m().mk_and(result, cond);
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
if (m().are_distinct(val, t)) {
|
||||
mk_eq(e, val, result);
|
||||
if (get_depth(e) < 500)
|
||||
mk_eq(e, val, result);
|
||||
else
|
||||
result = m().mk_eq(e, val);
|
||||
result = m().mk_and(result, m().mk_not(cond));
|
||||
return BR_REWRITE2;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ class bool_rewriter {
|
|||
ast_manager & m_manager;
|
||||
hoist_rewriter m_hoist;
|
||||
bool m_flat_and_or = false;
|
||||
bool m_sort_disjunctions = true;
|
||||
bool m_local_ctx = false;
|
||||
bool m_elim_and = false;
|
||||
bool m_blast_distinct = false;
|
||||
|
|
|
@ -307,7 +307,7 @@ namespace euf {
|
|||
}
|
||||
};
|
||||
SASSERT(e);
|
||||
if (num_scopes() > 0)
|
||||
if (num_scopes() > 0 && m_canonical.size() > n->get_id())
|
||||
m_trail.push(vtrail(m_canonical, n->get_id()));
|
||||
m_canonical.setx(n->get_id(), e);
|
||||
m_epochs.setx(n->get_id(), m_epoch, 0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue