3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-06 09:34:08 +00:00

additional array functions exposed over API, ping #1223

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-10-19 11:08:48 -07:00
parent d76566bf83
commit c9f540b066
13 changed files with 354 additions and 72 deletions

View file

@ -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);

View file

@ -250,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,
@ -2327,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]); }
@ -2573,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); \

View file

@ -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
};

View file

@ -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)
{

View file

@ -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()));
}
};

View file

@ -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()));

View file

@ -1881,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.
@ -2973,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.
@ -2991,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.
@ -3031,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 */
@ -3854,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

View file

@ -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, &param));
}
@ -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);
}

View file

@ -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,12 +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);
sort * s = f->get_range();
return m_manager.mk_app(m_fid, OP_AS_ARRAY, 1, &param, 0, 0, s);
}
};

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -117,7 +117,7 @@ func_decl_ref bvarray2uf_rewriter_cfg::mk_uf_for_array(expr * e) {
if (is_uninterp_const(e)) {
if (m_emc)
m_emc->insert(to_app(e)->get_decl(),
m_array_util.mk_as_array(m_manager.get_sort(e), bv_f));
m_array_util.mk_as_array(bv_f));
}
else if (m_fmc)
m_fmc->insert(bv_f);
@ -193,7 +193,7 @@ br_status bvarray2uf_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr
if (is_uninterp_const(e)) {
if (m_emc)
m_emc->insert(e->get_decl(),
m_array_util.mk_as_array(m_manager.get_sort(e), bv_f));
m_array_util.mk_as_array(bv_f));
}
else if (m_fmc)
m_fmc->insert(bv_f);
@ -207,7 +207,7 @@ br_status bvarray2uf_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr
q = m_manager.mk_forall(1, sorts, names, body);
extra_assertions.push_back(q);
result = m_array_util.mk_as_array(f->get_range(), bv_f);
result = m_array_util.mk_as_array(bv_f);
TRACE("bvarray2uf_rw", tout << "result: " << mk_ismt2_pp(result, m_manager) << ")" << std::endl;);
res = BR_DONE;
@ -234,7 +234,7 @@ br_status bvarray2uf_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr
if (is_bv_array(t)) {
// From [1]: For every array term t we create a fresh uninterpreted function f_t.
f_t = mk_uf_for_array(t);
result = m_array_util.mk_as_array(m_manager.get_sort(t), f_t);
result = m_array_util.mk_as_array(f_t);
res = BR_DONE;
}
else if (has_bv_arrays) {
@ -274,7 +274,7 @@ br_status bvarray2uf_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr
expr * v = args[0];
func_decl_ref f_t(mk_uf_for_array(t), m_manager);
result = m_array_util.mk_as_array(f->get_range(), f_t);
result = m_array_util.mk_as_array(f_t);
res = BR_DONE;
// Add \forall x . f_t(x) = v
@ -321,7 +321,7 @@ br_status bvarray2uf_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr
expr_ref frllx(m_manager.mk_forall(1, sorts, names, body), m_manager);
extra_assertions.push_back(frllx);
result = m_array_util.mk_as_array(f->get_range(), f_t);
result = m_array_util.mk_as_array(f_t);
res = BR_DONE;
}
else if (m_array_util.is_store(f)) {
@ -342,7 +342,7 @@ br_status bvarray2uf_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr
func_decl_ref f_s(mk_uf_for_array(s), m_manager);
func_decl_ref f_t(mk_uf_for_array(t), m_manager);
result = m_array_util.mk_as_array(f->get_range(), f_t);
result = m_array_util.mk_as_array(f_t);
res = BR_DONE;
sort * sorts[1] = { get_index_sort(f->get_range()) };