3
0
Fork 0
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:
Nikolaj Bjorner 2018-06-26 07:23:04 -07:00
parent bf4edef761
commit 520ce9a5ee
139 changed files with 2243 additions and 1506 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -37,6 +37,6 @@ namespace Microsoft.Z3
{
Contract.Requires(ctx != null);
}
#endregion
#endregion
}
}

View file

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

View file

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

View file

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

View file

@ -141,6 +141,7 @@ set(Z3_JAVA_JAR_SOURCE_FILES
IntNum.java
IntSort.java
IntSymbol.java
Lambda.java
ListSort.java
Log.java
ModelDecRefQueue.java

View file

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

View file

@ -37,7 +37,7 @@ public class Quantifier extends BoolExpr
**/
public boolean isExistential()
{
return !isUniversal();
return Native.isQuantifierExists(getContext().nCtx(), getNativeObject());
}
/**

View file

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

View file

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

View file

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