3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-05 21:53:23 +00:00
z3/src/api/dotnet/Goal.cs
Nikolaj Bjorner edeeded4ea
remove DecRefQueue, use Z3_enable_concurrent_dec_ref (#6332)
The notion of reference counted contexts never worked.
The reference count to a context only ends up being 0 if the GC kicks in and disposes the various z3 objects. A call to Dispose on Context should free up all resources associated with that context. In exchange none of the resources are allowed any other operation than DecRef. The invocations of DecRef are protected by a lock and test on the context that the native pointer associated with the context is non-zero. Dispose sets the native pointer to zero.

Z3_enable_concurrent_dec_ref ensures that:

- calls to decref are thread safe. Other threads can operate on the context without interference.

The Z3_context ensures that
- z3objects allocated, but not disposed during the lifetime of Z3_context are freed when Z3_context is deleted (it triggers a debug warning, but this is now benign).
2022-09-11 18:59:00 -07:00

273 lines
8.2 KiB
C#

/*++
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
{
/// <summary>
/// A goal (aka problem). A goal is essentially a set
/// of formulas, that can be solved and/or transformed using
/// tactics and solvers.
/// </summary>
public class Goal : Z3Object
{
/// <summary>
/// The precision of the goal.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
public Z3_goal_prec Precision
{
get { return (Z3_goal_prec)Native.Z3_goal_precision(Context.nCtx, NativeObject); }
}
/// <summary>
/// Indicates whether the goal is precise.
/// </summary>
public bool IsPrecise
{
get { return Precision == Z3_goal_prec.Z3_GOAL_PRECISE; }
}
/// <summary>
/// Indicates whether the goal is an under-approximation.
/// </summary>
public bool IsUnderApproximation
{
get { return Precision == Z3_goal_prec.Z3_GOAL_UNDER; }
}
/// <summary>
/// Indicates whether the goal is an over-approximation.
/// </summary>
public bool IsOverApproximation
{
get { return Precision == Z3_goal_prec.Z3_GOAL_OVER; }
}
/// <summary>
/// Indicates whether the goal is garbage (i.e., the product of over- and under-approximations).
/// </summary>
public bool IsGarbage
{
get { return Precision == Z3_goal_prec.Z3_GOAL_UNDER_OVER; }
}
/// <summary>
/// Adds the <paramref name="constraints"/> to the given goal.
/// </summary>
public void Assert(params BoolExpr[] constraints)
{
Debug.Assert(constraints != null);
Debug.Assert(constraints.All(c => c != null));
Context.CheckContextMatch<BoolExpr>(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);
}
}
/// <summary>
/// Alias for Assert.
/// </summary>
public void Add(params BoolExpr[] constraints)
{
Assert(constraints);
}
/// <summary>
/// Indicates whether the goal contains `false'.
/// </summary>
public bool Inconsistent
{
get { return Native.Z3_goal_inconsistent(Context.nCtx, NativeObject) != 0; }
}
/// <summary>
/// The depth of the goal.
/// </summary>
/// <remarks>
/// This tracks how many transformations were applied to it.
/// </remarks>
public uint Depth
{
get { return Native.Z3_goal_depth(Context.nCtx, NativeObject); }
}
/// <summary>
/// Erases all formulas from the given goal.
/// </summary>
public void Reset()
{
Native.Z3_goal_reset(Context.nCtx, NativeObject);
}
/// <summary>
/// The number of formulas in the goal.
/// </summary>
public uint Size
{
get { return Native.Z3_goal_size(Context.nCtx, NativeObject); }
}
/// <summary>
/// The formulas in the goal.
/// </summary>
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;
}
}
/// <summary>
/// The number of formulas, subformulas and terms in the goal.
/// </summary>
public uint NumExprs
{
get { return Native.Z3_goal_num_exprs(Context.nCtx, NativeObject); }
}
/// <summary>
/// Indicates whether the goal is empty, and it is precise or the product of an under approximation.
/// </summary>
public bool IsDecidedSat
{
get { return Native.Z3_goal_is_decided_sat(Context.nCtx, NativeObject) != 0; }
}
/// <summary>
/// Indicates whether the goal contains `false', and it is precise or the product of an over approximation.
/// </summary>
public bool IsDecidedUnsat
{
get { return Native.Z3_goal_is_decided_unsat(Context.nCtx, NativeObject) != 0; }
}
/// <summary>
/// Convert a model for the goal into a model of the
/// original goal from which this goal was derived.
/// </summary>
/// <returns>A model for <c>g</c></returns>
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));
}
/// <summary>
/// Translates (copies) the Goal to the target Context <paramref name="ctx"/>.
/// </summary>
public Goal Translate(Context ctx)
{
Debug.Assert(ctx != null);
return new Goal(ctx, Native.Z3_goal_translate(Context.nCtx, NativeObject, ctx.nCtx));
}
/// <summary>
/// Simplifies the goal.
/// </summary>
/// <remarks>Essentially invokes the `simplify' tactic on the goal.</remarks>
public Goal Simplify(Params p = null)
{
using Tactic t = Context.MkTactic("simplify");
using ApplyResult res = t.Apply(this, p);
if (res.NumSubgoals == 0)
throw new Z3Exception("No subgoals");
else
return res.Subgoals[0];
}
/// <summary>
/// Goal to string conversion.
/// </summary>
/// <returns>A string representation of the Goal.</returns>
public override string ToString()
{
return Native.Z3_goal_to_string(Context.nCtx, NativeObject);
}
/// <summary>
/// Goal to DIMACS formatted string conversion.
/// </summary>
/// <returns>A string representation of the Goal.</returns>
public string ToDimacs(bool include_names = true)
{
return Native.Z3_goal_to_dimacs_string(Context.nCtx, NativeObject, (byte)(include_names ? 1 : 0));
}
/// <summary>
/// Goal to BoolExpr conversion.
/// </summary>
/// <returns>A string representation of the Goal.</returns>
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 override void IncRef(IntPtr o)
{
Native.Z3_goal_inc_ref(Context.nCtx, o);
}
internal override void DecRef(IntPtr o)
{
lock (Context)
{
if (Context.nCtx != IntPtr.Zero)
Native.Z3_goal_dec_ref(Context.nCtx, o);
}
}
#endregion
}
}