/*++ Copyright (c) 2012 Microsoft Corporation Module Name: Context.cs Abstract: Z3 Managed API: Context Author: Christoph Wintersteiger (cwinter) 2012-03-15 Notes: --*/ using System; using System.Diagnostics; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Linq; namespace Microsoft.Z3 { /// /// The main interaction with Z3 happens via the Context. /// public class Context : IDisposable { #region Constructors /// /// Constructor. /// public Context() : base() { lock (creation_lock) { m_ctx = Native.Z3_mk_context_rc(IntPtr.Zero); InitContext(); } } /// /// Constructor. /// /// /// The following parameters can be set: /// - proof (Boolean) Enable proof generation /// - debug_ref_count (Boolean) Enable debug support for Z3_ast reference counting /// - trace (Boolean) Tracing support for VCC /// - trace_file_name (String) Trace out file for VCC traces /// - timeout (unsigned) default timeout (in milliseconds) used for solvers /// - well_sorted_check type checker /// - auto_config use heuristics to automatically select solver and configure it /// - model model generation for solvers, this parameter can be overwritten when creating a solver /// - model_validate validate models produced by solvers /// - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver /// Note that in previous versions of Z3, this constructor was also used to set global and module parameters. /// For this purpose we should now use /// public Context(Dictionary settings) : base() { Debug.Assert(settings != null); lock (creation_lock) { IntPtr cfg = Native.Z3_mk_config(); foreach (KeyValuePair kv in settings) Native.Z3_set_param_value(cfg, kv.Key, kv.Value); m_ctx = Native.Z3_mk_context_rc(cfg); Native.Z3_del_config(cfg); InitContext(); } } #endregion #region Symbols /// /// Creates a new symbol using an integer. /// /// /// Not all integers can be passed to this function. /// The legal range of unsigned integers is 0 to 2^30-1. /// public IntSymbol MkSymbol(int i) { return new IntSymbol(this, i); } /// /// Create a symbol using a string. /// public StringSymbol MkSymbol(string name) { return new StringSymbol(this, name); } /// /// Create an array of symbols. /// internal Symbol[] MkSymbols(string[] names) { if (names == null) return null; Symbol[] result = new Symbol[names.Length]; for (int i = 0; i < names.Length; ++i) result[i] = MkSymbol(names[i]); return result; } #endregion #region Sorts private BoolSort m_boolSort = null; private IntSort m_intSort = null; private RealSort m_realSort = null; private SeqSort m_stringSort = null; private CharSort m_charSort = null; /// /// Retrieves the Boolean sort of the context. /// public BoolSort BoolSort { get { if (m_boolSort == null) m_boolSort = new BoolSort(this); return m_boolSort; } } /// /// Retrieves the Integer sort of the context. /// public IntSort IntSort { get { if (m_intSort == null) m_intSort = new IntSort(this); return m_intSort; } } /// /// Retrieves the Real sort of the context. /// public RealSort RealSort { get { if (m_realSort == null) m_realSort = new RealSort(this); return m_realSort; } } /// /// Retrieves the String sort of the context. /// public CharSort CharSort { get { if (m_charSort == null) m_charSort = new CharSort(this); return m_charSort; } } /// /// Retrieves the String sort of the context. /// public SeqSort StringSort { get { if (m_stringSort == null) m_stringSort = new SeqSort(this, Native.Z3_mk_string_sort(nCtx)); return m_stringSort; } } /// /// Create a new Boolean sort. /// public BoolSort MkBoolSort() { return new BoolSort(this); } /// /// Create a new uninterpreted sort. /// public UninterpretedSort MkUninterpretedSort(Symbol s) { Debug.Assert(s != null); CheckContextMatch(s); return new UninterpretedSort(this, s); } /// /// Create a new uninterpreted sort. /// public UninterpretedSort MkUninterpretedSort(string str) { return MkUninterpretedSort(MkSymbol(str)); } /// /// Create a new integer sort. /// public IntSort MkIntSort() { return new IntSort(this); } /// /// Create a real sort. /// public RealSort MkRealSort() { return new RealSort(this); } /// /// Create a new bit-vector sort. /// public BitVecSort MkBitVecSort(uint size) { return new BitVecSort(this, Native.Z3_mk_bv_sort(nCtx, size)); } /// /// Create a new sequence sort. /// public SeqSort MkSeqSort(Sort s) { Debug.Assert(s != null); return new SeqSort(this, Native.Z3_mk_seq_sort(nCtx, s.NativeObject)); } /// /// Create a new regular expression sort. /// public ReSort MkReSort(SeqSort s) { Debug.Assert(s != null); return new ReSort(this, Native.Z3_mk_re_sort(nCtx, s.NativeObject)); } /// /// Create a new array sort. /// public ArraySort MkArraySort(Sort domain, Sort range) { Debug.Assert(domain != null); Debug.Assert(range != null); CheckContextMatch(domain); CheckContextMatch(range); return new ArraySort(this, domain, range); } /// /// Create a new n-ary array sort. /// public ArraySort MkArraySort(Sort[] domain, Sort range) { Debug.Assert(domain != null); Debug.Assert(range != null); CheckContextMatch(domain); CheckContextMatch(range); return new ArraySort(this, domain, range); } /// /// Create a new tuple sort. /// public TupleSort MkTupleSort(Symbol name, Symbol[] fieldNames, Sort[] fieldSorts) { Debug.Assert(name != null); Debug.Assert(fieldNames != null); Debug.Assert(fieldNames.All(fn => fn != null)); Debug.Assert(fieldSorts == null || fieldSorts.All(fs => fs != null)); CheckContextMatch(name); CheckContextMatch(fieldNames); CheckContextMatch(fieldSorts); return new TupleSort(this, name, (uint)fieldNames.Length, fieldNames, fieldSorts); } /// /// Create a new enumeration sort. /// public EnumSort MkEnumSort(Symbol name, params Symbol[] enumNames) { Debug.Assert(name != null); Debug.Assert(enumNames != null); Debug.Assert(enumNames.All(f => f != null)); CheckContextMatch(name); CheckContextMatch(enumNames); return new EnumSort(this, name, enumNames); } /// /// Create a new enumeration sort. /// public EnumSort MkEnumSort(string name, params string[] enumNames) { Debug.Assert(enumNames != null); return new EnumSort(this, MkSymbol(name), MkSymbols(enumNames)); } /// /// Create a new list sort. /// public ListSort MkListSort(Symbol name, Sort elemSort) { Debug.Assert(name != null); Debug.Assert(elemSort != null); CheckContextMatch(name); CheckContextMatch(elemSort); return new ListSort(this, name, elemSort); } /// /// Create a new list sort. /// public ListSort MkListSort(string name, Sort elemSort) { Debug.Assert(elemSort != null); CheckContextMatch(elemSort); return new ListSort(this, MkSymbol(name), elemSort); } /// /// Create a new finite domain sort. /// The result is a sort /// /// The name used to identify the sort /// The size of the sort public FiniteDomainSort MkFiniteDomainSort(Symbol name, ulong size) { Debug.Assert(name != null); CheckContextMatch(name); return new FiniteDomainSort(this, name, size); } /// /// Create a new finite domain sort. /// The result is a sort /// Elements of the sort are created using , /// and the elements range from 0 to size-1. /// /// The name used to identify the sort /// The size of the sort public FiniteDomainSort MkFiniteDomainSort(string name, ulong size) { return new FiniteDomainSort(this, MkSymbol(name), size); } #region Datatypes /// /// Create a datatype constructor. /// /// constructor name /// name of recognizer function. /// names of the constructor fields. /// field sorts, 0 if the field sort refers to a recursive sort. /// reference to datatype sort that is an argument to the constructor; /// if the corresponding sort reference is 0, then the value in sort_refs should be an index /// referring to one of the recursive datatypes that is declared. public Constructor MkConstructor(Symbol name, Symbol recognizer, Symbol[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null) { Debug.Assert(name != null); Debug.Assert(recognizer != null); return new Constructor(this, name, recognizer, fieldNames, sorts, sortRefs); } /// /// Create a datatype constructor. /// /// /// /// /// /// /// public Constructor MkConstructor(string name, string recognizer, string[] fieldNames = null, Sort[] sorts = null, uint[] sortRefs = null) { return new Constructor(this, MkSymbol(name), MkSymbol(recognizer), MkSymbols(fieldNames), sorts, sortRefs); } /// /// Create a new datatype sort. /// public DatatypeSort MkDatatypeSort(Symbol name, Constructor[] constructors) { Debug.Assert(name != null); Debug.Assert(constructors != null); Debug.Assert(constructors.All(c => c != null)); CheckContextMatch(name); CheckContextMatch(constructors); return new DatatypeSort(this, name, constructors); } /// /// Create a new datatype sort. /// public DatatypeSort MkDatatypeSort(string name, Constructor[] constructors) { Debug.Assert(constructors != null); Debug.Assert(constructors.All(c => c != null)); CheckContextMatch(constructors); return new DatatypeSort(this, MkSymbol(name), constructors); } /// /// Create mutually recursive datatypes. /// /// names of datatype sorts /// list of constructors, one list per sort. public DatatypeSort[] MkDatatypeSorts(Symbol[] names, Constructor[][] c) { Debug.Assert(names != null); Debug.Assert(c != null); Debug.Assert(names.Length == c.Length); //Debug.Assert(Contract.ForAll(0, c.Length, j => c[j] != null)); Debug.Assert(names.All(name => name != null)); CheckContextMatch(names); uint n = (uint)names.Length; ConstructorList[] cla = new ConstructorList[n]; IntPtr[] n_constr = new IntPtr[n]; for (uint i = 0; i < n; i++) { Constructor[] constructor = c[i]; CheckContextMatch(constructor); cla[i] = new ConstructorList(this, constructor); n_constr[i] = cla[i].NativeObject; } IntPtr[] n_res = new IntPtr[n]; Native.Z3_mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), n_res, n_constr); DatatypeSort[] res = new DatatypeSort[n]; for (uint i = 0; i < n; i++) res[i] = new DatatypeSort(this, n_res[i]); return res; } /// /// Create mutually recursive data-types. /// /// /// /// public DatatypeSort[] MkDatatypeSorts(string[] names, Constructor[][] c) { Debug.Assert(names != null); Debug.Assert(c != null); Debug.Assert(names.Length == c.Length); //Debug.Assert(Contract.ForAll(0, c.Length, j => c[j] != null)); //Debug.Assert(names.All(name => name != null)); return MkDatatypeSorts(MkSymbols(names), c); } /// /// Update a datatype field at expression t with value v. /// The function performs a record update at t. The field /// 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) { return Expr.Create(this, Native.Z3_datatype_update_field( nCtx, field.NativeObject, t.NativeObject, v.NativeObject)); } #endregion #endregion #region Function Declarations /// /// Creates a new function declaration. /// public FuncDecl MkFuncDecl(Symbol name, Sort[] domain, Sort range) { Debug.Assert(name != null); Debug.Assert(range != null); Debug.Assert(domain.All(d => d != null)); CheckContextMatch(name); CheckContextMatch(domain); CheckContextMatch(range); return new FuncDecl(this, name, domain, range); } /// /// Creates a new function declaration. /// public FuncDecl MkFuncDecl(Symbol name, Sort domain, Sort range) { Debug.Assert(name != null); Debug.Assert(domain != null); Debug.Assert(range != null); CheckContextMatch(name); CheckContextMatch(domain); CheckContextMatch(range); Sort[] q = new Sort[] { domain }; return new FuncDecl(this, name, q, range); } /// /// Creates a new function declaration. /// public FuncDecl MkFuncDecl(string name, Sort[] domain, Sort range) { Debug.Assert(range != null); Debug.Assert(domain.All(d => d != null)); CheckContextMatch(domain); CheckContextMatch(range); return new FuncDecl(this, MkSymbol(name), domain, range); } /// /// Creates a new recursive function declaration. /// public FuncDecl MkRecFuncDecl(string name, Sort[] domain, Sort range) { Debug.Assert(range != null); Debug.Assert(domain.All(d => d != null)); CheckContextMatch(domain); CheckContextMatch(range); return new FuncDecl(this, MkSymbol(name), domain, range, true); } /// /// Bind a definition to a recursive function declaration. /// The function must have previously been created using /// MkRecFuncDecl. The body may contain recursive uses of the function or /// other mutually recursive functions. /// public void AddRecDef(FuncDecl f, Expr[] args, Expr body) { CheckContextMatch(f); CheckContextMatch(args); CheckContextMatch(body); IntPtr[] argsNative = AST.ArrayToNative(args); Native.Z3_add_rec_def(nCtx, f.NativeObject, (uint)args.Length, argsNative, body.NativeObject); } /// /// Creates a new function declaration. /// public FuncDecl MkFuncDecl(string name, Sort domain, Sort range) { Debug.Assert(range != null); Debug.Assert(domain != null); CheckContextMatch(domain); CheckContextMatch(range); Sort[] q = new Sort[] { domain }; return new FuncDecl(this, MkSymbol(name), q, range); } /// /// Creates a fresh function declaration with a name prefixed with . /// /// /// public FuncDecl MkFreshFuncDecl(string prefix, Sort[] domain, Sort range) { Debug.Assert(range != null); Debug.Assert(domain.All(d => d != null)); CheckContextMatch(domain); CheckContextMatch(range); return new FuncDecl(this, prefix, domain, range); } /// /// Creates a new constant function declaration. /// public FuncDecl MkConstDecl(Symbol name, Sort range) { Debug.Assert(name != null); Debug.Assert(range != null); CheckContextMatch(name); CheckContextMatch(range); return new FuncDecl(this, name, null, range); } /// /// Creates a new constant function declaration. /// public FuncDecl MkConstDecl(string name, Sort range) { Debug.Assert(range != null); CheckContextMatch(range); return new FuncDecl(this, MkSymbol(name), null, range); } /// /// Creates a fresh constant function declaration with a name prefixed with . /// /// /// public FuncDecl MkFreshConstDecl(string prefix, Sort range) { Debug.Assert(range != null); CheckContextMatch(range); return new FuncDecl(this, prefix, null, range); } #endregion #region Bound Variables /// /// Creates a new bound variable. /// /// The de-Bruijn index of the variable /// The sort of the variable public Expr MkBound(uint index, Sort ty) { Debug.Assert(ty != null); return Expr.Create(this, Native.Z3_mk_bound(nCtx, index, ty.NativeObject)); } #endregion #region Quantifier Patterns /// /// Create a quantifier pattern. /// public Pattern MkPattern(params Expr[] terms) { Debug.Assert(terms != null); if (terms.Length == 0) throw new Z3Exception("Cannot create a pattern from zero terms"); IntPtr[] termsNative = AST.ArrayToNative(terms); return new Pattern(this, Native.Z3_mk_pattern(nCtx, (uint)terms.Length, termsNative)); } #endregion #region Constants /// /// Creates a new Constant of sort and named . /// public Expr MkConst(Symbol name, Sort range) { Debug.Assert(name != null); Debug.Assert(range != null); CheckContextMatch(name); CheckContextMatch(range); return Expr.Create(this, Native.Z3_mk_const(nCtx, name.NativeObject, range.NativeObject)); } /// /// Creates a new Constant of sort and named . /// public Expr MkConst(string name, Sort range) { Debug.Assert(range != null); return MkConst(MkSymbol(name), range); } /// /// Creates a fresh Constant of sort and a /// name prefixed with . /// public Expr MkFreshConst(string prefix, Sort range) { Debug.Assert(range != null); CheckContextMatch(range); return Expr.Create(this, Native.Z3_mk_fresh_const(nCtx, prefix, range.NativeObject)); } /// /// Creates a fresh constant from the FuncDecl . /// /// A decl of a 0-arity function public Expr MkConst(FuncDecl f) { Debug.Assert(f != null); return MkApp(f); } /// /// Create a Boolean constant. /// public BoolExpr MkBoolConst(Symbol name) { Debug.Assert(name != null); return (BoolExpr)MkConst(name, BoolSort); } /// /// Create a Boolean constant. /// public BoolExpr MkBoolConst(string name) { return (BoolExpr)MkConst(MkSymbol(name), BoolSort); } /// /// Creates an integer constant. /// public IntExpr MkIntConst(Symbol name) { Debug.Assert(name != null); return (IntExpr)MkConst(name, IntSort); } /// /// Creates an integer constant. /// public IntExpr MkIntConst(string name) { Debug.Assert(name != null); return (IntExpr)MkConst(name, IntSort); } /// /// Creates a real constant. /// public RealExpr MkRealConst(Symbol name) { Debug.Assert(name != null); return (RealExpr)MkConst(name, RealSort); } /// /// Creates a real constant. /// public RealExpr MkRealConst(string name) { return (RealExpr)MkConst(name, RealSort); } /// /// Creates a bit-vector constant. /// public BitVecExpr MkBVConst(Symbol name, uint size) { Debug.Assert(name != null); return (BitVecExpr)MkConst(name, MkBitVecSort(size)); } /// /// Creates a bit-vector constant. /// public BitVecExpr MkBVConst(string name, uint size) { return (BitVecExpr)MkConst(name, MkBitVecSort(size)); } #endregion #region Terms /// /// Create a new function application. /// public Expr MkApp(FuncDecl f, params Expr[] args) { Debug.Assert(f != null); Debug.Assert(args == null || args.All(a => a != null)); CheckContextMatch(f); CheckContextMatch(args); return Expr.Create(this, f, args); } /// /// Create a new function application. /// public Expr MkApp(FuncDecl f, IEnumerable args) { Debug.Assert(f != null); Debug.Assert(args == null || args.All( a => a != null)); CheckContextMatch(f); CheckContextMatch(args); return Expr.Create(this, f, args.ToArray()); } #region Propositional /// /// The true Term. /// public BoolExpr MkTrue() { return new BoolExpr(this, Native.Z3_mk_true(nCtx)); } /// /// The false Term. /// public BoolExpr MkFalse() { return new BoolExpr(this, Native.Z3_mk_false(nCtx)); } /// /// Creates a Boolean value. /// public BoolExpr MkBool(bool value) { return value ? MkTrue() : MkFalse(); } /// /// Creates the equality = . /// public BoolExpr MkEq(Expr x, Expr y) { Debug.Assert(x != null); Debug.Assert(y != null); CheckContextMatch(x); CheckContextMatch(y); return new BoolExpr(this, Native.Z3_mk_eq(nCtx, x.NativeObject, y.NativeObject)); } /// /// Creates a distinct term. /// public BoolExpr MkDistinct(params Expr[] args) { Debug.Assert(args != null); Debug.Assert(args.All(a => a != null)); CheckContextMatch(args); return new BoolExpr(this, Native.Z3_mk_distinct(nCtx, (uint)args.Length, AST.ArrayToNative(args))); } /// /// Mk an expression representing not(a). /// public BoolExpr MkNot(BoolExpr a) { Debug.Assert(a != null); CheckContextMatch(a); return new BoolExpr(this, Native.Z3_mk_not(nCtx, a.NativeObject)); } /// /// Create an expression representing an if-then-else: ite(t1, t2, t3). /// /// An expression with Boolean sort /// An expression /// An expression with the same sort as public Expr MkITE(BoolExpr t1, Expr t2, Expr t3) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); Debug.Assert(t3 != null); CheckContextMatch(t1); CheckContextMatch(t2); CheckContextMatch(t3); return Expr.Create(this, Native.Z3_mk_ite(nCtx, t1.NativeObject, t2.NativeObject, t3.NativeObject)); } /// /// Create an expression representing t1 iff t2. /// public BoolExpr MkIff(BoolExpr t1, BoolExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_iff(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an expression representing t1 -> t2. /// public BoolExpr MkImplies(BoolExpr t1, BoolExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_implies(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an expression representing t1 xor t2. /// public BoolExpr MkXor(BoolExpr t1, BoolExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_xor(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an expression representing t1 xor t2 xor t3 ... . /// public BoolExpr MkXor(IEnumerable ts) { Debug.Assert(ts != null); Debug.Assert(ts.All(a => a != null)); CheckContextMatch(ts); BoolExpr r = null; foreach (var t in ts) { if (r == null) r = t; else r = MkXor(r, t); } if (r == null) r = MkTrue(); return r; } /// /// Create an expression representing t[0] and t[1] and .... /// public BoolExpr MkAnd(params BoolExpr[] t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); return new BoolExpr(this, Native.Z3_mk_and(nCtx, (uint)t.Length, AST.ArrayToNative(t))); } /// /// Create an expression representing t[0] and t[1] and .... /// public BoolExpr MkAnd(IEnumerable t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); var ands = t.ToArray(); return new BoolExpr(this, Native.Z3_mk_and(nCtx, (uint)t.Count(), AST.ArrayToNative(ands))); } /// /// Create an expression representing t[0] or t[1] or .... /// public BoolExpr MkOr(params BoolExpr[] t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); return new BoolExpr(this, Native.Z3_mk_or(nCtx, (uint)t.Length, AST.ArrayToNative(t))); } /// /// Create an expression representing t[0] or t[1] or .... /// public BoolExpr MkOr(IEnumerable t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); var ts = t.ToArray(); return new BoolExpr(this, Native.Z3_mk_or(nCtx, (uint)ts.Length, AST.ArrayToNative(ts))); } #endregion #region Arithmetic /// /// Create an expression representing t[0] + t[1] + .... /// public ArithExpr MkAdd(params ArithExpr[] t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); return (ArithExpr)Expr.Create(this, Native.Z3_mk_add(nCtx, (uint)t.Length, AST.ArrayToNative(t))); } /// /// Create an expression representing t[0] + t[1] + .... /// public ArithExpr MkAdd(IEnumerable t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); var ts = t.ToArray(); return (ArithExpr)Expr.Create(this, Native.Z3_mk_add(nCtx, (uint)ts.Length, AST.ArrayToNative(ts))); } /// /// Create an expression representing t[0] * t[1] * .... /// public ArithExpr MkMul(params ArithExpr[] t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); var ts = t.ToArray(); return (ArithExpr)Expr.Create(this, Native.Z3_mk_mul(nCtx, (uint)ts.Length, AST.ArrayToNative(ts))); } /// /// Create an expression representing t[0] * t[1] * .... /// public ArithExpr MkMul(IEnumerable t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); var ts = t.ToArray(); return (ArithExpr)Expr.Create(this, Native.Z3_mk_mul(nCtx, (uint)ts.Length, AST.ArrayToNative(ts))); } /// /// Create an expression representing t[0] - t[1] - .... /// public ArithExpr MkSub(params ArithExpr[] t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); return (ArithExpr)Expr.Create(this, Native.Z3_mk_sub(nCtx, (uint)t.Length, AST.ArrayToNative(t))); } /// /// Create an expression representing -t. /// public ArithExpr MkUnaryMinus(ArithExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return (ArithExpr)Expr.Create(this, Native.Z3_mk_unary_minus(nCtx, t.NativeObject)); } /// /// Create an expression representing t1 / t2. /// public ArithExpr MkDiv(ArithExpr t1, ArithExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return (ArithExpr)Expr.Create(this, Native.Z3_mk_div(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an expression representing t1 mod t2. /// /// The arguments must have int type. public IntExpr MkMod(IntExpr t1, IntExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new IntExpr(this, Native.Z3_mk_mod(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an expression representing t1 rem t2. /// /// The arguments must have int type. public IntExpr MkRem(IntExpr t1, IntExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new IntExpr(this, Native.Z3_mk_rem(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an expression representing t1 ^ t2. /// public ArithExpr MkPower(ArithExpr t1, ArithExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return (ArithExpr)Expr.Create(this, Native.Z3_mk_power(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an expression representing t1 < t2 /// public BoolExpr MkLt(ArithExpr t1, ArithExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_lt(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an expression representing t1 <= t2 /// public BoolExpr MkLe(ArithExpr t1, ArithExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_le(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an expression representing t1 > t2 /// public BoolExpr MkGt(ArithExpr t1, ArithExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_gt(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an expression representing t1 >= t2 /// public BoolExpr MkGe(ArithExpr t1, ArithExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_ge(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Coerce an integer to a real. /// /// /// There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard. /// /// You can take the floor of a real by creating an auxiliary integer Term k and /// and asserting MakeInt2Real(k) <= t1 < MkInt2Real(k)+1. /// The argument must be of integer sort. /// public RealExpr MkInt2Real(IntExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new RealExpr(this, Native.Z3_mk_int2real(nCtx, t.NativeObject)); } /// /// Coerce a real to an integer. /// /// /// The semantics of this function follows the SMT-LIB standard for the function to_int. /// The argument must be of real sort. /// public IntExpr MkReal2Int(RealExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new IntExpr(this, Native.Z3_mk_real2int(nCtx, t.NativeObject)); } /// /// Creates an expression that checks whether a real number is an integer. /// public BoolExpr MkIsInteger(RealExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BoolExpr(this, Native.Z3_mk_is_int(nCtx, t.NativeObject)); } #endregion #region Bit-vectors /// /// Bitwise negation. /// /// The argument must have a bit-vector sort. public BitVecExpr MkBVNot(BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_bvnot(nCtx, t.NativeObject)); } /// /// Take conjunction of bits in a vector, return vector of length 1. /// /// The argument must have a bit-vector sort. public BitVecExpr MkBVRedAND(BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_bvredand(nCtx, t.NativeObject)); } /// /// Take disjunction of bits in a vector, return vector of length 1. /// /// The argument must have a bit-vector sort. public BitVecExpr MkBVRedOR(BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_bvredor(nCtx, t.NativeObject)); } /// /// Bitwise conjunction. /// /// The arguments must have a bit-vector sort. public BitVecExpr MkBVAND(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvand(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Bitwise disjunction. /// /// The arguments must have a bit-vector sort. public BitVecExpr MkBVOR(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvor(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Bitwise XOR. /// /// The arguments must have a bit-vector sort. public BitVecExpr MkBVXOR(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvxor(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Bitwise NAND. /// /// The arguments must have a bit-vector sort. public BitVecExpr MkBVNAND(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvnand(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Bitwise NOR. /// /// The arguments must have a bit-vector sort. public BitVecExpr MkBVNOR(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvnor(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Bitwise XNOR. /// /// The arguments must have a bit-vector sort. public BitVecExpr MkBVXNOR(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvxnor(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Standard two's complement unary minus. /// /// The arguments must have a bit-vector sort. public BitVecExpr MkBVNeg(BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_bvneg(nCtx, t.NativeObject)); } /// /// Two's complement addition. /// /// The arguments must have the same bit-vector sort. public BitVecExpr MkBVAdd(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvadd(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Two's complement subtraction. /// /// The arguments must have the same bit-vector sort. public BitVecExpr MkBVSub(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvsub(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Two's complement multiplication. /// /// The arguments must have the same bit-vector sort. public BitVecExpr MkBVMul(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvmul(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Unsigned division. /// /// /// It is defined as the floor of t1/t2 if \c t2 is /// different from zero. If t2 is zero, then the result /// is undefined. /// The arguments must have the same bit-vector sort. /// public BitVecExpr MkBVUDiv(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvudiv(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Signed division. /// /// /// It is defined in the following way: /// /// - The \c floor of t1/t2 if \c t2 is different from zero, and t1*t2 >= 0. /// /// - The \c ceiling of t1/t2 if \c t2 is different from zero, and t1*t2 < 0. /// /// If t2 is zero, then the result is undefined. /// The arguments must have the same bit-vector sort. /// public BitVecExpr MkBVSDiv(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvsdiv(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Unsigned remainder. /// /// /// It is defined as t1 - (t1 /u t2) * t2, where /u represents unsigned division. /// If t2 is zero, then the result is undefined. /// The arguments must have the same bit-vector sort. /// public BitVecExpr MkBVURem(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvurem(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Signed remainder. /// /// /// It is defined as t1 - (t1 /s t2) * t2, where /s represents signed division. /// The most significant bit (sign) of the result is equal to the most significant bit of \c t1. /// /// If t2 is zero, then the result is undefined. /// The arguments must have the same bit-vector sort. /// public BitVecExpr MkBVSRem(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvsrem(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Two's complement signed remainder (sign follows divisor). /// /// /// If t2 is zero, then the result is undefined. /// The arguments must have the same bit-vector sort. /// public BitVecExpr MkBVSMod(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvsmod(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Unsigned less-than /// /// /// The arguments must have the same bit-vector sort. /// public BoolExpr MkBVULT(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvult(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Two's complement signed less-than /// /// /// The arguments must have the same bit-vector sort. /// public BoolExpr MkBVSLT(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvslt(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Unsigned less-than or equal to. /// /// /// The arguments must have the same bit-vector sort. /// public BoolExpr MkBVULE(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvule(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Two's complement signed less-than or equal to. /// /// /// The arguments must have the same bit-vector sort. /// public BoolExpr MkBVSLE(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvsle(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Unsigned greater than or equal to. /// /// /// The arguments must have the same bit-vector sort. /// public BoolExpr MkBVUGE(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvuge(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Two's complement signed greater than or equal to. /// /// /// The arguments must have the same bit-vector sort. /// public BoolExpr MkBVSGE(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvsge(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Unsigned greater-than. /// /// /// The arguments must have the same bit-vector sort. /// public BoolExpr MkBVUGT(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvugt(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Two's complement signed greater-than. /// /// /// The arguments must have the same bit-vector sort. /// public BoolExpr MkBVSGT(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvsgt(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Bit-vector concatenation. /// /// /// The arguments must have a bit-vector sort. /// /// /// The result is a bit-vector of size n1+n2, where n1 (n2) /// is the size of t1 (t2). /// public BitVecExpr MkConcat(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_concat(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Bit-vector extraction. /// /// /// Extract the bits down to from a bitvector of /// size m to yield a new bitvector of size n, where /// n = high - low + 1. /// The argument must have a bit-vector sort. /// public BitVecExpr MkExtract(uint high, uint low, BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_extract(nCtx, high, low, t.NativeObject)); } /// /// Bit-vector sign extension. /// /// /// Sign-extends the given bit-vector to the (signed) equivalent bitvector of /// size m+i, where \c m is the size of the given bit-vector. /// The argument must have a bit-vector sort. /// public BitVecExpr MkSignExt(uint i, BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_sign_ext(nCtx, i, t.NativeObject)); } /// /// Bit-vector zero extension. /// /// /// Extend the given bit-vector with zeros to the (unsigned) equivalent /// bitvector of size m+i, where \c m is the size of the /// given bit-vector. /// The argument must have a bit-vector sort. /// public BitVecExpr MkZeroExt(uint i, BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_zero_ext(nCtx, i, t.NativeObject)); } /// /// Bit-vector repetition. /// /// /// The argument must have a bit-vector sort. /// public BitVecExpr MkRepeat(uint i, BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_repeat(nCtx, i, t.NativeObject)); } /// /// Shift left. /// /// /// It is equivalent to multiplication by 2^x where \c x is the value of . /// /// NB. The semantics of shift operations varies between environments. This /// definition does not necessarily capture directly the semantics of the /// programming language or assembly architecture you are modeling. /// /// The arguments must have a bit-vector sort. /// public BitVecExpr MkBVSHL(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvshl(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Logical shift right /// /// /// It is equivalent to unsigned division by 2^x where \c x is the value of . /// /// NB. The semantics of shift operations varies between environments. This /// definition does not necessarily capture directly the semantics of the /// programming language or assembly architecture you are modeling. /// /// The arguments must have a bit-vector sort. /// public BitVecExpr MkBVLSHR(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvlshr(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Arithmetic shift right /// /// /// It is like logical shift right except that the most significant /// bits of the result always copy the most significant bit of the /// second argument. /// /// NB. The semantics of shift operations varies between environments. This /// definition does not necessarily capture directly the semantics of the /// programming language or assembly architecture you are modeling. /// /// The arguments must have a bit-vector sort. /// public BitVecExpr MkBVASHR(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_bvashr(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Rotate Left. /// /// /// Rotate bits of \c t to the left \c i times. /// The argument must have a bit-vector sort. /// public BitVecExpr MkBVRotateLeft(uint i, BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_rotate_left(nCtx, i, t.NativeObject)); } /// /// Rotate Right. /// /// /// Rotate bits of \c t to the right \c i times. /// The argument must have a bit-vector sort. /// public BitVecExpr MkBVRotateRight(uint i, BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_rotate_right(nCtx, i, t.NativeObject)); } /// /// Rotate Left. /// /// /// Rotate bits of to the left times. /// The arguments must have the same bit-vector sort. /// public BitVecExpr MkBVRotateLeft(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_ext_rotate_left(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Rotate Right. /// /// /// Rotate bits of to the right times. /// The arguments must have the same bit-vector sort. /// public BitVecExpr MkBVRotateRight(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BitVecExpr(this, Native.Z3_mk_ext_rotate_right(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create an bit bit-vector from the integer argument . /// /// /// NB. This function is essentially treated as uninterpreted. /// So you cannot expect Z3 to precisely reflect the semantics of this function /// when solving constraints with this function. /// /// The argument must be of integer sort. /// public BitVecExpr MkInt2BV(uint n, IntExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BitVecExpr(this, Native.Z3_mk_int2bv(nCtx, n, t.NativeObject)); } /// /// Create an integer from the bit-vector argument . /// /// /// If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned. /// So the result is non-negative and in the range [0..2^N-1], where /// N are the number of bits in . /// If \c is_signed is true, \c t1 is treated as a signed bit-vector. /// /// NB. This function is essentially treated as uninterpreted. /// So you cannot expect Z3 to precisely reflect the semantics of this function /// when solving constraints with this function. /// /// The argument must be of bit-vector sort. /// public IntExpr MkBV2Int(BitVecExpr t, bool signed) { Debug.Assert(t != null); CheckContextMatch(t); return new IntExpr(this, Native.Z3_mk_bv2int(nCtx, t.NativeObject, (byte)(signed ? 1 : 0))); } /// /// Create a predicate that checks that the bit-wise addition does not overflow. /// /// /// The arguments must be of bit-vector sort. /// public BoolExpr MkBVAddNoOverflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvadd_no_overflow(nCtx, t1.NativeObject, t2.NativeObject, (byte)(isSigned ? 1 : 0))); } /// /// Create a predicate that checks that the bit-wise addition does not underflow. /// /// /// The arguments must be of bit-vector sort. /// public BoolExpr MkBVAddNoUnderflow(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvadd_no_underflow(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create a predicate that checks that the bit-wise subtraction does not overflow. /// /// /// The arguments must be of bit-vector sort. /// public BoolExpr MkBVSubNoOverflow(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvsub_no_overflow(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create a predicate that checks that the bit-wise subtraction does not underflow. /// /// /// The arguments must be of bit-vector sort. /// public BoolExpr MkBVSubNoUnderflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvsub_no_underflow(nCtx, t1.NativeObject, t2.NativeObject, (byte)(isSigned ? 1 : 0))); } /// /// Create a predicate that checks that the bit-wise signed division does not overflow. /// /// /// The arguments must be of bit-vector sort. /// public BoolExpr MkBVSDivNoOverflow(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvsdiv_no_overflow(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create a predicate that checks that the bit-wise negation does not overflow. /// /// /// The arguments must be of bit-vector sort. /// public BoolExpr MkBVNegNoOverflow(BitVecExpr t) { Debug.Assert(t != null); CheckContextMatch(t); return new BoolExpr(this, Native.Z3_mk_bvneg_no_overflow(nCtx, t.NativeObject)); } /// /// Create a predicate that checks that the bit-wise multiplication does not overflow. /// /// /// The arguments must be of bit-vector sort. /// public BoolExpr MkBVMulNoOverflow(BitVecExpr t1, BitVecExpr t2, bool isSigned) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvmul_no_overflow(nCtx, t1.NativeObject, t2.NativeObject, (byte)(isSigned ? 1 : 0))); } /// /// Create a predicate that checks that the bit-wise multiplication does not underflow. /// /// /// The arguments must be of bit-vector sort. /// public BoolExpr MkBVMulNoUnderflow(BitVecExpr t1, BitVecExpr t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new BoolExpr(this, Native.Z3_mk_bvmul_no_underflow(nCtx, t1.NativeObject, t2.NativeObject)); } #endregion #region Arrays /// /// Create an array constant. /// public ArrayExpr MkArrayConst(Symbol name, Sort domain, Sort range) { Debug.Assert(name != null); Debug.Assert(domain != null); Debug.Assert(range != null); return (ArrayExpr)MkConst(name, MkArraySort(domain, range)); } /// /// Create an array constant. /// public ArrayExpr MkArrayConst(string name, Sort domain, Sort range) { Debug.Assert(domain != null); Debug.Assert(range != null); return (ArrayExpr)MkConst(MkSymbol(name), MkArraySort(domain, range)); } /// /// Array read. /// /// /// The argument a is the array and i is the index /// of the array that gets read. /// /// The node a must have an array sort [domain -> range], /// and i must have the sort domain. /// The sort of the result is range. /// /// /// public Expr MkSelect(ArrayExpr a, Expr i) { Debug.Assert(a != null); Debug.Assert(i != null); CheckContextMatch(a); CheckContextMatch(i); return Expr.Create(this, Native.Z3_mk_select(nCtx, a.NativeObject, i.NativeObject)); } /// /// Array read. /// /// /// The argument a is the array and args are the indices /// of the array that gets read. /// /// The node a must have an array sort [domain1,..,domaink -> range], /// and args must have the sort domain1,..,domaink. /// The sort of the result is range. /// /// /// public Expr MkSelect(ArrayExpr a, params Expr[] args) { Debug.Assert(a != null); Debug.Assert(args != null && args.All(n => n != null)); CheckContextMatch(a); CheckContextMatch(args); return Expr.Create(this, Native.Z3_mk_select_n(nCtx, a.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args))); } /// /// Array update. /// /// /// The node a must have an array sort [domain -> range], /// i must have sort domain, /// v must have sort range. The sort of the result is [domain -> 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 a /// (with respect to select) /// on all indices except for i, where it maps to v /// (and the select of a with /// respect to i may be a different value). /// /// /// /// public ArrayExpr MkStore(ArrayExpr a, Expr i, Expr v) { Debug.Assert(a != null); Debug.Assert(i != null); Debug.Assert(v != null); CheckContextMatch(a); CheckContextMatch(i); CheckContextMatch(v); return new ArrayExpr(this, Native.Z3_mk_store(nCtx, a.NativeObject, i.NativeObject, v.NativeObject)); } /// /// Array update. /// /// /// The node a must have an array sort [domain1,..,domaink -> range], /// args must have sort domain1,..,domaink, /// v must have sort range. The sort of the result is [domain -> 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 a /// (with respect to select) /// on all indices except for args, where it maps to v /// (and the select of a with /// respect to args may be a different value). /// /// /// /// public ArrayExpr MkStore(ArrayExpr a, Expr[] args, Expr v) { Debug.Assert(a != null); Debug.Assert(args != null); Debug.Assert(v != null); CheckContextMatch(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)); } /// /// Create a constant array. /// /// /// The resulting term is an array, such that a selecton an arbitrary index /// produces the value v. /// /// /// public ArrayExpr MkConstArray(Sort domain, Expr v) { Debug.Assert(domain != null); Debug.Assert(v != null); CheckContextMatch(domain); CheckContextMatch(v); return new ArrayExpr(this, Native.Z3_mk_const_array(nCtx, domain.NativeObject, v.NativeObject)); } /// /// Maps f on the argument arrays. /// /// /// Each element of args must be of an array sort [domain_i -> range_i]. /// The function declaration f must have type range_1 .. range_n -> range. /// v must have sort range. The sort of the result is [domain_i -> range]. /// /// /// /// public ArrayExpr MkMap(FuncDecl f, params ArrayExpr[] args) { Debug.Assert(f != null); Debug.Assert(args == null || args.All(a => a != null)); CheckContextMatch(f); CheckContextMatch(args); return (ArrayExpr)Expr.Create(this, Native.Z3_mk_map(nCtx, f.NativeObject, AST.ArrayLength(args), AST.ArrayToNative(args))); } /// /// Access the array default value. /// /// /// Produces the default range value, for arrays that can be represented as /// finite maps with a default range value. /// public Expr MkTermArray(ArrayExpr array) { Debug.Assert(array != null); CheckContextMatch(array); return Expr.Create(this, Native.Z3_mk_array_default(nCtx, array.NativeObject)); } /// /// Create Extentionality index. Two arrays are equal if and only if they are equal on the index returned by MkArrayExt. /// public Expr MkArrayExt(ArrayExpr arg1, ArrayExpr arg2) { Debug.Assert(arg1 != null); Debug.Assert(arg2 != null); CheckContextMatch(arg1); CheckContextMatch(arg2); return Expr.Create(this, Native.Z3_mk_array_ext(nCtx, arg1.NativeObject, arg2.NativeObject)); } #endregion #region Sets /// /// Create a set type. /// public SetSort MkSetSort(Sort ty) { Debug.Assert(ty != null); CheckContextMatch(ty); return new SetSort(this, ty); } /// /// Create an empty set. /// public ArrayExpr MkEmptySet(Sort domain) { Debug.Assert(domain != null); CheckContextMatch(domain); return (ArrayExpr)Expr.Create(this, Native.Z3_mk_empty_set(nCtx, domain.NativeObject)); } /// /// Create the full set. /// public ArrayExpr MkFullSet(Sort domain) { Debug.Assert(domain != null); CheckContextMatch(domain); return (ArrayExpr)Expr.Create(this, Native.Z3_mk_full_set(nCtx, domain.NativeObject)); } /// /// Add an element to the set. /// public ArrayExpr MkSetAdd(ArrayExpr set, Expr element) { Debug.Assert(set != null); Debug.Assert(element != null); CheckContextMatch(set); CheckContextMatch(element); return (ArrayExpr)Expr.Create(this, Native.Z3_mk_set_add(nCtx, set.NativeObject, element.NativeObject)); } /// /// Remove an element from a set. /// public ArrayExpr MkSetDel(ArrayExpr set, Expr element) { Debug.Assert(set != null); Debug.Assert(element != null); CheckContextMatch(set); CheckContextMatch(element); return (ArrayExpr)Expr.Create(this, Native.Z3_mk_set_del(nCtx, set.NativeObject, element.NativeObject)); } /// /// Take the union of a list of sets. /// public ArrayExpr MkSetUnion(params ArrayExpr[] args) { Debug.Assert(args != null); Debug.Assert(args.All(a => a != null)); CheckContextMatch(args); return (ArrayExpr)Expr.Create(this, Native.Z3_mk_set_union(nCtx, (uint)args.Length, AST.ArrayToNative(args))); } /// /// Take the intersection of a list of sets. /// public ArrayExpr MkSetIntersection(params ArrayExpr[] args) { Debug.Assert(args != null); Debug.Assert(args.All(a => a != null)); CheckContextMatch(args); return (ArrayExpr)Expr.Create(this, Native.Z3_mk_set_intersect(nCtx, (uint)args.Length, AST.ArrayToNative(args))); } /// /// Take the difference between two sets. /// public ArrayExpr MkSetDifference(ArrayExpr arg1, ArrayExpr arg2) { Debug.Assert(arg1 != null); Debug.Assert(arg2 != null); CheckContextMatch(arg1); CheckContextMatch(arg2); return (ArrayExpr)Expr.Create(this, Native.Z3_mk_set_difference(nCtx, arg1.NativeObject, arg2.NativeObject)); } /// /// Take the complement of a set. /// public ArrayExpr MkSetComplement(ArrayExpr arg) { Debug.Assert(arg != null); CheckContextMatch(arg); return (ArrayExpr)Expr.Create(this, Native.Z3_mk_set_complement(nCtx, arg.NativeObject)); } /// /// Check for set membership. /// public BoolExpr MkSetMembership(Expr elem, ArrayExpr set) { Debug.Assert(elem != null); Debug.Assert(set != null); CheckContextMatch(elem); CheckContextMatch(set); return (BoolExpr) Expr.Create(this, Native.Z3_mk_set_member(nCtx, elem.NativeObject, set.NativeObject)); } /// /// Check for subsetness of sets. /// public BoolExpr MkSetSubset(ArrayExpr arg1, ArrayExpr arg2) { Debug.Assert(arg1 != null); Debug.Assert(arg2 != null); CheckContextMatch(arg1); CheckContextMatch(arg2); return (BoolExpr) Expr.Create(this, Native.Z3_mk_set_subset(nCtx, arg1.NativeObject, arg2.NativeObject)); } #endregion #region Sequence, string and regular expressions /// /// Create the empty sequence. /// public SeqExpr MkEmptySeq(Sort s) { Debug.Assert(s != null); return new SeqExpr(this, Native.Z3_mk_seq_empty(nCtx, s.NativeObject)); } /// /// Create the singleton sequence. /// public SeqExpr MkUnit(Expr elem) { Debug.Assert(elem != null); return new SeqExpr(this, Native.Z3_mk_seq_unit(nCtx, elem.NativeObject)); } /// /// Create a string constant. /// public SeqExpr MkString(string s) { Debug.Assert(s != null); return new SeqExpr(this, Native.Z3_mk_string(nCtx, s)); } /// /// Convert an integer expression to a string. /// public SeqExpr IntToString(Expr e) { Debug.Assert(e != null); Debug.Assert(e is ArithExpr); return new SeqExpr(this, Native.Z3_mk_int_to_str(nCtx, e.NativeObject)); } /// /// Convert a bit-vector expression, represented as an unsigned number, to a string. /// public SeqExpr UbvToString(Expr e) { Debug.Assert(e != null); Debug.Assert(e is ArithExpr); return new SeqExpr(this, Native.Z3_mk_ubv_to_str(nCtx, e.NativeObject)); } /// /// Convert a bit-vector expression, represented as an signed number, to a string. /// public SeqExpr SbvToString(Expr e) { Debug.Assert(e != null); Debug.Assert(e is ArithExpr); return new SeqExpr(this, Native.Z3_mk_sbv_to_str(nCtx, e.NativeObject)); } /// /// Convert an integer expression to a string. /// public IntExpr StringToInt(Expr e) { Debug.Assert(e != null); Debug.Assert(e is SeqExpr); return new IntExpr(this, Native.Z3_mk_str_to_int(nCtx, e.NativeObject)); } /// /// Concatenate sequences. /// public SeqExpr MkConcat(params SeqExpr[] t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); return new SeqExpr(this, Native.Z3_mk_seq_concat(nCtx, (uint)t.Length, AST.ArrayToNative(t))); } /// /// Retrieve the length of a given sequence. /// public IntExpr MkLength(SeqExpr s) { Debug.Assert(s != null); return (IntExpr) Expr.Create(this, Native.Z3_mk_seq_length(nCtx, s.NativeObject)); } /// /// Check for sequence prefix. /// public BoolExpr MkPrefixOf(SeqExpr s1, SeqExpr s2) { Debug.Assert(s1 != null); Debug.Assert(s2 != null); CheckContextMatch(s1, s2); return new BoolExpr(this, Native.Z3_mk_seq_prefix(nCtx, s1.NativeObject, s2.NativeObject)); } /// /// Check for sequence suffix. /// public BoolExpr MkSuffixOf(SeqExpr s1, SeqExpr s2) { Debug.Assert(s1 != null); Debug.Assert(s2 != null); CheckContextMatch(s1, s2); return new BoolExpr(this, Native.Z3_mk_seq_suffix(nCtx, s1.NativeObject, s2.NativeObject)); } /// /// Check for sequence containment of s2 in s1. /// public BoolExpr MkContains(SeqExpr s1, SeqExpr s2) { Debug.Assert(s1 != null); Debug.Assert(s2 != null); CheckContextMatch(s1, s2); return new BoolExpr(this, Native.Z3_mk_seq_contains(nCtx, s1.NativeObject, s2.NativeObject)); } /// /// Check if the string s1 is lexicographically strictly less than s2. /// public BoolExpr MkStringLt(SeqExpr s1, SeqExpr s2) { Debug.Assert(s1 != null); Debug.Assert(s2 != null); CheckContextMatch(s1, s2); return new BoolExpr(this, Native.Z3_mk_str_lt(nCtx, s1.NativeObject, s2.NativeObject)); } /// /// Check if the string s1 is lexicographically strictly less than s2. /// public BoolExpr MkStringLe(SeqExpr s1, SeqExpr s2) { Debug.Assert(s1 != null); Debug.Assert(s2 != null); CheckContextMatch(s1, s2); return new BoolExpr(this, Native.Z3_mk_str_le(nCtx, s1.NativeObject, s2.NativeObject)); } /// /// Retrieve sequence of length one at index. /// public SeqExpr MkAt(SeqExpr s, Expr index) { Debug.Assert(s != null); Debug.Assert(index != null); CheckContextMatch(s, index); return new SeqExpr(this, Native.Z3_mk_seq_at(nCtx, s.NativeObject, index.NativeObject)); } /// /// Retrieve element at index. /// public Expr MkNth(SeqExpr s, Expr index) { Debug.Assert(s != null); Debug.Assert(index != null); CheckContextMatch(s, index); return Expr.Create(this, Native.Z3_mk_seq_nth(nCtx, s.NativeObject, index.NativeObject)); } /// /// Extract subsequence. /// public SeqExpr MkExtract(SeqExpr s, IntExpr offset, IntExpr length) { Debug.Assert(s != null); Debug.Assert(offset != null); Debug.Assert(length != null); CheckContextMatch(s, offset, length); return new SeqExpr(this, Native.Z3_mk_seq_extract(nCtx, s.NativeObject, offset.NativeObject, length.NativeObject)); } /// /// Extract index of sub-string starting at offset. /// public IntExpr MkIndexOf(SeqExpr s, SeqExpr substr, ArithExpr offset) { Debug.Assert(s != null); Debug.Assert(offset != null); Debug.Assert(substr != null); CheckContextMatch(s, substr, offset); return new IntExpr(this, Native.Z3_mk_seq_index(nCtx, s.NativeObject, substr.NativeObject, offset.NativeObject)); } /// /// Replace the first occurrence of src by dst in s. /// public SeqExpr MkReplace(SeqExpr s, SeqExpr src, SeqExpr dst) { Debug.Assert(s != null); Debug.Assert(src != null); Debug.Assert(dst != null); CheckContextMatch(s, src, dst); return new SeqExpr(this, Native.Z3_mk_seq_replace(nCtx, s.NativeObject, src.NativeObject, dst.NativeObject)); } /// /// Convert a regular expression that accepts sequence s. /// public ReExpr MkToRe(SeqExpr s) { Debug.Assert(s != null); return new ReExpr(this, Native.Z3_mk_seq_to_re(nCtx, s.NativeObject)); } /// /// Check for regular expression membership. /// public BoolExpr MkInRe(SeqExpr s, ReExpr re) { Debug.Assert(s != null); Debug.Assert(re != null); CheckContextMatch(s, re); return new BoolExpr(this, Native.Z3_mk_seq_in_re(nCtx, s.NativeObject, re.NativeObject)); } /// /// Take the Kleene star of a regular expression. /// public ReExpr MkStar(ReExpr re) { Debug.Assert(re != null); return new ReExpr(this, Native.Z3_mk_re_star(nCtx, re.NativeObject)); } /// /// Take the bounded Kleene star of a regular expression. /// public ReExpr MkLoop(ReExpr re, uint lo, uint hi = 0) { Debug.Assert(re != null); return new ReExpr(this, Native.Z3_mk_re_loop(nCtx, re.NativeObject, lo, hi)); } /// /// Take the Kleene plus of a regular expression. /// public ReExpr MkPlus(ReExpr re) { Debug.Assert(re != null); return new ReExpr(this, Native.Z3_mk_re_plus(nCtx, re.NativeObject)); } /// /// Create the optional regular expression. /// public ReExpr MkOption(ReExpr re) { Debug.Assert(re != null); return new ReExpr(this, Native.Z3_mk_re_option(nCtx, re.NativeObject)); } /// /// Create the complement regular expression. /// public ReExpr MkComplement(ReExpr re) { Debug.Assert(re != null); return new ReExpr(this, Native.Z3_mk_re_complement(nCtx, re.NativeObject)); } /// /// Create the concatenation of regular languages. /// public ReExpr MkConcat(params ReExpr[] t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); return new ReExpr(this, Native.Z3_mk_re_concat(nCtx, (uint)t.Length, AST.ArrayToNative(t))); } /// /// Create the union of regular languages. /// public ReExpr MkUnion(params ReExpr[] t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); return new ReExpr(this, Native.Z3_mk_re_union(nCtx, (uint)t.Length, AST.ArrayToNative(t))); } /// /// Create the intersection of regular languages. /// public ReExpr MkIntersect(params ReExpr[] t) { Debug.Assert(t != null); Debug.Assert(t.All(a => a != null)); CheckContextMatch(t); return new ReExpr(this, Native.Z3_mk_re_intersect(nCtx, (uint)t.Length, AST.ArrayToNative(t))); } /// /// Create a difference regular expression. /// public ReExpr MkDiff(ReExpr a, ReExpr b) { Debug.Assert(a != null); Debug.Assert(b != null); CheckContextMatch(a, b); return new ReExpr(this, Native.Z3_mk_re_diff(nCtx, a.NativeObject, b.NativeObject)); } /// /// Create the empty regular expression. /// The sort s should be a regular expression. /// public ReExpr MkEmptyRe(Sort s) { Debug.Assert(s != null); return new ReExpr(this, Native.Z3_mk_re_empty(nCtx, s.NativeObject)); } /// /// Create the full regular expression. /// The sort s should be a regular expression. /// public ReExpr MkFullRe(Sort s) { Debug.Assert(s != null); return new ReExpr(this, Native.Z3_mk_re_full(nCtx, s.NativeObject)); } /// /// Create a range expression. /// public ReExpr MkRange(SeqExpr lo, SeqExpr hi) { Debug.Assert(lo != null); Debug.Assert(hi != null); CheckContextMatch(lo, hi); return new ReExpr(this, Native.Z3_mk_re_range(nCtx, lo.NativeObject, hi.NativeObject)); } /// /// Create less than or equal to between two characters. /// public BoolExpr MkCharLe(Expr ch1, Expr ch2) { Debug.Assert(ch1 != null); Debug.Assert(ch2 != null); return new BoolExpr(this, Native.Z3_mk_char_le(nCtx, ch1.NativeObject, ch2.NativeObject)); } /// /// Create an integer (code point) from character. /// public IntExpr CharToInt(Expr ch) { Debug.Assert(ch != null); return new IntExpr(this, Native.Z3_mk_char_to_int(nCtx, ch.NativeObject)); } /// /// Create a bit-vector (code point) from character. /// public BitVecExpr CharToBV(Expr ch) { Debug.Assert(ch != null); return new BitVecExpr(this, Native.Z3_mk_char_to_bv(nCtx, ch.NativeObject)); } /// /// Create a character from a bit-vector (code point). /// public Expr CharFromBV(BitVecExpr bv) { Debug.Assert(bv != null); return new Expr(this, Native.Z3_mk_char_from_bv(nCtx, bv.NativeObject)); } /// /// Create a check if the character is a digit. /// public BoolExpr MkIsDigit(Expr ch) { Debug.Assert(ch != null); return new BoolExpr(this, Native.Z3_mk_char_is_digit(nCtx, ch.NativeObject)); } #endregion #region Pseudo-Boolean constraints /// /// Create an at-most-k constraint. /// public BoolExpr MkAtMost(IEnumerable args, uint k) { Debug.Assert(args != null); CheckContextMatch(args); var ts = args.ToArray(); return new BoolExpr(this, Native.Z3_mk_atmost(nCtx, (uint) ts.Length, AST.ArrayToNative(ts), k)); } /// /// Create an at-least-k constraint. /// public BoolExpr MkAtLeast(IEnumerable args, uint k) { Debug.Assert(args != null); CheckContextMatch(args); var ts = args.ToArray(); return new BoolExpr(this, Native.Z3_mk_atleast(nCtx, (uint) ts.Length, AST.ArrayToNative(ts), k)); } /// /// Create a pseudo-Boolean less-or-equal constraint. /// public BoolExpr MkPBLe(int[] coeffs, BoolExpr[] args, int k) { Debug.Assert(args != null); Debug.Assert(coeffs != null); Debug.Assert(args.Length == coeffs.Length); CheckContextMatch(args); return new BoolExpr(this, Native.Z3_mk_pble(nCtx, (uint) args.Length, AST.ArrayToNative(args), coeffs, k)); } /// /// Create a pseudo-Boolean greater-or-equal constraint. /// public BoolExpr MkPBGe(int[] coeffs, BoolExpr[] args, int k) { Debug.Assert(args != null); Debug.Assert(coeffs != null); Debug.Assert(args.Length == coeffs.Length); CheckContextMatch(args); return new BoolExpr(this, Native.Z3_mk_pbge(nCtx, (uint) args.Length, AST.ArrayToNative(args), coeffs, k)); } /// /// Create a pseudo-Boolean equal constraint. /// public BoolExpr MkPBEq(int[] coeffs, BoolExpr[] args, int k) { Debug.Assert(args != null); Debug.Assert(coeffs != null); Debug.Assert(args.Length == coeffs.Length); CheckContextMatch(args); return new BoolExpr(this, Native.Z3_mk_pbeq(nCtx, (uint) args.Length, AST.ArrayToNative(args), coeffs, k)); } #endregion #region Numerals #region General Numerals /// /// Create a Term of a given sort. /// /// A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form [num]* / [num]*. /// The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size. /// A Term with value and sort public Expr MkNumeral(string v, Sort ty) { Debug.Assert(ty != null); CheckContextMatch(ty); return Expr.Create(this, Native.Z3_mk_numeral(nCtx, v, ty.NativeObject)); } /// /// Create a Term of a given sort. This function can be used to create numerals that fit in a machine integer. /// It is slightly faster than MakeNumeral since it is not necessary to parse a string. /// /// Value of the numeral /// Sort of the numeral /// A Term with value and type public Expr MkNumeral(int v, Sort ty) { Debug.Assert(ty != null); CheckContextMatch(ty); return Expr.Create(this, Native.Z3_mk_int(nCtx, v, ty.NativeObject)); } /// /// Create a Term of a given sort. This function can be used to create numerals that fit in a machine integer. /// It is slightly faster than MakeNumeral since it is not necessary to parse a string. /// /// Value of the numeral /// Sort of the numeral /// A Term with value and type public Expr MkNumeral(uint v, Sort ty) { Debug.Assert(ty != null); CheckContextMatch(ty); return Expr.Create(this, Native.Z3_mk_unsigned_int(nCtx, v, ty.NativeObject)); } /// /// Create a Term of a given sort. This function can be used to create numerals that fit in a machine integer. /// It is slightly faster than MakeNumeral since it is not necessary to parse a string. /// /// Value of the numeral /// Sort of the numeral /// A Term with value and type public Expr MkNumeral(long v, Sort ty) { Debug.Assert(ty != null); CheckContextMatch(ty); return Expr.Create(this, Native.Z3_mk_int64(nCtx, v, ty.NativeObject)); } /// /// Create a Term of a given sort. This function can be used to create numerals that fit in a machine integer. /// It is slightly faster than MakeNumeral since it is not necessary to parse a string. /// /// Value of the numeral /// Sort of the numeral /// A Term with value and type public Expr MkNumeral(ulong v, Sort ty) { Debug.Assert(ty != null); CheckContextMatch(ty); return Expr.Create(this, Native.Z3_mk_unsigned_int64(nCtx, v, ty.NativeObject)); } #endregion #region Reals /// /// Create a real from a fraction. /// /// numerator of rational. /// denominator of rational. /// A Term with value / and sort Real /// public RatNum MkReal(int num, int den) { if (den == 0) throw new Z3Exception("Denominator is zero"); return new RatNum(this, Native.Z3_mk_real(nCtx, num, den)); } /// /// Create a real numeral. /// /// A string representing the Term value in decimal notation. /// A Term with value and sort Real public RatNum MkReal(string v) { return new RatNum(this, Native.Z3_mk_numeral(nCtx, v, RealSort.NativeObject)); } /// /// Create a real numeral. /// /// value of the numeral. /// A Term with value and sort Real public RatNum MkReal(int v) { return new RatNum(this, Native.Z3_mk_int(nCtx, v, RealSort.NativeObject)); } /// /// Create a real numeral. /// /// value of the numeral. /// A Term with value and sort Real public RatNum MkReal(uint v) { return new RatNum(this, Native.Z3_mk_unsigned_int(nCtx, v, RealSort.NativeObject)); } /// /// Create a real numeral. /// /// value of the numeral. /// A Term with value and sort Real public RatNum MkReal(long v) { return new RatNum(this, Native.Z3_mk_int64(nCtx, v, RealSort.NativeObject)); } /// /// Create a real numeral. /// /// value of the numeral. /// A Term with value and sort Real public RatNum MkReal(ulong v) { return new RatNum(this, Native.Z3_mk_unsigned_int64(nCtx, v, RealSort.NativeObject)); } #endregion #region Integers /// /// Create an integer numeral. /// /// A string representing the Term value in decimal notation. public IntNum MkInt(string v) { return new IntNum(this, Native.Z3_mk_numeral(nCtx, v, IntSort.NativeObject)); } /// /// Create an integer numeral. /// /// value of the numeral. /// A Term with value and sort Integer public IntNum MkInt(int v) { return new IntNum(this, Native.Z3_mk_int(nCtx, v, IntSort.NativeObject)); } /// /// Create an integer numeral. /// /// value of the numeral. /// A Term with value and sort Integer public IntNum MkInt(uint v) { return new IntNum(this, Native.Z3_mk_unsigned_int(nCtx, v, IntSort.NativeObject)); } /// /// Create an integer numeral. /// /// value of the numeral. /// A Term with value and sort Integer public IntNum MkInt(long v) { return new IntNum(this, Native.Z3_mk_int64(nCtx, v, IntSort.NativeObject)); } /// /// Create an integer numeral. /// /// value of the numeral. /// A Term with value and sort Integer public IntNum MkInt(ulong v) { return new IntNum(this, Native.Z3_mk_unsigned_int64(nCtx, v, IntSort.NativeObject)); } #endregion #region Bit-vectors /// /// Create a bit-vector numeral. /// /// A string representing the value in decimal notation. /// the size of the bit-vector public BitVecNum MkBV(string v, uint size) { return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); } /// /// Create a bit-vector numeral. /// /// value of the numeral. /// the size of the bit-vector public BitVecNum MkBV(int v, uint size) { return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); } /// /// Create a bit-vector numeral. /// /// value of the numeral. /// the size of the bit-vector public BitVecNum MkBV(uint v, uint size) { return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); } /// /// Create a bit-vector numeral. /// /// value of the numeral. /// the size of the bit-vector public BitVecNum MkBV(long v, uint size) { return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); } /// /// Create a bit-vector numeral. /// /// value of the numeral. /// the size of the bit-vector public BitVecNum MkBV(ulong v, uint size) { return (BitVecNum)MkNumeral(v, MkBitVecSort(size)); } /// /// Create a bit-vector numeral. /// /// An array of bits representing the bit-vector. Least significant bit is at position 0. public BitVecNum MkBV(bool[] bits) { byte[] _bits = new byte[bits.Length]; for (int i = 0; i < bits.Length; ++i) _bits[i] = (byte)(bits[i] ? 1 : 0); return (BitVecNum)Expr.Create(this, Native.Z3_mk_bv_numeral(nCtx, (uint)bits.Length, _bits)); } #endregion #endregion // Numerals #region Quantifiers /// /// Create a universal Quantifier. /// /// /// Creates a forall formula, where is the weight, /// is an array of patterns, is an array /// with the sorts of the bound variables, is an array with the /// 'names' of the bound variables, and is the body of the /// quantifier. Quantifiers are associated with weights indicating the importance of /// using the quantifier during instantiation. /// Note that the bound variables are de-Bruijn indices created using . /// Z3 applies the convention that the last element in and /// refers to the variable with index 0, the second to last element /// of and refers to the variable /// with index 1, etc. /// /// the sorts of the bound variables. /// names of the bound variables /// the body of the quantifier. /// quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. /// array containing the patterns created using MkPattern. /// array containing the anti-patterns created using MkPattern. /// optional symbol to track quantifier. /// optional symbol to track skolem constants. public Quantifier MkForall(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) { Debug.Assert(sorts != null); Debug.Assert(names != null); Debug.Assert(body != null); Debug.Assert(sorts.Length == names.Length); Debug.Assert(sorts.All(s => s != null)); Debug.Assert(names.All(n => n != null)); Debug.Assert(patterns == null || patterns.All(p => p != null)); Debug.Assert(noPatterns == null || noPatterns.All(np => np != null)); return new Quantifier(this, true, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); } /// /// Create a universal Quantifier. /// /// /// Creates a universal quantifier using a list of constants that will /// form the set of bound variables. /// /// public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) { Debug.Assert(body != null); Debug.Assert(boundConstants == null || boundConstants.All(b => b != null)); Debug.Assert(patterns == null || patterns.All(p => p != null)); Debug.Assert(noPatterns == null || noPatterns.All(np => np != null)); return new Quantifier(this, true, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); } /// /// Create an existential Quantifier. /// /// /// Creates an existential quantifier using de-Bruijn indexed variables. /// (). /// public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) { Debug.Assert(sorts != null); Debug.Assert(names != null); Debug.Assert(body != null); Debug.Assert(sorts.Length == names.Length); Debug.Assert(sorts.All(s => s != null)); Debug.Assert(names.All(n => n != null)); Debug.Assert(patterns == null || patterns.All(p => p != null)); Debug.Assert(noPatterns == null || noPatterns.All(np => np != null)); return new Quantifier(this, false, sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); } /// /// Create an existential Quantifier. /// /// /// Creates an existential quantifier using a list of constants that will /// form the set of bound variables. /// /// public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) { Debug.Assert(body != null); Debug.Assert(boundConstants == null || boundConstants.All(n => n != null)); Debug.Assert(patterns == null || patterns.All(p => p != null)); Debug.Assert(noPatterns == null || noPatterns.All(np => np != null)); return new Quantifier(this, false, boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); } /// /// Create a Quantifier. /// /// public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) { Debug.Assert(body != null); Debug.Assert(names != null); Debug.Assert(sorts != null); Debug.Assert(sorts.Length == names.Length); Debug.Assert(sorts.All(s => s != null)); Debug.Assert(names.All(n => n != null)); Debug.Assert(patterns == null || patterns.All(p => p != null)); Debug.Assert(noPatterns == null || noPatterns.All(np => np != null)); if (universal) return MkForall(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); else return MkExists(sorts, names, body, weight, patterns, noPatterns, quantifierID, skolemID); } /// /// Create a Quantifier. /// /// public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null) { Debug.Assert(body != null); Debug.Assert(boundConstants == null || boundConstants.All(n => n != null)); Debug.Assert(patterns == null || patterns.All(p => p != null)); Debug.Assert(noPatterns == null || noPatterns.All(np => np != null)); if (universal) return MkForall(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); else return MkExists(boundConstants, body, weight, patterns, noPatterns, quantifierID, skolemID); } /// /// Create a lambda expression. /// /// /// Creates a lambda expression. /// is an array /// with the sorts of the bound variables, is an array with the /// 'names' of the bound variables, and is the body of the /// lambda. /// Note that the bound variables are de-Bruijn indices created using . /// Z3 applies the convention that the last element in and /// refers to the variable with index 0, the second to last element /// of and refers to the variable /// with index 1, etc. /// /// the sorts of the bound variables. /// names of the bound variables /// the body of the quantifier. public Lambda MkLambda(Sort[] sorts, Symbol[] names, Expr body) { Debug.Assert(sorts != null); Debug.Assert(names != null); Debug.Assert(body != null); Debug.Assert(sorts.Length == names.Length); Debug.Assert(sorts.All(s => s != null)); Debug.Assert(names.All(n => n != null)); return new Lambda(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) { Debug.Assert(body != null); Debug.Assert(boundConstants != null && boundConstants.All(b => b != null)); return new Lambda(this, boundConstants, body); } #endregion #endregion // Expr #region Options /// /// Selects the format used for pretty-printing expressions. /// /// /// The default mode for pretty printing expressions is to produce /// SMT-LIB style output where common subexpressions are printed /// at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL. /// To print shared common subexpressions only once, /// use the Z3_PRINT_LOW_LEVEL mode. /// To print in way that conforms to SMT-LIB standards and uses let /// expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT. /// /// /// /// /// public Z3_ast_print_mode PrintMode { set { Native.Z3_set_ast_print_mode(nCtx, (uint)value); } } #endregion #region SMT Files & Strings /// /// Parse the given string using the SMT-LIB2 parser. /// /// A conjunction of assertions in the scope (up to push/pop) at the end of the string. public BoolExpr[] ParseSMTLIB2String(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, FuncDecl[] decls = null) { uint csn = Symbol.ArrayLength(sortNames); uint cs = Sort.ArrayLength(sorts); uint cdn = Symbol.ArrayLength(declNames); uint cd = AST.ArrayLength(decls); if (csn != cs || cdn != cd) throw new Z3Exception("Argument size mismatch"); ASTVector assertions = new ASTVector(this, Native.Z3_parse_smtlib2_string(nCtx, str, AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))); return assertions.ToBoolExprArray(); } /// /// Parse the given file using the SMT-LIB2 parser. /// /// public BoolExpr[] ParseSMTLIB2File(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, FuncDecl[] decls = null) { uint csn = Symbol.ArrayLength(sortNames); uint cs = Sort.ArrayLength(sorts); uint cdn = Symbol.ArrayLength(declNames); uint cd = AST.ArrayLength(decls); if (csn != cs || cdn != cd) throw new Z3Exception("Argument size mismatch"); ASTVector assertions = new ASTVector(this, Native.Z3_parse_smtlib2_file(nCtx, fileName, AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts), AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))); return assertions.ToBoolExprArray(); } #endregion #region Goals /// /// Creates a new Goal. /// /// /// Note that the Context must have been created with proof generation support if /// is set to true here. /// /// Indicates whether model generation should be enabled. /// Indicates whether unsat core generation should be enabled. /// Indicates whether proof generation should be enabled. public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false) { return new Goal(this, models, unsatCores, proofs); } #endregion #region ParameterSets /// /// Creates a new ParameterSet. /// public Params MkParams() { return new Params(this); } #endregion #region Tactics /// /// The number of supported tactics. /// public uint NumTactics { get { return Native.Z3_get_num_tactics(nCtx); } } /// /// The names of all supported tactics. /// public string[] TacticNames { get { uint n = NumTactics; string[] res = new string[n]; for (uint i = 0; i < n; i++) res[i] = Native.Z3_get_tactic_name(nCtx, i); return res; } } /// /// Returns a string containing a description of the tactic with the given name. /// public string TacticDescription(string name) { return Native.Z3_tactic_get_descr(nCtx, name); } /// /// Creates a new Tactic. /// public Tactic MkTactic(string name) { return new Tactic(this, name); } /// /// Create a tactic that applies to a Goal and /// then to every subgoal produced by . /// public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); // Debug.Assert(ts == null || Contract.ForAll(0, ts.Length, j => ts[j] != null)); CheckContextMatch(t1); CheckContextMatch(t2); CheckContextMatch(ts); IntPtr last = IntPtr.Zero; if (ts != null && ts.Length > 0) { last = ts[ts.Length - 1].NativeObject; for (int i = ts.Length - 2; i >= 0; i--) last = Native.Z3_tactic_and_then(nCtx, ts[i].NativeObject, last); } if (last != IntPtr.Zero) { last = Native.Z3_tactic_and_then(nCtx, t2.NativeObject, last); return new Tactic(this, Native.Z3_tactic_and_then(nCtx, t1.NativeObject, last)); } else return new Tactic(this, Native.Z3_tactic_and_then(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create a tactic that applies to a Goal and /// then to every subgoal produced by . /// /// /// Shorthand for AndThen. /// public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); // Debug.Assert(ts == null || Contract.ForAll(0, ts.Length, j => ts[j] != null)); return AndThen(t1, t2, ts); } /// /// Create a tactic that first applies to a Goal and /// if it fails then returns the result of applied to the Goal. /// public Tactic OrElse(Tactic t1, Tactic t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new Tactic(this, Native.Z3_tactic_or_else(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Create a tactic that applies to a goal for milliseconds. /// /// /// If does not terminate within milliseconds, then it fails. /// public Tactic TryFor(Tactic t, uint ms) { Debug.Assert(t != null); CheckContextMatch(t); return new Tactic(this, Native.Z3_tactic_try_for(nCtx, t.NativeObject, ms)); } /// /// Create a tactic that applies to a given goal if the probe /// evaluates to true. /// /// /// If evaluates to false, then the new tactic behaves like the skip tactic. /// public Tactic When(Probe p, Tactic t) { Debug.Assert(p != null); Debug.Assert(t != null); CheckContextMatch(t); CheckContextMatch(p); return new Tactic(this, Native.Z3_tactic_when(nCtx, p.NativeObject, t.NativeObject)); } /// /// Create a tactic that applies to a given goal if the probe /// evaluates to true and otherwise. /// public Tactic Cond(Probe p, Tactic t1, Tactic t2) { Debug.Assert(p != null); Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(p); CheckContextMatch(t1); CheckContextMatch(t2); return new Tactic(this, Native.Z3_tactic_cond(nCtx, p.NativeObject, t1.NativeObject, t2.NativeObject)); } /// /// Create a tactic that keeps applying until the goal is not /// modified anymore or the maximum number of iterations is reached. /// public Tactic Repeat(Tactic t, uint max = uint.MaxValue) { Debug.Assert(t != null); CheckContextMatch(t); return new Tactic(this, Native.Z3_tactic_repeat(nCtx, t.NativeObject, max)); } /// /// Create a tactic that just returns the given goal. /// public Tactic Skip() { return new Tactic(this, Native.Z3_tactic_skip(nCtx)); } /// /// Create a tactic always fails. /// public Tactic Fail() { return new Tactic(this, Native.Z3_tactic_fail(nCtx)); } /// /// Create a tactic that fails if the probe evaluates to false. /// public Tactic FailIf(Probe p) { Debug.Assert(p != null); CheckContextMatch(p); return new Tactic(this, Native.Z3_tactic_fail_if(nCtx, p.NativeObject)); } /// /// Create a tactic that fails if the goal is not trivially satisfiable (i.e., empty) /// or trivially unsatisfiable (i.e., contains `false'). /// public Tactic FailIfNotDecided() { return new Tactic(this, Native.Z3_tactic_fail_if_not_decided(nCtx)); } /// /// Create a tactic that applies using the given set of parameters . /// public Tactic UsingParams(Tactic t, Params p) { Debug.Assert(t != null); Debug.Assert(p != null); CheckContextMatch(t); CheckContextMatch(p); return new Tactic(this, Native.Z3_tactic_using_params(nCtx, t.NativeObject, p.NativeObject)); } /// /// Create a tactic that applies using the given set of parameters . /// /// Alias for UsingParams public Tactic With(Tactic t, Params p) { Debug.Assert(t != null); Debug.Assert(p != null); return UsingParams(t, p); } /// /// Create a tactic that applies the given tactics in parallel until one of them succeeds (i.e., the first that doesn't fail). /// public Tactic ParOr(params Tactic[] t) { Debug.Assert(t == null || t.All(tactic => tactic != null)); CheckContextMatch(t); return new Tactic(this, Native.Z3_tactic_par_or(nCtx, Tactic.ArrayLength(t), Tactic.ArrayToNative(t))); } /// /// Create a tactic that applies to a given goal and then /// to every subgoal produced by . The subgoals are processed in parallel. /// public Tactic ParAndThen(Tactic t1, Tactic t2) { Debug.Assert(t1 != null); Debug.Assert(t2 != null); CheckContextMatch(t1); CheckContextMatch(t2); return new Tactic(this, Native.Z3_tactic_par_and_then(nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Interrupt the execution of a Z3 procedure. /// /// This procedure can be used to interrupt: solvers, simplifiers and tactics. public void Interrupt() { Native.Z3_interrupt(nCtx); } #endregion #region Probes /// /// The number of supported Probes. /// public uint NumProbes { get { return Native.Z3_get_num_probes(nCtx); } } /// /// The names of all supported Probes. /// public string[] ProbeNames { get { uint n = NumProbes; string[] res = new string[n]; for (uint i = 0; i < n; i++) res[i] = Native.Z3_get_probe_name(nCtx, i); return res; } } /// /// Returns a string containing a description of the probe with the given name. /// public string ProbeDescription(string name) { return Native.Z3_probe_get_descr(nCtx, name); } /// /// Creates a new Probe. /// public Probe MkProbe(string name) { return new Probe(this, name); } /// /// Create a probe that always evaluates to . /// public Probe ConstProbe(double val) { return new Probe(this, Native.Z3_probe_const(nCtx, val)); } /// /// Create a probe that evaluates to "true" when the value returned by /// is less than the value returned by /// public Probe Lt(Probe p1, Probe p2) { Debug.Assert(p1 != null); Debug.Assert(p2 != null); CheckContextMatch(p1); CheckContextMatch(p2); return new Probe(this, Native.Z3_probe_lt(nCtx, p1.NativeObject, p2.NativeObject)); } /// /// Create a probe that evaluates to "true" when the value returned by /// is greater than the value returned by /// public Probe Gt(Probe p1, Probe p2) { Debug.Assert(p1 != null); Debug.Assert(p2 != null); CheckContextMatch(p1); CheckContextMatch(p2); return new Probe(this, Native.Z3_probe_gt(nCtx, p1.NativeObject, p2.NativeObject)); } /// /// Create a probe that evaluates to "true" when the value returned by /// is less than or equal the value returned by /// public Probe Le(Probe p1, Probe p2) { Debug.Assert(p1 != null); Debug.Assert(p2 != null); CheckContextMatch(p1); CheckContextMatch(p2); return new Probe(this, Native.Z3_probe_le(nCtx, p1.NativeObject, p2.NativeObject)); } /// /// Create a probe that evaluates to "true" when the value returned by /// is greater than or equal the value returned by /// public Probe Ge(Probe p1, Probe p2) { Debug.Assert(p1 != null); Debug.Assert(p2 != null); CheckContextMatch(p1); CheckContextMatch(p2); return new Probe(this, Native.Z3_probe_ge(nCtx, p1.NativeObject, p2.NativeObject)); } /// /// Create a probe that evaluates to "true" when the value returned by /// is equal to the value returned by /// public Probe Eq(Probe p1, Probe p2) { Debug.Assert(p1 != null); Debug.Assert(p2 != null); CheckContextMatch(p1); CheckContextMatch(p2); return new Probe(this, Native.Z3_probe_eq(nCtx, p1.NativeObject, p2.NativeObject)); } /// /// Create a probe that evaluates to "true" when the value /// and evaluate to "true". /// public Probe And(Probe p1, Probe p2) { Debug.Assert(p1 != null); Debug.Assert(p2 != null); CheckContextMatch(p1); CheckContextMatch(p2); return new Probe(this, Native.Z3_probe_and(nCtx, p1.NativeObject, p2.NativeObject)); } /// /// Create a probe that evaluates to "true" when the value /// or evaluate to "true". /// public Probe Or(Probe p1, Probe p2) { Debug.Assert(p1 != null); Debug.Assert(p2 != null); CheckContextMatch(p1); CheckContextMatch(p2); return new Probe(this, Native.Z3_probe_or(nCtx, p1.NativeObject, p2.NativeObject)); } /// /// Create a probe that evaluates to "true" when the value /// does not evaluate to "true". /// public Probe Not(Probe p) { Debug.Assert(p != null); CheckContextMatch(p); return new Probe(this, Native.Z3_probe_not(nCtx, p.NativeObject)); } #endregion #region Solvers /// /// Creates a new (incremental) solver. /// /// /// This solver also uses a set of builtin tactics for handling the first /// check-sat command, and check-sat commands that take more than a given /// number of milliseconds to be solved. /// public Solver MkSolver(Symbol logic = null) { if (logic == null) return new Solver(this, Native.Z3_mk_solver(nCtx)); else return new Solver(this, Native.Z3_mk_solver_for_logic(nCtx, logic.NativeObject)); } /// /// Creates a new (incremental) solver. /// /// public Solver MkSolver(string logic) { return MkSolver(MkSymbol(logic)); } /// /// Creates a new (incremental) solver. /// public Solver MkSimpleSolver() { return new Solver(this, Native.Z3_mk_simple_solver(nCtx)); } /// /// Creates a solver that is implemented using the given tactic. /// /// /// The solver supports the commands Push and Pop, but it /// will always solve each check from scratch. /// public Solver MkSolver(Tactic t) { Debug.Assert(t != null); return new Solver(this, Native.Z3_mk_solver_from_tactic(nCtx, t.NativeObject)); } #endregion #region Fixedpoints /// /// Create a Fixedpoint context. /// public Fixedpoint MkFixedpoint() { return new Fixedpoint(this); } #endregion #region Optimization /// /// Create an Optimization context. /// public Optimize MkOptimize() { return new Optimize(this); } #endregion #region Floating-Point Arithmetic #region Rounding Modes #region RoundingMode Sort /// /// Create the floating-point RoundingMode sort. /// public FPRMSort MkFPRoundingModeSort() { return new FPRMSort(this); } #endregion #region Numerals /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. /// public FPRMExpr MkFPRoundNearestTiesToEven() { return new FPRMExpr(this, Native.Z3_mk_fpa_round_nearest_ties_to_even(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. /// public FPRMNum MkFPRNE() { return new FPRMNum(this, Native.Z3_mk_fpa_rne(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. /// public FPRMNum MkFPRoundNearestTiesToAway() { return new FPRMNum(this, Native.Z3_mk_fpa_round_nearest_ties_to_away(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. /// public FPRMNum MkFPRNA() { return new FPRMNum(this, Native.Z3_mk_fpa_rna(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. /// public FPRMNum MkFPRoundTowardPositive() { return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_positive(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardPositive rounding mode. /// public FPRMNum MkFPRTP() { return new FPRMNum(this, Native.Z3_mk_fpa_rtp(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. /// public FPRMNum MkFPRoundTowardNegative() { return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_negative(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardNegative rounding mode. /// public FPRMNum MkFPRTN() { return new FPRMNum(this, Native.Z3_mk_fpa_rtn(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. /// public FPRMNum MkFPRoundTowardZero() { return new FPRMNum(this, Native.Z3_mk_fpa_round_toward_zero(nCtx)); } /// /// Create a numeral of RoundingMode sort which represents the RoundTowardZero rounding mode. /// public FPRMNum MkFPRTZ() { return new FPRMNum(this, Native.Z3_mk_fpa_rtz(nCtx)); } #endregion #endregion #region FloatingPoint Sorts /// /// Create a FloatingPoint sort. /// /// exponent bits in the FloatingPoint sort. /// significand bits in the FloatingPoint sort. public FPSort MkFPSort(uint ebits, uint sbits) { return new FPSort(this, ebits, sbits); } /// /// Create the half-precision (16-bit) FloatingPoint sort. /// public FPSort MkFPSortHalf() { return new FPSort(this, Native.Z3_mk_fpa_sort_half(nCtx)); } /// /// Create the half-precision (16-bit) FloatingPoint sort. /// public FPSort MkFPSort16() { return new FPSort(this, Native.Z3_mk_fpa_sort_16(nCtx)); } /// /// Create the single-precision (32-bit) FloatingPoint sort. /// public FPSort MkFPSortSingle() { return new FPSort(this, Native.Z3_mk_fpa_sort_single(nCtx)); } /// /// Create the single-precision (32-bit) FloatingPoint sort. /// public FPSort MkFPSort32() { return new FPSort(this, Native.Z3_mk_fpa_sort_32(nCtx)); } /// /// Create the double-precision (64-bit) FloatingPoint sort. /// public FPSort MkFPSortDouble() { return new FPSort(this, Native.Z3_mk_fpa_sort_double(nCtx)); } /// /// Create the double-precision (64-bit) FloatingPoint sort. /// public FPSort MkFPSort64() { return new FPSort(this, Native.Z3_mk_fpa_sort_64(nCtx)); } /// /// Create the quadruple-precision (128-bit) FloatingPoint sort. /// public FPSort MkFPSortQuadruple() { return new FPSort(this, Native.Z3_mk_fpa_sort_quadruple(nCtx)); } /// /// Create the quadruple-precision (128-bit) FloatingPoint sort. /// public FPSort MkFPSort128() { return new FPSort(this, Native.Z3_mk_fpa_sort_128(nCtx)); } #endregion #region Numerals /// /// Create a NaN of sort s. /// /// FloatingPoint sort. public FPNum MkFPNaN(FPSort s) { return new FPNum(this, Native.Z3_mk_fpa_nan(nCtx, s.NativeObject)); } /// /// Create a floating-point infinity of sort s. /// /// FloatingPoint sort. /// indicates whether the result should be negative. public FPNum MkFPInf(FPSort s, bool negative) { return new FPNum(this, Native.Z3_mk_fpa_inf(nCtx, s.NativeObject, (byte)(negative ? 1 : 0))); } /// /// Create a floating-point zero of sort s. /// /// FloatingPoint sort. /// indicates whether the result should be negative. public FPNum MkFPZero(FPSort s, bool negative) { return new FPNum(this, Native.Z3_mk_fpa_zero(nCtx, s.NativeObject, (byte)(negative ? 1 : 0))); } /// /// Create a numeral of FloatingPoint sort from a float. /// /// numeral value. /// FloatingPoint sort. public FPNum MkFPNumeral(float v, FPSort s) { return new FPNum(this, Native.Z3_mk_fpa_numeral_float(nCtx, v, s.NativeObject)); } /// /// Create a numeral of FloatingPoint sort from a float. /// /// numeral value. /// FloatingPoint sort. public FPNum MkFPNumeral(double v, FPSort s) { return new FPNum(this, Native.Z3_mk_fpa_numeral_double(nCtx, v, s.NativeObject)); } /// /// Create a numeral of FloatingPoint sort from an int. /// /// numeral value. /// FloatingPoint sort. public FPNum MkFPNumeral(int v, FPSort s) { return new FPNum(this, Native.Z3_mk_fpa_numeral_int(nCtx, v, s.NativeObject)); } /// /// Create a numeral of FloatingPoint sort from a sign bit and two integers. /// /// the sign. /// the significand. /// the exponent. /// FloatingPoint sort. public FPNum MkFPNumeral(bool sgn, uint sig, int exp, FPSort s) { return new FPNum(this, Native.Z3_mk_fpa_numeral_int_uint(nCtx, (byte)(sgn ? 1 : 0), exp, sig, s.NativeObject)); } /// /// Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. /// /// the sign. /// the significand. /// the exponent. /// FloatingPoint sort. public FPNum MkFPNumeral(bool sgn, Int64 exp, UInt64 sig, FPSort s) { return new FPNum(this, Native.Z3_mk_fpa_numeral_int64_uint64(nCtx, (byte)(sgn ? 1 : 0), exp, sig, s.NativeObject)); } /// /// Create a numeral of FloatingPoint sort from a float. /// /// numeral value. /// FloatingPoint sort. public FPNum MkFP(float v, FPSort s) { return MkFPNumeral(v, s); } /// /// Create a numeral of FloatingPoint sort from a float. /// /// numeral value. /// FloatingPoint sort. public FPNum MkFP(double v, FPSort s) { return MkFPNumeral(v, s); } /// /// Create a numeral of FloatingPoint sort from an int. /// /// numeral value. /// FloatingPoint sort. public FPNum MkFP(int v, FPSort s) { return MkFPNumeral(v, s); } /// /// Create a numeral of FloatingPoint sort from a sign bit and two integers. /// /// the sign. /// the exponent. /// the significand. /// FloatingPoint sort. public FPNum MkFP(bool sgn, int exp, uint sig, FPSort s) { return MkFPNumeral(sgn, exp, sig, s); } /// /// Create a numeral of FloatingPoint sort from a sign bit and two 64-bit integers. /// /// the sign. /// the exponent. /// the significand. /// FloatingPoint sort. public FPNum MkFP(bool sgn, Int64 exp, UInt64 sig, FPSort s) { return MkFPNumeral(sgn, exp, sig, s); } #endregion #region Operators /// /// Floating-point absolute value /// /// floating-point term public FPExpr MkFPAbs(FPExpr t) { return new FPExpr(this, Native.Z3_mk_fpa_abs(this.nCtx, t.NativeObject)); } /// /// Floating-point negation /// /// floating-point term public FPExpr MkFPNeg(FPExpr t) { return new FPExpr(this, Native.Z3_mk_fpa_neg(this.nCtx, t.NativeObject)); } /// /// Floating-point addition /// /// rounding mode term /// floating-point term /// floating-point term public FPExpr MkFPAdd(FPRMExpr rm, FPExpr t1, FPExpr t2) { return new FPExpr(this, Native.Z3_mk_fpa_add(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); } /// /// Floating-point subtraction /// /// rounding mode term /// floating-point term /// floating-point term public FPExpr MkFPSub(FPRMExpr rm, FPExpr t1, FPExpr t2) { return new FPExpr(this, Native.Z3_mk_fpa_sub(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); } /// /// Floating-point multiplication /// /// rounding mode term /// floating-point term /// floating-point term public FPExpr MkFPMul(FPRMExpr rm, FPExpr t1, FPExpr t2) { return new FPExpr(this, Native.Z3_mk_fpa_mul(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); } /// /// Floating-point division /// /// rounding mode term /// floating-point term /// floating-point term public FPExpr MkFPDiv(FPRMExpr rm, FPExpr t1, FPExpr t2) { return new FPExpr(this, Native.Z3_mk_fpa_div(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject)); } /// /// Floating-point fused multiply-add /// /// /// The result is round((t1 * t2) + t3) /// /// rounding mode term /// floating-point term /// floating-point term /// floating-point term public FPExpr MkFPFMA(FPRMExpr rm, FPExpr t1, FPExpr t2, FPExpr t3) { return new FPExpr(this, Native.Z3_mk_fpa_fma(this.nCtx, rm.NativeObject, t1.NativeObject, t2.NativeObject, t3.NativeObject)); } /// /// Floating-point square root /// /// rounding mode term /// floating-point term public FPExpr MkFPSqrt(FPRMExpr rm, FPExpr t) { return new FPExpr(this, Native.Z3_mk_fpa_sqrt(this.nCtx, rm.NativeObject, t.NativeObject)); } /// /// Floating-point remainder /// /// floating-point term /// floating-point term public FPExpr MkFPRem(FPExpr t1, FPExpr t2) { return new FPExpr(this, Native.Z3_mk_fpa_rem(this.nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Floating-point roundToIntegral. Rounds a floating-point number to /// the closest integer, again represented as a floating-point number. /// /// term of RoundingMode sort /// floating-point term public FPExpr MkFPRoundToIntegral(FPRMExpr rm, FPExpr t) { return new FPExpr(this, Native.Z3_mk_fpa_round_to_integral(this.nCtx, rm.NativeObject, t.NativeObject)); } /// /// Minimum of floating-point numbers. /// /// floating-point term /// floating-point term public FPExpr MkFPMin(FPExpr t1, FPExpr t2) { return new FPExpr(this, Native.Z3_mk_fpa_min(this.nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Maximum of floating-point numbers. /// /// floating-point term /// floating-point term public FPExpr MkFPMax(FPExpr t1, FPExpr t2) { return new FPExpr(this, Native.Z3_mk_fpa_max(this.nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Floating-point less than or equal. /// /// floating-point term /// floating-point term public BoolExpr MkFPLEq(FPExpr t1, FPExpr t2) { return new BoolExpr(this, Native.Z3_mk_fpa_leq(this.nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Floating-point less than. /// /// floating-point term /// floating-point term public BoolExpr MkFPLt(FPExpr t1, FPExpr t2) { return new BoolExpr(this, Native.Z3_mk_fpa_lt(this.nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Floating-point greater than or equal. /// /// floating-point term /// floating-point term public BoolExpr MkFPGEq(FPExpr t1, FPExpr t2) { return new BoolExpr(this, Native.Z3_mk_fpa_geq(this.nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Floating-point greater than. /// /// floating-point term /// floating-point term public BoolExpr MkFPGt(FPExpr t1, FPExpr t2) { return new BoolExpr(this, Native.Z3_mk_fpa_gt(this.nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Floating-point equality. /// /// /// Note that this is IEEE 754 equality (as opposed to standard =). /// /// floating-point term /// floating-point term public BoolExpr MkFPEq(FPExpr t1, FPExpr t2) { return new BoolExpr(this, Native.Z3_mk_fpa_eq(this.nCtx, t1.NativeObject, t2.NativeObject)); } /// /// Predicate indicating whether t is a normal floating-point number. /// /// floating-point term public BoolExpr MkFPIsNormal(FPExpr t) { return new BoolExpr(this, Native.Z3_mk_fpa_is_normal(this.nCtx, t.NativeObject)); } /// /// Predicate indicating whether t is a subnormal floating-point number. /// /// floating-point term public BoolExpr MkFPIsSubnormal(FPExpr t) { return new BoolExpr(this, Native.Z3_mk_fpa_is_subnormal(this.nCtx, t.NativeObject)); } /// /// Predicate indicating whether t is a floating-point number with zero value, i.e., +0 or -0. /// /// floating-point term public BoolExpr MkFPIsZero(FPExpr t) { return new BoolExpr(this, Native.Z3_mk_fpa_is_zero(this.nCtx, t.NativeObject)); } /// /// Predicate indicating whether t is a floating-point number representing +oo or -oo. /// /// floating-point term public BoolExpr MkFPIsInfinite(FPExpr t) { return new BoolExpr(this, Native.Z3_mk_fpa_is_infinite(this.nCtx, t.NativeObject)); } /// /// Predicate indicating whether t is a NaN. /// /// floating-point term public BoolExpr MkFPIsNaN(FPExpr t) { return new BoolExpr(this, Native.Z3_mk_fpa_is_nan(this.nCtx, t.NativeObject)); } /// /// Predicate indicating whether t is a negative floating-point number. /// /// floating-point term public BoolExpr MkFPIsNegative(FPExpr t) { return new BoolExpr(this, Native.Z3_mk_fpa_is_negative(this.nCtx, t.NativeObject)); } /// /// Predicate indicating whether t is a positive floating-point number. /// /// floating-point term public BoolExpr MkFPIsPositive(FPExpr t) { return new BoolExpr(this, Native.Z3_mk_fpa_is_positive(this.nCtx, t.NativeObject)); } #endregion #region Conversions to FloatingPoint terms /// /// Create an expression of FloatingPoint sort from three bit-vector expressions. /// /// /// This is the operator named `fp' in the SMT FP theory definition. /// Note that sgn is required to be a bit-vector of size 1. Significand and exponent /// are required to be greater than 1 and 2 respectively. The FloatingPoint sort /// of the resulting expression is automatically determined from the bit-vector sizes /// of the arguments. /// /// bit-vector term (of size 1) representing the sign. /// bit-vector term representing the significand. /// bit-vector term representing the exponent. public FPExpr MkFP(BitVecExpr sgn, BitVecExpr sig, BitVecExpr exp) { return new FPExpr(this, Native.Z3_mk_fpa_fp(this.nCtx, sgn.NativeObject, sig.NativeObject, exp.NativeObject)); } /// /// Conversion of a single IEEE 754-2008 bit-vector into a floating-point number. /// /// /// Produces a term that represents the conversion of a bit-vector term bv to a /// floating-point term of sort s. The bit-vector size of bv (m) must be equal /// to ebits+sbits of s. The format of the bit-vector is as defined by the /// IEEE 754-2008 interchange format. /// /// bit-vector value (of size m). /// FloatingPoint sort (ebits+sbits == m) public FPExpr MkFPToFP(BitVecExpr bv, FPSort s) { return new FPExpr(this, Native.Z3_mk_fpa_to_fp_bv(this.nCtx, bv.NativeObject, s.NativeObject)); } /// /// Conversion of a FloatingPoint term into another term of different FloatingPoint sort. /// /// /// Produces a term that represents the conversion of a floating-point term t to a /// floating-point term of sort s. If necessary, the result will be rounded according /// to rounding mode rm. /// /// RoundingMode term. /// FloatingPoint term. /// FloatingPoint sort. public FPExpr MkFPToFP(FPRMExpr rm, FPExpr t, FPSort s) { return new FPExpr(this, Native.Z3_mk_fpa_to_fp_float(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject)); } /// /// Conversion of a term of real sort into a term of FloatingPoint sort. /// /// /// Produces a term that represents the conversion of term t of real sort into a /// floating-point term of sort s. If necessary, the result will be rounded according /// to rounding mode rm. /// /// RoundingMode term. /// term of Real sort. /// FloatingPoint sort. public FPExpr MkFPToFP(FPRMExpr rm, RealExpr t, FPSort s) { return new FPExpr(this, Native.Z3_mk_fpa_to_fp_real(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject)); } /// /// Conversion of a 2's complement signed bit-vector term into a term of FloatingPoint sort. /// /// /// Produces a term that represents the conversion of the bit-vector term t into a /// floating-point term of sort s. The bit-vector t is taken to be in signed /// 2's complement format (when signed==true, otherwise unsigned). If necessary, the /// result will be rounded according to rounding mode rm. /// /// RoundingMode term. /// term of bit-vector sort. /// FloatingPoint sort. /// flag indicating whether t is interpreted as signed or unsigned bit-vector. public FPExpr MkFPToFP(FPRMExpr rm, BitVecExpr t, FPSort s, bool signed) { if (signed) return new FPExpr(this, Native.Z3_mk_fpa_to_fp_signed(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject)); else return new FPExpr(this, Native.Z3_mk_fpa_to_fp_unsigned(this.nCtx, rm.NativeObject, t.NativeObject, s.NativeObject)); } /// /// Conversion of a floating-point number to another FloatingPoint sort s. /// /// /// Produces a term that represents the conversion of a floating-point term t to a different /// FloatingPoint sort s. If necessary, rounding according to rm is applied. /// /// FloatingPoint sort /// floating-point rounding mode term /// floating-point term public FPExpr MkFPToFP(FPSort s, FPRMExpr rm, FPExpr t) { return new FPExpr(this, Native.Z3_mk_fpa_to_fp_float(this.nCtx, s.NativeObject, rm.NativeObject, t.NativeObject)); } #endregion #region Conversions from FloatingPoint terms /// /// Conversion of a floating-point term into a bit-vector. /// /// /// Produces a term that represents the conversion of the floating-point term t into a /// bit-vector term of size sz in 2's complement format (signed when signed==true). If necessary, /// the result will be rounded according to rounding mode rm. /// /// RoundingMode term. /// FloatingPoint term /// Size of the resulting bit-vector. /// Indicates whether the result is a signed or unsigned bit-vector. public BitVecExpr MkFPToBV(FPRMExpr rm, FPExpr t, uint sz, bool signed) { if (signed) return new BitVecExpr(this, Native.Z3_mk_fpa_to_sbv(this.nCtx, rm.NativeObject, t.NativeObject, sz)); else return new BitVecExpr(this, Native.Z3_mk_fpa_to_ubv(this.nCtx, rm.NativeObject, t.NativeObject, sz)); } /// /// Conversion of a floating-point term into a real-numbered term. /// /// /// Produces a term that represents the conversion of the floating-point term t into a /// real number. Note that this type of conversion will often result in non-linear /// constraints over real terms. /// /// FloatingPoint term public RealExpr MkFPToReal(FPExpr t) { return new RealExpr(this, Native.Z3_mk_fpa_to_real(this.nCtx, t.NativeObject)); } #endregion #region Z3-specific extensions /// /// Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. /// /// /// The size of the resulting bit-vector is automatically determined. Note that /// IEEE 754-2008 allows multiple different representations of NaN. This conversion /// knows only one NaN and it will always produce the same bit-vector representation of /// that NaN. /// /// FloatingPoint term. public BitVecExpr MkFPToIEEEBV(FPExpr t) { return new BitVecExpr(this, Native.Z3_mk_fpa_to_ieee_bv(this.nCtx, t.NativeObject)); } /// /// Conversion of a real-sorted significand and an integer-sorted exponent into a term of FloatingPoint sort. /// /// /// Produces a term that represents the conversion of sig * 2^exp into a /// floating-point term of sort s. If necessary, the result will be rounded /// according to rounding mode rm. /// /// RoundingMode term. /// Exponent term of Int sort. /// Significand term of Real sort. /// FloatingPoint sort. public BitVecExpr MkFPToFP(FPRMExpr rm, IntExpr exp, RealExpr sig, FPSort s) { return new BitVecExpr(this, Native.Z3_mk_fpa_to_fp_int_real(this.nCtx, rm.NativeObject, exp.NativeObject, sig.NativeObject, s.NativeObject)); } #endregion #endregion // Floating-point Arithmetic #region Miscellaneous /// /// Wraps an AST. /// /// This function is used for transitions between native and /// managed objects. Note that must be a /// native object obtained from Z3 (e.g., through ) /// and that it must have a correct reference count (see e.g., /// . /// /// The native pointer to wrap. public AST WrapAST(IntPtr nativeObject) { return AST.Create(this, nativeObject); } /// /// Unwraps an AST. /// /// This function is used for transitions between native and /// managed objects. It returns the native pointer to the AST. Note that /// AST objects are reference counted and unwrapping an AST disables automatic /// reference counting, i.e., all references to the IntPtr that is returned /// must be handled externally and through native calls (see e.g., /// ). /// /// The AST to unwrap. public IntPtr UnwrapAST(AST a) { return a.NativeObject; } /// /// Return a string describing all available parameters to Expr.Simplify. /// public string SimplifyHelp() { return Native.Z3_simplify_get_help(nCtx); } /// /// Retrieves parameter descriptions for simplifier. /// public ParamDescrs SimplifyParameterDescriptions { get { return new ParamDescrs(this, Native.Z3_simplify_get_param_descrs(nCtx)); } } #endregion #region Error Handling ///// ///// A delegate which is executed when an error is raised. ///// ///// ///// Note that it is possible for memory leaks to occur if error handlers ///// throw exceptions. ///// //public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString); ///// ///// The OnError event. ///// //public event ErrorHandler OnError = null; #endregion #region Parameters /// /// Update a mutable configuration parameter. /// /// /// The list of all configuration parameters can be obtained using the Z3 executable: /// z3.exe -p /// Only a few configuration parameters are mutable once the context is created. /// An exception is thrown when trying to modify an immutable parameter. /// public void UpdateParamValue(string id, string value) { Native.Z3_update_param_value(nCtx, id, value); } #endregion #region Internal internal IntPtr m_ctx = IntPtr.Zero; internal Native.Z3_error_handler m_n_err_handler = null; internal static Object creation_lock = new Object(); internal IntPtr nCtx { get { return m_ctx; } } internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode) { // Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors. } internal void InitContext() { PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT; m_n_err_handler = new Native.Z3_error_handler(NativeErrorHandler); // keep reference so it doesn't get collected. Native.Z3_set_error_handler(m_ctx, m_n_err_handler); GC.SuppressFinalize(this); } internal void CheckContextMatch(Z3Object other) { Debug.Assert(other != null); if (!ReferenceEquals(this, other.Context)) throw new Z3Exception("Context mismatch"); } internal void CheckContextMatch(Z3Object other1, Z3Object other2) { Debug.Assert(other1 != null); Debug.Assert(other2 != null); CheckContextMatch(other1); CheckContextMatch(other2); } internal void CheckContextMatch(Z3Object other1, Z3Object other2, Z3Object other3) { Debug.Assert(other1 != null); Debug.Assert(other2 != null); Debug.Assert(other3 != null); CheckContextMatch(other1); CheckContextMatch(other2); CheckContextMatch(other3); } internal void CheckContextMatch(Z3Object[] arr) { Debug.Assert(arr == null || arr.All(a => a != null)); if (arr != null) { foreach (Z3Object a in arr) { Debug.Assert(a != null); // It was an assume, now we added the precondition, and we made it into an assert CheckContextMatch(a); } } } internal void CheckContextMatch(IEnumerable arr) where T : Z3Object { Debug.Assert(arr == null || arr.All(a => a != null)); if (arr != null) { foreach (Z3Object a in arr) { Debug.Assert(a != null); // It was an assume, now we added the precondition, and we made it into an assert CheckContextMatch(a); } } } private void ObjectInvariant() { Debug.Assert(m_AST_DRQ != null); Debug.Assert(m_ASTMap_DRQ != null); Debug.Assert(m_ASTVector_DRQ != null); Debug.Assert(m_ApplyResult_DRQ != null); Debug.Assert(m_FuncEntry_DRQ != null); Debug.Assert(m_FuncInterp_DRQ != null); Debug.Assert(m_Goal_DRQ != null); Debug.Assert(m_Model_DRQ != null); Debug.Assert(m_Params_DRQ != null); Debug.Assert(m_ParamDescrs_DRQ != null); Debug.Assert(m_Probe_DRQ != null); Debug.Assert(m_Solver_DRQ != null); Debug.Assert(m_Statistics_DRQ != null); Debug.Assert(m_Tactic_DRQ != null); Debug.Assert(m_Fixedpoint_DRQ != null); Debug.Assert(m_Optimize_DRQ != null); } readonly private AST.DecRefQueue m_AST_DRQ = new AST.DecRefQueue(); readonly private ASTMap.DecRefQueue m_ASTMap_DRQ = new ASTMap.DecRefQueue(10); readonly private ASTVector.DecRefQueue m_ASTVector_DRQ = new ASTVector.DecRefQueue(10); readonly private ApplyResult.DecRefQueue m_ApplyResult_DRQ = new ApplyResult.DecRefQueue(10); readonly private FuncInterp.Entry.DecRefQueue m_FuncEntry_DRQ = new FuncInterp.Entry.DecRefQueue(10); readonly private FuncInterp.DecRefQueue m_FuncInterp_DRQ = new FuncInterp.DecRefQueue(10); readonly private Goal.DecRefQueue m_Goal_DRQ = new Goal.DecRefQueue(10); readonly private Model.DecRefQueue m_Model_DRQ = new Model.DecRefQueue(10); readonly private Params.DecRefQueue m_Params_DRQ = new Params.DecRefQueue(10); readonly private ParamDescrs.DecRefQueue m_ParamDescrs_DRQ = new ParamDescrs.DecRefQueue(10); readonly private Probe.DecRefQueue m_Probe_DRQ = new Probe.DecRefQueue(10); readonly private Solver.DecRefQueue m_Solver_DRQ = new Solver.DecRefQueue(10); readonly private Statistics.DecRefQueue m_Statistics_DRQ = new Statistics.DecRefQueue(10); readonly private Tactic.DecRefQueue m_Tactic_DRQ = new Tactic.DecRefQueue(10); readonly private Fixedpoint.DecRefQueue m_Fixedpoint_DRQ = new Fixedpoint.DecRefQueue(10); readonly private Optimize.DecRefQueue m_Optimize_DRQ = new Optimize.DecRefQueue(10); /// /// AST DRQ /// public IDecRefQueue AST_DRQ { get { return m_AST_DRQ; } } /// /// ASTMap DRQ /// public IDecRefQueue ASTMap_DRQ { get { return m_ASTMap_DRQ; } } /// /// ASTVector DRQ /// public IDecRefQueue ASTVector_DRQ { get { return m_ASTVector_DRQ; } } /// /// ApplyResult DRQ /// public IDecRefQueue ApplyResult_DRQ { get { return m_ApplyResult_DRQ; } } /// /// FuncEntry DRQ /// public IDecRefQueue FuncEntry_DRQ { get { return m_FuncEntry_DRQ; } } /// /// FuncInterp DRQ /// public IDecRefQueue FuncInterp_DRQ { get { return m_FuncInterp_DRQ; } } /// /// Goal DRQ /// public IDecRefQueue Goal_DRQ { get { return m_Goal_DRQ; } } /// /// Model DRQ /// public IDecRefQueue Model_DRQ { get { return m_Model_DRQ; } } /// /// Params DRQ /// public IDecRefQueue Params_DRQ { get { return m_Params_DRQ; } } /// /// ParamDescrs DRQ /// public IDecRefQueue ParamDescrs_DRQ { get { return m_ParamDescrs_DRQ; } } /// /// Probe DRQ /// public IDecRefQueue Probe_DRQ { get { return m_Probe_DRQ; } } /// /// Solver DRQ /// public IDecRefQueue Solver_DRQ { get { return m_Solver_DRQ; } } /// /// Statistics DRQ /// public IDecRefQueue Statistics_DRQ { get { return m_Statistics_DRQ; } } /// /// Tactic DRQ /// public IDecRefQueue Tactic_DRQ { get { return m_Tactic_DRQ; } } /// /// FixedPoint DRQ /// public IDecRefQueue Fixedpoint_DRQ { get { return m_Fixedpoint_DRQ; } } /// /// Optimize DRQ /// public IDecRefQueue Optimize_DRQ { get { return m_Fixedpoint_DRQ; } } internal long refCount = 0; /// /// Finalizer. /// ~Context() { // Console.WriteLine("Context Finalizer from " + System.Threading.Thread.CurrentThread.ManagedThreadId); Dispose(); } /// /// Disposes of the context. /// public void Dispose() { // Console.WriteLine("Context Dispose from " + System.Threading.Thread.CurrentThread.ManagedThreadId); AST_DRQ.Clear(this); ASTMap_DRQ.Clear(this); ASTVector_DRQ.Clear(this); ApplyResult_DRQ.Clear(this); FuncEntry_DRQ.Clear(this); FuncInterp_DRQ.Clear(this); Goal_DRQ.Clear(this); Model_DRQ.Clear(this); Params_DRQ.Clear(this); ParamDescrs_DRQ.Clear(this); Probe_DRQ.Clear(this); Solver_DRQ.Clear(this); Statistics_DRQ.Clear(this); Tactic_DRQ.Clear(this); Fixedpoint_DRQ.Clear(this); Optimize_DRQ.Clear(this); m_boolSort = null; m_intSort = null; m_realSort = null; m_stringSort = null; if (refCount == 0 && m_ctx != IntPtr.Zero) { m_n_err_handler = null; IntPtr ctx = m_ctx; m_ctx = IntPtr.Zero; Native.Z3_del_context(ctx); } else GC.ReRegisterForFinalize(this); } #endregion } }