/*++ 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 { /// /// A Model contains interpretations (assignments) of constants and functions. /// [ContractVerification(true)] public class Model : Z3Object { /// /// Retrieves the interpretation (the assignment) of in the model. /// /// A Constant /// An expression if the constant has an interpretation in the model, null otherwise. public Expr ConstInterp(Expr a) { Contract.Requires(a != null); Context.CheckContextMatch(a); return ConstInterp(a.FuncDecl); } /// /// Retrieves the interpretation (the assignment) of in the model. /// /// A function declaration of zero arity /// An expression if the function has an interpretation in the model, null otherwise. 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); } /// /// Retrieves the interpretation (the assignment) of a non-constant in the model. /// /// A function declaration of non-zero arity /// A FunctionInterpretation if the function has an interpretation in the model, null otherwise. 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); } } /// /// The number of constants that have an interpretation in the model. /// public uint NumConsts { get { return Native.Z3_model_get_num_consts(Context.nCtx, NativeObject); } } /// /// The function declarations of the constants in the model. /// public FuncDecl[] ConstDecls { get { Contract.Ensures(Contract.Result() != 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; } } /// /// The number of function interpretations in the model. /// public uint NumFuncs { get { return Native.Z3_model_get_num_funcs(Context.nCtx, NativeObject); } } /// /// The function declarations of the function interpretations in the model. /// public FuncDecl[] FuncDecls { get { Contract.Ensures(Contract.Result() != 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; } } /// /// All symbols that have an interpretation in the model. /// public FuncDecl[] Decls { get { Contract.Ensures(Contract.Result() != 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; } } /// /// A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. /// public class ModelEvaluationFailedException : Z3Exception { /// /// An exception that is thrown when model evaluation fails. /// public ModelEvaluationFailedException() : base() { } } /// /// Evaluates the expression in the current model. /// /// /// This function may fail if contains quantifiers, /// is partial (MODEL_PARTIAL enabled), or if is not well-sorted. /// In this case a ModelEvaluationFailedException is thrown. /// /// An expression /// /// 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. /// /// The evaluation of in the model. public Expr Eval(Expr t, bool completion = false) { Contract.Requires(t != null); Contract.Ensures(Contract.Result() != 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); } /// /// Alias for Eval. /// public Expr Evaluate(Expr t, bool completion = false) { Contract.Requires(t != null); Contract.Ensures(Contract.Result() != null); return Eval(t, completion); } /// /// The number of uninterpreted sorts that the model has an interpretation for. /// public uint NumSorts { get { return Native.Z3_model_get_num_sorts(Context.nCtx, NativeObject); } } /// /// The uninterpreted sorts that the model has an interpretation for. /// /// /// 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. /// /// /// public Sort[] Sorts { get { Contract.Ensures(Contract.Result() != 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; } } /// /// The finite set of distinct values that represent the interpretation for sort . /// /// /// An uninterpreted sort /// An array of expressions, where each is an element of the universe of public Expr[] SortUniverse(Sort s) { Contract.Requires(s != null); Contract.Ensures(Contract.Result() != 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; } /// /// Conversion of models to strings. /// /// A string representation of the model. 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 } }