mirror of
https://github.com/Z3Prover/z3
synced 2025-04-22 16:45:31 +00:00
Merge remote-tracking branch 'upstream/master' into fix-length-testing
This commit is contained in:
commit
5e19e905fa
178 changed files with 3204 additions and 1694 deletions
|
@ -34,6 +34,19 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_sort Z3_API Z3_mk_array_sort_n(Z3_context c, unsigned n, Z3_sort const* domain, Z3_sort range) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_array_sort_n(c, n, domain, range);
|
||||
RESET_ERROR_CODE();
|
||||
vector<parameter> params;
|
||||
for (unsigned i = 0; i < n; ++i) params.push_back(parameter(to_sort(domain[i])));
|
||||
params.push_back(parameter(to_sort(range)));
|
||||
sort * ty = mk_c(c)->m().mk_sort(mk_c(c)->get_array_fid(), ARRAY_SORT, params.size(), params.c_ptr());
|
||||
mk_c(c)->save_ast_trail(ty);
|
||||
RETURN_Z3(of_sort(ty));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_select(Z3_context c, Z3_ast a, Z3_ast i) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_select(c, a, i);
|
||||
|
@ -57,6 +70,35 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_select_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_select_n(c, a, n, idxs);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _a = to_expr(a);
|
||||
// expr * _i = to_expr(i);
|
||||
sort * a_ty = m.get_sort(_a);
|
||||
// sort * i_ty = m.get_sort(_i);
|
||||
if (a_ty->get_family_id() != mk_c(c)->get_array_fid()) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<sort> domain;
|
||||
ptr_vector<expr> args;
|
||||
args.push_back(_a);
|
||||
domain.push_back(a_ty);
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
args.push_back(to_expr(idxs[i]));
|
||||
domain.push_back(m.get_sort(to_expr(idxs[i])));
|
||||
}
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_SELECT, 2, a_ty->get_parameters(), domain.size(), domain.c_ptr());
|
||||
app * r = m.mk_app(d, args.size(), args.c_ptr());
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_store(c, a, i, v);
|
||||
|
@ -82,6 +124,37 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_store_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs, Z3_ast v) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_store_n(c, a, n, idxs, v);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
expr * _a = to_expr(a);
|
||||
expr * _v = to_expr(v);
|
||||
sort * a_ty = m.get_sort(_a);
|
||||
sort * v_ty = m.get_sort(_v);
|
||||
if (a_ty->get_family_id() != mk_c(c)->get_array_fid()) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
ptr_vector<sort> domain;
|
||||
ptr_vector<expr> args;
|
||||
args.push_back(_a);
|
||||
domain.push_back(a_ty);
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
args.push_back(to_expr(idxs[i]));
|
||||
domain.push_back(m.get_sort(to_expr(idxs[i])));
|
||||
}
|
||||
args.push_back(_v);
|
||||
domain.push_back(v_ty);
|
||||
func_decl * d = m.mk_func_decl(mk_c(c)->get_array_fid(), OP_STORE, 2, a_ty->get_parameters(), domain.size(), domain.c_ptr());
|
||||
app * r = m.mk_app(d, args.size(), args.c_ptr());
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
check_sorts(c, r);
|
||||
RETURN_Z3(of_ast(r));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_map(Z3_context c, Z3_func_decl f, unsigned n, Z3_ast const* args) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_map(c, f, n, args);
|
||||
|
@ -188,6 +261,18 @@ extern "C" {
|
|||
MK_BINARY(Z3_mk_set_subset, mk_c(c)->get_array_fid(), OP_SET_SUBSET, SKIP);
|
||||
MK_BINARY(Z3_mk_array_ext, mk_c(c)->get_array_fid(), OP_ARRAY_EXT, SKIP);
|
||||
|
||||
Z3_ast Z3_API Z3_mk_as_array(Z3_context c, Z3_func_decl f) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_as_array(c, f);
|
||||
RESET_ERROR_CODE();
|
||||
ast_manager & m = mk_c(c)->m();
|
||||
array_util a(m);
|
||||
app * r = a.mk_as_array(to_func_decl(f));
|
||||
mk_c(c)->save_ast_trail(r);
|
||||
return of_ast(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_mk_set_member(Z3_context c, Z3_ast elem, Z3_ast set) {
|
||||
return Z3_mk_select(c, set, elem);
|
||||
}
|
||||
|
@ -222,7 +307,8 @@ extern "C" {
|
|||
CHECK_VALID_AST(t, 0);
|
||||
if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() &&
|
||||
to_sort(t)->get_decl_kind() == ARRAY_SORT) {
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(1).get_ast());
|
||||
unsigned n = to_sort(t)->get_num_parameters();
|
||||
Z3_sort r = reinterpret_cast<Z3_sort>(to_sort(t)->get_parameter(n-1).get_ast());
|
||||
RETURN_Z3(r);
|
||||
}
|
||||
SET_ERROR_CODE(Z3_INVALID_ARG);
|
||||
|
|
|
@ -1204,12 +1204,8 @@ extern "C" {
|
|||
case OP_FPA_TO_SBV: return Z3_OP_FPA_TO_SBV;
|
||||
case OP_FPA_TO_REAL: return Z3_OP_FPA_TO_REAL;
|
||||
case OP_FPA_TO_IEEE_BV: return Z3_OP_FPA_TO_IEEE_BV;
|
||||
case OP_FPA_MIN_I: return Z3_OP_FPA_MIN_I;
|
||||
case OP_FPA_MAX_I: return Z3_OP_FPA_MAX_I;
|
||||
case OP_FPA_BVWRAP: return Z3_OP_FPA_BVWRAP;
|
||||
case OP_FPA_BV2RM: return Z3_OP_FPA_BV2RM;
|
||||
case OP_FPA_MIN_UNSPECIFIED: return Z3_OP_FPA_MIN_UNSPECIFIED;
|
||||
case OP_FPA_MAX_UNSPECIFIED: return Z3_OP_FPA_MAX_UNSPECIFIED;
|
||||
return Z3_OP_UNINTERPRETED;
|
||||
default:
|
||||
return Z3_OP_INTERNAL;
|
||||
|
|
|
@ -283,15 +283,16 @@ extern "C" {
|
|||
Z3_optimize opt,
|
||||
std::istream& s) {
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
cmd_context ctx(false, &m);
|
||||
install_opt_cmds(ctx, to_optimize_ptr(opt));
|
||||
ctx.set_ignore_check(true);
|
||||
if (!parse_smt2_commands(ctx, s)) {
|
||||
scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &m);
|
||||
install_opt_cmds(*ctx.get(), to_optimize_ptr(opt));
|
||||
ctx->set_ignore_check(true);
|
||||
if (!parse_smt2_commands(*ctx.get(), s)) {
|
||||
ctx = nullptr;
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return;
|
||||
}
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
to_optimize_ptr(opt)->add_hard_constraint(*it);
|
||||
}
|
||||
|
@ -320,9 +321,6 @@ extern "C" {
|
|||
std::ostringstream strm;
|
||||
strm << "Could not open file " << s;
|
||||
throw default_exception(strm.str());
|
||||
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return;
|
||||
}
|
||||
Z3_optimize_from_stream(c, d, is);
|
||||
Z3_CATCH;
|
||||
|
|
|
@ -56,19 +56,20 @@ extern "C" {
|
|||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_parse_smtlib_string(c, str, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
std::ostringstream outs;
|
||||
scoped_ptr<std::ostringstream> outs = alloc(std::ostringstream);
|
||||
bool ok = false;
|
||||
|
||||
RESET_ERROR_CODE();
|
||||
init_smtlib_parser(c, num_sorts, sort_names, sorts, num_decls, decl_names, decls);
|
||||
mk_c(c)->m_smtlib_parser->set_error_stream(outs);
|
||||
mk_c(c)->m_smtlib_parser->set_error_stream(*outs);
|
||||
try {
|
||||
ok = mk_c(c)->m_smtlib_parser->parse_string(str);
|
||||
}
|
||||
catch (...) {
|
||||
ok = false;
|
||||
}
|
||||
mk_c(c)->m_smtlib_error_buffer = outs.str();
|
||||
mk_c(c)->m_smtlib_error_buffer = outs->str();
|
||||
outs = nullptr;
|
||||
if (!ok) {
|
||||
mk_c(c)->reset_parser();
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
|
@ -88,16 +89,17 @@ extern "C" {
|
|||
LOG_Z3_parse_smtlib_file(c, file_name, num_sorts, sort_names, types, num_decls, decl_names, decls);
|
||||
bool ok = false;
|
||||
RESET_ERROR_CODE();
|
||||
std::ostringstream outs;
|
||||
scoped_ptr<std::ostringstream> outs = alloc(std::ostringstream);
|
||||
init_smtlib_parser(c, num_sorts, sort_names, types, num_decls, decl_names, decls);
|
||||
mk_c(c)->m_smtlib_parser->set_error_stream(outs);
|
||||
mk_c(c)->m_smtlib_parser->set_error_stream(*outs);
|
||||
try {
|
||||
ok = mk_c(c)->m_smtlib_parser->parse_file(file_name);
|
||||
}
|
||||
catch(...) {
|
||||
ok = false;
|
||||
}
|
||||
mk_c(c)->m_smtlib_error_buffer = outs.str();
|
||||
mk_c(c)->m_smtlib_error_buffer = outs->str();
|
||||
outs = nullptr;
|
||||
if (!ok) {
|
||||
mk_c(c)->reset_parser();
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
|
@ -260,21 +262,22 @@ extern "C" {
|
|||
Z3_symbol const decl_names[],
|
||||
Z3_func_decl const decls[]) {
|
||||
Z3_TRY;
|
||||
cmd_context ctx(false, &(mk_c(c)->m()));
|
||||
ctx.set_ignore_check(true);
|
||||
scoped_ptr<cmd_context> ctx = alloc(cmd_context, false, &(mk_c(c)->m()));
|
||||
ctx->set_ignore_check(true);
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
ctx.insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
|
||||
ctx->insert(to_symbol(decl_names[i]), to_func_decl(decls[i]));
|
||||
}
|
||||
for (unsigned i = 0; i < num_sorts; ++i) {
|
||||
psort* ps = ctx.pm().mk_psort_cnst(to_sort(sorts[i]));
|
||||
ctx.insert(ctx.pm().mk_psort_user_decl(0, to_symbol(sort_names[i]), ps));
|
||||
psort* ps = ctx->pm().mk_psort_cnst(to_sort(sorts[i]));
|
||||
ctx->insert(ctx->pm().mk_psort_user_decl(0, to_symbol(sort_names[i]), ps));
|
||||
}
|
||||
if (!parse_smt2_commands(ctx, is)) {
|
||||
if (!parse_smt2_commands(*ctx.get(), is)) {
|
||||
ctx = nullptr;
|
||||
SET_ERROR_CODE(Z3_PARSER_ERROR);
|
||||
return of_ast(mk_c(c)->m().mk_true());
|
||||
}
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
ptr_vector<expr>::const_iterator it = ctx->begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx->end_assertions();
|
||||
unsigned size = static_cast<unsigned>(end - it);
|
||||
return of_ast(mk_c(c)->mk_and(size, it));
|
||||
Z3_CATCH_RETURN(0);
|
||||
|
|
|
@ -63,9 +63,11 @@ extern "C" {
|
|||
RESET_ERROR_CODE();
|
||||
if (!mk_c(c)->m().is_bool(to_expr(body))) {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return nullptr;
|
||||
}
|
||||
if (num_patterns > 0 && num_no_patterns > 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
return nullptr;
|
||||
}
|
||||
expr * const* ps = reinterpret_cast<expr * const*>(patterns);
|
||||
expr * const* no_ps = reinterpret_cast<expr * const*>(no_patterns);
|
||||
|
@ -76,7 +78,7 @@ extern "C" {
|
|||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
if (!v(num_decls, ps[i], 0, 0)) {
|
||||
SET_ERROR_CODE(Z3_INVALID_PATTERN);
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -442,6 +442,7 @@ extern "C" {
|
|||
unsigned sz = __assumptions.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
if (!is_expr(__assumptions[i])) {
|
||||
_assumptions.finalize(); _consequences.finalize(); _variables.finalize();
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
|
@ -451,6 +452,7 @@ extern "C" {
|
|||
sz = __variables.size();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
if (!is_expr(__variables[i])) {
|
||||
_assumptions.finalize(); _consequences.finalize(); _variables.finalize();
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
|
@ -471,6 +473,7 @@ extern "C" {
|
|||
}
|
||||
catch (z3_exception & ex) {
|
||||
to_solver_ref(s)->set_reason_unknown(eh);
|
||||
_assumptions.finalize(); _consequences.finalize(); _variables.finalize();
|
||||
mk_c(c)->handle_exception(ex);
|
||||
return Z3_L_UNDEF;
|
||||
}
|
||||
|
|
|
@ -140,18 +140,17 @@ namespace z3 {
|
|||
class context {
|
||||
bool m_enable_exceptions;
|
||||
Z3_context m_ctx;
|
||||
static void error_handler(Z3_context /*c*/, Z3_error_code /*e*/) { /* do nothing */ }
|
||||
void init(config & c) {
|
||||
m_ctx = Z3_mk_context_rc(c);
|
||||
m_enable_exceptions = true;
|
||||
Z3_set_error_handler(m_ctx, error_handler);
|
||||
Z3_set_error_handler(m_ctx, 0);
|
||||
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
||||
}
|
||||
|
||||
void init_interp(config & c) {
|
||||
m_ctx = Z3_mk_interpolation_context(c);
|
||||
m_enable_exceptions = true;
|
||||
Z3_set_error_handler(m_ctx, error_handler);
|
||||
Z3_set_error_handler(m_ctx, 0);
|
||||
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
||||
}
|
||||
|
||||
|
@ -251,6 +250,8 @@ namespace z3 {
|
|||
Example: Given a context \c c, <tt>c.array_sort(c.int_sort(), c.bool_sort())</tt> is an array sort from integer to Boolean.
|
||||
*/
|
||||
sort array_sort(sort d, sort r);
|
||||
sort array_sort(sort_vector const& d, sort r);
|
||||
|
||||
/**
|
||||
\brief Return an enumeration sort: enum_names[0], ..., enum_names[n-1].
|
||||
\c cs and \c ts are output parameters. The method stores in \c cs the constants corresponding to the enumerated elements,
|
||||
|
@ -354,7 +355,7 @@ namespace z3 {
|
|||
Z3_error_code check_error() const { return m_ctx->check_error(); }
|
||||
friend void check_context(object const & a, object const & b);
|
||||
};
|
||||
inline void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); }
|
||||
inline void check_context(object const & a, object const & b) { (void)a; (void)b; assert(a.m_ctx == b.m_ctx); }
|
||||
|
||||
class symbol : public object {
|
||||
Z3_symbol m_sym;
|
||||
|
@ -2328,6 +2329,11 @@ namespace z3 {
|
|||
inline sort context::re_sort(sort& s) { Z3_sort r = Z3_mk_re_sort(m_ctx, s); check_error(); return sort(*this, r); }
|
||||
|
||||
inline sort context::array_sort(sort d, sort r) { Z3_sort s = Z3_mk_array_sort(m_ctx, d, r); check_error(); return sort(*this, s); }
|
||||
inline sort context::array_sort(sort_vector const& d, sort r) {
|
||||
array<Z3_sort> dom(d);
|
||||
Z3_sort s = Z3_mk_array_sort_n(m_ctx, dom.size(), dom.ptr(), r); check_error(); return sort(*this, s);
|
||||
}
|
||||
|
||||
inline sort context::enumeration_sort(char const * name, unsigned n, char const * const * enum_names, func_decl_vector & cs, func_decl_vector & ts) {
|
||||
array<Z3_symbol> _enum_names(n);
|
||||
for (unsigned i = 0; i < n; i++) { _enum_names[i] = Z3_mk_string_symbol(*this, enum_names[i]); }
|
||||
|
@ -2574,11 +2580,32 @@ namespace z3 {
|
|||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
inline expr select(expr const & a, expr_vector const & i) {
|
||||
check_context(a, i);
|
||||
array<Z3_ast> idxs(i);
|
||||
Z3_ast r = Z3_mk_select_n(a.ctx(), a, idxs.size(), idxs.ptr());
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr store(expr const & a, int i, expr const & v) { return store(a, a.ctx().num_val(i, a.get_sort().array_domain()), v); }
|
||||
inline expr store(expr const & a, expr i, int v) { return store(a, i, a.ctx().num_val(v, a.get_sort().array_range())); }
|
||||
inline expr store(expr const & a, int i, int v) {
|
||||
return store(a, a.ctx().num_val(i, a.get_sort().array_domain()), a.ctx().num_val(v, a.get_sort().array_range()));
|
||||
}
|
||||
inline expr store(expr const & a, expr_vector const & i, expr const & v) {
|
||||
check_context(a, i); check_context(a, v);
|
||||
array<Z3_ast> idxs(i);
|
||||
Z3_ast r = Z3_mk_store_n(a.ctx(), a, idxs.size(), idxs.ptr(), v);
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr as_array(func_decl & f) {
|
||||
Z3_ast r = Z3_mk_as_array(f.ctx(), f);
|
||||
f.check_error();
|
||||
return expr(f.ctx(), r);
|
||||
}
|
||||
|
||||
#define MK_EXPR1(_fn, _arg) \
|
||||
Z3_ast r = _fn(_arg.ctx(), _arg); \
|
||||
|
|
|
@ -63,6 +63,13 @@ namespace Microsoft.Z3
|
|||
Contract.Requires(domain != null);
|
||||
Contract.Requires(range != null);
|
||||
}
|
||||
internal ArraySort(Context ctx, Sort[] domain, Sort range)
|
||||
: base(ctx, Native.Z3_mk_array_sort_n(ctx.nCtx, (uint)domain.Length, AST.ArrayToNative(domain), range.NativeObject))
|
||||
{
|
||||
Contract.Requires(ctx != null);
|
||||
Contract.Requires(domain != null);
|
||||
Contract.Requires(range != null);
|
||||
}
|
||||
#endregion
|
||||
};
|
||||
|
||||
|
|
|
@ -274,6 +274,20 @@ namespace Microsoft.Z3
|
|||
return new ArraySort(this, domain, range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new n-ary array sort.
|
||||
/// </summary>
|
||||
public ArraySort MkArraySort(Sort[] domain, Sort range)
|
||||
{
|
||||
Contract.Requires(domain != null);
|
||||
Contract.Requires(range != null);
|
||||
Contract.Ensures(Contract.Result<ArraySort>() != null);
|
||||
|
||||
CheckContextMatch<Sort>(domain);
|
||||
CheckContextMatch(range);
|
||||
return new ArraySort(this, domain, range);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new tuple sort.
|
||||
/// </summary>
|
||||
|
@ -2113,6 +2127,7 @@ namespace Microsoft.Z3
|
|||
return (ArrayExpr)MkConst(MkSymbol(name), MkArraySort(domain, range));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Array read.
|
||||
/// </summary>
|
||||
|
@ -2123,8 +2138,8 @@ namespace Microsoft.Z3
|
|||
/// The node <c>a</c> must have an array sort <c>[domain -> range]</c>,
|
||||
/// and <c>i</c> must have the sort <c>domain</c>.
|
||||
/// The sort of the result is <c>range</c>.
|
||||
/// <seealso cref="MkArraySort"/>
|
||||
/// <seealso cref="MkStore"/>
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkStore(ArrayExpr, Expr, Expr)"/>
|
||||
/// </remarks>
|
||||
public Expr MkSelect(ArrayExpr a, Expr i)
|
||||
{
|
||||
|
@ -2137,6 +2152,30 @@ namespace Microsoft.Z3
|
|||
return Expr.Create(this, Native.Z3_mk_select(nCtx, a.NativeObject, i.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Array read.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The argument <c>a</c> is the array and <c>args</c> are the indices
|
||||
/// of the array that gets read.
|
||||
///
|
||||
/// The node <c>a</c> must have an array sort <c>[domain1,..,domaink -> range]</c>,
|
||||
/// and <c>args</c> must have the sort <c>domain1,..,domaink</c>.
|
||||
/// The sort of the result is <c>range</c>.
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkStore(ArrayExpr, Expr, Expr)"/>
|
||||
/// </remarks>
|
||||
public Expr MkSelect(ArrayExpr a, params Expr[] args)
|
||||
{
|
||||
Contract.Requires(a != null);
|
||||
Contract.Requires(args != null && Contract.ForAll(args, n => n != null));
|
||||
Contract.Ensures(Contract.Result<Expr>() != null);
|
||||
|
||||
CheckContextMatch(a);
|
||||
CheckContextMatch<Expr>(args);
|
||||
return Expr.Create(this, Native.Z3_mk_select_n(nCtx, a.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Array update.
|
||||
/// </summary>
|
||||
|
@ -2151,8 +2190,9 @@ namespace Microsoft.Z3
|
|||
/// on all indices except for <c>i</c>, where it maps to <c>v</c>
|
||||
/// (and the <c>select</c> of <c>a</c> with
|
||||
/// respect to <c>i</c> may be a different value).
|
||||
/// <seealso cref="MkArraySort"/>
|
||||
/// <seealso cref="MkSelect"/>
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr[])"/>
|
||||
/// </remarks>
|
||||
public ArrayExpr MkStore(ArrayExpr a, Expr i, Expr v)
|
||||
{
|
||||
|
@ -2167,14 +2207,45 @@ namespace Microsoft.Z3
|
|||
return new ArrayExpr(this, Native.Z3_mk_store(nCtx, a.NativeObject, i.NativeObject, v.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Array update.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The node <c>a</c> must have an array sort <c>[domain1,..,domaink -> range]</c>,
|
||||
/// <c>args</c> must have sort <c>domain1,..,domaink</c>,
|
||||
/// <c>v</c> must have sort range. The sort of the result is <c>[domain -> range]</c>.
|
||||
/// The semantics of this function is given by the theory of arrays described in the SMT-LIB
|
||||
/// standard. See http://smtlib.org for more details.
|
||||
/// The result of this function is an array that is equal to <c>a</c>
|
||||
/// (with respect to <c>select</c>)
|
||||
/// on all indices except for <c>args</c>, where it maps to <c>v</c>
|
||||
/// (and the <c>select</c> of <c>a</c> with
|
||||
/// respect to <c>args</c> may be a different value).
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr[])"/>
|
||||
/// </remarks>
|
||||
public ArrayExpr MkStore(ArrayExpr a, Expr[] args, Expr v)
|
||||
{
|
||||
Contract.Requires(a != null);
|
||||
Contract.Requires(args != null);
|
||||
Contract.Requires(v != null);
|
||||
Contract.Ensures(Contract.Result<ArrayExpr>() != null);
|
||||
|
||||
CheckContextMatch<Expr>(args);
|
||||
CheckContextMatch(a);
|
||||
CheckContextMatch(v);
|
||||
return new ArrayExpr(this, Native.Z3_mk_store_n(nCtx, a.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args), v.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a constant array.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The resulting term is an array, such that a <c>select</c>on an arbitrary index
|
||||
/// produces the value <c>v</c>.
|
||||
/// <seealso cref="MkArraySort"/>
|
||||
/// <seealso cref="MkSelect"/>
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
|
||||
/// </remarks>
|
||||
public ArrayExpr MkConstArray(Sort domain, Expr v)
|
||||
{
|
||||
|
@ -2194,9 +2265,9 @@ namespace Microsoft.Z3
|
|||
/// Eeach element of <c>args</c> must be of an array sort <c>[domain_i -> range_i]</c>.
|
||||
/// The function declaration <c>f</c> must have type <c> range_1 .. range_n -> range</c>.
|
||||
/// <c>v</c> must have sort range. The sort of the result is <c>[domain_i -> range]</c>.
|
||||
/// <seealso cref="MkArraySort"/>
|
||||
/// <seealso cref="MkSelect"/>
|
||||
/// <seealso cref="MkStore"/>
|
||||
/// <seealso cref="MkArraySort(Sort, Sort)"/>
|
||||
/// <seealso cref="MkSelect(ArrayExpr, Expr)"/>
|
||||
/// <seealso cref="MkStore(ArrayExpr, Expr, Expr)"/>
|
||||
/// </remarks>
|
||||
public ArrayExpr MkMap(FuncDecl f, params ArrayExpr[] args)
|
||||
{
|
||||
|
|
|
@ -56,4 +56,10 @@ public class ArraySort extends Sort
|
|||
super(ctx, Native.mkArraySort(ctx.nCtx(), domain.getNativeObject(),
|
||||
range.getNativeObject()));
|
||||
}
|
||||
|
||||
ArraySort(Context ctx, Sort[] domains, Sort range)
|
||||
{
|
||||
super(ctx, Native.mkArraySortN(ctx.nCtx(), domains.length, AST.arrayToNative(domains),
|
||||
range.getNativeObject()));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -224,6 +224,17 @@ public class Context implements AutoCloseable {
|
|||
return new ArraySort(this, domain, range);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new array sort.
|
||||
**/
|
||||
public ArraySort mkArraySort(Sort[] domains, Sort range)
|
||||
{
|
||||
checkContextMatch(domains);
|
||||
checkContextMatch(range);
|
||||
return new ArraySort(this, domains, range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new string sort
|
||||
**/
|
||||
|
@ -414,7 +425,7 @@ public class Context implements AutoCloseable {
|
|||
* that is passed in as argument is updated with value v,
|
||||
* the remaining fields of t are unchanged.
|
||||
**/
|
||||
public Expr MkUpdateField(FuncDecl field, Expr t, Expr v)
|
||||
public Expr mkUpdateField(FuncDecl field, Expr t, Expr v)
|
||||
throws Z3Exception
|
||||
{
|
||||
return Expr.create (this,
|
||||
|
@ -706,7 +717,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Mk an expression representing {@code not(a)}.
|
||||
* Create an expression representing {@code not(a)}.
|
||||
**/
|
||||
public BoolExpr mkNot(BoolExpr a)
|
||||
{
|
||||
|
@ -1679,6 +1690,28 @@ public class Context implements AutoCloseable {
|
|||
i.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Array read.
|
||||
* Remarks: The argument {@code a} is the array and
|
||||
* {@code args} are the indices of the array that gets read.
|
||||
*
|
||||
* The node {@code a} must have an array sort
|
||||
* {@code [domains -> range]}, and {@code args} must have the sorts
|
||||
* {@code domains}. The sort of the result is {@code range}.
|
||||
*
|
||||
* @see #mkArraySort
|
||||
* @see #mkStore
|
||||
|
||||
**/
|
||||
public Expr mkSelect(ArrayExpr a, Expr[] args)
|
||||
{
|
||||
checkContextMatch(a);
|
||||
checkContextMatch(args);
|
||||
return Expr.create(
|
||||
this,
|
||||
Native.mkSelectN(nCtx(), a.getNativeObject(), args.length, AST.arrayToNative(args)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Array update.
|
||||
* Remarks: The node {@code a} must have an array sort
|
||||
|
@ -1704,6 +1737,31 @@ public class Context implements AutoCloseable {
|
|||
i.getNativeObject(), v.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Array update.
|
||||
* Remarks: The node {@code a} must have an array sort
|
||||
* {@code [domains -> range]}, {@code i} must have sort
|
||||
* {@code domain}, {@code v} must have sort range. The sort of the
|
||||
* result is {@code [domains -> range]}. The semantics of this function
|
||||
* is given by the theory of arrays described in the SMT-LIB standard. See
|
||||
* http://smtlib.org for more details. The result of this function is an
|
||||
* array that is equal to {@code a} (with respect to
|
||||
* {@code select}) on all indices except for {@code args}, where it
|
||||
* maps to {@code v} (and the {@code select} of {@code a}
|
||||
* with respect to {@code args} may be a different value).
|
||||
* @see #mkArraySort
|
||||
* @see #mkSelect
|
||||
|
||||
**/
|
||||
public ArrayExpr mkStore(ArrayExpr a, Expr[] args, Expr v)
|
||||
{
|
||||
checkContextMatch(a);
|
||||
checkContextMatch(args);
|
||||
checkContextMatch(v);
|
||||
return new ArrayExpr(this, Native.mkStoreN(nCtx(), a.getNativeObject(),
|
||||
args.length, AST.arrayToNative(args), v.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a constant array.
|
||||
* Remarks: The resulting term is an array, such
|
||||
|
@ -2104,7 +2162,7 @@ public class Context implements AutoCloseable {
|
|||
/**
|
||||
* Create a range expression.
|
||||
*/
|
||||
public ReExpr MkRange(SeqExpr lo, SeqExpr hi)
|
||||
public ReExpr mkRange(SeqExpr lo, SeqExpr hi)
|
||||
{
|
||||
checkContextMatch(lo, hi);
|
||||
return (ReExpr) Expr.create(this, Native.mkReRange(nCtx(), lo.getNativeObject(), hi.getNativeObject()));
|
||||
|
|
|
@ -120,7 +120,7 @@ def _get_args(args):
|
|||
try:
|
||||
if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)):
|
||||
return args[0]
|
||||
elif len(args) == 1 and isinstance(args[0], set):
|
||||
elif len(args) == 1 and (isinstance(args[0], set) or isinstance(args[0], AstVector)):
|
||||
return [arg for arg in args[0]]
|
||||
else:
|
||||
return args
|
||||
|
|
|
@ -993,18 +993,6 @@ typedef enum
|
|||
3 = 011 = Z3_OP_FPA_RM_TOWARD_NEGATIVE,
|
||||
4 = 100 = Z3_OP_FPA_RM_TOWARD_ZERO.
|
||||
|
||||
- Z3_OP_FPA_MIN_I: The same as Z3_OP_FPA_MIN, but the arguments are
|
||||
expected not to be zeroes with different signs.
|
||||
|
||||
- Z3_OP_FPA_MAX_I: The same as Z3_OP_FPA_MAX, but the arguments are
|
||||
expected not to be zeroes with different signs.
|
||||
|
||||
- Z3_OP_FPA_MIN_UNSPECIFIED: The same as Z3_OP_FPA_MIN, but the
|
||||
arguments are expected to be zeroes with different signs.
|
||||
|
||||
- Z3_OP_FPA_MAX_UNSPECIFIED: The same as Z3_OP_FPA_MAX, but the
|
||||
arguments are expected to be zeroes with different signs.
|
||||
|
||||
- Z3_OP_INTERNAL: internal (often interpreted) symbol, but no additional
|
||||
information is exposed. Tools may use the string representation of the
|
||||
function declaration to obtain more information.
|
||||
|
@ -1291,13 +1279,8 @@ typedef enum {
|
|||
|
||||
Z3_OP_FPA_TO_IEEE_BV,
|
||||
|
||||
Z3_OP_FPA_MIN_I,
|
||||
Z3_OP_FPA_MAX_I,
|
||||
|
||||
Z3_OP_FPA_BVWRAP,
|
||||
Z3_OP_FPA_BV2RM,
|
||||
Z3_OP_FPA_MIN_UNSPECIFIED,
|
||||
Z3_OP_FPA_MAX_UNSPECIFIED,
|
||||
|
||||
Z3_OP_INTERNAL,
|
||||
|
||||
|
@ -1898,6 +1881,17 @@ extern "C" {
|
|||
*/
|
||||
Z3_sort Z3_API Z3_mk_array_sort(Z3_context c, Z3_sort domain, Z3_sort range);
|
||||
|
||||
/**
|
||||
\brief Create an array type with N arguments
|
||||
|
||||
\sa Z3_mk_select_n
|
||||
\sa Z3_mk_store_n
|
||||
|
||||
def_API('Z3_mk_array_sort_n', SORT, (_in(CONTEXT), _in(UINT), _in_array(1, SORT), _in(SORT)))
|
||||
*/
|
||||
Z3_sort Z3_API Z3_mk_array_sort_n(Z3_context c, unsigned n, Z3_sort const * domain, Z3_sort range);
|
||||
|
||||
|
||||
/**
|
||||
\brief Create a tuple type.
|
||||
|
||||
|
@ -2990,6 +2984,15 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_select(Z3_context c, Z3_ast a, Z3_ast i);
|
||||
|
||||
/**
|
||||
\brief n-ary Array read.
|
||||
The argument \c a is the array and \c idxs are the indices of the array that gets read.
|
||||
|
||||
def_API('Z3_mk_select_n', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST)))
|
||||
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_select_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs);
|
||||
|
||||
/**
|
||||
\brief Array update.
|
||||
|
||||
|
@ -3008,6 +3011,14 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v);
|
||||
|
||||
/**
|
||||
\brief n-ary Array update.
|
||||
|
||||
def_API('Z3_mk_store_n', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST), _in(AST)))
|
||||
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_store_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs, Z3_ast v);
|
||||
|
||||
/**
|
||||
\brief Create the constant array.
|
||||
|
||||
|
@ -3048,6 +3059,15 @@ extern "C" {
|
|||
def_API('Z3_mk_array_default', AST, (_in(CONTEXT), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_array_default(Z3_context c, Z3_ast array);
|
||||
|
||||
/**
|
||||
\brief Create array with the same interpretation as a function.
|
||||
The array satisfies the property (f x) = (select (_ as-array f) x)
|
||||
for every argument x.
|
||||
|
||||
def_API('Z3_mk_as_array', AST, (_in(CONTEXT), _in(FUNC_DECL)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_as_array(Z3_context c, Z3_func_decl f);
|
||||
/*@}*/
|
||||
|
||||
/** @name Sets */
|
||||
|
@ -3871,6 +3891,7 @@ extern "C" {
|
|||
|
||||
/**
|
||||
\brief Return the domain of the given array sort.
|
||||
In the case of a multi-dimensional array, this function returns the sort of the first dimension.
|
||||
|
||||
\pre Z3_get_sort_kind(c, t) == Z3_ARRAY_SORT
|
||||
|
||||
|
|
|
@ -197,4 +197,4 @@ extern "C" {
|
|||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -242,7 +242,9 @@ func_decl* array_decl_plugin::mk_select(unsigned arity, sort * const * domain) {
|
|||
parameter const* parameters = s->get_parameters();
|
||||
|
||||
if (num_parameters != arity) {
|
||||
m_manager->raise_exception("select requires as many arguments as the size of the domain");
|
||||
std::stringstream strm;
|
||||
strm << "select requires " << num_parameters << " arguments, but was provided with " << arity << " arguments";
|
||||
m_manager->raise_exception(strm.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
ptr_buffer<sort> new_domain; // we need this because of coercions.
|
||||
|
@ -314,7 +316,7 @@ func_decl * array_decl_plugin::mk_array_ext(unsigned arity, sort * const * domai
|
|||
return 0;
|
||||
}
|
||||
sort * r = to_sort(s->get_parameter(i).get_ast());
|
||||
parameter param(s);
|
||||
parameter param(i);
|
||||
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, func_decl_info(m_family_id, OP_ARRAY_EXT, 1, ¶m));
|
||||
}
|
||||
|
||||
|
@ -592,3 +594,9 @@ sort * array_util::mk_array_sort(unsigned arity, sort* const* domain, sort* rang
|
|||
params.push_back(parameter(range));
|
||||
return m_manager.mk_sort(m_fid, ARRAY_SORT, params.size(), params.c_ptr());
|
||||
}
|
||||
|
||||
func_decl* array_util::mk_array_ext(sort *domain, unsigned i) {
|
||||
sort * domains[2] = { domain, domain };
|
||||
parameter p(i);
|
||||
return m_manager.mk_func_decl(m_fid, OP_ARRAY_EXT, 1, &p, 2, domains);
|
||||
}
|
||||
|
|
|
@ -143,6 +143,7 @@ public:
|
|||
bool is_const(expr* n) const { return is_app_of(n, m_fid, OP_CONST_ARRAY); }
|
||||
bool is_map(expr* n) const { return is_app_of(n, m_fid, OP_ARRAY_MAP); }
|
||||
bool is_as_array(expr * n) const { return is_app_of(n, m_fid, OP_AS_ARRAY); }
|
||||
bool is_as_array(expr * n, func_decl*& f) const { return is_as_array(n) && (f = get_as_array_func_decl(n), true); }
|
||||
bool is_select(func_decl* f) const { return is_decl_of(f, m_fid, OP_SELECT); }
|
||||
bool is_store(func_decl* f) const { return is_decl_of(f, m_fid, OP_STORE); }
|
||||
bool is_const(func_decl* f) const { return is_decl_of(f, m_fid, OP_CONST_ARRAY); }
|
||||
|
@ -182,13 +183,15 @@ public:
|
|||
return mk_const_array(s, m_manager.mk_true());
|
||||
}
|
||||
|
||||
func_decl * mk_array_ext(sort* domain, unsigned i);
|
||||
|
||||
sort * mk_array_sort(sort* dom, sort* range) { return mk_array_sort(1, &dom, range); }
|
||||
|
||||
sort * mk_array_sort(unsigned arity, sort* const* domain, sort* range);
|
||||
|
||||
app * mk_as_array(sort * s, func_decl * f) {
|
||||
app * mk_as_array(func_decl * f) {
|
||||
parameter param(f);
|
||||
return m_manager.mk_app(m_fid, OP_AS_ARRAY, 1, ¶m, 0, 0, s);
|
||||
return m_manager.mk_app(m_fid, OP_AS_ARRAY, 1, ¶m, 0, 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -471,6 +471,9 @@ bool compare_nodes(ast const * n1, ast const * n2) {
|
|||
compare_arrays(to_quantifier(n1)->get_decl_sorts(),
|
||||
to_quantifier(n2)->get_decl_sorts(),
|
||||
to_quantifier(n1)->get_num_decls()) &&
|
||||
compare_arrays(to_quantifier(n1)->get_decl_names(),
|
||||
to_quantifier(n2)->get_decl_names(),
|
||||
to_quantifier(n1)->get_num_decls()) &&
|
||||
to_quantifier(n1)->get_expr() == to_quantifier(n2)->get_expr() &&
|
||||
to_quantifier(n1)->get_weight() == to_quantifier(n2)->get_weight() &&
|
||||
to_quantifier(n1)->get_num_patterns() == to_quantifier(n2)->get_num_patterns() &&
|
||||
|
@ -765,7 +768,7 @@ func_decl * basic_decl_plugin::mk_compressed_proof_decl(char const * name, basic
|
|||
|
||||
func_decl * basic_decl_plugin::mk_proof_decl(char const * name, basic_op_kind k, unsigned num_parents, ptr_vector<func_decl> & cache) {
|
||||
if (num_parents >= cache.size()) {
|
||||
cache.resize(num_parents+1, 0);
|
||||
cache.resize(num_parents+1);
|
||||
}
|
||||
if (cache[num_parents] == 0) {
|
||||
cache[num_parents] = mk_proof_decl(name, k, num_parents);
|
||||
|
|
|
@ -121,6 +121,20 @@ public:
|
|||
explicit parameter(unsigned ext_id, bool):m_kind(PARAM_EXTERNAL), m_ext_id(ext_id) {}
|
||||
parameter(parameter const&);
|
||||
|
||||
parameter(parameter && other) : m_kind(other.m_kind) {
|
||||
switch (other.m_kind) {
|
||||
case PARAM_INT: m_int = other.get_int(); break;
|
||||
case PARAM_AST: m_ast = other.get_ast(); break;
|
||||
case PARAM_SYMBOL: m_symbol = other.m_symbol; break;
|
||||
case PARAM_RATIONAL: m_rational = 0; std::swap(m_rational, other.m_rational); break;
|
||||
case PARAM_DOUBLE: m_dval = other.m_dval; break;
|
||||
case PARAM_EXTERNAL: m_ext_id = other.m_ext_id; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
~parameter();
|
||||
|
||||
parameter& operator=(parameter const& other);
|
||||
|
|
|
@ -584,6 +584,8 @@ class smt2_printer {
|
|||
string_buffer<> buf;
|
||||
buf.append("(:var ");
|
||||
buf.append(v->get_idx());
|
||||
//buf.append(" ");
|
||||
//buf.append(v->get_sort()->get_name().str().c_str());
|
||||
buf.append(")");
|
||||
f = mk_string(m(), buf.c_str());
|
||||
}
|
||||
|
|
|
@ -863,8 +863,7 @@ app * bv_util::mk_numeral(rational const & val, sort* s) const {
|
|||
}
|
||||
|
||||
app * bv_util::mk_numeral(rational const & val, unsigned bv_size) const {
|
||||
parameter p1(val);
|
||||
parameter p[2] = { p1, parameter(static_cast<int>(bv_size)) };
|
||||
parameter p[2] = { parameter(val), parameter(static_cast<int>(bv_size)) };
|
||||
return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ Notes:
|
|||
|
||||
#include "ast/expr_abstract.h"
|
||||
#include "util/map.h"
|
||||
#include "ast/ast_pp.h"
|
||||
|
||||
void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
|
||||
|
||||
|
@ -109,6 +110,9 @@ void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const*
|
|||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
|
||||
expr_abstractor abs(m);
|
||||
abs(base, num_bound, bound, n, result);
|
||||
TRACE("expr_abstract",
|
||||
tout << expr_ref(n, m) << "\n";
|
||||
tout << result << "\n";);
|
||||
}
|
||||
|
||||
expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app* const* bound, expr* n) {
|
||||
|
@ -123,6 +127,11 @@ expr_ref mk_quantifier(bool is_forall, ast_manager& m, unsigned num_bound, app*
|
|||
}
|
||||
result = m.mk_quantifier(is_forall, num_bound, sorts.c_ptr(), names.c_ptr(), result);
|
||||
}
|
||||
TRACE("expr_abstract",
|
||||
tout << expr_ref(n, m) << "\n";
|
||||
for (unsigned i = 0; i < num_bound; ++i) tout << expr_ref(bound[i], m) << " ";
|
||||
tout << "\n";
|
||||
tout << result << "\n";);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
|
|
@ -16,8 +16,9 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include "ast/expr_substitution.h"
|
||||
#include "util/ref_util.h"
|
||||
#include "ast/expr_substitution.h"
|
||||
#include "ast/ast_pp.h"
|
||||
|
||||
typedef obj_map<expr, proof*> expr2proof;
|
||||
typedef obj_map<expr, expr_dependency*> expr2expr_dependency;
|
||||
|
@ -56,6 +57,13 @@ expr_substitution::~expr_substitution() {
|
|||
reset();
|
||||
}
|
||||
|
||||
std::ostream& expr_substitution::display(std::ostream& out) {
|
||||
for (auto & kv : m_subst) {
|
||||
out << mk_pp(kv.m_key, m()) << " |-> " << mk_pp(kv.m_value, m()) << "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void expr_substitution::insert(expr * c, expr * def, proof * def_pr, expr_dependency * def_dep) {
|
||||
obj_map<expr, expr*>::obj_map_entry * entry = m_subst.insert_if_not_there2(c, 0);
|
||||
if (entry->get_data().m_value == 0) {
|
||||
|
|
|
@ -50,6 +50,8 @@ public:
|
|||
bool contains(expr * s);
|
||||
void reset();
|
||||
void cleanup();
|
||||
|
||||
std::ostream& display(std::ostream& out);
|
||||
};
|
||||
|
||||
class scoped_expr_substitution {
|
||||
|
@ -78,12 +80,14 @@ public:
|
|||
m_trail_lim.resize(new_sz);
|
||||
}
|
||||
}
|
||||
unsigned scope_level() const { return m_trail_lim.size(); }
|
||||
bool empty() const { return m_subst.empty(); }
|
||||
expr* find(expr * e) { proof* pr; expr* d = 0; if (find(e, d, pr)) return d; else return e; }
|
||||
bool find(expr * s, expr * & def, proof * & def_pr) { return m_subst.find(s, def, def_pr); }
|
||||
bool find(expr * s, expr * & def, proof * & def_pr, expr_dependency * & def_dep) { return m_subst.find(s, def, def_pr, def_dep); }
|
||||
bool contains(expr * s) { return m_subst.contains(s); }
|
||||
void cleanup() { m_subst.cleanup(); }
|
||||
std::ostream& display(std::ostream& out) { return m_subst.display(out); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -62,8 +62,8 @@ bv2fpa_converter::bv2fpa_converter(ast_manager & m, fpa2bv_converter & conv) :
|
|||
m.inc_ref(it->m_key);
|
||||
m.inc_ref(it->m_value);
|
||||
}
|
||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = conv.m_min_max_specials.begin();
|
||||
it != conv.m_min_max_specials.end();
|
||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = conv.m_min_max_ufs.begin();
|
||||
it != conv.m_min_max_ufs.end();
|
||||
it++) {
|
||||
m_specials.insert(it->m_key, it->m_value);
|
||||
m.inc_ref(it->m_key);
|
||||
|
@ -250,7 +250,7 @@ bv2fpa_converter::array_model bv2fpa_converter::convert_array_func_interp(model_
|
|||
am.new_float_fd = m.mk_fresh_func_decl(arity, array_domain.c_ptr(), rng);
|
||||
am.new_float_fi = convert_func_interp(mc, am.new_float_fd, bv_f);
|
||||
am.bv_fd = bv_f;
|
||||
am.result = arr_util.mk_as_array(f->get_range(), am.new_float_fd);
|
||||
am.result = arr_util.mk_as_array(am.new_float_fd);
|
||||
return am;
|
||||
}
|
||||
|
||||
|
|
|
@ -230,39 +230,7 @@ void fpa2bv_converter::mk_var(unsigned base_inx, sort * srt, expr_ref & result)
|
|||
result = m_util.mk_fp(sgn, e, s);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_function_output(sort * rng, func_decl * fbv, expr * const * new_args, expr_ref & result) {
|
||||
if (m_util.is_float(rng)) {
|
||||
unsigned ebits = m_util.get_ebits(rng);
|
||||
unsigned sbits = m_util.get_sbits(rng);
|
||||
unsigned bv_sz = ebits + sbits;
|
||||
|
||||
app_ref na(m);
|
||||
na = m.mk_app(fbv, fbv->get_arity(), new_args);
|
||||
result = m_util.mk_fp(m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, na),
|
||||
m_bv_util.mk_extract(bv_sz - 2, sbits - 1, na),
|
||||
m_bv_util.mk_extract(sbits - 2, 0, na));
|
||||
}
|
||||
else if (m_util.is_rm(rng)) {
|
||||
app_ref na(m);
|
||||
na = m.mk_app(fbv, fbv->get_arity(), new_args);
|
||||
result = m_util.mk_bv2rm(na);
|
||||
}
|
||||
else
|
||||
result = m.mk_app(fbv, fbv->get_arity(), new_args);
|
||||
}
|
||||
|
||||
func_decl * fpa2bv_converter::get_bv_uf(func_decl * f, sort * bv_rng, unsigned arity) {
|
||||
func_decl * res;
|
||||
if (!m_uf2bvuf.find(f, res)) {
|
||||
res = m.mk_fresh_func_decl(f->get_name(), symbol("bv"), arity, f->get_domain(), bv_rng);
|
||||
m_uf2bvuf.insert(f, res);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(res);
|
||||
TRACE("fpa2bv", tout << "New UF func_decl: " << std::endl << mk_ismt2_pp(res, m) << std::endl;);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
void fpa2bv_converter::mk_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result)
|
||||
void fpa2bv_converter::mk_uf(func_decl * f, unsigned num, expr * const * args, expr_ref & result)
|
||||
{
|
||||
TRACE("fpa2bv", tout << "UF: " << mk_ismt2_pp(f, m) << std::endl; );
|
||||
|
||||
|
@ -278,7 +246,7 @@ void fpa2bv_converter::mk_function(func_decl * f, unsigned num, expr * const * a
|
|||
unsigned sbits = m_util.get_sbits(rng);
|
||||
unsigned bv_sz = ebits+sbits;
|
||||
bv_rng = m_bv_util.mk_sort(bv_sz);
|
||||
func_decl * bv_f = get_bv_uf(f, bv_rng, num);
|
||||
func_decl * bv_f = mk_bv_uf(f, f->get_domain(), bv_rng);
|
||||
bv_app = m.mk_app(bv_f, num, args);
|
||||
flt_app = m_util.mk_fp(m_bv_util.mk_extract(bv_sz-1, bv_sz-1, bv_app),
|
||||
m_bv_util.mk_extract(sbits+ebits-2, sbits-1, bv_app),
|
||||
|
@ -291,7 +259,7 @@ void fpa2bv_converter::mk_function(func_decl * f, unsigned num, expr * const * a
|
|||
sort_ref bv_rng(m);
|
||||
expr_ref new_eq(m);
|
||||
bv_rng = m_bv_util.mk_sort(3);
|
||||
func_decl * bv_f = get_bv_uf(f, bv_rng, num);
|
||||
func_decl * bv_f = mk_bv_uf(f, f->get_domain(), bv_rng);
|
||||
bv_app = m.mk_app(bv_f, num, args);
|
||||
flt_app = m_util.mk_bv2rm(bv_app);
|
||||
new_eq = m.mk_eq(fapp, flt_app);
|
||||
|
@ -1211,61 +1179,85 @@ void fpa2bv_converter::mk_abs(sort * s, expr_ref & x, expr_ref & result) {
|
|||
}
|
||||
|
||||
void fpa2bv_converter::mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
expr_ref x(m), y(m);
|
||||
x = args[0];
|
||||
y = args[1];
|
||||
|
||||
expr_ref x_is_zero(m), y_is_zero(m), both_are_zero(m);
|
||||
x_is_zero = m_util.mk_is_zero(x);
|
||||
y_is_zero = m_util.mk_is_zero(y);
|
||||
both_are_zero = m.mk_and(x_is_zero, y_is_zero);
|
||||
|
||||
expr_ref x_is_positive(m), x_is_negative(m), y_is_positive(m), y_is_negative(m), pn(m), np(m), pn_or_np(m);
|
||||
x_is_positive = m_util.mk_is_positive(x);
|
||||
x_is_negative = m_util.mk_is_negative(x);
|
||||
y_is_positive = m_util.mk_is_positive(y);
|
||||
y_is_negative = m_util.mk_is_negative(y);
|
||||
pn = m.mk_and(x_is_positive, y_is_negative);
|
||||
np = m.mk_and(x_is_negative, y_is_positive);
|
||||
pn_or_np = m.mk_or(pn, np);
|
||||
|
||||
expr_ref c(m), v(m);
|
||||
c = m.mk_and(both_are_zero, pn_or_np);
|
||||
v = m.mk_app(m_util.get_family_id(), OP_FPA_MIN_UNSPECIFIED, x, y);
|
||||
|
||||
// Note: This requires BR_REWRITE_FULL afterwards.
|
||||
expr_ref min_i(m);
|
||||
min_i = m.mk_app(m_util.get_family_id(), OP_FPA_MIN_I, x, y);
|
||||
m_simp.mk_ite(c, v, min_i, result);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_min_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
|
||||
expr * x = args[0], * y = args[1];
|
||||
|
||||
expr * x_sgn, * x_sig, * x_exp;
|
||||
expr * y_sgn, * y_sig, * y_exp;
|
||||
expr * x_sgn, *x_sig, *x_exp;
|
||||
expr * y_sgn, *y_sig, *y_exp;
|
||||
split_fp(x, x_sgn, x_exp, x_sig);
|
||||
split_fp(y, y_sgn, y_exp, y_sig);
|
||||
|
||||
expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), both_zero(m), pzero(m);
|
||||
mk_is_zero(x, x_is_zero);
|
||||
mk_is_zero(y, y_is_zero);
|
||||
m_simp.mk_and(x_is_zero, y_is_zero, both_zero);
|
||||
expr_ref bv0(m), bv1(m);
|
||||
bv0 = m_bv_util.mk_numeral(0, 1);
|
||||
bv1 = m_bv_util.mk_numeral(1, 1);
|
||||
|
||||
expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), xy_are_zero(m);
|
||||
mk_is_nan(x, x_is_nan);
|
||||
mk_is_nan(y, y_is_nan);
|
||||
mk_pzero(f, pzero);
|
||||
mk_is_zero(x, x_is_zero);
|
||||
mk_is_zero(y, y_is_zero);
|
||||
xy_are_zero = m.mk_and(x_is_zero, y_is_zero);
|
||||
|
||||
expr_ref sgn_eq(m), sgn_diff(m);
|
||||
sgn_eq = m.mk_eq(x_sgn, y_sgn);
|
||||
sgn_diff = m.mk_not(sgn_eq);
|
||||
expr_ref x_is_pos(m), x_is_neg(m);
|
||||
expr_ref y_is_pos(m), y_is_neg(m);
|
||||
expr_ref pn(m), np(m), pn_or_np_zeros(m);
|
||||
mk_is_pos(x, x_is_pos);
|
||||
mk_is_pos(y, y_is_pos);
|
||||
mk_is_neg(x, x_is_neg);
|
||||
mk_is_neg(y, y_is_neg);
|
||||
pn_or_np_zeros = m.mk_and(xy_are_zero, m.mk_not(m.mk_eq(x_sgn, y_sgn)));
|
||||
|
||||
expr_ref lt(m);
|
||||
mk_float_lt(f, num, args, lt);
|
||||
expr_ref unspec(m);
|
||||
unspec = mk_min_max_unspecified(f, x, y);
|
||||
|
||||
mk_ite(lt, x, y, result);
|
||||
mk_ite(both_zero, y, result, result);
|
||||
expr_ref x_lt_y(m);
|
||||
mk_float_lt(f, num, args, x_lt_y);
|
||||
|
||||
mk_ite(x_lt_y, x, y, result);
|
||||
mk_ite(xy_are_zero, y, result, result);
|
||||
mk_ite(pn_or_np_zeros, unspec, result, result);
|
||||
mk_ite(y_is_nan, x, result, result);
|
||||
mk_ite(x_is_nan, y, result, result);
|
||||
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
|
||||
expr * x = args[0], *y = args[1];
|
||||
|
||||
expr * x_sgn, *x_sig, *x_exp;
|
||||
expr * y_sgn, *y_sig, *y_exp;
|
||||
split_fp(x, x_sgn, x_exp, x_sig);
|
||||
split_fp(y, y_sgn, y_exp, y_sig);
|
||||
|
||||
expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), xy_are_zero(m);
|
||||
mk_is_nan(x, x_is_nan);
|
||||
mk_is_nan(y, y_is_nan);
|
||||
mk_is_zero(x, x_is_zero);
|
||||
mk_is_zero(y, y_is_zero);
|
||||
xy_are_zero = m.mk_and(x_is_zero, y_is_zero);
|
||||
|
||||
expr_ref x_is_pos(m), x_is_neg(m);
|
||||
expr_ref y_is_pos(m), y_is_neg(m);
|
||||
expr_ref pn(m), np(m), pn_or_np_zeros(m);
|
||||
mk_is_pos(x, x_is_pos);
|
||||
mk_is_pos(y, y_is_pos);
|
||||
mk_is_neg(x, x_is_neg);
|
||||
mk_is_neg(y, y_is_neg);
|
||||
pn_or_np_zeros = m.mk_and(xy_are_zero, m.mk_not(m.mk_eq(x_sgn, y_sgn)));
|
||||
|
||||
expr_ref unspec(m);
|
||||
unspec = mk_min_max_unspecified(f, x, y);
|
||||
|
||||
expr_ref x_gt_y(m);
|
||||
mk_float_gt(f, num, args, x_gt_y);
|
||||
|
||||
mk_ite(x_gt_y, x, y, result);
|
||||
mk_ite(xy_are_zero, y, result, result);
|
||||
mk_ite(pn_or_np_zeros, unspec, result, result);
|
||||
mk_ite(y_is_nan, x, result, result);
|
||||
mk_ite(x_is_nan, y, result, result);
|
||||
|
||||
|
@ -1281,10 +1273,10 @@ expr_ref fpa2bv_converter::mk_min_max_unspecified(func_decl * f, expr * x, expr
|
|||
// There is no "hardware interpretation" for fp.min/fp.max.
|
||||
|
||||
std::pair<app*, app*> decls(0, 0);
|
||||
if (!m_min_max_specials.find(f, decls)) {
|
||||
if (!m_min_max_ufs.find(f, decls)) {
|
||||
decls.first = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
decls.second = m.mk_fresh_const(0, m_bv_util.mk_sort(1));
|
||||
m_min_max_specials.insert(f, decls);
|
||||
m_min_max_ufs.insert(f, decls);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(decls.first);
|
||||
m.inc_ref(decls.second);
|
||||
|
@ -1303,68 +1295,6 @@ expr_ref fpa2bv_converter::mk_min_max_unspecified(func_decl * f, expr * x, expr
|
|||
return res;
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
expr_ref x(m), y(m);
|
||||
x = args[0];
|
||||
y = args[1];
|
||||
|
||||
expr_ref x_is_zero(m), y_is_zero(m), both_are_zero(m);
|
||||
x_is_zero = m_util.mk_is_zero(x);
|
||||
y_is_zero = m_util.mk_is_zero(y);
|
||||
both_are_zero = m.mk_and(x_is_zero, y_is_zero);
|
||||
|
||||
expr_ref x_is_positive(m), x_is_negative(m), y_is_positive(m), y_is_negative(m), pn(m), np(m), pn_or_np(m);
|
||||
x_is_positive = m_util.mk_is_positive(x);
|
||||
x_is_negative = m_util.mk_is_negative(x);
|
||||
y_is_positive = m_util.mk_is_positive(y);
|
||||
y_is_negative = m_util.mk_is_negative(y);
|
||||
pn = m.mk_and(x_is_positive, y_is_negative);
|
||||
np = m.mk_and(x_is_negative, y_is_positive);
|
||||
pn_or_np = m.mk_or(pn, np);
|
||||
|
||||
expr_ref c(m), v(m);
|
||||
c = m.mk_and(both_are_zero, pn_or_np);
|
||||
v = m.mk_app(m_util.get_family_id(), OP_FPA_MAX_UNSPECIFIED, x, y);
|
||||
|
||||
// Note: This requires BR_REWRITE_FULL afterwards.
|
||||
expr_ref max_i(m);
|
||||
max_i = m.mk_app(m_util.get_family_id(), OP_FPA_MAX_I, x, y);
|
||||
m_simp.mk_ite(c, v, max_i, result);
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 2);
|
||||
|
||||
expr * x = args[0], *y = args[1];
|
||||
|
||||
expr * x_sgn, *x_sig, *x_exp;
|
||||
expr * y_sgn, *y_sig, *y_exp;
|
||||
split_fp(x, x_sgn, x_exp, x_sig);
|
||||
split_fp(y, y_sgn, y_exp, y_sig);
|
||||
|
||||
expr_ref x_is_nan(m), y_is_nan(m), x_is_zero(m), y_is_zero(m), both_zero(m), pzero(m);
|
||||
mk_is_zero(x, x_is_zero);
|
||||
mk_is_zero(y, y_is_zero);
|
||||
m_simp.mk_and(x_is_zero, y_is_zero, both_zero);
|
||||
mk_is_nan(x, x_is_nan);
|
||||
mk_is_nan(y, y_is_nan);
|
||||
mk_pzero(f, pzero);
|
||||
|
||||
expr_ref sgn_diff(m), sgn_eq(m);
|
||||
sgn_eq = m.mk_eq(x_sgn, y_sgn);
|
||||
sgn_diff = m.mk_not(sgn_eq);
|
||||
|
||||
expr_ref gt(m);
|
||||
mk_float_gt(f, num, args, gt);
|
||||
|
||||
mk_ite(gt, x, y, result);
|
||||
mk_ite(both_zero, y, result, result);
|
||||
mk_ite(y_is_nan, x, result, result);
|
||||
mk_ite(x_is_nan, y, result, result);
|
||||
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args, expr_ref & result) {
|
||||
SASSERT(num == 4);
|
||||
SASSERT(m_util.is_bv2rm(args[0]));
|
||||
|
@ -3147,22 +3077,13 @@ void fpa2bv_converter::mk_to_ieee_bv(func_decl * f, unsigned num, expr * const *
|
|||
mk_is_nan(x, x_is_nan);
|
||||
|
||||
sort * fp_srt = m.get_sort(x);
|
||||
unsigned ebits = m_util.get_ebits(fp_srt);
|
||||
unsigned sbits = m_util.get_sbits(fp_srt);
|
||||
|
||||
expr_ref nanv(m);
|
||||
if (m_hi_fp_unspecified)
|
||||
// The "hardware interpretation" is 01...10...01.
|
||||
nanv = m_bv_util.mk_concat(m_bv_util.mk_numeral(0, 1),
|
||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(-1, ebits),
|
||||
m_bv_util.mk_concat(m_bv_util.mk_numeral(0, sbits - 2),
|
||||
m_bv_util.mk_numeral(1, 1))));
|
||||
else
|
||||
mk_to_ieee_bv_unspecified(f, num, args, nanv);
|
||||
expr_ref unspec(m);
|
||||
mk_to_ieee_bv_unspecified(f, num, args, unspec);
|
||||
|
||||
expr_ref sgn_e_s(m);
|
||||
join_fp(x, sgn_e_s);
|
||||
m_simp.mk_ite(x_is_nan, nanv, sgn_e_s, result);
|
||||
m_simp.mk_ite(x_is_nan, unspec, sgn_e_s, result);
|
||||
|
||||
TRACE("fpa2bv_to_ieee_bv", tout << "result=" << mk_ismt2_pp(result, m) << std::endl;);
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
|
@ -3174,26 +3095,15 @@ void fpa2bv_converter::mk_to_ieee_bv_unspecified(func_decl * f, unsigned num, ex
|
|||
unsigned ebits = f->get_domain()[0]->get_parameter(0).get_int();
|
||||
unsigned sbits = f->get_domain()[0]->get_parameter(1).get_int();
|
||||
|
||||
if (m_hi_fp_unspecified) {
|
||||
result = m_bv_util.mk_concat(m_bv_util.mk_concat(
|
||||
m_bv_util.mk_numeral(0, 1),
|
||||
m_bv_util.mk_numeral(-1, ebits)),
|
||||
m_bv_util.mk_numeral(1, sbits-1));
|
||||
}
|
||||
if (m_hi_fp_unspecified)
|
||||
mk_nan(f->get_range(), result);
|
||||
else {
|
||||
expr * n = args[0];
|
||||
expr_ref n_bv(m);
|
||||
join_fp(n, n_bv);
|
||||
|
||||
func_decl * f_bv;
|
||||
if (!m_uf2bvuf.find(f, f_bv)) {
|
||||
sort * domain[2] = { m.get_sort(n_bv) };
|
||||
f_bv = m.mk_fresh_func_decl(0, 1, domain, f->get_range());
|
||||
m_uf2bvuf.insert(f, f_bv);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(f_bv);
|
||||
}
|
||||
|
||||
sort * domain[1] = { m.get_sort(n_bv) };
|
||||
func_decl * f_bv = mk_bv_uf(f, domain, f->get_range());
|
||||
result = m.mk_app(f_bv, n_bv);
|
||||
|
||||
expr_ref exp_bv(m), exp_all_ones(m);
|
||||
|
@ -3382,14 +3292,8 @@ void fpa2bv_converter::mk_to_bv_unspecified(func_decl * f, unsigned num, expr *
|
|||
expr_ref n_bv(m);
|
||||
join_fp(n, n_bv);
|
||||
|
||||
func_decl * f_bv;
|
||||
if (!m_uf2bvuf.find(f, f_bv)) {
|
||||
sort * domain[2] = { m.get_sort(rm_bv), m.get_sort(n_bv) };
|
||||
f_bv = m.mk_fresh_func_decl(0, 2, domain, f->get_range());
|
||||
m_uf2bvuf.insert(f, f_bv);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(f_bv);
|
||||
}
|
||||
sort * domain[2] = { m.get_sort(rm_bv), m.get_sort(n_bv) };
|
||||
func_decl * f_bv = mk_bv_uf(f, domain, f->get_range());
|
||||
result = m.mk_app(f_bv, rm_bv, n_bv);
|
||||
}
|
||||
|
||||
|
@ -3407,14 +3311,8 @@ void fpa2bv_converter::mk_to_real_unspecified(func_decl * f, unsigned num, expr
|
|||
expr_ref n_bv(m);
|
||||
join_fp(n, n_bv);
|
||||
|
||||
func_decl * f_bv;
|
||||
if (!m_uf2bvuf.find(f, f_bv)) {
|
||||
sort * domain[2] = { m.get_sort(n_bv) };
|
||||
f_bv = m.mk_fresh_func_decl(0, 1, domain, f->get_range());
|
||||
m_uf2bvuf.insert(f, f_bv);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(f_bv);
|
||||
}
|
||||
sort * domain[1] = { m.get_sort(n_bv) };
|
||||
func_decl * f_bv = mk_bv_uf(f, domain, f->get_range());
|
||||
result = m.mk_app(f_bv, n_bv);
|
||||
}
|
||||
}
|
||||
|
@ -4190,13 +4088,25 @@ void fpa2bv_converter::reset(void) {
|
|||
dec_ref_map_key_values(m, m_const2bv);
|
||||
dec_ref_map_key_values(m, m_rm_const2bv);
|
||||
dec_ref_map_key_values(m, m_uf2bvuf);
|
||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_min_max_specials.begin();
|
||||
it != m_min_max_specials.end();
|
||||
for (obj_map<func_decl, std::pair<app*, app*> >::iterator it = m_min_max_ufs.begin();
|
||||
it != m_min_max_ufs.end();
|
||||
it++) {
|
||||
m.dec_ref(it->m_key);
|
||||
m.dec_ref(it->m_value.first);
|
||||
m.dec_ref(it->m_value.second);
|
||||
}
|
||||
m_min_max_specials.reset();
|
||||
m_min_max_ufs.reset();
|
||||
m_extra_assertions.reset();
|
||||
}
|
||||
|
||||
func_decl * fpa2bv_converter::mk_bv_uf(func_decl * f, sort * const * domain, sort * range) {
|
||||
func_decl * res;
|
||||
if (!m_uf2bvuf.find(f, res)) {
|
||||
res = m.mk_fresh_func_decl(0, f->get_arity(), domain, range);
|
||||
m_uf2bvuf.insert(f, res);
|
||||
m.inc_ref(f);
|
||||
m.inc_ref(res);
|
||||
TRACE("fpa2bv", tout << "New UF func_decl: " << std::endl << mk_ismt2_pp(res, m) << std::endl;);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ protected:
|
|||
const2bv_t m_const2bv;
|
||||
const2bv_t m_rm_const2bv;
|
||||
uf2bvuf_t m_uf2bvuf;
|
||||
special_t m_min_max_specials;
|
||||
special_t m_min_max_ufs;
|
||||
|
||||
friend class fpa2bv_model_converter;
|
||||
friend class bv2fpa_converter;
|
||||
|
@ -87,7 +87,7 @@ public:
|
|||
void mk_numeral(sort * s, mpf const & v, expr_ref & result);
|
||||
virtual void mk_const(func_decl * f, expr_ref & result);
|
||||
virtual void mk_rm_const(func_decl * f, expr_ref & result);
|
||||
virtual void mk_function(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
virtual void mk_uf(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_var(unsigned base_inx, sort * srt, expr_ref & result);
|
||||
|
||||
void mk_pinf(func_decl * f, expr_ref & result);
|
||||
|
@ -147,18 +147,15 @@ public:
|
|||
void set_unspecified_fp_hi(bool v) { m_hi_fp_unspecified = v; }
|
||||
|
||||
void mk_min(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_min_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
virtual expr_ref mk_min_max_unspecified(func_decl * f, expr * x, expr * y);
|
||||
|
||||
void mk_max(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
void mk_max_i(func_decl * f, unsigned num, expr * const * args, expr_ref & result);
|
||||
expr_ref mk_min_max_unspecified(func_decl * f, expr * x, expr * y);
|
||||
|
||||
void reset(void);
|
||||
|
||||
void dbg_decouple(const char * prefix, expr_ref & e);
|
||||
expr_ref_vector m_extra_assertions;
|
||||
|
||||
special_t const & get_min_max_specials() const { return m_min_max_specials; };
|
||||
special_t const & get_min_max_specials() const { return m_min_max_ufs; };
|
||||
const2bv_t const & get_const2bv() const { return m_const2bv; };
|
||||
const2bv_t const & get_rm_const2bv() const { return m_rm_const2bv; };
|
||||
uf2bvuf_t const & get_uf2bvuf() const { return m_uf2bvuf; };
|
||||
|
@ -202,12 +199,6 @@ protected:
|
|||
|
||||
void mk_to_bv(func_decl * f, unsigned num, expr * const * args, bool is_signed, expr_ref & result);
|
||||
|
||||
sort_ref replace_float_sorts(sort * s);
|
||||
func_decl_ref replace_function(func_decl * f);
|
||||
expr_ref replace_float_arg(expr * a);
|
||||
void mk_function_output(sort * rng, func_decl * fbv, expr * const * new_args, expr_ref & result);
|
||||
func_decl * get_bv_uf(func_decl * f, sort * bv_rng, unsigned arity);
|
||||
|
||||
private:
|
||||
void mk_nan(sort * s, expr_ref & result);
|
||||
void mk_nzero(sort * s, expr_ref & result);
|
||||
|
@ -226,6 +217,8 @@ private:
|
|||
void mk_round_to_integral(sort * s, expr_ref & rm, expr_ref & x, expr_ref & result);
|
||||
|
||||
void mk_to_fp_float(sort * s, expr * rm, expr * x, expr_ref & result);
|
||||
|
||||
func_decl * mk_bv_uf(func_decl * f, sort * const * domain, sort * range);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -124,6 +124,8 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
case OP_FPA_DIV: m_conv.mk_div(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_REM: m_conv.mk_rem(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_ABS: m_conv.mk_abs(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_FMA: m_conv.mk_fma(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_SQRT: m_conv.mk_sqrt(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_ROUND_TO_INTEGRAL: m_conv.mk_round_to_integral(f, num, args, result); return BR_DONE;
|
||||
|
@ -147,14 +149,6 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
case OP_FPA_TO_REAL: m_conv.mk_to_real(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_TO_IEEE_BV: m_conv.mk_to_ieee_bv(f, num, args, result); return BR_DONE;
|
||||
|
||||
case OP_FPA_MIN: m_conv.mk_min(f, num, args, result); return BR_REWRITE_FULL;
|
||||
case OP_FPA_MAX: m_conv.mk_max(f, num, args, result); return BR_REWRITE_FULL;
|
||||
|
||||
case OP_FPA_MIN_UNSPECIFIED:
|
||||
case OP_FPA_MAX_UNSPECIFIED: result = m_conv.mk_min_max_unspecified(f, args[0], args[1]); return BR_DONE;
|
||||
case OP_FPA_MIN_I: m_conv.mk_min_i(f, num, args, result); return BR_DONE;
|
||||
case OP_FPA_MAX_I: m_conv.mk_max_i(f, num, args, result); return BR_DONE;
|
||||
|
||||
case OP_FPA_BVWRAP:
|
||||
case OP_FPA_BV2RM:
|
||||
return BR_FAILED;
|
||||
|
@ -169,7 +163,7 @@ br_status fpa2bv_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * co
|
|||
{
|
||||
SASSERT(!m_conv.is_float_family(f));
|
||||
if (m_conv.fu().contains_floats(f)) {
|
||||
m_conv.mk_function(f, num, args, result);
|
||||
m_conv.mk_uf(f, num, args, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -361,10 +361,6 @@ func_decl * fpa_decl_plugin::mk_binary_decl(decl_kind k, unsigned num_parameters
|
|||
case OP_FPA_REM: name = "fp.rem"; break;
|
||||
case OP_FPA_MIN: name = "fp.min"; break;
|
||||
case OP_FPA_MAX: name = "fp.max"; break;
|
||||
case OP_FPA_MIN_I: name = "fp.min_i"; break;
|
||||
case OP_FPA_MAX_I: name = "fp.max_i"; break;
|
||||
case OP_FPA_MIN_UNSPECIFIED: name = "fp.min_unspecified"; break;
|
||||
case OP_FPA_MAX_UNSPECIFIED: name = "fp.max_unspecified"; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -781,12 +777,6 @@ func_decl * fpa_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
|
|||
case OP_FPA_BV2RM:
|
||||
return mk_bv2rm(k, num_parameters, parameters, arity, domain, range);
|
||||
|
||||
case OP_FPA_MIN_I:
|
||||
case OP_FPA_MAX_I:
|
||||
case OP_FPA_MIN_UNSPECIFIED:
|
||||
case OP_FPA_MAX_UNSPECIFIED:
|
||||
return mk_binary_decl(k, num_parameters, parameters, arity, domain, range);
|
||||
|
||||
default:
|
||||
m_manager->raise_exception("unsupported floating point operator");
|
||||
return 0;
|
||||
|
|
|
@ -89,11 +89,6 @@ enum fpa_op_kind {
|
|||
OP_FPA_BVWRAP,
|
||||
OP_FPA_BV2RM,
|
||||
|
||||
OP_FPA_MIN_I,
|
||||
OP_FPA_MAX_I,
|
||||
OP_FPA_MIN_UNSPECIFIED,
|
||||
OP_FPA_MAX_UNSPECIFIED,
|
||||
|
||||
LAST_FLOAT_OP
|
||||
};
|
||||
|
||||
|
@ -351,21 +346,12 @@ public:
|
|||
}
|
||||
|
||||
bool is_bvwrap(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_BVWRAP); }
|
||||
bool is_bvwrap(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_BVWRAP; }
|
||||
bool is_bv2rm(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_BV2RM); }
|
||||
bool is_bv2rm(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_BV2RM; }
|
||||
|
||||
bool is_min_interpreted(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_MIN_I); }
|
||||
bool is_min_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_MIN_UNSPECIFIED); }
|
||||
bool is_max_interpreted(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_MAX_I); }
|
||||
bool is_max_unspecified(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_MAX_UNSPECIFIED); }
|
||||
bool is_to_ubv(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_TO_UBV); }
|
||||
bool is_to_sbv(expr const * e) const { return is_app_of(e, get_family_id(), OP_FPA_TO_SBV); }
|
||||
|
||||
bool is_min_interpreted(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_MIN_I; }
|
||||
bool is_min_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_MIN_UNSPECIFIED; }
|
||||
bool is_max_interpreted(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_MAX_I; }
|
||||
bool is_max_unspecified(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_MAX_UNSPECIFIED; }
|
||||
bool is_bvwrap(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_BVWRAP; }
|
||||
bool is_bv2rm(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_BV2RM; }
|
||||
bool is_to_ubv(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_TO_UBV; }
|
||||
bool is_to_sbv(func_decl const * f) const { return f->get_family_id() == get_family_id() && f->get_decl_kind() == OP_FPA_TO_SBV; }
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ enum nnf_mode {
|
|||
transformation will be in skolem normal form.
|
||||
If a formula is too expensive to be put into NNF,
|
||||
then nested quantifiers and labels are renamed.
|
||||
|
||||
|
||||
This mode is sufficient when using E-matching.
|
||||
*/
|
||||
NNF_QUANT, /* A subformula is put into NNF if it contains
|
||||
|
@ -48,7 +48,7 @@ enum nnf_mode {
|
|||
quantifier. The result of the transformation will be
|
||||
in skolem normal form, and the body of quantifiers
|
||||
will be in NNF. If a ground formula is too expensive to
|
||||
be put into NNF, then nested quantifiers and labels
|
||||
be put into NNF, then nested quantifiers and labels
|
||||
are renamed.
|
||||
|
||||
This mode is sufficient when using Superposition
|
||||
|
@ -89,7 +89,7 @@ class skolemizer {
|
|||
}
|
||||
|
||||
TRACE("skolemizer", tout << "skid: " << q->get_skid() << "\n";);
|
||||
|
||||
|
||||
expr_ref_vector substitution(m());
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
for (unsigned i = num_decls; i > 0; ) {
|
||||
|
@ -111,7 +111,7 @@ class skolemizer {
|
|||
substitution.push_back(0);
|
||||
}
|
||||
//
|
||||
// (VAR num_decls) ... (VAR num_decls+sz-1)
|
||||
// (VAR num_decls) ... (VAR num_decls+sz-1)
|
||||
// are in positions num_decls .. num_decls+sz-1
|
||||
//
|
||||
std::reverse(substitution.c_ptr(), substitution.c_ptr() + substitution.size());
|
||||
|
@ -139,7 +139,7 @@ class skolemizer {
|
|||
s(body, substitution.size(), substitution.c_ptr(), r);
|
||||
p = 0;
|
||||
if (m().proofs_enabled()) {
|
||||
if (q->is_forall())
|
||||
if (q->is_forall())
|
||||
p = m().mk_skolemization(m().mk_not(q), m().mk_not(r));
|
||||
else
|
||||
p = m().mk_skolemization(q, r);
|
||||
|
@ -175,7 +175,7 @@ public:
|
|||
m_cache_pr.insert(q, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool is_sk_hack(expr * p) const {
|
||||
SASSERT(m().is_pattern(p));
|
||||
if (to_app(p)->get_num_args() != 1)
|
||||
|
@ -204,11 +204,11 @@ struct nnf::imp {
|
|||
unsigned m_i:28;
|
||||
unsigned m_pol:1; // pos/neg polarity
|
||||
unsigned m_in_q:1; // true if m_curr is nested in a quantifier
|
||||
unsigned m_new_child:1;
|
||||
unsigned m_new_child:1;
|
||||
unsigned m_cache_result:1;
|
||||
unsigned m_spos; // top of the result stack, when the frame was created.
|
||||
frame(expr_ref& n, bool pol, bool in_q, bool cache_res, unsigned spos):
|
||||
m_curr(n),
|
||||
frame(expr_ref && n, bool pol, bool in_q, bool cache_res, unsigned spos):
|
||||
m_curr(std::move(n)),
|
||||
m_i(0),
|
||||
m_pol(pol),
|
||||
m_in_q(in_q),
|
||||
|
@ -216,6 +216,16 @@ struct nnf::imp {
|
|||
m_cache_result(cache_res),
|
||||
m_spos(spos) {
|
||||
}
|
||||
frame(frame && other):
|
||||
m_curr(std::move(other.m_curr)),
|
||||
m_i(other.m_i),
|
||||
m_pol(other.m_pol),
|
||||
m_in_q(other.m_in_q),
|
||||
m_new_child(other.m_new_child),
|
||||
m_cache_result(other.m_cache_result),
|
||||
m_spos(other.m_spos) {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// There are four caches:
|
||||
|
@ -223,22 +233,22 @@ struct nnf::imp {
|
|||
#define POS_NQ_CIDX 1 // positive polarity and not nested in a quantifier
|
||||
#define NEG_Q_CIDX 2 // negative polarity and nested in a quantifier
|
||||
#define POS_Q_CIDX 3 // positive polarity and nested in a quantifier
|
||||
|
||||
|
||||
ast_manager & m_manager;
|
||||
vector<frame> m_frame_stack;
|
||||
expr_ref_vector m_result_stack;
|
||||
|
||||
|
||||
typedef act_cache cache;
|
||||
cache * m_cache[4];
|
||||
|
||||
expr_ref_vector m_todo_defs;
|
||||
proof_ref_vector m_todo_proofs;
|
||||
|
||||
|
||||
// proof generation goodness ----
|
||||
proof_ref_vector m_result_pr_stack;
|
||||
cache * m_cache_pr[4];
|
||||
// ------------------------------
|
||||
|
||||
|
||||
skolemizer m_skolemizer;
|
||||
|
||||
// configuration ----------------
|
||||
|
@ -249,7 +259,7 @@ struct nnf::imp {
|
|||
|
||||
name_exprs * m_name_nested_formulas;
|
||||
name_exprs * m_name_quant;
|
||||
|
||||
|
||||
unsigned long long m_max_memory; // in bytes
|
||||
|
||||
imp(ast_manager & m, defined_names & n, params_ref const & p):
|
||||
|
@ -292,9 +302,9 @@ struct nnf::imp {
|
|||
m_mode = NNF_FULL;
|
||||
else if (mode_sym == "quantifiers")
|
||||
m_mode = NNF_QUANT;
|
||||
else
|
||||
else
|
||||
throw nnf_params_exception("invalid NNF mode");
|
||||
|
||||
|
||||
TRACE("nnf", tout << "nnf-mode: " << m_mode << " " << mode_sym << "\n" << _p << "\n";);
|
||||
|
||||
m_ignore_labels = p.ignore_labels();
|
||||
|
@ -324,12 +334,11 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
void push_frame(expr * t, bool pol, bool in_q, bool cache_res) {
|
||||
expr_ref tr(t, m());
|
||||
m_frame_stack.push_back(frame(tr, pol, in_q, cache_res, m_result_stack.size()));
|
||||
m_frame_stack.push_back(frame(expr_ref(t, m()), pol, in_q, cache_res, m_result_stack.size()));
|
||||
}
|
||||
|
||||
static unsigned get_cache_idx(bool pol, bool in_q) {
|
||||
return static_cast<unsigned>(in_q) * 2 + static_cast<unsigned>(pol);
|
||||
static unsigned get_cache_idx(bool pol, bool in_q) {
|
||||
return static_cast<unsigned>(in_q) * 2 + static_cast<unsigned>(pol);
|
||||
}
|
||||
|
||||
void cache_result(expr * t, bool pol, bool in_q, expr * v, proof * pr) {
|
||||
|
@ -339,8 +348,8 @@ struct nnf::imp {
|
|||
m_cache_pr[idx]->insert(t, pr);
|
||||
}
|
||||
|
||||
expr * get_cached(expr * t, bool pol, bool in_q) const {
|
||||
return m_cache[get_cache_idx(pol, in_q)]->find(t);
|
||||
expr * get_cached(expr * t, bool pol, bool in_q) const {
|
||||
return m_cache[get_cache_idx(pol, in_q)]->find(t);
|
||||
}
|
||||
|
||||
proof * get_cached_pr(expr * t, bool pol, bool in_q) const {
|
||||
|
@ -368,12 +377,12 @@ struct nnf::imp {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void checkpoint() {
|
||||
cooperate("nnf");
|
||||
if (memory::get_allocation_size() > m_max_memory)
|
||||
throw nnf_exception(Z3_MAX_MEMORY_MSG);
|
||||
if (m().canceled())
|
||||
if (m().canceled())
|
||||
throw nnf_exception(m().limit().get_cancel_msg());
|
||||
}
|
||||
|
||||
|
@ -382,11 +391,11 @@ struct nnf::imp {
|
|||
m_frame_stack.back().m_new_child = true;
|
||||
}
|
||||
|
||||
void set_new_child_flag(expr * old_t, expr * new_t) {
|
||||
if (old_t != new_t)
|
||||
set_new_child_flag();
|
||||
void set_new_child_flag(expr * old_t, expr * new_t) {
|
||||
if (old_t != new_t)
|
||||
set_new_child_flag();
|
||||
}
|
||||
|
||||
|
||||
void skip(expr * t, bool pol) {
|
||||
expr * r = pol ? t : m().mk_not(t);
|
||||
m_result_stack.push_back(r);
|
||||
|
@ -448,10 +457,10 @@ struct nnf::imp {
|
|||
if (pol) {
|
||||
if (old_e->get_decl() == new_e->get_decl())
|
||||
return m().mk_oeq_congruence(old_e, new_e, num_parents, parents);
|
||||
else
|
||||
else
|
||||
return m().mk_nnf_pos(old_e, new_e, num_parents, parents);
|
||||
}
|
||||
else
|
||||
else
|
||||
return m().mk_nnf_neg(old_e, new_e, num_parents, parents);
|
||||
}
|
||||
|
||||
|
@ -468,7 +477,7 @@ struct nnf::imp {
|
|||
r = m().mk_and(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
|
||||
else
|
||||
r = m().mk_or(t->get_num_args(), m_result_stack.c_ptr() + fr.m_spos);
|
||||
|
||||
|
||||
m_result_stack.shrink(fr.m_spos);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -520,7 +529,7 @@ struct nnf::imp {
|
|||
r = m().mk_or(2, m_result_stack.c_ptr() + fr.m_spos);
|
||||
else
|
||||
r = m().mk_and(2, m_result_stack.c_ptr() + fr.m_spos);
|
||||
|
||||
|
||||
m_result_stack.shrink(fr.m_spos);
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -554,7 +563,7 @@ struct nnf::imp {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
expr * const * rs = m_result_stack.c_ptr() + fr.m_spos;
|
||||
expr * _cond = rs[0];
|
||||
expr * _not_cond = rs[1];
|
||||
|
@ -574,7 +583,7 @@ struct nnf::imp {
|
|||
}
|
||||
|
||||
bool is_eq(app * t) const { return m().is_eq(t) || m().is_iff(t); }
|
||||
|
||||
|
||||
bool process_iff_xor(app * t, frame & fr) {
|
||||
SASSERT(t->get_num_args() == 2);
|
||||
switch (fr.m_i) {
|
||||
|
@ -605,7 +614,7 @@ struct nnf::imp {
|
|||
expr * not_rhs = rs[3];
|
||||
|
||||
app * r;
|
||||
if (is_eq(t) == fr.m_pol)
|
||||
if (is_eq(t) == fr.m_pol)
|
||||
r = m().mk_and(m().mk_or(not_lhs, rhs), m().mk_or(lhs, not_rhs));
|
||||
else
|
||||
r = m().mk_and(m().mk_or(lhs, rhs), m().mk_or(not_lhs, not_rhs));
|
||||
|
@ -626,7 +635,7 @@ struct nnf::imp {
|
|||
else
|
||||
return process_default(t, fr);
|
||||
}
|
||||
|
||||
|
||||
bool process_default(app * t, frame & fr) {
|
||||
SASSERT(fr.m_i == 0);
|
||||
if (m_mode == NNF_FULL || t->has_quantifiers() || t->has_labels()) {
|
||||
|
@ -636,10 +645,10 @@ struct nnf::imp {
|
|||
m_name_nested_formulas->operator()(t, m_todo_defs, m_todo_proofs, n2, pr2);
|
||||
else
|
||||
m_name_quant->operator()(t, m_todo_defs, m_todo_proofs, n2, pr2);
|
||||
|
||||
|
||||
if (!fr.m_pol)
|
||||
n2 = m().mk_not(n2);
|
||||
|
||||
|
||||
m_result_stack.push_back(n2);
|
||||
if (proofs_enabled()) {
|
||||
if (!fr.m_pol) {
|
||||
|
@ -666,10 +675,10 @@ struct nnf::imp {
|
|||
expr * arg = m_result_stack.back();
|
||||
proof * arg_pr = proofs_enabled() ? m_result_pr_stack.back() : 0;
|
||||
|
||||
if (m_ignore_labels && !proofs_enabled())
|
||||
if (m_ignore_labels && !proofs_enabled())
|
||||
return true; // the result is already on the stack
|
||||
|
||||
|
||||
|
||||
buffer<symbol> names;
|
||||
bool pos;
|
||||
m().is_label(t, pos, names);
|
||||
|
@ -684,7 +693,7 @@ struct nnf::imp {
|
|||
pr = m().mk_transitivity(mk_proof(fr.m_pol, 1, &arg_pr, t, to_app(aux)),
|
||||
m().mk_iff_oeq(m().mk_rewrite(aux, r)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
r = arg;
|
||||
if (proofs_enabled()) {
|
||||
|
@ -692,7 +701,7 @@ struct nnf::imp {
|
|||
pr = m().mk_transitivity(p1, arg_pr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_result_stack.pop_back();
|
||||
m_result_stack.push_back(r);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -729,7 +738,7 @@ struct nnf::imp {
|
|||
if (m().is_label(t)) {
|
||||
return process_label(t, fr);
|
||||
}
|
||||
|
||||
|
||||
return process_default(t, fr);
|
||||
}
|
||||
|
||||
|
@ -737,7 +746,7 @@ struct nnf::imp {
|
|||
skip(v, fr.m_pol);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool process_quantifier(quantifier * q, frame & fr) {
|
||||
expr_ref r(m());
|
||||
proof_ref pr(m());
|
||||
|
@ -757,7 +766,7 @@ struct nnf::imp {
|
|||
if (q->is_forall() == fr.m_pol || !m_skolemize) {
|
||||
expr * new_expr = m_result_stack.back();
|
||||
proof * new_expr_pr = proofs_enabled() ? m_result_pr_stack.back() : 0;
|
||||
|
||||
|
||||
ptr_buffer<expr> new_patterns;
|
||||
|
||||
if (q->is_forall() == fr.m_pol) {
|
||||
|
@ -773,7 +782,7 @@ struct nnf::imp {
|
|||
// New quantifier has existential force.
|
||||
// So, ignore patterns
|
||||
}
|
||||
|
||||
|
||||
quantifier * new_q = 0;
|
||||
proof * new_q_pr = 0;
|
||||
if (fr.m_pol) {
|
||||
|
@ -786,7 +795,7 @@ struct nnf::imp {
|
|||
if (proofs_enabled())
|
||||
new_q_pr = m().mk_nnf_neg(q, new_q, 1, &new_expr_pr);
|
||||
}
|
||||
|
||||
|
||||
m_result_stack.pop_back();
|
||||
m_result_stack.push_back(new_q);
|
||||
if (proofs_enabled()) {
|
||||
|
@ -809,7 +818,7 @@ struct nnf::imp {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void recover_result(expr * t, expr_ref & result, proof_ref & result_pr) {
|
||||
// recover result from the top of the stack.
|
||||
result = m_result_stack.back();
|
||||
|
@ -873,7 +882,7 @@ struct nnf::imp {
|
|||
process(n, r, pr);
|
||||
unsigned old_sz1 = new_defs.size();
|
||||
unsigned old_sz2 = new_def_proofs.size();
|
||||
|
||||
|
||||
for (unsigned i = 0; i < m_todo_defs.size(); i++) {
|
||||
expr_ref dr(m());
|
||||
proof_ref dpr(m());
|
||||
|
@ -881,7 +890,7 @@ struct nnf::imp {
|
|||
new_defs.push_back(dr);
|
||||
if (proofs_enabled()) {
|
||||
proof * new_pr = m().mk_modus_ponens(m_todo_proofs.get(i), dpr);
|
||||
new_def_proofs.push_back(new_pr);
|
||||
new_def_proofs.push_back(new_pr);
|
||||
}
|
||||
}
|
||||
std::reverse(new_defs.c_ptr() + old_sz1, new_defs.c_ptr() + new_defs.size());
|
||||
|
@ -898,7 +907,7 @@ nnf::nnf(ast_manager & m, defined_names & n, params_ref const & p) {
|
|||
nnf::~nnf() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
|
||||
void nnf::operator()(expr * n, expr_ref_vector & new_defs, proof_ref_vector & new_def_proofs, expr_ref & r, proof_ref & p) {
|
||||
m_imp->operator()(n, new_defs, new_def_proofs, r, p);
|
||||
TRACE("nnf_result", tout << mk_ismt2_pp(n, m_imp->m()) << "\nNNF result:\n" << mk_ismt2_pp(r, m_imp->m()) << "\n";);
|
||||
|
|
|
@ -179,11 +179,11 @@ expr_pattern_match::compile(expr* q)
|
|||
}
|
||||
|
||||
if (m_regs.size() <= max_reg) {
|
||||
m_regs.resize(max_reg+1, 0);
|
||||
m_regs.resize(max_reg+1);
|
||||
}
|
||||
if (m_bound_dom.size() <= num_bound) {
|
||||
m_bound_dom.resize(num_bound+1, 0);
|
||||
m_bound_rng.resize(num_bound+1, 0);
|
||||
m_bound_dom.resize(num_bound+1);
|
||||
m_bound_rng.resize(num_bound+1);
|
||||
}
|
||||
|
||||
instr.m_kind = YIELD;
|
||||
|
|
|
@ -272,7 +272,7 @@ void bit_blaster_tpl<Cfg>::mk_multiplier(unsigned sz, expr * const * a_bits, exp
|
|||
zero = m().mk_false();
|
||||
|
||||
vector< expr_ref_vector > pps;
|
||||
pps.resize(sz, m());
|
||||
pps.resize(sz, expr_ref_vector(m()));
|
||||
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
checkpoint();
|
||||
|
|
|
@ -94,12 +94,6 @@ br_status fpa_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
|
|||
case OP_FPA_TO_IEEE_BV: SASSERT(num_args == 1); st = mk_to_ieee_bv(f, args[0], result); break;
|
||||
case OP_FPA_TO_REAL: SASSERT(num_args == 1); st = mk_to_real(args[0], result); break;
|
||||
|
||||
case OP_FPA_MIN_I:SASSERT(num_args == 2); st = mk_min_i(f, args[0], args[1], result); break;
|
||||
case OP_FPA_MAX_I: SASSERT(num_args == 2); st = mk_max_i(f, args[0], args[1], result); break;
|
||||
case OP_FPA_MIN_UNSPECIFIED:
|
||||
case OP_FPA_MAX_UNSPECIFIED:
|
||||
SASSERT(num_args == 2); st = BR_FAILED; break;
|
||||
|
||||
case OP_FPA_BVWRAP: SASSERT(num_args == 1); st = mk_bvwrap(args[0], result); break;
|
||||
case OP_FPA_BV2RM: SASSERT(num_args == 1); st = mk_bv2rm(args[0], result); break;
|
||||
|
||||
|
@ -131,11 +125,10 @@ br_status fpa_rewriter::mk_to_fp(func_decl * f, unsigned num_args, expr * const
|
|||
const mpz & sm1 = m_fm.m_powers2(sbits - 1);
|
||||
const mpz & em1 = m_fm.m_powers2(ebits);
|
||||
|
||||
scoped_mpq q(mpqm);
|
||||
mpqm.set(q, r1.to_mpq());
|
||||
SASSERT(mpzm.is_one(q.get().denominator()));
|
||||
const mpq & q = r1.to_mpq();
|
||||
SASSERT(mpzm.is_one(q.denominator()));
|
||||
scoped_mpz z(mpzm);
|
||||
z = q.get().numerator();
|
||||
z = q.numerator();
|
||||
|
||||
mpzm.rem(z, sm1, sig);
|
||||
mpzm.div(z, sm1, z);
|
||||
|
@ -385,38 +378,13 @@ br_status fpa_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
}
|
||||
|
||||
scoped_mpf v1(m_fm), v2(m_fm);
|
||||
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
|
||||
if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2)) {
|
||||
result = m().mk_app(get_fid(), OP_FPA_MIN_UNSPECIFIED, arg1, arg2);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
else {
|
||||
scoped_mpf r(m_fm);
|
||||
m_fm.minimum(v1, v2, r);
|
||||
result = m_util.mk_value(r);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
expr_ref c(m()), v(m());
|
||||
c = m().mk_and(m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2)),
|
||||
m().mk_or(m().mk_and(m_util.mk_is_positive(arg1), m_util.mk_is_negative(arg2)),
|
||||
m().mk_and(m_util.mk_is_negative(arg1), m_util.mk_is_positive(arg2))));
|
||||
v = m().mk_app(get_fid(), OP_FPA_MIN_UNSPECIFIED, arg1, arg2);
|
||||
|
||||
result = m().mk_ite(c, v, m().mk_app(get_fid(), OP_FPA_MIN_I, arg1, arg2));
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_min_i(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) {
|
||||
scoped_mpf v1(m_fm), v2(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
|
||||
if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2))
|
||||
result = m().mk_app(get_fid(), OP_FPA_MIN_UNSPECIFIED, arg1, arg2);
|
||||
else
|
||||
result = m_util.mk_min(arg1, arg2);
|
||||
return BR_FAILED;
|
||||
|
||||
scoped_mpf r(m_fm);
|
||||
m_fm.minimum(v1, v2, r);
|
||||
result = m_util.mk_value(r);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
@ -434,38 +402,13 @@ br_status fpa_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
|
|||
}
|
||||
|
||||
scoped_mpf v1(m_fm), v2(m_fm);
|
||||
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
|
||||
if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2)) {
|
||||
result = m().mk_app(get_fid(), OP_FPA_MAX_UNSPECIFIED, arg1, arg2);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
else {
|
||||
scoped_mpf r(m_fm);
|
||||
m_fm.maximum(v1, v2, r);
|
||||
result = m_util.mk_value(r);
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
expr_ref c(m()), v(m());
|
||||
c = m().mk_and(m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2)),
|
||||
m().mk_or(m().mk_and(m_util.mk_is_positive(arg1), m_util.mk_is_negative(arg2)),
|
||||
m().mk_and(m_util.mk_is_negative(arg1), m_util.mk_is_positive(arg2))));
|
||||
v = m().mk_app(get_fid(), OP_FPA_MAX_UNSPECIFIED, arg1, arg2);
|
||||
|
||||
result = m().mk_ite(c, v, m().mk_app(get_fid(), OP_FPA_MAX_I, arg1, arg2));
|
||||
return BR_REWRITE_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
br_status fpa_rewriter::mk_max_i(func_decl * f, expr * arg1, expr * arg2, expr_ref & result) {
|
||||
scoped_mpf v1(m_fm), v2(m_fm);
|
||||
|
||||
if (m_util.is_numeral(arg1, v1) && m_util.is_numeral(arg2, v2)) {
|
||||
if (m_fm.is_zero(v1) && m_fm.is_zero(v2) && m_fm.sgn(v1) != m_fm.sgn(v2))
|
||||
result = m().mk_app(get_fid(), OP_FPA_MIN_UNSPECIFIED, arg1, arg2);
|
||||
else
|
||||
result = m_util.mk_max(arg1, arg2);
|
||||
return BR_FAILED;
|
||||
|
||||
scoped_mpf r(m_fm);
|
||||
m_fm.maximum(v1, v2, r);
|
||||
result = m_util.mk_value(r);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,13 +54,13 @@ br_status maximize_ac_sharing::reduce_app(func_decl * f, unsigned num_args, expr
|
|||
TRACE("ac_sharing_detail", tout << "args: "; for (unsigned i = 0; i < num_args; i++) tout << mk_pp(_args[i], m) << "\n";);
|
||||
try_to_reuse:
|
||||
if (num_args > 1 && num_args < MAX_NUM_ARGS_FOR_OPT) {
|
||||
for (unsigned i = 0; i < num_args - 1; i++) {
|
||||
for (unsigned i = 0; i + 1 < num_args; i++) {
|
||||
for (unsigned j = i + 1; j < num_args; j++) {
|
||||
if (contains(f, _args[i], _args[j])) {
|
||||
TRACE("ac_sharing_detail", tout << "reusing args: " << i << " " << j << "\n";);
|
||||
_args[i] = m.mk_app(f, _args[i], _args[j]);
|
||||
SASSERT(num_args > 1);
|
||||
for (unsigned w = j; w < num_args - 1; w++) {
|
||||
for (unsigned w = j; w + 1 < num_args; w++) {
|
||||
_args[w] = _args[w+1];
|
||||
}
|
||||
num_args--;
|
||||
|
@ -144,6 +144,7 @@ void maximize_ac_sharing::restore_entries(unsigned old_lim) {
|
|||
while (i != old_lim) {
|
||||
--i;
|
||||
entry * e = m_entries[i];
|
||||
m_cache.remove(e);
|
||||
m.dec_ref(e->m_arg1);
|
||||
m.dec_ref(e->m_arg2);
|
||||
}
|
||||
|
@ -151,11 +152,7 @@ void maximize_ac_sharing::restore_entries(unsigned old_lim) {
|
|||
}
|
||||
|
||||
void maximize_ac_sharing::reset() {
|
||||
restore_entries(0);
|
||||
m_entries.reset();
|
||||
m_cache.reset();
|
||||
m_region.reset();
|
||||
m_scopes.reset();
|
||||
}
|
||||
|
||||
void maximize_bv_sharing::init_core() {
|
||||
|
|
|
@ -42,6 +42,10 @@ void rewriter_tpl<Config>::process_var(var * v) {
|
|||
unsigned index = m_bindings.size() - idx - 1;
|
||||
var * r = (var*)(m_bindings[index]);
|
||||
if (r != 0) {
|
||||
CTRACE("rewriter", v->get_sort() != m().get_sort(r),
|
||||
tout << expr_ref(v, m()) << ":" << sort_ref(v->get_sort(), m()) << " != " << expr_ref(r, m()) << ":" << sort_ref(m().get_sort(r), m());
|
||||
tout << "index " << index << " bindings " << m_bindings.size() << "\n";
|
||||
display_bindings(tout););
|
||||
SASSERT(v->get_sort() == m().get_sort(r));
|
||||
if (!is_ground(r) && m_shifts[index] != m_bindings.size()) {
|
||||
|
||||
|
|
|
@ -256,7 +256,7 @@ void substitution_tree::insert(expr * new_expr) {
|
|||
sort * s = to_var(new_expr)->get_sort();
|
||||
unsigned id = s->get_decl_id();
|
||||
if (id >= m_vars.size())
|
||||
m_vars.resize(id+1, 0);
|
||||
m_vars.resize(id+1);
|
||||
if (m_vars[id] == 0)
|
||||
m_vars[id] = alloc(var_ref_vector, m_manager);
|
||||
var_ref_vector * v = m_vars[id];
|
||||
|
@ -277,7 +277,7 @@ void substitution_tree::insert(app * new_expr) {
|
|||
unsigned id = d->get_decl_id();
|
||||
|
||||
if (id >= m_roots.size())
|
||||
m_roots.resize(id+1, 0);
|
||||
m_roots.resize(id+1);
|
||||
|
||||
if (!m_roots[id]) {
|
||||
// there is no tree for the function symbol heading new_expr
|
||||
|
|
|
@ -58,7 +58,7 @@ void used_vars::process(expr * n, unsigned delta) {
|
|||
if (idx >= delta) {
|
||||
idx = idx - delta;
|
||||
if (idx >= m_found_vars.size())
|
||||
m_found_vars.resize(idx + 1, 0);
|
||||
m_found_vars.resize(idx + 1);
|
||||
m_found_vars[idx] = to_var(n)->get_sort();
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -202,7 +202,7 @@ func_decl * func_decls::find(unsigned arity, sort * const * domain, sort * range
|
|||
if (f->get_arity() != arity)
|
||||
continue;
|
||||
unsigned i = 0;
|
||||
for (i = 0; i < arity; i++) {
|
||||
for (i = 0; domain && i < arity; i++) {
|
||||
if (f->get_domain(i) != domain[i])
|
||||
break;
|
||||
}
|
||||
|
@ -774,7 +774,6 @@ bool cmd_context::is_func_decl(symbol const & s) const {
|
|||
}
|
||||
|
||||
void cmd_context::insert(symbol const & s, func_decl * f) {
|
||||
m_check_sat_result = 0;
|
||||
if (!m_check_logic(f)) {
|
||||
throw cmd_exception(m_check_logic.get_last_error());
|
||||
}
|
||||
|
@ -805,7 +804,6 @@ void cmd_context::insert(symbol const & s, func_decl * f) {
|
|||
}
|
||||
|
||||
void cmd_context::insert(symbol const & s, psort_decl * p) {
|
||||
m_check_sat_result = 0;
|
||||
if (m_psort_decls.contains(s)) {
|
||||
throw cmd_exception("sort already defined ", s);
|
||||
}
|
||||
|
@ -819,7 +817,6 @@ void cmd_context::insert(symbol const & s, psort_decl * p) {
|
|||
|
||||
void cmd_context::insert(symbol const & s, unsigned arity, sort *const* domain, expr * t) {
|
||||
expr_ref _t(t, m());
|
||||
m_check_sat_result = 0;
|
||||
if (m_builtin_decls.contains(s)) {
|
||||
throw cmd_exception("invalid macro/named expression, builtin symbol ", s);
|
||||
}
|
||||
|
@ -870,6 +867,12 @@ void cmd_context::insert_rec_fun(func_decl* f, expr_ref_vector const& binding, s
|
|||
lhs = m().mk_app(f, binding.size(), binding.c_ptr());
|
||||
eq = m().mk_eq(lhs, e);
|
||||
if (!ids.empty()) {
|
||||
if (is_var(e)) {
|
||||
ptr_vector<sort> domain;
|
||||
for (expr* b : binding) domain.push_back(m().get_sort(b));
|
||||
insert_macro(f->get_name(), domain.size(), domain.c_ptr(), e);
|
||||
return;
|
||||
}
|
||||
if (!is_app(e)) {
|
||||
throw cmd_exception("Z3 only supports recursive definitions that are proper terms (not binders or variables)");
|
||||
}
|
||||
|
@ -937,7 +940,7 @@ static builtin_decl const & peek_builtin_decl(builtin_decl const & first, family
|
|||
func_decl * cmd_context::find_func_decl(symbol const & s, unsigned num_indices, unsigned const * indices,
|
||||
unsigned arity, sort * const * domain, sort * range) const {
|
||||
builtin_decl d;
|
||||
if (m_builtin_decls.find(s, d)) {
|
||||
if (domain && m_builtin_decls.find(s, d)) {
|
||||
family_id fid = d.m_fid;
|
||||
decl_kind k = d.m_decl;
|
||||
// Hack: if d.m_next != 0, we use domain[0] (if available) to decide which plugin we use.
|
||||
|
@ -961,7 +964,7 @@ func_decl * cmd_context::find_func_decl(symbol const & s, unsigned num_indices,
|
|||
return f;
|
||||
}
|
||||
|
||||
if (contains_macro(s, arity, domain))
|
||||
if (domain && contains_macro(s, arity, domain))
|
||||
throw cmd_exception("invalid function declaration reference, named expressions (aka macros) cannot be referenced ", s);
|
||||
|
||||
if (num_indices > 0)
|
||||
|
@ -1545,6 +1548,26 @@ void cmd_context::reset_assertions() {
|
|||
}
|
||||
|
||||
|
||||
void cmd_context::display_dimacs() {
|
||||
if (m_solver) {
|
||||
try {
|
||||
gparams::set("sat.dimacs.display", "true");
|
||||
params_ref p;
|
||||
m_solver->updt_params(p);
|
||||
m_solver->check_sat(0, nullptr);
|
||||
}
|
||||
catch (...) {
|
||||
gparams::set("sat.dimacs.display", "false");
|
||||
params_ref p;
|
||||
m_solver->updt_params(p);
|
||||
throw;
|
||||
}
|
||||
gparams::set("sat.dimacs.display", "false");
|
||||
params_ref p;
|
||||
m_solver->updt_params(p);
|
||||
}
|
||||
}
|
||||
|
||||
void cmd_context::display_model(model_ref& mdl) {
|
||||
if (mdl) {
|
||||
model_params p;
|
||||
|
@ -1582,7 +1605,9 @@ void cmd_context::validate_check_sat_result(lbool r) {
|
|||
throw cmd_exception("check annotation that says unsat");
|
||||
#else
|
||||
diagnostic_stream() << "BUG: incompleteness" << std::endl;
|
||||
exit(ERR_INCOMPLETENESS);
|
||||
// WORKAROUND: `exit()` causes LSan to be invoked and produce
|
||||
// many false positives.
|
||||
_Exit(ERR_INCOMPLETENESS);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -1592,7 +1617,9 @@ void cmd_context::validate_check_sat_result(lbool r) {
|
|||
throw cmd_exception("check annotation that says sat");
|
||||
#else
|
||||
diagnostic_stream() << "BUG: unsoundness" << std::endl;
|
||||
exit(ERR_UNSOUNDNESS);
|
||||
// WORKAROUND: `exit()` causes LSan to be invoked and produce
|
||||
// many false positives.
|
||||
_Exit(ERR_UNSOUNDNESS);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
@ -1743,6 +1770,7 @@ void cmd_context::validate_model() {
|
|||
continue;
|
||||
}
|
||||
try {
|
||||
for_each_expr(contains_underspecified, a);
|
||||
for_each_expr(contains_underspecified, r);
|
||||
}
|
||||
catch (contains_underspecified_op_proc::found) {
|
||||
|
|
|
@ -419,6 +419,7 @@ public:
|
|||
|
||||
void display_assertions();
|
||||
void display_statistics(bool show_total_time = false, double total_time = 0.0);
|
||||
void display_dimacs();
|
||||
void reset(bool finalize = false);
|
||||
void assert_expr(expr * t);
|
||||
void assert_expr(symbol const & name, expr * t);
|
||||
|
|
|
@ -31,7 +31,6 @@ Notes:
|
|||
#include "ast/rewriter/var_subst.h"
|
||||
#include "util/gparams.h"
|
||||
|
||||
#ifndef _EXTERNAL_RELEASE
|
||||
|
||||
BINARY_SYM_CMD(get_quantifier_body_cmd,
|
||||
"dbg-get-qbody",
|
||||
|
@ -343,10 +342,19 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
class print_dimacs_cmd : public cmd {
|
||||
public:
|
||||
print_dimacs_cmd():cmd("display-dimacs") {}
|
||||
virtual char const * get_usage() const { return ""; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "print benchmark in DIMACS format"; }
|
||||
virtual unsigned get_arity() const { return 0; }
|
||||
virtual void prepare(cmd_context & ctx) {}
|
||||
virtual void execute(cmd_context & ctx) { ctx.display_dimacs(); }
|
||||
};
|
||||
|
||||
|
||||
void install_dbg_cmds(cmd_context & ctx) {
|
||||
#ifndef _EXTERNAL_RELEASE
|
||||
ctx.insert(alloc(print_dimacs_cmd));
|
||||
ctx.insert(alloc(get_quantifier_body_cmd));
|
||||
ctx.insert(alloc(set_cmd));
|
||||
ctx.insert(alloc(pp_var_cmd));
|
||||
|
@ -369,5 +377,4 @@ void install_dbg_cmds(cmd_context & ctx) {
|
|||
ctx.insert(alloc(instantiate_cmd));
|
||||
ctx.insert(alloc(instantiate_nested_cmd));
|
||||
ctx.insert(alloc(set_next_id));
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -33,9 +33,11 @@
|
|||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "ast/expr_abstract.h"
|
||||
#include "util/params.h"
|
||||
#include "ast/used_vars.h"
|
||||
|
||||
|
||||
using namespace stl_ext;
|
||||
|
@ -938,3 +940,30 @@ void iz3mgr::get_bound_substitutes(stl_ext::hash_map<ast,bool> &memo, const ast
|
|||
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned iz3mgr::num_free_variables(const ast &e){
|
||||
used_vars uv;
|
||||
uv(to_expr(e.raw()));
|
||||
return uv.get_num_vars();
|
||||
}
|
||||
|
||||
iz3mgr::ast iz3mgr::close_universally (ast e){
|
||||
used_vars uv;
|
||||
uv(to_expr(e.raw()));
|
||||
std::vector<ast> bvs;
|
||||
stl_ext::hash_map<ast,ast> subst_memo;
|
||||
for (unsigned i = 0; i < uv.get_max_found_var_idx_plus_1(); i++){
|
||||
if (uv.get(i)) {
|
||||
std::ostringstream os;
|
||||
os << "%%" << i;
|
||||
ast c = make_var(os.str(),uv.get(i));
|
||||
ast v = cook(m().mk_var(i,uv.get(i)));
|
||||
subst_memo[v] = c;
|
||||
bvs.push_back(c);
|
||||
}
|
||||
}
|
||||
e = subst(subst_memo,e);
|
||||
for (unsigned i = 0; i < bvs.size(); i++)
|
||||
e = apply_quant(Forall,bvs[i],e);
|
||||
return e;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ class ast_r : public ast_i {
|
|||
|
||||
ast_r(const ast_r &other) : ast_i(other) {
|
||||
_m = other._m;
|
||||
_m->inc_ref(_ast);
|
||||
if (_m) _m->inc_ref(_ast);
|
||||
}
|
||||
|
||||
ast_r &operator=(const ast_r &other) {
|
||||
|
@ -104,7 +104,7 @@ class ast_r : public ast_i {
|
|||
_m->dec_ref(_ast);
|
||||
_ast = other._ast;
|
||||
_m = other._m;
|
||||
_m->inc_ref(_ast);
|
||||
if (_m) _m->inc_ref(_ast);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -661,6 +661,12 @@ class iz3mgr {
|
|||
|
||||
ast apply_quant(opr quantifier, ast var, ast e);
|
||||
|
||||
// Universally quantify all the free variables in a formula.
|
||||
// Makes up names for the quntifiers.
|
||||
|
||||
ast close_universally (ast e);
|
||||
|
||||
unsigned num_free_variables(const ast &e);
|
||||
|
||||
/** For debugging */
|
||||
void show(ast);
|
||||
|
|
|
@ -2968,9 +2968,9 @@ class iz3proof_itp_impl : public iz3proof_itp {
|
|||
ast interpolate(const node &pf){
|
||||
// proof of false must be a formula, with quantified symbols
|
||||
#ifndef BOGUS_QUANTS
|
||||
return add_quants(z3_simplify(pf));
|
||||
return close_universally(add_quants(z3_simplify(pf)));
|
||||
#else
|
||||
return z3_simplify(pf);
|
||||
return close_universally(z3_simplify(pf));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -234,6 +234,11 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// if(!range_is_empty(rng)){
|
||||
// if (num_free_variables(con) > 0)
|
||||
// rng = range_empty();
|
||||
// }
|
||||
|
||||
if(res == INT_MAX){
|
||||
if(range_is_empty(rng))
|
||||
res = -1;
|
||||
|
|
|
@ -24,6 +24,7 @@ Revision History:
|
|||
|
||||
#include "math/automata/symbolic_automata.h"
|
||||
#include "util/hashtable.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
|
||||
|
||||
|
@ -311,7 +312,7 @@ symbolic_automata<T, M>::mk_determinstic_param(automaton_t& a, bool flip_accepta
|
|||
s2id.insert(set, p_state_id++); // the index to the initial state is 0
|
||||
id2s.push_back(set);
|
||||
|
||||
svector<uint_set> todo; //States to visit
|
||||
::vector<uint_set> todo; //States to visit
|
||||
todo.push_back(set);
|
||||
|
||||
uint_set state;
|
||||
|
|
|
@ -162,7 +162,7 @@ private:
|
|||
void checkpoint();
|
||||
|
||||
public:
|
||||
interval_manager(reslimit& lim, C const & c);
|
||||
interval_manager(reslimit& lim, C && c);
|
||||
~interval_manager();
|
||||
|
||||
numeral_manager & m() const { return m_c.m(); }
|
||||
|
|
|
@ -31,7 +31,7 @@ Revision History:
|
|||
// #define TRACE_NTH_ROOT
|
||||
|
||||
template<typename C>
|
||||
interval_manager<C>::interval_manager(reslimit& lim, C const & c): m_limit(lim), m_c(c) {
|
||||
interval_manager<C>::interval_manager(reslimit& lim, C && c): m_limit(lim), m_c(std::move(c)) {
|
||||
m().set(m_minus_one, -1);
|
||||
m().set(m_one, 1);
|
||||
m_pi_n = 0;
|
||||
|
|
|
@ -2632,10 +2632,14 @@ namespace algebraic_numbers {
|
|||
scoped_mpz neg_n(qm());
|
||||
qm().set(neg_n, v.numerator());
|
||||
qm().neg(neg_n);
|
||||
mpz const coeffs[2] = { neg_n.get(), v.denominator() };
|
||||
unsynch_mpz_manager zmgr;
|
||||
// FIXME: remove these copies
|
||||
mpz coeffs[2] = { zmgr.dup(neg_n.get()), zmgr.dup(v.denominator()) };
|
||||
out << "(";
|
||||
upm().display(out, 2, coeffs, "#");
|
||||
out << ", 1)"; // first root of the polynomial d*# - n
|
||||
zmgr.del(coeffs[0]);
|
||||
zmgr.del(coeffs[1]);
|
||||
}
|
||||
else {
|
||||
algebraic_cell * c = a.to_algebraic();
|
||||
|
@ -2678,10 +2682,14 @@ namespace algebraic_numbers {
|
|||
scoped_mpz neg_n(qm());
|
||||
qm().set(neg_n, v.numerator());
|
||||
qm().neg(neg_n);
|
||||
mpz const coeffs[2] = { neg_n.get(), v.denominator() };
|
||||
unsynch_mpz_manager zmgr;
|
||||
// FIXME: remove these copies
|
||||
mpz coeffs[2] = { zmgr.dup(neg_n.get()), zmgr.dup(v.denominator()) };
|
||||
out << "(root-obj ";
|
||||
upm().display_smt2(out, 2, coeffs, "x");
|
||||
out << " 1)"; // first root of the polynomial d*# - n
|
||||
zmgr.del(coeffs[0]);
|
||||
zmgr.del(coeffs[1]);
|
||||
}
|
||||
else {
|
||||
algebraic_cell * c = a.to_algebraic();
|
||||
|
|
|
@ -3536,10 +3536,11 @@ namespace polynomial {
|
|||
iccp(p, max_var(p), i, c, pp);
|
||||
}
|
||||
|
||||
void pp(polynomial const * p, var x, polynomial_ref & pp) {
|
||||
polynomial_ref pp(polynomial const * p, var x) {
|
||||
scoped_numeral i(m_manager);
|
||||
polynomial_ref c(pm());
|
||||
iccp(p, x, i, c, pp);
|
||||
polynomial_ref c(pm()), result(pm());
|
||||
iccp(p, x, i, c, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool is_primitive(polynomial const * p, var x) {
|
||||
|
@ -3598,7 +3599,7 @@ namespace polynomial {
|
|||
if (is_zero(rem)) {
|
||||
TRACE("polynomial", tout << "rem is zero...\npp_v: " << pp_v << "\n";);
|
||||
flip_sign_if_lm_neg(pp_v);
|
||||
pp(pp_v, x, r);
|
||||
r = pp(pp_v, x);
|
||||
r = mul(d_a, d_r, r);
|
||||
return;
|
||||
}
|
||||
|
@ -3849,7 +3850,7 @@ namespace polynomial {
|
|||
TRACE("mgcd", tout << "new combined:\n" << C_star << "\n";);
|
||||
}
|
||||
}
|
||||
pp(C_star, x, candidate);
|
||||
candidate = pp(C_star, x);
|
||||
TRACE("mgcd", tout << "candidate:\n" << candidate << "\n";);
|
||||
scoped_numeral lc_candidate(m());
|
||||
lc_candidate = univ_coeff(candidate, degree(candidate, x));
|
||||
|
@ -4821,10 +4822,9 @@ namespace polynomial {
|
|||
|
||||
polynomial * mk_x_minus_y(var x, var y) {
|
||||
numeral zero(0);
|
||||
numeral one(1);
|
||||
numeral minus_one; // It is not safe to initialize with -1 when numeral_manager is GF_2
|
||||
m_manager.set(minus_one, -1);
|
||||
numeral as[2] = { one, minus_one };
|
||||
numeral as[2] = { numeral(1), std::move(minus_one) };
|
||||
var xs[2] = { x, y };
|
||||
return mk_linear(2, as, xs, zero);
|
||||
}
|
||||
|
@ -4844,8 +4844,7 @@ namespace polynomial {
|
|||
|
||||
polynomial * mk_x_plus_y(var x, var y) {
|
||||
numeral zero(0);
|
||||
numeral one(1);
|
||||
numeral as[2] = { one, one };
|
||||
numeral as[2] = { numeral(1), numeral(1) };
|
||||
var xs[2] = { x, y };
|
||||
return mk_linear(2, as, xs, zero);
|
||||
}
|
||||
|
@ -6619,8 +6618,8 @@ namespace polynomial {
|
|||
polynomial_ref cf1(pm()); m_wrapper.content(f1, x, cf1);
|
||||
polynomial_ref cf2(pm()); m_wrapper.content(f2, x, cf2);
|
||||
tout << "content(f1): " << cf1 << "\ncontent(f2): " << cf2 << "\n";);
|
||||
pp(f1, x, f1);
|
||||
pp(f2, x, f2);
|
||||
f1 = pp(f1, x);
|
||||
f2 = pp(f2, x);
|
||||
TRACE("factor", tout << "f1: " << f1 << "\nf2: " << f2 << "\n";);
|
||||
DEBUG_CODE({
|
||||
polynomial_ref f1f2(pm());
|
||||
|
@ -7150,7 +7149,7 @@ namespace polynomial {
|
|||
}
|
||||
|
||||
void manager::primitive(polynomial const * p, var x, polynomial_ref & pp) {
|
||||
m_imp->pp(p, x, pp);
|
||||
pp = m_imp->pp(p, x);
|
||||
}
|
||||
|
||||
void manager::icpp(polynomial const * p, var x, numeral & i, polynomial_ref & c, polynomial_ref & pp) {
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace upolynomial {
|
|||
for (unsigned i = 0; i < p.size(); ++ i) {
|
||||
numeral p_i; // no need to delete, we keep it pushed in zp_p
|
||||
zp_nm.set(p_i, p[i]);
|
||||
zp_p.push_back(p_i);
|
||||
zp_p.push_back(std::move(p_i));
|
||||
}
|
||||
zp_upm.trim(zp_p);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace simplex {
|
|||
struct row_entry {
|
||||
numeral m_coeff;
|
||||
var_t m_var;
|
||||
row_entry(numeral const& c, var_t v): m_coeff(c), m_var(v) {}
|
||||
row_entry(numeral && c, var_t v) : m_coeff(std::move(c)), m_var(v) {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -61,7 +61,7 @@ namespace simplex {
|
|||
int m_col_idx;
|
||||
int m_next_free_row_entry_idx;
|
||||
};
|
||||
_row_entry(numeral const & c, var_t v): row_entry(c, v), m_col_idx(0) {}
|
||||
_row_entry(numeral && c, var_t v) : row_entry(std::move(c), v), m_col_idx(0) {}
|
||||
_row_entry() : row_entry(numeral(), dead_id), m_col_idx(0) {}
|
||||
bool is_dead() const { return row_entry::m_var == dead_id; }
|
||||
};
|
||||
|
|
|
@ -739,7 +739,7 @@ void context_t<C>::del_sum(polynomial * p) {
|
|||
|
||||
template<typename C>
|
||||
var context_t<C>::mk_sum(numeral const & c, unsigned sz, numeral const * as, var const * xs) {
|
||||
m_num_buffer.reserve(num_vars(), numeral());
|
||||
m_num_buffer.reserve(num_vars());
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
SASSERT(xs[i] < num_vars());
|
||||
nm().set(m_num_buffer[xs[i]], as[i]);
|
||||
|
|
|
@ -117,7 +117,7 @@ bool func_interp::is_fi_entry_expr(expr * e, ptr_vector<expr> & args) {
|
|||
(m_arity > 1 && (!m().is_and(c) || to_app(c)->get_num_args() != m_arity)))
|
||||
return false;
|
||||
|
||||
args.resize(m_arity, 0);
|
||||
args.resize(m_arity);
|
||||
for (unsigned i = 0; i < m_arity; i++) {
|
||||
expr * ci = (m_arity == 1 && i == 0) ? c : to_app(c)->get_arg(i);
|
||||
|
||||
|
@ -140,7 +140,6 @@ void func_interp::set_else(expr * e) {
|
|||
return;
|
||||
|
||||
reset_interp_cache();
|
||||
|
||||
ptr_vector<expr> args;
|
||||
while (e && is_fi_entry_expr(e, args)) {
|
||||
TRACE("func_interp", tout << "fi entry expr: " << mk_ismt2_pp(e, m()) << std::endl;);
|
||||
|
|
|
@ -86,18 +86,22 @@ void model_core::register_decl(func_decl * d, func_interp * fi) {
|
|||
void model_core::unregister_decl(func_decl * d) {
|
||||
decl2expr::obj_map_entry * ec = m_interp.find_core(d);
|
||||
if (ec && ec->get_data().m_value != 0) {
|
||||
m_manager.dec_ref(ec->get_data().m_key);
|
||||
m_manager.dec_ref(ec->get_data().m_value);
|
||||
auto k = ec->get_data().m_key;
|
||||
auto v = ec->get_data().m_value;
|
||||
m_interp.remove(d);
|
||||
m_const_decls.erase(d);
|
||||
m_manager.dec_ref(k);
|
||||
m_manager.dec_ref(v);
|
||||
return;
|
||||
}
|
||||
|
||||
decl2finterp::obj_map_entry * ef = m_finterp.find_core(d);
|
||||
if (ef && ef->get_data().m_value != 0) {
|
||||
m_manager.dec_ref(ef->get_data().m_key);
|
||||
dealloc(ef->get_data().m_value);
|
||||
auto k = ef->get_data().m_key;
|
||||
auto v = ef->get_data().m_value;
|
||||
m_finterp.remove(d);
|
||||
m_func_decls.erase(d);
|
||||
m_manager.dec_ref(k);
|
||||
dealloc(v);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -453,7 +453,8 @@ namespace datalog {
|
|||
return new_pred;
|
||||
}
|
||||
|
||||
void context::add_rule(expr* rl, symbol const& name, unsigned bound) {
|
||||
void context::add_rule(expr* rl, symbol const& name, unsigned bound) {
|
||||
SASSERT(rl);
|
||||
m_rule_fmls.push_back(rl);
|
||||
m_rule_names.push_back(name);
|
||||
m_rule_bounds.push_back(bound);
|
||||
|
|
|
@ -192,10 +192,15 @@ namespace datalog {
|
|||
for (unsigned i = 0; i < new_tbvs.size(); ++i) {
|
||||
tbv const& nt = *new_tbvs[i];
|
||||
IF_VERBOSE(10, m_tbv.display(verbose_stream() << "insert: ", nt); verbose_stream() << "\n";);
|
||||
if (contains(nt)) continue;
|
||||
ddnf_node* n = alloc(ddnf_node, *this, m_tbv, nt, m_noderefs.size());
|
||||
m_noderefs.push_back(n);
|
||||
m_nodes.insert(n);
|
||||
ddnf_node* n;
|
||||
if (contains(nt)) {
|
||||
n = find(nt);
|
||||
}
|
||||
else {
|
||||
n = alloc(ddnf_node, *this, m_tbv, nt, m_noderefs.size());
|
||||
m_noderefs.push_back(n);
|
||||
m_nodes.insert(n);
|
||||
}
|
||||
insert(*m_root, n, new_tbvs);
|
||||
}
|
||||
return find(t);
|
||||
|
@ -275,13 +280,17 @@ namespace datalog {
|
|||
void insert(ddnf_node& root, ddnf_node* new_n, ptr_vector<tbv const>& new_intersections) {
|
||||
tbv const& new_tbv = new_n->get_tbv();
|
||||
|
||||
IF_VERBOSE(10, m_tbv.display(verbose_stream() << "root: ", root.get_tbv());
|
||||
m_tbv.display(verbose_stream() << " new node ", new_tbv); verbose_stream() << "\n";);
|
||||
SASSERT(m_tbv.contains(root.get_tbv(), new_tbv));
|
||||
if (&root == new_n) return;
|
||||
if (m_eq(&root, new_n)) return;
|
||||
++m_stats.m_num_inserts;
|
||||
bool inserted = false;
|
||||
for (unsigned i = 0; i < root.num_children(); ++i) {
|
||||
ddnf_node& child = *(root[i]);
|
||||
++m_stats.m_num_comparisons;
|
||||
IF_VERBOSE(10, m_tbv.display(verbose_stream() << "child ", child.get_tbv());
|
||||
verbose_stream() << " contains: " << m_tbv.contains(child.get_tbv(), new_tbv) << "\n";);
|
||||
if (m_tbv.contains(child.get_tbv(), new_tbv)) {
|
||||
inserted = true;
|
||||
insert(child, new_n, new_intersections);
|
||||
|
@ -299,11 +308,13 @@ namespace datalog {
|
|||
// checking for subset
|
||||
if (m_tbv.contains(new_tbv, child.get_tbv())) {
|
||||
subset_children.push_back(&child);
|
||||
IF_VERBOSE(10, m_tbv.display(verbose_stream() << "contains child", child.get_tbv()); verbose_stream() << "\n";);
|
||||
++m_stats.m_num_comparisons;
|
||||
}
|
||||
else if (m_tbv.intersect(child.get_tbv(), new_tbv, *intr)) {
|
||||
// this means there is a non-full intersection
|
||||
new_intersections.push_back(intr);
|
||||
IF_VERBOSE(10, m_tbv.display(verbose_stream() << "intersect child ", child.get_tbv()); verbose_stream() << "\n";);
|
||||
intr = m_tbv.allocate();
|
||||
m_stats.m_num_comparisons += 2;
|
||||
}
|
||||
|
|
|
@ -189,11 +189,12 @@ public:
|
|||
m_bound = bound;
|
||||
m_arg_idx++;
|
||||
}
|
||||
virtual void reset(cmd_context & ctx) { m_dl_ctx->reset(); prepare(ctx); }
|
||||
virtual void reset(cmd_context & ctx) { m_dl_ctx->reset(); prepare(ctx); m_t = nullptr; }
|
||||
virtual void prepare(cmd_context& ctx) { m_arg_idx = 0; m_name = symbol::null; m_bound = UINT_MAX; }
|
||||
virtual void finalize(cmd_context & ctx) {
|
||||
}
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
if (!m_t) throw cmd_exception("invalid rule, expected formula");
|
||||
m_dl_ctx->add_rule(m_t, m_name, m_bound);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace datalog {
|
|||
void set_reg(reg_idx i, reg_type val) {
|
||||
if (i >= m_registers.size()) {
|
||||
check_overflow(i);
|
||||
m_registers.resize(i+1,0);
|
||||
m_registers.resize(i+1);
|
||||
}
|
||||
if (m_registers[i]) {
|
||||
m_registers[i]->deallocate();
|
||||
|
|
|
@ -465,7 +465,7 @@ namespace datalog {
|
|||
|
||||
unsigned sz = r.get_signature().size();
|
||||
ptr_vector<expr> subst_arg;
|
||||
subst_arg.resize(sz, 0);
|
||||
subst_arg.resize(sz);
|
||||
unsigned ofs = sz-1;
|
||||
for (unsigned i=0; i<sz; i++) {
|
||||
SASSERT(!r.is_undefined(i) || !contains_var(m_new_rule, i));
|
||||
|
|
|
@ -111,8 +111,8 @@ namespace datalog {
|
|||
|
||||
void filter_interpreted(app* cond) {
|
||||
rational one(1), mone(-1);
|
||||
expr* e1, *e2, *en;
|
||||
var* v, *w;
|
||||
expr* e1 = 0, *e2 = 0, *en = 0;
|
||||
var* v = 0, *w = 0;
|
||||
rational n1, n2;
|
||||
expr_ref_vector conjs(m);
|
||||
flatten_and(cond, conjs);
|
||||
|
|
|
@ -74,8 +74,7 @@ tbv* tbv_manager::allocate(tbv const& bv) {
|
|||
}
|
||||
tbv* tbv_manager::allocate(uint64 val) {
|
||||
tbv* v = allocate0();
|
||||
for (unsigned bit = num_tbits(); bit > 0;) {
|
||||
--bit;
|
||||
for (unsigned bit = std::min(64u, num_tbits()); bit-- > 0;) {
|
||||
if (val & (1ULL << bit)) {
|
||||
set(*v, bit, BIT_1);
|
||||
} else {
|
||||
|
|
|
@ -66,7 +66,6 @@ class peq {
|
|||
app_ref m_peq; // partial equality application
|
||||
app_ref m_eq; // equivalent std equality using def. of partial eq
|
||||
array_util m_arr_u;
|
||||
ast_eq_proc m_eq_proc; // for checking if two asts are equal
|
||||
|
||||
public:
|
||||
static const char* PARTIAL_EQ;
|
||||
|
@ -102,7 +101,7 @@ peq::peq (app* p, ast_manager& m):
|
|||
VERIFY (is_partial_eq (p));
|
||||
SASSERT (m_arr_u.is_array (m_lhs) &&
|
||||
m_arr_u.is_array (m_rhs) &&
|
||||
m_eq_proc (m.get_sort (m_lhs), m.get_sort (m_rhs)));
|
||||
ast_eq_proc() (m.get_sort (m_lhs), m.get_sort (m_rhs)));
|
||||
for (unsigned i = 2; i < p->get_num_args (); i++) {
|
||||
m_diff_indices.push_back (p->get_arg (i));
|
||||
}
|
||||
|
@ -121,7 +120,7 @@ peq::peq (expr* lhs, expr* rhs, unsigned num_indices, expr * const * diff_indice
|
|||
{
|
||||
SASSERT (m_arr_u.is_array (lhs) &&
|
||||
m_arr_u.is_array (rhs) &&
|
||||
m_eq_proc (m.get_sort (lhs), m.get_sort (rhs)));
|
||||
ast_eq_proc() (m.get_sort (lhs), m.get_sort (rhs)));
|
||||
ptr_vector<sort> sorts;
|
||||
sorts.push_back (m.get_sort (m_lhs));
|
||||
sorts.push_back (m.get_sort (m_rhs));
|
||||
|
|
|
@ -398,8 +398,8 @@ namespace datalog {
|
|||
}
|
||||
|
||||
bool mk_interp_tail_simplifier::propagate_variable_equivalences(rule * r, rule_ref& res) {
|
||||
if (!m_context.get_params ().xform_tail_simplifier_pve ())
|
||||
return false;
|
||||
if (!m_context.get_params ().xform_tail_simplifier_pve ())
|
||||
return false;
|
||||
unsigned u_len = r->get_uninterpreted_tail_size();
|
||||
unsigned len = r->get_tail_size();
|
||||
if (u_len == len) {
|
||||
|
|
|
@ -24,6 +24,7 @@ Revision History:
|
|||
#include "ast/ast_pp.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/rewriter/rewriter.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/has_free_vars.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "parsers/smt2/smt2parser.h"
|
||||
|
@ -68,6 +69,7 @@ namespace smt2 {
|
|||
|
||||
scoped_ptr<bv_util> m_bv_util;
|
||||
scoped_ptr<arith_util> m_arith_util;
|
||||
scoped_ptr<datatype_util> m_datatype_util;
|
||||
scoped_ptr<seq_util> m_seq_util;
|
||||
scoped_ptr<pattern_validator> m_pattern_validator;
|
||||
scoped_ptr<var_shifter> m_var_shifter;
|
||||
|
@ -108,6 +110,7 @@ namespace smt2 {
|
|||
symbol m_check_sat_assuming;
|
||||
symbol m_define_fun_rec;
|
||||
symbol m_define_funs_rec;
|
||||
symbol m_match;
|
||||
symbol m_underscore;
|
||||
|
||||
typedef std::pair<symbol, expr*> named_expr;
|
||||
|
@ -135,7 +138,7 @@ namespace smt2 {
|
|||
|
||||
typedef psort_frame sort_frame;
|
||||
|
||||
enum expr_frame_kind { EF_APP, EF_LET, EF_LET_DECL, EF_QUANT, EF_ATTR_EXPR, EF_PATTERN };
|
||||
enum expr_frame_kind { EF_APP, EF_LET, EF_LET_DECL, EF_MATCH, EF_QUANT, EF_ATTR_EXPR, EF_PATTERN };
|
||||
|
||||
struct expr_frame {
|
||||
expr_frame_kind m_kind;
|
||||
|
@ -172,6 +175,10 @@ namespace smt2 {
|
|||
m_expr_spos(expr_spos) {}
|
||||
};
|
||||
|
||||
struct match_frame : public expr_frame {
|
||||
match_frame():expr_frame(EF_MATCH) {}
|
||||
};
|
||||
|
||||
struct let_frame : public expr_frame {
|
||||
bool m_in_decls;
|
||||
unsigned m_sym_spos;
|
||||
|
@ -275,6 +282,12 @@ namespace smt2 {
|
|||
return *(m_arith_util.get());
|
||||
}
|
||||
|
||||
datatype_util & dtutil() {
|
||||
if (m_datatype_util.get() == 0)
|
||||
m_datatype_util = alloc(datatype_util, m());
|
||||
return *(m_datatype_util.get());
|
||||
}
|
||||
|
||||
seq_util & sutil() {
|
||||
if (m_seq_util.get() == 0)
|
||||
m_seq_util = alloc(seq_util, m());
|
||||
|
@ -389,6 +402,7 @@ namespace smt2 {
|
|||
|
||||
bool curr_id_is_underscore() const { SASSERT(curr_is_identifier()); return curr_id() == m_underscore; }
|
||||
bool curr_id_is_as() const { SASSERT(curr_is_identifier()); return curr_id() == m_as; }
|
||||
bool curr_id_is_match() const { SASSERT(curr_is_identifier()); return curr_id() == m_match; }
|
||||
bool curr_id_is_forall() const { SASSERT(curr_is_identifier()); return curr_id() == m_forall; }
|
||||
bool curr_id_is_exists() const { SASSERT(curr_is_identifier()); return curr_id() == m_exists; }
|
||||
bool curr_id_is_bang() const { SASSERT(curr_is_identifier()); return curr_id() == m_bang; }
|
||||
|
@ -430,7 +444,10 @@ namespace smt2 {
|
|||
m_ctx.regular_stream()<< "line " << line << " column " << pos << ": " << escaped(msg, true) << "\")" << std::endl;
|
||||
}
|
||||
if (m_ctx.exit_on_error()) {
|
||||
exit(1);
|
||||
// WORKAROUND: ASan's LeakSanitizer reports many false positives when
|
||||
// calling `exit()` so call `_Exit()` instead which avoids invoking leak
|
||||
// checking.
|
||||
_Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1258,6 +1275,23 @@ namespace smt2 {
|
|||
return num;
|
||||
}
|
||||
|
||||
void push_let_frame() {
|
||||
next();
|
||||
check_lparen_next("invalid let declaration, '(' expected");
|
||||
void * mem = m_stack.allocate(sizeof(let_frame));
|
||||
new (mem) let_frame(symbol_stack().size(), expr_stack().size());
|
||||
m_num_expr_frames++;
|
||||
}
|
||||
|
||||
void push_bang_frame(expr_frame * curr) {
|
||||
TRACE("consume_attributes", tout << "begin bang, expr_stack.size(): " << expr_stack().size() << "\n";);
|
||||
next();
|
||||
void * mem = m_stack.allocate(sizeof(attr_expr_frame));
|
||||
new (mem) attr_expr_frame(curr, symbol_stack().size(), expr_stack().size());
|
||||
m_num_expr_frames++;
|
||||
}
|
||||
|
||||
|
||||
void push_quant_frame(bool is_forall) {
|
||||
SASSERT(curr_is_identifier());
|
||||
SASSERT(curr_id_is_forall() || curr_id_is_exists());
|
||||
|
@ -1273,6 +1307,202 @@ namespace smt2 {
|
|||
throw parser_exception("invalid quantifier, list of sorted variables is empty");
|
||||
}
|
||||
|
||||
/**
|
||||
* SMT-LIB 2.6 pattern matches are of the form
|
||||
* (match t ((p1 t1) ... (pm+1 tm+1)))
|
||||
*/
|
||||
void push_match_frame() {
|
||||
SASSERT(curr_is_identifier());
|
||||
SASSERT(curr_id() == m_match);
|
||||
next();
|
||||
void * mem = m_stack.allocate(sizeof(match_frame));
|
||||
new (mem) match_frame();
|
||||
unsigned num_frames = m_num_expr_frames;
|
||||
|
||||
parse_expr();
|
||||
expr_ref t(expr_stack().back(), m());
|
||||
expr_stack().pop_back();
|
||||
expr_ref_vector patterns(m()), cases(m());
|
||||
sort* srt = m().get_sort(t);
|
||||
|
||||
check_lparen_next("pattern bindings should be enclosed in a parenthesis");
|
||||
while (!curr_is_rparen()) {
|
||||
m_env.begin_scope();
|
||||
unsigned num_bindings = m_num_bindings;
|
||||
check_lparen_next("invalid pattern binding, '(' expected");
|
||||
parse_match_pattern(srt);
|
||||
patterns.push_back(expr_stack().back());
|
||||
expr_stack().pop_back();
|
||||
parse_expr();
|
||||
cases.push_back(expr_stack().back());
|
||||
expr_stack().pop_back();
|
||||
m_num_bindings = num_bindings;
|
||||
m_env.end_scope();
|
||||
check_rparen_next("invalid pattern binding, ')' expected");
|
||||
}
|
||||
next();
|
||||
m_num_expr_frames = num_frames + 1;
|
||||
expr_stack().push_back(compile_patterns(t, patterns, cases));
|
||||
}
|
||||
|
||||
void pop_match_frame(match_frame* fr) {
|
||||
m_stack.deallocate(fr);
|
||||
m_num_expr_frames--;
|
||||
}
|
||||
|
||||
expr_ref compile_patterns(expr* t, expr_ref_vector const& patterns, expr_ref_vector const& cases) {
|
||||
expr_ref result(m());
|
||||
var_subst sub(m(), false);
|
||||
TRACE("parse_expr", tout << "term\n" << expr_ref(t, m()) << "\npatterns\n" << patterns << "\ncases\n" << cases << "\n";);
|
||||
check_patterns(patterns, m().get_sort(t));
|
||||
for (unsigned i = patterns.size(); i > 0; ) {
|
||||
--i;
|
||||
expr_ref_vector subst(m());
|
||||
expr_ref cond = bind_match(t, patterns[i], subst);
|
||||
expr_ref new_case(m());
|
||||
if (subst.empty()) {
|
||||
new_case = cases[i];
|
||||
}
|
||||
else {
|
||||
sub(cases[i], subst.size(), subst.c_ptr(), new_case);
|
||||
inv_var_shifter inv(m());
|
||||
inv(new_case, subst.size(), new_case);
|
||||
}
|
||||
if (result) {
|
||||
result = m().mk_ite(cond, new_case, result);
|
||||
}
|
||||
else {
|
||||
// pattern match binding is ignored.
|
||||
result = new_case;
|
||||
}
|
||||
}
|
||||
TRACE("parse_expr", tout << result << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
void check_patterns(expr_ref_vector const& patterns, sort* s) {
|
||||
if (!dtutil().is_datatype(s))
|
||||
throw parser_exception("pattern matching is only supported for algebraic datatypes");
|
||||
ptr_vector<func_decl> const& cons = *dtutil().get_datatype_constructors(s);
|
||||
for (expr * arg : patterns) if (is_var(arg)) return;
|
||||
if (patterns.size() < cons.size())
|
||||
throw parser_exception("non-exhaustive pattern match");
|
||||
ast_fast_mark1 marked;
|
||||
for (expr * arg : patterns)
|
||||
marked.mark(to_app(arg)->get_decl(), true);
|
||||
for (func_decl * f : cons)
|
||||
if (!marked.is_marked(f))
|
||||
throw parser_exception("a constructor is missing from pattern match");
|
||||
}
|
||||
|
||||
// compute match condition and substitution
|
||||
// t is shifted by size of subst.
|
||||
expr_ref bind_match(expr* t, expr* pattern, expr_ref_vector& subst) {
|
||||
expr_ref tsh(m());
|
||||
if (is_var(pattern)) {
|
||||
shifter()(t, 1, tsh);
|
||||
subst.push_back(tsh);
|
||||
return expr_ref(m().mk_true(), m());
|
||||
}
|
||||
else {
|
||||
SASSERT(is_app(pattern));
|
||||
func_decl * f = to_app(pattern)->get_decl();
|
||||
func_decl * r = dtutil().get_constructor_recognizer(f);
|
||||
ptr_vector<func_decl> const * acc = dtutil().get_constructor_accessors(f);
|
||||
shifter()(t, acc->size(), tsh);
|
||||
for (func_decl* a : *acc) {
|
||||
subst.push_back(m().mk_app(a, tsh));
|
||||
}
|
||||
return expr_ref(m().mk_app(r, t), m());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* parse a match pattern
|
||||
* (C x1 .... xn)
|
||||
* C
|
||||
* _
|
||||
* x
|
||||
*/
|
||||
|
||||
bool parse_constructor_pattern(sort * srt) {
|
||||
if (!curr_is_lparen()) {
|
||||
return false;
|
||||
}
|
||||
next();
|
||||
svector<symbol> vars;
|
||||
expr_ref_vector args(m());
|
||||
symbol C(check_identifier_next("constructor symbol expected"));
|
||||
while (!curr_is_rparen()) {
|
||||
symbol v(check_identifier_next("variable symbol expected"));
|
||||
if (v != m_underscore && vars.contains(v)) {
|
||||
throw parser_exception("unexpected repeated variable in pattern expression");
|
||||
}
|
||||
vars.push_back(v);
|
||||
}
|
||||
next();
|
||||
|
||||
// now have C, vars
|
||||
// look up constructor C,
|
||||
// create bound variables based on constructor type.
|
||||
// store expression in expr_stack().
|
||||
// ensure that bound variables are adjusted to vars
|
||||
|
||||
func_decl* f = m_ctx.find_func_decl(C, 0, nullptr, vars.size(), nullptr, srt);
|
||||
if (!f) {
|
||||
throw parser_exception("expecting a constructor that has been declared");
|
||||
}
|
||||
if (!dtutil().is_constructor(f)) {
|
||||
throw parser_exception("expecting a constructor");
|
||||
}
|
||||
if (f->get_arity() != vars.size()) {
|
||||
throw parser_exception("mismatching number of variables supplied to constructor");
|
||||
}
|
||||
m_num_bindings += vars.size();
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
var * v = m().mk_var(i, f->get_domain(i));
|
||||
args.push_back(v);
|
||||
if (vars[i] != m_underscore) {
|
||||
m_env.insert(vars[i], local(v, m_num_bindings));
|
||||
}
|
||||
}
|
||||
expr_stack().push_back(m().mk_app(f, args.size(), args.c_ptr()));
|
||||
return true;
|
||||
}
|
||||
|
||||
void parse_match_pattern(sort* srt) {
|
||||
if (parse_constructor_pattern(srt)) {
|
||||
// done
|
||||
}
|
||||
else if (curr_id() == m_underscore) {
|
||||
// we have a wild-card.
|
||||
// store dummy variable in expr_stack()
|
||||
next();
|
||||
var* v = m().mk_var(0, srt);
|
||||
expr_stack().push_back(v);
|
||||
}
|
||||
else {
|
||||
symbol xC(check_identifier_next("constructor symbol or variable expected"));
|
||||
// check if xC is a constructor, otherwise make it a variable
|
||||
// of sort srt.
|
||||
try {
|
||||
func_decl* f = m_ctx.find_func_decl(xC, 0, nullptr, 0, nullptr, srt);
|
||||
if (!dtutil().is_constructor(f)) {
|
||||
throw parser_exception("expecting a constructor, got a previously declared function");
|
||||
}
|
||||
if (f->get_arity() > 0) {
|
||||
throw parser_exception("constructor expects arguments, but no arguments were supplied in pattern");
|
||||
}
|
||||
expr_stack().push_back(m().mk_const(f));
|
||||
}
|
||||
catch (cmd_exception &) {
|
||||
var* v = m().mk_var(0, srt);
|
||||
expr_stack().push_back(v);
|
||||
m_env.insert(xC, local(v, m_num_bindings++));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
symbol parse_indexed_identifier_core() {
|
||||
check_underscore_next("invalid indexed identifier, '_' expected");
|
||||
check_identifier("invalid indexed identifier, symbol expected");
|
||||
|
@ -1564,8 +1794,7 @@ namespace smt2 {
|
|||
new (mem) app_frame(f, expr_spos, param_spos, has_as);
|
||||
m_num_expr_frames++;
|
||||
}
|
||||
|
||||
// return true if a new frame was created.
|
||||
|
||||
void push_expr_frame(expr_frame * curr) {
|
||||
SASSERT(curr_is_lparen());
|
||||
next();
|
||||
|
@ -1573,11 +1802,7 @@ namespace smt2 {
|
|||
if (curr_is_identifier()) {
|
||||
TRACE("push_expr_frame", tout << "push_expr_frame(), curr_id(): " << curr_id() << "\n";);
|
||||
if (curr_id_is_let()) {
|
||||
next();
|
||||
check_lparen_next("invalid let declaration, '(' expected");
|
||||
void * mem = m_stack.allocate(sizeof(let_frame));
|
||||
new (mem) let_frame(symbol_stack().size(), expr_stack().size());
|
||||
m_num_expr_frames++;
|
||||
push_let_frame();
|
||||
}
|
||||
else if (curr_id_is_forall()) {
|
||||
push_quant_frame(true);
|
||||
|
@ -1586,19 +1811,17 @@ namespace smt2 {
|
|||
push_quant_frame(false);
|
||||
}
|
||||
else if (curr_id_is_bang()) {
|
||||
TRACE("consume_attributes", tout << "begin bang, expr_stack.size(): " << expr_stack().size() << "\n";);
|
||||
next();
|
||||
void * mem = m_stack.allocate(sizeof(attr_expr_frame));
|
||||
new (mem) attr_expr_frame(curr, symbol_stack().size(), expr_stack().size());
|
||||
m_num_expr_frames++;
|
||||
push_bang_frame(curr);
|
||||
}
|
||||
else if (curr_id_is_as() || curr_id_is_underscore()) {
|
||||
TRACE("push_expr_frame", tout << "push_expr_frame(): parse_qualified_name\n";);
|
||||
parse_qualified_name();
|
||||
}
|
||||
else if (curr_id_is_root_obj()) {
|
||||
parse_root_obj();
|
||||
}
|
||||
else if (curr_id_is_match()) {
|
||||
push_match_frame();
|
||||
}
|
||||
else {
|
||||
push_app_frame();
|
||||
}
|
||||
|
@ -1658,6 +1881,8 @@ namespace smt2 {
|
|||
// the resultant expression is on the top of the stack
|
||||
TRACE("let_frame", tout << "let result expr: " << mk_pp(expr_stack().back(), m()) << "\n";);
|
||||
expr_ref r(m());
|
||||
if (expr_stack().empty())
|
||||
throw parser_exception("invalid let expression");
|
||||
r = expr_stack().back();
|
||||
expr_stack().pop_back();
|
||||
// remove local declarations from the stack
|
||||
|
@ -1773,6 +1998,9 @@ namespace smt2 {
|
|||
m_stack.deallocate(static_cast<let_decl_frame*>(fr));
|
||||
m_num_expr_frames--;
|
||||
break;
|
||||
case EF_MATCH:
|
||||
pop_match_frame(static_cast<match_frame*>(fr));
|
||||
break;
|
||||
case EF_QUANT:
|
||||
pop_quant_frame(static_cast<quant_frame*>(fr));
|
||||
break;
|
||||
|
@ -2232,8 +2460,10 @@ namespace smt2 {
|
|||
throw cmd_exception("invalid assert command, expression required as argument");
|
||||
}
|
||||
expr * f = expr_stack().back();
|
||||
if (!m().is_bool(f))
|
||||
if (!m().is_bool(f)) {
|
||||
TRACE("smt2parser", tout << expr_ref(f, m()) << "\n";);
|
||||
throw cmd_exception("invalid assert command, term is not Boolean");
|
||||
}
|
||||
if (f == m_last_named_expr.second) {
|
||||
m_ctx.assert_expr(m_last_named_expr.first, f);
|
||||
}
|
||||
|
@ -2730,6 +2960,7 @@ namespace smt2 {
|
|||
m_check_sat_assuming("check-sat-assuming"),
|
||||
m_define_fun_rec("define-fun-rec"),
|
||||
m_define_funs_rec("define-funs-rec"),
|
||||
m_match("match"),
|
||||
m_underscore("_"),
|
||||
m_num_open_paren(0),
|
||||
m_current_file(filename) {
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace smt2 {
|
|||
next();
|
||||
bool is_float = false;
|
||||
|
||||
while (true) {
|
||||
while (!m_at_eof) {
|
||||
char c = curr();
|
||||
if ('0' <= c && c <= '9') {
|
||||
m_number = rational(10)*m_number + rational(c - '0');
|
||||
|
|
|
@ -1272,7 +1272,7 @@ namespace qe {
|
|||
family_id fid = p->get_family_id();
|
||||
SASSERT(fid != null_family_id);
|
||||
if (static_cast<int>(m_plugins.size()) <= fid) {
|
||||
m_plugins.resize(fid+1,0);
|
||||
m_plugins.resize(fid+1);
|
||||
}
|
||||
SASSERT(!m_plugins[fid]);
|
||||
m_plugins[fid] = p;
|
||||
|
|
|
@ -105,10 +105,10 @@ namespace qe {
|
|||
rational r;
|
||||
app* alit = to_app(lit);
|
||||
vector<std::pair<expr*,rational> > nums;
|
||||
for (unsigned i = 0; i < alit->get_num_args(); ++i) {
|
||||
val = eval(alit->get_arg(i));
|
||||
for (expr* arg : *alit) {
|
||||
val = eval(arg);
|
||||
if (!a.is_numeral(val, r)) return false;
|
||||
nums.push_back(std::make_pair(alit->get_arg(i), r));
|
||||
nums.push_back(std::make_pair(arg, r));
|
||||
}
|
||||
std::sort(nums.begin(), nums.end(), compare_second());
|
||||
for (unsigned i = 0; i + 1 < nums.size(); ++i) {
|
||||
|
@ -168,8 +168,8 @@ namespace qe {
|
|||
}
|
||||
else if (a.is_add(t)) {
|
||||
app* ap = to_app(t);
|
||||
for (unsigned i = 0; i < ap->get_num_args(); ++i) {
|
||||
linearize(mbo, eval, mul, ap->get_arg(i), c, fmls, ts, tids);
|
||||
for (expr* arg : *ap) {
|
||||
linearize(mbo, eval, mul, arg, c, fmls, ts, tids);
|
||||
}
|
||||
}
|
||||
else if (a.is_sub(t, t1, t2)) {
|
||||
|
@ -226,16 +226,16 @@ namespace qe {
|
|||
else if (a.is_mul(t)) {
|
||||
app* ap = to_app(t);
|
||||
r = rational(1);
|
||||
for (unsigned i = 0; i < ap->get_num_args(); ++i) {
|
||||
if (!is_numeral(ap->get_arg(i), r1)) return false;
|
||||
for (expr * arg : *ap) {
|
||||
if (!is_numeral(arg, r1)) return false;
|
||||
r *= r1;
|
||||
}
|
||||
}
|
||||
else if (a.is_add(t)) {
|
||||
app* ap = to_app(t);
|
||||
r = rational(0);
|
||||
for (unsigned i = 0; i < ap->get_num_args(); ++i) {
|
||||
if (!is_numeral(ap->get_arg(i), r1)) return false;
|
||||
for (expr * arg : *ap) {
|
||||
if (!is_numeral(arg, r1)) return false;
|
||||
r += r1;
|
||||
}
|
||||
}
|
||||
|
@ -297,6 +297,7 @@ namespace qe {
|
|||
|
||||
opt::model_based_opt mbo;
|
||||
obj_map<expr, unsigned> tids;
|
||||
expr_ref_vector pinned(m);
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < fmls.size(); ++i) {
|
||||
expr* fml = fmls[i].get();
|
||||
|
@ -308,6 +309,7 @@ namespace qe {
|
|||
}
|
||||
else {
|
||||
TRACE("qe", tout << mk_pp(fml, m) << "\n";);
|
||||
pinned.push_back(fml);
|
||||
}
|
||||
}
|
||||
fmls.resize(j);
|
||||
|
@ -321,8 +323,7 @@ namespace qe {
|
|||
// return those to fmls.
|
||||
|
||||
expr_mark var_mark, fmls_mark;
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
app* v = vars[i].get();
|
||||
for (app * v : vars) {
|
||||
var_mark.mark(v);
|
||||
if (is_arith(v) && !tids.contains(v)) {
|
||||
rational r;
|
||||
|
@ -332,17 +333,16 @@ namespace qe {
|
|||
tids.insert(v, mbo.add_var(r, a.is_int(v)));
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < fmls.size(); ++i) {
|
||||
fmls_mark.mark(fmls[i].get());
|
||||
for (expr* fml : fmls) {
|
||||
fmls_mark.mark(fml);
|
||||
}
|
||||
obj_map<expr, unsigned>::iterator it = tids.begin(), end = tids.end();
|
||||
ptr_vector<expr> index2expr;
|
||||
for (; it != end; ++it) {
|
||||
expr* e = it->m_key;
|
||||
for (auto& kv : tids) {
|
||||
expr* e = kv.m_key;
|
||||
if (!var_mark.is_marked(e)) {
|
||||
mark_rec(fmls_mark, e);
|
||||
}
|
||||
index2expr.setx(it->m_value, e, 0);
|
||||
index2expr.setx(kv.m_value, e, 0);
|
||||
}
|
||||
j = 0;
|
||||
unsigned_vector real_vars;
|
||||
|
@ -360,8 +360,7 @@ namespace qe {
|
|||
}
|
||||
vars.resize(j);
|
||||
TRACE("qe", tout << "remaining vars: " << vars << "\n";
|
||||
for (unsigned i = 0; i < real_vars.size(); ++i) {
|
||||
unsigned v = real_vars[i];
|
||||
for (unsigned v : real_vars) {
|
||||
tout << "v" << v << " " << mk_pp(index2expr[v], m) << "\n";
|
||||
}
|
||||
mbo.display(tout););
|
||||
|
@ -449,8 +448,8 @@ namespace qe {
|
|||
|
||||
// extract linear constraints
|
||||
|
||||
for (unsigned i = 0; i < fmls.size(); ++i) {
|
||||
linearize(mbo, eval, fmls[i].get(), fmls, tids);
|
||||
for (expr * fml : fmls) {
|
||||
linearize(mbo, eval, fml, fmls, tids);
|
||||
}
|
||||
|
||||
// find optimal value
|
||||
|
@ -459,11 +458,10 @@ namespace qe {
|
|||
|
||||
// update model to use new values that satisfy optimality
|
||||
ptr_vector<expr> vars;
|
||||
obj_map<expr, unsigned>::iterator it = tids.begin(), end = tids.end();
|
||||
for (; it != end; ++it) {
|
||||
expr* e = it->m_key;
|
||||
for (auto& kv : tids) {
|
||||
expr* e = kv.m_key;
|
||||
if (is_uninterp_const(e)) {
|
||||
unsigned id = it->m_value;
|
||||
unsigned id = kv.m_value;
|
||||
func_decl* f = to_app(e)->get_decl();
|
||||
expr_ref val(a.mk_numeral(mbo.get_value(id), false), m);
|
||||
mdl.register_decl(f, val);
|
||||
|
@ -509,10 +507,9 @@ namespace qe {
|
|||
void extract_coefficients(opt::model_based_opt& mbo, model_evaluator& eval, obj_map<expr, rational> const& ts, obj_map<expr, unsigned>& tids, vars& coeffs) {
|
||||
coeffs.reset();
|
||||
eval.set_model_completion(true);
|
||||
obj_map<expr, rational>::iterator it = ts.begin(), end = ts.end();
|
||||
for (; it != end; ++it) {
|
||||
for (auto& kv : ts) {
|
||||
unsigned id;
|
||||
expr* v = it->m_key;
|
||||
expr* v = kv.m_key;
|
||||
if (!tids.find(v, id)) {
|
||||
rational r;
|
||||
expr_ref val = eval(v);
|
||||
|
@ -520,9 +517,9 @@ namespace qe {
|
|||
id = mbo.add_var(r, a.is_int(v));
|
||||
tids.insert(v, id);
|
||||
}
|
||||
CTRACE("qe", it->m_value.is_zero(), tout << mk_pp(v, m) << " has coefficeint 0\n";);
|
||||
if (!it->m_value.is_zero()) {
|
||||
coeffs.push_back(var(id, it->m_value));
|
||||
CTRACE("qe", kv.m_value.is_zero(), tout << mk_pp(v, m) << " has coefficeint 0\n";);
|
||||
if (!kv.m_value.is_zero()) {
|
||||
coeffs.push_back(var(id, kv.m_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace sat {
|
|||
m_glue("glue"),
|
||||
m_glue_psm("glue_psm"),
|
||||
m_psm_glue("psm_glue") {
|
||||
m_num_parallel = 1;
|
||||
m_num_parallel = 1;
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
|
@ -114,6 +114,7 @@ namespace sat {
|
|||
m_core_minimize = p.core_minimize();
|
||||
m_core_minimize_partial = p.core_minimize_partial();
|
||||
m_dyn_sub_res = p.dyn_sub_res();
|
||||
m_dimacs_display = p.dimacs_display();
|
||||
}
|
||||
|
||||
void config::collect_param_descrs(param_descrs & r) {
|
||||
|
|
|
@ -74,6 +74,7 @@ namespace sat {
|
|||
bool m_core_minimize;
|
||||
bool m_core_minimize_partial;
|
||||
|
||||
bool m_dimacs_display;
|
||||
|
||||
symbol m_always_true;
|
||||
symbol m_always_false;
|
||||
|
|
|
@ -23,4 +23,5 @@ def_module_params('sat',
|
|||
('core.minimize', BOOL, False, 'minimize computed core'),
|
||||
('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'),
|
||||
('parallel_threads', UINT, 1, 'number of parallel threads to use'),
|
||||
('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks')))
|
||||
('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks'),
|
||||
('dimacs.display', BOOL, False, 'display SAT instance in DIMACS format and return unknown instead of solving')))
|
||||
|
|
|
@ -1311,7 +1311,6 @@ namespace sat {
|
|||
clause_use_list & neg_occs = m_use_list.get(neg_l);
|
||||
unsigned num_pos = pos_occs.size() + num_bin_pos;
|
||||
unsigned num_neg = neg_occs.size() + num_bin_neg;
|
||||
m_elim_counter -= num_pos + num_neg;
|
||||
|
||||
TRACE("resolution", tout << v << " num_pos: " << num_pos << " neg_pos: " << num_neg << "\n";);
|
||||
|
||||
|
@ -1352,8 +1351,6 @@ namespace sat {
|
|||
collect_clauses(pos_l, m_pos_cls);
|
||||
collect_clauses(neg_l, m_neg_cls);
|
||||
|
||||
m_elim_counter -= num_pos * num_neg + before_lits;
|
||||
|
||||
TRACE("resolution_detail", tout << "collecting number of after_clauses\n";);
|
||||
unsigned before_clauses = num_pos + num_neg;
|
||||
unsigned after_clauses = 0;
|
||||
|
@ -1376,7 +1373,7 @@ namespace sat {
|
|||
}
|
||||
}
|
||||
TRACE("resolution", tout << "found var to eliminate, before: " << before_clauses << " after: " << after_clauses << "\n";);
|
||||
|
||||
m_elim_counter -= num_pos * num_neg + before_lits;
|
||||
|
||||
// eliminate variable
|
||||
model_converter::entry & mc_entry = s.m_mc.mk(model_converter::ELIM_VAR, v);
|
||||
|
|
|
@ -724,6 +724,13 @@ namespace sat {
|
|||
pop_to_base_level();
|
||||
IF_VERBOSE(2, verbose_stream() << "(sat.sat-solver)\n";);
|
||||
SASSERT(scope_lvl() == 0);
|
||||
if (m_config.m_dimacs_display) {
|
||||
display_dimacs(std::cout);
|
||||
for (unsigned i = 0; i < num_lits; ++i) {
|
||||
std::cout << dimacs_lit(lits[i]) << " 0\n";
|
||||
}
|
||||
return l_undef;
|
||||
}
|
||||
if (m_config.m_num_parallel > 1 && !m_par) {
|
||||
return check_par(num_lits, lits);
|
||||
}
|
||||
|
@ -1242,10 +1249,7 @@ namespace sat {
|
|||
}
|
||||
|
||||
void solver::sort_watch_lits() {
|
||||
vector<watch_list>::iterator it = m_watches.begin();
|
||||
vector<watch_list>::iterator end = m_watches.end();
|
||||
for (; it != end; ++it) {
|
||||
watch_list & wlist = *it;
|
||||
for (watch_list & wlist : m_watches) {
|
||||
std::stable_sort(wlist.begin(), wlist.end(), watched_lt());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,6 @@ public:
|
|||
|
||||
virtual void set_progress_callback(progress_callback * callback) {}
|
||||
|
||||
|
||||
void display_weighted(std::ostream& out, unsigned sz, expr * const * assumptions, unsigned const* weights) {
|
||||
if (weights != 0) {
|
||||
for (unsigned i = 0; i < sz; ++i) m_weights.push_back(weights[i]);
|
||||
|
@ -163,6 +162,11 @@ public:
|
|||
if (r != l_true) return r;
|
||||
|
||||
r = m_solver.check(m_asms.size(), m_asms.c_ptr());
|
||||
if (r == l_undef && m_solver.get_config().m_dimacs_display) {
|
||||
for (auto const& kv : m_map) {
|
||||
std::cout << "c " << kv.m_value << " " << mk_pp(kv.m_key, m) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
switch (r) {
|
||||
case l_true:
|
||||
|
@ -644,14 +648,12 @@ private:
|
|||
}
|
||||
sat::model const & ll_m = m_solver.get_model();
|
||||
model_ref md = alloc(model, m);
|
||||
atom2bool_var::iterator it = m_map.begin();
|
||||
atom2bool_var::iterator end = m_map.end();
|
||||
for (; it != end; ++it) {
|
||||
expr * n = it->m_key;
|
||||
for (auto const& kv : m_map) {
|
||||
expr * n = kv.m_key;
|
||||
if (is_app(n) && to_app(n)->get_num_args() > 0) {
|
||||
continue;
|
||||
}
|
||||
sat::bool_var v = it->m_value;
|
||||
sat::bool_var v = kv.m_value;
|
||||
switch (sat::value_at(v, ll_m)) {
|
||||
case l_true:
|
||||
md->register_decl(to_app(n)->get_decl(), m.mk_true());
|
||||
|
|
|
@ -109,10 +109,10 @@ namespace sat {
|
|||
bool operator!=(watched const & w) const { return !operator==(w); }
|
||||
};
|
||||
|
||||
COMPILE_TIME_ASSERT(0 <= watched::BINARY && watched::BINARY <= 3);
|
||||
COMPILE_TIME_ASSERT(0 <= watched::TERNARY && watched::TERNARY <= 3);
|
||||
COMPILE_TIME_ASSERT(0 <= watched::CLAUSE && watched::CLAUSE <= 3);
|
||||
COMPILE_TIME_ASSERT(0 <= watched::EXT_CONSTRAINT && watched::EXT_CONSTRAINT <= 3);
|
||||
static_assert(0 <= watched::BINARY && watched::BINARY <= 3, "");
|
||||
static_assert(0 <= watched::TERNARY && watched::TERNARY <= 3, "");
|
||||
static_assert(0 <= watched::CLAUSE && watched::CLAUSE <= 3, "");
|
||||
static_assert(0 <= watched::EXT_CONSTRAINT && watched::EXT_CONSTRAINT <= 3, "");
|
||||
|
||||
struct watched_lt {
|
||||
bool operator()(watched const & w1, watched const & w2) const {
|
||||
|
|
|
@ -16,11 +16,11 @@ Author:
|
|||
Notes:
|
||||
|
||||
--*/
|
||||
#include "ast/ast_pp.h"
|
||||
#include "tactic/tactical.h"
|
||||
#include "tactic/filter_model_converter.h"
|
||||
#include "sat/tactic/goal2sat.h"
|
||||
#include "sat/sat_solver.h"
|
||||
#include "tactic/filter_model_converter.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "model/model_v2_pp.h"
|
||||
|
||||
class sat_tactic : public tactic {
|
||||
|
@ -56,11 +56,9 @@ class sat_tactic : public tactic {
|
|||
sat::literal_vector assumptions;
|
||||
m_goal2sat(*g, m_params, m_solver, map, dep2asm);
|
||||
TRACE("sat_solver_unknown", tout << "interpreted_atoms: " << map.interpreted_atoms() << "\n";
|
||||
atom2bool_var::iterator it = map.begin();
|
||||
atom2bool_var::iterator end = map.end();
|
||||
for (; it != end; ++it) {
|
||||
if (!is_uninterp_const(it->m_key))
|
||||
tout << mk_ismt2_pp(it->m_key, m) << "\n";
|
||||
for (auto const& kv : map) {
|
||||
if (!is_uninterp_const(kv.m_key))
|
||||
tout << mk_ismt2_pp(kv.m_key, m) << "\n";
|
||||
});
|
||||
g->reset();
|
||||
g->m().compact_memory();
|
||||
|
@ -70,6 +68,11 @@ class sat_tactic : public tactic {
|
|||
TRACE("sat_dimacs", m_solver.display_dimacs(tout););
|
||||
dep2assumptions(dep2asm, assumptions);
|
||||
lbool r = m_solver.check(assumptions.size(), assumptions.c_ptr());
|
||||
if (r == l_undef && m_solver.get_config().m_dimacs_display) {
|
||||
for (auto const& kv : map) {
|
||||
std::cout << "c " << kv.m_value << " " << mk_pp(kv.m_key, g->m()) << "\n";
|
||||
}
|
||||
}
|
||||
if (r == l_false) {
|
||||
expr_dependency * lcore = 0;
|
||||
if (produce_core) {
|
||||
|
@ -90,11 +93,9 @@ class sat_tactic : public tactic {
|
|||
model_ref md = alloc(model, m);
|
||||
sat::model const & ll_m = m_solver.get_model();
|
||||
TRACE("sat_tactic", for (unsigned i = 0; i < ll_m.size(); i++) tout << i << ":" << ll_m[i] << " "; tout << "\n";);
|
||||
atom2bool_var::iterator it = map.begin();
|
||||
atom2bool_var::iterator end = map.end();
|
||||
for (; it != end; ++it) {
|
||||
expr * n = it->m_key;
|
||||
sat::bool_var v = it->m_value;
|
||||
for (auto const& kv : map) {
|
||||
expr * n = kv.m_key;
|
||||
sat::bool_var v = kv.m_value;
|
||||
TRACE("sat_tactic", tout << "extracting value of " << mk_ismt2_pp(n, m) << "\nvar: " << v << "\n";);
|
||||
switch (sat::value_at(v, ll_m)) {
|
||||
case l_true:
|
||||
|
@ -126,17 +127,15 @@ class sat_tactic : public tactic {
|
|||
|
||||
void dep2assumptions(obj_map<expr, sat::literal>& dep2asm,
|
||||
sat::literal_vector& assumptions) {
|
||||
obj_map<expr, sat::literal>::iterator it = dep2asm.begin(), end = dep2asm.end();
|
||||
for (; it != end; ++it) {
|
||||
assumptions.push_back(it->m_value);
|
||||
for (auto const& kv : dep2asm) {
|
||||
assumptions.push_back(kv.m_value);
|
||||
}
|
||||
}
|
||||
|
||||
void mk_asm2dep(obj_map<expr, sat::literal>& dep2asm,
|
||||
u_map<expr*>& lit2asm) {
|
||||
obj_map<expr, sat::literal>::iterator it = dep2asm.begin(), end = dep2asm.end();
|
||||
for (; it != end; ++it) {
|
||||
lit2asm.insert(it->m_value.index(), it->m_key);
|
||||
for (auto const& kv : dep2asm) {
|
||||
lit2asm.insert(kv.m_value.index(), kv.m_key);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -38,7 +38,7 @@ asserted_formulas::asserted_formulas(ast_manager & m, smt_params & p):
|
|||
m_qhead(0),
|
||||
m_macro_manager(m),
|
||||
m_bv_sharing(m),
|
||||
m_inconsistent(false),
|
||||
m_inconsistent(false),
|
||||
m_has_quantifiers(false),
|
||||
m_reduce_asserted_formulas(*this),
|
||||
m_distribute_forall(*this),
|
||||
|
@ -54,8 +54,8 @@ asserted_formulas::asserted_formulas(ast_manager & m, smt_params & p):
|
|||
m_lift_ite(*this),
|
||||
m_ng_lift_ite(*this),
|
||||
m_find_macros(*this),
|
||||
m_propagate_values(*this),
|
||||
m_nnf_cnf(*this),
|
||||
m_propagate_values(*this),
|
||||
m_nnf_cnf(*this),
|
||||
m_apply_quasi_macros(*this) {
|
||||
|
||||
m_macro_finder = alloc(macro_finder, m, m_macro_manager);
|
||||
|
@ -68,7 +68,7 @@ asserted_formulas::asserted_formulas(ast_manager & m, smt_params & p):
|
|||
void asserted_formulas::setup() {
|
||||
switch (m_params.m_lift_ite) {
|
||||
case LI_FULL:
|
||||
m_params.m_ng_lift_ite = LI_NONE;
|
||||
m_params.m_ng_lift_ite = LI_NONE;
|
||||
break;
|
||||
case LI_CONSERVATIVE:
|
||||
if (m_params.m_ng_lift_ite == LI_CONSERVATIVE)
|
||||
|
@ -77,7 +77,7 @@ void asserted_formulas::setup() {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (m_params.m_relevancy_lvl == 0)
|
||||
m_params.m_relevancy_lemma = false;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ void asserted_formulas::push_assertion(expr * e, proof * pr, vector<justified_ex
|
|||
expr* e1 = 0;
|
||||
if (m.is_false(e)) {
|
||||
result.push_back(justified_expr(m, e, pr));
|
||||
m_inconsistent = true;
|
||||
m_inconsistent = true;
|
||||
}
|
||||
else if (m.is_true(e)) {
|
||||
// skip
|
||||
|
@ -110,8 +110,8 @@ void asserted_formulas::push_assertion(expr * e, proof * pr, vector<justified_ex
|
|||
expr* arg = to_app(e1)->get_arg(i);
|
||||
proof_ref _pr(m.mk_not_or_elim(pr, i), m);
|
||||
expr_ref narg(mk_not(m, arg), m);
|
||||
push_assertion(narg, _pr, result);
|
||||
}
|
||||
push_assertion(narg, _pr, result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.push_back(justified_expr(m, e, pr));
|
||||
|
@ -130,6 +130,7 @@ void asserted_formulas::set_eliminate_and(bool flag) {
|
|||
p.set_bool("eq2ineq", m_params.m_arith_eq2ineq);
|
||||
p.set_bool("gcd_rounding", true);
|
||||
p.set_bool("expand_select_store", true);
|
||||
p.set_bool("bv_sort_ac", true);
|
||||
m_rewriter.updt_params(p);
|
||||
flush_cache();
|
||||
}
|
||||
|
@ -139,11 +140,9 @@ void asserted_formulas::assert_expr(expr * e, proof * _in_pr) {
|
|||
proof_ref in_pr(_in_pr, m), pr(_in_pr, m);
|
||||
expr_ref r(e, m);
|
||||
|
||||
if (inconsistent())
|
||||
if (inconsistent())
|
||||
return;
|
||||
|
||||
m_has_quantifiers |= ::has_quantifiers(e);
|
||||
|
||||
if (m_params.m_preprocess) {
|
||||
TRACE("assert_expr_bug", tout << r << "\n";);
|
||||
set_eliminate_and(false); // do not eliminate and before nnf.
|
||||
|
@ -156,6 +155,9 @@ void asserted_formulas::assert_expr(expr * e, proof * _in_pr) {
|
|||
}
|
||||
TRACE("assert_expr_bug", tout << "after...\n" << r << "\n";);
|
||||
}
|
||||
|
||||
m_has_quantifiers |= ::has_quantifiers(e);
|
||||
|
||||
push_assertion(r, pr, m_formulas);
|
||||
TRACE("asserted_formulas_bug", tout << "after assert_expr\n"; display(tout););
|
||||
}
|
||||
|
@ -170,7 +172,7 @@ void asserted_formulas::get_assertions(ptr_vector<expr> & result) const {
|
|||
|
||||
void asserted_formulas::push_scope() {
|
||||
SASSERT(inconsistent() || m_qhead == m_formulas.size() || m.canceled());
|
||||
TRACE("asserted_formulas_scopes", tout << "push:\n"; display(tout););
|
||||
TRACE("asserted_formulas_scopes", tout << "before push: " << m_scopes.size() << "\n";);
|
||||
m_scoped_substitution.push();
|
||||
m_scopes.push_back(scope());
|
||||
scope & s = m_scopes.back();
|
||||
|
@ -181,10 +183,11 @@ void asserted_formulas::push_scope() {
|
|||
m_bv_sharing.push_scope();
|
||||
m_macro_manager.push_scope();
|
||||
commit();
|
||||
TRACE("asserted_formulas_scopes", tout << "after push: " << m_scopes.size() << "\n";);
|
||||
}
|
||||
|
||||
|
||||
void asserted_formulas::pop_scope(unsigned num_scopes) {
|
||||
TRACE("asserted_formulas_scopes", tout << "before pop " << num_scopes << "\n"; display(tout););
|
||||
TRACE("asserted_formulas_scopes", tout << "before pop " << num_scopes << " of " << m_scopes.size() << "\n";);
|
||||
m_bv_sharing.pop_scope(num_scopes);
|
||||
m_macro_manager.pop_scope(num_scopes);
|
||||
unsigned new_lvl = m_scopes.size() - num_scopes;
|
||||
|
@ -196,7 +199,7 @@ void asserted_formulas::pop_scope(unsigned num_scopes) {
|
|||
m_qhead = s.m_formulas_lim;
|
||||
m_scopes.shrink(new_lvl);
|
||||
flush_cache();
|
||||
TRACE("asserted_formulas_scopes", tout << "after pop " << num_scopes << "\n"; display(tout););
|
||||
TRACE("asserted_formulas_scopes", tout << "after pop " << num_scopes << "\n";);
|
||||
}
|
||||
|
||||
void asserted_formulas::reset() {
|
||||
|
@ -211,7 +214,7 @@ void asserted_formulas::reset() {
|
|||
|
||||
bool asserted_formulas::check_well_sorted() const {
|
||||
for (justified_expr const& je : m_formulas) {
|
||||
if (!is_well_sorted(m, je.get_fml())) return false;
|
||||
if (!is_well_sorted(m, je.get_fml())) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -223,20 +226,20 @@ void asserted_formulas::reduce() {
|
|||
return;
|
||||
if (m_qhead == m_formulas.size())
|
||||
return;
|
||||
if (!m_params.m_preprocess)
|
||||
return;
|
||||
if (m_macro_manager.has_macros())
|
||||
if (!m_params.m_preprocess)
|
||||
return;
|
||||
if (m_macro_manager.has_macros())
|
||||
invoke(m_find_macros);
|
||||
|
||||
|
||||
TRACE("before_reduce", display(tout););
|
||||
CASSERT("well_sorted", check_well_sorted());
|
||||
|
||||
|
||||
set_eliminate_and(false); // do not eliminate and before nnf.
|
||||
if (!invoke(m_propagate_values)) return;
|
||||
if (!invoke(m_find_macros)) return;
|
||||
if (!invoke(m_nnf_cnf)) return;
|
||||
set_eliminate_and(true);
|
||||
if (!invoke(m_reduce_asserted_formulas)) return;
|
||||
if (!invoke(m_reduce_asserted_formulas)) return;
|
||||
if (!invoke(m_pull_cheap_ite_trees)) return;
|
||||
if (!invoke(m_pull_nested_quantifiers)) return;
|
||||
if (!invoke(m_lift_ite)) return;
|
||||
|
@ -275,14 +278,14 @@ bool asserted_formulas::invoke(simplify_fmls& s) {
|
|||
if (!s.should_apply()) return true;
|
||||
IF_VERBOSE(10, verbose_stream() << "(smt." << s.id() << ")\n";);
|
||||
s();
|
||||
IF_VERBOSE(10000, verbose_stream() << "total size: " << get_total_size() << "\n";);
|
||||
TRACE("reduce_step_ll", ast_mark visited; display_ll(tout, visited););
|
||||
CASSERT("well_sorted",check_well_sorted());
|
||||
if (inconsistent() || canceled()) {
|
||||
TRACE("after_reduce", display(tout););
|
||||
TRACE("after_reduce_ll", ast_mark visited; display_ll(tout, visited););
|
||||
IF_VERBOSE(10000, verbose_stream() << "total size: " << get_total_size() << "\n";);
|
||||
TRACE("reduce_step_ll", ast_mark visited; display_ll(tout, visited););
|
||||
CASSERT("well_sorted",check_well_sorted());
|
||||
if (inconsistent() || canceled()) {
|
||||
TRACE("after_reduce", display(tout););
|
||||
TRACE("after_reduce_ll", ast_mark visited; display_ll(tout, visited););
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
|
@ -300,10 +303,10 @@ void asserted_formulas::display(std::ostream & out) const {
|
|||
|
||||
void asserted_formulas::display_ll(std::ostream & out, ast_mark & pp_visited) const {
|
||||
if (!m_formulas.empty()) {
|
||||
for (justified_expr const& f : m_formulas)
|
||||
for (justified_expr const& f : m_formulas)
|
||||
ast_def_ll_pp(out, m, f.get_fml(), pp_visited, true, false);
|
||||
out << "asserted formulas:\n";
|
||||
for (justified_expr const& f : m_formulas)
|
||||
for (justified_expr const& f : m_formulas)
|
||||
out << "#" << f.get_fml()->get_id() << " ";
|
||||
out << "\n";
|
||||
}
|
||||
|
@ -331,9 +334,9 @@ void asserted_formulas::find_macros_core() {
|
|||
void asserted_formulas::apply_quasi_macros() {
|
||||
TRACE("before_quasi_macros", display(tout););
|
||||
vector<justified_expr> new_fmls;
|
||||
quasi_macros proc(m, m_macro_manager);
|
||||
while (proc(m_formulas.size() - m_qhead,
|
||||
m_formulas.c_ptr() + m_qhead,
|
||||
quasi_macros proc(m, m_macro_manager);
|
||||
while (proc(m_formulas.size() - m_qhead,
|
||||
m_formulas.c_ptr() + m_qhead,
|
||||
new_fmls)) {
|
||||
swap_asserted_formulas(new_fmls);
|
||||
new_fmls.reset();
|
||||
|
@ -347,7 +350,7 @@ void asserted_formulas::nnf_cnf() {
|
|||
vector<justified_expr> new_fmls;
|
||||
expr_ref_vector push_todo(m);
|
||||
proof_ref_vector push_todo_prs(m);
|
||||
|
||||
|
||||
unsigned i = m_qhead;
|
||||
unsigned sz = m_formulas.size();
|
||||
TRACE("nnf_bug", tout << "i: " << i << " sz: " << sz << "\n";);
|
||||
|
@ -377,7 +380,7 @@ void asserted_formulas::nnf_cnf() {
|
|||
CASSERT("well_sorted",is_well_sorted(m, r1));
|
||||
if (canceled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (m.proofs_enabled())
|
||||
pr = m.mk_modus_ponens(push_todo_prs.get(k), pr1);
|
||||
push_assertion(r1, pr, new_fmls);
|
||||
|
@ -388,8 +391,8 @@ void asserted_formulas::nnf_cnf() {
|
|||
|
||||
void asserted_formulas::simplify_fmls::operator()() {
|
||||
vector<justified_expr> new_fmls;
|
||||
unsigned sz = af.m_formulas.size();
|
||||
for (unsigned i = af.m_qhead; i < sz; i++) {
|
||||
unsigned sz = af.m_formulas.size();
|
||||
for (unsigned i = af.m_qhead; i < sz; i++) {
|
||||
auto& j = af.m_formulas[i];
|
||||
expr_ref result(m);
|
||||
proof_ref result_pr(m);
|
||||
|
@ -405,8 +408,8 @@ void asserted_formulas::simplify_fmls::operator()() {
|
|||
af.push_assertion(result, result_pr, new_fmls);
|
||||
}
|
||||
if (af.canceled()) return;
|
||||
}
|
||||
af.swap_asserted_formulas(new_fmls);
|
||||
}
|
||||
af.swap_asserted_formulas(new_fmls);
|
||||
TRACE("asserted_formulas", af.display(tout););
|
||||
post_op();
|
||||
}
|
||||
|
@ -472,12 +475,12 @@ void asserted_formulas::propagate_values() {
|
|||
|
||||
unsigned asserted_formulas::propagate_values(unsigned i) {
|
||||
expr_ref n(m_formulas[i].get_fml(), m);
|
||||
expr_ref new_n(m);
|
||||
proof_ref new_pr(m);
|
||||
m_rewriter(n, new_n, new_pr);
|
||||
if (m.proofs_enabled()) {
|
||||
expr_ref new_n(m);
|
||||
proof_ref new_pr(m);
|
||||
m_rewriter(n, new_n, new_pr);
|
||||
if (m.proofs_enabled()) {
|
||||
proof * pr = m_formulas[i].get_proof();
|
||||
new_pr = m.mk_modus_ponens(pr, new_pr);
|
||||
new_pr = m.mk_modus_ponens(pr, new_pr);
|
||||
}
|
||||
justified_expr j(m, new_n, new_pr);
|
||||
m_formulas[i] = j;
|
||||
|
@ -509,10 +512,10 @@ void asserted_formulas::update_substitution(expr* n, proof* pr) {
|
|||
TRACE("propagate_values", tout << "incompatible " << mk_pp(n, m) << "\n";);
|
||||
}
|
||||
if (m.is_not(n, n1)) {
|
||||
m_scoped_substitution.insert(n1, m.mk_false(), m.mk_iff_false(pr));
|
||||
m_scoped_substitution.insert(n1, m.mk_false(), m.mk_iff_false(pr));
|
||||
}
|
||||
else {
|
||||
m_scoped_substitution.insert(n, m.mk_true(), m.mk_iff_true(pr));
|
||||
m_scoped_substitution.insert(n, m.mk_true(), m.mk_iff_true(pr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,13 +556,13 @@ bool asserted_formulas::is_gt(expr* lhs, expr* rhs) {
|
|||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void asserted_formulas::compute_depth(expr* e) {
|
||||
ptr_vector<expr> todo;
|
||||
todo.push_back(e);
|
||||
todo.push_back(e);
|
||||
while (!todo.empty()) {
|
||||
e = todo.back();
|
||||
unsigned d = 0;
|
||||
|
@ -602,7 +605,7 @@ proof * asserted_formulas::get_inconsistency_proof() const {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void asserted_formulas::refine_inj_axiom_fn::simplify(justified_expr const& j, expr_ref& n, proof_ref& p) {
|
||||
void asserted_formulas::refine_inj_axiom_fn::simplify(justified_expr const& j, expr_ref& n, proof_ref& p) {
|
||||
expr* f = j.get_fml();
|
||||
if (is_quantifier(f) && simplify_inj_axiom(m, to_quantifier(f), n)) {
|
||||
TRACE("inj_axiom", tout << "simplifying...\n" << mk_pp(f, m) << "\n" << n << "\n";);
|
||||
|
|
|
@ -1753,10 +1753,6 @@ namespace smt {
|
|||
m_use_filters(use_filters) {
|
||||
}
|
||||
|
||||
context & get_context() {
|
||||
return m_context;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create a new code tree for the given quantifier.
|
||||
|
||||
|
@ -2003,7 +1999,7 @@ namespace smt {
|
|||
m_ast_manager(ctx.get_manager()),
|
||||
m_mam(m),
|
||||
m_use_filters(use_filters) {
|
||||
m_args.resize(INIT_ARGS_SIZE, 0);
|
||||
m_args.resize(INIT_ARGS_SIZE);
|
||||
}
|
||||
|
||||
~interpreter() {
|
||||
|
@ -2020,26 +2016,20 @@ namespace smt {
|
|||
void execute(code_tree * t) {
|
||||
TRACE("trigger_bug", tout << "execute for code tree:\n"; t->display(tout););
|
||||
init(t);
|
||||
enode_vector::const_iterator it = t->get_candidates().begin();
|
||||
enode_vector::const_iterator end = t->get_candidates().end();
|
||||
if (t->filter_candidates()) {
|
||||
for (; it != end; ++it) {
|
||||
enode * app = *it;
|
||||
for (enode * app : t->get_candidates()) {
|
||||
if (!app->is_marked() && app->is_cgr()) {
|
||||
execute_core(t, app);
|
||||
app->set_mark();
|
||||
}
|
||||
}
|
||||
it = t->get_candidates().begin();
|
||||
for (; it != end; ++it) {
|
||||
enode * app = *it;
|
||||
for (enode * app : t->get_candidates()) {
|
||||
if (app->is_marked())
|
||||
app->unset_mark();
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (; it != end; ++it) {
|
||||
enode * app = *it;
|
||||
for (enode * app : t->get_candidates()) {
|
||||
TRACE("trigger_bug", tout << "candidate\n" << mk_ismt2_pp(app->get_owner(), m_ast_manager) << "\n";);
|
||||
if (app->is_cgr()) {
|
||||
TRACE("trigger_bug", tout << "is_cgr\n";);
|
||||
|
@ -2825,15 +2815,13 @@ namespace smt {
|
|||
} // end of execute_core
|
||||
|
||||
void display_trees(std::ostream & out, const ptr_vector<code_tree> & trees) {
|
||||
ptr_vector<code_tree>::const_iterator it = trees.begin();
|
||||
ptr_vector<code_tree>::const_iterator end = trees.end();
|
||||
unsigned lbl = 0;
|
||||
for (; it != end; ++it, ++lbl) {
|
||||
code_tree * tree = *it;
|
||||
for (code_tree* tree : trees) {
|
||||
if (tree) {
|
||||
out << "tree for f" << lbl << "\n";
|
||||
out << *tree;
|
||||
}
|
||||
++lbl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -148,11 +148,8 @@ namespace smt {
|
|||
}
|
||||
|
||||
void qi_queue::instantiate() {
|
||||
svector<entry>::iterator it = m_new_entries.begin();
|
||||
svector<entry>::iterator end = m_new_entries.end();
|
||||
unsigned since_last_check = 0;
|
||||
for (; it != end; ++it) {
|
||||
entry & curr = *it;
|
||||
for (entry & curr : m_new_entries) {
|
||||
fingerprint * f = curr.m_qb;
|
||||
quantifier * qa = static_cast<quantifier*>(f->get_data());
|
||||
|
||||
|
|
|
@ -487,6 +487,7 @@ namespace smt {
|
|||
*/
|
||||
void context::add_eq(enode * n1, enode * n2, eq_justification js) {
|
||||
unsigned old_trail_size = m_trail_stack.size();
|
||||
scoped_suspend_rlimit _suspend_cancel(m_manager.limit());
|
||||
|
||||
try {
|
||||
TRACE("add_eq", tout << "assigning: #" << n1->get_owner_id() << " = #" << n2->get_owner_id() << "\n";);
|
||||
|
@ -541,10 +542,14 @@ namespace smt {
|
|||
mark_as_relevant(r1);
|
||||
}
|
||||
|
||||
TRACE("add_eq", tout << "to trail\n";);
|
||||
|
||||
push_trail(add_eq_trail(r1, n1, r2->get_num_parents()));
|
||||
|
||||
TRACE("add_eq", tout << "qmanager add_eq\n";);
|
||||
m_qmanager->add_eq_eh(r1, r2);
|
||||
|
||||
TRACE("add_eq", tout << "merge theory_vars\n";);
|
||||
merge_theory_vars(n2, n1, js);
|
||||
|
||||
// 'Proof' tree
|
||||
|
@ -577,6 +582,7 @@ namespace smt {
|
|||
#endif
|
||||
|
||||
|
||||
TRACE("add_eq", tout << "remove_parents_from_cg_table\n";);
|
||||
remove_parents_from_cg_table(r1);
|
||||
|
||||
enode * curr = r1;
|
||||
|
@ -588,8 +594,10 @@ namespace smt {
|
|||
|
||||
SASSERT(r1->get_root() == r2);
|
||||
|
||||
TRACE("add_eq", tout << "reinsert_parents_into_cg_table\n";);
|
||||
reinsert_parents_into_cg_table(r1, r2, n1, n2, js);
|
||||
|
||||
TRACE("add_eq", tout << "propagate_bool_enode_assignment\n";);
|
||||
if (n2->is_bool())
|
||||
propagate_bool_enode_assignment(r1, r2, n1, n2);
|
||||
|
||||
|
@ -604,6 +612,7 @@ namespace smt {
|
|||
catch (...) {
|
||||
// Restore trail size since procedure was interrupted in the middle.
|
||||
// If the add_eq_trail remains on the trail stack, then Z3 may crash when the destructor is invoked.
|
||||
TRACE("add_eq", tout << "add_eq interrupted. This is unsafe " << m_manager.limit().get_cancel_flag() << "\n";);
|
||||
m_trail_stack.shrink(old_trail_size);
|
||||
throw;
|
||||
}
|
||||
|
@ -972,7 +981,7 @@ namespace smt {
|
|||
enode * parent = *it;
|
||||
if (parent->is_cgc_enabled()) {
|
||||
TRACE("add_eq_parents", tout << "removing: #" << parent->get_owner_id() << "\n";);
|
||||
CTRACE("add_eq", !parent->is_cgr(),
|
||||
CTRACE("add_eq", !parent->is_cgr() || !m_cg_table.contains_ptr(parent),
|
||||
tout << "old num_parents: " << r2_num_parents << ", num_parents: " << r2->m_parents.size() << ", parent: #" <<
|
||||
parent->get_owner_id() << ", parents: \n";
|
||||
for (unsigned i = 0; i < r2->m_parents.size(); i++) {
|
||||
|
@ -1277,7 +1286,7 @@ namespace smt {
|
|||
else {
|
||||
if (depth >= m_almost_cg_tables.size()) {
|
||||
unsigned old_sz = m_almost_cg_tables.size();
|
||||
m_almost_cg_tables.resize(depth+1, 0);
|
||||
m_almost_cg_tables.resize(depth+1);
|
||||
for (unsigned i = old_sz; i < depth + 1; i++)
|
||||
m_almost_cg_tables[i] = alloc(almost_cg_table);
|
||||
}
|
||||
|
@ -4374,9 +4383,17 @@ namespace smt {
|
|||
expr* fn = to_app(q->get_pattern(0))->get_arg(0);
|
||||
expr* body = to_app(q->get_pattern(1))->get_arg(0);
|
||||
SASSERT(is_app(fn));
|
||||
// reverse argument order so that variable 0 starts at the beginning.
|
||||
expr_ref_vector subst(m);
|
||||
for (expr* arg : *to_app(fn)) {
|
||||
subst.push_back(arg);
|
||||
}
|
||||
expr_ref bodyr(m);
|
||||
var_subst sub(m, false);
|
||||
sub(body, subst.size(), subst.c_ptr(), bodyr);
|
||||
func_decl* f = to_app(fn)->get_decl();
|
||||
func_interp* fi = alloc(func_interp, m, f->get_arity());
|
||||
fi->set_else(body);
|
||||
fi->set_else(bodyr);
|
||||
m_model->register_decl(f, fi);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -284,7 +284,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
lbool reduce_cond(model_ref& model, expr* e) {
|
||||
expr* e1, *e2;
|
||||
expr* e1 = 0, *e2 = 0;
|
||||
if (m.is_eq(e, e1, e2) && m_array_util.is_as_array(e1) && m_array_util.is_as_array(e2)) {
|
||||
if (e1 == e2) {
|
||||
return l_true;
|
||||
|
|
|
@ -198,19 +198,19 @@ namespace smt {
|
|||
if (get_depth(n) > DEEP_EXPR_THRESHOLD) {
|
||||
// if the expression is deep, then execute topological sort to avoid
|
||||
// stack overflow.
|
||||
// a caveat is that theory internalizers do rely on recursive descent so
|
||||
// internalization over these follows top-down
|
||||
TRACE("deep_internalize", tout << "expression is deep: #" << n->get_id() << "\n" << mk_ll_pp(n, m_manager););
|
||||
svector<expr_bool_pair> sorted_exprs;
|
||||
top_sort_expr(n, sorted_exprs);
|
||||
TRACE("deep_internalize",
|
||||
svector<expr_bool_pair>::const_iterator it = sorted_exprs.begin();
|
||||
svector<expr_bool_pair>::const_iterator end = sorted_exprs.end();
|
||||
for (; it != end; ++it) {
|
||||
tout << "#" << it->first->get_id() << " " << it->second << "\n";
|
||||
});
|
||||
svector<expr_bool_pair>::const_iterator it = sorted_exprs.begin();
|
||||
svector<expr_bool_pair>::const_iterator end = sorted_exprs.end();
|
||||
for (; it != end; ++it)
|
||||
internalize(it->first, it->second);
|
||||
TRACE("deep_internalize", for (auto & kv : sorted_exprs) tout << "#" << kv.first->get_id() << " " << kv.second << "\n"; );
|
||||
for (auto & kv : sorted_exprs) {
|
||||
expr* e = kv.first;
|
||||
if (!is_app(e) ||
|
||||
to_app(e)->get_family_id() == null_family_id ||
|
||||
to_app(e)->get_family_id() == m_manager.get_basic_family_id())
|
||||
internalize(e, kv.second);
|
||||
}
|
||||
}
|
||||
SASSERT(m_manager.is_bool(n));
|
||||
if (is_gate(m_manager, n)) {
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace smt {
|
|||
ptr_vector<theory>::const_iterator it = m_context->begin_theories();
|
||||
ptr_vector<theory>::const_iterator end = m_context->end_theories();
|
||||
for (; it != end; ++it) {
|
||||
TRACE("model_generator_bug", tout << "init_model for theory: " << (*it)->get_name() << "\n";);
|
||||
TRACE("model", tout << "init_model for theory: " << (*it)->get_name() << "\n";);
|
||||
(*it)->init_model(*this);
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ namespace smt {
|
|||
sort * s = m_manager.get_sort(r->get_owner());
|
||||
model_value_proc * proc = 0;
|
||||
if (m_manager.is_bool(s)) {
|
||||
CTRACE("func_interp_bug", m_context->get_assignment(r) == l_undef,
|
||||
CTRACE("model", m_context->get_assignment(r) == l_undef,
|
||||
tout << mk_pp(r->get_owner(), m_manager) << "\n";);
|
||||
SASSERT(m_context->get_assignment(r) != l_undef);
|
||||
if (m_context->get_assignment(r) == l_true)
|
||||
|
@ -108,7 +108,7 @@ namespace smt {
|
|||
SASSERT(proc);
|
||||
}
|
||||
else {
|
||||
TRACE("model_bug", tout << "creating fresh value for #" << r->get_owner_id() << "\n";);
|
||||
TRACE("model", tout << "creating fresh value for #" << r->get_owner_id() << "\n";);
|
||||
proc = alloc(fresh_value_proc, mk_extra_fresh_value(m_manager.get_sort(r->get_owner())));
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ namespace smt {
|
|||
if (!m_manager.is_model_value(n)) {
|
||||
sort * s = m_manager.get_sort(r->get_owner());
|
||||
n = m_model->get_fresh_value(s);
|
||||
CTRACE("model_generator_bug", n == 0,
|
||||
CTRACE("model", n == 0,
|
||||
tout << mk_pp(r->get_owner(), m_manager) << "\nsort:\n" << mk_pp(s, m_manager) << "\n";
|
||||
tout << "is_finite: " << m_model->is_finite(s) << "\n";);
|
||||
}
|
||||
|
@ -406,9 +406,11 @@ namespace smt {
|
|||
*/
|
||||
bool model_generator::include_func_interp(func_decl * f) const {
|
||||
family_id fid = f->get_family_id();
|
||||
TRACE("model", tout << f->get_name() << " " << fid << "\n";);
|
||||
if (fid == null_family_id) return !m_hidden_ufs.contains(f);
|
||||
if (fid == m_manager.get_basic_family_id()) return false;
|
||||
theory * th = m_context->get_theory(fid);
|
||||
TRACE("model", tout << th << "\n";);
|
||||
if (!th) return true;
|
||||
return th->include_func_interp(f);
|
||||
}
|
||||
|
@ -443,7 +445,7 @@ namespace smt {
|
|||
SASSERT(m_model->has_interpretation(f));
|
||||
SASSERT(m_model->get_func_interp(f) == fi);
|
||||
// The entry must be new because n->get_cg() == n
|
||||
TRACE("func_interp_bug",
|
||||
TRACE("model",
|
||||
tout << "insert new entry for:\n" << mk_ismt2_pp(n->get_owner(), m_manager) << "\nargs: ";
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
tout << "#" << n->get_arg(i)->get_owner_id() << " ";
|
||||
|
@ -507,20 +509,20 @@ namespace smt {
|
|||
|
||||
void model_generator::register_macros() {
|
||||
unsigned num = m_context->get_num_macros();
|
||||
TRACE("register_macros", tout << "num. macros: " << num << "\n";);
|
||||
TRACE("model", tout << "num. macros: " << num << "\n";);
|
||||
expr_ref v(m_manager);
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
func_decl * f = m_context->get_macro_interpretation(i, v);
|
||||
func_interp * fi = alloc(func_interp, m_manager, f->get_arity());
|
||||
fi->set_else(v);
|
||||
TRACE("register_macros", tout << f->get_name() << "\n" << mk_pp(v, m_manager) << "\n";);
|
||||
TRACE("model", tout << f->get_name() << "\n" << mk_pp(v, m_manager) << "\n";);
|
||||
m_model->register_decl(f, fi);
|
||||
}
|
||||
}
|
||||
|
||||
proto_model * model_generator::mk_model() {
|
||||
SASSERT(!m_model);
|
||||
TRACE("func_interp_bug", m_context->display(tout););
|
||||
TRACE("model", m_context->display(tout););
|
||||
init_model();
|
||||
register_existing_model_values();
|
||||
mk_bool_model();
|
||||
|
|
|
@ -216,6 +216,7 @@ namespace smt {
|
|||
|
||||
void setup::setup_QF_DT() {
|
||||
setup_QF_UF();
|
||||
setup_datatypes();
|
||||
}
|
||||
|
||||
void setup::setup_QF_BVRE() {
|
||||
|
|
|
@ -109,8 +109,10 @@ namespace smt {
|
|||
}
|
||||
|
||||
virtual void assert_expr(expr * t, expr * a) {
|
||||
if (m_name2assertion.contains(a)) {
|
||||
throw default_exception("named assertion defined twice");
|
||||
}
|
||||
solver_na2as::assert_expr(t, a);
|
||||
SASSERT(!m_name2assertion.contains(a));
|
||||
get_manager().inc_ref(t);
|
||||
m_name2assertion.insert(a, t);
|
||||
}
|
||||
|
|
|
@ -67,9 +67,9 @@ namespace smt {
|
|||
};
|
||||
|
||||
// 32 bit machine
|
||||
COMPILE_TIME_ASSERT(sizeof(expr*) != 4 || sizeof(theory_var_list) == sizeof(theory_var_list *) + sizeof(int));
|
||||
static_assert(sizeof(expr*) != 4 || sizeof(theory_var_list) == sizeof(theory_var_list *) + sizeof(int), "32 bit");
|
||||
// 64 bit machine
|
||||
COMPILE_TIME_ASSERT(sizeof(expr*) != 8 || sizeof(theory_var_list) == sizeof(theory_var_list *) + sizeof(int) + /* a structure must be aligned */ sizeof(int));
|
||||
static_assert(sizeof(expr*) != 8 || sizeof(theory_var_list) == sizeof(theory_var_list *) + sizeof(int) + /* a structure must be aligned */ sizeof(int), "64 bit");
|
||||
};
|
||||
|
||||
#endif /* SMT_THEORY_VAR_LIST_H_ */
|
||||
|
|
|
@ -780,7 +780,7 @@ namespace smt {
|
|||
of a non linear monomial that is not satisfied by the current assignment.
|
||||
if v >= l, then create the case split v >= l+1
|
||||
else v <= u, then create the case split v <= u-1
|
||||
else do nothing and return false.
|
||||
else create the bound v = 0 and case split on it.
|
||||
*/
|
||||
template<typename Ext>
|
||||
bool theory_arith<Ext>::branch_nl_int_var(theory_var v) {
|
||||
|
|
|
@ -53,18 +53,12 @@ namespace smt {
|
|||
var_data * d2 = m_var_data[v2];
|
||||
if (!d1->m_prop_upward && d2->m_prop_upward)
|
||||
set_prop_upward(v1);
|
||||
ptr_vector<enode>::iterator it = d2->m_stores.begin();
|
||||
ptr_vector<enode>::iterator end = d2->m_stores.end();
|
||||
for (; it != end; ++it)
|
||||
add_store(v1, *it);
|
||||
it = d2->m_parent_stores.begin();
|
||||
end = d2->m_parent_stores.end();
|
||||
for (; it != end; ++it)
|
||||
add_parent_store(v1, *it);
|
||||
it = d2->m_parent_selects.begin();
|
||||
end = d2->m_parent_selects.end();
|
||||
for (; it != end; ++it)
|
||||
add_parent_select(v1, *it);
|
||||
for (enode* n : d2->m_stores)
|
||||
add_store(v1, n);
|
||||
for (enode* n : d2->m_parent_stores)
|
||||
add_parent_store(v1, n);
|
||||
for (enode* n : d2->m_parent_selects)
|
||||
add_parent_select(v1, n);
|
||||
TRACE("array", tout << "after merge\n"; display_var(tout, v1););
|
||||
}
|
||||
|
||||
|
@ -103,16 +97,11 @@ namespace smt {
|
|||
d->m_parent_selects.push_back(s);
|
||||
TRACE("array", tout << mk_pp(s->get_owner(), get_manager()) << " " << mk_pp(get_enode(v)->get_owner(), get_manager()) << "\n";);
|
||||
m_trail_stack.push(push_back_trail<theory_array, enode *, false>(d->m_parent_selects));
|
||||
ptr_vector<enode>::iterator it = d->m_stores.begin();
|
||||
ptr_vector<enode>::iterator end = d->m_stores.end();
|
||||
for (; it != end; ++it) {
|
||||
instantiate_axiom2a(s, *it);
|
||||
for (enode* n : d->m_stores) {
|
||||
instantiate_axiom2a(s, n);
|
||||
}
|
||||
if (!m_params.m_array_weak && !m_params.m_array_delay_exp_axiom && d->m_prop_upward) {
|
||||
it = d->m_parent_stores.begin();
|
||||
end = d->m_parent_stores.end();
|
||||
for (; it != end; ++it) {
|
||||
enode * store = *it;
|
||||
for (enode* store : d->m_parent_stores) {
|
||||
SASSERT(is_store(store));
|
||||
if (!m_params.m_array_cg || store->is_cgr()) {
|
||||
instantiate_axiom2b(s, store);
|
||||
|
@ -129,27 +118,19 @@ namespace smt {
|
|||
var_data * d = m_var_data[v];
|
||||
d->m_parent_stores.push_back(s);
|
||||
m_trail_stack.push(push_back_trail<theory_array, enode *, false>(d->m_parent_stores));
|
||||
if (!m_params.m_array_weak && !m_params.m_array_delay_exp_axiom && d->m_prop_upward) {
|
||||
ptr_vector<enode>::iterator it = d->m_parent_selects.begin();
|
||||
ptr_vector<enode>::iterator end = d->m_parent_selects.end();
|
||||
for (; it != end; ++it)
|
||||
if (!m_params.m_array_cg || (*it)->is_cgr())
|
||||
instantiate_axiom2b(*it, s);
|
||||
}
|
||||
if (!m_params.m_array_weak && !m_params.m_array_delay_exp_axiom && d->m_prop_upward)
|
||||
for (enode* n : d->m_parent_selects)
|
||||
if (!m_params.m_array_cg || n->is_cgr())
|
||||
instantiate_axiom2b(n, s);
|
||||
}
|
||||
|
||||
bool theory_array::instantiate_axiom2b_for(theory_var v) {
|
||||
bool result = false;
|
||||
var_data * d = m_var_data[v];
|
||||
ptr_vector<enode>::iterator it = d->m_parent_stores.begin();
|
||||
ptr_vector<enode>::iterator end = d->m_parent_stores.end();
|
||||
for (; it != end; ++it) {
|
||||
ptr_vector<enode>::iterator it2 = d->m_parent_selects.begin();
|
||||
ptr_vector<enode>::iterator end2 = d->m_parent_selects.end();
|
||||
for (; it2 != end2; ++it2)
|
||||
if (instantiate_axiom2b(*it2, *it))
|
||||
for (enode* n1 : d->m_parent_stores)
|
||||
for (enode * n2 : d->m_parent_selects)
|
||||
if (instantiate_axiom2b(n2, n1))
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -167,10 +148,8 @@ namespace smt {
|
|||
d->m_prop_upward = true;
|
||||
if (!m_params.m_array_delay_exp_axiom)
|
||||
instantiate_axiom2b_for(v);
|
||||
ptr_vector<enode>::iterator it = d->m_stores.begin();
|
||||
ptr_vector<enode>::iterator end = d->m_stores.end();
|
||||
for (; it != end; ++it)
|
||||
set_prop_upward(*it);
|
||||
for (enode * n : d->m_stores)
|
||||
set_prop_upward(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,11 +188,9 @@ namespace smt {
|
|||
}
|
||||
d->m_stores.push_back(s);
|
||||
m_trail_stack.push(push_back_trail<theory_array, enode *, false>(d->m_stores));
|
||||
ptr_vector<enode>::iterator it = d->m_parent_selects.begin();
|
||||
ptr_vector<enode>::iterator end = d->m_parent_selects.end();
|
||||
for (; it != end; ++it) {
|
||||
SASSERT(is_select(*it));
|
||||
instantiate_axiom2a(*it, s);
|
||||
for (enode * n : d->m_parent_selects) {
|
||||
SASSERT(is_select(n));
|
||||
instantiate_axiom2a(n, s);
|
||||
}
|
||||
if (m_params.m_array_always_prop_upward || lambda_equiv_class_size >= 1)
|
||||
set_prop_upward(s);
|
||||
|
@ -374,7 +351,7 @@ namespace smt {
|
|||
|
||||
final_check_status theory_array::final_check_eh() {
|
||||
m_final_check_idx++;
|
||||
final_check_status r;
|
||||
final_check_status r = FC_DONE;
|
||||
if (m_params.m_array_lazy_ieq) {
|
||||
// Delay the creation of interface equalities... The
|
||||
// motivation is too give other theories and quantifier
|
||||
|
|
|
@ -210,17 +210,16 @@ namespace smt {
|
|||
|
||||
|
||||
|
||||
|
||||
func_decl_ref_vector * theory_array_base::register_sort(sort * s_array) {
|
||||
unsigned dimension = get_dimension(s_array);
|
||||
func_decl_ref_vector * ext_skolems = 0;
|
||||
if (!m_sort2skolem.find(s_array, ext_skolems)) {
|
||||
array_util util(get_manager());
|
||||
ast_manager & m = get_manager();
|
||||
ext_skolems = alloc(func_decl_ref_vector, m);
|
||||
for (unsigned i = 0; i < dimension; ++i) {
|
||||
sort * ext_sk_domain[2] = { s_array, s_array };
|
||||
parameter p(i);
|
||||
func_decl * ext_sk_decl = m.mk_func_decl(get_id(), OP_ARRAY_EXT, 1, &p, 2, ext_sk_domain);
|
||||
func_decl * ext_sk_decl = util.mk_array_ext(s_array, i);
|
||||
ext_skolems->push_back(ext_sk_decl);
|
||||
}
|
||||
m_sort2skolem.insert(s_array, ext_skolems);
|
||||
|
@ -617,8 +616,8 @@ namespace smt {
|
|||
m_else_values.reset();
|
||||
m_parents.reset();
|
||||
m_parents.resize(num_vars, -1);
|
||||
m_defaults.resize(num_vars, 0);
|
||||
m_else_values.resize(num_vars, 0);
|
||||
m_defaults.resize(num_vars);
|
||||
m_else_values.resize(num_vars);
|
||||
|
||||
if (m_use_unspecified_default)
|
||||
return;
|
||||
|
|
|
@ -620,7 +620,7 @@ namespace smt {
|
|||
sort * s = recognizer->get_decl()->get_domain(0);
|
||||
if (d->m_recognizers.empty()) {
|
||||
SASSERT(m_util.is_datatype(s));
|
||||
d->m_recognizers.resize(m_util.get_datatype_num_constructors(s), 0);
|
||||
d->m_recognizers.resize(m_util.get_datatype_num_constructors(s));
|
||||
}
|
||||
SASSERT(d->m_recognizers.size() == m_util.get_datatype_num_constructors(s));
|
||||
unsigned c_idx = m_util.get_recognizer_constructor_idx(recognizer->get_decl());
|
||||
|
|
|
@ -151,14 +151,15 @@ namespace smt {
|
|||
m_autil.is_numeral(rhs, _k);
|
||||
numeral offset(_k);
|
||||
app * s, * t;
|
||||
if (m_autil.is_add(lhs) && to_app(lhs)->get_num_args() == 2 && is_times_minus_one(to_app(lhs)->get_arg(1), s)) {
|
||||
t = to_app(to_app(lhs)->get_arg(0));
|
||||
expr *arg1, *arg2;
|
||||
if (m_autil.is_add(lhs, arg1, arg2) && is_times_minus_one(arg2, s)) {
|
||||
t = to_app(arg1);
|
||||
}
|
||||
else if (m_autil.is_add(lhs) && to_app(lhs)->get_num_args() == 2 && is_times_minus_one(to_app(lhs)->get_arg(0), s)) {
|
||||
t = to_app(to_app(lhs)->get_arg(1));
|
||||
else if (m_autil.is_add(lhs, arg1, arg2) && is_times_minus_one(arg1, s)) {
|
||||
t = to_app(arg2);
|
||||
}
|
||||
else if (m_autil.is_mul(lhs) && to_app(lhs)->get_num_args() == 2 && m_autil.is_minus_one(to_app(lhs)->get_arg(0))) {
|
||||
s = to_app(to_app(lhs)->get_arg(1));
|
||||
else if (m_autil.is_mul(lhs, arg1, arg2) && m_autil.is_minus_one(arg1)) {
|
||||
s = to_app(arg2);
|
||||
t = mk_zero_for(s);
|
||||
}
|
||||
else if (!m_autil.is_arith_expr(lhs)) {
|
||||
|
@ -170,6 +171,7 @@ namespace smt {
|
|||
found_non_diff_logic_expr(n);
|
||||
return false;
|
||||
}
|
||||
TRACE("arith", tout << expr_ref(lhs, get_manager()) << " " << expr_ref(s, get_manager()) << " " << expr_ref(t, get_manager()) << "\n";);
|
||||
source = internalize_term_core(s);
|
||||
target = internalize_term_core(t);
|
||||
if (source == null_theory_var || target == null_theory_var) {
|
||||
|
@ -912,6 +914,8 @@ namespace smt {
|
|||
}
|
||||
verbose_stream() << " + " << m_objective_consts[v] << "\n";);
|
||||
|
||||
unsynch_mpq_manager mgr;
|
||||
unsynch_mpq_inf_manager inf_mgr;
|
||||
unsigned num_nodes = get_num_vars();
|
||||
unsigned num_edges = m_edges.size();
|
||||
S.ensure_var(num_nodes + num_edges + m_objectives.size());
|
||||
|
@ -919,8 +923,9 @@ namespace smt {
|
|||
numeral const& a = m_assignment[i];
|
||||
rational fin = a.get_rational().to_rational();
|
||||
rational inf = a.get_infinitesimal().to_rational();
|
||||
mpq_inf q(fin.to_mpq(), inf.to_mpq());
|
||||
mpq_inf q(mgr.dup(fin.to_mpq()), mgr.dup(inf.to_mpq()));
|
||||
S.set_value(i, q);
|
||||
inf_mgr.del(q);
|
||||
}
|
||||
for (unsigned i = 0; i < num_nodes; ++i) {
|
||||
enode * n = get_enode(i);
|
||||
|
@ -931,7 +936,6 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
svector<unsigned> vars;
|
||||
unsynch_mpq_manager mgr;
|
||||
scoped_mpq_vector coeffs(mgr);
|
||||
coeffs.push_back(mpq(1));
|
||||
coeffs.push_back(mpq(-1));
|
||||
|
@ -952,8 +956,9 @@ namespace smt {
|
|||
numeral const& w = e.m_offset;
|
||||
rational fin = w.get_rational().to_rational();
|
||||
rational inf = w.get_infinitesimal().to_rational();
|
||||
mpq_inf q(fin.to_mpq(),inf.to_mpq());
|
||||
mpq_inf q(mgr.dup(fin.to_mpq()), mgr.dup(inf.to_mpq()));
|
||||
S.set_upper(base_var, q);
|
||||
inf_mgr.del(q);
|
||||
}
|
||||
unsigned w = num_nodes + num_edges + v;
|
||||
|
||||
|
|
|
@ -733,7 +733,6 @@ theory_var theory_diff_logic<Ext>::mk_term(app* n) {
|
|||
source = mk_var(a);
|
||||
for (unsigned i = 0; i < n->get_num_args(); ++i) {
|
||||
expr* arg = n->get_arg(i);
|
||||
std::cout << "internalize: " << mk_pp(arg, get_manager()) << " " << ctx.e_internalized(arg) << "\n";
|
||||
if (!ctx.e_internalized(arg)) {
|
||||
ctx.internalize(arg, false);
|
||||
}
|
||||
|
@ -1108,6 +1107,8 @@ unsigned theory_diff_logic<Ext>::simplex2edge(unsigned e) {
|
|||
|
||||
template<typename Ext>
|
||||
void theory_diff_logic<Ext>::update_simplex(Simplex& S) {
|
||||
unsynch_mpq_manager mgr;
|
||||
unsynch_mpq_inf_manager inf_mgr;
|
||||
unsigned num_nodes = m_graph.get_num_nodes();
|
||||
vector<dl_edge<GExt> > const& es = m_graph.get_all_edges();
|
||||
S.ensure_var(num_simplex_vars());
|
||||
|
@ -1115,13 +1116,13 @@ void theory_diff_logic<Ext>::update_simplex(Simplex& S) {
|
|||
numeral const& a = m_graph.get_assignment(i);
|
||||
rational fin = a.get_rational().to_rational();
|
||||
rational inf = a.get_infinitesimal().to_rational();
|
||||
mpq_inf q(fin.to_mpq(), inf.to_mpq());
|
||||
mpq_inf q(mgr.dup(fin.to_mpq()), mgr.dup(inf.to_mpq()));
|
||||
S.set_value(node2simplex(i), q);
|
||||
inf_mgr.del(q);
|
||||
}
|
||||
S.set_lower(node2simplex(get_zero()), mpq_inf(mpq(0), mpq(0)));
|
||||
S.set_upper(node2simplex(get_zero()), mpq_inf(mpq(0), mpq(0)));
|
||||
svector<unsigned> vars;
|
||||
unsynch_mpq_manager mgr;
|
||||
scoped_mpq_vector coeffs(mgr);
|
||||
coeffs.push_back(mpq(1));
|
||||
coeffs.push_back(mpq(-1));
|
||||
|
@ -1146,8 +1147,9 @@ void theory_diff_logic<Ext>::update_simplex(Simplex& S) {
|
|||
numeral const& w = e.get_weight();
|
||||
rational fin = w.get_rational().to_rational();
|
||||
rational inf = w.get_infinitesimal().to_rational();
|
||||
mpq_inf q(fin.to_mpq(),inf.to_mpq());
|
||||
mpq_inf q(mgr.dup(fin.to_mpq()), mgr.dup(inf.to_mpq()));
|
||||
S.set_upper(base_var, q);
|
||||
inf_mgr.del(q);
|
||||
}
|
||||
else {
|
||||
S.unset_upper(base_var);
|
||||
|
|
|
@ -884,22 +884,4 @@ namespace smt {
|
|||
out << r->get_id() << " --> " << mk_ismt2_pp(n, m) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool theory_fpa::include_func_interp(func_decl * f) {
|
||||
TRACE("t_fpa", tout << "f = " << mk_ismt2_pp(f, get_manager()) << std::endl;);
|
||||
|
||||
if (f->get_family_id() == get_family_id()) {
|
||||
bool include =
|
||||
m_fpa_util.is_min_unspecified(f) ||
|
||||
m_fpa_util.is_max_unspecified(f) ;
|
||||
if (include && !m_is_added_to_model.contains(f)) {
|
||||
//m_is_added_to_model.insert(f);
|
||||
//get_manager().inc_ref(f);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -158,7 +158,6 @@ namespace smt {
|
|||
virtual char const * get_name() const { return "fpa"; }
|
||||
|
||||
virtual model_value_proc * mk_value(enode * n, model_generator & mg);
|
||||
virtual bool include_func_interp(func_decl * f);
|
||||
|
||||
void assign_eh(bool_var v, bool is_true);
|
||||
virtual void relevant_eh(app * n);
|
||||
|
@ -180,8 +179,6 @@ namespace smt {
|
|||
expr_ref convert_term(expr * e);
|
||||
expr_ref convert_conversion_term(expr * e);
|
||||
|
||||
void add_trail(ast * a);
|
||||
|
||||
void attach_new_th_var(enode * n);
|
||||
void assert_cnstr(expr * e);
|
||||
|
||||
|
|
|
@ -689,7 +689,7 @@ namespace smt {
|
|||
SASSERT(!ctx().b_internalized(atom));
|
||||
bool_var bv = ctx().mk_bool_var(atom);
|
||||
ctx().set_var_theory(bv, get_id());
|
||||
expr* n1, *n2;
|
||||
expr* n1 = 0, *n2 = 0;
|
||||
rational r;
|
||||
lra_lp::bound_kind k;
|
||||
theory_var v = null_theory_var;
|
||||
|
@ -721,7 +721,7 @@ namespace smt {
|
|||
SASSERT(!ctx().b_internalized(atom));
|
||||
bool_var bv = ctx().mk_bool_var(atom);
|
||||
ctx().set_var_theory(bv, get_id());
|
||||
expr* n1, *n2;
|
||||
expr* n1 = 0, *n2 = 0;
|
||||
rational r;
|
||||
lra_lp::bound_kind k;
|
||||
theory_var v = null_theory_var;
|
||||
|
@ -862,7 +862,7 @@ namespace smt {
|
|||
|
||||
void relevant_eh(app* n) {
|
||||
TRACE("arith", tout << mk_pp(n, m) << "\n";);
|
||||
expr* n1, *n2;
|
||||
expr* n1 = 0, *n2 = 0;
|
||||
if (a.is_mod(n, n1, n2))
|
||||
mk_idiv_mod_axioms(n1, n2);
|
||||
else if (a.is_rem(n, n1, n2))
|
||||
|
|
|
@ -806,8 +806,9 @@ namespace smt {
|
|||
if (c != 0) {
|
||||
if (m_enable_simplex) {
|
||||
row_info const& info = m_ineq_row_info.find(v);
|
||||
unsynch_mpq_manager mgr;
|
||||
scoped_eps_numeral coeff(m_mpq_inf_mgr);
|
||||
coeff = std::make_pair(info.m_bound.to_mpq(), mpq(0));
|
||||
coeff = std::make_pair(mgr.dup(info.m_bound.to_mpq()), mpq(0));
|
||||
unsigned slack = info.m_slack;
|
||||
if (is_true) {
|
||||
update_bound(slack, literal(v), true, coeff);
|
||||
|
|
|
@ -279,7 +279,6 @@ namespace smt {
|
|||
//
|
||||
void compile_ineq(ineq& c);
|
||||
void inc_propagations(ineq& c);
|
||||
unsigned get_compilation_threshold(ineq& c);
|
||||
|
||||
//
|
||||
// Conflict resolution, cutting plane derivation.
|
||||
|
|
|
@ -3466,6 +3466,8 @@ static bool get_arith_value(context& ctx, theory_id afid, expr* e, expr_ref& v)
|
|||
bool theory_seq::get_num_value(expr* e, rational& val) const {
|
||||
context& ctx = get_context();
|
||||
expr_ref _val(m);
|
||||
if (!ctx.e_internalized(e))
|
||||
return false;
|
||||
enode* next = ctx.get_enode(e), *n = next;
|
||||
do {
|
||||
if (get_arith_value(ctx, m_autil.get_family_id(), next->get_owner(), _val) && m_autil.is_numeral(_val, val) && val.is_int()) {
|
||||
|
|
|
@ -315,6 +315,7 @@ namespace smt {
|
|||
m_trail.push_back(node);
|
||||
if (!cut_var_map.contains(baseNode)) {
|
||||
T_cut * varInfo = alloc(T_cut);
|
||||
m_cut_allocs.push_back(varInfo);
|
||||
varInfo->level = slevel;
|
||||
varInfo->vars[node] = 1;
|
||||
cut_var_map.insert(baseNode, std::stack<T_cut*>());
|
||||
|
@ -323,6 +324,7 @@ namespace smt {
|
|||
} else {
|
||||
if (cut_var_map[baseNode].empty()) {
|
||||
T_cut * varInfo = alloc(T_cut);
|
||||
m_cut_allocs.push_back(varInfo);
|
||||
varInfo->level = slevel;
|
||||
varInfo->vars[node] = 1;
|
||||
cut_var_map[baseNode].push(varInfo);
|
||||
|
@ -330,6 +332,7 @@ namespace smt {
|
|||
} else {
|
||||
if (cut_var_map[baseNode].top()->level < slevel) {
|
||||
T_cut * varInfo = alloc(T_cut);
|
||||
m_cut_allocs.push_back(varInfo);
|
||||
varInfo->level = slevel;
|
||||
cut_vars_map_copy(varInfo->vars, cut_var_map[baseNode].top()->vars);
|
||||
varInfo->vars[node] = 1;
|
||||
|
@ -359,6 +362,7 @@ namespace smt {
|
|||
|
||||
if (!cut_var_map.contains(destNode)) {
|
||||
T_cut * varInfo = alloc(T_cut);
|
||||
m_cut_allocs.push_back(varInfo);
|
||||
varInfo->level = slevel;
|
||||
cut_vars_map_copy(varInfo->vars, cut_var_map[srcNode].top()->vars);
|
||||
cut_var_map.insert(destNode, std::stack<T_cut*>());
|
||||
|
@ -367,6 +371,7 @@ namespace smt {
|
|||
} else {
|
||||
if (cut_var_map[destNode].empty() || cut_var_map[destNode].top()->level < slevel) {
|
||||
T_cut * varInfo = alloc(T_cut);
|
||||
m_cut_allocs.push_back(varInfo);
|
||||
varInfo->level = slevel;
|
||||
cut_vars_map_copy(varInfo->vars, cut_var_map[destNode].top()->vars);
|
||||
cut_vars_map_copy(varInfo->vars, cut_var_map[srcNode].top()->vars);
|
||||
|
@ -8883,15 +8888,30 @@ namespace smt {
|
|||
if (concat_lhs_haseqc && concat_rhs_haseqc && !var_haseqc) {
|
||||
TRACE("str", tout << "backpropagate into " << mk_pp(var, m) << " = " << mk_pp(concat, m) << std::endl
|
||||
<< "LHS ~= " << mk_pp(concat_lhs_str, m) << " RHS ~= " << mk_pp(concat_rhs_str, m) << std::endl;);
|
||||
|
||||
zstring lhsString, rhsString;
|
||||
u.str.is_string(concat_lhs_str, lhsString);
|
||||
u.str.is_string(concat_rhs_str, rhsString);
|
||||
zstring concatString = lhsString + rhsString;
|
||||
expr_ref lhs1(ctx.mk_eq_atom(concat_lhs, concat_lhs_str), m);
|
||||
expr_ref lhs2(ctx.mk_eq_atom(concat_rhs, concat_rhs_str), m);
|
||||
expr_ref lhs(m.mk_and(lhs1, lhs2), m);
|
||||
expr_ref rhs(ctx.mk_eq_atom(concat, mk_string(concatString)), m);
|
||||
assert_implication(lhs, rhs);
|
||||
|
||||
// special handling: don't assert that string constants are equal to themselves
|
||||
expr_ref_vector lhs_terms(m);
|
||||
if (!u.str.is_string(concat_lhs)) {
|
||||
lhs_terms.push_back(ctx.mk_eq_atom(concat_lhs, concat_lhs_str));
|
||||
}
|
||||
if (!u.str.is_string(concat_rhs)) {
|
||||
lhs_terms.push_back(ctx.mk_eq_atom(concat_rhs, concat_rhs_str));
|
||||
}
|
||||
|
||||
if (lhs_terms.empty()) {
|
||||
// no assumptions on LHS
|
||||
expr_ref rhs(ctx.mk_eq_atom(concat, mk_string(concatString)), m);
|
||||
assert_axiom(rhs);
|
||||
} else {
|
||||
expr_ref lhs(mk_and(lhs_terms), m);
|
||||
expr_ref rhs(ctx.mk_eq_atom(concat, mk_string(concatString)), m);
|
||||
assert_implication(lhs, rhs);
|
||||
}
|
||||
backpropagation_occurred = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,12 @@
|
|||
#define _THEORY_STR_H_
|
||||
|
||||
#include "util/trail.h"
|
||||
#include "util/union_find.h"
|
||||
#include "util/scoped_ptr_vector.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
#include "smt/smt_theory.h"
|
||||
#include "smt/params/theory_str_params.h"
|
||||
#include "smt/proto_model/value_factory.h"
|
||||
|
@ -29,8 +32,6 @@
|
|||
#include<stack>
|
||||
#include<vector>
|
||||
#include<map>
|
||||
#include "ast/seq_decl_plugin.h"
|
||||
#include "util/union_find.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
|
@ -292,6 +293,7 @@ protected:
|
|||
bool avoidLoopCut;
|
||||
bool loopDetected;
|
||||
obj_map<expr, std::stack<T_cut*> > cut_var_map;
|
||||
scoped_ptr_vector<T_cut> m_cut_allocs;
|
||||
expr_ref m_theoryStrOverlapAssumption_term;
|
||||
|
||||
obj_hashtable<expr> variable_set;
|
||||
|
|
|
@ -85,6 +85,10 @@ namespace smt {
|
|||
watch_list():
|
||||
m_data(0) {
|
||||
}
|
||||
|
||||
watch_list(watch_list && other) : m_data(0) {
|
||||
std::swap(m_data, other.m_data);
|
||||
}
|
||||
|
||||
~watch_list() {
|
||||
destroy();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue