From bf14aeb1bde040e8a5c7fb5100b8dcb3198af67a Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 2 Mar 2022 10:06:38 -0800 Subject: [PATCH] stub out nativesolver --- src/api/dotnet/CMakeLists.txt | 1 + src/api/dotnet/NativeContext.cs | 18 ++ src/api/dotnet/NativeSolver.cs | 540 ++++++++++++++++++++++++++++++++ 3 files changed, 559 insertions(+) create mode 100644 src/api/dotnet/NativeSolver.cs diff --git a/src/api/dotnet/CMakeLists.txt b/src/api/dotnet/CMakeLists.txt index 25b3136ad39..e2055cd7a00 100644 --- a/src/api/dotnet/CMakeLists.txt +++ b/src/api/dotnet/CMakeLists.txt @@ -88,6 +88,7 @@ set(Z3_DOTNET_ASSEMBLY_SOURCES_IN_SRC_TREE NativeContext.cs NativeFuncInterp.cs NativeModel.cs + NativeSolver.cs Optimize.cs ParamDescrs.cs Params.cs diff --git a/src/api/dotnet/NativeContext.cs b/src/api/dotnet/NativeContext.cs index a8676e05b73..a13e48bf7bb 100644 --- a/src/api/dotnet/NativeContext.cs +++ b/src/api/dotnet/NativeContext.cs @@ -179,5 +179,23 @@ internal void InitContext() #endregion + + /// + /// Utility to convert a vector object of ast to a .Net array + /// + /// + /// + public Z3_ast[] ToArray(Z3_ast_vector vec) + { + Native.Z3_ast_vector_inc_ref(nCtx, vec); + var sz = Native.Z3_ast_vector_size(nCtx, vec); + var result = new Z3_ast[sz]; + for (uint i = 0; i < sz; ++i) + result[i] = Native.Z3_ast_vector_get(nCtx, vec, i); + Native.Z3_ast_vector_dec_ref(nCtx, vec); + return result; + + } + } } \ No newline at end of file diff --git a/src/api/dotnet/NativeSolver.cs b/src/api/dotnet/NativeSolver.cs new file mode 100644 index 00000000000..0c494fa3309 --- /dev/null +++ b/src/api/dotnet/NativeSolver.cs @@ -0,0 +1,540 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + NativeSolver.cs + +Abstract: + + Z3 Managed API: Native Solver + +Author: + + Christoph Wintersteiger (cwinter) 2012-03-22 + Nikolaj Bjorner (nbjorner) 2022-03-01 + +Notes: + +--*/ + +using System; +using System.Diagnostics; +using System.Linq; +using System.Collections.Generic; + +namespace Microsoft.Z3 +{ + + using Z3_context = System.IntPtr; + using Z3_ast = System.IntPtr; + using Z3_app = System.IntPtr; + using Z3_sort = System.IntPtr; + using Z3_func_decl = System.IntPtr; + using Z3_model = System.IntPtr; + using Z3_func_interp = System.IntPtr; + using Z3_func_entry = System.IntPtr; + using Z3_ast_vector = System.IntPtr; + using Z3_solver = System.IntPtr; + + /// + /// Solvers. + /// + public class NativeSolver : IDisposable + { + /// + /// A string that describes all available solver parameters. + /// + public string Help + { + get + { + + return Native.Z3_solver_get_help(Context.nCtx, NativeObject); + } + } + + /// + /// Sets the solver parameters. + /// + public Params Parameters + { + set + { + Debug.Assert(value != null); + + Native.Z3_solver_set_params(Context.nCtx, NativeObject, value.NativeObject); + } + } + +#if false + /// + /// Sets parameter on the solver + /// + public void Set(string name, bool value) { Parameters = Context.MkParams().Add(name, value); } + /// + /// Sets parameter on the solver + /// + public void Set(string name, uint value) { Parameters = Context.MkParams().Add(name, value); } + /// + /// Sets parameter on the solver + /// + public void Set(string name, double value) { Parameters = Context.MkParams().Add(name, value); } + /// + /// Sets parameter on the solver + /// + public void Set(string name, string value) { Parameters = Context.MkParams().Add(name, value); } + /// + /// Sets parameter on the solver + /// + public void Set(string name, Symbol value) { Parameters = Context.MkParams().Add(name, value); } + /// + /// Sets parameter on the solver + /// + public void Set(Symbol name, bool value) { Parameters = Context.MkParams().Add(name, value); } + /// + /// Sets parameter on the solver + /// + public void Set(Symbol name, uint value) { Parameters = Context.MkParams().Add(name, value); } + /// + /// Sets parameter on the solver + /// + public void Set(Symbol name, double value) { Parameters = Context.MkParams().Add(name, value); } + /// + /// Sets parameter on the solver + /// + public void Set(Symbol name, string value) { Parameters = Context.MkParams().Add(name, value); } + /// + /// Sets parameter on the solver + /// + public void Set(Symbol name, Symbol value) { Parameters = Context.MkParams().Add(name, value); } + + /// + /// Retrieves parameter descriptions for solver. + /// + public ParamDescrs ParameterDescriptions + { + get { return new ParamDescrs(Context, Native.Z3_solver_get_param_descrs(Context.nCtx, NativeObject)); } + } + +#endif + + /// + /// The current number of backtracking points (scopes). + /// + /// + /// + public uint NumScopes + { + get { return Native.Z3_solver_get_num_scopes(Context.nCtx, NativeObject); } + } + + /// + /// Creates a backtracking point. + /// + /// + public void Push() + { + Native.Z3_solver_push(Context.nCtx, NativeObject); + } + + /// + /// Backtracks backtracking points. + /// + /// Note that an exception is thrown if is not smaller than NumScopes + /// + public void Pop(uint n = 1) + { + Native.Z3_solver_pop(Context.nCtx, NativeObject, n); + } + + /// + /// Resets the Solver. + /// + /// This removes all assertions from the solver. + public void Reset() + { + Native.Z3_solver_reset(Context.nCtx, NativeObject); + } + + /// + /// Assert a constraint (or multiple) into the solver. + /// + public void Assert(params Z3_ast[] constraints) + { + Debug.Assert(constraints != null); + Debug.Assert(constraints.All(c => c != IntPtr.Zero)); + + foreach (Z3_ast a in constraints) + { + Native.Z3_solver_assert(Context.nCtx, NativeObject, a); + } + } + + /// + /// Alias for Assert. + /// + public void Add(params Z3_ast[] constraints) + { + Assert(constraints); + } + + /// + /// Alias for Assert. + /// + public void Add(IEnumerable constraints) + { + Assert(constraints.ToArray()); + } + + /// + /// Assert multiple constraints into the solver, and track them (in the unsat) core + /// using the Boolean constants in ps. + /// + /// + /// This API is an alternative to with assumptions for extracting unsat cores. + /// Both APIs can be used in the same solver. The unsat core will contain a combination + /// of the Boolean variables provided using + /// and the Boolean literals + /// provided using with assumptions. + /// + public void AssertAndTrack(Z3_ast[] constraints, Z3_ast[] ps) + { + Debug.Assert(constraints != null); + Debug.Assert(constraints.All(c => c != IntPtr.Zero)); + Debug.Assert(ps.All(c => c != IntPtr.Zero)); + if (constraints.Length != ps.Length) + throw new Z3Exception("Argument size mismatch"); + + for (int i = 0; i < constraints.Length; i++) + Native.Z3_solver_assert_and_track(Context.nCtx, NativeObject, constraints[i], ps[i]); + } + + /// + /// Assert a constraint into the solver, and track it (in the unsat) core + /// using the Boolean constant p. + /// + /// + /// This API is an alternative to with assumptions for extracting unsat cores. + /// Both APIs can be used in the same solver. The unsat core will contain a combination + /// of the Boolean variables provided using + /// and the Boolean literals + /// provided using with assumptions. + /// + public void AssertAndTrack(Z3_ast constraint, Z3_ast p) + { + Debug.Assert(constraint != null); + Debug.Assert(p != null); + + Native.Z3_solver_assert_and_track(Context.nCtx, NativeObject, constraint, p); + } + + /// + /// Load solver assertions from a file. + /// + public void FromFile(string file) + { + Native.Z3_solver_from_file(Context.nCtx, NativeObject, file); + } + + /// + /// Load solver assertions from a string. + /// + public void FromString(string str) + { + Native.Z3_solver_from_string(Context.nCtx, NativeObject, str); + } + + /// + /// The number of assertions in the solver. + /// + public uint NumAssertions + { + get + { + var assertions = Native.Z3_solver_get_assertions(Context.nCtx, NativeObject); + Native.Z3_ast_vector_inc_ref(Context.nCtx, assertions); + var sz = Native.Z3_ast_vector_size(Context.nCtx, assertions); + Native.Z3_ast_vector_dec_ref(Context.nCtx, assertions); + return sz; + } + } + + /// + /// The set of asserted formulas. + /// + public Z3_ast[] Assertions + { + get + { + var assertions = Native.Z3_solver_get_assertions(Context.nCtx, NativeObject); + return Context.ToArray(assertions); + } + } + + /// + /// Currently inferred units. + /// + public Z3_ast[] Units + { + get + { + var units = Native.Z3_solver_get_units(Context.nCtx, NativeObject); + return Context.ToArray(units); + } + } + + /// + /// Checks whether the assertions in the solver are consistent or not. + /// + /// + /// + /// + /// + /// + public Status Check(params Z3_ast[] assumptions) + { + Z3_lbool r; + if (assumptions == null || assumptions.Length == 0) + r = (Z3_lbool)Native.Z3_solver_check(Context.nCtx, NativeObject); + else + r = (Z3_lbool)Native.Z3_solver_check_assumptions(Context.nCtx, NativeObject, (uint)assumptions.Length, assumptions); + return lboolToStatus(r); + } + + /// + /// Checks whether the assertions in the solver are consistent or not. + /// + /// + /// + /// + /// + /// + public Status Check(IEnumerable assumptions) + { + Z3_lbool r; + Z3_ast[] asms = assumptions.ToArray(); + if (asms.Length == 0) + r = (Z3_lbool)Native.Z3_solver_check(Context.nCtx, NativeObject); + else + r = (Z3_lbool)Native.Z3_solver_check_assumptions(Context.nCtx, NativeObject, (uint)asms.Length, asms); + return lboolToStatus(r); + } + +#if false + /// + /// Retrieve fixed assignments to the set of variables in the form of consequences. + /// Each consequence is an implication of the form + /// + /// relevant-assumptions Implies variable = value + /// + /// where the relevant assumptions is a subset of the assumptions that are passed in + /// and the equality on the right side of the implication indicates how a variable + /// is fixed. + /// + /// + /// + /// + /// + /// + public Status Consequences(IEnumerable assumptions, IEnumerable variables, out Z3_ast[] consequences) + { + ASTVector result = new ASTVector(Context); + ASTVector asms = new ASTVector(Context); + ASTVector vars = new ASTVector(Context); + foreach (var asm in assumptions) asms.Push(asm); + foreach (var v in variables) vars.Push(v); + Z3_lbool r = (Z3_lbool)Native.Z3_solver_get_consequences(Context.nCtx, NativeObject, asms.NativeObject, vars.NativeObject, result.NativeObject); + consequences = result.ToBoolExprArray(); + return lboolToStatus(r); + } +#endif + + /// + /// The model of the last Check(params Expr[] assumptions). + /// + /// + /// The result is null if Check(params Expr[] assumptions) was not invoked before, + /// if its results was not SATISFIABLE, or if model production is not enabled. + /// + public NativeModel Model + { + get + { + IntPtr x = Native.Z3_solver_get_model(Context.nCtx, NativeObject); + if (x == IntPtr.Zero) + return null; + else + return new NativeModel(Context, x); + } + } + + /// + /// The proof of the last Check(params Expr[] assumptions). + /// + /// + /// The result is null if Check(params Expr[] assumptions) was not invoked before, + /// if its results was not UNSATISFIABLE, or if proof production is disabled. + /// + public Z3_ast Proof + { + get + { + return Native.Z3_solver_get_proof(Context.nCtx, NativeObject); + } + } + + /// + /// The unsat core of the last Check. + /// + /// + /// The unsat core is a subset of Assertions + /// The result is empty if Check was not invoked before, + /// if its results was not UNSATISFIABLE, or if core production is disabled. + /// + public Z3_ast[] UnsatCore + { + get + { + return Context.ToArray(Native.Z3_solver_get_unsat_core(Context.nCtx, NativeObject)); + } + } + + /// + /// A brief justification of why the last call to Check returned UNKNOWN. + /// + public string ReasonUnknown + { + get + { + return Native.Z3_solver_get_reason_unknown(Context.nCtx, NativeObject); + } + } + + /// + /// Backtrack level that can be adjusted by conquer process + /// + public uint BacktrackLevel { get; set; } + +#if false + /// + /// Variables available and returned by the cuber. + /// + public Z3_ast[] CubeVariables { get; set; } + + + /// + /// Return a set of cubes. + /// + public IEnumerable Cube() + { + ASTVector cv = new ASTVector(Context); + if (CubeVariables != null) + foreach (var b in CubeVariables) cv.Push(b); + + while (true) + { + var lvl = BacktrackLevel; + BacktrackLevel = uint.MaxValue; + ASTVector r = new ASTVector(Context, Native.Z3_solver_cube(Context.nCtx, NativeObject, cv.NativeObject, lvl)); + var v = r.ToBoolExprArray(); + CubeVariables = cv.ToBoolExprArray(); + if (v.Length == 1 && v[0].IsFalse) + { + break; + } + yield return v; + if (v.Length == 0) + { + break; + } + } + } +#endif + /// + /// Create a clone of the current solver with respect to ctx. + /// + public NativeSolver Translate(NativeContext ctx) + { + Debug.Assert(ctx != null); + return new NativeSolver(ctx, Native.Z3_solver_translate(Context.nCtx, NativeObject, ctx.nCtx)); + } + + /// + /// Import model converter from other solver. + /// + public void ImportModelConverter(NativeSolver src) + { + Native.Z3_solver_import_model_converter(Context.nCtx, src.NativeObject, NativeObject); + } + +#if false + /// + /// Solver statistics. + /// + public Statistics Statistics + { + get + { + + return new Statistics(Context, Native.Z3_solver_get_statistics(Context.nCtx, NativeObject)); + } + } +#endif + + /// + /// A string representation of the solver. + /// + public override string ToString() + { + return Native.Z3_solver_to_string(Context.nCtx, NativeObject); + } + +#region Internal + NativeContext Context; + IntPtr NativeObject; + internal NativeSolver(NativeContext ctx, Z3_solver obj) + { + Context = ctx; + NativeObject = obj; + + Debug.Assert(ctx != null); + this.BacktrackLevel = uint.MaxValue; + Native.Z3_solver_inc_ref(ctx.nCtx, obj); + } + + /// + /// Finalizer. + /// + ~NativeSolver() + { + Dispose(); + } + + /// + /// Disposes of the underlying native Z3 object. + /// + public void Dispose() + { + if (NativeObject != IntPtr.Zero) + { + Native.Z3_solver_dec_ref(Context.nCtx, NativeObject); + NativeObject = IntPtr.Zero; + } + GC.SuppressFinalize(this); + } + + + private Status lboolToStatus(Z3_lbool r) + { + switch (r) + { + case Z3_lbool.Z3_L_TRUE: return Status.SATISFIABLE; + case Z3_lbool.Z3_L_FALSE: return Status.UNSATISFIABLE; + default: return Status.UNKNOWN; + } + } + +#endregion + } +}