3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-12 20:18:18 +00:00
z3/Microsoft.Z3V3/Microsoft.Z3V3.h
Leonardo de Moura 68269c43a6 other components
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:48:48 -07:00

4776 lines
154 KiB
C++

/*++
Copyright (c) 2007 Microsoft Corporation
Module Name:
Microsoft.Z3V3.h
Abstract:
Z3 Managed API.
Author:
Nikolaj Bjorner (nbjorner)
Leonardo de Moura (leonardo) 2007-06-8
Notes:
This API is deprecated and support for this is discontinued.
It is superseeded by the new Microsoft.Z3 API.
--*/
#ifndef _MICROSOFT_Z3V3_H__
#define _MICROSOFT_Z3V3_H__
struct _Z3_model {};
struct _Z3_config {};
struct _Z3_context {};
struct _Z3_func_decl {};
struct _Z3_app {};
struct _Z3_sort {};
struct _Z3_symbol {};
struct _Z3_ast {};
struct _Z3_literals {};
struct _Z3_pattern {};
struct _Z3_constructor {};
struct _Z3_constructor_list {};
typedef _Z3_literals *Z3_literals;
struct _Z3_theory {};
struct _Z3_ast_vector {};
struct _Z3_fixedpoint {};
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Runtime::InteropServices;
using namespace System::Numerics;
#include "..\lib\z3.h"
namespace Microsoft {
namespace Z3V3 {
class ref_context {
unsigned m_count;
bool m_owned;
bool m_scoped;
Z3_context m_ctx;
Z3_fixedpoint m_dl;
ref_context(Z3_context ctx, bool owned, bool scoped): m_count(1), m_owned(owned), m_scoped(scoped), m_ctx(ctx), m_dl(0) {}
public:
static ref_context* mk(Z3_context ctx, bool owned, bool scoped);
void dec_ref();
void inc_ref();
Z3_context operator()() { return m_ctx; }
~ref_context() {}
bool is_ref_counted() const { return !is_scoped(); }
bool is_scoped() const { return m_scoped; }
Z3_fixedpoint dl();
};
/**
\defgroup mapi Managed (.NET) API
*/
/*@{*/
public ref class Z3Log {
static bool m_open = false;
public:
/**
\brief Log assertions to a file.
\sa Close
Returns \c true if the open succeeds, otherwise \c false.
*/
static bool Open(String^ filename);
/**
\brief Return true if the log is open.
*/
static bool IsOpen() { return m_open; }
/**
\brief Append user comment to log.
\sa Open
*/
static void Append(String^ string);
/**
\brief Close file with logged API calls.
\sa Open
*/
static void Close();
};
/**
\brief Symbol.
Wrapper class for string or integer symbols.
This class remains unsafe. You cannot access the ToString()
method after the owning context has been deleted.
We don't use dispose pattern here. I believe it would be too
awkward to manage.
*/
public ref class Symbol {
Z3_context m_ctx;
Z3_symbol m_symbol;
internal:
Symbol(Z3_context c, Z3_symbol s) : m_ctx(c), m_symbol(s) { }
Z3_symbol get() { return m_symbol; }
public:
virtual String^ ToString() override;
};
/**
\brief Lifted Booleans.
The result of m_context->Check() is a lifted Boolean. When Z3 is unable to
decide whether the result is satisfiable or unsatisfiable it returns
Undef.
*/
public enum class LBool
{
True,
False,
Undef
};
/**
\brief Z3 error codes.
- Ok,
- TypeError: User tried to build an invalid (type incorrect) AST.
- IndexOutOfBounds: Index out of bounds
- InvalidArgument:: Invalid argument was provided
- ParserError: An error occurred when parsing a string or file.
- NoParser: Parser output is not available, that is, user didn't invoke ParseSmtlibString or ParseSmtlibFile.
- InvalidPattern: An invalid pattern was used to build a quantifier.
- InternalFatal: An internal fatal error was encountered.
- InvalidUsage: The API was used in an invalid context.
- FileAccessError: File access failed for an inaccessible file.
- NonDisposedConfig A configuration was not disposed explictly.
- NonDisposedContext: A context was not disposed explictly.
- NonDisposedLiterals: A conflict literal set was not disposed explicitly.
- NonDisposedModel: A model was not disposed of explicitly.
There is no error code for out of memory errors.
Z3 will throw the library exception <tt>OutOfMemoryException</tt>
if memory allocation fails. Users should call ResetMemory()
to reclaim all allocated resources.
*/
public enum class ErrorCode
{
Ok,
TypeError,
IndexOutOfBounds,
InvalidArgument,
ParserError,
NoParser,
InvalidPattern,
InternalFatal,
InvalidUsage,
FileAccessError,
NonDisposedConfig,
NonDisposedContext,
NonDisposedLiterals,
NonDisposedModel
};
/**
\brief Z3 pretty printing modes used when pretty printing terms.
- SmtlibFull: Print AST nodes in SMTLIB verbose format.
- LowLevel: Print AST nodes using a low-level format.
- SmtlibCompliant Print AST in SMTLIB 1.x compliant format.
- Smtlib2Compliant Print AST in SMTLIB 1.x compliant format.
*/
public enum class PrintMode
{
SmtlibFull,
LowLevel,
SmtlibCompliant,
Smtlib2Compliant
};
/**
\brief Z3 error exceptions contain an \c ErrorCode.
A \c Z3Error exception gets raised on errors caused by
malformed calls into the #Context.
*/
public ref class Z3Error : Exception {
public:
Z3Error(ErrorCode c) { Code = c; InternalCode = 0; }
Z3Error(int i) { Code = ErrorCode::Ok; InternalCode = i; }
ErrorCode Code;
int InternalCode;
};
/// @cond 0
typedef IntPtr AstPtr;
typedef IntPtr SortPtr;
typedef IntPtr FuncDeclPtr;
typedef IntPtr TermPtr;
typedef IntPtr PatternPtr;
typedef IntPtr AppPtr;
Z3_func_decl get_func_decl(FuncDeclPtr t) {
if (t == IntPtr::Zero) {
throw gcnew Z3Error(ErrorCode::InvalidArgument);
}
return static_cast<Z3_func_decl>(t.ToPointer());
}
Z3_ast get_ast(TermPtr t) {
if (t == IntPtr::Zero) {
throw gcnew Z3Error(ErrorCode::InvalidArgument);
}
return static_cast<Z3_ast>(t.ToPointer());
}
Z3_sort get_sort(SortPtr t) {
if (t == IntPtr::Zero) {
throw gcnew Z3Error(ErrorCode::InvalidArgument);
}
return static_cast<Z3_sort>(t.ToPointer());
}
Z3_app get_const_ast(AppPtr c) {
if (c == IntPtr::Zero) {
throw gcnew Z3Error(ErrorCode::InvalidArgument);
}
return static_cast<Z3_app>(c.ToPointer());
}
Z3_pattern get_pattern(PatternPtr p) {
if (p == IntPtr::Zero) {
throw gcnew Z3Error(ErrorCode::InvalidArgument);
}
return static_cast<Z3_pattern>(p.ToPointer());
}
/// @endcond
/**
\brief In Z3, a symbol can be represented using integers and strings (See #GetSymbolKind).
\sa MkIntSymbol
\sa MkStringSymbol
*/
public enum class SymbolKind
{
Int,
String
};
/**
\brief The different kinds of Z3 sorts (See #GetSortKind).
*/
public enum class SortKind
{
Uninterpreted,
Bool,
Int,
Real,
BitVector,
Array,
Datatype,
Unknown
};
/**
\brief Different failure kinds.
- NoFailure
- Unknown:
- TimeOut:
- MemOut:
- UserCanceled:
- MaxConflicts:
- Theory:
- Quantifiers:
*/
public enum class SearchFailureExplanation
{
NoFailure,
Unknown,
TimeOut,
MemOut,
UserCanceled,
MaxConflicts,
Theory,
Quantifiers
};
/**
\brief The different kinds of Z3 Terms.
- Numeral: numerals
- App: constant and applications
- Var: bound variables
- Quantifier: quantifiers
- Unknown: internal
*/
public enum class TermKind
{
Numeral,
App,
Var,
Quantifier,
Unknown
};
/** \brief Different kinds of Z3 built-in declarations (See #GetDeclKind)
*/
public enum class DeclKind
{
// Basic operators
True,
False,
Eq,
Distinct,
Ite,
And,
Or,
Iff,
Xor,
Not,
Implies,
// Arithmetic
ArithNum,
Le,
Ge,
Lt,
Gt,
Add,
Sub,
Uminus,
Mul,
Div,
IDiv,
Rem,
Mod,
ToReal,
ToInt,
IsInt,
// Arrays
Store,
Select,
ConstArray,
DefaultArray,
MapArray,
Union,
Intersect,
Difference,
Complement,
Subset,
AsArray,
// Bit-vectors.
BitNum,
Bit1,
Bit0,
BNeg,
BAdd,
BSub,
BMul,
BSDiv,
BUDiv,
BSRem,
BURem,
BSMod,
BSDiv0,
BUDiv0,
BSRem0,
BURem0,
BSMod0,
BULeq,
BSLeq,
BUGeq,
BSGeq,
BULt,
BSLt,
BUGt,
BSGt,
BAnd,
BOr,
BNot,
BXor,
BNand,
BNor,
BXnor,
BConcat,
BSignExt,
BZeroExt,
BExtract,
BRepeat,
BRedOr,
BRedAnd,
BComp,
BShl,
BLShr,
BAShr,
BRotateLeft,
BRotateRight,
BExtRotateLeft,
BExtRotateRight,
BInt2Bv,
BBv2Int,
BCarry,
BXor3,
PrAsserted,
PrGoal,
PrModusPonens,
PrReflexivity,
PrTransitivity,
PrTransitivityStar,
PrSymmetry,
PrMonotonicity,
PrQuantIntro,
PrDistributivity,
PrAndElim,
PrNotOrElim,
PrRewrite,
PrRewriteStar,
PrPullQuant,
PrPullQuantStar,
PrPushQuant,
PrElimUnusedVars,
PrDer,
PrQuantInst,
PrHypothesis,
PrLemma,
PrUnitResolution,
PrIffTrue,
PrIffFalse,
PrCommutativity,
PrDefAxiom,
PrDefIntro,
PrApplyDef,
PrIffOeq,
PrNnfPos,
PrNnfNeg,
PrNnfStar,
PrSkolemize,
PrCnfStar,
PrModusPonensOeq,
PrThLemma,
RaStore,
RaEmpty,
RaIsEmpty,
RaJoin,
RaUnion,
RaWiden,
RaProject,
RaFilter,
RaNegationFilter,
RaRename,
RaComplement,
RaSelect,
RaClone,
Label,
LabelLit,
Uninterpreted
};
/**
\brief IErrorHandler is an abstract (interface) class for passing
an error handler.
The \c Handler method takes as argument an \c ErrorCode and processes
it.
*/
public interface class IErrorHandler
{
public:
virtual void Handler(ErrorCode code) = 0;
};
/// @cond 0
LBool ToLBool(Z3_lbool b) {
switch(b) {
case Z3_L_FALSE: return LBool::False;
case Z3_L_TRUE: return LBool::True;
default: return LBool::Undef;
}
}
/// @endcond
/**
\brief Container for labeled literals.
A satisfiable state can be queried for a set of labeled literals that are satisfied.
*/
public ref class LabeledLiterals {
ref_context& m_context;
Z3_literals m_labels;
internal:
LabeledLiterals(ref_context& ctx, Z3_literals lbls): m_context(ctx), m_labels(lbls) { ctx.inc_ref(); }
Z3_literals Get() { return m_labels; }
TermPtr GetLiteral(unsigned idx) { return TermPtr(Z3_get_literal(m_context(), m_labels, idx)); }
protected:
!LabeledLiterals();
public:
~LabeledLiterals() { if (m_labels) { Z3_del_literals(m_context(), m_labels); } m_labels = 0; m_context.dec_ref(); }
unsigned GetNumLabels() { return Z3_get_num_literals(m_context(), m_labels); }
void Disable(unsigned idx) { Z3_disable_literal(m_context(), m_labels, idx); }
Symbol^ GetLabel(unsigned idx) { return gcnew Symbol(m_context(), Z3_get_label_symbol(m_context(), m_labels, idx)); }
};
/**
\brief Container for constructor declarations.
*/
public ref class Constructor {
ref_context& m_context;
Z3_constructor m_constructor;
FuncDeclPtr m_constructor_decl;
FuncDeclPtr m_tester;
array<FuncDeclPtr>^ m_accessors;
!Constructor();
internal:
String^ m_name;
String^ m_tester_name;
array<String^>^ m_field_names;
array<SortPtr>^ m_field_sorts;
array<unsigned>^ m_field_refs;
Constructor(
ref_context& context,
String^ name,
String^ tester,
array<String^>^ field_names,
array<SortPtr>^ field_sorts,
array<unsigned>^ field_refs
);
Z3_constructor Query();
Z3_constructor Get();
FuncDeclPtr GetConstructor();
FuncDeclPtr GetTester();
array<FuncDeclPtr>^ GetAccessors();
public:
~Constructor();
};
/**
\brief Configuration
Configuration can be set prior to creating an instance
of the Z3 Context.
To set a parameter create an instance of the Params class
and call the SetParamValue() method.
The set of legal parameters can be found by executing z3.exe /ini?
*/
public ref class Config
{
/// @cond 0
Z3_config m_config;
/// @endcond
internal:
/// @cond 0
Z3_config get() { return m_config; }
/// @endcond
protected:
!Config();
public:
/**
\brief Create configuration context.
Create a configuration context to supply configurations to the
Z3 #Context. Callers must explicitly close the configuration
in order to collect the resources allocated in the configuration.
*/
Config();
/// \brief Configuration destructor.
~Config();
/**
\brief Set parameter to specified value.
The list of all configuration parameters can be obtained using the Z3 executable:
\verbatim
z3.exe /ini?
\endverbatim
*/
void SetParamValue(String^ name, String^ value);
};
/**
\brief Z3 Parameter values.
*/
public interface class IRawParameter { };
public interface class IParameter { };
public ref class IntParameter : public IRawParameter, public IParameter {
int m_value;
internal:
IntParameter(int i) : m_value(i) {}
public:
property int Int { int get() { return m_value; } }
virtual String^ ToString() override { return m_value.ToString(); }
};
public ref class DoubleParameter : public IRawParameter, public IParameter {
double m_value;
internal:
DoubleParameter(double i) : m_value(i) {}
public:
property double Double { double get() { return m_value; } }
virtual String^ ToString() override { return m_value.ToString(); }
};
public ref class RationalParameter : public IRawParameter, public IParameter {
String^ m_value;
internal:
RationalParameter(String^ s): m_value(s) {}
public:
property String^ GetRational { String^ get() { return m_value; } }
virtual String^ ToString() override { return m_value; }
};
public ref class SymbolParameter : public IRawParameter, public IParameter {
Symbol^ m_value;
internal:
SymbolParameter(Symbol^ s): m_value(s) {}
public:
property Symbol^ GetSymbol { Symbol^ get() { return m_value; } }
};
public ref class TermPtrParameter : public IRawParameter {
TermPtr m_value;
internal:
TermPtrParameter(TermPtr t) : m_value(t) {}
public:
property TermPtr GetTerm { TermPtr get() { return m_value; } }
};
public ref class SortPtrParameter : public IRawParameter {
SortPtr m_value;
internal:
SortPtrParameter(SortPtr t) : m_value(t) {}
public:
property SortPtr GetSort { SortPtr get() { return m_value; } }
};
public ref class FuncDeclPtrParameter : public IRawParameter {
FuncDeclPtr m_value;
internal:
FuncDeclPtrParameter(FuncDeclPtr t) : m_value(t) {}
public:
property FuncDeclPtr GetFuncDecl { FuncDeclPtr get() { return m_value; } }
};
/**
\brief Z3 Array Value object.
*/
public ref class RawArrayValue {
public:
array<TermPtr>^ Domain;
array<TermPtr>^ Range;
TermPtr ElseCase;
};
/**
\brief Z3 Function entry object.
A FunctionEntry object summarizes what a function maps to
based on a given set of argument values.
*/
public ref class RawFunctionEntry {
public:
array<TermPtr>^ Arguments;
TermPtr Result;
};
/**
\brief Z3 Function graph object.
The finite function graph of an uninterpreted function
is represented as a list of #FunctionEntry entries, together
with a default value. The domain values not listed in the
#FunctionEntry array map to the default value \c Else.
\param Declaration contains the function declaration Ast.
\param Entries contains the array of entries where the function
is defined explicitly.
\param Contains the default value of the function; where the function
maps to a default value.
*/
public ref class RawFunctionGraph {
public:
FuncDeclPtr Declaration;
array<RawFunctionEntry^>^ Entries;
TermPtr Else;
};
public ref class RawQuantifier {
public:
bool IsForall;
unsigned Weight;
array<PatternPtr>^ Patterns;
array<TermPtr>^ NoPatterns;
array<SortPtr>^ Sorts;
array<Symbol^>^ Names;
TermPtr Body;
};
ref class RawModel;
public delegate void Action0();
generic<typename T, typename S>
public delegate void Action2(
T obj1,
S obj2
);
generic<typename T, typename S, typename U>
public delegate void Action3(
T obj1,
S obj2,
U obj3
);
generic<typename T>
public delegate T Func0();
generic<typename T, typename S>
public delegate S Func1(
T obj
);
generic<typename T, typename S, typename U>
public delegate U Func2(
T obj1,
S obj2
);
/**
\brief Z3 RawModel object.
*/
public ref class RawModel {
ref_context& m_context;
Z3_model m_model;
Dictionary<FuncDeclPtr, RawFunctionGraph^>^ m_graphs;
internal:
RawModel(ref_context& c, Z3_model m) : m_context(c), m_model(m), m_graphs(nullptr) { c.inc_ref(); }
void Reset();
protected:
!RawModel();
public:
~RawModel();
/**
\brief Return the constants assigned by the given model.
*/
array<FuncDeclPtr>^ GetModelConstants();
/**
\brief Return the function interpretations in the given model.
A function interpretation is represented as a finite map and an 'else' value.
Each entry in the finite map represents the value of a function given a set of arguments.
*/
Dictionary<FuncDeclPtr, RawFunctionGraph^>^ GetFunctionGraphs();
/**
\brief Evaluate the AST node \c t in the given model.
Return the result as a non-zero value. The
returned value is null if the term does not evaluate to a fixed value
in the current model.
term to a value.
The evaluation may fail for the following reasons:
- \c t contains a quantifier or bound variable.
- the model \c m is partial, that is, it doesn't have a complete interpretation for free functions.
That is, the option <tt>PARTIAL_MODELS=true</tt> was used.
- the evaluator doesn't have support for some interpreted operator.
- \c t is type incorrect (see #TypeCheck).
- The result of an intepreted operator in \c t is undefined (e.g. division by zero).
*/
TermPtr Eval(TermPtr);
TermPtr Eval(FuncDeclPtr, array<TermPtr>^ args);
/**
\brief Return decomposed sequence of stores as an array value.
*/
bool TryGetArrayValue(TermPtr a,[Out] RawArrayValue^% av);
/**
\brief Convert the given model into a string.
*/
virtual String^ ToString() override;
/**
\brief Display model to TextWriter
*/
void Display(System::IO::TextWriter^ w);
};
public ref class ReferenceCounted {};
public ref class TermProofPtr {
TermPtr m_term;
TermPtr m_proof; // proof is optional, use IntPtr::Zero for absence of proofs.
public:
TermProofPtr(TermPtr term, TermPtr proof): m_term(term), m_proof(proof) {}
property TermPtr GetTerm { TermPtr get() { return m_term; } }
property TermPtr Proof { TermPtr get() { return m_proof; } }
};
ref class RawTheory;
/**
\brief Z3 API object.
*/
public ref class RawContext : public MarshalByRefObject
{
ref_context* m_context;
bool m_disposed;
static List<KeyValuePair<AstPtr,RawContext^> >^ s_todec;
static IntPtr^ s_monitor;
static bool s_nonempty;
void Init();
internal:
static IErrorHandler^ m_error_handler = nullptr;
Z3_context ctx() { return (*m_context)(); }
Z3_fixedpoint dl() { return m_context->dl(); }
ref_context& ref_context() { return *m_context; }
/**
\brief Increment and decrement reference counters on
terms, sorts and declarations.
These methods are required when the context is created
using the ReferenceCounted argument.
*/
void IncRef(AstPtr ast);
void EnqueueDecRef(AstPtr ast);
protected:
!RawContext();
public:
/**
\brief Create a logical context using the given configuration.
After a context is created, the configuration cannot be changed.
All main interaction with Z3 happens in the context of a \c Context.
All contexts that are created must be disposed (call Dispose).
Failure to dispose contexts cause memory leaks.
Garbage collection will not free resources allocated in contexts.
*/
RawContext(Config^ config);
/**
\brief Create a logical context using the given configuration.
This constructor is similar to the default RawContext constructor.
Reference counts to terms, functions, and sorts that are created
over the API have to be handled explicitly by the caller, however.
Terms (sorts, declarations) created by the context have initially
reference count 0, and the caller has to explicitly manage the reference counts.
This mode is more flexible, but also very error prone.
Use the metheods AddRef and DecRef on terms, sorts, declarations to
control the reference counts.
All contexts that are created must be disposed (call Dispose).
Failure to dispose contexts cause memory leaks.
Garbage collection will not free resources allocated in contexts.
*/
RawContext(Config^ config, ReferenceCounted^ rc);
RawContext();
void SetContext(Z3_context ctx);
void Reset();
~RawContext();
/**
@name Tracing and logging
*/
/*@{*/
/**
\brief Enable low-level debug tracing.
This method only works with debug builds.
*/
void EnableDebugTrace(String^ 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);
/**
\brief Update a mutable configuration parameter.
The list of all configuration parameters can be obtained using the Z3 executable:
\verbatim
z3.exe -ini?
\endverbatim
Only a few configuration parameters are mutable once the context is created.
The error handler is invoked when trying to modify an immutable parameter.
\sa SetParamValue
*/
void UpdateParamValue(String^ param_id, String^ value);
/**
\brief Get a configuration parameter.
\sa Z3_mk_config
\sa Z3_set_param_value
*/
String^ GetParamValue(String^ param_id);
/**
\brief Configure the SMTLIB logic to be used in the given logical context.
*/
bool SetLogic(String^ logic);
/*@}*/
/**
@name Symbols
*/
/*@{*/
/**
\brief Create a Z3 symbol using an intege or a string.
Symbols are used to name several term and type constructors.
*/
Symbol^ MkSymbol(int i);
Symbol^ MkSymbol(String^ s);
/*@}*/
/**
@name Types
*/
/*@{*/
/**
\brief Create a free (uninterpreted) type using the given name (symbol).
Two free types are considered the same iff the have the same name.
*/
SortPtr MkSort(Symbol^ s);
SortPtr MkSort(String^ s);
SortPtr MkSort(int i);
/**
\brief Create the boolean type.
This type is used to create propositional variables and predicates.
*/
SortPtr MkBoolSort();
/**
\brief Create an integer type.
This type is not the int type found in programming languages.
A machine integer can be represented using bit-vectors. The function
#MkBvType creates a bit-vector type.
\sa MkBvType
*/
SortPtr MkIntSort();
/**
\brief Create a real type.
This type is not a floating point number.
Z3 does not have support for floating point numbers yet.
*/
SortPtr MkRealSort();
/**
\brief Create a bit-vector type of the given size.
This type can also be seen as a machine integer.
\remark The size of the bitvector type must be greater than zero.
*/
SortPtr MkBvSort(unsigned sz);
/**
\brief Create an array type.
We usually represent the array type as: <tt>[domain -> range]</tt>.
Arrays are usually used to model the heap/memory in software verification.
\sa MkArraySelect
\sa MkArrayStore
\sa MkArrayMap
\sa MkConstArray
*/
SortPtr MkArraySort(SortPtr domain, SortPtr range);
/**
\brief Create a named finite domain sort.
To create constants that belong to the finite domain,
use MkNumeral for creating numerals and pass a numeric
constant together with the sort returned by this call.
*/
SortPtr MkFiniteDomainSort(String^ name, unsigned __int64 domain_size);
/**
\brief Create a tuple type.
A tuple with \c n fields has a constructor and \c n projections.
This function will also declare the constructor and projection functions.
\param mk_tuple_name name of the constructor function associated with the tuple type.
\param field_names name of the projection functions.
\param field_types type of the tuple fields.
\param mk_tuple_decl output parameter that will contain the constructor declaration.
\param proj_decl output parameter that will contain the projection function declarations.
This field must be a buffer of size \c num_fields allocated by the user.
*/
SortPtr MkTupleSort(
Symbol^ mk_tuple_name,
array<Symbol^>^ field_names,
array<SortPtr>^ field_types,
[Out] FuncDeclPtr% mk_tuple_decl,
[In] [Out] array<FuncDeclPtr>^ proj_decl
);
SortPtr MkTupleSort(
String^ mk_tuple_name,
array<String^>^ field_names,
array<SortPtr>^ field_types,
[Out] FuncDeclPtr% mk_tuple_decl,
[In, Out] array<FuncDeclPtr>^ proj_decl
);
/**
\brief create an enumeration type.
\param name - name of enumeration sort.
\param enum_names - names of enumerated elements.
\param enum_consts - output function declarations for enumerated elements.
\param enum_testers - output function declarations for enumeration testers.
*/
SortPtr MkEnumerationSort(
String^ name,
array<String^>^ enum_names,
array<FuncDeclPtr>^ enum_consts,
array<FuncDeclPtr>^ enum_testers);
/**
\brief create list sort.
\param name of resulting list type.
\param elem_sort sort of elements.
\param nil_decl function declaration for nil.
\param is_nil_decl function declaration for nil tester.
\param cons_decl function declaration for cons constructor.
\param is_cons_decl function declaration for cons tester.
\param head_decl function declaration for head accessor.
\param tail_decl function declaration for tail accessor.
*/
SortPtr MkListSort(
String^ name,
SortPtr elem_sort,
[Out] FuncDeclPtr% nil_decl,
[Out] FuncDeclPtr% is_nil_decl,
[Out] FuncDeclPtr% cons_decl,
[Out] FuncDeclPtr% is_cons_decl,
[Out] FuncDeclPtr% head_decl,
[Out] FuncDeclPtr% tail_decl
);
/**
\brief create constructor object for datatype declarations.
The object must be disposed with manually.
Use the methods #GetConstructor, #GetTester, and #GetAccessors to
retrieve the function declarations for constructors, tester and accessors
after the datatype has been declared.
A field_ref is the index of the (mutually) recursive datatype.
For example, if you declare a single recursive datatype, then
a reference to the recursive datatype that is being declared is
the number 0. If you declare two mutually recursive datatypes, then
the reference to the second recursive datatype is 1.
*/
Constructor^ MkConstructor(
String^ name,
String^ tester,
array<String^>^ field_names,
array<SortPtr>^ field_sorts,
array<unsigned>^ field_refs
);
/**
\brief retrieve constructor function declaration.
*/
FuncDeclPtr GetConstructor(Constructor^ c) { return c->GetConstructor(); }
/**
\brief retrieve test function for constructor.
*/
FuncDeclPtr GetTester(Constructor^ c) { return c->GetTester(); }
/**
\brief retrieve accessors for datatype.
*/
array<FuncDeclPtr>^ GetAccessors(Constructor^ c) { return c->GetAccessors(); }
/**
\brief create datatype sort.
*/
SortPtr MkDataType(
String^ name,
array<Constructor^>^ constructors
);
/**
\brief create datatype sorts.
\param names array of names for the recursive datatypes.
\param constructors array of arrays of constructors.
*/
array<SortPtr>^ MkDataTypes(
array<String^>^ names,
array<array<Constructor^>^>^ constructors
);
/*@}*/
/**
@name Constants and Applications
*/
/*@{*/
/**
\brief Declare a constant or function.
\param s name of the constant or function.
\param domain array containing the type of each argument.
The array must contain domain_size elements. It is 0 whe declaring a constant.
\param range type of the constant or the return type of the function.
After declaring a constant or function, the function
#MkApp can be used to create a constant or function
application.
\sa MkApp
*/
FuncDeclPtr MkFuncDecl(Symbol^ s, array<SortPtr>^ domain, SortPtr range);
FuncDeclPtr MkFuncDecl(String^ s, array<SortPtr>^ domain, SortPtr range);
FuncDeclPtr MkConstDecl(Symbol^ s, SortPtr ty) {
return MkFuncDecl(s, gcnew array<SortPtr>(0), ty);
}
FuncDeclPtr MkFuncDecl(Symbol^ s, SortPtr domain, SortPtr range);
FuncDeclPtr MkFuncDecl(Symbol^ s, SortPtr d1, SortPtr d2, SortPtr range);
FuncDeclPtr MkConstDecl(String^ s, SortPtr ty) {
return MkFuncDecl(s, gcnew array<SortPtr>(0), ty);
}
FuncDeclPtr MkFuncDecl(String^ s, SortPtr domain, SortPtr range);
FuncDeclPtr MkFuncDecl(String^ s, SortPtr d1, SortPtr d2, SortPtr range);
/**
\brief Create a constant or function application.
\sa MkFuncDecl
*/
AppPtr MkApp(FuncDeclPtr d, array<TermPtr>^ args);
AppPtr MkApp(FuncDeclPtr d, TermPtr arg);
AppPtr MkApp(FuncDeclPtr d, TermPtr arg1, TermPtr arg2);
AppPtr MkApp(FuncDeclPtr d, TermPtr arg1, TermPtr arg2, TermPtr arg3);
/**
\brief Declare and create a constant.
\sa MkApp
\sa MkFuncDecl
*/
AppPtr MkConst(FuncDeclPtr d);
AppPtr MkConst(String^ s, SortPtr ty);
AppPtr MkConst(Symbol^ s, SortPtr ty);
/**
\brief Declare a fresh constant or function.
Z3 will generate an unique name for this function declaration.
\sa MkFuncDecl
*/
FuncDeclPtr MkFreshFuncDecl(String^ prefix, array<SortPtr>^ domain, SortPtr range);
/**
\brief Declare and create a fresh constant.
\sa MkFuncDecl
\sa MkApp
*/
TermPtr MkFreshConst(String^ prefix, SortPtr ty);
/**
\brief Create labeled formula.
*/
TermPtr MkLabel(Symbol^ name, bool pos, TermPtr fml);
/**
\brief Create an AST node representing \c true.
*/
TermPtr MkTrue() { return TermPtr(Z3_mk_true(ctx())); }
/**
\brief Create an AST node representing \c false.
*/
TermPtr MkFalse() { return TermPtr(Z3_mk_false(ctx())); }
/**
\brief Create an AST node representing <tt>l = r</tt>.
The nodes \c l and \c r must have the same type.
*/
TermPtr MkEq(TermPtr l, TermPtr r);
/**
\brief Create an AST node representing <tt>distinct(args[0], ..., args[args.Length-1])</tt>.
The \c distinct construct is used for declaring the arguments pairwise distinct.
That is, <tt>Forall 0 <= i < j < args.Length. not args[i] = args[j]</tt>.
All arguments must have the same type.
\remark The number of arguments of a distinct construct must be greater than one.
*/
TermPtr MkDistinct(array<TermPtr>^ args);
/**
\brief Create an AST node representing <tt>not(a)</tt>.
The node \c a must have Boolean type.
*/
virtual TermPtr MkNot(TermPtr arg);
/**
\brief
Create an AST node representing an if-then-else: <tt>ite(t1, t2, t3)</tt>.
The node \c t1 must have Boolean type, \c t2 and \c t3 must have the same type.
The type of the new node is equal to the type of \c t2 and \c t3.
*/
TermPtr MkIte(TermPtr t1, TermPtr t2, TermPtr t3);
/**
\brief Create an AST node representing <tt>t1 iff t2</tt>.
The nodes \c t1 and \c t2 must have Boolean type.
*/
TermPtr MkIff(TermPtr t1, TermPtr t2);
/**
\brief Create an AST node representing <tt>t1 implies t2</tt>.
The nodes \c t1 and \c t2 must have Boolean type.
*/
TermPtr MkImplies(TermPtr t1, TermPtr t2);
/**
\brief Create an AST node representing <tt>t1 xor t2</tt>.
The nodes \c t1 and \c t2 must have Boolean type.
*/
TermPtr MkXor(TermPtr t1, TermPtr t2);
/**
\brief Create an AST node representing <tt>args[0] and ... and args[args.Length-1]</tt>.
All arguments must have Boolean type.
\remark The number of arguments must be greater than zero.
*/
TermPtr MkAnd(array<TermPtr>^ args);
TermPtr MkAnd(TermPtr arg1, TermPtr arg2);
/**
\brief Create an AST node representing <tt>args[0] or ... or args[args.Length-1]</tt>.
All arguments must have Boolean type.
\remark The number of arguments must be greater than zero.
*/
TermPtr MkOr(array<TermPtr>^ args);
TermPtr MkOr(TermPtr arg1, TermPtr arg2);
/**
\brief Create an AST node representing <tt>args[0] + ... + args[args.Length-1]</tt>.
All arguments must have int or real type.
\remark The number of arguments must be greater than zero.
*/
TermPtr MkAdd(array<TermPtr>^ args);
TermPtr MkAdd(TermPtr arg1, TermPtr arg2);
/**
\brief Create an AST node representing <tt>args[0] * ... * args[args.Length-1]</tt>.
All arguments must have int or real type.
\remark Z3 has limited support for non-linear arithmetic.
\remark The number of arguments must be greater than zero.
*/
TermPtr MkMul(array<TermPtr>^ args);
TermPtr MkMul(TermPtr arg1, TermPtr arg2);
/**
\brief Create an AST node representing <tt>args[0] - ... - args[args.Length - 1]</tt>.
All arguments must have int or real type.
\remark The number of arguments must be greater than zero.
*/
TermPtr MkSub(array<TermPtr>^ args);
TermPtr MkSub(TermPtr arg1, TermPtr arg2);
/**
\brief Create an AST node representing <tt>- arg</tt>.
The argument must have int or real type.
*/
TermPtr MkUnaryMinus(TermPtr arg);
/**
\brief Create integer or real division.
The nodes \c arg1 and \c arg2 must have the same type, and must be int or real.
*/
TermPtr MkDiv(TermPtr arg1, TermPtr arg2);
/**
\brief Create integer modulus
The nodes \c arg1 and \c arg2 must have integer type.
*/
TermPtr MkMod(TermPtr arg1, TermPtr arg2);
/**
\brief Create integer remainder
The nodes \c arg1 and \c arg2 must have integer type.
*/
TermPtr MkRem(TermPtr arg1, TermPtr arg2);
/**
\brief Create coercion from integer to real
The node \c arg must have integer type.
*/
TermPtr MkToReal(TermPtr arg);
/**
\brief Create coercion from real to integer (floor)
The node \c arg must have real type.
*/
TermPtr MkToInt(TermPtr arg);
/**
\brief Check if real is an integer value.
The node \c arg must have real type.
*/
TermPtr MkIsInt(TermPtr arg);
/**
\brief Create less than.
The nodes \c arg1 and \c arg2 must have the same type, and must be int or real.
*/
TermPtr MkLt(TermPtr arg1, TermPtr arg2);
/**
\brief Create less than or equal to.
The nodes \c arg1 and \c arg2 must have the same type, and must be int or real.
*/
TermPtr MkLe(TermPtr arg1, TermPtr arg2);
/**
\brief Create greater than.
The nodes \c arg1 and \c arg2 must have the same type, and must be int or real.
*/
TermPtr MkGt(TermPtr arg1, TermPtr arg2);
/**
\brief Create greater than or equal to.
The nodes \c arg1 and \c arg2 must have the same type, and must be int or real.
*/
TermPtr MkGe(TermPtr arg1, TermPtr arg2);
/**
\brief Bitwise negation.
The node \c arg1 must have a bit-vector type.
*/
TermPtr MkBvNot(TermPtr t1);
/**
\brief Take conjunction of bits in vector.
The node \c arg1 must have a bit-vector type.
*/
TermPtr MkBvReduceAnd(TermPtr t1);
/**
\brief Take disjunction of bits in vector.
The node \c arg1 must have a bit-vector type.
*/
TermPtr MkBvReduceOr(TermPtr t1);
/**
\brief Bitwise and.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvAnd(TermPtr t1, TermPtr t2);
/**
\brief Bitwise or.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvOr(TermPtr t1, TermPtr t2);
/**
\brief Bitwise exclusive-or.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvXor(TermPtr t1, TermPtr t2);
/**
\brief Bitwise nand.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvNand(TermPtr t1, TermPtr t2);
/**
\brief Bitwise nor.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvNor(TermPtr t1, TermPtr t2);
/**
\brief Bitwise xnor.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvXnor(TermPtr t1, TermPtr t2);
/**
\brief Standard two's complement unary minus.
The node \c t1 must have bit-vector type.
*/
TermPtr MkBvNeg(TermPtr t1);
/**
\brief Standard two's complement addition.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvAdd(TermPtr t1, TermPtr t2);
/**
\brief Standard two's complement subtraction.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvSub(TermPtr t1, TermPtr t2);
/**
\brief Standard two's complement multiplication.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvMul(TermPtr t1, TermPtr t2);
/**
\brief Unsigned division.
It is defined as the \c floor of <tt>t1/t2</tt> if \c t2 is
different from zero. If <tt>t2</tt> is zero, then the result
is undefined.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvUdiv(TermPtr t1, TermPtr t2);
/**
\brief Two's complement signed division.
It is defined in the following way:
- The \c floor of <tt>t1/t2</tt> if \c t2 is different from zero, and <tt>t1*t2 >= 0</tt>.
- The \c ceiling of <tt>t1/t2</tt> if \c t2 is different from zero, and <tt>t1*t2 < 0</tt>.
If <tt>t2</tt> is zero, then the result is undefined.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvSdiv(TermPtr t1, TermPtr t2);
/**
\brief Unsigned remainder.
It is defined as <tt>t1 - (t1 /u t2) * t2</tt>, where <tt>/u</tt> represents unsigned division.
If <tt>t2</tt> is zero, then the result is undefined.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvUrem(TermPtr t1, TermPtr t2);
/**
\brief Two's complement signed remainder (sign follows dividend).
It is defined as <tt>t1 - (t1 /s t2) * t2</tt>, where <tt>/s</tt> represents signed division.
The most significant bit (sign) of the result is equal to the most significant bit of \c t1.
If <tt>t2</tt> is zero, then the result is undefined.
The nodes \c t1 and \c t2 must have the same bit-vector type.
\sa MkBvSmod
*/
TermPtr MkBvSrem(TermPtr t1, TermPtr t2);
/**
\brief Two's complement signed remainder (sign follows divisor).
If <tt>t2</tt> is zero, then the result is undefined.
The nodes \c t1 and \c t2 must have the same bit-vector type.
\sa MkBvSrem
*/
TermPtr MkBvSmod(TermPtr t1, TermPtr t2);
/**
\brief Unsigned less than.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvUlt(TermPtr t1, TermPtr t2);
/**
\brief Two's complement signed less than.
It abbreviates:
\code
(or (and (= (extract[|m-1|:|m-1|] s) bit1)
(= (extract[|m-1|:|m-1|] t) bit0))
(and (= (extract[|m-1|:|m-1|] s) (extract[|m-1|:|m-1|] t))
(bvult s t)))
\endcode
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvSlt(TermPtr t1, TermPtr t2);
/**
\brief Unsigned less than or equal to.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvUle(TermPtr t1, TermPtr t2);
/**
\brief Two's complement signed less than or equal to.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvSle(TermPtr t1, TermPtr t2);
/**
\brief Unsigned greater than or equal to.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvUge(TermPtr t1, TermPtr t2);
/**
\brief Two's complement signed greater than or equal to.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvSge(TermPtr t1, TermPtr t2);
/**
\brief Unsigned greater than.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvUgt(TermPtr t1, TermPtr t2);
/**
\brief Two's complement signed greater than.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvSgt(TermPtr t1, TermPtr t2);
/**
\brief Concatenate the given bit-vectors.
The nodes \c t1 and \c t2 must have (possibly different) bit-vector types
The result is a bit-vector of size <tt>n1+n2</tt>, where \c n1 (\c n2) is the size
of \c t1 (\c t2).
*/
TermPtr MkBvConcat(TermPtr t1, TermPtr t2);
/**
\brief Extract the bits \c high down to \c low from a bitvector of
size \c m to yield a new bitvector of size \c n, where <tt>n =
high - low + 1</tt>.
The node \c t must have a bit-vector type.
*/
TermPtr MkBvExtract(unsigned high, unsigned low, TermPtr t);
/**
\brief Sign-extend of the given bit-vector to the (signed) equivalent bitvector of
size <tt>m+i</tt>, where \c m is the size of the given
bit-vector.
The node \c t must have a bit-vector type.
*/
TermPtr MkBvSignExt(unsigned i, TermPtr t);
/**
\brief Extend the given bit-vector with zeros to the (unsigned) equivalent
bitvector of size <tt>m+i</tt>, where \c m is the size of the
given bit-vector.
The node \c t1 must have a bit-vector type.
*/
TermPtr MkBvZeroExt(unsigned i, TermPtr t);
/**
\brief Repeat the bit-vector <tt>i</tt> times.
The node \c t1 must have a bit-vector type.
*/
TermPtr MkBvRepeat(unsigned i, TermPtr t);
/**
\brief Shift left.
It is equivalent to multiplication by <tt>2^x</tt> where \c x is the value of the
third argument.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvShl(TermPtr t1, TermPtr t2);
/**
\brief Logical shift right.
It is equivalent to unsigned division by <tt>2^x</tt> where \c x is the
value of the third argument.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvLshr(TermPtr t1, TermPtr t2);
/**
\brief Arithmetic shift right.
It is like logical shift right except that the most significant
bits of the result always copy the most significant bit of the
second argument.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvAshr(TermPtr t1, TermPtr t2);
/**
\brief Rotate bits of \c t1 to the left \c i times.
The node \c t1 must have a bit-vector type.
*/
TermPtr MkBvRotateLeft(unsigned i, TermPtr t1);
/**
\brief Rotate bits of \c t1 to the right \c i times.
The node \c t1 must have a bit-vector type.
*/
TermPtr MkBvRotateRight(unsigned i, TermPtr t1);
/**
\brief Rotate bits of \c t1 to the left \c t2 times.
The node \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvRotateLeft(TermPtr t1, TermPtr t2);
/**
\brief Rotate bits of \c t1 to the right \c t2 times.
The node \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvRotateRight(TermPtr t1, TermPtr t2);
/**
\brief Convert bit vector to integer.
The node \c t1 must have a bit-vector type.
*/
TermPtr MkBv2Int(TermPtr t1, bool is_signed);
/**
\brief Convert integer to bit vector.
The node \c t1 must have a integer type.
*/
TermPtr MkInt2Bv(unsigned size, TermPtr t1);
/**
\brief Check that addition does not overflow.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvAddNoOverflow(TermPtr t1, TermPtr t2, bool is_signed);
/**
\brief Check that addition does not underflow.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvAddNoUnderflow(TermPtr t1, TermPtr t2);
/**
\brief Check that subtraction does not overflow.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvSubNoOverflow(TermPtr t1, TermPtr t2);
/**
\brief Check that subtraction does not underflow.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvSubNoUnderflow(TermPtr t1, TermPtr t2, bool is_signed);
/**
\brief Check that division does not overflow.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvSDivNoOverflow(TermPtr t1, TermPtr t2);
/**
\brief Check that negation does not overflow.
*/
TermPtr MkBvNegNoOverflow(TermPtr t1);
/**
\brief Check that multiplication does not overflow.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvMulNoOverflow(TermPtr t1, TermPtr t2, bool is_signed);
/**
\brief Check that multiplication does not underflow.
The nodes \c t1 and \c t2 must have the same bit-vector type.
*/
TermPtr MkBvMulNoUnderflow(TermPtr t1, TermPtr t2);
/**
\brief Array read.
The node \c a must have an array type <tt>[domain -> range]</tt>, and \c i must have the type \c domain.
The type of the result is \c range.
\sa MkArraySort
\sa MkArrayStore
*/
TermPtr MkArraySelect(TermPtr a, TermPtr i);
/**
\brief Array update.
The node \c a must have an array type <tt>[domain -> range]</tt>, \c i must have type \c domain,
\c v must have type range. The type of the result is <tt>[domain -> range]</tt>.
\sa MkArraySort
\sa MkArraySelect
*/
TermPtr MkArrayStore(TermPtr a, TermPtr i, TermPtr v);
/**
\brief Array map.
The \c n nodes \c args must be of array sorts <tt>[domain_i -> range_i]</tt>.
The function declaration \c f must have type <tt> range_1 .. range_n -> range</tt>.
\c v must have sort range. The sort of the result is <tt>[domain_i -> range]</tt>.
\sa MkArraySort
\sa MkArraySelect
\sa MkArrayStore
*/
TermPtr MkArrayMap(FuncDeclPtr d, array<TermPtr>^ args);
/**
\brief Constant array.
The node \c a must have an array type <tt>[range]</tt>, \c domain indicates the domain
of the array.
The type of the result is <tt>[domain -> range]</tt>.
\sa MkArraySort
\sa MkArraySelect
\sa MkArrayStore
*/
TermPtr MkArrayConst(SortPtr domain, TermPtr v);
/**
\brief Access the array default.
The node \c a must have an array type <tt>[domain -> range]</tt>.
The type of the result is <tt>[range]</tt>. The result is a term
whose value holds the default array value. That is, models should
ensure that the default for <tt>a</tt> (ElseCase) evaluates to the
same value as <tt>MkArrayDefault(a)</tt>.
\sa MkArraySort
\sa MkArraySelect
\sa MkArrayStore
\sa MkArrayconst
*/
TermPtr MkArrayDefault(TermPtr a);
/*@}*/
/**
@name Sets
*/
/*@{*/
/**
\brief Create Set type.
*/
SortPtr MkSetSort(SortPtr ty) { return SortPtr(Z3_mk_set_sort(ctx(), get_sort(ty))); }
/**
\brief Create the empty set.
*/
TermPtr MkEmptySet(SortPtr ty) { return TermPtr(Z3_mk_empty_set(ctx(), get_sort(ty))); }
/**
\brief Create the full set.
*/
TermPtr MkFullSet(SortPtr ty) { return TermPtr(Z3_mk_full_set(ctx(), get_sort(ty))); }
/**
\brief Add an element to a set.
The first argument must be a set, the second an element.
*/
TermPtr MkSetAdd(TermPtr set, TermPtr elem) {
return TermPtr(Z3_mk_set_add(ctx(), get_ast(set), get_ast(elem)));
}
/**
\brief Remove an element to a set.
The first argument must be a set, the second an element.
*/
TermPtr MkSetDel(TermPtr set, TermPtr elem) {
return TermPtr(Z3_mk_set_del(ctx(), get_ast(set), get_ast(elem)));
}
/**
\brief Take the union of a arrays of sets.
The arguments must all be of the same type and all be of set types.
*/
TermPtr MkSetUnion(array<TermPtr>^ sets);
TermPtr MkSetUnion(TermPtr set1, TermPtr set2);
/**
\brief Take the intersection of a arrays of sets.
*/
TermPtr MkSetIntersect(array<TermPtr>^ sets);
TermPtr MkSetIntersect(TermPtr set1, TermPtr set2);
/**
\brief Take the set difference between two sets.
*/
TermPtr MkSetDifference(TermPtr arg1, TermPtr arg2) {
return TermPtr(Z3_mk_set_difference(ctx(), get_ast(arg1), get_ast(arg2)));
}
/**
\brief Take the complement of a set.
*/
TermPtr MkSetComplement(TermPtr arg) {
return TermPtr(Z3_mk_set_complement(ctx(), get_ast(arg)));
}
/**
\brief Check for set membership.
The first argument should be an element type of the set.
*/
TermPtr MkSetMember(TermPtr elem, TermPtr set) {
return TermPtr(Z3_mk_set_member(ctx(), get_ast(elem), get_ast(set)));
}
/**
\brief Check for subsetness of sets.
*/
TermPtr MkSetSubset(TermPtr arg1, TermPtr arg2) {
return TermPtr(Z3_mk_set_subset(ctx(), get_ast(arg1), get_ast(arg2)));
}
/*@}*/
/**
@name Injective functions
*/
/*@{*/
/**
\brief Create injective function
*/
FuncDeclPtr MkInjectiveFunction(String^ name, array<SortPtr>^ domain, SortPtr range);
FuncDeclPtr MkInjectiveFunction(Symbol^ name, array<SortPtr>^ 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 <tt>[num]* / [num]*</tt>.
\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 <tt>MkPattern</tt>.
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
<pre>
pattern1 = context.MkPattern(new TermPtr[]{
context.MkArrayStore(A,I,V),
context.MkArraySelect(A,J)
})
</pre>
Then form the array
<pre>
new PatternPtr[]{ pattern1 }
</pre>
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:
<pre>
pattern2 = context.MkPattern(new TermPtr[] {
context.MkArraySelect(context.MkArrayStore(A,I,V),J) })
</pre>
Then form the array:
<pre>
new PatternPtr[] { pattern1, pattern2 }
</pre>
\sa MkForall
\sa MkExists
*/
PatternPtr MkPattern(array<TermPtr>^ 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<PatternPtr>^ patterns,
array<SortPtr>^ types,
array<Symbol^>^ 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<PatternPtr>^ patterns,
array<SortPtr>^ types,
array<String^>^ 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
<tt>bound</tt> 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<AppPtr>^ bound,
array<PatternPtr>^ patterns,
TermPtr body
);
/**
\brief Create an exists formula. Similar to #MkForall.
\sa MkPattern
\sa MkBound
\sa MkForall
*/
TermPtr MkExists(
unsigned weight,
array<PatternPtr>^ patterns,
array<SortPtr>^ types,
array<Symbol^>^ names,
TermPtr body
);
TermPtr MkExists(
unsigned weight,
array<PatternPtr>^ patterns,
array<SortPtr>^ types,
array<String^>^ names,
TermPtr body
);
TermPtr MkExists(
unsigned weight,
array<AppPtr>^ bound,
array<PatternPtr>^ 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<PatternPtr>^ patterns,
array<TermPtr>^ no_patterns,
array<SortPtr>^ types,
array<Symbol^>^ 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<PatternPtr>^ patterns,
array<TermPtr>^ no_patterns,
array<SortPtr>^ types,
array<Symbol^>^ 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<PatternPtr>^ patterns,
array<TermPtr>^ no_patterns,
array<TermPtr>^ 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<IRawParameter^>^ 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<TermPtr>^ 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<TermPtr>^ 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<SortPtr>^ 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<FuncDeclPtr>^ 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<TermPtr>^ 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<TermPtr>^ assumptions,
[Out] TermPtr% proof,
[Out] array<TermPtr>^% 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<TermPtr>^ terms,
[Out] array<unsigned>^% 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<TermPtr>^ 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<SortPtr>^ sorts,
[In] array<FuncDeclPtr>^ decls,
[Out] array<TermPtr>^% assumptions,
[Out] array<TermPtr>^% formulas,
[Out] array<FuncDeclPtr>^% new_decls,
[Out] array<SortPtr>^% new_sorts,
[Out] String^% parser_out
);
/**
\brief Similar to #ParseSmtlibString, but reads the benchmark from a file.
*/
void ParseSmtlibFile(
String^ file,
[In] array<SortPtr>^ sorts,
[In] array<FuncDeclPtr>^ decls,
[Out] array<TermPtr>^% assumptions,
[Out] array<TermPtr>^% formulas,
[Out] array<FuncDeclPtr>^% new_decls,
[Out] array<SortPtr>^% 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<SortPtr>^ sorts, array<FuncDeclPtr>^ decls);
/**
\brief Parse a file containing formulas in SMT-LIB2 format.
Return conjunction of Asserts occurring in the file.
*/
TermPtr ParseSmtlib2File(String^ filename, array<SortPtr>^ sorts, array<FuncDeclPtr>^ decls);
/**
\brief Execute commands from a string in the SMT-LIB2 format.
Return conjunction of Asserts modulo push/pop.
*/
TermPtr ExecSmtlib2String(String^ s, array<SortPtr>^ sorts, array<FuncDeclPtr>^ 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<SortPtr>^ sorts, array<FuncDeclPtr>^ 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<GCHandle, RawContext^>^ 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<TermPtr>^ queries);
array<TermPtr>^ SimplifyFixedpointRules(array<TermPtr>^ rules, array<FuncDeclPtr>^ 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<FuncDeclPtr, array<TermPtr>^, array<TermPtr>^>^ m_fixedpoint_assign;
Func2<FuncDeclPtr, array<TermPtr>^, TermPtr>^ m_fixedpoint_apply;
void init_fixedpoint_callbacks();
public:
property Action3<FuncDeclPtr, array<TermPtr>^, array<TermPtr>^>^ FixedpointAssign {
void set(Action3<FuncDeclPtr, array<TermPtr>^, array<TermPtr>^>^ value) {
m_fixedpoint_assign = value;
init_fixedpoint_callbacks();
}
}
property Func2<FuncDeclPtr, array<TermPtr>^, TermPtr>^ FixedpointApply {
void set(Func2<FuncDeclPtr, array<TermPtr>^, 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<GCHandle,RawTheory^>^ 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<TermPtr, TermPtr, TermPtr>^ reduce_eq;
void set_reduce_eq(Func2<TermPtr, TermPtr, TermPtr>^ value);
public:
property Func2<TermPtr, TermPtr, TermPtr>^ ReduceEq {
void set(Func2<TermPtr, TermPtr, TermPtr>^ value) {
set_reduce_eq(value);
}
}
// ReduceApp
private:
Func2<FuncDeclPtr, array<TermPtr>^, TermPtr>^ reduce_app;
void set_reduce_app(Func2<FuncDeclPtr, array<TermPtr>^, TermPtr>^ value);
public:
property Func2<FuncDeclPtr, array<TermPtr>^, TermPtr>^ ReduceApp {
void set(Func2<FuncDeclPtr, array<TermPtr>^, 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<array<TermPtr>^, TermPtr>^ reduce_distinct;
void set_reduce_distinct(Func1<array<TermPtr>^, TermPtr>^ value);
internal:
static Z3_bool reduce_distinct_callback(Z3_theory th, unsigned n, Z3_ast const args[], Z3_ast* r);
public:
property Func1<array<TermPtr>^, TermPtr>^ ReduceDistinct {
void set(Func1<array<TermPtr>^, TermPtr>^ value) {
set_reduce_distinct(value);
}
}
// NewRelevant
internal:
Action<TermPtr>^ new_relevant;
private:
void set_new_relevant(Action<TermPtr>^ value);
public:
property Action<TermPtr>^ NewRelevant {
void set(Action<TermPtr>^ value) {
set_new_relevant(value);
}
}
// NewApp
private:
void set_new_app(Action<TermPtr>^ value);
internal:
Action<TermPtr>^ new_app;
public:
property Action<TermPtr>^ NewApp {
void set(Action<TermPtr>^ value) {
set_new_app(value);
}
}
// NewElem
private:
void set_new_elem(Action<TermPtr>^ value);
internal:
Action<TermPtr>^ new_elem;
public:
property Action<TermPtr>^ NewElem {
void set(Action<TermPtr>^ 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<bool>^ value);
internal:
Func0<bool>^ final_check;
public:
property Func0<bool>^ FinalCheck {
void set(Func0<bool>^ value) { set_final_check(value); }
}
// NewEq
private:
void set_new_eq(Action2<TermPtr, TermPtr>^ value);
internal:
Action2<TermPtr, TermPtr>^ new_eq;
public:
property Action2<TermPtr, TermPtr>^ NewEq
{
void set(Action2<TermPtr, TermPtr>^ value) { set_new_eq(value); }
}
// NewDiseq
private:
void set_new_diseq(Action2<TermPtr, TermPtr>^ value);
internal:
Action2<TermPtr, TermPtr>^ new_diseq;
public:
property Action2<TermPtr, TermPtr>^ NewDiseq
{
void set(Action2<TermPtr, TermPtr>^ value) { set_new_diseq(value); }
}
// NewAssignment
internal:
Action2<TermPtr, bool>^ new_assignment;
private:
void set_new_assignment(Action2<TermPtr, bool>^ value);
public:
property Action2<TermPtr, bool>^ NewAssignment {
void set(Action2<TermPtr, bool>^ 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<TermPtr>^ GetParents(TermPtr n) {
unsigned np = Z3_theory_get_num_parents(m_theory, get_ast(n));
array<TermPtr>^ result = gcnew array<TermPtr>(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<TermPtr>^ GetElems()
{
unsigned n = Z3_theory_get_num_elems(m_theory);
array<TermPtr>^ result = gcnew array<TermPtr>(n);
for (unsigned i = 0; i < n; ++i)
{
result[i] = TermPtr(Z3_theory_get_elem(m_theory, i));
}
return result;
}
array<TermPtr>^ GetApps()
{
unsigned n = Z3_theory_get_num_apps(m_theory);
array<TermPtr>^ result = gcnew array<TermPtr>(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<SortPtr>^ domain, SortPtr range);
SortPtr MkSort(String^ s);
TermPtr MkValue(String^ s, SortPtr srt);
TermPtr MkConstant(String^ s, SortPtr srt);
FuncDeclPtr MkFuncDecl(String^ n, array<SortPtr>^ 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<Term^>^ 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<Pattern^>^ Patterns;
array<Term^>^ NoPatterns;
array<Sort^>^ Sorts;
array<Symbol^>^ Names;
Term^ Body;
};
public ref class ArrayValue {
public:
array<Term^>^ Domain;
array<Term^>^ 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<class Tptr, class T>
array<Tptr>^ CopyArray(array<T^>^ a) {
if (!a) {
return gcnew array<Tptr>(0);
}
int len = a->Length;
array<Tptr>^ result = gcnew array<Tptr>(len);
for (int i = 0; i < len; ++i) {
if (a[i]) {
result[i] = a[i]();
}
else {
result[i] = IntPtr(0);
}
}
return result;
}
array<SortPtr>^ CopyArray(array<Sort^>^ a) {
return CopyArray<SortPtr, Sort>(a);
}
array<FuncDeclPtr>^ CopyArray(array<FuncDecl^>^ a) {
return CopyArray<FuncDeclPtr, FuncDecl>(a);
}
array<TermPtr>^ CopyArray(array<Term^>^ a) {
return CopyArray<TermPtr,Term>(a);
}
array<PatternPtr>^ CopyArray(array<Pattern^>^ a) {
return CopyArray<PatternPtr,Pattern>(a);
}
internal:
template<class T, class TPtr>
static array<T^>^ CopyAstArray(RawContext^ ctx, array<TPtr>^ a) {
if (!a) return nullptr;
int len = a->Length;
array<T^>^ result = gcnew array<T^>(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<class T, class TPtr>
array<T^>^ CopyAstArray(array<TPtr>^ a) {
return CopyAstArray<T,TPtr>(m_ctx, a);
}
array<Sort^>^ CopySortArray(array<SortPtr>^ a) {
return CopyAstArray<Sort, SortPtr>(a);
}
array<Term^>^ CopyTermArray(array<TermPtr>^ a) {
return CopyAstArray<Term, TermPtr>(a);
}
array<FuncDecl^>^ CopyFuncDeclArray(array<FuncDeclPtr>^ a) {
return CopyAstArray<FuncDecl, FuncDeclPtr>(a);
}
internal:
static array<Term^>^ CopyTermArray(RawContext^ ctx, array<TermPtr>^ a) {
return CopyAstArray<Term, TermPtr>(ctx, a);
}
static array<Sort^>^ CopySortArray(RawContext^ ctx, array<SortPtr>^ a) {
return CopyAstArray<Sort, SortPtr>(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<Term^>^ 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<Term^>^ assumptions,
[Out] Term^% proof,
[Out] array<Term^>^% core);
void SoftCheckCancel();
LBool GetImpliedEqualities(
[In] array<Term^>^ terms,
[Out] array<unsigned>^% 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<Term^>^ assumptions,
Term^ formula);
void ParseSmtlibString(
String^ string,
[In] array<Sort^>^ sorts,
[In] array<FuncDecl^>^ decls,
[Out] array<Term^>^% assumptions,
[Out] array<Term^>^% formulas,
[Out] array<FuncDecl^>^% new_decls,
[Out] array<Sort^>^% new_sorts,
[Out] String^% parser_out
);
void ParseSmtlibFile(
String^ file,
[In] array<Sort^>^ sorts,
[In] array<FuncDecl^>^ decls,
[Out] array<Term^>^% assumptions,
[Out] array<Term^>^% formulas,
[Out] array<FuncDecl^>^% new_decls,
[Out] array<Sort^>^% new_sorts,
[Out] String^% parser_out
);
Term^ ParseZ3String(String^ s) {
return gcnew Term(m_ctx,m_ctx->ParseZ3String(s));
}
Term^ ParseZ3File(String^ s) {
return gcnew Term(m_ctx,m_ctx->ParseZ3File(s));
}
Term^ ParseSmtlib2String(String^ s, array<Sort^>^ sorts, array<FuncDecl^>^ decls) {
return gcnew Term(m_ctx,m_ctx->ParseSmtlib2String(s, CopyArray(sorts), CopyArray(decls)));
}
Term^ ParseSmtlib2File(String^ s, array<Sort^>^ sorts, array<FuncDecl^>^ decls) {
return gcnew Term(m_ctx,m_ctx->ParseSmtlib2File(s, CopyArray(sorts), CopyArray(decls)));
}
Term^ ExecSmtlib2String(String^ s, array<Sort^>^ sorts, array<FuncDecl^>^ decls) {
return gcnew Term(m_ctx,m_ctx->ExecSmtlib2String(s, CopyArray(sorts), CopyArray(decls)));
}
Term^ ExecSmtlib2File(String^ s, array<Sort^>^ sorts, array<FuncDecl^>^ decls) {
return gcnew Term(m_ctx,m_ctx->ExecSmtlib2File(s, CopyArray(sorts), CopyArray(decls)));
}
static void SetErrorHandler(IErrorHandler^ h) {
RawContext::SetErrorHandler(h);
}
static String^ GetErrorMessage(ErrorCode err) {
return RawContext::GetErrorMessage(err);
}
static void ResetMemory() {
RawContext::ResetMemory();
}
void SetPrintMode(PrintMode mode) { m_ctx->SetPrintMode(mode); }
String^ ToString(Ast^ a) { return m_ctx->ToString(a()); }
void Display(System::IO::TextWriter^ w, Ast^ a) { m_ctx->Display(w, a()); }
Sort^ MkIntSort() { return gcnew Sort(m_ctx,m_ctx->MkIntSort()); }
Sort^ MkBoolSort() { return gcnew Sort(m_ctx,m_ctx->MkBoolSort()); }
Sort^ MkSort(Symbol^ s) { return gcnew Sort(m_ctx,m_ctx->MkSort(s)); }
Sort^ MkSort(String^ s) { return gcnew Sort(m_ctx,m_ctx->MkSort(s)); }
Sort^ MkSort(int i) { return gcnew Sort(m_ctx,m_ctx->MkSort(i)); }
Sort^ MkFiniteDomainSort(String^ s, unsigned __int64 domain_size) { return gcnew Sort(m_ctx, m_ctx->MkFiniteDomainSort(s, domain_size)); }
Sort^ MkRealSort() { return gcnew Sort(m_ctx,m_ctx->MkRealSort()); }
Sort^ MkBvSort(unsigned sz) { return gcnew Sort(m_ctx,m_ctx->MkBvSort(sz)); }
Sort^ MkArraySort(Sort^ domain, Sort^ range) { return gcnew Sort(m_ctx,m_ctx->MkArraySort(domain(), range())); }
Sort^ MkTupleSort(
Symbol^ mk_tuple_name,
array<Symbol^>^ field_names,
array<Sort^>^ field_types,
[Out] FuncDecl^% mk_tuple_decl,
[In, Out] array<FuncDecl^>^ proj_decl
);
Sort^ MkTupleSort(
String^ mk_tuple_name,
array<String^>^ field_names,
array<Sort^>^ field_types,
[Out] FuncDecl^% mk_tuple_decl,
[In, Out] array<FuncDecl^>^ proj_decl
);
Sort^ MkEnumerationSort(
String^ name,
array<String^>^ enum_names,
array<FuncDecl^>^ enum_consts,
array<FuncDecl^>^ enum_testers);
Sort^ MkListSort(
String^ name,
Sort^ elem_sort,
[Out] FuncDecl^% nil_decl,
[Out] FuncDecl^% is_nil_decl,
[Out] FuncDecl^% cons_decl,
[Out] FuncDecl^% is_cons_decl,
[Out] FuncDecl^% head_decl,
[Out] FuncDecl^% tail_decl
);
Constructor^ MkConstructor(
String^ name,
String^ tester,
array<String^>^ field_names,
array<Sort^>^ field_sorts,
array<unsigned>^ field_refs
);
FuncDecl^ GetConstructor(Constructor^ c);
FuncDecl^ GetTester(Constructor^ c);
array<FuncDecl^>^ GetAccessors(Constructor^ c);
/**
\brief create datatype sort.
*/
Sort^ MkDataType(
String^ name,
array<Constructor^>^ constructors
) {
return gcnew Sort(m_ctx, m_ctx->MkDataType(name, constructors));
}
/**
\brief create datatype sort.
*/
array<Sort^>^ MkDataTypes(
array<String^>^ names,
array<array<Constructor^>^>^ constructors
) {
return CopySortArray(m_ctx->MkDataTypes(names, constructors));
}
FuncDecl^ MkFuncDecl(Symbol^ s, array<Sort^>^ domain, Sort^ range) {
return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, CopyArray(domain), range()));
}
FuncDecl^ MkFuncDecl(String^ s, array<Sort^>^ domain, Sort^ range) {
return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, CopyArray(domain), range()));
}
FuncDecl^ MkConstDecl(Symbol^ s, Sort^ ty) {
return MkFuncDecl(s, gcnew array<Sort^>(0), ty);
}
FuncDecl^ MkFuncDecl(Symbol^ s, Sort^ domain, Sort^ range) {
return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, domain(), range()));
}
FuncDecl^ MkFuncDecl(Symbol^ s, Sort^ d1, Sort^ d2, Sort^ range) {
return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, d1(), d2(), range()));
}
FuncDecl^ MkConstDecl(String^ s, Sort^ ty) {
return MkFuncDecl(s, gcnew array<Sort^>(0), ty);
}
FuncDecl^ MkFuncDecl(String^ s, Sort^ domain, Sort^ range) {
return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, domain(), range()));
}
FuncDecl^ MkFuncDecl(String^ s, Sort^ d1, Sort^ d2, Sort^ range) {
return gcnew FuncDecl(m_ctx,m_ctx->MkFuncDecl(s, d1(), d2(), range()));
}
Term^ MkApp(FuncDecl^ d, array<Term^>^ args) {
return gcnew Term(m_ctx,m_ctx->MkApp(d(), CopyArray(args)));
}
Term^ MkApp(FuncDecl^ d, Term^ arg) {
return gcnew Term(m_ctx,m_ctx->MkApp(d(), arg()));
}
Term^ MkApp(FuncDecl^ d, Term^ arg1, Term^ arg2) {
return gcnew Term(m_ctx,m_ctx->MkApp(d(), arg1(), arg2()));
}
Term^ MkApp(FuncDecl^ d, Term^ arg1, Term^ arg2, Term^ arg3) {
return gcnew Term(m_ctx,m_ctx->MkApp(d(), arg1(), arg2(), arg3()));
}
Term^ MkConst(FuncDecl^ d) {
return gcnew Term(m_ctx,m_ctx->MkConst(d()));
}
Term^ MkConst(String^ s, Sort^ ty) {
return gcnew Term(m_ctx,m_ctx->MkConst(s,ty()));
}
Term^ MkConst(Symbol^ s, Sort^ ty) {
return gcnew Term(m_ctx,m_ctx->MkConst(s, ty()));
}
FuncDecl^ MkFreshFuncDecl(String^ prefix, array<Sort^>^ domain, Sort^ range) {
return gcnew FuncDecl(m_ctx,m_ctx->MkFreshFuncDecl(prefix, CopyArray(domain), range()));
}
Term^ MkFreshConst(String^ prefix, Sort^ ty) {
return gcnew Term(m_ctx,m_ctx->MkFreshConst(prefix, ty()));
}
Term^ MkTrue() { return gcnew Term(m_ctx,m_ctx->MkTrue()); }
Term^ MkFalse() { return gcnew Term(m_ctx,m_ctx->MkFalse()); }
Term^ MkLabel(Symbol^ name, bool pos, Term^ fml) { return gcnew Term(m_ctx,m_ctx->MkLabel(name, pos, fml())); }
Term^ MkEq(Term^ l, Term^ r) { return gcnew Term(m_ctx,m_ctx->MkEq(l(), r())); }
Term^ MkDistinct(array<Term^>^ args) {
return gcnew Term(m_ctx,m_ctx->MkDistinct(CopyArray(args)));
}
Term^ MkNot(Term^ arg) { return gcnew Term(m_ctx,m_ctx->MkNot(arg())); }
Term^ MkIte(Term^ t1, Term^ t2, Term^ t3) {
return gcnew Term(m_ctx,m_ctx->MkIte(t1(), t2(), t3()));
}
Term^ MkIff(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkIff(t1(), t2())); }
Term^ MkImplies(Term^ t1, Term^ t2) {return gcnew Term(m_ctx,m_ctx->MkImplies(t1(), t2()));}
Term^ MkXor(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkXor(t1(), t2())); }
Term^ MkAnd(array<Term^>^ args) { return gcnew Term(m_ctx,m_ctx->MkAnd(CopyArray(args))); }
Term^ MkAnd(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkAnd(t1(), t2())); }
Term^ MkOr(array<Term^>^ args) { return gcnew Term(m_ctx,m_ctx->MkOr(CopyArray(args))); }
Term^ MkOr(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkOr(t1(), t2())); }
Term^ MkAdd(array<Term^>^ args) { return gcnew Term(m_ctx,m_ctx->MkAdd(CopyArray(args))); }
Term^ MkAdd(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkAdd(t1(), t2())); }
Term^ MkMul(array<Term^>^ args) { return gcnew Term(m_ctx,m_ctx->MkMul(CopyArray(args))); }
Term^ MkMul(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkMul(t1(), t2())); }
Term^ MkSub(array<Term^>^ args) { return gcnew Term(m_ctx,m_ctx->MkSub(CopyArray(args))); }
Term^ MkSub(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkSub(t1(), t2())); }
Term^ MkUnaryMinus(Term^ arg) { return gcnew Term(m_ctx,m_ctx->MkUnaryMinus(arg())); }
Term^ MkDiv(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkDiv(t1(), t2())); }
Term^ MkMod(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkMod(t1(), t2())); }
Term^ MkRem(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkRem(t1(), t2())); }
Term^ MkToReal(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkToReal(t1())); }
Term^ MkToInt(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkToInt(t1())); }
Term^ MkIsInt(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkIsInt(t1())); }
Term^ MkLt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkLt(t1(), t2())); }
Term^ MkLe(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkLe(t1(), t2())); }
Term^ MkGt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkGt(t1(), t2())); }
Term^ MkGe(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkGe(t1(), t2())); }
Term^ MkBvNot(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvNot(t1())); }
Term^ MkBvReduceAnd(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvReduceAnd(t1())); }
Term^ MkBvRedcueOr(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvReduceOr(t1())); }
Term^ MkBvAnd(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvAnd(t1(), t2())); }
Term^ MkBvOr(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvOr(t1(), t2())); }
Term^ MkBvXor(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvXor(t1(), t2())); }
Term^ MkBvNand(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvNand(t1(), t2())); }
Term^ MkBvNor(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvNor(t1(), t2())); }
Term^ MkBvXnor(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvXnor(t1(), t2())); }
Term^ MkBvNeg(Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvNeg(t1())); }
Term^ MkBvAdd(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvAdd(t1(), t2())); }
Term^ MkBvSub(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSub(t1(), t2())); }
Term^ MkBvMul(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvMul(t1(), t2())); }
Term^ MkBvUdiv(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUdiv(t1(), t2())); }
Term^ MkBvSdiv(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSdiv(t1(), t2())); }
Term^ MkBvUrem(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUrem(t1(), t2())); }
Term^ MkBvSrem(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSrem(t1(), t2())); }
Term^ MkBvSmod(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSmod(t1(), t2())); }
Term^ MkBvUlt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUlt(t1(), t2())); }
Term^ MkBvSlt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSlt(t1(), t2())); }
Term^ MkBvUle(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUle(t1(), t2())); }
Term^ MkBvSle(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSle(t1(), t2())); }
Term^ MkBvUge(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUge(t1(), t2())); }
Term^ MkBvSge(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSge(t1(), t2())); }
Term^ MkBvUgt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvUgt(t1(), t2())); }
Term^ MkBvSgt(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvSgt(t1(), t2())); }
Term^ MkBvConcat(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvConcat(t1(), t2())); }
Term^ MkBvExtract(unsigned high, unsigned low, Term^ t) {
return gcnew Term(m_ctx,m_ctx->MkBvExtract(high, low, t()));
}
Term^ MkBvSignExt(unsigned i, Term^ t) {
return gcnew Term(m_ctx,m_ctx->MkBvSignExt(i, t()));
}
Term^ MkBvZeroExt(unsigned i, Term^ t) {
return gcnew Term(m_ctx,m_ctx->MkBvZeroExt(i, t()));
}
Term^ MkBvRepeat(unsigned i, Term^ t) {
return gcnew Term(m_ctx,m_ctx->MkBvRepeat(i, t()));
}
Term^ MkBvShl(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvShl(t1(), t2())); }
Term^ MkBvLshr(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvLshr(t1(), t2())); }
Term^ MkBvAshr(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvAshr(t1(), t2())); }
Term^ MkBvRotateLeft(unsigned i, Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvRotateLeft(i,t1())); }
Term^ MkBvRotateRight(unsigned i, Term^ t1) { return gcnew Term(m_ctx,m_ctx->MkBvRotateRight(i,t1())); }
Term^ MkBvRotateLeft(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvRotateLeft(t1(), t2())); }
Term^ MkBvRotateRight(Term^ t1, Term^ t2) { return gcnew Term(m_ctx,m_ctx->MkBvRotateRight(t1(), t2())); }
Term^ MkBv2Int(Term^ t1, bool is_signed) { return gcnew Term(m_ctx, m_ctx->MkBv2Int(t1(), is_signed)); }
Term^ MkInt2Bv(unsigned n, Term^ t1) { return gcnew Term(m_ctx, m_ctx->MkInt2Bv(n, t1())); }
Term^ MkBvAddNoOverflow(Term^ t1, Term^ t2, bool is_signed) {
return gcnew Term(m_ctx,m_ctx->MkBvAddNoOverflow(t1(), t2(), is_signed));
}
Term^ MkBvAddNoUnderflow(Term^ t1, Term^ t2) {
return gcnew Term(m_ctx,m_ctx->MkBvAddNoUnderflow(t1(), t2()));
}
Term^ MkBvSubNoOverflow(Term^ t1, Term^ t2) {
return gcnew Term(m_ctx,m_ctx->MkBvSubNoOverflow(t1(), t2()));
}
Term^ MkBvSubNoUnderflow(Term^ t1, Term^ t2, bool is_signed) {
return gcnew Term(m_ctx,m_ctx->MkBvSubNoUnderflow(t1(), t2(), is_signed));
}
Term^ MkBvSDivNoOverflow(Term^ t1, Term^ t2) {
return gcnew Term(m_ctx,m_ctx->MkBvSDivNoOverflow(t1(), t2()));
}
Term^ MkBvNegNoOverflow(Term^ t1) {
return gcnew Term(m_ctx,m_ctx->MkBvNegNoOverflow(t1()));
}
Term^ MkBvMulNoOverflow(Term^ t1, Term^ t2, bool is_signed) {
return gcnew Term(m_ctx,m_ctx->MkBvMulNoOverflow(t1(), t2(), is_signed));
}
Term^ MkBvMulNoUnderflow(Term^ t1, Term^ t2) {
return gcnew Term(m_ctx,m_ctx->MkBvMulNoUnderflow(t1(), t2()));
}
Term^ MkArraySelect(Term^ a, Term^ i) { return gcnew Term(m_ctx,m_ctx->MkArraySelect(a(), i())); }
Term^ MkArrayStore(Term^ a, Term^ i, Term^ v) {
return gcnew Term(m_ctx,m_ctx->MkArrayStore(a(), i(), v()));
}
Term^ MkArrayMap(FuncDecl^ f, array<Term^>^ args) {
return gcnew Term(m_ctx, m_ctx->MkArrayMap(f(), CopyArray(args)));
}
Term^ MkArrayConst(Sort^ domain, Term^ v) { return gcnew Term(m_ctx,m_ctx->MkArrayConst(domain(), v())); }
Term^ MkArrayDefault(Term^ a) { return gcnew Term(m_ctx,m_ctx->MkArrayDefault(a())); }
Sort^ MkSetSort(Sort^ ty) { return gcnew Sort(m_ctx,m_ctx->MkSetSort(ty())); }
Term^ MkEmptySet(Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkEmptySet(ty())); }
Term^ MkFullSet(Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkFullSet(ty())); }
Term^ MkSetAdd(Term^ set, Term^ elem) { return gcnew Term(m_ctx,m_ctx->MkSetAdd(set(), elem())); }
Term^ MkSetDel(Term^ set, Term^ elem) { return gcnew Term(m_ctx,m_ctx->MkSetDel(set(), elem())); }
Term^ MkSetUnion(array<Term^>^ sets) {
return gcnew Term(m_ctx,m_ctx->MkSetUnion(CopyArray(sets)));
}
Term^ MkSetUnion(Term^ set1, Term^ set2) {
return gcnew Term(m_ctx,m_ctx->MkSetUnion(set1(), set2()));
}
Term^ MkSetIntersect(array<Term^>^ sets) {
return gcnew Term(m_ctx,m_ctx->MkSetIntersect(CopyArray(sets)));
}
Term^ MkSetIntersect(Term^ set1, Term^ set2) {
return gcnew Term(m_ctx,m_ctx->MkSetIntersect(set1(), set2()));
}
Term^ MkSetDifference(Term^ t1, Term^ t2) {
return gcnew Term(m_ctx,m_ctx->MkSetDifference(t1(), t2()));
}
Term^ MkSetComplement(Term^ arg) {
return gcnew Term(m_ctx,m_ctx->MkSetComplement(arg()));
}
Term^ MkSetMember(Term^ elem, Term^ set) {
return gcnew Term(m_ctx,m_ctx->MkSetMember(elem(), set()));
}
Term^ MkSetSubset(Term^ t1, Term^ t2) {
return gcnew Term(m_ctx,m_ctx->MkSetSubset(t1(), t2()));
}
FuncDecl^ MkInjectiveFunction(String^ name, array<Sort^>^ domain, Sort^ range) {
return gcnew FuncDecl(m_ctx,m_ctx->MkInjectiveFunction(name, CopyArray(domain), range()));
}
FuncDecl^ MkInjectiveFunction(Symbol^ name, array<Sort^>^ domain, Sort^ range) {
return gcnew FuncDecl(m_ctx,m_ctx->MkInjectiveFunction(name, CopyArray(domain), range()));
}
Term^ MkNumeral(String^ numeral, Sort^ ty) {
return gcnew Term(m_ctx,m_ctx->MkNumeral(numeral, ty()));
}
Term^ MkNumeral(int n, Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkNumeral(n, ty())); }
Term^ MkNumeral(unsigned n, Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkNumeral(n, ty())); }
Term^ MkNumeral(__int64 n, Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkNumeral(n, ty())); }
Term^ MkNumeral(unsigned __int64 n, Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkNumeral(n, ty())); }
Term^ MkIntNumeral(String^ n) { return MkNumeral(n, MkIntSort()); }
Term^ MkIntNumeral(int n) { return MkNumeral(n, MkIntSort()); }
Term^ MkIntNumeral(unsigned n) { return MkNumeral(n, MkIntSort()); }
Term^ MkIntNumeral(__int64 n) { return MkNumeral(n, MkIntSort()); }
Term^ MkIntNumeral(unsigned __int64 n) { return MkNumeral(n, MkIntSort()); }
Term^ MkRealNumeral(String^ n) { return MkNumeral(n, MkRealSort()); }
Term^ MkRealNumeral(int n) { return MkNumeral(n, MkRealSort()); }
Term^ MkRealNumeral(unsigned n) { return MkNumeral(n, MkRealSort()); }
Term^ MkRealNumeral(__int64 n) { return MkNumeral(n, MkRealSort()); }
Term^ MkRealNumeral(unsigned __int64 n) { return MkNumeral(n, MkRealSort()); }
Pattern^ MkPattern(array<Term^>^ terms) { return gcnew Pattern(m_ctx,m_ctx->MkPattern(CopyArray(terms))); }
Term^ MkBound(unsigned index, Sort^ ty) { return gcnew Term(m_ctx,m_ctx->MkBound(index, ty())); }
Term^ MkForall(
unsigned weight,
array<Pattern^>^ patterns,
array<Sort^>^ types,
array<Symbol^>^ names,
Term^ body
) {
return gcnew Term(m_ctx,m_ctx->MkForall(weight, CopyArray(patterns), CopyArray(types), names, body()));
}
Term^ MkForall(
unsigned weight,
array<Pattern^>^ patterns,
array<Sort^>^ types,
array<String^>^ names,
Term^ body
) {
return gcnew Term(m_ctx,m_ctx->MkForall(weight, CopyArray(patterns), CopyArray(types), names, body()));
}
Term^ MkForall(
unsigned weight,
array<Term^>^ bound,
array<Pattern^>^ patterns,
Term^ body
) {
return gcnew Term(m_ctx,m_ctx->MkForall(weight, CopyArray(bound), CopyArray(patterns), body()));
}
Term^ MkExists(
unsigned weight,
array<Pattern^>^ patterns,
array<Sort^>^ types,
array<Symbol^>^ names,
Term^ body
) {
return gcnew Term(m_ctx,m_ctx->MkExists(weight, CopyArray(patterns), CopyArray(types), names, body()));
}
Term^ MkExists(
unsigned weight,
array<Pattern^>^ patterns,
array<Sort^>^ types,
array<String^>^ names,
Term^ body
) {
return gcnew Term(m_ctx,m_ctx->MkExists(weight, CopyArray(patterns), CopyArray(types), names, body()));
}
Term^ MkExists(
unsigned weight,
array<Term^>^ bound,
array<Pattern^>^ patterns,
Term^ body
) {
return gcnew Term(m_ctx,m_ctx->MkExists(weight, CopyArray(bound), CopyArray(patterns), body()));
}
Term^ MkQuantifier(
bool is_forall,
unsigned weight,
array<Pattern^>^ patterns,
array<Term^>^ no_patterns,
array<Sort^>^ types,
array<Symbol^>^ names,
Term^ body
) {
return MkQuantifier(is_forall, weight, nullptr, nullptr, patterns, no_patterns, types, names, body);
}
Term^ MkQuantifier(
bool is_forall,
unsigned weight,
Symbol^ quantifier_id,
Symbol^ skolem_id,
array<Pattern^>^ patterns,
array<Term^>^ no_patterns,
array<Sort^>^ types,
array<Symbol^>^ names,
Term^ body
) {
return gcnew Term(m_ctx,m_ctx->MkQuantifier(
is_forall, weight,
quantifier_id, skolem_id,
CopyArray(patterns),
CopyArray(no_patterns),
CopyArray(types),
names,
body()));
}
Term^ MkQuantifier(
bool is_forall,
unsigned weight,
Symbol^ quantifier_id,
Symbol^ skolem_id,
array<Pattern^>^ patterns,
array<Term^>^ no_patterns,
array<Term^>^ bound,
Term^ body
) {
return gcnew Term(m_ctx,m_ctx->MkQuantifier(
is_forall, weight,
quantifier_id, skolem_id,
CopyArray(patterns),
CopyArray(no_patterns),
CopyArray(bound),
body()));
}
SymbolKind GetSymbolKind(Symbol^ s) { return m_ctx->GetSymbolKind(s); }
int GetSymbolInt(Symbol^ s) { return m_ctx->GetSymbolInt(s); }
String^ GetSymbolString(Symbol^ s) { return m_ctx->GetSymbolString(s); }
bool IsEq(Term^ t1, Term^ t2) { return m_ctx->IsEq(t1(), t2()); }
bool IsWellSorted(Term^ t) { return m_ctx->IsWellSorted(t()); }
TermKind GetTermKind(Term^ a) { return m_ctx->GetTermKind(a()); }
DeclKind GetDeclKind(FuncDecl^ d) { return m_ctx->GetDeclKind(d()); }
array<IParameter^>^ GetDeclParameters(FuncDecl^ d);
FuncDecl^ GetAppDecl(Term^ a) { return gcnew FuncDecl(m_ctx,m_ctx->GetAppDecl(a())); }
array<Term^>^ GetAppArgs(Term^ a) { return CopyTermArray(m_ctx->GetAppArgs(a())); }
String^ GetNumeralString(Term^ a) { return m_ctx->GetNumeralString(a()); }
int GetNumeralInt(Term^ v) { return m_ctx->GetNumeralInt(v()); }
bool TryGetNumeralInt(Term^ v, [Out] int% i) { return m_ctx->TryGetNumeralInt(v(), i); }
unsigned int GetNumeralUInt(Term^ v) { return m_ctx->GetNumeralUInt(v()); }
bool TryGetNumeralUInt(Term^ v, [Out] unsigned int% u) { return m_ctx->TryGetNumeralUInt(v(), u); }
__int64 GetNumeralInt64(Term^ v) { return m_ctx->GetNumeralInt64(v()); }
bool TryGetNumeralInt64(Term^ v, [Out] __int64% i) { return m_ctx->TryGetNumeralInt64(v(), i); }
unsigned __int64 GetNumeralUInt64(Term^ v) { return m_ctx->GetNumeralUInt64(v()); }
bool TryGetNumeralUInt64(Term^ v, [Out] unsigned __int64% u) { return m_ctx->TryGetNumeralUInt64(v(), u); }
bool TryGetNumeral(Term^ v, [Out] __int64% num, [Out] __int64% den) { return m_ctx->TryGetNumeral(v(), num, den); }
void GetNumeral(Term^ v, [Out] System::Numerics::BigInteger% num, [Out] System::Numerics::BigInteger% den) {
m_ctx->GetNumeral(v(), num, den);
}
LBool GetBoolValue(Term^ v) { return m_ctx->GetBoolValue(v()); }
unsigned GetVarIndex(Term^ a) { return m_ctx->GetVarIndex(a()); }
Quantifier^ GetQuantifier(Term^ a) { return GetQuantifier(m_ctx, a); }
array<Term^>^ GetPatternTerms(Pattern^ p) { return CopyTermArray(m_ctx->GetPatternTerms(p())); }
Symbol^ GetDeclName(FuncDecl^ d) { return m_ctx->GetDeclName(d()); }
Symbol^ GetSortName(Sort^ ty) { return m_ctx->GetSortName(ty()); }
Sort^ GetSort(Term^ a) { return gcnew Sort(m_ctx,m_ctx->GetSort(a())); }
array<Sort^>^ GetDomain(FuncDecl^ d) { return CopySortArray(m_ctx->GetDomain(d())); }
Sort^ GetRange(FuncDecl^ d) { return gcnew Sort(m_ctx,m_ctx->GetRange(d())); }
SortKind GetSortKind(Sort^ t) { return m_ctx->GetSortKind(t()); }
unsigned GetBvSortSize(Sort^ t) { return m_ctx->GetBvSortSize(t()); }
Sort^ GetArraySortDomain(Sort^ t) { return gcnew Sort(m_ctx,m_ctx->GetArraySortDomain(t())); }
Sort^ GetArraySortRange(Sort^ t) { return gcnew Sort(m_ctx,m_ctx->GetArraySortRange(t())); }
FuncDecl^ GetTupleConstructor(Sort^ t) { return gcnew FuncDecl(m_ctx,m_ctx->GetTupleConstructor(t())); }
array<FuncDecl^>^ GetTupleFields(Sort^ t) { return CopyFuncDeclArray(m_ctx->GetTupleFields(t())); }
Theory^ MkTheory(String^ name);
void RegisterRelation(FuncDecl^ r) { m_ctx->RegisterRelation(r()); }
void AddRule(Term^ rule, Symbol^ name) { m_ctx->AddRule(rule(), name); }
LBool Query(Term^ query) { return m_ctx->Query(query()); }
String^ GetQueryStatus() { return m_ctx->GetQueryStatus(); }
Term^ GetQueryAnswer() { return gcnew Term(m_ctx, m_ctx->GetQueryAnswer()); }
String^ FixedpointkToString(array<Term^>^ queries) {
return m_ctx->FixedpointToString(CopyArray(queries));
}
array<Term^>^ SimplifyFixedpointRules(array<Term^>^ rules, array<FuncDecl^>^ output_predicates) {
return CopyTermArray(m_ctx->SimplifyFixedpointRules(CopyArray(rules), CopyArray(output_predicates)));
}
// functions for creating custom Fixedpoint relations.
private:
Action3<FuncDecl^, array<Term^>^, array<Term^>^>^ m_assign_callback;
void AssignCallbackAux(FuncDeclPtr f, array<TermPtr>^ args, array<TermPtr>^ outs) {
m_assign_callback(gcnew FuncDecl(m_ctx, f), CopyAstArray<Term, TermPtr>(args), CopyAstArray<Term, TermPtr>(outs));
}
Func2<FuncDecl^, array<Term^>^, Term^>^ m_apply_callback;
TermPtr ApplyCallbackAux(FuncDeclPtr f, array<TermPtr>^ args) {
return m_apply_callback(gcnew FuncDecl(m_ctx, f), CopyAstArray<Term, TermPtr>(args))();
}
public:
property Action3<FuncDecl^, array<Term^>^, array<Term^>^>^ FixedpointAssign {
void set(Action3<FuncDecl^, array<Term^>^, array<Term^>^>^ value) {
m_assign_callback = value;
m_ctx->FixedpointAssign = gcnew Action3<FuncDeclPtr, array<TermPtr>^, array<TermPtr>^>(this,&Context::AssignCallbackAux);
}
}
property Func2<FuncDecl^, array<Term^>^, Term^>^ FixedpointApply {
void set(Func2<FuncDecl^, array<Term^>^, Term^>^ value) {
m_apply_callback = value;
m_ctx->FixedpointApply = gcnew Func2<FuncDeclPtr, array<TermPtr>^, TermPtr>(this,&Context::ApplyCallbackAux);
}
}
};
public ref class FunctionEntry {
public:
array<Term^>^ Arguments;
Term^ Result;
};
public ref class FunctionGraph {
public:
FuncDecl^ Declaration;
array<FunctionEntry^>^ Entries;
Term^ Else;
};
public ref class Model {
RawModel^ m_model;
Context^ m_ctx;
ArrayValue^ Mk(RawArrayValue^ av);
FunctionEntry^ Mk(RawFunctionEntry^ fe);
FunctionGraph^ Mk(RawFunctionGraph^ fg);
Dictionary<FuncDecl^, FunctionGraph^>^ Mk(Dictionary<FuncDeclPtr, RawFunctionGraph^>^ fgs);
internal:
property Context^ GetContext { Context^ get() { return m_ctx; }}
property RawModel^ GetModel { RawModel^ get() { return m_model; }}
Model(RawModel^ m, Context^ c) : m_model(m), m_ctx(c) {}
public:
~Model() { m_model->Reset(); }
array<FuncDecl^>^ GetModelConstants() {
return m_ctx->CopyFuncDeclArray(m_model->GetModelConstants());
}
bool TryGetArrayValue(Term^ a, [Out] ArrayValue^% av);
Dictionary<FuncDecl^, FunctionGraph^>^ GetFunctionGraphs() { return Mk(m_model->GetFunctionGraphs()); }
Term^ Eval(Term^ t) { return gcnew Term(m_ctx->GetContext, m_model->Eval(t())); }
Term^ Eval(FuncDecl^ d, array<Term^>^ args) {
return gcnew Term(m_ctx->GetContext, m_model->Eval(d(), m_ctx->CopyArray(args)));
}
void Display(System::IO::TextWriter^ w) { m_model->Display(w); }
};
public ref class Theory
{
Context^ m_context;
RawTheory^ m_theory;
public:
property String^ Name { String^ get() { return m_theory->Name; } }
internal:
Theory(Context^ ctx, String^ name)
{
m_context = ctx;
m_theory = gcnew RawTheory(ctx->GetContext->ref_context(), name);
}
private:
array<Term^>^ MkTerms(array<TermPtr>^ ts)
{
return m_context->CopyAstArray<Term, TermPtr>(ts);
}
Term^ MkTerm(TermPtr t) { return gcnew Term(m_context->GetContext, t); }
FuncDecl^ MkFuncDecl(FuncDeclPtr f) { return gcnew FuncDecl(m_context->GetContext, f); }
TermPtr GetTermPtr(Term^ t)
{
if (t) return t();
return IntPtr::Zero;
}
public:
property Action0^ DeleteHandler
{
void set(Action0^ value)
{
m_theory->DeleteHandler = value;
}
}
private:
Func2<Term^, Term^, Term^>^ reduce_eq;
TermPtr ReduceEqAux(TermPtr a, TermPtr b) {
return GetTermPtr(reduce_eq(MkTerm(a), MkTerm(b)));
}
public:
property Func2<Term^, Term^, Term^>^ ReduceEq
{
void set(Func2<Term^, Term^, Term^>^ value)
{
reduce_eq = value;
m_theory->ReduceEq = gcnew Func2<TermPtr,TermPtr,TermPtr>(this,&Theory::ReduceEqAux);
}
}
private:
Func2<FuncDecl^, array<Term^>^, Term^>^ reduce_app;
TermPtr ReduceAppAux(FuncDeclPtr a, array<TermPtr>^ b) {
return GetTermPtr(reduce_app(MkFuncDecl(a), MkTerms(b)));
}
public:
property Func2<FuncDecl^, array<Term^>^, Term^>^ ReduceApp
{
void set(Func2<FuncDecl^, array<Term^>^, Term^>^ value)
{
reduce_app = value;
m_theory->ReduceApp = gcnew Func2<FuncDeclPtr,array<TermPtr>^,TermPtr>(this,&Theory::ReduceAppAux);
}
}
private:
Func1<array<Term^>^, Term^>^ reduce_distinct;
TermPtr ReduceDistinctAux(array<TermPtr>^ args) {
return GetTermPtr(reduce_distinct(MkTerms(args)));
}
public:
property Func1<array<Term^>^, Term^>^ ReduceDistinct
{
void set(Func1<array<Term^>^, Term^>^ value)
{
reduce_distinct = value;
m_theory->ReduceDistinct = gcnew Func1<array<TermPtr>^,TermPtr>(this, &Theory::ReduceDistinctAux);
}
}
private:
Action<Term^>^ new_app;
void NewAppAux(TermPtr a) { return new_app(MkTerm(a)); }
public:
property Action<Term^>^ NewApp
{
void set(Action<Term^>^ value)
{
new_app = value;
m_theory->NewApp = gcnew Action<TermPtr>(this, &Theory::NewAppAux);
}
}
private:
Action<Term^>^ new_elem;
void NewElemAux(TermPtr a) { return new_elem(MkTerm(a)); }
public:
property Action<Term^>^ NewElem
{
void set(Action<Term^>^ value)
{
new_elem = value;
m_theory->NewElem = gcnew Action<TermPtr>(this, &Theory::NewElemAux);
}
}
property Action0^ InitSearch
{
void set(Action0^ value)
{
m_theory->InitSearch = value;
}
}
property Action0^ Push
{
void set(Action0^ value)
{
m_theory->Push = value;
}
}
property Action0^ Pop
{
void set(Action0^ value)
{
m_theory->Pop = value;
}
}
property Action0^ Reset
{
void set(Action0^ value)
{
m_theory->Reset = value;
}
}
property Action0^ Restart
{
void set(Action0^ value)
{
m_theory->Restart = value;
}
}
property Func0<bool>^ FinalCheck
{
void set(Func0<bool>^ value)
{
m_theory->FinalCheck = value;
}
}
private:
Action2<Term^,Term^>^ new_eq;
void NewEqAux(TermPtr a, TermPtr b) {
new_eq(MkTerm(a), MkTerm(b));
}
public:
property Action2<Term^, Term^>^ NewEq
{
void set(Action2<Term^, Term^>^ value)
{
new_eq = value;
m_theory->NewEq = gcnew Action2<TermPtr,TermPtr>(this, &Theory::NewEqAux);
}
}
private:
Action2<Term^,Term^>^ new_diseq;
void NewDiseqAux(TermPtr a, TermPtr b) {
new_diseq(MkTerm(a), MkTerm(b));
}
public:
property Action2<Term^, Term^>^ NewDiseq
{
void set(Action2<Term^, Term^>^ value)
{
new_diseq = value;
m_theory->NewDiseq = gcnew Action2<TermPtr,TermPtr>(this, &Theory::NewDiseqAux);
}
}
private:
Action2<Term^,bool>^ new_assignment;
void NewAssignmentAux(TermPtr a, bool b) {
new_assignment(MkTerm(a), b);
}
public:
property Action2<Term^, bool>^ NewAssignment
{
void set(Action2<Term^, bool>^ value)
{
new_assignment = value;
m_theory->NewAssignment = gcnew Action2<TermPtr,bool>(this, &Theory::NewAssignmentAux);
}
}
private:
Action<Term^>^ new_relevant;
void NewRelevantAux(TermPtr a) { new_relevant(MkTerm(a)); }
public:
property Action<Term^>^ NewRelevant
{
void set(Action<Term^>^ value) {
new_relevant = value;
m_theory->NewRelevant = gcnew Action<TermPtr>(this, &Theory::NewRelevantAux);
}
}
void AssertTheoryAxiom(Term^ ax)
{
m_theory->AssertTheoryAxiom(ax());
}
void AssumeEq(Term^ lhs, Term^ rhs)
{
m_theory->AssumeEq(lhs(), rhs());
}
void EnableTheoryAxiomSimplification(bool flag)
{
m_theory->EnableTheoryAxiomSimplification(flag);
}
Term^ GetEqcRoot(Term^ n)
{
return MkTerm(m_theory->GetEqcRoot(n()));
}
Term^ GetEqcNext(Term^ n)
{
return MkTerm(m_theory->GetEqcNext(n()));
}
array<Term^>^ GetParents(Term^ n)
{
return MkTerms(m_theory->GetParents(n()));
}
bool IsTheoryValue(Term^ a)
{
return m_theory->IsTheoryValue(a());
}
bool IsTheoryDecl(FuncDecl^ d)
{
return m_theory->IsTheoryDecl(d());
}
array<Term^>^ GetElems()
{
return MkTerms(m_theory->GetElems());
}
array<Term^>^ GetApps()
{
return MkTerms(m_theory->GetApps());
}
Sort^ MkSort(Symbol^ s)
{
return gcnew Sort(m_context->GetContext,m_theory->MkSort(s));
}
Term^ MkValue(Symbol^ s, Sort^ srt)
{
return MkTerm(m_theory->MkValue(s, srt()));
}
Term^ MkConstant(Symbol^ s, Sort^ srt)
{
return MkTerm(m_theory->MkConstant(s, srt()));
}
FuncDecl^ MkFuncDecl(Symbol^ n, array<Sort^>^ domain, Sort^ range)
{
array<SortPtr>^ dom = gcnew array<SortPtr>(domain->Length);
for (int i = 0; i < domain->Length; ++i) dom[i] = domain[i]();
return gcnew FuncDecl(m_context->GetContext, m_theory->MkFuncDecl(n, dom, range()));
}
Sort^ MkSort(String^ s)
{
return gcnew Sort(m_context->GetContext,m_theory->MkSort(s));
}
Term^ MkValue(String^ s, Sort^ srt)
{
return MkTerm(m_theory->MkValue(s, srt()));
}
Term^ MkConstant(String^ s, Sort^ srt)
{
return MkTerm(m_theory->MkConstant(s, srt()));
}
FuncDecl^ MkFuncDecl(String^ n, array<Sort^>^ domain, Sort^ range)
{
return this->MkFuncDecl(m_context->MkSymbol(n), domain, range);
}
};
/*@}*/
};
};
#endif