mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
integrate lambda expressions
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
bf4edef761
commit
520ce9a5ee
139 changed files with 2243 additions and 1506 deletions
|
@ -47,6 +47,7 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
@ -99,6 +100,7 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
@ -155,6 +157,7 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(nullptr);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
|
|
@ -808,8 +808,7 @@ extern "C" {
|
|||
expr * a = to_expr(_a);
|
||||
expr * const * to = to_exprs(_to);
|
||||
var_subst subst(m, false);
|
||||
expr_ref new_a(m);
|
||||
subst(a, num_exprs, to, new_a);
|
||||
expr_ref new_a = subst(a, num_exprs, to);
|
||||
mk_c(c)->save_ast_trail(new_a);
|
||||
RETURN_Z3(of_expr(new_a.get()));
|
||||
Z3_CATCH_RETURN(nullptr);
|
||||
|
@ -910,6 +909,7 @@ extern "C" {
|
|||
case PR_TRANSITIVITY_STAR: return Z3_OP_PR_TRANSITIVITY_STAR;
|
||||
case PR_MONOTONICITY: return Z3_OP_PR_MONOTONICITY;
|
||||
case PR_QUANT_INTRO: return Z3_OP_PR_QUANT_INTRO;
|
||||
case PR_BIND: return Z3_OP_PR_BIND;
|
||||
case PR_DISTRIBUTIVITY: return Z3_OP_PR_DISTRIBUTIVITY;
|
||||
case PR_AND_ELIM: return Z3_OP_PR_AND_ELIM;
|
||||
case PR_NOT_OR_ELIM: return Z3_OP_PR_NOT_OR_ELIM;
|
||||
|
|
|
@ -173,6 +173,7 @@ extern "C" {
|
|||
to_optimize_ptr(o)->get_model(_m);
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref, *mk_c(c));
|
||||
if (_m) {
|
||||
if (mk_c(c)->params().m_model_compress) _m->compress();
|
||||
m_ref->m_model = _m;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -90,7 +90,7 @@ extern "C" {
|
|||
expr_ref result(mk_c(c)->m());
|
||||
if (num_decls > 0) {
|
||||
result = mk_c(c)->m().mk_quantifier(
|
||||
(0 != is_forall),
|
||||
is_forall ? forall_k : exists_k,
|
||||
names.size(), ts, names.c_ptr(), to_expr(body),
|
||||
weight,
|
||||
qid,
|
||||
|
@ -144,6 +144,61 @@ extern "C" {
|
|||
return Z3_mk_quantifier(c, 0, weight, num_patterns, patterns, num_decls, types, decl_names, body);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_lambda(Z3_context c,
|
||||
unsigned num_decls, Z3_sort const types[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body) {
|
||||
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_lambda(c, num_decls, types, decl_names, body);
|
||||
RESET_ERROR_CODE();
|
||||
expr_ref result(mk_c(c)->m());
|
||||
if (num_decls == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
|
||||
sort* const* ts = reinterpret_cast<sort * const*>(types);
|
||||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
names.push_back(to_symbol(decl_names[i]));
|
||||
}
|
||||
result = mk_c(c)->m().mk_lambda(names.size(), ts, names.c_ptr(), to_expr(body));
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
return of_ast(result.get());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_ast Z3_API Z3_mk_lambda_const(Z3_context c,
|
||||
unsigned num_decls, Z3_app const vars[],
|
||||
Z3_ast body) {
|
||||
|
||||
Z3_TRY;
|
||||
LOG_Z3_mk_lambda_const(c, num_decls, vars, body);
|
||||
RESET_ERROR_CODE();
|
||||
if (num_decls == 0) {
|
||||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
RETURN_Z3(0);
|
||||
}
|
||||
|
||||
svector<symbol> _names;
|
||||
ptr_vector<sort> _vars;
|
||||
ptr_vector<expr> _args;
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
app* a = to_app(vars[i]);
|
||||
_names.push_back(to_app(a)->get_decl()->get_name());
|
||||
_args.push_back(a);
|
||||
_vars.push_back(mk_c(c)->m().get_sort(a));
|
||||
}
|
||||
expr_ref result(mk_c(c)->m());
|
||||
expr_abstract(mk_c(c)->m(), 0, num_decls, _args.c_ptr(), to_expr(body), result);
|
||||
|
||||
result = mk_c(c)->m().mk_lambda(_vars.size(), _vars.c_ptr(), _names.c_ptr(), result);
|
||||
mk_c(c)->save_ast_trail(result.get());
|
||||
return of_ast(result.get());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
Z3_ast Z3_API Z3_mk_quantifier_const_ex(Z3_context c,
|
||||
Z3_bool is_forall,
|
||||
|
@ -292,17 +347,27 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_is_quantifier_forall(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
ast * _a = to_ast(a);
|
||||
if (_a->get_kind() == AST_QUANTIFIER) {
|
||||
return to_quantifier(_a)->is_forall();
|
||||
}
|
||||
else {
|
||||
SET_ERROR_CODE(Z3_SORT_ERROR);
|
||||
return Z3_FALSE;
|
||||
}
|
||||
return ::is_forall(to_ast(a)) ? Z3_TRUE : Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_quantifier_exists(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_quantifier_exists(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
return ::is_exists(to_ast(a)) ? Z3_TRUE : Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
Z3_bool Z3_API Z3_is_lambda(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_is_lambda(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
return ::is_lambda(to_ast(a)) ? Z3_TRUE : Z3_FALSE;
|
||||
Z3_CATCH_RETURN(Z3_FALSE);
|
||||
}
|
||||
|
||||
|
||||
unsigned Z3_API Z3_get_quantifier_weight(Z3_context c, Z3_ast a) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_get_quantifier_weight(c, a);
|
||||
|
@ -485,3 +550,4 @@ extern "C" {
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -433,6 +433,9 @@ extern "C" {
|
|||
SET_ERROR_CODE(Z3_INVALID_USAGE);
|
||||
RETURN_Z3(nullptr);
|
||||
}
|
||||
if (_m) {
|
||||
if (mk_c(c)->params().m_model_compress) _m->compress();
|
||||
}
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref, *mk_c(c));
|
||||
m_ref->m_model = _m;
|
||||
mk_c(c)->save_object(m_ref);
|
||||
|
|
|
@ -252,7 +252,6 @@ namespace z3 {
|
|||
*/
|
||||
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,
|
||||
|
@ -675,7 +674,21 @@ namespace z3 {
|
|||
\brief Return true if this expression is a quantifier.
|
||||
*/
|
||||
bool is_quantifier() const { return kind() == Z3_QUANTIFIER_AST; }
|
||||
|
||||
/**
|
||||
\brief Return true if this expression is a universal quantifier.
|
||||
*/
|
||||
bool is_forall() const { return 0 != Z3_is_quantifier_forall(ctx(), m_ast); }
|
||||
/**
|
||||
\brief Return true if this expression is an existential quantifier.
|
||||
*/
|
||||
bool is_exists() const { return 0 != Z3_is_quantifier_exists(ctx(), m_ast); }
|
||||
/**
|
||||
\brief Return true if this expression is a lambda expression.
|
||||
*/
|
||||
bool is_lambda() const { return 0 != Z3_is_lambda(ctx(), m_ast); }
|
||||
/**
|
||||
|
||||
\brief Return true if this expression is a variable.
|
||||
*/
|
||||
bool is_var() const { return kind() == Z3_VAR_AST; }
|
||||
|
@ -1638,6 +1651,31 @@ namespace z3 {
|
|||
array<Z3_app> vars(xs);
|
||||
Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, vars.size(), vars.ptr(), 0, 0, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr lambda(expr const & x, expr const & b) {
|
||||
check_context(x, b);
|
||||
Z3_app vars[] = {(Z3_app) x};
|
||||
Z3_ast r = Z3_mk_lambda_const(b.ctx(), 1, vars, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr lambda(expr const & x1, expr const & x2, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2};
|
||||
Z3_ast r = Z3_mk_lambda_const(b.ctx(), 2, vars, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr lambda(expr const & x1, expr const & x2, expr const & x3, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3 };
|
||||
Z3_ast r = Z3_mk_lambda_const(b.ctx(), 3, vars, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr lambda(expr const & x1, expr const & x2, expr const & x3, expr const & x4, expr const & b) {
|
||||
check_context(x1, b); check_context(x2, b); check_context(x3, b); check_context(x4, b);
|
||||
Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3, (Z3_app) x4 };
|
||||
Z3_ast r = Z3_mk_lambda_const(b.ctx(), 4, vars, b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
inline expr lambda(expr_vector const & xs, expr const & b) {
|
||||
array<Z3_app> vars(xs);
|
||||
Z3_ast r = Z3_mk_lambda_const(b.ctx(), vars.size(), vars.ptr(), b); b.check_error(); return expr(b.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr pble(expr_vector const& es, int const* coeffs, int bound) {
|
||||
assert(es.size() > 0);
|
||||
context& ctx = es[0].ctx();
|
||||
|
@ -2521,7 +2559,6 @@ namespace z3 {
|
|||
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]); }
|
||||
|
@ -2785,12 +2822,8 @@ namespace z3 {
|
|||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
}
|
||||
inline expr select(expr const & a, int i) { return select(a, a.ctx().num_val(i, a.get_sort().array_domain())); }
|
||||
inline expr store(expr const & a, expr const & i, expr const & v) {
|
||||
check_context(a, i); check_context(a, v);
|
||||
Z3_ast r = Z3_mk_store(a.ctx(), a, i, v);
|
||||
a.check_error();
|
||||
return expr(a.ctx(), r);
|
||||
inline expr select(expr const & a, int i) {
|
||||
return select(a, a.ctx().num_val(i, a.get_sort().array_domain()));
|
||||
}
|
||||
inline expr select(expr const & a, expr_vector const & i) {
|
||||
check_context(a, i);
|
||||
|
@ -2800,6 +2833,13 @@ namespace z3 {
|
|||
return expr(a.ctx(), r);
|
||||
}
|
||||
|
||||
inline expr store(expr const & a, expr const & i, expr const & v) {
|
||||
check_context(a, i); check_context(a, v);
|
||||
Z3_ast r = Z3_mk_store(a.ctx(), a, i, v);
|
||||
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) {
|
||||
|
|
|
@ -37,6 +37,6 @@ namespace Microsoft.Z3
|
|||
{
|
||||
Contract.Requires(ctx != null);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ set(Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE
|
|||
IntNum.cs
|
||||
IntSort.cs
|
||||
IntSymbol.cs
|
||||
Lambda.cs
|
||||
ListSort.cs
|
||||
Log.cs
|
||||
Model.cs
|
||||
|
|
|
@ -3292,6 +3292,53 @@ namespace Microsoft.Z3
|
|||
return MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a lambda expression.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a lambda expression.
|
||||
/// <paramref name="sorts"/> is an array
|
||||
/// with the sorts of the bound variables, <paramref name="names"/> is an array with the
|
||||
/// 'names' of the bound variables, and <paramref name="body"/> is the body of the
|
||||
/// lambda.
|
||||
/// Note that the bound variables are de-Bruijn indices created using <see cref="MkBound"/>.
|
||||
/// Z3 applies the convention that the last element in <paramref name="names"/> and
|
||||
/// <paramref name="sorts"/> refers to the variable with index 0, the second to last element
|
||||
/// of <paramref name="names"/> and <paramref name="sorts"/> refers to the variable
|
||||
/// with index 1, etc.
|
||||
/// </remarks>
|
||||
/// <param name="sorts">the sorts of the bound variables.</param>
|
||||
/// <param name="names">names of the bound variables</param>
|
||||
/// <param name="body">the body of the quantifier.</param>
|
||||
public Lambda MkLambda(Sort[] sorts, Symbol[] names, Expr body)
|
||||
{
|
||||
Contract.Requires(sorts != null);
|
||||
Contract.Requires(names != null);
|
||||
Contract.Requires(body != null);
|
||||
Contract.Requires(sorts.Length == names.Length);
|
||||
Contract.Requires(Contract.ForAll(sorts, s => s != null));
|
||||
Contract.Requires(Contract.ForAll(names, n => n != null));
|
||||
Contract.Ensures(Contract.Result<Lambda>() != null);
|
||||
return new Lambda(this, sorts, names, body);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a lambda expression.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a lambda expression using a list of constants that will
|
||||
/// form the set of bound variables.
|
||||
/// <seealso cref="MkLambda(Sort[], Symbol[], Expr)"/>
|
||||
/// </remarks>
|
||||
public Lambda MkLambda(Expr[] boundConstants, Expr body)
|
||||
{
|
||||
Contract.Requires(body != null);
|
||||
Contract.Requires(boundConstants != null && Contract.ForAll(boundConstants, b => b != null));
|
||||
Contract.Ensures(Contract.Result<Lambda>() != null);
|
||||
return new Lambda(this, boundConstants, body);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion // Expr
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace Microsoft.Z3
|
|||
/// </summary>
|
||||
public bool IsExistential
|
||||
{
|
||||
get { return !IsUniversal; }
|
||||
get { return Native.Z3_is_quantifier_exists(Context.nCtx, NativeObject) != 0; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -141,6 +141,7 @@ set(Z3_JAVA_JAR_SOURCE_FILES
|
|||
IntNum.java
|
||||
IntSort.java
|
||||
IntSymbol.java
|
||||
Lambda.java
|
||||
ListSort.java
|
||||
Log.java
|
||||
ModelDecRefQueue.java
|
||||
|
|
|
@ -518,7 +518,7 @@ public class Context implements AutoCloseable {
|
|||
|
||||
/**
|
||||
* Creates a fresh constant function declaration with a name prefixed with
|
||||
* {@code prefix"}.
|
||||
* {@code prefix}.
|
||||
* @see #mkFuncDecl(String,Sort,Sort)
|
||||
* @see #mkFuncDecl(String,Sort[],Sort)
|
||||
**/
|
||||
|
@ -696,7 +696,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates the equality {@code x"/> = <paramref name="y}.
|
||||
* Creates the equality {@code x = y}
|
||||
**/
|
||||
public BoolExpr mkEq(Expr x, Expr y)
|
||||
{
|
||||
|
@ -2498,6 +2498,40 @@ public class Context implements AutoCloseable {
|
|||
quantifierID, skolemID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a lambda expression.
|
||||
*
|
||||
* {@code sorts} is an array
|
||||
* with the sorts of the bound variables, {@code names} is an array with the
|
||||
* 'names' of the bound variables, and {@code body} is the body of the
|
||||
* lambda.
|
||||
* Note that the bound variables are de-Bruijn indices created using {@see #MkBound}
|
||||
* Z3 applies the convention that the last element in {@code names} and
|
||||
* {@code sorts} refers to the variable with index 0, the second to last element
|
||||
* of {@code names} and {@code sorts} refers to the variable
|
||||
* with index 1, etc.
|
||||
*
|
||||
* @param sorts the sorts of the bound variables.
|
||||
* @param names names of the bound variables.
|
||||
* @param body the body of the quantifier.
|
||||
**/
|
||||
public Lambda mkLambda(Sort[] sorts, Symbol[] names, Expr body)
|
||||
{
|
||||
return Lambda.of(this, sorts, names, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a lambda expression.
|
||||
*
|
||||
* Creates a lambda expression using a list of constants that will
|
||||
* form the set of bound variables.
|
||||
**/
|
||||
public Lambda mkLambda(Expr[] boundConstants, Expr body)
|
||||
{
|
||||
return Lambda.of(this, boundConstants, body);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Selects the format used for pretty-printing expressions.
|
||||
* Remarks: The
|
||||
|
@ -2653,7 +2687,7 @@ public class Context implements AutoCloseable {
|
|||
|
||||
/**
|
||||
* Create a tactic that applies {@code t1} to a Goal and then
|
||||
* {@code t2"/> to every subgoal produced by <paramref name="t1}.
|
||||
* {@code t2} to every subgoal produced by {@code t1}
|
||||
**/
|
||||
public Tactic andThen(Tactic t1, Tactic t2, Tactic... ts)
|
||||
|
||||
|
@ -2734,7 +2768,7 @@ public class Context implements AutoCloseable {
|
|||
|
||||
/**
|
||||
* Create a tactic that applies {@code t1} to a given goal if the
|
||||
* probe {@code p"/> evaluates to true and <paramref name="t2}
|
||||
* probe {@code p} evaluates to true and {@code t2}
|
||||
* otherwise.
|
||||
**/
|
||||
public Tactic cond(Probe p, Tactic t1, Tactic t2)
|
||||
|
@ -2895,7 +2929,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value returned by
|
||||
* Create a probe that evaluates to {@code true} when the value returned by
|
||||
* {@code p1} is less than the value returned by {@code p2}
|
||||
**/
|
||||
public Probe lt(Probe p1, Probe p2)
|
||||
|
@ -2907,7 +2941,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value returned by
|
||||
* Create a probe that evaluates to {@code true} when the value returned by
|
||||
* {@code p1} is greater than the value returned by {@code p2}
|
||||
**/
|
||||
public Probe gt(Probe p1, Probe p2)
|
||||
|
@ -2919,7 +2953,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value returned by
|
||||
* Create a probe that evaluates to {@code true} when the value returned by
|
||||
* {@code p1} is less than or equal the value returned by
|
||||
* {@code p2}
|
||||
**/
|
||||
|
@ -2932,7 +2966,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value returned by
|
||||
* Create a probe that evaluates to {@code true} when the value returned by
|
||||
* {@code p1} is greater than or equal the value returned by
|
||||
* {@code p2}
|
||||
**/
|
||||
|
@ -2945,7 +2979,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value returned by
|
||||
* Create a probe that evaluates to {@code true} when the value returned by
|
||||
* {@code p1} is equal to the value returned by {@code p2}
|
||||
**/
|
||||
public Probe eq(Probe p1, Probe p2)
|
||||
|
@ -2957,7 +2991,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value {@code p1} and {@code p2} evaluate to "true".
|
||||
* Create a probe that evaluates to {@code true} when the value {@code p1} and {@code p2} evaluate to {@code true}.
|
||||
**/
|
||||
public Probe and(Probe p1, Probe p2)
|
||||
{
|
||||
|
@ -2968,7 +3002,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value {@code p1} or {@code p2} evaluate to "true".
|
||||
* Create a probe that evaluates to {@code true} when the value {@code p1} or {@code p2} evaluate to {@code true}.
|
||||
**/
|
||||
public Probe or(Probe p1, Probe p2)
|
||||
{
|
||||
|
@ -2979,7 +3013,7 @@ public class Context implements AutoCloseable {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a probe that evaluates to "true" when the value {@code p} does not evaluate to "true".
|
||||
* Create a probe that evaluates to {@code true} when the value {@code p} does not evaluate to {@code true}.
|
||||
**/
|
||||
public Probe not(Probe p)
|
||||
{
|
||||
|
|
|
@ -37,7 +37,7 @@ public class Quantifier extends BoolExpr
|
|||
**/
|
||||
public boolean isExistential()
|
||||
{
|
||||
return !isUniversal();
|
||||
return Native.isQuantifierExists(getContext().nCtx(), getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1766,6 +1766,34 @@ class QuantifierRef(BoolRef):
|
|||
"""
|
||||
return Z3_is_quantifier_forall(self.ctx_ref(), self.ast)
|
||||
|
||||
def is_exists(self):
|
||||
"""Return `True` if `self` is an existential quantifier.
|
||||
|
||||
>>> f = Function('f', IntSort(), IntSort())
|
||||
>>> x = Int('x')
|
||||
>>> q = ForAll(x, f(x) == 0)
|
||||
>>> q.is_exists()
|
||||
False
|
||||
>>> q = Exists(x, f(x) != 0)
|
||||
>>> q.is_exists()
|
||||
True
|
||||
"""
|
||||
return Z3_is_quantifier_exists(self.ctx_ref(), self.ast)
|
||||
|
||||
def is_lambda(self):
|
||||
"""Return `True` if `self` is a lambda expression.
|
||||
|
||||
>>> f = Function('f', IntSort(), IntSort())
|
||||
>>> x = Int('x')
|
||||
>>> q = Lambda(x, f(x))
|
||||
>>> q.is_lambda()
|
||||
True
|
||||
>>> q = Exists(x, f(x) != 0)
|
||||
>>> q.is_lambda()
|
||||
False
|
||||
"""
|
||||
return Z3_is_lambda(self.ctx_ref(), self.ast)
|
||||
|
||||
def weight(self):
|
||||
"""Return the weight annotation of `self`.
|
||||
|
||||
|
@ -1973,6 +2001,26 @@ def Exists(vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]):
|
|||
"""
|
||||
return _mk_quantifier(False, vs, body, weight, qid, skid, patterns, no_patterns)
|
||||
|
||||
def Lambda(vs, body):
|
||||
"""Create a Z3 lambda expression.
|
||||
|
||||
>>> f = Function('f', IntSort(), IntSort(), IntSort())
|
||||
>>> mem0 = Array('mem0', IntSort(), IntSort())
|
||||
>>> lo, hi, e, i = Ints('lo hi e i')
|
||||
>>> mem1 = Lambda([i], If(And(lo <= i, i <= hi), e, mem0[i]))
|
||||
>>> mem1
|
||||
Lambda(i, If(And(lo <= i, i <= hi), e, mem0[i]))
|
||||
"""
|
||||
ctx = body.ctx
|
||||
if is_app(vs):
|
||||
vs = [vs]
|
||||
num_vars = len(vs)
|
||||
_vs = (Ast * num_vars)()
|
||||
for i in range(num_vars):
|
||||
## TODO: Check if is constant
|
||||
_vs[i] = vs[i].as_ast()
|
||||
return QuantifierRef(Z3_mk_lambda_const(ctx.ref(), num_vars, _vs, body.as_ast()), ctx)
|
||||
|
||||
#########################################
|
||||
#
|
||||
# Arithmetic
|
||||
|
@ -5582,7 +5630,7 @@ class FuncEntry:
|
|||
>>> m = s.model()
|
||||
>>> f_i = m[f]
|
||||
>>> f_i.num_entries()
|
||||
3
|
||||
1
|
||||
>>> e = f_i.entry(0)
|
||||
>>> e.num_args()
|
||||
2
|
||||
|
@ -5600,16 +5648,16 @@ class FuncEntry:
|
|||
>>> m = s.model()
|
||||
>>> f_i = m[f]
|
||||
>>> f_i.num_entries()
|
||||
3
|
||||
1
|
||||
>>> e = f_i.entry(0)
|
||||
>>> e
|
||||
[0, 1, 10]
|
||||
[1, 2, 20]
|
||||
>>> e.num_args()
|
||||
2
|
||||
>>> e.arg_value(0)
|
||||
0
|
||||
>>> e.arg_value(1)
|
||||
1
|
||||
>>> e.arg_value(1)
|
||||
2
|
||||
>>> try:
|
||||
... e.arg_value(2)
|
||||
... except IndexError:
|
||||
|
@ -5631,14 +5679,14 @@ class FuncEntry:
|
|||
>>> m = s.model()
|
||||
>>> f_i = m[f]
|
||||
>>> f_i.num_entries()
|
||||
3
|
||||
1
|
||||
>>> e = f_i.entry(0)
|
||||
>>> e
|
||||
[0, 1, 10]
|
||||
[1, 2, 20]
|
||||
>>> e.num_args()
|
||||
2
|
||||
>>> e.value()
|
||||
10
|
||||
20
|
||||
"""
|
||||
return _to_expr_ref(Z3_func_entry_get_value(self.ctx.ref(), self.entry), self.ctx)
|
||||
|
||||
|
@ -5652,10 +5700,10 @@ class FuncEntry:
|
|||
>>> m = s.model()
|
||||
>>> f_i = m[f]
|
||||
>>> f_i.num_entries()
|
||||
3
|
||||
1
|
||||
>>> e = f_i.entry(0)
|
||||
>>> e.as_list()
|
||||
[0, 1, 10]
|
||||
[1, 2, 20]
|
||||
"""
|
||||
args = [ self.arg_value(i) for i in range(self.num_args())]
|
||||
args.append(self.value())
|
||||
|
@ -5693,7 +5741,7 @@ class FuncInterp(Z3PPObject):
|
|||
sat
|
||||
>>> m = s.model()
|
||||
>>> m[f]
|
||||
[0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
|
||||
[2 -> 0, else -> 1]
|
||||
>>> m[f].else_value()
|
||||
1
|
||||
"""
|
||||
|
@ -5713,9 +5761,9 @@ class FuncInterp(Z3PPObject):
|
|||
sat
|
||||
>>> m = s.model()
|
||||
>>> m[f]
|
||||
[0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
|
||||
[2 -> 0, else -> 1]
|
||||
>>> m[f].num_entries()
|
||||
3
|
||||
1
|
||||
"""
|
||||
return int(Z3_func_interp_get_num_entries(self.ctx.ref(), self.f))
|
||||
|
||||
|
@ -5743,14 +5791,10 @@ class FuncInterp(Z3PPObject):
|
|||
sat
|
||||
>>> m = s.model()
|
||||
>>> m[f]
|
||||
[0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
|
||||
[2 -> 0, else -> 1]
|
||||
>>> m[f].num_entries()
|
||||
3
|
||||
1
|
||||
>>> m[f].entry(0)
|
||||
[0, 1]
|
||||
>>> m[f].entry(1)
|
||||
[1, 1]
|
||||
>>> m[f].entry(2)
|
||||
[2, 0]
|
||||
"""
|
||||
if idx >= self.num_entries():
|
||||
|
@ -5777,9 +5821,9 @@ class FuncInterp(Z3PPObject):
|
|||
sat
|
||||
>>> m = s.model()
|
||||
>>> m[f]
|
||||
[0 -> 1, 1 -> 1, 2 -> 0, else -> 1]
|
||||
[2 -> 0, else -> 1]
|
||||
>>> m[f].as_list()
|
||||
[[0, 1], [1, 1], [2, 0], 1]
|
||||
[[2, 0], 1]
|
||||
"""
|
||||
r = [ self.entry(i).as_list() for i in range(self.num_entries())]
|
||||
r.append(self.else_value())
|
||||
|
@ -5891,7 +5935,7 @@ class ModelRef(Z3PPObject):
|
|||
>>> m[x]
|
||||
1
|
||||
>>> m[f]
|
||||
[1 -> 0, else -> 0]
|
||||
[else -> 0]
|
||||
"""
|
||||
if __debug__:
|
||||
_z3_assert(isinstance(decl, FuncDeclRef) or is_const(decl), "Z3 declaration expected")
|
||||
|
@ -6008,10 +6052,10 @@ class ModelRef(Z3PPObject):
|
|||
>>> m[x]
|
||||
1
|
||||
>>> m[f]
|
||||
[1 -> 0, else -> 0]
|
||||
[else -> 0]
|
||||
>>> for d in m: print("%s -> %s" % (d, m[d]))
|
||||
x -> 1
|
||||
f -> [1 -> 0, else -> 0]
|
||||
f -> [else -> 0]
|
||||
"""
|
||||
if _is_int(idx):
|
||||
if idx >= len(self):
|
||||
|
|
|
@ -959,8 +959,10 @@ class Formatter:
|
|||
ys_pp = seq3(ys, '[', ']')
|
||||
if a.is_forall():
|
||||
header = 'ForAll'
|
||||
else:
|
||||
elif a.is_exists():
|
||||
header = 'Exists'
|
||||
else:
|
||||
header = 'Lambda'
|
||||
return seq1(header, (ys_pp, body_pp))
|
||||
|
||||
def pp_expr(self, a, d, xs):
|
||||
|
|
|
@ -482,6 +482,10 @@ typedef enum
|
|||
T1: (~ p q)
|
||||
[quant-intro T1]: (~ (forall (x) p) (forall (x) q))
|
||||
|
||||
- Z3_OP_PR_BIND: Given a proof p, produces a proof of lambda x . p, where x are free variables in p.
|
||||
T1: f
|
||||
[proof-bind T1] forall (x) f
|
||||
|
||||
- Z3_OP_PR_DISTRIBUTIVITY: Distributivity proof object.
|
||||
Given that f (= or) distributes over g (= and), produces a proof for
|
||||
|
||||
|
@ -1109,6 +1113,7 @@ typedef enum {
|
|||
Z3_OP_PR_TRANSITIVITY_STAR,
|
||||
Z3_OP_PR_MONOTONICITY,
|
||||
Z3_OP_PR_QUANT_INTRO,
|
||||
Z3_OP_PR_BIND,
|
||||
Z3_OP_PR_DISTRIBUTIVITY,
|
||||
Z3_OP_PR_AND_ELIM,
|
||||
Z3_OP_PR_NOT_OR_ELIM,
|
||||
|
@ -1857,7 +1862,6 @@ extern "C" {
|
|||
*/
|
||||
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.
|
||||
|
||||
|
@ -2946,6 +2950,8 @@ 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.
|
||||
|
@ -2955,6 +2961,7 @@ extern "C" {
|
|||
*/
|
||||
Z3_ast Z3_API Z3_mk_select_n(Z3_context c, Z3_ast a, unsigned n, Z3_ast const* idxs);
|
||||
|
||||
|
||||
/**
|
||||
\brief Array update.
|
||||
|
||||
|
@ -2973,6 +2980,7 @@ 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.
|
||||
|
||||
|
@ -3763,6 +3771,54 @@ extern "C" {
|
|||
Z3_ast body
|
||||
);
|
||||
|
||||
/**
|
||||
\brief Create a lambda expression. It taks an expression \c body that contains bound variables
|
||||
of the same sorts as the sorts listed in the array \c sorts. The bound variables are de-Bruijn indices created
|
||||
using #Z3_mk_bound. The array \c decl_names contains the names that the quantified formula uses for the
|
||||
bound variables. Z3 applies the convention that the last element in the \c decl_names and \c sorts array
|
||||
refers to the variable with index 0, the second to last element of \c decl_names and \c sorts refers
|
||||
to the variable with index 1, etc.
|
||||
The sort of the resulting expression is \c (Array sorts range) where \c range is the sort of \c body.
|
||||
For example, if the lambda binds two variables of sort \c Int and \c Bool, and the \c body has sort \c Real,
|
||||
the sort of the expression is \c (Array Int Bool Real).
|
||||
|
||||
\param c logical context
|
||||
\param num_decls number of variables to be bound.
|
||||
\param sorts the sorts of the bound variables.
|
||||
\param decl_names names of the bound variables
|
||||
\param body the body of the lambda expression.
|
||||
|
||||
\sa Z3_mk_bound
|
||||
\sa Z3_mk_forall
|
||||
\sa Z3_mk_lambda_const
|
||||
|
||||
def_API('Z3_mk_lambda', AST, (_in(CONTEXT), _in(UINT), _in_array(1, SORT), _in_array(1, SYMBOL), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_lambda(Z3_context c,
|
||||
unsigned num_decls, Z3_sort const sorts[],
|
||||
Z3_symbol const decl_names[],
|
||||
Z3_ast body);
|
||||
|
||||
/**
|
||||
\brief Create a lambda expression using a list of constants that form the set
|
||||
of bound variables
|
||||
|
||||
\param c logical context.
|
||||
\param num_bound number of constants to be abstracted into bound variables.
|
||||
\param bound array of constants to be abstracted into bound variables.
|
||||
\param body the body of the lambda expression.
|
||||
|
||||
\sa Z3_mk_bound
|
||||
\sa Z3_mk_forall
|
||||
\sa Z3_mk_lambda
|
||||
|
||||
def_API('Z3_mk_lambda_const', AST, (_in(CONTEXT), _in(UINT), _in_array(1, APP), _in(AST)))
|
||||
*/
|
||||
Z3_ast Z3_API Z3_mk_lambda_const(Z3_context c,
|
||||
unsigned num_bound, Z3_app const bound[],
|
||||
Z3_ast body);
|
||||
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @name Accessors */
|
||||
|
@ -4529,14 +4585,29 @@ extern "C" {
|
|||
unsigned Z3_API Z3_get_index_value(Z3_context c, Z3_ast a);
|
||||
|
||||
/**
|
||||
\brief Determine if quantifier is universal.
|
||||
|
||||
\pre Z3_get_ast_kind(a) == Z3_QUANTIFIER_AST
|
||||
\brief Determine if an ast is a universal quantifier.
|
||||
|
||||
def_API('Z3_is_quantifier_forall', BOOL, (_in(CONTEXT), _in(AST)))
|
||||
*/
|
||||
Z3_bool Z3_API Z3_is_quantifier_forall(Z3_context c, Z3_ast a);
|
||||
|
||||
/**
|
||||
\brief Determine if ast is an existential quantifier.
|
||||
|
||||
|
||||
def_API('Z3_is_quantifier_exists', BOOL, (_in(CONTEXT), _in(AST)))
|
||||
*/
|
||||
Z3_bool Z3_API Z3_is_quantifier_exists(Z3_context c, Z3_ast a);
|
||||
|
||||
/**
|
||||
\brief Determine if ast is a lambda expresion.
|
||||
|
||||
\pre Z3_get_ast_kind(a) == Z3_QUANTIFIER_AST
|
||||
|
||||
def_API('Z3_is_lambda', BOOL, (_in(CONTEXT), _in(AST)))
|
||||
*/
|
||||
Z3_bool Z3_API Z3_is_lambda(Z3_context c, Z3_ast a);
|
||||
|
||||
/**
|
||||
\brief Obtain weight of quantifier.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue