^ domain, SortPtr range);
/*@}*/
/**
@name Numerals
*/
/*@{*/
/**
\brief Create a numeral of a given type.
\param numeral An integer, or a string representing the numeral value in decimal notation.
If the given type is a real, then the numeral can be a rational, that is, a string of the form [num]* / [num]*.
\param ty The type of the numeral. In the current implementation, the given type can be an int, real, or bit-vectors of arbitrary size.
*/
TermPtr MkNumeral(String^ numeral, SortPtr ty);
TermPtr MkNumeral(int n, SortPtr ty);
TermPtr MkNumeral(unsigned n, SortPtr ty);
TermPtr MkNumeral(__int64 n, SortPtr ty);
TermPtr MkNumeral(unsigned __int64 n, SortPtr ty);
/**
\brief Create a numeral of type Int.
*/
TermPtr MkIntNumeral(String^ n) { return MkNumeral(n, MkIntSort()); }
TermPtr MkIntNumeral(int n) { return MkNumeral(n, MkIntSort()); }
TermPtr MkIntNumeral(unsigned n) { return MkNumeral(n, MkIntSort()); }
TermPtr MkIntNumeral(__int64 n) { return MkNumeral(n, MkIntSort()); }
TermPtr MkIntNumeral(unsigned __int64 n) { return MkNumeral(n, MkIntSort()); }
/**
\brief Create a numeral of type Real.
*/
TermPtr MkRealNumeral(String^ n) { return MkNumeral(n, MkRealSort()); }
TermPtr MkRealNumeral(int n) { return MkNumeral(n, MkRealSort()); }
TermPtr MkRealNumeral(unsigned n) { return MkNumeral(n, MkRealSort()); }
TermPtr MkRealNumeral(__int64 n) { return MkNumeral(n, MkRealSort()); }
TermPtr MkRealNumeral(unsigned __int64 n) { return MkNumeral(n, MkRealSort()); }
/*@}*/
/**
@name Quantifiers
*/
/*@{*/
/**
\brief Create a pattern for quantifier instantiation.
Z3 uses pattern matching to instantiate quantifiers. If a
pattern is not provided for a quantifier, then Z3 will
automatically compute a set of patterns for it. However, for
optimal performance, the user should provide the patterns.
Patterns comprise an array of terms. The array of terms
passed to MkPattern should be
non-empty. If the array comprises of more than one term, it is
a called a multi-pattern.
In general, one can pass in an array of (multi-)patterns in the
quantifier constructor.
To summarize, each quantifier takes an array of alternative multi-patterns.
The quantifier is instantiated for every multi-pattern that is matched.
Each multi-pattern is an array of terms. All terms must match for the
multi-pattern to trigger instantiation.
Create a multi-pattern using MkPattern.
Create an array of multi-patterns and pass it to the quantifier constructor.
If you just want a multi-pattern with a single term, then pass in the singleton array
For example, if you want to create the multi-pattern
consisting of the two terms: \ccode{(store A I V)}
and \ccode{(select A J)}
where A, I, J, V are bound variables, create the pattern
pattern1 = context.MkPattern(new TermPtr[]{
context.MkArrayStore(A,I,V),
context.MkArraySelect(A,J)
})
Then form the array
new PatternPtr[]{ pattern1 }
and pass it to the
function \ccode{MkForall} or \ccode{MkExists}.
Suppose you also want to have the quantifier be instantiated if
the pattern \ccode{(select (store A I V) J)} is matched, then create the
pattern:
pattern2 = context.MkPattern(new TermPtr[] {
context.MkArraySelect(context.MkArrayStore(A,I,V),J) })
Then form the array:
new PatternPtr[] { pattern1, pattern2 }
\sa MkForall
\sa MkExists
*/
PatternPtr MkPattern(array^ terms);
/**
\brief Create a bound variable.
Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain
the meaning of de-Bruijn indices by indicating the compilation process from
non-de-Bruijn formulas to de-Bruijn format.
\verbatim
abs(forall (x1) phi) = forall (x1) abs1(phi, x1, 0)
abs(forall (x1, x2) phi) = abs(forall (x1) abs(forall (x2) phi))
abs1(x, x, n) = b_n
abs1(y, x, n) = y
abs1(f(t1,...,tn), x, n) = f(abs1(t1,x,n), ..., abs1(tn,x,n))
abs1(forall (x1) phi, x, n) = forall (x1) (abs1(phi, x, n+1))
\endverbatim
The last line is significant: the index of a bound variable is different depending
on the scope in which it appears. The deeper x appears, the higher is its
index.
\param index de-Bruijn index
\param ty type of the bound variable
\sa MkForall
\sa MkExists
*/
TermPtr MkBound(unsigned index, SortPtr ty);
/**
\brief Create a forall formula.
\param weight quantifiers are associated with weights indicating the importance
of using the quantifier during instantiation. By default, pass the weight 0.
\param patterns array containing the patterns created using #MkPattern.
\param types array containing the types of the bound variables.
\param names array containing the names as symbols of the bound variables.
\param body the body of the quantifier.
\sa MkPattern
\sa MkBound
\sa MkExists
*/
TermPtr MkForall(
unsigned weight,
array^ patterns,
array^ types,
array^ names,
TermPtr body
);
/**
\brief Create a forall formula.
\param weight quantifiers are associated with weights indicating the importance
of using the quantifier during instantiation. By default, pass the weight 0.
\param patterns array containing the patterns created using #MkPattern.
\param types array containing the types of the bound variables.
\param names array containing the names as strings of the bound variables.
\param body the body of the quantifier.
\sa MkPattern
\sa MkBound
\sa MkExists
*/
TermPtr MkForall(
unsigned weight,
array^ patterns,
array^ types,
array^ names,
TermPtr body
);
/**
\brief Create a forall formula.
This function allows creating a forall without using de-Bruijn indices in the body or patterns.
It is sometimes convenient to create the body of a quantifier without de-Bruijn indices, but
instead use constants. These constants have to be replaced by de-Bruijn indices for the
internal representation. This function allows the caller to hand over the task to Z3 of abstracting
the constants into bound variables, so that each occurrence of the variables in the array
bound gets replaced by a de-Bruijn index.
\param weight quantifiers are associated with weights indicating the importance
of using the quantifier during instantiation. By default, pass the weight 0.
\param bound array containing the constants to be abstracted as bound variables.
\param patterns array containing the patterns created using #MkPattern.
\param body the body of the quantifier.
\sa MkPattern
\sa MkExists
*/
TermPtr MkForall(
unsigned weight,
array^ bound,
array^ patterns,
TermPtr body
);
/**
\brief Create an exists formula. Similar to #MkForall.
\sa MkPattern
\sa MkBound
\sa MkForall
*/
TermPtr MkExists(
unsigned weight,
array^ patterns,
array^ types,
array^ names,
TermPtr body
);
TermPtr MkExists(
unsigned weight,
array^ patterns,
array^ types,
array^ names,
TermPtr body
);
TermPtr MkExists(
unsigned weight,
array^ bound,
array^ patterns,
TermPtr body
);
/**
\brief Create a quantifier with no-pattern directives and symbols.
Use de-Bruijn indexing.
\sa MkPattern
\sa MkBound
\sa MkForall
\sa MkExists
*/
TermPtr MkQuantifier(
bool is_forall,
unsigned weight,
array^ patterns,
array^ no_patterns,
array^ types,
array^ names,
TermPtr body
)
{
return MkQuantifier(is_forall, weight, nullptr, nullptr, patterns, no_patterns, types, names, body);
}
TermPtr MkQuantifier(
bool is_forall,
unsigned weight,
Symbol^ quantifier_id,
Symbol^ skolem_id,
array^ patterns,
array^ no_patterns,
array^ types,
array^ names,
TermPtr body
);
/**
\brief Create a quantifier with no-pattern directives and symbols.
Abstract terms as the bound variables.
\sa MkPattern
\sa MkBound
\sa MkForall
\sa MkExists
*/
TermPtr MkQuantifier(
bool is_forall,
unsigned weight,
Symbol^ quantifier_id,
Symbol^ skolem_id,
array^ patterns,
array^ no_patterns,
array^ bound,
TermPtr body
);
/*@}*/
/**
@name Accessors
*/
/*@{*/
/**
\brief Return a unique identifier for \c t.
*/
unsigned GetTermId(TermPtr t);
/**
\brief Return a unique identifier for \c f.
*/
unsigned GetFuncDeclId(FuncDeclPtr f);
/**
\brief Return a unique identifier for \c s.
*/
unsigned GetSortId(SortPtr s);
/**
\brief Return \c SymbolKind.Int if the symbol was constructed
using #MkIntSymbol, and \c SymbolKind.String if the symbol
was constructed using #MkStringSymbol.
*/
SymbolKind GetSymbolKind(Symbol^ s);
/**
\brief Return the symbol int value.
\pre GetSymbolKind(s) == SymbolKind.Int
\sa MkIntSymbol
*/
int GetSymbolInt(Symbol^ s);
/**
\brief Return the symbol name.
\pre GetSymbolKind(s) = SymbolKind.String
\sa MkStringSymbol
*/
String^ GetSymbolString(Symbol^ s);
/**
\brief Return \c true if the two given AST nodes are equal.
*/
bool IsEq(TermPtr t1, TermPtr t2);
/**
\brief Return \c true if \c t is well sorted.
*/
bool IsWellSorted(TermPtr t);
/**
\brief Return the kind of the given AST.
*/
TermKind GetTermKind(TermPtr a);
/**
\brief Return the kind of the built-in operator.
\pre GetTermKind(a) == TermKind.App
*/
DeclKind GetDeclKind(FuncDeclPtr d);
/**
\brief Return auxiliary parameters associated with the built-in operator.
For example, the operator for bit-vector extraction uses
two parameters, the upper and lower bit-index for extraction.
*/
array^ GetDeclParameters(FuncDeclPtr d);
/**
\brief Return the declaration of a constant or function application.
\pre GetTermKind(a) == TermKind.App
*/
FuncDeclPtr GetAppDecl(AppPtr a);
/**
\brief Return the arguments of an application. If \c t
is an constant, then array is empty.
*/
array^ GetAppArgs(AppPtr a);
/**
\brief Return the number of a numeric ast.
\pre GetTermKind(a) == TermKind.Numeral
*/
String^ GetNumeralString(TermPtr a);
/**
\brief Similar to #GetNumeralString, but only succeeds if
the value can fit in a machine int. Throw InvalidArgument if the call fails.
\pre GetTermKind(v) == TermKind.Numeral && IsInt32(v)
\sa GetNumeralString
*/
int GetNumeralInt(TermPtr v);
bool TryGetNumeralInt(TermPtr v, [Out] int% i);
/**
\brief Similar to #GetNumeralString, but only succeeds if
the value can fit in a machine unsigned int. Throw InvalidArgument if the call fails.
\pre GetTermKind(v) == TermKind.Numeral
\sa GetNumeralString
*/
unsigned int GetNumeralUInt(TermPtr v);
bool TryGetNumeralUInt(TermPtr v, [Out] unsigned int% u);
/**
\brief Similar to #GetNumeralString, but only succeeds if
the value can fit in a machine unsigned long long int. Throw InvalidArgument if the call fails.
\pre GetTermKind(v) == TermKind.Numeral
\sa GetNumeralString
*/
unsigned __int64 GetNumeralUInt64(TermPtr v);
bool TryGetNumeralUInt64(TermPtr v, [Out] unsigned __int64% u);
/**
\brief Similar to #GetNumeralString, but only succeeds if
the value can fit in a machine long long int. Throw InvalidArgument if the call fails.
\pre GetTermKind(v) == TermKind.Numeral
*/
__int64 GetNumeralInt64(TermPtr v);
bool TryGetNumeralInt64(TermPtr v, [Out] __int64% i);
/**
\brief Similar to #GetNumeralString, but only succeeds if
the value can fit in a machine long long int. Throw InvalidArgument if the call fails.
\pre GetTermKind(v) == TermKind.Numeral
\sa GetNumeralString
*/
bool TryGetNumeral(TermPtr v, [Out] __int64% num, [Out] __int64% den);
void GetNumeral(TermPtr v, [Out] System::Numerics::BigInteger% num, [Out] System::Numerics::BigInteger% den);
/**
\brief Return the Boolean value of a truth constant. Return LBool::Undef if a is not a boolean constant (true or false).
\pre GetTermKind(a) == TermKind.App
*/
LBool GetBoolValue(TermPtr a);
/**
\brief Return the index of a de-Brujin bound variable.
\pre GetTermKind(a) == TermKind.Var
*/
unsigned GetVarIndex(TermPtr a) {
return Z3_get_index_value(ctx(), get_ast(a));
}
/**
\brief Return components of a quantifier.
\pre GetTermKind(a) = TermKind.Quantifier
*/
RawQuantifier^ GetQuantifier(TermPtr a);
/**
\brief Return array of terms in the pattern.
\pre GetTermKind(a) = TermKind.Pattern
*/
array^ GetPatternTerms(PatternPtr p);
/**
\brief Return the constant declaration name as a symbol.
*/
Symbol^ GetDeclName(FuncDeclPtr d);
/**
\brief Return the type name as a symbol.
*/
Symbol^ GetSortName(SortPtr ty);
/**
\brief Return the type of an AST node.
The AST node must be a constant, application, numeral, bound variable, or quantifier.
*/
SortPtr GetSort(TermPtr a);
/**
\brief Return the domain of a function declaration.
*/
array^ GetDomain(FuncDeclPtr d);
/**
\brief Return the range of the given declaration.
If \c d is a constant (i.e., has zero arguments), then this
function returns the type of the constant.
*/
SortPtr GetRange(FuncDeclPtr d);
/**
\brief Return the type kind (e.g., array, tuple, int, bool, etc).
\sa SortKind
*/
SortKind GetSortKind(SortPtr t);
/**
\brief Return the size of the given bit-vector type.
\pre GetSortKind(t) = SortKind.Bv
\sa MkBvSort
\sa GetSortKind
*/
unsigned GetBvSortSize(SortPtr t);
/**
\brief Return the domain of the given array type.
\pre GetSortKind(t) == SortKind.Array
\sa MkArraySort
\sa GetSortKind
*/
SortPtr GetArraySortDomain(SortPtr t);
/**
\brief Return the range of the given array type.
\pre GetSortKind(t) == SortKind.Array
\sa MkArraySort
\sa GetSortKind
*/
SortPtr GetArraySortRange(SortPtr t);
/**
\brief Return the constructor declaration of the given tuple
type.
\pre GetSortKind(t) == SortKind.Tuple
\sa MkTupleSort
\sa GetSortKind
*/
FuncDeclPtr GetTupleConstructor(SortPtr t);
/**
\brief Return the field declarations of a given tuple type.
\pre GetSortKind(t) == SortKind.Tuple
\sa MkTupleSort
\sa GetSortKind
*/
array^ GetTupleFields(SortPtr t);
/*@}*/
/**
@name Modifiers
*/
/*@{*/
/**
\brief Update the arguments of a term or quantifier.
\pre The number of arguments passed in new_args should
be the same as number of arguments to the term t.
*/
TermPtr UpdateTerm(TermPtr t, array^ new_args);
/*@}*/
/**
@name Constraints
*/
/*@{*/
/**
\brief Create a backtracking point.
The logical context can be viewed as a stack of contexts. The
scope level is the number of elements on this stack. The stack
of contexts is simulated using trail (undo) stacks.
\sa Pop
\sa PersistTerm
*/
void Push();
/**
\brief Backtrack.
Restores the context from the top of the stack, and pops it off the
stack. Any changes to the logical context (by #AssertCnstr or
other functions) between the matching #Push and \c Pop
operators are flushed, and the context is completely restored to
what it was right before the #Push.
\param num_scopes number of scopes to pop. Default value is 1.
\sa Push
\sa PersistTerm
*/
void Pop(unsigned num_scopes);
void Pop() { Pop(1); }
unsigned GetNumScopes();
/**
\brief Persist a term during num_scopes of pops.
Normally, references to terms are no longer valid when
popping scopes beyond the level where the terms are created.
If you want to reference a term below the scope where it
was created, use this method to specify how many pops
the term should survive.
The current scope level is given as the current
total number of calls to push subtracted by the
total number of calls to pop.
If num_scopes is larger or equal to the current
scope level, then the term pointer persists throughout
the life-time of the context.
Example usage:
context.Push();
context.Push();
Term t = context.MkNumeral(1, context.MkIntSort());
context.PersistTerm(t, 1);
context.Pop();
// reference to t is valid.
context.Pop();
// reference to t is not valid.
*/
void PersistTerm(TermPtr t, unsigned num_scopes);
/**
\brief Assert a constraing into the logical context.
After one assertion, the logical context may become
inconsistent.
The functions #Check or #CheckAndGetModel should be
used to check whether the logical context is consistent or not.
\sa Check
\sa CheckAndGetModel
*/
void AssertCnstr(TermPtr a);
/**
\brief Check whether the given logical context is consistent or not.
If the logical context is not unsatisfiable (i.e., the return value is different from \c false)
and model construction is enabled (see #Config), then a model is stored in \c m. Otherwise,
the value \c null is stored in \c m.
The caller is responsible for deleting the model using its Dispose method.
\remark Model construction must be enabled using configuration
parameters (See, #Config).
\sa Check
*/
LBool CheckAndGetModel([Out] RawModel^% m);
/**
\brief Check whether the given logical context is consistent or not.
The function #CheckAndGetModel should be used when models are needed.
*/
LBool Check();
/**
\brief Check whether the given logical context is consistent or
not with respect to auxiliary assumptions.
If the logical context is not unsatisfiable (i.e., the return value is different from \c false)
and model construction is enabled (see #Config), then a model is stored in \c m. Otherwise,
the value \c null is stored in \c m.
The caller is responsible for deleting the model using its Dispose method.
If the logical context is unsatisfiable, then a proof object is return and stored
in \c proof.
An unsatisfiable core (subset) for the set of supplied assumptions is returned.
\remark Model construction must be enabled using configuration
parameters (See, #Config).
\param m returned model.
\param assumptions array of auxiliary assumptions.
\param proof proof object. Proofs must be enabled for this value to be returned.
\param core subset of assumptions that is an unsatisfiable core.
\sa Check
*/
LBool CheckAssumptions([Out] RawModel^% m,
[In] array^ assumptions,
[Out] TermPtr% proof,
[Out] array^% core);
/**
\brief Cancel the current search initiated using #Check, #CheckAndGetModel, or #CheckAssumptions.
\sa Check
\sa CheckAndGetModel
\sa CheckAssumptions
*/
void SoftCheckCancel();
/**
\brief Retrieve congruence class representatives for terms.
The function can be used for relying on Z3 to identify equal terms under the current
set of assumptions. The array of terms and array of class identifiers should have
the same length. The class identifiers are numerals that are assigned to the same
value for their corresponding terms if the current context forces the terms to be
equal. You cannot deduce that terms corresponding to different numerals must be different,
(especially when using non-convex theories).
Also note that not necessarily all implied equalities are returned by this call.
Only the set of implied equalities that follow from simple constraint and
equality propagation is discovered.
A side-effect of the function is a satisfiability check.
The function return LBool.False if the current assertions are not satisfiable.
\sa Check
*/
LBool GetImpliedEqualities(
[In] array^ terms,
[Out] array^% class_ids
);
/**
\brief Obtain explanation for search failure.
\sa Check()
*/
SearchFailureExplanation GetSearchFailureExplanation();
/**
\brief Return conjunction of literals and formulas assigned to true in the current state.
*/
TermPtr GetAssignments();
/**
\brief Retrieve set of labels set in current satisfying assignment.
*/
LabeledLiterals^ GetRelevantLabels();
/**
\brief Retrieve set of literals satisfying the current assignment.
*/
LabeledLiterals^ GetRelevantLiterals();
/**
\brief Retrieve set of guessed literals satisfying the current assignment.
*/
LabeledLiterals^ GetGuessedLiterals();
/**
\brief Block the combination of remaining non-disabled labels.
Subsequent calls to Check will not contain satisfying assignments with the same
combination of labels.
*/
void BlockLiterals(LabeledLiterals^ labels);
/**
\brief Obtain literal corresponding to index in list of literals.
*/
TermPtr GetLiteral(LabeledLiterals^ labels, unsigned idx) {
return labels->GetLiteral(idx);
}
/**
\brief Interface to simplifier.
Provides an interface to the AST simplifier used by Z3.
It allows clients to piggyback on top of the AST simplifier
for their own term manipulation.
*/
TermPtr Simplify(TermPtr a);
/*@}*/
/**
@name String conversion
*/
/*@{*/
/**
\brief Select mode for the format used for pretty-printing AST nodes.
The default mode for pretty printing AST nodes is to produce
SMT-LIB style output where common subexpressions are printed
at each occurrence. The mode is called PrintMode.SmtlibFull.
To print shared common subexpressions only once, use the PrintMode.LowLevel
mode.
*/
void SetPrintMode(PrintMode mode);
/**
\brief Convert the given AST node into a string.
*/
String^ ToString(AstPtr a);
void Display(System::IO::TextWriter^ w, AstPtr a);
/**
\brief Convert the given logical context into a string.
This function is mainly used for debugging purposes. It displays
the internal structure of a logical context.
*/
virtual String^ ToString() override;
void Display(System::IO::TextWriter^ w);
/**
\brief Convert the given logical context into a string.
This function is mainly used for debugging purposes. It displays
the internal structure of a logical context.
*/
String^ StatisticsToString() {
return gcnew String(Z3_statistics_to_string(ctx()));
}
void DisplayStatistics(System::IO::TextWriter^ w) {
w->Write(StatisticsToString());
}
/**
\brief Convert the given benchmark into SMT-LIB formatted string.
*/
String^ BenchmarkToSmtlib(String^ name,
String^ logic,
String^ status,
String^ attributes,
array^ assumptions,
TermPtr formula);
/*@}*/
/**
@name Parser interface
*/
/*@{*/
/**
\brief Parse the given string using the SMT-LIB parser.
The symbol table of the parser can be initialized using the given types and declarations.
The symbols in the arrays \c type_names and \c decl_names don't need to match the names
of the types and declarations in the arrays \c types and \c decls. This is an useful feature
since we can use arbitrary names to reference types and declarations defined using the C API.
The formulas, assumptions and declarations defined in \c str.
\param string The string contianing the SMT-LIB benchmark
\param sorts List of auxiliary sorts used in SMT-LIB benchmark.
\param decls List of declarations to be used for parsing the SMT-LIB string.
\param assumptions Returned set of assumptions.
\param formulas Returned set of formulas.
\param new_decls Additional declarations from the SMT-LIB benchmark.
\param new_sorts Additional sorts fromt he SMT-LIB benchmark.
\param parser_out String containing error messages from parsing.
*/
void ParseSmtlibString(
String^ string,
[In] array^ sorts,
[In] array^ decls,
[Out] array^% assumptions,
[Out] array^% formulas,
[Out] array^% new_decls,
[Out] array^% new_sorts,
[Out] String^% parser_out
);
/**
\brief Similar to #ParseSmtlibString, but reads the benchmark from a file.
*/
void ParseSmtlibFile(
String^ file,
[In] array^ sorts,
[In] array^ decls,
[Out] array^% assumptions,
[Out] array^% formulas,
[Out] array^% new_decls,
[Out] array^% new_sorts,
[Out] String^% parser_out
);
/**
\brief Parse a string in the native Z3 format.
Return conjunction of Asserts occurring in the string.
*/
TermPtr ParseZ3String(String^ s);
/**
\brief Parse a file containing formulas in Z3's native format.
Return conjunction of Asserts occurring in the file.
*/
TermPtr ParseZ3File(String^ filename);
/**
\brief Parse a string in the SMT-LIB2 format.
Return conjunction of Asserts occurring in the string.
*/
TermPtr ParseSmtlib2String(String^ s, array^ sorts, array^ decls);
/**
\brief Parse a file containing formulas in SMT-LIB2 format.
Return conjunction of Asserts occurring in the file.
*/
TermPtr ParseSmtlib2File(String^ filename, array^ sorts, array^ decls);
/**
\brief Execute commands from a string in the SMT-LIB2 format.
Return conjunction of Asserts modulo push/pop.
*/
TermPtr ExecSmtlib2String(String^ s, array^ sorts, array^ decls);
/**
\brief Execute commands from a file containing formulas in SMT-LIB2 format.
Return conjunction of Asserts modulo push/pop.
*/
TermPtr ExecSmtlib2File(String^ filename, array^ sorts, array^ decls);
/*@}*/
/**
@name Errors
*/
/*{@*/
/**
\brief Register a Z3 error handler.
A call to a Z3 function throw Z3Error when
it is not used correctly. An error handler can be registered
and will be called in this case prior to throwing Z3Error.
*/
static void SetErrorHandler(IErrorHandler^ h);
/**
\brief Return a string describing the given error code.
*/
static String^ GetErrorMessage(ErrorCode err);
/**
\brief Free all resources allocated for Z3.
*/
static void ResetMemory();
/*@}*/
/**
@name Miscellaneous
*/
/*@{*/
/**
\brief Return Z3 version number information.
*/
void GetVersion(
[Out] unsigned % major,
[Out] unsigned % minor,
[Out] unsigned % build_number,
[Out] unsigned % revision_number);
/*@}*/
/**
\brief Create user theory.
*/
RawTheory^ MkTheory(String^ name);
internal:
static Dictionary^ contexts;
public:
/**
\brief Register fixed-point rules.
*/
void RegisterRelation(FuncDeclPtr relation);
void AddRule(TermPtr rule, Symbol^ name);
/**
\brief post a query.
The return value is LBool.True if the query is satisfiabl,e
it is LBool.False if it is not satisfiabled, and Undef on
timeouts or approximation.
*/
LBool Query(TermPtr query);
/**
\brief retrieve details on the search satus.
*/
String^ GetQueryStatus();
/**
\brief retrieve formula that satisfies the previous query,
assuming the return value was LBool.True
*/
TermPtr GetQueryAnswer();
String^ FixedpointToString(array^ queries);
array^ SimplifyFixedpointRules(array^ rules, array^ output_predicates);
// functions for creating custom Fixedpoint relations.
internal:
static void fixedpoint_assign_callback(void*, Z3_func_decl, unsigned, Z3_ast const[], unsigned, Z3_ast const[]);
static void fixedpoint_apply_callback(void*, Z3_func_decl, unsigned, Z3_ast const[], Z3_ast*);
IntPtr m_fixedpoint_gch;
private:
Action3^, array^>^ m_fixedpoint_assign;
Func2^, TermPtr>^ m_fixedpoint_apply;
void init_fixedpoint_callbacks();
public:
property Action3^, array^>^ FixedpointAssign {
void set(Action3^, array^>^ value) {
m_fixedpoint_assign = value;
init_fixedpoint_callbacks();
}
}
property Func2^, TermPtr>^ FixedpointApply {
void set(Func2^, TermPtr>^ value) {
m_fixedpoint_apply = value;
init_fixedpoint_callbacks();
}
}
};
public ref class RawTheory {
typedef GCHandle GCHandle;
typedef GCHandleType GCHandleType;
private:
Z3_theory m_theory;
ref_context& m_context;
String^ m_name;
static Dictionary^ theories;
protected:
!RawTheory() {}
public:
property String^ Name { String^ get() { return m_name; } }
internal:
RawTheory(ref_context& ctx, String^ name);
~RawTheory();
static RawTheory^ GetTheory(Z3_theory th) {
Z3_theory_data td = Z3_theory_get_ext_data(th);
return theories[GCHandle::FromIntPtr(IntPtr(td))];
}
// Delete Handler
private:
Action0^ delete_handler;
internal:
static void static_delete_callback(Z3_theory th);
public:
property Action0^ DeleteHandler
{
void set(Action0^ value)
{
delete_handler = value;
}
}
// ReduceEq
internal:
static Z3_bool reduce_eq_callback(Z3_theory th, Z3_ast a, Z3_ast b, Z3_ast* r);
private:
Func2^ reduce_eq;
void set_reduce_eq(Func2^ value);
public:
property Func2^ ReduceEq {
void set(Func2^ value) {
set_reduce_eq(value);
}
}
// ReduceApp
private:
Func2^, TermPtr>^ reduce_app;
void set_reduce_app(Func2^, TermPtr>^ value);
public:
property Func2^, TermPtr>^ ReduceApp {
void set(Func2^, TermPtr>^ value) {
set_reduce_app(value);
}
}
internal:
static Z3_bool reduce_app_callback(Z3_theory th, Z3_func_decl f, unsigned num_args, Z3_ast const args[], Z3_ast* r);
// Reduce distinct
private:
Func1^, TermPtr>^ reduce_distinct;
void set_reduce_distinct(Func1^, TermPtr>^ value);
internal:
static Z3_bool reduce_distinct_callback(Z3_theory th, unsigned n, Z3_ast const args[], Z3_ast* r);
public:
property Func1^, TermPtr>^ ReduceDistinct {
void set(Func1^, TermPtr>^ value) {
set_reduce_distinct(value);
}
}
// NewRelevant
internal:
Action^ new_relevant;
private:
void set_new_relevant(Action^ value);
public:
property Action^ NewRelevant {
void set(Action^ value) {
set_new_relevant(value);
}
}
// NewApp
private:
void set_new_app(Action^ value);
internal:
Action^ new_app;
public:
property Action^ NewApp {
void set(Action^ value) {
set_new_app(value);
}
}
// NewElem
private:
void set_new_elem(Action^ value);
internal:
Action^ new_elem;
public:
property Action^ NewElem {
void set(Action^ value) {
set_new_elem(value);
}
}
// InitSearch
private:
void set_init_search(Action0^ value);
internal:
Action0^ init_search;
public:
property Action0^ InitSearch {
void set(Action0^ value) { set_init_search(value); }
}
// Push
private:
void set_push(Action0^ value);
internal:
Action0^ push;
public:
property Action0^ Push {
void set(Action0^ value) { set_push(value); }
}
// Pop
private:
void set_pop(Action0^ value);
internal:
Action0^ pop;
public:
property Action0^ Pop {
void set(Action0^ value) { set_pop(value); }
}
// Restart
private:
void set_restart(Action0^ value);
internal:
Action0^ restart;
public:
property Action0^ Restart {
void set(Action0^ value) { set_restart(value); }
}
// Reset
private:
void set_reset(Action0^ value);
internal:
Action0^ reset;
public:
property Action0^ Reset {
void set(Action0^ value) { set_reset(value); }
}
// FinalCheck
private:
void set_final_check(Func0^ value);
internal:
Func0^ final_check;
public:
property Func0^ FinalCheck {
void set(Func0^ value) { set_final_check(value); }
}
// NewEq
private:
void set_new_eq(Action2^ value);
internal:
Action2^ new_eq;
public:
property Action2^ NewEq
{
void set(Action2^ value) { set_new_eq(value); }
}
// NewDiseq
private:
void set_new_diseq(Action2^ value);
internal:
Action2^ new_diseq;
public:
property Action2^ NewDiseq
{
void set(Action2^ value) { set_new_diseq(value); }
}
// NewAssignment
internal:
Action2^ new_assignment;
private:
void set_new_assignment(Action2^ value);
public:
property Action2^ NewAssignment {
void set(Action2^ value) {
set_new_assignment(value);
}
}
void AssertTheoryAxiom(TermPtr ax)
{
Z3_theory_assert_axiom(m_theory, get_ast(ax));
}
void AssumeEq(TermPtr lhs, TermPtr rhs)
{
Z3_theory_assume_eq(m_theory, get_ast(lhs), get_ast(rhs));
}
void EnableTheoryAxiomSimplification(bool flag)
{
Z3_theory_enable_axiom_simplification(m_theory, flag);
}
TermPtr GetEqcRoot(TermPtr n)
{
return TermPtr(Z3_theory_get_eqc_root(m_theory, get_ast(n)));
}
TermPtr GetEqcNext(TermPtr n)
{
return TermPtr(Z3_theory_get_eqc_next(m_theory, get_ast(n)));
}
array^ GetParents(TermPtr n) {
unsigned np = Z3_theory_get_num_parents(m_theory, get_ast(n));
array^ result = gcnew array(np);
for (unsigned i = 0; i < np; ++i)
{
result[i] = TermPtr(Z3_theory_get_parent(m_theory, get_ast(n), i));
}
return result;
}
bool IsTheoryValue(TermPtr a)
{
return 0 != Z3_theory_is_value(m_theory, get_ast(a));
}
bool IsTheoryDecl(FuncDeclPtr d)
{
return 0 != Z3_theory_is_decl(m_theory, get_func_decl(d));
}
array^ GetElems()
{
unsigned n = Z3_theory_get_num_elems(m_theory);
array^ result = gcnew array(n);
for (unsigned i = 0; i < n; ++i)
{
result[i] = TermPtr(Z3_theory_get_elem(m_theory, i));
}
return result;
}
array^ GetApps()
{
unsigned n = Z3_theory_get_num_apps(m_theory);
array^ result = gcnew array(n);
for (unsigned i = 0; i < n; ++i)
{
result[i] = TermPtr(Z3_theory_get_app(m_theory, i));
}
return result;
}
SortPtr MkSort(Symbol^ s)
{
return SortPtr(Z3_theory_mk_sort(m_context(), m_theory, s->get()));
}
TermPtr MkValue(Symbol^ s, SortPtr srt)
{
return TermPtr(Z3_theory_mk_value(m_context(), m_theory, s->get(), get_sort(srt)));
}
TermPtr MkConstant(Symbol^ s, SortPtr srt)
{
return TermPtr(Z3_theory_mk_constant(m_context(), m_theory, s->get(), get_sort(srt)));
}
FuncDeclPtr MkFuncDecl(Symbol^ n, array^ domain, SortPtr range);
SortPtr MkSort(String^ s);
TermPtr MkValue(String^ s, SortPtr srt);
TermPtr MkConstant(String^ s, SortPtr srt);
FuncDeclPtr MkFuncDecl(String^ n, array^ domain, SortPtr range);
};
ref class Context;
ref class Model;
ref class Theory;
public ref class Ast : public System::IComparable {
protected:
AstPtr m_ast;
RawContext^ m_ctx;
!Ast();
internal:
Ast(RawContext^ c, AstPtr a);
AstPtr GetPtr() { return m_ast; }
AstPtr operator()() { return m_ast; }
public:
~Ast();
/**
\brief Test equality of asts.
*/
virtual bool Equals(Object^ obj) override;
/**
\brief Obtain hash code.
*/
virtual int GetHashCode() override;
/**
\brief Pretty print term, sort or declaration.
*/
virtual String^ ToString() override;
/**
\brief Implement IComparable::CompareTo
*/
virtual int CompareTo(Object^ other);
/**
\brief overload ==, !=
*/
// virtual bool operator==(Object^ other);
// virtual bool operator!=(Object^ other);
virtual unsigned GetId() { return m_ctx->GetTermId(m_ast); }
};
public ref class Sort : public Ast{
internal:
Sort(RawContext^ c, SortPtr a) : Ast(c,a) {}
public:
String^ GetName();
virtual unsigned GetId() override { return m_ctx->GetSortId(m_ast); }
};
public ref class FuncDecl : public Ast {
internal:
FuncDecl(RawContext^ c, FuncDeclPtr a) : Ast(c,a) {}
public:
String^ GetDeclName();
DeclKind GetKind();
virtual unsigned GetId() override { return m_ctx->GetFuncDeclId(m_ast); }
};
public ref class Term : public Ast {
internal:
Term(RawContext^ c, TermPtr a) : Ast(c,a) {}
public:
/**
\brief Overloading of Boolean operators.
\pre Argument type is Boolean.
*/
static Term^ operator!(Term^ t1);
static Term^ operator&(Term^ t1, Term^ t2);
static Term^ operator|(Term^ t1, Term^ t2);
static Term^ operator^(Term^ t1, Term^ t2);
/**
\brief Overloading of common arithmetical operators.
\pre Argument types are integers or reals.
*/
static Term^ operator+(Term^ t1, Term^ t2);
static Term^ operator*(Term^ t1, Term^ t2);
static Term^ operator/(Term^ t1, Term^ t2);
static Term^ operator-(Term^ t1, Term^ t2);
static Term^ operator>(Term^ t1, Term^ t2);
static Term^ operator<(Term^ t1, Term^ t2);
static Term^ operator>=(Term^ t1, Term^ t2);
static Term^ operator<=(Term^ t1, Term^ t2);
/**
\brief Overloading of array select.
\pre Argument is an index, the main term is of array type.
*/
Term^ operator[](Term^ index);
TermKind GetKind();
FuncDecl^ GetAppDecl();
array^ GetAppArgs();
Sort^ GetSort();
String^ GetNumeralString();
unsigned GetVarIndex();
ref class Quantifier^ GetQuantifier();
};
public ref class Pattern : public Ast {
internal:
Pattern(RawContext^ c, PatternPtr a) : Ast(c,a) {}
};
public ref class Quantifier {
public:
bool IsForall;
unsigned Weight;
array^ Patterns;
array^ NoPatterns;
array^ Sorts;
array^ Names;
Term^ Body;
};
public ref class ArrayValue {
public:
array^ Domain;
array^ Range;
Term^ ElseCase;
};
public ref class TermParameter : public IParameter {
Term^ m_value;
internal:
TermParameter(Term^ t) : m_value(t) {}
public:
virtual String^ ToString() override { return m_value->ToString(); }
property Term^ GetTerm { Term^ get() { return m_value; } }
};
public ref class SortParameter : public IParameter {
Sort^ m_value;
internal:
SortParameter(Sort^ s): m_value(s) {}
public:
property Sort^ GetSort { Sort^ get() { return m_value; } }
virtual String^ ToString() override { return m_value->ToString(); }
};
public ref class FuncDeclParameter : public IParameter {
FuncDecl^ m_value;
internal:
FuncDeclParameter(FuncDecl^ d): m_value(d) {}
public:
property FuncDecl^ GetFuncDecl { FuncDecl^ get() { return m_value; } }
virtual String^ ToString() override { return m_value->ToString(); }
};
/**
\brief Term and optional proof object returned by user-simplifier
*/
public ref class TermProof {
Term^ m_term;
Term^ m_proof; // proof is optional, use null for absence of proofs.
public:
TermProof(Term^ term, Term^ proof): m_term(term), m_proof(proof) {}
property Term^ GetTerm { Term^ get() { return m_term; } }
property Term^ Proof { Term^ get() { return m_proof; } }
};
/**
\brief Type safe contexts.
*/
public ref class Context {
/// @cond 0
RawContext^ m_ctx;
public:
template
array^ CopyArray(array^ a) {
if (!a) {
return gcnew array(0);
}
int len = a->Length;
array^ result = gcnew array(len);
for (int i = 0; i < len; ++i) {
if (a[i]) {
result[i] = a[i]();
}
else {
result[i] = IntPtr(0);
}
}
return result;
}
array^ CopyArray(array^ a) {
return CopyArray(a);
}
array^ CopyArray(array^ a) {
return CopyArray(a);
}
array^ CopyArray(array^ a) {
return CopyArray(a);
}
array^ CopyArray(array^ a) {
return CopyArray(a);
}
internal:
template
static array^ CopyAstArray(RawContext^ ctx, array^ a) {
if (!a) return nullptr;
int len = a->Length;
array^ result = gcnew array(len);
for (int i = 0; i < len; ++i) {
if (a[i] != IntPtr(0)) {
result[i] = gcnew T(ctx,a[i]);
}
else {
result[i] = nullptr;
}
}
return result;
}
public:
template
array^ CopyAstArray(array^ a) {
return CopyAstArray(m_ctx, a);
}
array^ CopySortArray(array^ a) {
return CopyAstArray(a);
}
array^ CopyTermArray(array^ a) {
return CopyAstArray(a);
}
array^ CopyFuncDeclArray(array^ a) {
return CopyAstArray(a);
}
internal:
static array^ CopyTermArray(RawContext^ ctx, array^ a) {
return CopyAstArray(ctx, a);
}
static array^ CopySortArray(RawContext^ ctx, array^ a) {
return CopyAstArray(ctx, a);
}
static Quantifier^ GetQuantifier(RawContext^ ctx, Term^ term);
internal:
property RawContext^ GetContext { RawContext^ get() { return m_ctx; } }
/// @endcond
public:
/**
\brief Create a type safe version of a context.
Terms and models created using the type safe context are wrapped within
objects. The object wrappers prevent confusing the \ccode{IntPtr} type used for
terms, sorts and values with arbitrary instances.
Each method in #Context is paired with a corresponding method in Context.
\sa Context.
*/
Context() { m_ctx = gcnew RawContext(); }
Context(Config^ config) : m_ctx(gcnew RawContext(config)) {}
Context(Config^ config, ReferenceCounted^ rc) : m_ctx(gcnew RawContext(config, rc)) {}
/**
\brief Set the context from an externally created context.
*/
void SetContext(Z3_context ctx){ m_ctx->SetContext(ctx); }
/**
\brief Dispose method for type safe contexts.
*/
~Context() { m_ctx->Reset(); }
/**
\brief Enable low-level debug tracing.
This method only works with debug builds.
*/
void EnableDebugTrace(String^ tag) { m_ctx->EnableDebugTrace(tag); }
/**
\brief Enable or disable warning messages sent to the console out/error.
Warnings are printed after passing \c true, warning messages are
suppressed after calling this method with \c false.
*/
void ToggleWarningMessages(bool enabled) { m_ctx->ToggleWarningMessages(enabled); }
void UpdateParamValue(String^ param_id, String^ value) { m_ctx->UpdateParamValue(param_id, value); }
String^ GetParamValue(String^ param_id) {
return m_ctx->GetParamValue(param_id);
}
/**
\brief Configure the SMTLIB logic to be used in the given logical context.
*/
bool SetLogic(String^ logic) { return m_ctx->SetLogic(logic); }
/**
@name Symbols
*/
/*@{*/
Symbol^ MkSymbol(int i) { return m_ctx->MkSymbol(i); }
Symbol^ MkSymbol(String^ s) { return m_ctx->MkSymbol(s); }
/*@}*/
/**
@name Modifiers
*/
/*@{*/
/**
\brief Update the arguments of a term or quantifier.
\pre The number of arguments passed in new_args should
be the same as number of arguments to the term t.
*/
Term^ UpdateTerm(Term^ t, array^ new_args) {
return gcnew Term(m_ctx, m_ctx->UpdateTerm(t(), CopyArray(new_args)));
}
/*@}*/
/**
@name Constraints
*/
/*@{*/
void Push() { m_ctx->Push(); }
void Pop(unsigned num_scopes) { m_ctx->Pop(num_scopes); }
void Pop() { Pop(1); }
unsigned GetNumScopes() { return m_ctx->GetNumScopes(); }
void PersistTerm(Term^ t, unsigned num_scopes) {
m_ctx->PersistTerm(t(), num_scopes);
}
LBool Check() { return m_ctx->Check(); }
LBool CheckAndGetModel([Out] Model^% m);
LBool CheckAssumptions([Out] Model^% m,
[In] array^ assumptions,
[Out] Term^% proof,
[Out] array^% core);
void SoftCheckCancel();
LBool GetImpliedEqualities(
[In] array^ terms,
[Out] array^% class_ids);
SearchFailureExplanation GetSearchFailureExplanation() { return m_ctx->GetSearchFailureExplanation(); }
LabeledLiterals^ GetRelevantLabels() { return m_ctx->GetRelevantLabels(); }
LabeledLiterals^ GetRelevantLiterals() { return m_ctx->GetRelevantLiterals(); }
LabeledLiterals^ GetGuessedLiterals() { return m_ctx->GetGuessedLiterals(); }
void BlockLiterals(LabeledLiterals^ lbls) { m_ctx->BlockLiterals(lbls); }
Term^ GetLiteral(LabeledLiterals^ lbls, unsigned idx) { return gcnew Term(m_ctx, m_ctx->GetLiteral(lbls, idx)); }
Term^ Simplify(Term^ a) { return gcnew Term(m_ctx,m_ctx->Simplify(a())); }
void AssertCnstr(Term^ a) { m_ctx->AssertCnstr(a()); }
/*@}*/
virtual String^ ToString() override { return m_ctx->ToString(); }
void Display(System::IO::TextWriter^ w) { m_ctx->Display(w); }
Term^ GetAssignments() { return gcnew Term(m_ctx, m_ctx->GetAssignments()); }
String^ StatisticsToString() { return m_ctx->StatisticsToString(); }
void DisplayStatistics(System::IO::TextWriter^ w) { m_ctx->DisplayStatistics(w); }
/**
\brief Convert the given benchmark into SMT-LIB formatted string.
*/
String^ BenchmarkToSmtlib(String^ name,
String^ logic,
String^ status,
String^ attributes,
array^ assumptions,
Term^ formula);
void ParseSmtlibString(
String^ string,
[In] array^ sorts,
[In] array^ decls,
[Out] array^% assumptions,
[Out] array^% formulas,
[Out] array^% new_decls,
[Out] array^% new_sorts,
[Out] String^% parser_out
);
void ParseSmtlibFile(
String^ file,
[In] array^ sorts,
[In] array^ decls,
[Out] array^% assumptions,
[Out] array