/*++ Copyright (c) 2012 Microsoft Corporation Module Name: Goal.cs Abstract: Z3 Managed API: Goal Author: Christoph Wintersteiger (cwinter) 2012-03-21 Notes: --*/ using System; using System.Diagnostics; using System.Linq; namespace Microsoft.Z3 { /// /// A goal (aka problem). A goal is essentially a set /// of formulas, that can be solved and/or transformed using /// tactics and solvers. /// public class Goal : Z3Object { /// /// The precision of the goal. /// /// /// Goals can be transformed using over and under approximations. /// An under approximation is applied when the objective is to find a model for a given goal. /// An over approximation is applied when the objective is to find a proof for a given goal. /// public Z3_goal_prec Precision { get { return (Z3_goal_prec)Native.Z3_goal_precision(Context.nCtx, NativeObject); } } /// /// Indicates whether the goal is precise. /// public bool IsPrecise { get { return Precision == Z3_goal_prec.Z3_GOAL_PRECISE; } } /// /// Indicates whether the goal is an under-approximation. /// public bool IsUnderApproximation { get { return Precision == Z3_goal_prec.Z3_GOAL_UNDER; } } /// /// Indicates whether the goal is an over-approximation. /// public bool IsOverApproximation { get { return Precision == Z3_goal_prec.Z3_GOAL_OVER; } } /// /// Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). /// public bool IsGarbage { get { return Precision == Z3_goal_prec.Z3_GOAL_UNDER_OVER; } } /// /// Adds the to the given goal. /// public void Assert(params BoolExpr[] constraints) { Debug.Assert(constraints != null); Debug.Assert(constraints.All(c => c != null)); Context.CheckContextMatch(constraints); foreach (BoolExpr c in constraints) { Debug.Assert(c != null); // It was an assume, now made an assert just to be sure we do not regress Native.Z3_goal_assert(Context.nCtx, NativeObject, c.NativeObject); } } /// /// Alias for Assert. /// public void Add(params BoolExpr[] constraints) { Assert(constraints); } /// /// Indicates whether the goal contains `false'. /// public bool Inconsistent { get { return Native.Z3_goal_inconsistent(Context.nCtx, NativeObject) != 0; } } /// /// The depth of the goal. /// /// /// This tracks how many transformations were applied to it. /// public uint Depth { get { return Native.Z3_goal_depth(Context.nCtx, NativeObject); } } /// /// Erases all formulas from the given goal. /// public void Reset() { Native.Z3_goal_reset(Context.nCtx, NativeObject); } /// /// The number of formulas in the goal. /// public uint Size { get { return Native.Z3_goal_size(Context.nCtx, NativeObject); } } /// /// The formulas in the goal. /// public BoolExpr[] Formulas { get { uint n = Size; BoolExpr[] res = new BoolExpr[n]; for (uint i = 0; i < n; i++) res[i] = (BoolExpr)Expr.Create(Context, Native.Z3_goal_formula(Context.nCtx, NativeObject, i)); return res; } } /// /// The number of formulas, subformulas and terms in the goal. /// public uint NumExprs { get { return Native.Z3_goal_num_exprs(Context.nCtx, NativeObject); } } /// /// Indicates whether the goal is empty, and it is precise or the product of an under approximation. /// public bool IsDecidedSat { get { return Native.Z3_goal_is_decided_sat(Context.nCtx, NativeObject) != 0; } } /// /// Indicates whether the goal contains `false', and it is precise or the product of an over approximation. /// public bool IsDecidedUnsat { get { return Native.Z3_goal_is_decided_unsat(Context.nCtx, NativeObject) != 0; } } /// /// Convert a model for the goal into a model of the /// original goal from which this goal was derived. /// /// A model for g public Model ConvertModel(Model m) { if (m != null) return new Model(Context, Native.Z3_goal_convert_model(Context.nCtx, NativeObject, m.NativeObject)); else return new Model(Context, Native.Z3_goal_convert_model(Context.nCtx, NativeObject, IntPtr.Zero)); } /// /// Translates (copies) the Goal to the target Context . /// public Goal Translate(Context ctx) { Debug.Assert(ctx != null); return new Goal(ctx, Native.Z3_goal_translate(Context.nCtx, NativeObject, ctx.nCtx)); } /// /// Simplifies the goal. /// /// Essentially invokes the `simplify' tactic on the goal. public Goal Simplify(Params p = null) { Tactic t = Context.MkTactic("simplify"); ApplyResult res = t.Apply(this, p); if (res.NumSubgoals == 0) throw new Z3Exception("No subgoals"); else return res.Subgoals[0]; } /// /// Goal to string conversion. /// /// A string representation of the Goal. public override string ToString() { return Native.Z3_goal_to_string(Context.nCtx, NativeObject); } /// /// Goal to DIMACS formatted string conversion. /// /// A string representation of the Goal. public string ToDimacs() { return Native.Z3_goal_to_dimacs_string(Context.nCtx, NativeObject); } /// /// Goal to BoolExpr conversion. /// /// A string representation of the Goal. public BoolExpr AsBoolExpr() { uint n = Size; if (n == 0) return Context.MkTrue(); else if (n == 1) return Formulas[0]; else { return Context.MkAnd(Formulas); } } #region Internal internal Goal(Context ctx, IntPtr obj) : base(ctx, obj) { Debug.Assert(ctx != null); } internal Goal(Context ctx, bool models, bool unsatCores, bool proofs) : base(ctx, Native.Z3_mk_goal(ctx.nCtx, (byte)(models ? 1 : 0), (byte)(unsatCores ? 1 : 0), (byte)(proofs ? 1 : 0))) { Debug.Assert(ctx != null); } internal class DecRefQueue : IDecRefQueue { public DecRefQueue() : base() { } public DecRefQueue(uint move_limit) : base(move_limit) { } internal override void IncRef(Context ctx, IntPtr obj) { Native.Z3_goal_inc_ref(ctx.nCtx, obj); } internal override void DecRef(Context ctx, IntPtr obj) { Native.Z3_goal_dec_ref(ctx.nCtx, obj); } }; internal override void IncRef(IntPtr o) { Context.Goal_DRQ.IncAndClear(Context, o); base.IncRef(o); } internal override void DecRef(IntPtr o) { Context.Goal_DRQ.Add(o); base.DecRef(o); } #endregion } }