3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-10 19:27:06 +00:00
z3/Microsoft.Z3/Model.cs
Leonardo de Moura 68269c43a6 other components
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:48:48 -07:00

319 lines
11 KiB
C#

/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
Model.cs
Abstract:
Z3 Managed API: Models
Author:
Christoph Wintersteiger (cwinter) 2012-03-21
Notes:
--*/
using System;
using System.Diagnostics.Contracts;
namespace Microsoft.Z3
{
/// <summary>
/// A Model contains interpretations (assignments) of constants and functions.
/// </summary>
[ContractVerification(true)]
public class Model : Z3Object
{
/// <summary>
/// Retrieves the interpretation (the assignment) of <paramref name="a"/> in the model.
/// </summary>
/// <param name="a">A Constant</param>
/// <returns>An expression if the constant has an interpretation in the model, null otherwise.</returns>
public Expr ConstInterp(Expr a)
{
Contract.Requires(a != null);
Context.CheckContextMatch(a);
return ConstInterp(a.FuncDecl);
}
/// <summary>
/// Retrieves the interpretation (the assignment) of <paramref name="f"/> in the model.
/// </summary>
/// <param name="f">A function declaration of zero arity</param>
/// <returns>An expression if the function has an interpretation in the model, null otherwise.</returns>
public Expr ConstInterp(FuncDecl f)
{
Contract.Requires(f != null);
Context.CheckContextMatch(f);
if (f.Arity != 0 ||
Native.Z3_get_sort_kind(Context.nCtx, Native.Z3_get_range(Context.nCtx, f.NativeObject)) == (uint)Z3_sort_kind.Z3_ARRAY_SORT)
throw new Z3Exception("Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.");
IntPtr n = Native.Z3_model_get_const_interp(Context.nCtx, NativeObject, f.NativeObject);
if (n == IntPtr.Zero)
return null;
else
return Expr.Create(Context, n);
}
/// <summary>
/// Retrieves the interpretation (the assignment) of a non-constant <paramref name="f"/> in the model.
/// </summary>
/// <param name="f">A function declaration of non-zero arity</param>
/// <returns>A FunctionInterpretation if the function has an interpretation in the model, null otherwise.</returns>
public FuncInterp FuncInterp(FuncDecl f)
{
Contract.Requires(f != null);
Context.CheckContextMatch(f);
Z3_sort_kind sk = (Z3_sort_kind)Native.Z3_get_sort_kind(Context.nCtx, Native.Z3_get_range(Context.nCtx, f.NativeObject));
if (f.Arity == 0)
{
IntPtr n = Native.Z3_model_get_const_interp(Context.nCtx, NativeObject, f.NativeObject);
if (sk == Z3_sort_kind.Z3_ARRAY_SORT)
{
if (n == IntPtr.Zero)
return null;
else
{
if (Native.Z3_is_as_array(Context.nCtx, n) == 0)
throw new Z3Exception("Argument was not an array constant");
IntPtr fd = Native.Z3_get_as_array_func_decl(Context.nCtx, n);
return FuncInterp(new FuncDecl(Context, fd));
}
}
else
{
throw new Z3Exception("Constant functions do not have a function interpretation; use ConstInterp");
}
}
else
{
IntPtr n = Native.Z3_model_get_func_interp(Context.nCtx, NativeObject, f.NativeObject);
if (n == IntPtr.Zero)
return null;
else
return new FuncInterp(Context, n);
}
}
/// <summary>
/// The number of constants that have an interpretation in the model.
/// </summary>
public uint NumConsts
{
get { return Native.Z3_model_get_num_consts(Context.nCtx, NativeObject); }
}
/// <summary>
/// The function declarations of the constants in the model.
/// </summary>
public FuncDecl[] ConstDecls
{
get
{
Contract.Ensures(Contract.Result<FuncDecl[]>() != null);
uint n = NumConsts;
FuncDecl[] res = new FuncDecl[n];
for (uint i = 0; i < n; i++)
res[i] = new FuncDecl(Context, Native.Z3_model_get_const_decl(Context.nCtx, NativeObject, i));
return res;
}
}
/// <summary>
/// The number of function interpretations in the model.
/// </summary>
public uint NumFuncs
{
get { return Native.Z3_model_get_num_funcs(Context.nCtx, NativeObject); }
}
/// <summary>
/// The function declarations of the function interpretations in the model.
/// </summary>
public FuncDecl[] FuncDecls
{
get
{
Contract.Ensures(Contract.Result<FuncDecl[]>() != null);
uint n = NumFuncs;
FuncDecl[] res = new FuncDecl[n];
for (uint i = 0; i < n; i++)
res[i] = new FuncDecl(Context, Native.Z3_model_get_func_decl(Context.nCtx, NativeObject, i));
return res;
}
}
/// <summary>
/// All symbols that have an interpretation in the model.
/// </summary>
public FuncDecl[] Decls
{
get
{
Contract.Ensures(Contract.Result<FuncDecl[]>() != null);
var nFuncs = NumFuncs;
var nConsts = NumConsts;
uint n = nFuncs + nConsts;
FuncDecl[] res = new FuncDecl[n];
for (uint i = 0; i < nConsts; i++)
res[i] = new FuncDecl(Context, Native.Z3_model_get_const_decl(Context.nCtx, NativeObject, i));
for (uint i = 0; i < nFuncs; i++)
res[nConsts + i] = new FuncDecl(Context, Native.Z3_model_get_func_decl(Context.nCtx, NativeObject, i));
return res;
}
}
/// <summary>
/// A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model.
/// </summary>
public class ModelEvaluationFailedException : Z3Exception
{
/// <summary>
/// An exception that is thrown when model evaluation fails.
/// </summary>
public ModelEvaluationFailedException() : base() { }
}
/// <summary>
/// Evaluates the expression <paramref name="t"/> in the current model.
/// </summary>
/// <remarks>
/// This function may fail if <paramref name="t"/> contains quantifiers,
/// is partial (MODEL_PARTIAL enabled), or if <paramref name="t"/> is not well-sorted.
/// In this case a <c>ModelEvaluationFailedException</c> is thrown.
/// </remarks>
/// <param name="t">An expression</param>
/// <param name="completion">
/// When this flag is enabled, a model value will be assigned to any constant
/// or function that does not have an interpretation in the model.
/// </param>
/// <returns>The evaluation of <paramref name="t"/> in the model.</returns>
public Expr Eval(Expr t, bool completion = false)
{
Contract.Requires(t != null);
Contract.Ensures(Contract.Result<Expr>() != null);
IntPtr v = IntPtr.Zero;
if (Native.Z3_model_eval(Context.nCtx, NativeObject, t.NativeObject, (completion) ? 1 : 0, ref v) == 0)
throw new ModelEvaluationFailedException();
else
return Expr.Create(Context, v);
}
/// <summary>
/// Alias for <c>Eval</c>.
/// </summary>
public Expr Evaluate(Expr t, bool completion = false)
{
Contract.Requires(t != null);
Contract.Ensures(Contract.Result<Expr>() != null);
return Eval(t, completion);
}
/// <summary>
/// The number of uninterpreted sorts that the model has an interpretation for.
/// </summary>
public uint NumSorts { get { return Native.Z3_model_get_num_sorts(Context.nCtx, NativeObject); } }
/// <summary>
/// The uninterpreted sorts that the model has an interpretation for.
/// </summary>
/// <remarks>
/// Z3 also provides an intepretation for uninterpreted sorts used in a formula.
/// The interpretation for a sort is a finite set of distinct values. We say this finite set is
/// the "universe" of the sort.
/// </remarks>
/// <seealso cref="NumSorts"/>
/// <seealso cref="SortUniverse"/>
public Sort[] Sorts
{
get
{
Contract.Ensures(Contract.Result<Sort[]>() != null);
uint n = NumSorts;
Sort[] res = new Sort[n];
for (uint i = 0; i < n; i++)
res[i] = Sort.Create(Context, Native.Z3_model_get_sort(Context.nCtx, NativeObject, i));
return res;
}
}
/// <summary>
/// The finite set of distinct values that represent the interpretation for sort <paramref name="s"/>.
/// </summary>
/// <seealso cref="Sorts"/>
/// <param name="s">An uninterpreted sort</param>
/// <returns>An array of expressions, where each is an element of the universe of <paramref name="s"/></returns>
public Expr[] SortUniverse(Sort s)
{
Contract.Requires(s != null);
Contract.Ensures(Contract.Result<Expr[]>() != null);
ASTVector nUniv = new ASTVector(Context, Native.Z3_model_get_sort_universe(Context.nCtx, NativeObject, s.NativeObject));
uint n = nUniv.Size;
Expr[] res = new Expr[n];
for (uint i = 0; i < n; i++)
res[i] = Expr.Create(Context, nUniv[i].NativeObject);
return res;
}
/// <summary>
/// Conversion of models to strings.
/// </summary>
/// <returns>A string representation of the model.</returns>
public override string ToString()
{
return Native.Z3_model_to_string(Context.nCtx, NativeObject);
}
#region Internal
internal Model(Context ctx, IntPtr obj)
: base(ctx, obj)
{
Contract.Requires(ctx != null);
}
internal class DecRefQueue : Z3.DecRefQueue
{
public override void IncRef(Context ctx, IntPtr obj)
{
Native.Z3_model_inc_ref(ctx.nCtx, obj);
}
public override void DecRef(Context ctx, IntPtr obj)
{
Native.Z3_model_dec_ref(ctx.nCtx, obj);
}
};
internal override void IncRef(IntPtr o)
{
Context.Model_DRQ.IncAndClear(Context, o);
base.IncRef(o);
}
internal override void DecRef(IntPtr o)
{
Context.Model_DRQ.Add(o);
base.DecRef(o);
}
#endregion
}
}