/// <summary> /// Add constraints to ensure the function f can only be injective. /// Example: /// for function f : D1 x D2 -> R /// assert axioms /// forall (x1 : D1, x2 : D2) x1 = inv1(f(x1,x2)) /// forall (x1 : D1, x2 : D2) x2 = inv2(f(x1,x2)) /// </summary> /// <param name="f"></param> public void AssertInjective(Z3_func_decl f) { uint arity = Native.Z3_get_arity(nCtx, f); Z3_sort range = Native.Z3_get_range(nCtx, f); Z3_ast[] vars = new Z3_ast[arity]; Z3_sort[] sorts = new Z3_sort[arity]; Z3_symbol[] names = new Z3_symbol[arity]; for (uint i = 0; i < arity; ++i) { Z3_sort domain = Native.Z3_get_domain(nCtx, f, i); vars[i] = ntvContext.MkBound(arity - i - 1, domain); sorts[i] = domain; names[i] = Native.Z3_mk_int_symbol(nCtx, (int)i); } Z3_ast app_f = IntPtr.Zero; // Context.MkApp(f, vars); for (uint i = 0; i < arity; ++i) { Z3_sort domain = Native.Z3_get_domain(nCtx, f, i); Z3_func_decl proj = ntvContext.MkFreshFuncDecl("inv", new Z3_sort[] { range }, domain); Z3_ast body = ntvContext.MkEq(vars[i], ntvContext.MkApp(proj, app_f)); Z3_ast q = ntvContext.MkForall(names, sorts, body); Assert(q); } }
/// <summary> /// Create a new tuple sort. /// </summary> public Z3_sort MkTupleSort(Z3_symbol name, Z3_symbol[] fieldNames, Z3_sort[] fieldSorts, out Z3_func_decl constructor, Z3_func_decl[] projections) { Debug.Assert(name != IntPtr.Zero); Debug.Assert(fieldNames != null); Debug.Assert(fieldNames.All(fn => fn != IntPtr.Zero)); Debug.Assert(fieldSorts == null || fieldSorts.All(fs => fs != IntPtr.Zero)); var numFields = (uint)(fieldNames?.Length ?? 0); constructor = IntPtr.Zero; return(Native.Z3_mk_tuple_sort(nCtx, name, numFields, fieldNames, fieldSorts, ref constructor, projections)); }