3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-09 02:41:52 +00:00
z3/src/api/ml/z3.ml
Christoph M. Wintersteiger 371db347af More new ML API.
Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
2015-01-19 15:49:20 +00:00

5438 lines
187 KiB
OCaml

(**
The Z3 ML/Ocaml Interface.
Copyright (C) 2012 Microsoft Corporation
@author CM Wintersteiger (cwinter) 2012-12-17
*)
open Z3enums
(**/**)
class virtual idisposable =
object
method virtual dispose : unit
end
(** Context objects *)
class context settings =
object (self)
inherit idisposable
val mutable m_n_ctx : Z3native.z3_context =
let cfg = Z3native.mk_config in
let f e = (Z3native.set_param_value cfg (fst e) (snd e)) in
(List.iter f settings) ;
let v = Z3native.mk_context_rc cfg in
Z3native.del_config(cfg) ;
v
val mutable m_obj_cnt : int = 0
initializer
(* Printf.printf "Installing finalizer on context %d \n" (Oo.id self) ; *)
let f = fun o -> o#dispose in
let v = self in
Gc.finalise f v
method dispose : unit =
if m_obj_cnt == 0 then (
(* Printf.printf "Disposing context %d \n" (Oo.id self) ; *)
(Z3native.del_context m_n_ctx)
) else (
Printf.printf "NOT DISPOSING context %d because it still has %d objects alive\n" (Oo.id self) m_obj_cnt;
(* re-queue for finalization? *)
)
method add_one_ctx_obj = m_obj_cnt <- m_obj_cnt + 1
method sub_one_ctx_obj = m_obj_cnt <- m_obj_cnt - 1
method gno = m_n_ctx
end
(** Z3 objects *)
class virtual z3object ctx_init obj_init =
object (self)
inherit idisposable
val mutable m_ctx : context = ctx_init
val mutable m_n_obj : Z3native.ptr option = obj_init
initializer
(match m_n_obj with
| Some (x) -> self#incref m_ctx#gno x;
m_ctx#add_one_ctx_obj
| None -> ()
);
(* Printf.printf "Installing finalizer on z3object %d \n" (Oo.id self) ; *)
let f = fun o -> o#dispose in
let v = self in
Gc.finalise f v
method virtual incref : Z3native.ptr -> Z3native.ptr -> unit
method virtual decref : Z3native.ptr -> Z3native.ptr -> unit
method dispose =
(* Printf.printf "Disposing z3object %d \n" (Oo.id self) ; *)
(match m_n_obj with
| Some (x) ->
self#decref m_ctx#gno x;
m_ctx#sub_one_ctx_obj ;
m_n_obj <- None;
| None -> ()
);
method gno = match m_n_obj with
| Some(x) -> x
| None -> raise (Z3native.Exception "Z3 object lost")
method sno (ctx : context) o =
m_ctx#add_one_ctx_obj ;
self#incref ctx#gno o ;
(match m_n_obj with
| Some(x) -> self#decref ctx#gno x ; m_ctx#sub_one_ctx_obj
| None -> ()
);
m_n_obj <- Some o
method gc = m_ctx
method gnc = m_ctx#gno
end
(** Parameter set objects *)
class params ctx obj =
object (self)
inherit z3object ctx obj as super
method incref nc o = Z3native.params_inc_ref nc o
method decref nc o = Z3native.params_dec_ref nc o
end
(** Symbol objects *)
class symbol ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = ()
method decref nc o = ()
end
let symbolaton (a : symbol array) =
let f (e : symbol) = e#gno in
Array.map f a
(** Int symbol objects *)
class int_symbol ctx =
object(self)
inherit symbol ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_int i = (self#sno ctx (Z3native.mk_int_symbol ctx#gno i)) ; self
end
(** String symbol objects *)
class string_symbol ctx =
object(self)
inherit symbol ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_string name = (self#sno ctx (Z3native.mk_string_symbol ctx#gno name)) ; self
end
let create_symbol ctx no =
match (symbol_kind_of_int (Z3native.get_symbol_kind ctx#gno no)) with
| INT_SYMBOL -> (((new int_symbol ctx)#cnstr_obj no) :> symbol)
| STRING_SYMBOL -> (((new string_symbol ctx)#cnstr_obj no) :> symbol)
(** AST objects *)
class ast ctx =
object (self)
inherit z3object ctx None as super (* CMW: derive from icomparable? *)
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.inc_ref nc o
method decref nc o = Z3native.dec_ref nc o
end
let astaton (a : ast array) =
let f (e : ast) = e#gno in
Array.map f a
(** Sort objects *)
class sort ctx =
object (self)
inherit ast ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
let sortaton (a : sort array) =
let f (e : sort) = e#gno in
Array.map f a
(** Arithmetic sort objects, i.e., Int or Real. *)
class arith_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Array sorts objects *)
class array_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_dr (domain : sort) (range : sort) = (self#sno ctx (Z3native.mk_array_sort ctx#gno domain#gno range#gno)) ; self
end
(** Bit-vector sort objects *)
class bitvec_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Boolean sort objects *)
class bool_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Int sort objects *)
class int_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Real sort objects *)
class real_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Uninterpreted sort objects *)
class uninterpreted_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_s (s : symbol) = (self #sno ctx (Z3native.mk_uninterpreted_sort ctx#gno s#gno)) ; self
end
(** Finite domain sort objects *)
class finite_domain_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_si (s : symbol) ( sz : int )= (self #sno ctx (Z3native.mk_finite_domain_sort ctx#gno s#gno sz)) ; self
end
(** Relation sort objects *)
class relation_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Set sort objects *)
class set_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_s (s : sort) = (self#sno ctx s#gno) ; self
end
(** Tuple sort objects *)
class tuple_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_siss (name : symbol) (num_fields: int) (field_names : symbol array) (field_sorts : sort array) =
let (x,_,_) = (Z3native.mk_tuple_sort ctx#gno name#gno num_fields (symbolaton field_names) (astaton field_sorts)) in
(self#sno ctx x) ;
self
end
(** Function declaration objects *)
class func_decl ctx =
object (self)
inherit ast ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_ndr (name : symbol) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_func_decl ctx#gno name#gno (Array.length domain) (astaton domain) range#gno)) ; self
method cnstr_pdr (prefix : string) (domain : sort array) (range : sort) = (self#sno ctx (Z3native.mk_fresh_func_decl ctx#gno prefix (Array.length domain) (astaton domain) range#gno)) ; self
method incref nc o = super#incref nc o
method decref nc o = super#decref nc o
end
class parameter =
object (self)
val mutable m_kind : parameter_kind = PARAMETER_INT;
val mutable m_i : int = 0
val mutable m_d : float = 0.0
val mutable m_sym : symbol option = None
val mutable m_srt : sort option = None
val mutable m_ast : ast option = None
val mutable m_fd : func_decl option = None
val mutable m_r : string = ""
method cnstr_int i = m_kind <- PARAMETER_INT; m_i <- i
method cnstr_double d = m_kind <- PARAMETER_DOUBLE; m_d <- d
method cnstr_symbol sym = m_kind <- PARAMETER_SYMBOL; m_sym <- sym
method cnstr_sort srt = m_kind <- PARAMETER_SORT; m_srt <- srt
method cnstr_ast ast = m_kind <- PARAMETER_AST; m_ast <- ast
method cnstr_func_decl fd = m_kind <- PARAMETER_FUNC_DECL; m_fd <- fd
method cnstr_rational r = m_kind <- PARAMETER_RATIONAL; m_r <- r
method kind = m_kind
method int = m_i
method double = m_d
method symbol = match m_sym with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing parameter symbol")
method sort = match m_srt with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing parameter sort")
method ast = match m_ast with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing parameter ast")
method func_decl = match m_fd with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing parameter func_decl")
method rational = m_r
end
(** Enum sort objects *)
class enum_sort ctx =
object (self)
inherit sort ctx as super
val mutable _constdecls : func_decl array option = None
val mutable _testerdecls : func_decl array option = None
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_ss (name : symbol) (enum_names : symbol array) =
let (r, a, b) = (Z3native.mk_enumeration_sort ctx#gno name#gno (Array.length enum_names) (symbolaton enum_names)) in
_constdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f a)) ;
_testerdecls <- Some (let f e = (new func_decl ctx)#cnstr_obj e in (Array.map f b)) ;
(self#sno ctx r) ;
self
method const_decls = match _constdecls with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing const decls")
method tester_decls = match _testerdecls with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing tester decls")
end
(** List sort objects *)
class list_sort ctx =
object (self)
inherit sort ctx as super
val mutable _nildecl : func_decl option = None
val mutable _is_nildecl : func_decl option = None
val mutable _consdecl : func_decl option = None
val mutable _is_consdecl : func_decl option = None
val mutable _headdecl : func_decl option = None
val mutable _taildecl : func_decl option = None
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_ss (name : symbol) (elem_sort : sort) =
let (r, a, b, c, d, e, f) = (Z3native.mk_list_sort ctx#gno name#gno elem_sort#gno) in
_nildecl <- Some ((new func_decl ctx)#cnstr_obj a) ;
_is_nildecl <- Some ((new func_decl ctx)#cnstr_obj b) ;
_consdecl <- Some ((new func_decl ctx)#cnstr_obj c) ;
_is_consdecl <- Some ((new func_decl ctx)#cnstr_obj d) ;
_headdecl <- Some ((new func_decl ctx)#cnstr_obj e) ;
_taildecl <- Some ((new func_decl ctx)#cnstr_obj f) ;
(self#sno ctx r) ;
self
method nil_decl = match _nildecl with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing nil decl")
method is_nil_decl = match _is_nildecl with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing is_nil decl")
method cons_decl = match _consdecl with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing cons decl")
method is_cons_decl = match _is_consdecl with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing is_cons decl")
method head_decl = match _headdecl with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing head decl")
method tail_decl = match _taildecl with
| Some(x) -> x
| None -> raise (Z3native.Exception "Missing tail decl")
end
(** Constructor objects *)
class constructor ctx =
object (self)
inherit z3object ctx None as super
val mutable m_n : int = 0
val mutable m_tester_decl : func_decl option = None
val mutable m_constructor_decl : func_decl option = None
val mutable m_accessor_decls : func_decl array option = None
method incref nc o = ()
method decref nc o = ()
initializer
let f = fun o -> Z3native.del_constructor o#gnc o#gno in
let v = self in
Gc.finalise f v
method cnstr_ssssi (name : symbol) (recognizer : symbol) (field_names : symbol array) (sorts : sort array) (sort_refs : int array) =
m_n <- (Array.length field_names) ;
if m_n != (Array.length sorts) then
raise (Z3native.Exception "Number of field names does not match number of sorts")
else
if m_n != (Array.length sort_refs) then
raise (Z3native.Exception "Number of field names does not match number of sort refs")
else
let o = (Z3native.mk_constructor ctx#gno name#gno recognizer#gno m_n (symbolaton field_names)
(sortaton sorts)
sort_refs) in
self#sno ctx o ;
self
method private init =
match m_tester_decl with
| None ->
let (a, b, c) = (Z3native.query_constructor self#gnc self#gno m_n) in
m_constructor_decl <- Some ((new func_decl ctx)#cnstr_obj a) ;
m_tester_decl <- Some ((new func_decl ctx)#cnstr_obj b) ;
m_accessor_decls <- Some (let f e = ((new func_decl ctx)#cnstr_obj e) in Array.map f c) ;
()
| _ -> ()
method get_n = m_n
method tester_decl = match m_tester_decl with
| Some(x) -> x
| None -> self#init ; self#tester_decl
method constructor_decl = match m_constructor_decl with
| Some(x) -> x
| None -> self#init ; self#constructor_decl
method accessor_decls = match m_accessor_decls with
| Some(x) -> x
| None -> self#init ; self#accessor_decls
end
let constructoraton (a : constructor array) =
let f (e : constructor) = e#gno in
Array.map f a
(** Constructor list objects *)
class constructor_list ctx =
object (self)
inherit z3object ctx None
method incref nc o = ()
method decref nc o = ()
initializer
let f = fun o -> Z3native.del_constructor_list o#gnc o#gno in
let v = self in
Gc.finalise f v
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_ca ( c : constructor array ) =
self#sno ctx (Z3native.mk_constructor_list ctx#gno (Array.length c) (constructoraton c)) ;
self
end
let constructor_listaton (a : constructor_list array) =
let f (e : constructor_list) = e#gno in
Array.map f a
(** Datatype sort objects *)
class datatype_sort ctx =
object (self)
inherit sort ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method cnstr_sc (name : symbol) (constructors : constructor array) = (self#sno ctx (fst (Z3native.mk_datatype ctx#gno name#gno (Array.length constructors) (constructoraton constructors)))) ; self
end
let create_sort ctx obj =
match (sort_kind_of_int (Z3native.get_sort_kind ctx#gno obj)) with
| ARRAY_SORT -> (((new array_sort ctx)#cnstr_obj obj) :> sort)
| BOOL_SORT -> (((new bool_sort ctx)#cnstr_obj obj) :> sort)
| BV_SORT -> (((new bitvec_sort ctx)#cnstr_obj obj) :> sort)
| DATATYPE_SORT -> (((new datatype_sort ctx)#cnstr_obj obj) :> sort)
| INT_SORT -> (((new int_sort ctx)#cnstr_obj obj) :> sort)
| REAL_SORT -> (((new real_sort ctx)#cnstr_obj obj) :> sort)
| UNINTERPRETED_SORT -> (((new uninterpreted_sort ctx)#cnstr_obj obj) :> sort)
| FINITE_DOMAIN_SORT -> (((new finite_domain_sort ctx)#cnstr_obj obj) :> sort)
| RELATION_SORT -> (((new relation_sort ctx)#cnstr_obj obj) :> sort)
| UNKNOWN_SORT -> raise (Z3native.Exception "Unknown sort kind encountered")
(** AST vector objects *)
class ast_vector ctx =
object (self)
inherit z3object ctx None
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.ast_vector_inc_ref nc o
method decref nc o = Z3native.ast_vector_dec_ref nc o
end
(** AST map objects *)
class ast_map ctx =
object (self)
inherit z3object ctx None
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.ast_map_inc_ref nc o
method decref nc o = Z3native.ast_map_dec_ref nc o
end
(** Expression objects *)
class expr ctx =
object(self)
inherit ast ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
let expraton (a : expr array) =
let f (e : expr) = e#gno in
Array.map f a
(** Boolean expression objects *)
class bool_expr ctx =
object (self)
inherit expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Arithmetic expression objects (int/real) *)
class arith_expr ctx =
object (self)
inherit expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Int expression objects *)
class int_expr ctx =
object (self)
inherit arith_expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Real expression objects *)
class real_expr ctx =
object (self)
inherit arith_expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Bit-vector expression objects *)
class bitvec_expr ctx =
object (self)
inherit expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Array expression objects *)
class array_expr ctx =
object (self)
inherit expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Datatype expression objects *)
class datatype_expr ctx =
object (self)
inherit expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Integer numeral expression objects *)
class int_num ctx =
object (self)
inherit int_expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Rational numeral expression objects *)
class rat_num ctx =
object (self)
inherit real_expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Bit-vector numeral expression objects *)
class bitvec_num ctx =
object (self)
inherit bitvec_expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Algebraic numeral expression objects *)
class algebraic_num ctx =
object (self)
inherit arith_expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Quantifier objects *)
class quantifier ctx =
object (self)
inherit expr ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
(** Quantifier pattern objects *)
class pattern ctx =
object (self)
inherit ast ctx as super
method cnstr_obj obj = (self#sno ctx obj) ; self
end
let patternaton (a : pattern array) =
let f (e : pattern) = e#gno in
Array.map f a
(** Parameter description objects *)
class param_descrs ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.param_descrs_inc_ref nc o
method decref nc o = Z3native.param_descrs_dec_ref nc o
end
(** Goal objects *)
class goal ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.goal_inc_ref nc o
method decref nc o = Z3native.goal_dec_ref nc o
end
(** Tactic objects *)
class tactic ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.tactic_inc_ref nc o
method decref nc o = Z3native.tactic_dec_ref nc o
end
(** Function interpretation entry objects *)
class func_entry ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.func_entry_inc_ref nc o
method decref nc o = Z3native.func_entry_dec_ref nc o
end
(** Function interpretation objects *)
class func_interp ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.func_interp_inc_ref nc o
method decref nc o = Z3native.func_interp_dec_ref nc o
end
(** Model objects *)
class model ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.model_inc_ref nc o
method decref nc o = Z3native.model_dec_ref nc o
end
(** Tactic application result objects *)
class apply_result ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.apply_result_inc_ref nc o
method decref nc o = Z3native.apply_result_dec_ref nc o
end
(** Probe objects *)
class probe ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.probe_inc_ref nc o
method decref nc o = Z3native.probe_dec_ref nc o
end
(** Statistical value objects *)
class statistics_entry =
object (self)
val mutable m_key : string = ""
val mutable m_is_int = false
val mutable m_is_float = false
val mutable m_int = 0
val mutable m_float = 0.0
method cnstr_si k v =
m_key <- k;
m_is_int <- true;
m_int <- v;
self
method cnstr_sd k v =
m_key <- k;
m_is_float <- true;
m_float <- v;
self
method key = m_key
method int = m_int
method float = m_float
method is_int = m_is_int
method is_float = m_is_float
end
(** Statistics objects *)
class statistics ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.stats_inc_ref nc o
method decref nc o = Z3native.stats_dec_ref nc o
end
(** Solver objects *)
class solver ctx =
object (self)
inherit z3object ctx None as super
method cnstr_obj obj = (self#sno ctx obj) ; self
method incref nc o = Z3native.solver_inc_ref nc o
method decref nc o = Z3native.solver_dec_ref nc o
end
(**/**)
(** Interaction logging for Z3
Note that this is a global, static log and if multiple Context
objects are created, it logs the interaction with all of them. *)
module Log =
struct
(** Open an interaction log file.
@param filename the name of the file to open.
@return True if opening the log file succeeds, false otherwise.
*)
(* CMW: "open" seems to be a reserved keyword? *)
let open_ filename = ((lbool_of_int (Z3native.open_log filename)) == L_TRUE)
(** Closes the interaction log. *)
let close = Z3native.close_log
(** Appends a user-provided string to the interaction log.
@param s the string to append*)
let append s = Z3native.append_log s
end
(** Version information *)
module Version =
struct
(** The major version. *)
let major = let (x, _, _, _) = Z3native.get_version in x
(** The minor version. *)
let minor = let (_, x, _, _) = Z3native.get_version in x
(** The build version. *)
let build = let (_, _, x, _) = Z3native.get_version in x
(** The revision. *)
let revision = let (_, _, _, x) = Z3native.get_version in x
(** A string representation of the version information. *)
let to_string =
let (mj, mn, bld, rev) = Z3native.get_version in
string_of_int mj ^ "." ^
string_of_int mn ^ "." ^
string_of_int bld ^ "." ^
string_of_int rev ^ "."
end
(** Symbols are used to name several term and type constructors *)
module Symbol =
struct
(** The kind of the symbol (int or string) *)
let kind (o : symbol) = (symbol_kind_of_int (Z3native.get_symbol_kind o#gnc o#gno))
(** Indicates whether the symbol is of Int kind *)
let is_int_symbol (o : symbol) = (kind o) == INT_SYMBOL
(** Indicates whether the symbol is of string kind. *)
let is_string_symbol (o : symbol) = (kind o) == STRING_SYMBOL
(** The int value of the symbol. *)
let get_int (o : int_symbol) = Z3native.get_symbol_int o#gnc o#gno
(** The string value of the symbol. *)
let get_string (o : string_symbol) = Z3native.get_symbol_string o#gnc o#gno
(** A string representation of the symbol. *)
let to_string (o : symbol) =
match (kind o) with
| INT_SYMBOL -> (string_of_int (Z3native.get_symbol_int o#gnc o#gno))
| STRING_SYMBOL -> (Z3native.get_symbol_string o#gnc o#gno)
(**
Creates a new symbol using an integer.
Not all integers can be passed to this function.
The legal range of unsigned integers is 0 to 2^30-1.
*)
let mk_int ( ctx : context ) i =
(new int_symbol ctx)#cnstr_int i
(** Creates a new symbol using a string. *)
let mk_string ( ctx : context ) s =
(new string_symbol ctx)#cnstr_string s
(**
Create an array of symbols.
*)
let mk_ints ( ctx : context ) ( names : int array ) =
let f elem = mk_int ( ctx : context ) elem in
(Array.map f names)
(**
Create an array of symbols.
*)
let mk_strings ( ctx : context ) ( names : string array ) =
let f elem = mk_string ( ctx : context ) elem in
(Array.map f names)
end
(** The Sort module implements type information for ASTs *)
module Sort =
struct
(**
Comparison operator.
@param a A sort
@param b A sort
@return True if <paramref name="a"/> and <paramref name="b"/> are from the same context
and represent the same sort; false otherwise.
*)
let ( = ) (a : sort) (b : sort) = (a == b) ||
if a#gnc != b#gnc then
false
else
((lbool_of_int (Z3native.is_eq_sort a#gnc a#gno b#gno)) == L_TRUE)
(**
Returns a unique identifier for the sort.
*)
let get_id (x : sort) = Z3native.get_sort_id x#gnc x#gno
(**
The kind of the sort.
*)
let get_sort_kind (x : sort) = (sort_kind_of_int (Z3native.get_sort_kind x#gnc x#gno))
(**
The name of the sort
*)
let get_name (x : sort) = (create_symbol x#gc (Z3native.get_sort_name x#gnc x#gno))
(**
A string representation of the sort.
*)
let to_string (x : sort) = Z3native.sort_to_string x#gnc x#gno
(**
Create a new Boolean sort.
*)
let mk_bool ( ctx : context ) =
(new bool_sort ctx)#cnstr_obj (Z3native.mk_bool_sort ctx#gno)
(**
Create a new uninterpreted sort.
*)
let mk_uninterpreted ( ctx : context ) (s : symbol) =
(new uninterpreted_sort ctx)#cnstr_s s
(**
Create a new uninterpreted sort.
*)
let mk_uninterpreted_s ( ctx : context ) (s : string) =
mk_uninterpreted ctx ((Symbol.mk_string ( ctx : context ) s) :> symbol)
end
(**/**)
let create_expr ctx obj =
if ast_kind_of_int (Z3native.get_ast_kind ctx#gno obj) == QUANTIFIER_AST then
(((new quantifier ctx)#cnstr_obj obj) :> expr)
else
let s = Z3native.get_sort ctx#gno obj in
let sk = (sort_kind_of_int (Z3native.get_sort_kind ctx#gno s)) in
if (lbool_of_int (Z3native.is_algebraic_number ctx#gno obj) == L_TRUE) then
(((new algebraic_num ctx)#cnstr_obj obj) :> expr)
else
if ((lbool_of_int (Z3native.is_numeral_ast ctx#gno obj)) == L_TRUE) &&
(sk == INT_SORT or sk == REAL_SORT or sk == BV_SORT) then
match sk with
| INT_SORT -> (((new int_num ctx)#cnstr_obj obj) :> expr)
| REAL_SORT -> (((new rat_num ctx)#cnstr_obj obj) :> expr)
| BV_SORT -> (((new bitvec_num ctx)#cnstr_obj obj) :> expr)
| _ -> raise (Z3native.Exception "Unsupported numeral object")
else
match sk with
| BOOL_SORT -> (((new bool_expr ctx)#cnstr_obj obj) :> expr)
| INT_SORT -> (((new int_expr ctx)#cnstr_obj obj) :> expr)
| REAL_SORT -> (((new real_expr ctx)#cnstr_obj obj) :> expr)
| BV_SORT -> (((new bitvec_expr ctx)#cnstr_obj obj) :> expr)
| ARRAY_SORT -> (((new array_expr ctx)#cnstr_obj obj) :> expr)
| DATATYPE_SORT -> (((new datatype_expr ctx)#cnstr_obj obj) :> expr)
| _ -> (new expr ctx)#cnstr_obj obj
let create_expr_fa (ctx : context) (f : func_decl) (args : expr array) =
let o = Z3native.mk_app ctx#gno f#gno (Array.length args) (astaton args) in
create_expr ctx o
let create_ast ctx no =
match (ast_kind_of_int (Z3native.get_ast_kind ctx#gno no)) with
| FUNC_DECL_AST -> (((new func_decl ctx)#cnstr_obj no) :> ast)
| QUANTIFIER_AST -> (((new quantifier ctx)#cnstr_obj no) :> ast)
| SORT_AST -> ((create_sort ctx no) :> ast)
| APP_AST
| NUMERAL_AST
| VAR_AST -> ((create_expr ctx no) :> ast)
| UNKNOWN_AST -> raise (Z3native.Exception "Cannot create asts of type unknown")
(**/**)
(** Function declarations *)
module FuncDecl =
struct
(** Parameters of Func_Decls *)
module Parameter =
struct
(**
The kind of the parameter.
*)
let get_kind (x : parameter) = x#kind
(**The int value of the parameter.*)
let get_int (x : parameter) =
if (x#kind != PARAMETER_INT) then
raise (Z3native.Exception "parameter is not an int")
else
x#int
(**The double value of the parameter.*)
let get_double (x : parameter) =
if (x#kind != PARAMETER_DOUBLE) then
raise (Z3native.Exception "parameter is not a double")
else
x#double
(**The Symbol value of the parameter.*)
let get_symbol (x : parameter) =
if (x#kind != PARAMETER_SYMBOL) then
raise (Z3native.Exception "parameter is not a symbol")
else
x#symbol
(**The Sort value of the parameter.*)
let get_sort (x : parameter) =
if (x#kind != PARAMETER_SORT) then
raise (Z3native.Exception "parameter is not a sort")
else
x#sort
(**The AST value of the parameter.*)
let get_ast (x : parameter) =
if (x#kind != PARAMETER_AST) then
raise (Z3native.Exception "parameter is not an ast")
else
x#ast
(**The FunctionDeclaration value of the parameter.*)
let get_ast (x : parameter) =
if (x#kind != PARAMETER_FUNC_DECL) then
raise (Z3native.Exception "parameter is not an function declaration")
else
x#func_decl
(**The rational string value of the parameter.*)
let get_rational (x : parameter) =
if (x#kind != PARAMETER_RATIONAL) then
raise (Z3native.Exception "parameter is not a ratinoal string")
else
x#rational
(**
Creates a new function declaration.
*)
let mk_func_decl ( ctx : context ) ( name : symbol ) ( domain : sort array ) ( range : sort) =
(new func_decl ctx)#cnstr_ndr name domain range
(**
Creates a new function declaration.
*)
let mk_func_decl_s ( ctx : context ) ( name : string ) ( domain : sort array ) ( range : sort) =
mk_func_decl ctx ((Symbol.mk_string ctx name) :> symbol) domain range
(**
Creates a fresh function declaration with a name prefixed with <paramref name="prefix"/>.
<seealso cref="MkFunc_Decl(string,Sort,Sort)"/>
<seealso cref="MkFunc_Decl(string,Sort[],Sort)"/>
*)
let mk_fresh_func_decl ( ctx : context ) ( prefix : string ) ( domain : sort array ) ( range : sort) =
(new func_decl ctx)#cnstr_pdr prefix domain range
(**
Creates a new constant function declaration.
*)
let mk_const_decl ( ctx : context ) ( name : symbol ) ( range : sort) =
(new func_decl ctx)#cnstr_ndr name [||] range
(**
Creates a new constant function declaration.
*)
let mk_const_decl_s ( ctx : context ) ( name : string ) ( range : sort) =
(new func_decl ctx)#cnstr_ndr ((Symbol.mk_string ctx name) :> symbol) [||] range
(**
Creates a fresh constant function declaration with a name prefixed with <paramref name="prefix"/>.
<seealso cref="MkFunc_Decl(string,Sort,Sort)"/>
<seealso cref="MkFunc_Decl(string,Sort[],Sort)"/>
*)
let mk_fresh_const_decl ( ctx : context ) ( prefix : string ) ( range : sort) =
(new func_decl ctx)#cnstr_pdr prefix [||] range
end
(**
Comparison operator.
@param a A func_decl
@param b A func_decl
@return True if <paramref name="a"/> and <paramref name="b"/> are from the same context
and represent the same func_decl; false otherwise.
*)
let ( = ) (a : func_decl) (b : func_decl) = (a == b) ||
if a#gnc == a#gnc then
false
else
((lbool_of_int (Z3native.is_eq_func_decl a#gnc a#gno b#gno)) == L_TRUE)
(**
A string representations of the function declaration.
*)
let to_string (x : func_decl) = Z3native.func_decl_to_string x#gnc x#gno
(**
Returns a unique identifier for the function declaration.
*)
let get_id (x : func_decl) = Z3native.get_func_decl_id x#gnc x#gno
(**
The arity of the function declaration
*)
let get_arity (x : func_decl) = Z3native.get_arity x#gnc x#gno
(**
The size of the domain of the function declaration
<seealso cref="Arity"/>
*)
let get_domain_size (x : func_decl) = Z3native.get_domain_size x#gnc x#gno
(**
The domain of the function declaration
*)
let get_domain (x : func_decl) =
let n = (get_domain_size x) in
let f i = create_sort x#gc (Z3native.get_domain x#gnc x#gno i) in
Array.init n f
(**
The range of the function declaration
*)
let get_range (x : func_decl) =
create_sort x#gc (Z3native.get_range x#gnc x#gno)
(**
The kind of the function declaration.
*)
let get_decl_kind (x : func_decl) = (decl_kind_of_int (Z3native.get_decl_kind x#gnc x#gno))
(**
The name of the function declaration
*)
let get_name (x : func_decl) = (create_symbol x#gc (Z3native.get_decl_name x#gnc x#gno))
(**
The number of parameters of the function declaration
*)
let get_num_parameters (x : func_decl) = (Z3native.get_decl_num_parameters x#gnc x#gno)
(**
The parameters of the function declaration
*)
let get_parameters (x : func_decl) =
let n = (get_num_parameters x) in
let f i = (
match (parameter_kind_of_int (Z3native.get_decl_parameter_kind x#gnc x#gno i)) with
| PARAMETER_INT -> (new parameter)#cnstr_int (Z3native.get_decl_int_parameter x#gnc x#gno i)
| PARAMETER_DOUBLE -> (new parameter)#cnstr_double (Z3native.get_decl_double_parameter x#gnc x#gno i)
| PARAMETER_SYMBOL-> (new parameter)#cnstr_symbol (Some (create_symbol x#gc (Z3native.get_decl_symbol_parameter x#gnc x#gno i)))
| PARAMETER_SORT -> (new parameter)#cnstr_sort (Some (create_sort x#gc (Z3native.get_decl_sort_parameter x#gnc x#gno i)))
| PARAMETER_AST -> (new parameter)#cnstr_ast (Some (create_ast x#gc (Z3native.get_decl_ast_parameter x#gnc x#gno i)))
| PARAMETER_FUNC_DECL -> (new parameter)#cnstr_func_decl (Some ((new func_decl x#gc)#cnstr_obj (Z3native.get_decl_func_decl_parameter x#gnc x#gno i)))
| PARAMETER_RATIONAL -> (new parameter)#cnstr_rational (Z3native.get_decl_rational_parameter x#gnc x#gno i)
) in
Array.init n f
(**
Create expression that applies function to arguments.
@param args The arguments
*)
let apply (x : func_decl) (args : expr array) = create_expr_fa x#gc x args
end
(** The abstract syntax tree (AST) module *)
module AST =
struct
(** Vectors of ASTs *)
module ASTVector =
struct
(** The size of the vector *)
let get_size ( x : ast_vector ) =
Z3native.ast_vector_size x#gnc x#gno
(**
Retrieves the i-th object in the vector.
@param i Index
@return An AST
*)
let get ( x : ast_vector ) ( i : int ) =
create_ast x#gc (Z3native.ast_vector_get x#gnc x#gno i)
(** Sets the i-th object in the vector. *)
let set ( x : ast_vector ) ( i : int ) ( value : ast ) =
Z3native.ast_vector_set x#gnc x#gno i value#gno
(** Resize the vector to <paramref name="newSize"/>.
@param newSize The new size of the vector. *)
let resize ( x : ast_vector ) ( new_size : int ) =
Z3native.ast_vector_resize x#gnc x#gno new_size
(**
Add the AST <paramref name="a"/> to the back of the vector. The size
is increased by 1.
@param a An AST
*)
let push ( x : ast_vector ) ( a : ast ) =
Z3native.ast_vector_push x#gnc x#gno a#gno
(**
Translates all ASTs in the vector to <paramref name="to_ctx"/>.
@param to_ctx A context
@return A new ASTVector
*)
let translate ( x : ast_vector ) ( to_ctx : context ) =
(new ast_vector to_ctx)#cnstr_obj (Z3native.ast_vector_translate x#gnc x#gno to_ctx#gno)
(** Retrieves a string representation of the vector. *)
let to_string ( x : ast_vector ) =
Z3native.ast_vector_to_string x#gnc x#gno
end
(** Map from AST to AST *)
module ASTMap =
struct
(** Checks whether the map contains the key <paramref name="k"/>.
@param k An AST
@return True if <paramref name="k"/> is a key in the map, false otherwise. *)
let contains ( m : ast_map ) ( key : ast ) =
(lbool_of_int (Z3native.ast_map_contains m#gnc m#gno key#gno)) == L_TRUE
(** Finds the value associated with the key <paramref name="k"/>.
<remarks>
This function signs an error when <paramref name="k"/> is not a key in the map.
@param k An AST
*)
let find ( m : ast_map ) ( key : ast ) =
create_ast m#gc (Z3native.ast_map_find m#gnc m#gno key#gno)
(**
Stores or replaces a new key/value pair in the map.
@param k The key AST
@param v The value AST
*)
let insert ( m : ast_map ) ( key : ast ) ( value : ast) =
Z3native.ast_map_insert m#gnc m#gno key#gno value#gno
(**
Erases the key <paramref name="k"/> from the map.
@param k An AST
*)
let erase ( m : ast_map ) ( key : ast ) =
Z3native.ast_map_erase m#gnc m#gno key#gno
(** Removes all keys from the map. *)
let reset ( m : ast_map ) =
Z3native.ast_map_reset m#gnc m#gno
(** The size of the map *)
let get_size ( m : ast_map ) =
Z3native.ast_map_size m#gnc m#gno
(** The keys stored in the map. *)
let get_keys ( m : ast_map ) =
(new ast_vector m#gc)#cnstr_obj (Z3native.ast_map_keys m#gnc m#gno)
(** Retrieves a string representation of the map.*)
let to_strnig ( m : ast_map ) =
Z3native.ast_map_to_string m#gnc m#gno
end
(**
The AST's hash code.
@return A hash code
*)
let get_hash_code ( x : ast) = Z3native.get_ast_hash x#gnc x#gno
(**
A unique identifier for the AST (unique among all ASTs).
*)
let get_id ( x : ast) = Z3native.get_ast_id x#gnc x#gno
(**
The kind of the AST.
*)
let get_ast_kind ( x : ast) = (ast_kind_of_int (Z3native.get_ast_kind x#gnc x#gno))
(**
Indicates whether the AST is an Expr
*)
let is_expr ( x : ast) =
match get_ast_kind ( x : ast) with
| APP_AST
| NUMERAL_AST
| QUANTIFIER_AST
| VAR_AST -> true
| _ -> false
(**
Indicates whether the AST is a bound variable
*)
let is_var ( x : ast) = (get_ast_kind x) == VAR_AST
(**
Indicates whether the AST is a Quantifier
*)
let is_quantifier ( x : ast) = (get_ast_kind x) == QUANTIFIER_AST
(**
Indicates whether the AST is a Sort
*)
let is_sort ( x : ast) = (get_ast_kind x) == SORT_AST
(**
Indicates whether the AST is a FunctionDeclaration
*)
let is_func_decl ( x : ast) = (get_ast_kind x) == FUNC_DECL_AST
(**
A string representation of the AST.
*)
let to_string ( x : ast) = Z3native.ast_to_string x#gnc x#gno
(**
A string representation of the AST in s-expression notation.
*)
let to_sexpr ( x : ast) = Z3native.ast_to_string x#gnc x#gno
(**
Comparison operator.
@param a An AST
@param b An AST
@return True if <paramref name="a"/> and <paramref name="b"/> are from the same context
and represent the same sort; false otherwise.
*)
let ( = ) (a : expr) (b : expr) = (a == b) ||
if a#gnc == b#gnc then
false
else
((lbool_of_int (Z3native.is_eq_ast a#gnc a#gno b#gno)) == L_TRUE)
(**
Object Comparison.
@param other Another ast
@return Negative if the object should be sorted before <paramref name="other"/>, positive if after else zero.
*)
let compare a b =
if (get_id a) < (get_id b) then -1 else
if (get_id a) > (get_id b) then 1 else
0
(** Operator < *)
let ( < ) (a : ast) (b : ast) = (compare a b)
(**
Translates (copies) the AST to the Context <paramref name="ctx"/>.
@param ctx A context
@return A copy of the AST which is associated with <paramref name="ctx"/>
*)
let translate ( x : ast) to_ctx =
if x#gc == to_ctx then
x
else
(create_ast to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno))
end
(** General expressions (terms), including Boolean logic *)
module Expr =
struct
(**
Returns a simplified version of the expression.
@param p A set of parameters to configure the simplifier
<seealso cref="Context.SimplifyHelp"/>
*)
let simplify ( x : expr ) ( p : params option ) = match p with
| None -> create_expr x#gc (Z3native.simplify x#gnc x#gno)
| Some pp -> create_expr x#gc (Z3native.simplify_ex x#gnc x#gno pp#gno)
(**
The function declaration of the function that is applied in this expression.
*)
let get_func_decl ( x : expr ) = (new func_decl x#gc)#cnstr_obj (Z3native.get_app_decl x#gnc x#gno)
(**
Indicates whether the expression is the true or false expression
or something else (L_UNDEF).
*)
let get_bool_value ( x : expr ) = lbool_of_int (Z3native.get_bool_value x#gnc x#gno)
(**
The number of arguments of the expression.
*)
let get_num_args ( x : expr ) = Z3native.get_app_num_args x#gnc x#gno
(**
The arguments of the expression.
*)
let get_args ( x : expr ) = let n = (get_num_args x) in
let f i = create_expr x#gc (Z3native.get_app_arg x#gnc x#gno i) in
Array.init n f
(**
Update the arguments of the expression using the arguments <paramref name="args"/>
The number of new arguments should coincide with the current number of arguments.
*)
let update ( x : expr ) args =
if (Array.length args <> (get_num_args x)) then
raise (Z3native.Exception "Number of arguments does not match")
else
x#sno x#gc (Z3native.update_term x#gnc x#gno (Array.length args) (expraton args))
(**
Substitute every occurrence of <c>from[i]</c> in the expression with <c>to[i]</c>, for <c>i</c> smaller than <c>num_exprs</c>.
<remarks>
The result is the new expression. The arrays <c>from</c> and <c>to</c> must have size <c>num_exprs</c>.
For every <c>i</c> smaller than <c>num_exprs</c>, we must have that
sort of <c>from[i]</c> must be equal to sort of <c>to[i]</c>.
*)
let substitute ( x : expr ) from to_ =
if (Array.length from) <> (Array.length to_) then
raise (Z3native.Exception "Argument sizes do not match")
else
create_expr x#gc (Z3native.substitute x#gnc x#gno (Array.length from) (expraton from) (expraton to_))
(**
Substitute every occurrence of <c>from</c> in the expression with <c>to</c>.
<seealso cref="Substitute(Expr[],Expr[])"/>
*)
let substitute_one ( x : expr ) from to_ =
substitute ( x : expr ) [| from |] [| to_ |]
(**
Substitute the free variables in the expression with the expressions in <paramref name="to"/>
<remarks>
For every <c>i</c> smaller than <c>num_exprs</c>, the variable with de-Bruijn index <c>i</c> is replaced with term <c>to[i]</c>.
*)
let substitute_vars ( x : expr ) to_ =
create_expr x#gc (Z3native.substitute_vars x#gnc x#gno (Array.length to_) (expraton to_))
(**
Translates (copies) the term to the Context <paramref name="ctx"/>.
@param ctx A context
@return A copy of the term which is associated with <paramref name="ctx"/>
*)
let translate ( x : expr ) to_ctx =
if x#gc == to_ctx then
x
else
create_expr to_ctx (Z3native.translate x#gnc x#gno to_ctx#gno)
(**
Returns a string representation of the expression.
*)
let to_string ( x : expr ) = Z3native.ast_to_string x#gnc x#gno
(**
Indicates whether the term is a numeral
*)
let is_numeral ( x : expr ) = lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno) == L_TRUE
(**
Indicates whether the term is well-sorted.
@return True if the term is well-sorted, false otherwise.
*)
let is_well_sorted ( x : expr ) = lbool_of_int (Z3native.is_well_sorted x#gnc x#gno) == L_TRUE
(**
The Sort of the term.
*)
let get_sort ( x : expr ) = create_sort x#gc (Z3native.get_sort x#gnc x#gno)
(**
Indicates whether the term has Boolean sort.
*)
let is_bool ( x : expr ) = (AST.is_expr x) &&
(lbool_of_int (Z3native.is_eq_sort x#gnc
(Z3native.mk_bool_sort x#gnc)
(Z3native.get_sort x#gnc x#gno))) == L_TRUE
(**
Indicates whether the term represents a constant.
*)
let is_const ( x : expr ) = (AST.is_expr x) &&
(get_num_args x) == 0 &&
FuncDecl.get_domain_size(get_func_decl x) == 0
(**
Indicates whether the term is the constant true.
*)
let is_true ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_TRUE)
(**
Indicates whether the term is the constant false.
*)
let is_false ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_FALSE)
(**
Indicates whether the term is an equality predicate.
*)
let is_eq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_EQ)
(**
Indicates whether the term is an n-ary distinct predicate (every argument is mutually distinct).
*)
let is_distinct ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_DISTINCT)
(**
Indicates whether the term is a ternary if-then-else term
*)
let is_ite ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_ITE)
(**
Indicates whether the term is an n-ary conjunction
*)
let is_and ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_AND)
(**
Indicates whether the term is an n-ary disjunction
*)
let is_or ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OR)
(**
Indicates whether the term is an if-and-only-if (Boolean equivalence, binary)
*)
let is_iff ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IFF)
(**
Indicates whether the term is an exclusive or
*)
let is_xor ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_XOR)
(**
Indicates whether the term is a negation
*)
let is_not ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_NOT)
(**
Indicates whether the term is an implication
*)
let is_implies ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_IMPLIES)
(**
Indicates whether the term is a label (used by the Boogie Verification condition generator).
<remarks>The label has two parameters, a string and a Boolean polarity. It takes one argument, a formula.
*)
let is_label ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL)
(**
Indicates whether the term is a label literal (used by the Boogie Verification condition generator).
<remarks>A label literal has a set of string parameters. It takes no arguments.
let is_label_lit ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_LABEL_LIT)
*)
(**
Indicates whether the term is a binary equivalence modulo namings.
<remarks>This binary predicate is used in proof terms.
It captures equisatisfiability and equivalence modulo renamings.
*)
let is_oeq ( x : expr ) = (FuncDecl.get_decl_kind (get_func_decl x) == OP_OEQ)
(**
Creates a new Constant of sort <paramref name="range"/> and named <paramref name="name"/>.
*)
let mk_const ( ctx : context ) ( name : symbol ) ( range : sort ) =
create_expr ctx (Z3native.mk_const ctx#gno name#gno range#gno)
(**
Creates a new Constant of sort <paramref name="range"/> and named <paramref name="name"/>.
*)
let mk_const_s ( ctx : context ) ( name : string ) ( range : sort ) =
mk_const ctx ((Symbol.mk_string ctx name) :> symbol) range
(**
Creates a constant from the func_decl <paramref name="f"/>.
@param f An expression of a 0-arity function
*)
let mk_const_f ( ctx : context ) ( f : func_decl ) =
create_expr_fa ctx f [||]
(**
Creates a fresh constant of sort <paramref name="range"/> and a
name prefixed with <paramref name="prefix"/>.
*)
let mk_fresh_const ( ctx : context ) ( prefix : string ) ( range : sort) =
create_expr ctx (Z3native.mk_fresh_const ctx#gno prefix range#gno)
(**
Create a Boolean constant.
*)
let mk_bool_const ( ctx : context ) ( name : symbol ) =
((mk_const ctx name (Sort.mk_bool ctx)) :> bool_expr)
(**
Create a Boolean constant.
*)
let mk_bool_const_s ( ctx : context ) ( name : string ) =
mk_bool_const ctx ((Symbol.mk_string ctx name) :> symbol)
(**
Create a new function application.
*)
let mk_app ( ctx : context ) ( f : func_decl ) ( args : expr array ) =
create_expr_fa ctx f args
(**
The true Term.
*)
let mk_true ( ctx : context ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_true ctx#gno)
(**
The false Term.
*)
let mk_false ( ctx : context ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_false ctx#gno)
(**
Creates a Boolean value.
*)
let mk_bool ( ctx : context ) ( value : bool) =
if value then mk_true ctx else mk_false ctx
(**
Creates the equality <paramref name="x"/> = <paramref name="y"/>.
*)
let mk_eq ( ctx : context ) ( x : expr ) ( y : expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_eq ctx#gno x#gno y#gno)
(**
Creates a <c>distinct</c> term.
*)
let mk_distinct ( ctx : context ) ( args : expr array ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_distinct ctx#gno (Array.length args) (astaton args))
(**
Mk an expression representing <c>not(a)</c>.
*)
let mk_not ( ctx : context ) ( a : bool_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_not ctx#gno a#gno)
(**
Create an expression representing an if-then-else: <c>ite(t1, t2, t3)</c>.
@param t1 An expression with Boolean sort
@param t2 An expression
@param t3 An expression with the same sort as <paramref name="t2"/>
*)
let mk_ite ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) ( t3 : bool_expr ) =
create_expr ctx (Z3native.mk_ite ctx#gno t1#gno t2#gno t3#gno)
(**
Create an expression representing <c>t1 iff t2</c>.
*)
let mk_iff ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_iff ctx#gno t1#gno t2#gno)
(**
Create an expression representing <c>t1 -> t2</c>.
*)
let mk_implies ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_implies ctx#gno t1#gno t2#gno)
(**
Create an expression representing <c>t1 xor t2</c>.
*)
let mk_xor ( ctx : context ) ( t1 : bool_expr ) ( t2 : bool_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_xor ctx#gno t1#gno t2#gno)
(**
Create an expression representing the AND of args
*)
let mk_and ( ctx : context ) ( args : bool_expr array ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_and ctx#gno (Array.length args) (astaton args))
(**
Create an expression representing the OR of args
*)
let mk_or ( ctx : context ) ( args : bool_expr array ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_or ctx#gno (Array.length args) (astaton args))
(**
Create a numeral of a given sort.
@param v A string representing the Term value in decimal notation. If the given sort is a real, then the Term can be a rational, that is, a string of the form <c>[num]* / [num]*</c>.
@param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, or bit-vectors of arbitrary size.
@return A Term with value <paramref name="v"/> and sort <paramref name="ty"/>
*)
let mk_numeral_string ( ctx : context ) ( v : string ) ( ty : sort ) =
create_expr ctx (Z3native.mk_numeral ctx#gno v ty#gno)
(**
Create a numeral of a given sort. This function can be use to create numerals that fit in a machine integer.
It is slightly faster than <c>MakeNumeral</c> since it is not necessary to parse a string.
@param v Value of the numeral
@param ty Sort of the numeral
@return A Term with value <paramref name="v"/> and type <paramref name="ty"/>
*)
let mk_numeral_int ( ctx : context ) ( v : int ) ( ty : sort ) =
create_expr ctx (Z3native.mk_int ctx#gno v ty#gno)
end
(** Quantifier expressions *)
module Quantifiers =
struct
(**
The de-Burijn index of a bound variable.
<remarks>
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.
<code>
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))
</code>
The last line is significant: the index of a bound variable is different depending
on the scope in which it appears. The deeper ( x : expr ) appears, the higher is its
index.
*)
let get_index ( x : expr ) =
if not (AST.is_var x) then
raise (Z3native.Exception "Term is not a bound variable.")
else
Z3native.get_index_value x#gnc x#gno
(** Quantifier patterns
Patterns comprise a list of terms. The list should be
non-empty. If the list comprises of more than one term, it is
also called a multi-pattern.
*)
module Pattern =
struct
(**
The number of terms in the pattern.
*)
let get_num_terms ( x : pattern ) =
Z3native.get_pattern_num_terms x#gnc x#gno
(**
The terms in the pattern.
*)
let get_terms ( x : pattern ) =
let n = (get_num_terms x) in
let f i = (create_expr x#gc (Z3native.get_pattern x#gnc x#gno i)) in
Array.init n f
(**
A string representation of the pattern.
*)
let to_string ( x : pattern ) = Z3native.pattern_to_string x#gnc x#gno
end
(**
Indicates whether the quantifier is universal.
*)
let is_universal ( x : quantifier ) =
lbool_of_int (Z3native.is_quantifier_forall x#gnc x#gno) == L_TRUE
(**
Indicates whether the quantifier is existential.
*)
let is_existential ( x : quantifier ) = not (is_universal x)
(**
The weight of the quantifier.
*)
let get_weight ( x : quantifier ) = Z3native.get_quantifier_weight x#gnc x#gno
(**
The number of patterns.
*)
let get_num_patterns ( x : quantifier ) = Z3native.get_quantifier_num_patterns x#gnc x#gno
(**
The patterns.
*)
let get_patterns ( x : quantifier ) =
let n = (get_num_patterns x) in
let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_pattern_ast x#gnc x#gno i)) in
Array.init n f
(**
The number of no-patterns.
*)
let get_num_no_patterns ( x : quantifier ) = Z3native.get_quantifier_num_no_patterns x#gnc x#gno
(**
The no-patterns.
*)
let get_no_patterns ( x : quantifier ) =
let n = (get_num_patterns x) in
let f i = ((new pattern x#gc)#cnstr_obj (Z3native.get_quantifier_no_pattern_ast x#gnc x#gno i)) in
Array.init n f
(**
The number of bound variables.
*)
let get_num_bound ( x : quantifier ) = Z3native.get_quantifier_num_bound x#gnc x#gno
(**
The symbols for the bound variables.
*)
let get_bound_variable_names ( x : quantifier ) =
let n = (get_num_bound x) in
let f i = (create_symbol x#gc (Z3native.get_quantifier_bound_name x#gnc x#gno i)) in
Array.init n f
(**
The sorts of the bound variables.
*)
let get_bound_variable_sorts ( x : quantifier ) =
let n = (get_num_bound x) in
let f i = (create_sort x#gc (Z3native.get_quantifier_bound_sort x#gnc x#gno i)) in
Array.init n f
(**
The body of the quantifier.
*)
let get_body ( x : quantifier ) =
(new bool_expr x#gc)#cnstr_obj (Z3native.get_quantifier_body x#gnc x#gno)
(**
Creates a new bound variable.
@param index The de-Bruijn index of the variable
@param ty The sort of the variable
*)
let mk_bound ( ctx : context ) ( index : int ) ( ty : sort ) =
create_expr ctx (Z3native.mk_bound ctx#gno index ty#gno)
(**
Create a quantifier pattern.
*)
let mk_pattern ( ctx : context ) ( terms : expr array ) =
if (Array.length terms) == 0 then
raise (Z3native.Exception "Cannot create a pattern from zero terms")
else
(new pattern ctx)#cnstr_obj (Z3native.mk_pattern ctx#gno (Array.length terms) (astaton terms))
(**
Create a universal Quantifier.
<remarks>
Creates a forall formula, where <paramref name="weight"/> is the weight,
<paramref name="patterns"/> is an array of patterns, <paramref name="sorts"/> is an array
with the sorts of the bound variables, <paramref name="names"/> is an array with the
'names' of the bound variables, and <paramref name="body"/> is the body of the
quantifier. Quantifiers are associated with weights indicating
the importance of using the quantifier during instantiation.
@param sorts the sorts of the bound variables.
@param names names of the bound variables
@param body the body of the quantifier.
@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 <c>MkPattern</c>.
@param noPatterns array containing the anti-patterns created using <c>MkPattern</c>.
@param quantifierID optional symbol to track quantifier.
@param skolemID optional symbol to track skolem constants.
*)
let mk_forall ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) =
if (Array.length sorts) != (Array.length names) then
raise (Z3native.Exception "Number of sorts does not match number of names")
else if (nopatterns == None && quantifier_id == None && skolem_id == None) then
(new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno (int_of_lbool L_TRUE)
(match weight with | None -> 1 | Some(x) -> x)
(match patterns with | None -> 0 | Some(x) -> (Array.length x))
(match patterns with | None -> [||] | Some(x) -> (patternaton x))
(Array.length sorts) (astaton sorts)
(astaton names)
body#gno)
else
let null = Z3native.mk_null() in
(new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno (int_of_lbool L_TRUE)
(match weight with | None -> 1 | Some(x) -> x)
(match quantifier_id with | None -> null | Some(x) -> x#gno)
(match skolem_id with | None -> null | Some(x) -> x#gno)
(match patterns with | None -> 0 | Some(x) -> (Array.length x))
(match patterns with | None -> [||] | Some(x) -> (patternaton x))
(match nopatterns with | None -> 0 | Some(x) -> (Array.length x))
(match nopatterns with | None -> [||] | Some(x) -> (patternaton x))
(Array.length sorts) (astaton sorts)
(astaton names)
body#gno)
(**
Create a universal Quantifier.
*)
let mk_forall_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) =
if (nopatterns == None && quantifier_id == None && skolem_id == None) then
(new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno (int_of_lbool L_TRUE)
(match weight with | None -> 1 | Some(x) -> x)
(Array.length bound_constants) (expraton bound_constants)
(match patterns with | None -> 0 | Some(x) -> (Array.length x))
(match patterns with | None -> [||] | Some(x) -> (patternaton x))
body#gno)
else
let null = Z3native.mk_null() in
(new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno (int_of_lbool L_TRUE)
(match weight with | None -> 1 | Some(x) -> x)
(match quantifier_id with | None -> null | Some(x) -> x#gno)
(match skolem_id with | None -> null | Some(x) -> x#gno)
(Array.length bound_constants) (expraton bound_constants)
(match patterns with | None -> 0 | Some(x) -> (Array.length x))
(match patterns with | None -> [||] | Some(x) -> (patternaton x))
(match nopatterns with | None -> 0 | Some(x) -> (Array.length x))
(match nopatterns with | None -> [||] | Some(x) -> (patternaton x))
body#gno)
(**
Create an existential Quantifier.
<seealso cref="MkForall(Sort[],Symbol[],Expr,uint,Pattern[],Expr[],Symbol,Symbol)"/>
*)
let mk_exists ( ctx : context ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) =
if (Array.length sorts) != (Array.length names) then
raise (Z3native.Exception "Number of sorts does not match number of names")
else if (nopatterns == None && quantifier_id == None && skolem_id == None) then
(new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier ctx#gno (int_of_lbool L_FALSE)
(match weight with | None -> 1 | Some(x) -> x)
(match patterns with | None -> 0 | Some(x) -> (Array.length x))
(match patterns with | None -> [||] | Some(x) -> (patternaton x))
(Array.length sorts) (astaton sorts)
(astaton names)
body#gno)
else
let null = Z3native.mk_null() in
(new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_ex ctx#gno (int_of_lbool L_FALSE)
(match weight with | None -> 1 | Some(x) -> x)
(match quantifier_id with | None -> null | Some(x) -> x#gno)
(match skolem_id with | None -> null | Some(x) -> x#gno)
(match patterns with | None -> 0 | Some(x) -> (Array.length x))
(match patterns with | None -> [||] | Some(x) -> (patternaton x))
(match nopatterns with | None -> 0 | Some(x) -> (Array.length x))
(match nopatterns with | None -> [||] | Some(x) -> (patternaton x))
(Array.length sorts) (astaton sorts)
(astaton names)
body#gno)
(**
Create an existential Quantifier.
*)
let mk_exists_const ( ctx : context ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) =
if (nopatterns == None && quantifier_id == None && skolem_id == None) then
(new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const ctx#gno (int_of_lbool L_FALSE)
(match weight with | None -> 1 | Some(x) -> x)
(Array.length bound_constants) (expraton bound_constants)
(match patterns with | None -> 0 | Some(x) -> (Array.length x))
(match patterns with | None -> [||] | Some(x) -> (patternaton x))
body#gno)
else
let null = Z3native.mk_null() in
(new quantifier ctx)#cnstr_obj (Z3native.mk_quantifier_const_ex ctx#gno (int_of_lbool L_FALSE)
(match weight with | None -> 1 | Some(x) -> x)
(match quantifier_id with | None -> null | Some(x) -> x#gno)
(match skolem_id with | None -> null | Some(x) -> x#gno)
(Array.length bound_constants) (expraton bound_constants)
(match patterns with | None -> 0 | Some(x) -> (Array.length x))
(match patterns with | None -> [||] | Some(x) -> (patternaton x))
(match nopatterns with | None -> 0 | Some(x) -> (Array.length x))
(match nopatterns with | None -> [||] | Some(x) -> (patternaton x))
body#gno)
(**
Create a Quantifier.
*)
let mk_quantifier ( ctx : context ) ( universal : bool ) ( sorts : sort array ) ( names : symbol array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) =
if (universal) then
(mk_forall ctx sorts names body weight patterns nopatterns quantifier_id skolem_id)
else
(mk_exists ctx sorts names body weight patterns nopatterns quantifier_id skolem_id)
(**
Create a Quantifier.
*)
let mk_quantifier ( ctx : context ) ( universal : bool ) ( bound_constants : expr array ) ( body : expr) ( weight : int option ) ( patterns : pattern array option ) ( nopatterns : pattern array option ) ( quantifier_id : symbol option ) ( skolem_id : symbol option ) =
if (universal) then
mk_forall_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id
else
mk_exists_const ctx bound_constants body weight patterns nopatterns quantifier_id skolem_id
end
(** Functions to manipulate Array expressions *)
module Arrays =
struct
(**
Create a new array sort.
*)
let mk_sort ( ctx : context ) domain range =
(new array_sort ctx)#cnstr_dr domain range
(**
Indicates whether the term is an array store.
<remarks>It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j).
Array store takes at least 3 arguments.
*)
let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_STORE)
(**
Indicates whether the term is an array select.
*)
let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SELECT)
(**
Indicates whether the term is a constant array.
<remarks>For example, select(const(v),i) = v holds for every v and i. The function is unary.
*)
let is_constant_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONST_ARRAY)
(**
Indicates whether the term is a default array.
<remarks>For example default(const(v)) = v. The function is unary.
*)
let is_default_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_DEFAULT)
(**
Indicates whether the term is an array map.
<remarks>It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i.
*)
let is_array_map ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ARRAY_MAP)
(**
Indicates whether the term is an as-array term.
<remarks>An as-array term is n array value that behaves as the function graph of the
function passed as parameter.
*)
let is_as_array ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_AS_ARRAY)
(**
Indicates whether the term is of an array sort.
*)
let is_array ( x : expr ) =
((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) &&
((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == ARRAY_SORT)
(** The domain of the array sort. *)
let get_domain (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_domain x#gnc x#gno)
(** The range of the array sort. *)
let get_range (x : array_sort) = create_sort x#gc (Z3native.get_array_sort_range x#gnc x#gno)
(**
Create an array constant.
*)
let mk_const ( ctx : context ) ( name : symbol ) ( domain : sort ) ( range : sort ) =
((Expr.mk_const ctx name ((mk_sort ctx domain range) :> sort)) :> array_expr)
(**
Create an array constant.
*)
let mk_const_s ( ctx : context ) ( name : string ) ( domain : sort ) ( range : sort ) =
mk_const ctx ((Symbol.mk_string ctx name) :> symbol) domain range
(**
Array read.
<remarks>
The argument <c>a</c> is the array and <c>i</c> is the index
of the array that gets read.
The node <c>a</c> must have an array sort <c>[domain -> range]</c>,
and <c>i</c> must have the sort <c>domain</c>.
The sort of the result is <c>range</c>.
<seealso cref="MkArraySort"/>
<seealso cref="MkStore"/>
*)
let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) =
((create_expr ctx (Z3native.mk_select ctx#gno a#gno i#gno)) :> array_expr)
(**
Array update.
<remarks>
The node <c>a</c> must have an array sort <c>[domain -> range]</c>,
<c>i</c> must have sort <c>domain</c>,
<c>v</c> must have sort range. The sort of the result is <c>[domain -> range]</c>.
The semantics of this function is given by the theory of arrays described in the SMT-LIB
standard. See http://smtlib.org for more details.
The result of this function is an array that is equal to <c>a</c>
(with respect to <c>select</c>)
on all indices except for <c>i</c>, where it maps to <c>v</c>
(and the <c>select</c> of <c>a</c> with
respect to <c>i</c> may be a different value).
<seealso cref="MkArraySort"/>
<seealso cref="MkSelect"/>
*)
let mk_select ( ctx : context ) ( a : array_expr ) ( i : expr ) ( v : expr) =
(new array_expr ctx)#cnstr_obj (Z3native.mk_store ctx#gno a#gno i#gno v#gno)
(**
Create a constant array.
<remarks>
The resulting term is an array, such that a <c>select</c>on an arbitrary index
produces the value <c>v</c>.
<seealso cref="MkArraySort"/>
<seealso cref="MkSelect"/>
*)
let mk_const_array ( ctx : context ) ( domain : sort ) ( v : expr ) =
(new array_expr ctx)#cnstr_obj (Z3native.mk_const_array ctx#gno domain#gno v#gno)
(**
Maps f on the argument arrays.
<remarks>
Eeach element of <c>args</c> must be of an array sort <c>[domain_i -> range_i]</c>.
The function declaration <c>f</c> must have type <c> range_1 .. range_n -> range</c>.
<c>v</c> must have sort range. The sort of the result is <c>[domain_i -> range]</c>.
<seealso cref="MkArraySort"/>
<seealso cref="MkSelect"/>
<seealso cref="MkStore"/>
*)
let mk_map ( ctx : context ) ( f : func_decl ) ( args : array_expr array ) =
((create_expr ctx (Z3native.mk_map ctx#gno f#gno (Array.length args) (astaton args))) :> array_expr)
(**
Access the array default value.
<remarks>
Produces the default range value, for arrays that can be represented as
finite maps with a default range value.
*)
let mk_term_array ( ctx : context ) ( arg : array_expr ) =
((create_expr ctx (Z3native.mk_array_default ctx#gno arg#gno)) :> array_expr)
end
(** Functions to manipulate Set expressions *)
module Sets =
struct
(**
Indicates whether the term is set union
*)
let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_UNION)
(**
Indicates whether the term is set intersection
*)
let is_intersect ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_INTERSECT)
(**
Indicates whether the term is set difference
*)
let is_difference ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_DIFFERENCE)
(**
Indicates whether the term is set complement
*)
let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_COMPLEMENT)
(**
Indicates whether the term is set subset
*)
let is_subset ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SET_SUBSET)
(**
Create a set type.
*)
let mk_sort ( ctx : context ) ( ty : sort) =
(new set_sort ctx)#cnstr_s ty
(**
Create an empty set.
*)
let mk_empty ( ctx : context ) ( domain : sort ) =
(create_expr ctx (Z3native.mk_empty_set ctx#gno domain#gno))
(**
Create the full set.
*)
let mk_full ( ctx : context ) ( domain : sort ) =
create_expr ctx (Z3native.mk_full_set ctx#gno domain#gno)
(**
Add an element to the set.
*)
let mk_set_add ( ctx : context ) ( set : expr ) ( element : expr ) =
create_expr ctx (Z3native.mk_set_add ctx#gno set#gno element#gno)
(**
Remove an element from a set.
*)
let mk_del ( ctx : context ) ( set : expr ) ( element : expr ) =
create_expr ctx (Z3native.mk_set_del ctx#gno set#gno element#gno)
(**
Take the union of a list of sets.
*)
let mk_union ( ctx : context ) ( args : expr array ) =
create_expr ctx (Z3native.mk_set_union ctx#gno (Array.length args) (astaton args))
(**
Take the intersection of a list of sets.
*)
let mk_intersection ( ctx : context ) ( args : expr array ) =
create_expr ctx (Z3native.mk_set_intersect ctx#gno (Array.length args) (astaton args))
(**
Take the difference between two sets.
*)
let mk_difference ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) =
create_expr ctx (Z3native.mk_set_difference ctx#gno arg1#gno arg2#gno)
(**
Take the complement of a set.
*)
let mk_complement ( ctx : context ) ( arg : expr ) =
create_expr ctx (Z3native.mk_set_complement ctx#gno arg#gno)
(**
Check for set membership.
*)
let mk_membership ( ctx : context ) ( elem : expr ) ( set : expr ) =
create_expr ctx (Z3native.mk_set_member ctx#gno elem#gno set#gno)
(**
Check for subsetness of sets.
*)
let mk_subset ( ctx : context ) ( arg1 : expr ) ( arg2 : expr) =
create_expr ctx (Z3native.mk_set_subset ctx#gno arg1#gno arg2#gno)
end
(** Functions to manipulate Finite Domain expressions *)
module FiniteDomains =
struct
(**
Create a new finite domain sort.
*)
let mk_sort ( ctx : context ) ( name : symbol ) size =
(new finite_domain_sort ctx)#cnstr_si name size
(**
Create a new finite domain sort.
*)
let mk_sort_s ( ctx : context ) ( name : string ) size =
(new finite_domain_sort ctx)#cnstr_si ((Symbol.mk_string ctx name) :> symbol) size
(**
Indicates whether the term is of an array sort.
*)
let is_finite_domain ( x : expr ) =
((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) &&
(sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == FINITE_DOMAIN_SORT)
(**
Indicates whether the term is a less than predicate over a finite domain.
*)
let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_FD_LT)
(** The size of the finite domain sort. *)
let get_size (x : finite_domain_sort) =
let (r, v) = Z3native.get_finite_domain_sort_size x#gnc x#gno in
if lbool_of_int(r) == L_TRUE then v
else raise (Z3native.Exception "Conversion failed.")
end
(** Functions to manipulate Relation expressions *)
module Relations =
struct
(**
Indicates whether the term is of a relation sort.
*)
let is_relation ( x : expr ) =
((lbool_of_int (Z3native.is_app x#gnc x#gno)) == L_TRUE) &&
(sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno)) == RELATION_SORT)
(**
Indicates whether the term is an relation store
<remarks>
Insert a record into a relation.
The function takes <c>n+1</c> arguments, where the first argument is the relation and the remaining <c>n</c> elements
correspond to the <c>n</c> columns of the relation.
*)
let is_store ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_STORE)
(**
Indicates whether the term is an empty relation
*)
let is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_EMPTY)
(**
Indicates whether the term is a test for the emptiness of a relation
*)
let is_is_empty ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_IS_EMPTY)
(**
Indicates whether the term is a relational join
*)
let is_join ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_JOIN)
(**
Indicates whether the term is the union or convex hull of two relations.
<remarks>The function takes two arguments.
*)
let is_union ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_UNION)
(**
Indicates whether the term is the widening of two relations
<remarks>The function takes two arguments.
*)
let is_widen ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_WIDEN)
(**
Indicates whether the term is a projection of columns (provided as numbers in the parameters).
<remarks>The function takes one argument.
*)
let is_project ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_PROJECT)
(**
Indicates whether the term is a relation filter
<remarks>
Filter (restrict) a relation with respect to a predicate.
The first argument is a relation.
The second argument is a predicate with free de-Brujin indices
corresponding to the columns of the relation.
So the first column in the relation has index 0.
*)
let is_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_FILTER)
(**
Indicates whether the term is an intersection of a relation with the negation of another.
<remarks>
Intersect the first relation with respect to negation
of the second relation (the function takes two arguments).
Logically, the specification can be described by a function
target = filter_by_negation(pos, neg, columns)
where columns are pairs c1, d1, .., cN, dN of columns from pos and neg, such that
target are elements in ( x : expr ) in pos, such that there is no y in neg that agrees with
( x : expr ) on the columns c1, d1, .., cN, dN.
*)
let is_negation_filter ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_NEGATION_FILTER)
(**
Indicates whether the term is the renaming of a column in a relation
<remarks>
The function takes one argument.
The parameters contain the renaming as a cycle.
*)
let is_rename ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_RENAME)
(**
Indicates whether the term is the complement of a relation
*)
let is_complement ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_COMPLEMENT)
(**
Indicates whether the term is a relational select
<remarks>
Check if a record is an element of the relation.
The function takes <c>n+1</c> arguments, where the first argument is a relation,
and the remaining <c>n</c> arguments correspond to a record.
*)
let is_select ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_SELECT)
(**
Indicates whether the term is a relational clone (copy)
<remarks>
Create a fresh copy (clone) of a relation.
The function is logically the identity, but
in the context of a register machine allows
for terms of kind <seealso cref="IsRelationUnion"/>
to perform destructive updates to the first argument.
*)
let is_clone ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_RA_CLONE)
(** The arity of the relation sort. *)
let get_arity (x : relation_sort) = Z3native.get_relation_arity x#gnc x#gno
(** The sorts of the columns of the relation sort. *)
let get_column_sorts (x : relation_sort) =
let n = get_arity x in
let f i = create_sort x#gc (Z3native.get_relation_column x#gnc x#gno i) in
Array.init n f
end
(** Functions to manipulate Datatype expressions *)
module Datatypes =
struct
(** Constructors *)
module Constructor =
struct
(** The number of fields of the constructor. *)
let get_num_fields ( x : constructor ) = x#get_n
(** The function declaration of the constructor. *)
let get_constructor_decl ( x : constructor ) = x#constructor_decl
(** The function declaration of the tester. *)
let get_tester_decl ( x : constructor ) = x#tester_decl
(** The function declarations of the accessors *)
let get_accessor_decls ( x : constructor ) = x#accessor_decls
end
(* DATATYPES *)
(**
Create a datatype constructor.
@param name constructor name
@param recognizer name of recognizer function.
@param fieldNames names of the constructor fields.
@param sorts field sorts, 0 if the field sort refers to a recursive sort.
@param sortRefs reference to datatype sort that is an argument to the constructor;
if the corresponding sort reference is 0, then the value in sort_refs should be an index
referring to one of the recursive datatypes that is declared.
*)
let mk_constructor ( ctx : context ) ( name : symbol ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) =
(new constructor ctx)#cnstr_ssssi name recognizer field_names sorts sort_refs
(**
Create a datatype constructor.
@param name constructor name
@param recognizer name of recognizer function.
@param fieldNames names of the constructor fields.
@param sorts field sorts, 0 if the field sort refers to a recursive sort.
@param sortRefs reference to datatype sort that is an argument to the constructor;
if the corresponding sort reference is 0, then the value in sort_refs should be an index
referring to one of the recursive datatypes that is declared.
*)
let mk_constructor_s ( ctx : context ) ( name : string ) ( recognizer : symbol ) ( field_names : symbol array ) ( sorts : sort array ) ( sort_refs : int array) =
mk_constructor ctx ((Symbol.mk_string ctx name) :> symbol) recognizer field_names sorts sort_refs
(**
Create a new datatype sort.
*)
let mk_sort ( ctx : context ) ( name : symbol ) ( constructors : constructor array) =
(new datatype_sort ctx)#cnstr_sc name constructors
(**
Create a new datatype sort.
*)
let mk_sort_s ( ctx : context ) ( name : string ) ( constructors : constructor array) =
mk_sort ctx ((Symbol.mk_string ctx name) :> symbol) constructors
(**
Create mutually recursive datatypes.
@param names names of datatype sorts
@param c list of constructors, one list per sort.
*)
let mk_sorts ( ctx : context ) ( names : symbol array ) ( c : constructor array array ) =
let n = (Array.length names) in
let f e = ( (new constructor_list ctx)#cnstr_ca e ) in
let cla = (Array.map f c) in
let (r, a) = (Z3native.mk_datatypes ctx#gno n (symbolaton names) (constructor_listaton cla)) in
let g e = ( (new datatype_sort ctx)#cnstr_obj e) in
(Array.map g r)
(** Create mutually recursive data-types. *)
let mk_sorts_s ( ctx : context ) ( names : string array ) ( c : constructor array array ) =
mk_sorts ctx
(
let f e = ((Symbol.mk_string ctx e) :> symbol) in
Array.map f names
)
c
(** The number of constructors of the datatype sort. *)
let get_num_constructors (x : datatype_sort) = Z3native.get_datatype_sort_num_constructors x#gnc x#gno
(** The range of the array sort. *)
let get_constructors (x : datatype_sort) =
let n = (get_num_constructors x) in
let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i) in
Array.init n f
(** The recognizers. *)
let get_recognizers (x : datatype_sort) =
let n = (get_num_constructors x) in
let f i = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_recognizer x#gnc x#gno i) in
Array.init n f
(** The constructor accessors. *)
let get_accessors (x : datatype_sort) =
let n = (get_num_constructors x) in
let f i = (
let fd = ((new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor x#gnc x#gno i)) in
let ds = (Z3native.get_domain_size fd#gnc fd#gno) in
let g j = (new func_decl x#gc)#cnstr_obj (Z3native.get_datatype_sort_constructor_accessor x#gnc x#gno i j) in
Array.init ds g
) in
Array.init n f
end
(** Functions to manipulate Enumeration expressions *)
module Enumerations =
struct
(**
Create a new enumeration sort.
*)
let mk_sort ( ctx : context ) name enum_names =
(new enum_sort ctx)#cnstr_ss name enum_names
(**
Create a new enumeration sort.
*)
let mk_sort_s ( ctx : context ) name enum_names =
(new enum_sort ctx)#cnstr_ss
((Symbol.mk_string ( ctx : context ) name) :> symbol)
(let f e = (e :> symbol) in
(Array.map f (Symbol.mk_strings ( ctx : context ) enum_names))
)
(** The function declarations of the constants in the enumeration. *)
let get_const_decls (x : enum_sort) = x#const_decls
(** The test predicates for the constants in the enumeration. *)
let get_tester_decls (x : enum_sort) = x#tester_decls
end
(** Functions to manipulate List expressions *)
module Lists =
struct
(**
Create a new list sort.
*)
let mk_sort ( ctx : context ) (name : symbol) elem_sort =
(new list_sort ctx)#cnstr_ss name elem_sort
(**
Create a new list sort.
*)
let mk_list_s ( ctx : context ) (name : string) elem_sort =
mk_sort ctx ((Symbol.mk_string ctx name) :> symbol) elem_sort
(** The declaration of the nil function of this list sort. *)
let get_nil_decl (x : list_sort) = x#nil_decl
(** The declaration of the isNil function of this list sort. *)
let get_is_nil_decl (x : list_sort) = x#is_nil_decl
(** The declaration of the cons function of this list sort. *)
let get_cons_decl (x : list_sort) = x#cons_decl
(** The declaration of the isCons function of this list sort. *)
let get_is_cons_decl (x : list_sort) = x#is_cons_decl
(** The declaration of the head function of this list sort. *)
let get_head_decl (x : list_sort) = x#head_decl
(** The declaration of the tail function of this list sort. *)
let get_tail_decl (x : list_sort) = x#tail_decl
(** The empty list. *)
let nil (x : list_sort) = create_expr_fa x#gc (get_nil_decl x) [||]
end
(** Functions to manipulate Tuple expressions *)
module Tuples =
struct
(**
Create a new tuple sort.
*)
let mk_sort ( ctx : context ) name field_names field_sorts =
(new tuple_sort ctx)#cnstr_siss name (Array.length field_names) field_names field_sorts
(** The constructor function of the tuple. *)
let get_mk_decl (x : tuple_sort) =
(new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_mk_decl x#gnc x#gno)
(** The number of fields in the tuple. *)
let get_num_fields (x : tuple_sort) = Z3native.get_tuple_sort_num_fields x#gnc x#gno
(** The field declarations. *)
let get_field_decls (x : tuple_sort) =
let n = get_num_fields x in
let f i = ((new func_decl x#gc)#cnstr_obj (Z3native.get_tuple_sort_field_decl x#gnc x#gno i)) in
Array.init n f
end
(** Functions to manipulate arithmetic expressions *)
module Arithmetic =
struct
(**
Create a new integer sort.
*)
let mk_int_sort ( ctx : context ) =
(new int_sort ctx)#cnstr_obj (Z3native.mk_int_sort ctx#gno)
(**
Create a real sort.
*)
let mk_real_sort ( ctx : context ) =
(new real_sort ctx)#cnstr_obj (Z3native.mk_real_sort ctx#gno)
(**
Indicates whether the term is of integer sort.
*)
let is_int ( x : expr ) =
((lbool_of_int (Z3native.is_numeral_ast x#gnc x#gno)) == L_TRUE) &&
((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == INT_SORT)
(**
Indicates whether the term is an arithmetic numeral.
*)
let is_arithmetic_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ANUM)
(**
Indicates whether the term is a less-than-or-equal
*)
let is_le ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LE)
(**
Indicates whether the term is a greater-than-or-equal
*)
let is_ge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GE)
(**
Indicates whether the term is a less-than
*)
let is_lt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_LT)
(**
Indicates whether the term is a greater-than
*)
let is_gt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_GT)
(**
Indicates whether the term is addition (binary)
*)
let is_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ADD)
(**
Indicates whether the term is subtraction (binary)
*)
let is_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SUB)
(**
Indicates whether the term is a unary minus
*)
let is_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UMINUS)
(**
Indicates whether the term is multiplication (binary)
*)
let is_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MUL)
(**
Indicates whether the term is division (binary)
*)
let is_div ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_DIV)
(**
Indicates whether the term is integer division (binary)
*)
let is_idiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IDIV)
(**
Indicates whether the term is remainder (binary)
*)
let is_remainder ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REM)
(**
Indicates whether the term is modulus (binary)
*)
let is_modulus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_MOD)
(**
Indicates whether the term is a coercion of integer to real (unary)
*)
let is_inttoreal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_REAL)
(**
Indicates whether the term is a coercion of real to integer (unary)
*)
let is_real_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_TO_INT)
(**
Indicates whether the term is a check that tests whether a real is integral (unary)
*)
let is_real_is_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_IS_INT)
(**
Indicates whether the term is of sort real.
*)
let is_real ( x : expr ) =
((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == REAL_SORT)
(**
Indicates whether the term is an integer numeral.
*)
let is_int_numeral ( x : expr ) = (Expr.is_numeral x) && (is_int x)
(**
Indicates whether the term is a real numeral.
*)
let is_rat_num ( x : expr ) = (Expr.is_numeral x) && (is_real x)
(**
Indicates whether the term is an algebraic number
*)
let is_algebraic_number ( x : expr ) = lbool_of_int(Z3native.is_algebraic_number x#gnc x#gno) == L_TRUE
(** Retrieve the int value. *)
let get_int ( x : int_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in
if lbool_of_int(r) == L_TRUE then v
else raise (Z3native.Exception "Conversion failed.")
(** Returns a string representation of the numeral. *)
let to_string ( x : int_num ) = Z3native.get_numeral_string x#gnc x#gno
(** The numerator of a rational numeral. *)
let get_numerator ( x : rat_num ) =
(new int_num x#gc)#cnstr_obj (Z3native.get_numerator x#gnc x#gno)
(** The denominator of a rational numeral. *)
let get_denominator ( x : rat_num ) =
(new int_num x#gc)#cnstr_obj (Z3native.get_denominator x#gnc x#gno)
(** Returns a string representation in decimal notation.
<remarks>The result has at most <paramref name="precision"/> decimal places.*)
let to_decimal_string ( x : rat_num ) (precision : int) =
Z3native.get_numeral_decimal_string x#gnc x#gno precision
(** Returns a string representation of the numeral. *)
let to_string ( x : rat_num ) = Z3native.get_numeral_string x#gnc x#gno
(**
Creates an integer constant.
*)
let mk_int_const ( ctx : context ) ( name : symbol ) =
((Expr.mk_const ctx name (mk_int_sort ctx)) :> int_expr)
(**
Creates an integer constant.
*)
let mk_int_const_s ( ctx : context ) ( name : string ) =
mk_int_const ctx ((Symbol.mk_string ctx name) :> symbol)
(**
Creates a real constant.
*)
let mk_real_const ( ctx : context ) ( name : symbol ) =
((Expr.mk_const ctx name (mk_real_sort ctx)) :> real_expr)
(**
Creates a real constant.
*)
let mk_real_const_s ( ctx : context ) ( name : string ) =
mk_real_const ctx ((Symbol.mk_string ctx name) :> symbol)
(**
Create an expression representing <c>t[0] + t[1] + ...</c>.
*)
let mk_add ( ctx : context ) ( t : arith_expr array ) =
(create_expr ctx (Z3native.mk_add ctx#gno (Array.length t) (astaton t)) :> arith_expr)
(**
Create an expression representing <c>t[0] * t[1] * ...</c>.
*)
let mk_mul ( ctx : context ) ( t : arith_expr array ) =
(create_expr ctx (Z3native.mk_mul ctx#gno (Array.length t) (astaton t)) :> arith_expr)
(**
Create an expression representing <c>t[0] - t[1] - ...</c>.
*)
let mk_sub ( ctx : context ) ( t : arith_expr array ) =
(create_expr ctx (Z3native.mk_sub ctx#gno (Array.length t) (astaton t)) :> arith_expr)
(**
Create an expression representing <c>-t</c>.
*)
let mk_unary_minus ( ctx : context ) ( t : arith_expr ) =
(create_expr ctx (Z3native.mk_unary_minus ctx#gno t#gno) :> arith_expr)
(**
Create an expression representing <c>t1 / t2</c>.
*)
let mk_div ( ctx : context ) ( t1 : arith_expr ) ( t2 : arith_expr ) =
(create_expr ctx (Z3native.mk_div ctx#gno t1#gno t2#gno) :> arith_expr)
(**
Create an expression representing <c>t1 mod t2</c>.
<remarks>The arguments must have int type.
*)
let mk_mod ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) =
(new int_expr ctx)#cnstr_obj (Z3native.mk_mod ctx#gno t1#gno t2#gno)
(**
Create an expression representing <c>t1 rem t2</c>.
<remarks>The arguments must have int type.
*)
let mk_rem ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) =
(new int_expr ctx)#cnstr_obj (Z3native.mk_rem ctx#gno t1#gno t2#gno)
(**
Create an expression representing <c>t1 ^ t2</c>.
*)
let mk_Power ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) =
(create_expr ctx (Z3native.mk_power ctx#gno t1#gno t2#gno) :> arith_expr)
(**
Create an expression representing <c>t1 < t2</c>
*)
let mk_lt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_lt ctx#gno t1#gno t2#gno)
(**
Create an expression representing <c>t1 <= t2</c>
*)
let mk_le ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_le ctx#gno t1#gno t2#gno)
(**
Create an expression representing <c>t1 > t2</c>
*)
let mk_gt ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_gt ctx#gno t1#gno t2#gno)
(**
Create an expression representing <c>t1 >= t2</c>
*)
let mk_ge ( ctx : context ) ( t1 : int_expr ) ( t2 : int_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_ge ctx#gno t1#gno t2#gno)
(**
Coerce an integer to a real.
<remarks>
There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard.
You can take the floor of a real by creating an auxiliary integer Term <c>k</c> and
and asserting <c>MakeInt2Real(k) <= t1 < MkInt2Real(k)+1</c>.
The argument must be of integer sort.
*)
let mk_int2real ( ctx : context ) ( t : int_expr ) =
(new real_expr ctx)#cnstr_obj (Z3native.mk_int2real ctx#gno t#gno)
(**
Coerce a real to an integer.
<remarks>
The semantics of this function follows the SMT-LIB standard for the function to_int.
The argument must be of real sort.
*)
let mk_real2int ( ctx : context ) ( t : real_expr ) =
(new int_expr ctx)#cnstr_obj (Z3native.mk_real2int ctx#gno t#gno)
(**
Creates an expression that checks whether a real number is an integer.
*)
let mk_is_integer ( ctx : context ) ( t : real_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_is_int ctx#gno t#gno)
(**
Return a upper bound for a given real algebraic number.
The interval isolating the number is smaller than 1/10^<paramref name="precision"/>.
<seealso cref="Expr.IsAlgebraicNumber"/>
@param precision the precision of the result
@return A numeral Expr of sort Real
*)
let to_upper ( x : algebraic_num ) ( precision : int ) =
(new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_upper x#gnc x#gno precision)
(**
Return a lower bound for the given real algebraic number.
The interval isolating the number is smaller than 1/10^<paramref name="precision"/>.
<seealso cref="Expr.IsAlgebraicNumber"/>
@param precision the precision of the result
@return A numeral Expr of sort Real
*)
let to_lower ( x : algebraic_num ) precision =
(new rat_num x#gc)#cnstr_obj (Z3native.get_algebraic_number_lower x#gnc x#gno precision)
(** Returns a string representation in decimal notation.
<remarks>The result has at most <paramref name="precision"/> decimal places.*)
let to_decimal_string ( x : algebraic_num ) ( precision : int ) =
Z3native.get_numeral_decimal_string x#gnc x#gno precision
(**
Create a real from a fraction.
@param num numerator of rational.
@param den denominator of rational.
@return A Term with value <paramref name="num"/>/<paramref name="den"/> and sort Real
<seealso cref="MkNumeral(string, Sort)"/>
*)
let mk_real_numeral_nd ( ctx : context ) ( num : int ) ( den : int) =
if (den == 0) then
raise (Z3native.Exception "Denominator is zero")
else
(new rat_num ctx)#cnstr_obj (Z3native.mk_real ctx#gno num den)
(**
Create a real numeral.
@param v A string representing the Term value in decimal notation.
@return A Term with value <paramref name="v"/> and sort Real
*)
let mk_real_numeral_s ( ctx : context ) ( v : string ) =
(new rat_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_real_sort ctx)#gno)
(**
Create a real numeral.
@param v value of the numeral.
@return A Term with value <paramref name="v"/> and sort Real
*)
let mk_real_numeral_i ( ctx : context ) ( v : int ) =
(new rat_num ctx)#cnstr_obj (Z3native.mk_int ctx#gno v (mk_real_sort ctx)#gno)
(**
Create an integer numeral.
@param v A string representing the Term value in decimal notation.
*)
let mk_int_numeral_s ( ctx : context ) ( v : string ) =
(new int_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_int_sort ctx)#gno)
(**
Create an integer numeral.
@param v value of the numeral.
@return A Term with value <paramref name="v"/> and sort Integer
*)
let mk_int_numeral_i ( ctx : context ) ( v : int ) =
(new int_num ctx)#cnstr_obj (Z3native.mk_int ctx#gno v (mk_int_sort ctx)#gno)
(** Returns a string representation of the numeral. *)
let to_string ( x : algebraic_num ) = Z3native.get_numeral_string x#gnc x#gno
end
(** Functions to manipulate bit-vector expressions *)
module BitVectors =
struct
(**
Create a new bit-vector sort.
*)
let mk_sort ( ctx : context ) size =
(new bitvec_sort ctx)#cnstr_obj (Z3native.mk_bv_sort ctx#gno size)
(**
Indicates whether the terms is of bit-vector sort.
*)
let is_bv ( x : expr ) =
((sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_sort x#gnc x#gno))) == BV_SORT)
(**
Indicates whether the term is a bit-vector numeral
*)
let is_bv_numeral ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNUM)
(**
Indicates whether the term is a one-bit bit-vector with value one
*)
let is_bv_bit1 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT1)
(**
Indicates whether the term is a one-bit bit-vector with value zero
*)
let is_bv_bit0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BIT0)
(**
Indicates whether the term is a bit-vector unary minus
*)
let is_bv_uminus ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNEG)
(**
Indicates whether the term is a bit-vector addition (binary)
*)
let is_bv_add ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BADD)
(**
Indicates whether the term is a bit-vector subtraction (binary)
*)
let is_bv_sub ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSUB)
(**
Indicates whether the term is a bit-vector multiplication (binary)
*)
let is_bv_mul ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BMUL)
(**
Indicates whether the term is a bit-vector signed division (binary)
*)
let is_bv_sdiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV)
(**
Indicates whether the term is a bit-vector unsigned division (binary)
*)
let is_bv_udiv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV)
(**
Indicates whether the term is a bit-vector signed remainder (binary)
*)
let is_bv_SRem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM)
(**
Indicates whether the term is a bit-vector unsigned remainder (binary)
*)
let is_bv_urem ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM)
(**
Indicates whether the term is a bit-vector signed modulus
*)
let is_bv_smod ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD)
(**
Indicates whether the term is a bit-vector signed division by zero
*)
let is_bv_sdiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSDIV0)
(**
Indicates whether the term is a bit-vector unsigned division by zero
*)
let is_bv_udiv0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUDIV0)
(**
Indicates whether the term is a bit-vector signed remainder by zero
*)
let is_bv_srem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSREM0)
(**
Indicates whether the term is a bit-vector unsigned remainder by zero
*)
let is_bv_urem0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BUREM0)
(**
Indicates whether the term is a bit-vector signed modulus by zero
*)
let is_bv_smod0 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSMOD0)
(**
Indicates whether the term is an unsigned bit-vector less-than-or-equal
*)
let is_bv_ule ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULEQ)
(**
Indicates whether the term is a signed bit-vector less-than-or-equal
*)
let is_bv_sle ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLEQ)
(**
Indicates whether the term is an unsigned bit-vector greater-than-or-equal
*)
let is_bv_uge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGEQ)
(**
Indicates whether the term is a signed bit-vector greater-than-or-equal
*)
let is_bv_sge ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGEQ)
(**
Indicates whether the term is an unsigned bit-vector less-than
*)
let is_bv_ult ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ULT)
(**
Indicates whether the term is a signed bit-vector less-than
*)
let is_bv_slt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SLT)
(**
Indicates whether the term is an unsigned bit-vector greater-than
*)
let is_bv_ugt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_UGT)
(**
Indicates whether the term is a signed bit-vector greater-than
*)
let is_bv_sgt ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SGT)
(**
Indicates whether the term is a bit-wise AND
*)
let is_bv_and ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BAND)
(**
Indicates whether the term is a bit-wise OR
*)
let is_bv_or ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BOR)
(**
Indicates whether the term is a bit-wise NOT
*)
let is_bv_not ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOT)
(**
Indicates whether the term is a bit-wise XOR
*)
let is_bv_xor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXOR)
(**
Indicates whether the term is a bit-wise NAND
*)
let is_bv_nand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNAND)
(**
Indicates whether the term is a bit-wise NOR
*)
let is_bv_nor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BNOR)
(**
Indicates whether the term is a bit-wise XNOR
*)
let is_bv_xnor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BXNOR)
(**
Indicates whether the term is a bit-vector concatenation (binary)
*)
let is_bv_concat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CONCAT)
(**
Indicates whether the term is a bit-vector sign extension
*)
let is_bv_signextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_SIGN_EXT)
(**
Indicates whether the term is a bit-vector zero extension
*)
let is_bv_zeroextension ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ZERO_EXT)
(**
Indicates whether the term is a bit-vector extraction
*)
let is_bv_extract ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXTRACT)
(**
Indicates whether the term is a bit-vector repetition
*)
let is_bv_repeat ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_REPEAT)
(**
Indicates whether the term is a bit-vector reduce OR
*)
let is_bv_reduceor ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDOR)
(**
Indicates whether the term is a bit-vector reduce AND
*)
let is_bv_reduceand ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BREDAND)
(**
Indicates whether the term is a bit-vector comparison
*)
let is_bv_comp ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BCOMP)
(**
Indicates whether the term is a bit-vector shift left
*)
let is_bv_shiftleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BSHL)
(**
Indicates whether the term is a bit-vector logical shift right
*)
let is_bv_shiftrightlogical ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BLSHR)
(**
Indicates whether the term is a bit-vector arithmetic shift left
*)
let is_bv_shiftrightarithmetic ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BASHR)
(**
Indicates whether the term is a bit-vector rotate left
*)
let is_bv_rotateleft ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_LEFT)
(**
Indicates whether the term is a bit-vector rotate right
*)
let is_bv_rotateright ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_ROTATE_RIGHT)
(**
Indicates whether the term is a bit-vector rotate left (extended)
<remarks>Similar to Z3_OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one.
*)
let is_bv_rotateleftextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_LEFT)
(**
Indicates whether the term is a bit-vector rotate right (extended)
<remarks>Similar to Z3_OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one.
*)
let is_bv_rotaterightextended ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_EXT_ROTATE_RIGHT)
(**
Indicates whether the term is a coercion from integer to bit-vector
<remarks>This function is not supported by the decision procedures. Only the most
rudimentary simplification rules are applied to this function.
*)
let is_int_to_bv ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_INT2BV)
(**
Indicates whether the term is a coercion from bit-vector to integer
<remarks>This function is not supported by the decision procedures. Only the most
rudimentary simplification rules are applied to this function.
*)
let is_bv_to_int ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_BV2INT)
(**
Indicates whether the term is a bit-vector carry
<remarks>Compute the carry bit in a full-adder. The meaning is given by the
equivalence (carry l1 l2 l3) <=> (or (and l1 l2) (and l1 l3) (and l2 l3)))
*)
let is_bv_carry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_CARRY)
(**
Indicates whether the term is a bit-vector ternary XOR
<remarks>The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3)
*)
let is_bv_xor3 ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_XOR3)
(** The size of a bit-vector sort. *)
let get_size (x : bitvec_sort) = Z3native.get_bv_sort_size x#gnc x#gno
(** Retrieve the int value. *)
let get_int ( x : bitvec_num ) = let (r, v) = Z3native.get_numeral_int x#gnc x#gno in
if lbool_of_int(r) == L_TRUE then v
else raise (Z3native.Exception "Conversion failed.")
(** Returns a string representation of the numeral. *)
let to_string ( x : bitvec_num ) = Z3native.get_numeral_string x#gnc x#gno
(**
Creates a bit-vector constant.
*)
let mk_const ( ctx : context ) ( name : symbol ) ( size : int ) =
((Expr.mk_const ctx name (mk_sort ctx size)) :> bitvec_expr)
(**
Creates a bit-vector constant.
*)
let mk_const_s ( ctx : context ) ( name : string ) ( size : int ) =
mk_const ctx ((Symbol.mk_string ctx name) :> symbol) size
(**
Bitwise negation.
<remarks>The argument must have a bit-vector sort.
*)
let mk_not ( ctx : context ) ( t : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnot ctx#gno t#gno)
(**
Take conjunction of bits in a vector,vector of length 1.
<remarks>The argument must have a bit-vector sort.
*)
let mk_redand ( ctx : context ) ( t : bitvec_expr) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredand ctx#gno t#gno)
(**
Take disjunction of bits in a vector,vector of length 1.
<remarks>The argument must have a bit-vector sort.
*)
let mk_redor ( ctx : context ) ( t : bitvec_expr) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvredor ctx#gno t#gno)
(**
Bitwise conjunction.
<remarks>The arguments must have a bit-vector sort.
*)
let mk_and ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvand ctx#gno t1#gno t2#gno)
(**
Bitwise disjunction.
<remarks>The arguments must have a bit-vector sort.
*)
let mk_or ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvor ctx#gno t1#gno t2#gno)
(**
Bitwise XOR.
<remarks>The arguments must have a bit-vector sort.
*)
let mk_xor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxor ctx#gno t1#gno t2#gno)
(**
Bitwise NAND.
<remarks>The arguments must have a bit-vector sort.
*)
let mk_nand ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnand ctx#gno t1#gno t2#gno)
(**
Bitwise NOR.
<remarks>The arguments must have a bit-vector sort.
*)
let mk_nor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvnor ctx#gno t1#gno t2#gno)
(**
Bitwise XNOR.
<remarks>The arguments must have a bit-vector sort.
*)
let mk_xnor ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvxnor ctx#gno t1#gno t2#gno)
(**
Standard two's complement unary minus.
<remarks>The arguments must have a bit-vector sort.
*)
let mk_neg ( ctx : context ) ( t : bitvec_expr) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvneg ctx#gno t#gno)
(**
Two's complement addition.
<remarks>The arguments must have the same bit-vector sort.
*)
let mk_add ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvadd ctx#gno t1#gno t2#gno)
(**
Two's complement subtraction.
<remarks>The arguments must have the same bit-vector sort.
*)
let mk_sub ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsub ctx#gno t1#gno t2#gno)
(**
Two's complement multiplication.
<remarks>The arguments must have the same bit-vector sort.
*)
let mk_mul ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvmul ctx#gno t1#gno t2#gno)
(**
Unsigned division.
<remarks>
It is defined as the floor of <c>t1/t2</c> if \c t2 is
different from zero. If <c>t2</c> is zero, then the result
is undefined.
The arguments must have the same bit-vector sort.
*)
let mk_udiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvudiv ctx#gno t1#gno t2#gno)
(**
Signed division.
<remarks>
It is defined in the following way:
- The \c floor of <c>t1/t2</c> if \c t2 is different from zero, and <c>t1*t2 >= 0</c>.
- The \c ceiling of <c>t1/t2</c> if \c t2 is different from zero, and <c>t1*t2 < 0</c>.
If <c>t2</c> is zero, then the result is undefined.
The arguments must have the same bit-vector sort.
*)
let mk_sdiv ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv ctx#gno t1#gno t2#gno)
(**
Unsigned remainder.
<remarks>
It is defined as <c>t1 - (t1 /u t2) * t2</c>, where <c>/u</c> represents unsigned division.
If <c>t2</c> is zero, then the result is undefined.
The arguments must have the same bit-vector sort.
*)
let mk_urem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvurem ctx#gno t1#gno t2#gno)
(**
Signed remainder.
<remarks>
It is defined as <c>t1 - (t1 /s t2) * t2</c>, where <c>/s</c> represents signed division.
The most significant bit (sign) of the result is equal to the most significant bit of \c t1.
If <c>t2</c> is zero, then the result is undefined.
The arguments must have the same bit-vector sort.
*)
let mk_srem ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsrem ctx#gno t1#gno t2#gno)
(**
Two's complement signed remainder (sign follows divisor).
<remarks>
If <c>t2</c> is zero, then the result is undefined.
The arguments must have the same bit-vector sort.
*)
let mk_smod ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvsmod ctx#gno t1#gno t2#gno)
(**
Unsigned less-than
<remarks>
The arguments must have the same bit-vector sort.
*)
let mk_ult ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvult ctx#gno t1#gno t2#gno)
(**
Two's complement signed less-than
<remarks>
The arguments must have the same bit-vector sort.
*)
let mk_slt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvslt ctx#gno t1#gno t2#gno)
(**
Unsigned less-than or equal to.
<remarks>
The arguments must have the same bit-vector sort.
*)
let mk_ule ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvule ctx#gno t1#gno t2#gno)
(**
Two's complement signed less-than or equal to.
<remarks>
The arguments must have the same bit-vector sort.
*)
let mk_sle ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsle ctx#gno t1#gno t2#gno)
(**
Unsigned greater than or equal to.
<remarks>
The arguments must have the same bit-vector sort.
*)
let mk_uge ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvuge ctx#gno t1#gno t2#gno)
(**
Two's complement signed greater than or equal to.
<remarks>
The arguments must have the same bit-vector sort.
*)
let mk_SGE ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsge ctx#gno t1#gno t2#gno)
(**
Unsigned greater-than.
<remarks>
The arguments must have the same bit-vector sort.
*)
let mk_ugt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvugt ctx#gno t1#gno t2#gno)
(**
Two's complement signed greater-than.
<remarks>
The arguments must have the same bit-vector sort.
*)
let mk_sgt ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsgt ctx#gno t1#gno t2#gno)
(**
Bit-vector concatenation.
<remarks>
The arguments must have a bit-vector sort.
@return
The result is a bit-vector of size <c>n1+n2</c>, where <c>n1</c> (<c>n2</c>)
is the size of <c>t1</c> (<c>t2</c>).
*)
let mk_concat ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_concat ctx#gno t1#gno t2#gno)
(**
Bit-vector extraction.
<remarks>
Extract the bits <paramref name="high"/> down to <paramref name="low"/> from a bitvector of
size <c>m</c> to yield a new bitvector of size <c>n</c>, where
<c>n = high - low + 1</c>.
The argument <paramref name="t"/> must have a bit-vector sort.
*)
let mk_extract ( ctx : context ) ( high : int ) ( low : int ) ( t : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_extract ctx#gno high low t#gno)
(**
Bit-vector sign extension.
<remarks>
Sign-extends the given bit-vector to the (signed) equivalent bitvector of
size <c>m+i</c>, where \c m is the size of the given bit-vector.
The argument <paramref name="t"/> must have a bit-vector sort.
*)
let mk_sign_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_sign_ext ctx#gno i t#gno)
(**
Bit-vector zero extension.
<remarks>
Extend the given bit-vector with zeros to the (unsigned) equivalent
bitvector of size <c>m+i</c>, where \c m is the size of the
given bit-vector.
The argument <paramref name="t"/> must have a bit-vector sort.
*)
let mk_zero_ext ( ctx : context ) ( i : int ) ( t : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_zero_ext ctx#gno i t#gno)
(**
Bit-vector repetition.
<remarks>
The argument <paramref name="t"/> must have a bit-vector sort.
*)
let mk_repeat ( ctx : context ) ( i : int ) ( t : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_repeat ctx#gno i t#gno)
(**
Shift left.
<remarks>
It is equivalent to multiplication by <c>2^x</c> where \c x is the value of <paramref name="t2"/>.
NB. The semantics of shift operations varies between environments. This
definition does not necessarily capture directly the semantics of the
programming language or assembly architecture you are modeling.
The arguments must have a bit-vector sort.
*)
let mk_shl ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvshl ctx#gno t1#gno t2#gno)
(**
Logical shift right
<remarks>
It is equivalent to unsigned division by <c>2^x</c> where \c x is the value of <paramref name="t2"/>.
NB. The semantics of shift operations varies between environments. This
definition does not necessarily capture directly the semantics of the
programming language or assembly architecture you are modeling.
The arguments must have a bit-vector sort.
*)
let mk_lshr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvlshr ctx#gno t1#gno t2#gno)
(**
Arithmetic shift right
<remarks>
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.
NB. The semantics of shift operations varies between environments. This
definition does not necessarily capture directly the semantics of the
programming language or assembly architecture you are modeling.
The arguments must have a bit-vector sort.
*)
let mk_ashr ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_bvashr ctx#gno t1#gno t2#gno)
(**
Rotate Left.
<remarks>
Rotate bits of \c t to the left \c i times.
The argument <paramref name="t"/> must have a bit-vector sort.
*)
let mk_rotate_left ( ctx : context ) ( i : int ) ( t : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_left ctx#gno i t#gno)
(**
Rotate Right.
<remarks>
Rotate bits of \c t to the right \c i times.
The argument <paramref name="t"/> must have a bit-vector sort.
*)
let mk_rotate_right ( ctx : context ) ( i : int ) ( t : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_rotate_right ctx#gno i t#gno)
(**
Rotate Left.
<remarks>
Rotate bits of <paramref name="t1"/> to the left <paramref name="t2"/> times.
The arguments must have the same bit-vector sort.
*)
let mk_rotate_left ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_left ctx#gno t1#gno t2#gno)
(**
Rotate Right.
<remarks>
Rotate bits of <paramref name="t1"/> to the right<paramref name="t2"/> times.
The arguments must have the same bit-vector sort.
*)
let mk_rotate_right ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_ext_rotate_right ctx#gno t1#gno t2#gno)
(**
Create an <paramref name="n"/> bit bit-vector from the integer argument <paramref name="t"/>.
<remarks>
NB. This function is essentially treated as uninterpreted.
So you cannot expect Z3 to precisely reflect the semantics of this function
when solving constraints with this function.
The argument must be of integer sort.
*)
let mk_int2bv ( ctx : context ) ( n : int ) ( t : int_expr ) =
(new bitvec_expr ctx)#cnstr_obj (Z3native.mk_int2bv ctx#gno n t#gno)
(**
Create an integer from the bit-vector argument <paramref name="t"/>.
<remarks>
If \c is_signed is false, then the bit-vector \c t1 is treated as unsigned.
So the result is non-negative and in the range <c>[0..2^N-1]</c>, where
N are the number of bits in <paramref name="t"/>.
If \c is_signed is true, \c t1 is treated as a signed bit-vector.
NB. This function is essentially treated as uninterpreted.
So you cannot expect Z3 to precisely reflect the semantics of this function
when solving constraints with this function.
The argument must be of bit-vector sort.
*)
let mk_bv2int ( ctx : context ) ( t : bitvec_expr ) ( signed : bool) =
(new int_expr ctx)#cnstr_obj (Z3native.mk_bv2int ctx#gno t#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE)))
(**
Create a predicate that checks that the bit-wise addition does not overflow.
<remarks>
The arguments must be of bit-vector sort.
*)
let mk_add_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_overflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE)))
(**
Create a predicate that checks that the bit-wise addition does not underflow.
<remarks>
The arguments must be of bit-vector sort.
*)
let mk_add_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvadd_no_underflow ctx#gno t1#gno t2#gno)
(**
Create a predicate that checks that the bit-wise subtraction does not overflow.
<remarks>
The arguments must be of bit-vector sort.
*)
let mk_sub_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_overflow ctx#gno t1#gno t2#gno)
(**
Create a predicate that checks that the bit-wise subtraction does not underflow.
<remarks>
The arguments must be of bit-vector sort.
*)
let mk_sub_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsub_no_underflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE)))
(**
Create a predicate that checks that the bit-wise signed division does not overflow.
<remarks>
The arguments must be of bit-vector sort.
*)
let mk_sdiv_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvsdiv_no_overflow ctx#gno t1#gno t2#gno)
(**
Create a predicate that checks that the bit-wise negation does not overflow.
<remarks>
The arguments must be of bit-vector sort.
*)
let mk_neg_no_overflow ( ctx : context ) ( t : bitvec_expr) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvneg_no_overflow ctx#gno t#gno)
(**
Create a predicate that checks that the bit-wise multiplication does not overflow.
<remarks>
The arguments must be of bit-vector sort.
*)
let mk_mul_no_overflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) ( signed : bool) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_overflow ctx#gno t1#gno t2#gno (int_of_lbool (if (signed) then L_TRUE else L_FALSE)))
(**
Create a predicate that checks that the bit-wise multiplication does not underflow.
<remarks>
The arguments must be of bit-vector sort.
*)
let mk_mul_no_underflow ( ctx : context ) ( t1 : bitvec_expr ) ( t2 : bitvec_expr ) =
(new bool_expr ctx)#cnstr_obj (Z3native.mk_bvmul_no_underflow ctx#gno t1#gno t2#gno)
(**
Create a bit-vector numeral.
@param v A string representing the value in decimal notation.
@param size the size of the bit-vector
*)
let mk_numeral ( ctx : context ) ( ctx : context ) ( v : string ) ( size : int) =
(new bitvec_num ctx)#cnstr_obj (Z3native.mk_numeral ctx#gno v (mk_sort ctx size)#gno)
end
(** Functions to manipulate proof expressions *)
module Proofs =
struct
(**
Indicates whether the term is a Proof for the expression 'true'.
*)
let is_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRUE)
(**
Indicates whether the term is a proof for a fact asserted by the user.
*)
let is_asserted ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ASSERTED)
(**
Indicates whether the term is a proof for a fact (tagged as goal) asserted by the user.
*)
let is_goal ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_GOAL)
(**
Indicates whether the term is proof via modus ponens
<remarks>
Given a proof for p and a proof for (implies p q), produces a proof for q.
T1: p
T2: (implies p q)
[mp T1 T2]: q
The second antecedents may also be a proof for (iff p q).
*)
let is_modus_ponens ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS)
(**
Indicates whether the term is a proof for (R t t), where R is a reflexive relation.
<remarks>This proof object has no antecedents.
The only reflexive relations that are used are
equivalence modulo namings, equality and equivalence.
That is, R is either '~', '=' or 'iff'.
*)
let is_reflexivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REFLEXIVITY)
(**
Indicates whether the term is proof by symmetricity of a relation
<remarks>
Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t).
T1: (R t s)
[symmetry T1]: (R s t)
T1 is the antecedent of this proof object.
*)
let is_symmetry ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SYMMETRY)
(**
Indicates whether the term is a proof by transitivity of a relation
<remarks>
Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof
for (R t u).
T1: (R t s)
T2: (R s u)
[trans T1 T2]: (R t u)
*)
let is_transitivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY)
(**
Indicates whether the term is a proof by condensed transitivity of a relation
<remarks>
Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1.
It combines several symmetry and transitivity proofs.
Example:
T1: (R a b)
T2: (R c b)
T3: (R c d)
[trans* T1 T2 T3]: (R a d)
R must be a symmetric and transitive relation.
Assuming that this proof object is a proof for (R s t), then
a proof checker must check if it is possible to prove (R s t)
using the antecedents, symmetry and transitivity. That is,
if there is a path from s to t, if we view every
antecedent (R a b) as an edge between a and b.
*)
let is_Transitivity_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TRANSITIVITY_STAR)
(**
Indicates whether the term is a monotonicity proof object.
<remarks>
T1: (R t_1 s_1)
...
Tn: (R t_n s_n)
[monotonicity T1 ... Tn]: (R (f t_1 ... t_n) (f s_1 ... s_n))
Remark: if t_i == s_i, then the antecedent Ti is suppressed.
That is, reflexivity proofs are supressed to save space.
*)
let is_monotonicity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MONOTONICITY)
(**
Indicates whether the term is a quant-intro proof
<remarks>
Given a proof for (~ p q), produces a proof for (~ (forall (x) p) (forall (x) q)).
T1: (~ p q)
[quant-intro T1]: (~ (forall (x) p) (forall (x) q))
*)
let is_quant_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INTRO)
(**
Indicates whether the term is a distributivity proof object.
<remarks>
Given that f (= or) distributes over g (= and), produces a proof for
(= (f a (g c d))
(g (f a c) (f a d)))
If f and g are associative, this proof also justifies the following equality:
(= (f (g a b) (g c d))
(g (f a c) (f a d) (f b c) (f b d)))
where each f and g can have arbitrary number of arguments.
This proof object has no antecedents.
Remark. This rule is used by the CNF conversion pass and
instantiated by f = or, and g = and.
*)
let is_distributivity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DISTRIBUTIVITY)
(**
Indicates whether the term is a proof by elimination of AND
<remarks>
Given a proof for (and l_1 ... l_n), produces a proof for l_i
T1: (and l_1 ... l_n)
[and-elim T1]: l_i
*)
let is_and_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_AND_ELIM)
(**
Indicates whether the term is a proof by eliminiation of not-or
<remarks>
Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i).
T1: (not (or l_1 ... l_n))
[not-or-elim T1]: (not l_i)
*)
let is_or_elimination ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NOT_OR_ELIM)
(**
Indicates whether the term is a proof by rewriting
<remarks>
A proof for a local rewriting step (= t s).
The head function symbol of t is interpreted.
This proof object has no antecedents.
The conclusion of a rewrite rule is either an equality (= t s),
an equivalence (iff t s), or equi-satisfiability (~ t s).
Remark: if f is bool, then = is iff.
Examples:
(= (+ ( x : expr ) 0) x)
(= (+ ( x : expr ) 1 2) (+ 3 x))
(iff (or ( x : expr ) false) x)
*)
let is_rewrite ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE)
(**
Indicates whether the term is a proof by rewriting
<remarks>
A proof for rewriting an expression t into an expression s.
This proof object is used if the parameter PROOF_MODE is 1.
This proof object can have n antecedents.
The antecedents are proofs for equalities used as substitution rules.
The object is also used in a few cases if the parameter PROOF_MODE is 2.
The cases are:
- When applying contextual simplification (CONTEXT_SIMPLIFIER=true)
- When converting bit-vectors to Booleans (BIT2BOOL=true)
- When pulling ite expression up (PULL_CHEAP_ITE_TREES=true)
*)
let is_rewrite_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_REWRITE_STAR)
(**
Indicates whether the term is a proof for pulling quantifiers out.
<remarks>
A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents.
*)
let is_pull_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT)
(**
Indicates whether the term is a proof for pulling quantifiers out.
<remarks>
A proof for (iff P Q) where Q is in prenex normal form.
This proof object is only used if the parameter PROOF_MODE is 1.
This proof object has no antecedents
*)
let is_pull_quant_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PULL_QUANT_STAR)
(**
Indicates whether the term is a proof for pushing quantifiers in.
<remarks>
A proof for:
(iff (forall (x_1 ... x_m) (and p_1[x_1 ... x_m] ... p_n[x_1 ... x_m]))
(and (forall (x_1 ... x_m) p_1[x_1 ... x_m])
...
(forall (x_1 ... x_m) p_n[x_1 ... x_m])))
This proof object has no antecedents
*)
let is_push_quant ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_PUSH_QUANT)
(**
Indicates whether the term is a proof for elimination of unused variables.
<remarks>
A proof for (iff (forall (x_1 ... x_n y_1 ... y_m) p[x_1 ... x_n])
(forall (x_1 ... x_n) p[x_1 ... x_n]))
It is used to justify the elimination of unused variables.
This proof object has no antecedents.
*)
let is_elim_unused_vars ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_ELIM_UNUSED_VARS)
(**
Indicates whether the term is a proof for destructive equality resolution
<remarks>
A proof for destructive equality resolution:
(iff (forall (x) (or (not (= ( x : expr ) t)) P[x])) P[t])
if ( x : expr ) does not occur in t.
This proof object has no antecedents.
Several variables can be eliminated simultaneously.
*)
let is_der ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DER)
(**
Indicates whether the term is a proof for quantifier instantiation
<remarks>
A proof of (or (not (forall (x) (P x))) (P a))
*)
let is_quant_inst ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_QUANT_INST)
(**
Indicates whether the term is a hypthesis marker.
<remarks>Mark a hypothesis in a natural deduction style proof.
*)
let is_hypothesis ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_HYPOTHESIS)
(**
Indicates whether the term is a proof by lemma
<remarks>
T1: false
[lemma T1]: (or (not l_1) ... (not l_n))
This proof object has one antecedent: a hypothetical proof for false.
It converts the proof in a proof for (or (not l_1) ... (not l_n)),
when T1 contains the hypotheses: l_1, ..., l_n.
*)
let is_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_LEMMA)
(**
Indicates whether the term is a proof by unit resolution
<remarks>
T1: (or l_1 ... l_n l_1' ... l_m')
T2: (not l_1)
...
T(n+1): (not l_n)
[unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m')
*)
let is_unit_resolution ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_UNIT_RESOLUTION)
(**
Indicates whether the term is a proof by iff-true
<remarks>
T1: p
[iff-true T1]: (iff p true)
*)
let is_iff_true ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_TRUE)
(**
Indicates whether the term is a proof by iff-false
<remarks>
T1: (not p)
[iff-false T1]: (iff p false)
*)
let is_iff_false ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_FALSE)
(**
Indicates whether the term is a proof by commutativity
<remarks>
[comm]: (= (f a b) (f b a))
f is a commutative operator.
This proof object has no antecedents.
Remark: if f is bool, then = is iff.
*)
let is_commutativity ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_COMMUTATIVITY) (* *)
(**
Indicates whether the term is a proof for Tseitin-like axioms
<remarks>
Proof object used to justify Tseitin's like axioms:
(or (not (and p q)) p)
(or (not (and p q)) q)
(or (not (and p q r)) p)
(or (not (and p q r)) q)
(or (not (and p q r)) r)
...
(or (and p q) (not p) (not q))
(or (not (or p q)) p q)
(or (or p q) (not p))
(or (or p q) (not q))
(or (not (iff p q)) (not p) q)
(or (not (iff p q)) p (not q))
(or (iff p q) (not p) (not q))
(or (iff p q) p q)
(or (not (ite a b c)) (not a) b)
(or (not (ite a b c)) a c)
(or (ite a b c) (not a) (not b))
(or (ite a b c) a (not c))
(or (not (not a)) (not a))
(or (not a) a)
This proof object has no antecedents.
Note: all axioms are propositional tautologies.
Note also that 'and' and 'or' can take multiple arguments.
You can recover the propositional tautologies by
unfolding the Boolean connectives in the axioms a small
bounded number of steps (=3).
*)
let is_def_axiom ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_AXIOM)
(**
Indicates whether the term is a proof for introduction of a name
<remarks>
Introduces a name for a formula/term.
Suppose e is an expression with free variables x, and def-intro
introduces the name n(x). The possible cases are:
When e is of Boolean type:
[def-intro]: (and (or n (not e)) (or (not n) e))
or:
[def-intro]: (or (not n) e)
when e only occurs positively.
When e is of the form (ite cond th el):
[def-intro]: (and (or (not cond) (= n th)) (or cond (= n el)))
Otherwise:
[def-intro]: (= n e)
*)
let is_def_intro ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_DEF_INTRO)
(**
Indicates whether the term is a proof for application of a definition
<remarks>
[apply-def T1]: F ~ n
F is 'equivalent' to n, given that T1 is a proof that
n is a name for F.
*)
let is_apply_def ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_APPLY_DEF)
(**
Indicates whether the term is a proof iff-oeq
<remarks>
T1: (iff p q)
[iff~ T1]: (~ p q)
*)
let is_iff_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_IFF_OEQ)
(**
Indicates whether the term is a proof for a positive NNF step
<remarks>
Proof for a (positive) NNF step. Example:
T1: (not s_1) ~ r_1
T2: (not s_2) ~ r_2
T3: s_1 ~ r_1'
T4: s_2 ~ r_2'
[nnf-pos T1 T2 T3 T4]: (~ (iff s_1 s_2)
(and (or r_1 r_2') (or r_1' r_2)))
The negation normal form steps NNF_POS and NNF_NEG are used in the following cases:
(a) When creating the NNF of a positive force quantifier.
The quantifier is retained (unless the bound variables are eliminated).
Example
T1: q ~ q_new
[nnf-pos T1]: (~ (forall (x T) q) (forall (x T) q_new))
(b) When recursively creating NNF over Boolean formulas, where the top-level
connective is changed during NNF conversion. The relevant Boolean connectives
for NNF_POS are 'implies', 'iff', 'xor', 'ite'.
NNF_NEG furthermore handles the case where negation is pushed
over Boolean connectives 'and' and 'or'.
*)
let is_nnf_pos ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_POS)
(**
Indicates whether the term is a proof for a negative NNF step
<remarks>
Proof for a (negative) NNF step. Examples:
T1: (not s_1) ~ r_1
...
Tn: (not s_n) ~ r_n
[nnf-neg T1 ... Tn]: (not (and s_1 ... s_n)) ~ (or r_1 ... r_n)
and
T1: (not s_1) ~ r_1
...
Tn: (not s_n) ~ r_n
[nnf-neg T1 ... Tn]: (not (or s_1 ... s_n)) ~ (and r_1 ... r_n)
and
T1: (not s_1) ~ r_1
T2: (not s_2) ~ r_2
T3: s_1 ~ r_1'
T4: s_2 ~ r_2'
[nnf-neg T1 T2 T3 T4]: (~ (not (iff s_1 s_2))
(and (or r_1 r_2) (or r_1' r_2')))
*)
let is_nnf_neg ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_NEG)
(**
Indicates whether the term is a proof for (~ P Q) here Q is in negation normal form.
<remarks>
A proof for (~ P Q) where Q is in negation normal form.
This proof object is only used if the parameter PROOF_MODE is 1.
This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO.
*)
let is_nnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_NNF_STAR)
(**
Indicates whether the term is a proof for (~ P Q) where Q is in conjunctive normal form.
<remarks>
A proof for (~ P Q) where Q is in conjunctive normal form.
This proof object is only used if the parameter PROOF_MODE is 1.
This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO.
*)
let is_cnf_star ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_CNF_STAR)
(**
Indicates whether the term is a proof for a Skolemization step
<remarks>
Proof for:
[sk]: (~ (not (forall ( x : expr ) (p ( x : expr ) y))) (not (p (sk y) y)))
[sk]: (~ (exists ( x : expr ) (p ( x : expr ) y)) (p (sk y) y))
This proof object has no antecedents.
*)
let is_skolemize ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_SKOLEMIZE)
(**
Indicates whether the term is a proof by modus ponens for equi-satisfiability.
<remarks>
Modus ponens style rule for equi-satisfiability.
T1: p
T2: (~ p q)
[mp~ T1 T2]: q
*)
let is_modus_ponens_oeq ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_MODUS_PONENS_OEQ)
(**
Indicates whether the term is a proof for theory lemma
<remarks>
Generic proof for theory lemmas.
The theory lemma function comes with one or more parameters.
The first parameter indicates the name of the theory.
For the theory of arithmetic, additional parameters provide hints for
checking the theory lemma.
The hints for arithmetic are:
- farkas - followed by rational coefficients. Multiply the coefficients to the
inequalities in the lemma, add the (negated) inequalities and obtain a contradiction.
- triangle-eq - Indicates a lemma related to the equivalence:
(iff (= t1 t2) (and (<= t1 t2) (<= t2 t1)))
- gcd-test - Indicates an integer linear arithmetic lemma that uses a gcd test.
*)
let is_theory_lemma ( x : expr ) = (FuncDecl.get_decl_kind (Expr.get_func_decl x) == OP_PR_TH_LEMMA)
end
(**
Parameter sets (of Solvers, Tactics, ...)
A Params objects represents a configuration in the form of symbol/value pairs.
*)
module Params =
struct
(**
Adds a parameter setting.
*)
let add_bool (p : params) (name : symbol) (value : bool) =
Z3native.params_set_bool p#gnc p#gno name#gno (int_of_lbool (if value then L_TRUE else L_FALSE))
(**
Adds a parameter setting.
*)
let add_int (p : params) (name : symbol) (value : int) =
Z3native.params_set_uint p#gnc p#gno name#gno value
(**
Adds a parameter setting.
*)
let add_double (p : params) (name : symbol) (value : float) =
Z3native.params_set_double p#gnc p#gno name#gno value
(**
Adds a parameter setting.
*)
let add_symbol (p : params) (name : symbol) (value : symbol) =
Z3native.params_set_symbol p#gnc p#gno name#gno value#gno
(**
Adds a parameter setting.
*)
let add_s_bool (p : params) (name : string) (value : bool) =
add_bool p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value
(**
Adds a parameter setting.
*)
let add_s_int (p : params) (name : string) (value : int) =
add_int p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value
(**
Adds a parameter setting.
*)
let add_s_double (p : params) (name : string) (value : float) =
add_double p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value
(**
Adds a parameter setting.
*)
let add_s_symbol (p : params) (name : string) (value : symbol) =
add_symbol p ((new symbol p#gc)#cnstr_obj (Z3native.mk_string_symbol p#gnc name)) value
(**
A string representation of the parameter set.
*)
let to_string (p : params) = Z3native.params_to_string p#gnc p#gno
end
(** ParamDescrs describe sets of parameters (of Solvers, Tactics, ...) *)
module ParamDescrs =
struct
(** Validate a set of parameters. *)
let validate ( x : param_descrs ) ( p : params )= Z3native.params_validate x#gnc p#gno x#gno
(** Retrieve kind of parameter. *)
let get_kind ( x : param_descrs ) ( name : symbol ) =
(param_kind_of_int (Z3native.param_descrs_get_kind x#gnc x#gno name#gno))
(** Retrieve all names of parameters. *)
let get_names ( x : param_descrs ) =
let n = Z3native.param_descrs_size x#gnc x#gno in
let f i = create_symbol x#gc (Z3native.param_descrs_get_name x#gnc x#gno i) in
Array.init n f
(** The size of the ParamDescrs. *)
let get_size ( x : param_descrs ) = Z3native.param_descrs_size x#gnc x#gno
(** Retrieves a string representation of the ParamDescrs. *)
let to_string ( x : param_descrs ) = Z3native.param_descrs_to_string x#gnc x#gno
end
(** Goals
A goal (aka problem). A goal is essentially a
of formulas, that can be solved and/or transformed using
tactics and solvers. *)
module Goal =
struct
(** The precision of the goal.
Goals can be transformed using over and under approximations.
An under approximation is applied when the objective is to find a model for a given goal.
An over approximation is applied when the objective is to find a proof for a given goal.
*)
let get_precision ( x : goal ) =
goal_prec_of_int (Z3native.goal_precision x#gnc x#gno)
(** Indicates whether the goal is precise. *)
let is_precise ( x : goal ) =
(get_precision x) == GOAL_PRECISE
(** Indicates whether the goal is an under-approximation. *)
let is_underapproximation ( x : goal ) =
(get_precision x) == GOAL_UNDER
(** Indicates whether the goal is an over-approximation. *)
let is_overapproximation ( x : goal ) =
(get_precision x) == GOAL_OVER
(** Indicates whether the goal is garbage (i.e., the product of over- and under-approximations). *)
let is_garbage ( x : goal ) =
(get_precision x) == GOAL_UNDER_OVER
(** Adds the constraints to the given goal. *)
(* CMW: assert seems to be a keyword. *)
let assert_ ( x : goal ) ( constraints : bool_expr array ) =
let f e = Z3native.goal_assert x#gnc x#gno e#gno in
Array.map f constraints
(** Indicates whether the goal contains `false'. *)
let is_inconsistent ( x : goal ) =
(lbool_of_int (Z3native.goal_inconsistent x#gnc x#gno)) == L_TRUE
(** The depth of the goal.
This tracks how many transformations were applied to it. *)
let get_depth ( x : goal ) = Z3native.goal_depth x#gnc x#gno
(** Erases all formulas from the given goal. *)
let reset ( x : goal ) = Z3native.goal_reset x#gnc x#gno
(** The number of formulas in the goal. *)
let get_size ( x : goal ) = Z3native.goal_size x#gnc x#gno
(** The formulas in the goal. *)
let get_formulas ( x : goal ) =
let n = get_size x in
let f i = (new bool_expr x#gc)#cnstr_obj (Z3native.goal_formula x#gnc x#gno i) in
Array.init n f
(** The number of formulas, subformulas and terms in the goal. *)
let get_num_exprs ( x : goal ) = Z3native.goal_num_exprs x#gnc x#gno
(** Indicates whether the goal is empty, and it is precise or the product of an under approximation. *)
let is_decided_sat ( x : goal ) =
(lbool_of_int (Z3native.goal_is_decided_sat x#gnc x#gno)) == L_TRUE
(** Indicates whether the goal contains `false', and it is precise or the product of an over approximation. *)
let is_decided_unsat ( x : goal ) =
(lbool_of_int (Z3native.goal_is_decided_unsat x#gnc x#gno)) == L_TRUE
(** Translates (copies) the Goal to the target Context <paramref name="to_ctx"/>. *)
let translate ( x : goal ) ( to_ctx : context ) =
(new goal to_ctx)#cnstr_obj (Z3native.goal_translate x#gnc x#gno to_ctx#gno)
(** Simplifies the goal. Essentially invokes the `simplify' tactic on the goal. *)
let simplify ( x : goal ) ( p : params option ) =
let tn = Z3native.mk_tactic x#gnc "simplify" in
Z3native.tactic_inc_ref x#gnc tn ;
let arn = match p with
| None -> Z3native.tactic_apply x#gnc tn x#gno
| Some(pn) -> Z3native.tactic_apply_ex x#gnc tn x#gno pn#gno
in
Z3native.apply_result_inc_ref x#gnc arn ;
let sg = Z3native.apply_result_get_num_subgoals x#gnc arn in
let res = if sg == 0 then
raise (Z3native.Exception "No subgoals")
else
Z3native.apply_result_get_subgoal x#gnc arn 0 in
Z3native.apply_result_dec_ref x#gnc arn ;
Z3native.tactic_dec_ref x#gnc tn ;
(new goal x#gc)#cnstr_obj res
(** A string representation of the Goal. *)
let to_string ( x : goal ) = Z3native.goal_to_string x#gnc x#gno
end
(** Tactics
Tactics are the basic building block for creating custom solvers for specific problem domains.
The complete list of tactics may be obtained using <c>Context.get_num_tactics</c>
and <c>Context.get_tactic_names</c>.
It may also be obtained using the command <c>(help-tactics)</c> in the SMT 2.0 front-end.
*)
module Tactic =
struct
(** A string containing a description of parameters accepted by the tactic. *)
let get_help ( x : tactic ) = Z3native.tactic_get_help x#gnc x#gno
(** Retrieves parameter descriptions for Tactics. *)
let get_param_descrs ( x : tactic ) =
(new param_descrs x#gc)#cnstr_obj (Z3native.tactic_get_param_descrs x#gnc x#gno)
(** Apply the tactic to the goal. *)
let apply ( x : tactic ) ( g : goal ) ( p : params option ) =
match p with
| None -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply x#gnc x#gno g#gno)
| Some (pn) -> (new apply_result x#gc)#cnstr_obj (Z3native.tactic_apply_ex x#gnc x#gno g#gno pn#gno)
(** creates a solver that is implemented using the given tactic.
<seealso cref="Context.MkSolver(Tactic)"/> *)
let get_solver ( x : tactic ) =
(new solver x#gc)#cnstr_obj (Z3native.mk_solver_from_tactic x#gnc x#gno)
end
(** Models
A Model contains interpretations (assignments) of constants and functions. *)
module Model =
struct
(** Function interpretations
A function interpretation is represented as a finite map and an 'else'.
Each entry in the finite map represents the value of a function given a set of arguments.
*)
module FuncInterp =
struct
(** Function interpretations entries
An Entry object represents an element in the finite map used to a function interpretation.
*)
module FuncEntry =
struct
(**
Return the (symbolic) value of this entry.
*)
let get_value ( x : func_entry ) =
create_expr x#gc (Z3native.func_entry_get_value x#gnc x#gno)
(**
The number of arguments of the entry.
*)
let get_num_args ( x : func_entry ) = Z3native.func_entry_get_num_args x#gnc x#gno
(**
The arguments of the function entry.
*)
let get_args ( x : func_entry ) =
let n = (get_num_args x) in
let f i = (create_expr x#gc (Z3native.func_entry_get_arg x#gnc x#gno i)) in
Array.init n f
(**
A string representation of the function entry.
*)
let to_string ( x : func_entry ) =
let a = (get_args x) in
let f c p = (p ^ (Expr.to_string c) ^ ", ") in
"[" ^ Array.fold_right f a ((Expr.to_string (get_value x)) ^ "]]")
end
(**
The number of entries in the function interpretation.
*)
let get_num_entries ( x: func_interp ) = Z3native.func_interp_get_num_entries x#gnc x#gno
(**
The entries in the function interpretation
*)
let get_entries ( x : func_interp ) =
let n = (get_num_entries x) in
let f i = ((new func_entry x#gc)#cnstr_obj (Z3native.func_interp_get_entry x#gnc x#gno i)) in
Array.init n f
(**
The (symbolic) `else' value of the function interpretation.
*)
let get_else ( x : func_interp ) = create_expr x#gc (Z3native.func_interp_get_else x#gnc x#gno)
(**
The arity of the function interpretation
*)
let get_arity ( x : func_interp ) = Z3native.func_interp_get_arity x#gnc x#gno
(**
A string representation of the function interpretation.
*)
let to_string ( x : func_interp ) =
let f c p = (
let n = (FuncEntry.get_num_args c) in
p ^
let g c p = (p ^ (Expr.to_string c) ^ ", ") in
(if n > 1 then "[" else "") ^
(Array.fold_right
g
(FuncEntry.get_args c)
((if n > 1 then "]" else "") ^ " -> " ^ (Expr.to_string (FuncEntry.get_value c)) ^ ", "))
) in
Array.fold_right f (get_entries x) ("else -> " ^ (Expr.to_string (get_else x)) ^ "]")
end
(** Retrieves the interpretation (the assignment) of <paramref name="f"/> in the model.
<param name="f">A function declaration of zero arity</param>
<returns>An expression if the function has an interpretation in the model, null otherwise.</returns> *)
let get_const_interp ( x : model ) ( f : func_decl ) =
if (FuncDecl.get_arity f) != 0 ||
(sort_kind_of_int (Z3native.get_sort_kind f#gnc (Z3native.get_range f#gnc f#gno))) == ARRAY_SORT then
raise (Z3native.Exception "Non-zero arity functions and arrays have FunctionInterpretations as a model. Use FuncInterp.")
else
let np = Z3native.model_get_const_interp x#gnc x#gno f#gno in
if (Z3native.is_null np) then
None
else
Some (create_expr x#gc np)
(** Retrieves the interpretation (the assignment) of <paramref name="a"/> in the model.
<param name="a">A Constant</param>
<returns>An expression if the constant has an interpretation in the model, null otherwise.</returns>
*)
let get_const_interp_e ( x : model ) ( a : expr ) = get_const_interp x (Expr.get_func_decl a)
(** Retrieves the interpretation (the assignment) of a non-constant <paramref name="f"/> in the model.
<param name="f">A function declaration of non-zero arity</param>
<returns>A FunctionInterpretation if the function has an interpretation in the model, null otherwise.</returns> *)
let rec get_func_interp ( x : model ) ( f : func_decl ) =
let sk = (sort_kind_of_int (Z3native.get_sort_kind x#gnc (Z3native.get_range f#gnc f#gno))) in
if (FuncDecl.get_arity f) == 0 then
let n = Z3native.model_get_const_interp x#gnc x#gno f#gno in
if (Z3native.is_null n) then
None
else
match sk with
| ARRAY_SORT ->
if (lbool_of_int (Z3native.is_as_array x#gnc n)) == L_FALSE then
raise (Z3native.Exception "Argument was not an array constant")
else
let fd = Z3native.get_as_array_func_decl x#gnc n in
get_func_interp x ((new func_decl f#gc)#cnstr_obj fd)
| _ -> raise (Z3native.Exception "Constant functions do not have a function interpretation; use ConstInterp");
else
let n = (Z3native.model_get_func_interp x#gnc x#gno f#gno) in
if (Z3native.is_null n) then None else Some ((new func_interp x#gc)#cnstr_obj n)
(** The number of constants that have an interpretation in the model. *)
let get_num_consts ( x : model ) = Z3native.model_get_num_consts x#gnc x#gno
(** The function declarations of the constants in the model. *)
let get_const_decls ( x : model ) =
let n = (get_num_consts x) in
let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in
Array.init n f
(** The number of function interpretations in the model. *)
let get_num_funcs ( x : model ) = Z3native.model_get_num_funcs x#gnc x#gno
(** The function declarations of the function interpretations in the model. *)
let get_func_decls ( x : model ) =
let n = (get_num_consts x) in
let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in
Array.init n f
(** All symbols that have an interpretation in the model. *)
let get_decls ( x : model ) =
let n_funcs = (get_num_funcs x) in
let n_consts = (get_num_consts x ) in
let f i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_func_decl x#gnc x#gno i) in
let g i = (new func_decl x#gc)#cnstr_obj (Z3native.model_get_const_decl x#gnc x#gno i) in
Array.append (Array.init n_funcs f) (Array.init n_consts g)
(** A ModelEvaluationFailedException is thrown when an expression cannot be evaluated by the model. *)
exception ModelEvaluationFailedException of string
(**
Evaluates the expression <paramref name="t"/> in the current model.
<remarks>
This function may fail if <paramref name="t"/> contains quantifiers,
is partial (MODEL_PARTIAL enabled), or if <paramref name="t"/> is not well-sorted.
In this case a <c>ModelEvaluationFailedException</c> is thrown.
<param name="t">An expression</param>
<param name="completion">
When this flag is enabled, a model value will be assigned to any constant
or function that does not have an interpretation in the model.
</param>
<returns>The evaluation of <paramref name="t"/> in the model.</returns>
*)
let eval ( x : model ) ( t : expr ) ( completion : bool ) =
let (r, v) = (Z3native.model_eval x#gnc x#gno t#gno (int_of_lbool (if completion then L_TRUE else L_FALSE))) in
if (lbool_of_int r) == L_FALSE then
raise (ModelEvaluationFailedException "evaluation failed")
else
create_expr x#gc v
(** Alias for <c>eval</c>. *)
let evaluate ( x : model ) ( t : expr ) ( completion : bool ) =
eval x t completion
(** The number of uninterpreted sorts that the model has an interpretation for. *)
let get_num_sorts ( x : model ) = Z3native.model_get_num_sorts x#gnc x#gno
(** The uninterpreted sorts that the model has an interpretation for.
<remarks>
Z3 also provides an intepretation for uninterpreted sorts used in a formula.
The interpretation for a sort is a finite set of distinct values. We say this finite set is
the "universe" of the sort.
<seealso cref="NumSorts"/>
<seealso cref="SortUniverse"/>
*)
let get_sorts ( x : model ) =
let n = (get_num_sorts x) in
let f i = (create_sort x#gc (Z3native.model_get_sort x#gnc x#gno i)) in
Array.init n f
(** The finite set of distinct values that represent the interpretation for sort <paramref name="s"/>.
<seealso cref="Sorts"/>
<param name="s">An uninterpreted sort</param>
<returns>An array of expressions, where each is an element of the universe of <paramref name="s"/></returns>
*)
let sort_universe ( x : model ) ( s : sort ) =
let n_univ = (new ast_vector x#gc)#cnstr_obj (Z3native.model_get_sort_universe x#gnc x#gno s#gno) in
let n = (AST.ASTVector.get_size n_univ) in
let f i = (AST.ASTVector.get n_univ i) in
Array.init n f
(** Conversion of models to strings.
<returns>A string representation of the model.</returns>
*)
let to_string ( x : model ) = Z3native.model_to_string x#gnc x#gno
end
(** Tactic application results
ApplyResult objects represent the result of an application of a
tactic to a goal. It contains the subgoals that were produced. *)
module ApplyResult =
struct
(** The number of Subgoals. *)
let get_num_subgoals ( x : apply_result ) =
Z3native.apply_result_get_num_subgoals x#gnc x#gno
(** Retrieves the subgoals from the apply_result. *)
let get_subgoals ( x : apply_result ) =
let n = (get_num_subgoals x) in
let f i = (new goal x#gc)#cnstr_obj (Z3native.apply_result_get_subgoal x#gnc x#gno i) in
Array.init n f
(** Convert a model for the subgoal <paramref name="i"/> into a model for the original
goal <c>g</c>, that the ApplyResult was obtained from.
#return A model for <c>g</c>
*)
let convert_model ( x : apply_result ) ( i : int ) ( m : model ) =
(new model x#gc)#cnstr_obj (Z3native.apply_result_convert_model x#gnc x#gno i m#gno)
(** A string representation of the ApplyResult. *)
let to_string ( x : apply_result) = Z3native.apply_result_to_string x#gnc x#gno
end
(** Solvers *)
module Solver =
struct
type status = UNSATISFIABLE | UNKNOWN | SATISFIABLE
(** Objects that track statistical information about solvers. *)
module Statistics =
struct
(**
Statistical data is organized into pairs of [Key, Entry], where every
Entry is either a <c>DoubleEntry</c> or a <c>UIntEntry</c>
*)
module Entry =
struct
(** The key of the entry. *)
let get_key (x : statistics_entry) = x#key
(** The int-value of the entry. *)
let get_int (x : statistics_entry) = x#int
(** The float-value of the entry. *)
let get_float (x : statistics_entry) = x#float
(** True if the entry is uint-valued. *)
let is_int (x : statistics_entry) = x#is_int
(** True if the entry is double-valued. *)
let is_float (x : statistics_entry) = x#is_float
(** The string representation of the the entry's value. *)
let to_string_value (x : statistics_entry) =
if (is_int x) then
string_of_int (get_int x)
else if (is_float x) then
string_of_float (get_float x)
else
raise (Z3native.Exception "Unknown statistical entry type")
(** The string representation of the entry (key and value) *)
let to_string ( x : statistics_entry ) = (get_key x) ^ ": " ^ (to_string_value x)
end
(** A string representation of the statistical data. *)
let to_string ( x : statistics ) = Z3native.stats_to_string x#gnc x#gno
(** The number of statistical data. *)
let get_size ( x : statistics ) = Z3native.stats_size x#gnc x#gno
(** The data entries. *)
let get_entries ( x : statistics ) =
let n = (get_size x ) in
let f i = (
let k = Z3native.stats_get_key x#gnc x#gno i in
if (lbool_of_int (Z3native.stats_is_uint x#gnc x#gno i)) == L_TRUE then
((new statistics_entry)#cnstr_si k (Z3native.stats_get_uint_value x#gnc x#gno i))
else
((new statistics_entry)#cnstr_sd k (Z3native.stats_get_double_value x#gnc x#gno i))
) in
Array.init n f
(**
The statistical counters.
*)
let get_keys ( x : statistics ) =
let n = (get_size x) in
let f i = (Z3native.stats_get_key x#gnc x#gno i) in
Array.init n f
(**
The value of a particular statistical counter.
*)
let get ( x : statistics ) ( key : string ) =
let f p c = (if (Entry.get_key c) = key then (Some c) else p) in
Array.fold_left f None (get_entries x)
end
(**
A string that describes all available solver parameters.
*)
let get_help ( x : solver ) = Z3native.solver_get_help x#gnc x#gno
(**
Sets the solver parameters.
*)
let set_parameters ( x : solver ) ( value : params )=
Z3native.solver_set_params x#gnc x#gno value#gno
(**
Retrieves parameter descriptions for solver.
*)
let get_param_descrs ( x : solver ) =
(new param_descrs x#gc)#cnstr_obj (Z3native.solver_get_param_descrs x#gnc x#gno)
(**
The current number of backtracking points (scopes).
<seealso cref="Pop"/>
<seealso cref="Push"/>
*)
let get_num_scopes ( x : solver ) = Z3native.solver_get_num_scopes x#gnc x#gno
(**
Creates a backtracking point.
<seealso cref="Pop"/>
*)
let push ( x : solver ) = Z3native.solver_push x#gnc x#gno
(**
Backtracks <paramref name="n"/> backtracking points.
<remarks>Note that an exception is thrown if <paramref name="n"/> is not smaller than <c>NumScopes</c>
<seealso cref="Push"/>
*)
let pop ( x : solver ) ( n : int ) = Z3native.solver_pop x#gnc x#gno n
(**
Resets the Solver.
<remarks>This removes all assertions from the solver.
*)
let reset ( x : solver ) = Z3native.solver_reset x#gnc x#gno
(**
Assert a constraint (or multiple) into the solver.
*)
let assert_ ( x : solver ) ( constraints : bool_expr array ) =
let f e = (Z3native.solver_assert x#gnc x#gno e#gno) in
Array.map f constraints
(**
The number of assertions in the solver.
*)
let get_num_assertions ( x : solver ) =
let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in
(AST.ASTVector.get_size a)
(**
The set of asserted formulas.
*)
let get_assertions ( x : solver ) =
let a = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_assertions x#gnc x#gno) in
let n = (AST.ASTVector.get_size a) in
let f i = ((new bool_expr x#gc)#cnstr_obj (AST.ASTVector.get a i)#gno) in
Array.init n f
(**
Checks whether the assertions in the solver are consistent or not.
<remarks>
<seealso cref="Model"/>
<seealso cref="UnsatCore"/>
<seealso cref="Proof"/>
*)
let check ( x : solver ) ( assumptions : bool_expr array option) =
let r =
match assumptions with
| None -> lbool_of_int (Z3native.solver_check x#gnc x#gno)
| Some (ass) -> lbool_of_int (Z3native.solver_check_assumptions x#gnc x#gno (Array.length ass) (astaton ass))
in
match r with
| L_TRUE -> SATISFIABLE
| L_FALSE -> UNSATISFIABLE
| _ -> UNKNOWN
(**
The model of the last <c>Check</c>.
<remarks>
The result is <c>None</c> if <c>Check</c> was not invoked before,
if its results was not <c>SATISFIABLE</c>, or if model production is not enabled.
*)
let get_model ( x : solver ) =
let q = Z3native.solver_get_model x#gnc x#gno in
if (Z3native.is_null q) then
None
else
Some ((new model x#gc)#cnstr_obj q)
(**
The proof of the last <c>Check</c>.
<remarks>
The result is <c>null</c> if <c>Check</c> was not invoked before,
if its results was not <c>UNSATISFIABLE</c>, or if proof production is disabled.
*)
let get_proof ( x : solver ) =
let q = Z3native.solver_get_proof x#gnc x#gno in
if (Z3native.is_null q) then
None
else
Some (create_expr x#gc q)
(**
The unsat core of the last <c>Check</c>.
<remarks>
The unsat core is a subset of <c>Assertions</c>
The result is empty if <c>Check</c> was not invoked before,
if its results was not <c>UNSATISFIABLE</c>, or if core production is disabled.
*)
let get_unsat_core ( x : solver ) =
let cn = (new ast_vector x#gc)#cnstr_obj (Z3native.solver_get_unsat_core x#gnc x#gno) in
let n = (AST.ASTVector.get_size cn) in
let f i = (AST.ASTVector.get cn i) in
Array.init n f
(**
A brief justification of why the last call to <c>Check</c> returned <c>UNKNOWN</c>.
*)
let get_reason_unknown ( x : solver ) = Z3native.solver_get_reason_unknown x#gnc x#gno
(**
Solver statistics.
*)
let get_statistics ( x : solver ) =
(new statistics x#gc)#cnstr_obj (Z3native.solver_get_statistics x#gnc x#gno)
(**
A string representation of the solver.
*)
let to_string ( x : solver ) = Z3native.solver_to_string x#gnc x#gno
end
(** Probes
Probes are used to inspect a goal (aka problem) and collect information that may be used to decide
which solver and/or preprocessing step will be used.
The complete list of probes may be obtained using the procedures <c>Context.NumProbes</c>
and <c>Context.ProbeNames</c>.
It may also be obtained using the command <c>(help-tactics)</c> in the SMT 2.0 front-end.
*)
module Probe =
struct
(**
Execute the probe over the goal.
<returns>A probe always produce a double value.
"Boolean" probes return 0.0 for false, and a value different from 0.0 for true.</returns>
*)
let apply ( x : probe ) (g : goal) =
Z3native.probe_apply x#gnc x#gno g#gno
end
(* STUFF FROM THE CONTEXT *)
(**
(* OPTIONS *)
(**
Selects the format used for pretty-printing expressions.
<remarks>
The default mode for pretty printing expressions is to produce
SMT-LIB style output where common subexpressions are printed
at each occurrence. The mode is called Z3_PRINT_SMTLIB_FULL.
To print shared common subexpressions only once,
use the Z3_PRINT_LOW_LEVEL mode.
To print in way that conforms to SMT-LIB standards and uses let
expressions to share common sub-expressions use Z3_PRINT_SMTLIB_COMPLIANT.
*)
<seealso cref="AST.ToString ( ctx : context ) ="/>
<seealso cref="Pattern.ToString ( ctx : context ) ="/>
<seealso cref="FuncDecl.ToString ( ctx : context ) ="/>
<seealso cref="Sort.ToString ( ctx : context ) ="/>
public Z3_ast_print_mode PrintMode
set { Z3native.set_ast_print_mode ctx#gno (uint)value); }
(* SMT Files & Strings *)
(**
Convert a benchmark into an SMT-LIB formatted string.
*)
@param name Name of the benchmark. The argument is optional.
@param logic The benchmark logic.
@param status The status string (sat, unsat, or unknown)
@param attributes Other attributes, such as source, difficulty or category.
@param assumptions Auxiliary assumptions.
@param formula Formula to be checked for consistency in conjunction with assumptions.
@return A string representation of the benchmark.
public string BenchmarkToSMTString(string name, string logic, string status, string attributes,
BoolExpr[] assumptions, BoolExpr formula)
Z3native.benchmark_to_smtlib_string ctx#gno name, logic, status, attributes,
(uint)assumptions.Length, AST.ArrayToNative(assumptions),
formula#gno);
(**
Parse the given string using the SMT-LIB parser.
<remarks>
The symbol table of the parser can be initialized using the given sorts and declarations.
The symbols in the arrays <paramref name="sortNames"/> and <paramref name="declNames"/>
don't need to match the names of the sorts and declarations in the arrays <paramref name="sorts"/>
and <paramref name="decls"/>. This is a useful feature since we can use arbitrary names to
reference sorts and declarations.
*)
public void ParseSMTLIBString(string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null)
uint csn = Symbol.ArrayLength(sortNames);
uint cs = Sort.ArrayLength(sorts);
uint cdn = Symbol.ArrayLength(declNames);
uint cd = AST.ArrayLength(decls);
if (csn != cs || cdn != cd)
throw new Z3Exception("Argument size mismatch");
Z3native.parse_smtlib_string ctx#gno str,
AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts),
AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)
(**
Parse the given file using the SMT-LIB parser.
*)
<seealso cref="ParseSMTLIBString"/>
public void ParseSMTLIBFile(string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null)
uint csn = Symbol.ArrayLength(sortNames);
uint cs = Sort.ArrayLength(sorts);
uint cdn = Symbol.ArrayLength(declNames);
uint cd = AST.ArrayLength(decls);
if (csn != cs || cdn != cd)
throw new Z3Exception("Argument size mismatch");
Z3native.parse_smtlib_file ctx#gno fileName,
AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts),
AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls)
(**
The number of SMTLIB formulas parsed by the last call to <c>ParseSMTLIBString</c> or <c>ParseSMTLIBFile</c>.
*)
public uint NumSMTLIBFormulas { get {Z3native.get_smtlib_num_formulas ctx#gno))
(**
The formulas parsed by the last call to <c>ParseSMTLIBString</c> or <c>ParseSMTLIBFile</c>.
*)
let[] SMTLIBFormulas
get
uint n = NumSMTLIBFormulas;
BoolExpr[] res = new BoolExpr[n];
for (uint i = 0; i < n; i++)
res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_formula ctx#gno i)
res;
(**
The number of SMTLIB assumptions parsed by the last call to <c>ParseSMTLIBString</c> or <c>ParseSMTLIBFile</c>.
*)
public uint NumSMTLIBAssumptions { get {Z3native.get_smtlib_num_assumptions ctx#gno))
(**
The assumptions parsed by the last call to <c>ParseSMTLIBString</c> or <c>ParseSMTLIBFile</c>.
*)
let[] SMTLIBAssumptions
get
uint n = NumSMTLIBAssumptions;
BoolExpr[] res = new BoolExpr[n];
for (uint i = 0; i < n; i++)
res[i] = (BoolExpr)create_expr ctx (Z3native.get_smtlib_assumption ctx#gno i)
res;
(**
The number of SMTLIB declarations parsed by the last call to <c>ParseSMTLIBString</c> or <c>ParseSMTLIBFile</c>.
*)
public uint NumSMTLIBDecls { get {Z3native.get_smtlib_num_decls ctx#gno))
(**
The declarations parsed by the last call to <c>ParseSMTLIBString</c> or <c>ParseSMTLIBFile</c>.
*)
public Func_Decl[] SMTLIBDecls
get
uint n = NumSMTLIBDecls;
Func_Decl[] res = new Func_Decl[n];
for (uint i = 0; i < n; i++)
res[i] = new Func_Decl(this, Z3native.get_smtlib_decl ctx#gno i)
res;
(**
The number of SMTLIB sorts parsed by the last call to <c>ParseSMTLIBString</c> or <c>ParseSMTLIBFile</c>.
*)
public uint NumSMTLIBSorts { get {Z3native.get_smtlib_num_sorts ctx#gno))
(**
The declarations parsed by the last call to <c>ParseSMTLIBString</c> or <c>ParseSMTLIBFile</c>.
*)
public Sort[] SMTLIBSorts
get
uint n = NumSMTLIBSorts;
Sort[] res = new Sort[n];
for (uint i = 0; i < n; i++)
res[i] = Sort.Create(this, Z3native.get_smtlib_sort ctx#gno i)
res;
(**
Parse the given string using the SMT-LIB2 parser.
*)
<seealso cref="ParseSMTLIBString"/>
@return A conjunction of assertions in the scope (up to push/pop) at the end of the string.
let ParseSMTLIB2String ( ctx : context ) string str, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null)
uint csn = Symbol.ArrayLength(sortNames);
uint cs = Sort.ArrayLength(sorts);
uint cdn = Symbol.ArrayLength(declNames);
uint cd = AST.ArrayLength(decls);
if (csn != cs || cdn != cd)
throw new Z3Exception("Argument size mismatch");
(BoolExpr)create_expr ctx (Z3native.parse_smtlib2_string ctx#gno str,
AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts),
AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))
(**
Parse the given file using the SMT-LIB2 parser.
*)
<seealso cref="ParseSMTLIB2String"/>
let ParseSMTLIB2File ( ctx : context ) string fileName, Symbol[] sortNames = null, Sort[] sorts = null, Symbol[] declNames = null, Func_Decl[] decls = null)
uint csn = Symbol.ArrayLength(sortNames);
uint cs = Sort.ArrayLength(sorts);
uint cdn = Symbol.ArrayLength(declNames);
uint cd = AST.ArrayLength(decls);
if (csn != cs || cdn != cd)
throw new Z3Exception("Argument size mismatch");
(BoolExpr)create_expr ctx (Z3native.parse_smtlib2_file ctx#gno fileName,
AST.ArrayLength(sorts), Symbol.ArrayToNative(sortNames), AST.ArrayToNative(sorts),
AST.ArrayLength(decls), Symbol.ArrayToNative(declNames), AST.ArrayToNative(decls))
(* GOALS *)
(**
Creates a new Goal.
<remarks>
Note that the Context must have been created with proof generation support if
<paramref name="proofs"/> is set to true here.
*)
@param models Indicates whether model generation should be enabled.
@param unsatCores Indicates whether unsat core generation should be enabled.
@param proofs Indicates whether proof generation should be enabled.
public Goal MkGoal(bool models = true, bool unsatCores = false, bool proofs = false)
new Goal(this, models, unsatCores, proofs);
(* PARAMETERSETS *)
(**
Creates a new ParameterSet.
*)
public Params MkParams ( ctx : context ) =
new Params(this);
(* TACTICS *)
(**
The number of supported tactics.
*)
public uint NumTactics
get {Z3native.get_num_tactics ctx#gno); }
(**
The names of all supported tactics.
*)
public string[] TacticNames
get
uint n = NumTactics;
string[] res = new string[n];
for (uint i = 0; i < n; i++)
res[i] = Z3native.get_tactic_name ctx#gno i);
res;
(**
Returns a string containing a description of the tactic with the given name.
*)
public string TacticDescription(string name)
Z3native.tactic_get_descr ctx#gno name);
(**
Creates a new Tactic.
*)
public Tactic MkTactic(string name)
new Tactic(this, name);
(**
Create a tactic that applies <paramref name="t1"/> to a Goal and
then <paramref name="t2"/> to every subgoal produced by <paramref name="t1"/>.
*)
public Tactic AndThen(Tactic t1, Tactic t2, params Tactic[] ts)
IntPtr last = IntPtr.Zero;
if (ts != null && ts.Length > 0)
last = ts[ts.Length - 1]#gno;
for (int i = ts.Length - 2; i >= 0; i--)
last = Z3native.tactic_and_then ctx#gno ts[i]#gno last);
if (last != IntPtr.Zero)
last = Z3native.tactic_and_then ctx#gno t2#gno last);
new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno last)
else
new Tactic(this, Z3native.tactic_and_then ctx#gno t1#gno t2#gno)
(**
Create a tactic that applies <paramref name="t1"/> to a Goal and
then <paramref name="t2"/> to every subgoal produced by <paramref name="t1"/>.
<remarks>
Shorthand for <c>AndThen</c>.
*)
public Tactic Then(Tactic t1, Tactic t2, params Tactic[] ts)
AndThen(t1, t2, ts);
(**
Create a tactic that first applies <paramref name="t1"/> to a Goal and
if it fails then returns the result of <paramref name="t2"/> applied to the Goal.
*)
public Tactic OrElse(Tactic t1, Tactic t2)
new Tactic(this, Z3native.tactic_or_else ctx#gno t1#gno t2#gno)
(**
Create a tactic that applies <paramref name="t"/> to a goal for <paramref name="ms"/> milliseconds.
<remarks>
If <paramref name="t"/> does not terminate within <paramref name="ms"/> milliseconds, then it fails.
*)
public Tactic TryFor(Tactic t, uint ms)
new Tactic(this, Z3native.tactic_try_for ctx#gno t#gno ms)
(**
Create a tactic that applies <paramref name="t"/> to a given goal if the probe
<paramref name="p"/> evaluates to true.
<remarks>
If <paramref name="p"/> evaluates to false, then the new tactic behaves like the <c>skip</c> tactic.
*)
public Tactic When(Probe p, Tactic t)
new Tactic(this, Z3native.tactic_when ctx#gno p#gno t#gno)
(**
Create a tactic that applies <paramref name="t1"/> to a given goal if the probe
<paramref name="p"/> evaluates to true and <paramref name="t2"/> otherwise.
*)
public Tactic Cond(Probe p, Tactic t1, Tactic t2)
new Tactic(this, Z3native.tactic_cond ctx#gno p#gno t1#gno t2#gno)
(**
Create a tactic that keeps applying <paramref name="t"/> until the goal is not
modified anymore or the maximum number of iterations <paramref name="max"/> is reached.
*)
public Tactic Repeat(Tactic t, uint max = uint.MaxValue)
new Tactic(this, Z3native.tactic_repeat ctx#gno t#gno max)
(**
Create a tactic that just returns the given goal.
*)
public Tactic Skip ( ctx : context ) =
new Tactic(this, Z3native.tactic_skip ctx#gno)
(**
Create a tactic always fails.
*)
public Tactic Fail ( ctx : context ) =
new Tactic(this, Z3native.tactic_fail ctx#gno)
(**
Create a tactic that fails if the probe <paramref name="p"/> evaluates to false.
*)
public Tactic FailIf(Probe p)
new Tactic(this, Z3native.tactic_fail_if ctx#gno p#gno)
(**
Create a tactic that fails if the goal is not triviall satisfiable (i.e., empty)
or trivially unsatisfiable (i.e., contains `false').
*)
public Tactic FailIfNotDecided ( ctx : context ) =
new Tactic(this, Z3native.tactic_fail_if_not_decided ctx#gno)
(**
Create a tactic that applies <paramref name="t"/> using the given set of parameters <paramref name="p"/>.
*)
public Tactic UsingParams(Tactic t, Params p)
new Tactic(this, Z3native.tactic_using_params ctx#gno t#gno p#gno)
(**
Create a tactic that applies <paramref name="t"/> using the given set of parameters <paramref name="p"/>.
<remarks>Alias for <c>UsingParams</c>*)
public Tactic With(Tactic t, Params p)
UsingParams(t, p);
(**
Create a tactic that applies the given tactics in parallel.
*)
public Tactic ParOr(params Tactic[] t)
new Tactic(this, Z3native.tactic_par_or ctx#gno Tactic.ArrayLength(t), Tactic.ArrayToNative(t))
(**
Create a tactic that applies <paramref name="t1"/> to a given goal and then <paramref name="t2"/>
to every subgoal produced by <paramref name="t1"/>. The subgoals are processed in parallel.
*)
public Tactic ParAndThen(Tactic t1, Tactic t2)
new Tactic(this, Z3native.tactic_par_and_then ctx#gno t1#gno t2#gno)
(**
Interrupt the execution of a Z3 procedure.
*)
<remarks>This procedure can be used to interrupt: solvers, simplifiers and tactics.
public void Interrupt ( ctx : context ) =
Z3native.interrupt ctx#gno);
(* PROBES *)
(**
The number of supported Probes.
*)
public uint NumProbes
get {Z3native.get_num_probes ctx#gno); }
(**
The names of all supported Probes.
*)
public string[] ProbeNames
get
uint n = NumProbes;
string[] res = new string[n];
for (uint i = 0; i < n; i++)
res[i] = Z3native.get_probe_name ctx#gno i);
res;
(**
Returns a string containing a description of the probe with the given name.
*)
public string ProbeDescription(string name)
Z3native.probe_get_descr ctx#gno name);
(**
Creates a new Probe.
*)
public Probe MkProbe(string name)
new Probe(this, name);
(**
Create a probe that always evaluates to <paramref name="val"/>.
*)
public Probe Const(double val)
new Probe(this, Z3native.probe_const ctx#gno val)
(**
Create a probe that evaluates to "true" when the value returned by <paramref name="p1"/>
is less than the value returned by <paramref name="p2"/>
*)
public Probe Lt(Probe p1, Probe p2)
new Probe(this, Z3native.probe_lt ctx#gno p1#gno p2#gno)
(**
Create a probe that evaluates to "true" when the value returned by <paramref name="p1"/>
is greater than the value returned by <paramref name="p2"/>
*)
public Probe Gt(Probe p1, Probe p2)
new Probe(this, Z3native.probe_gt ctx#gno p1#gno p2#gno)
(**
Create a probe that evaluates to "true" when the value returned by <paramref name="p1"/>
is less than or equal the value returned by <paramref name="p2"/>
*)
public Probe Le(Probe p1, Probe p2)
new Probe(this, Z3native.probe_le ctx#gno p1#gno p2#gno)
(**
Create a probe that evaluates to "true" when the value returned by <paramref name="p1"/>
is greater than or equal the value returned by <paramref name="p2"/>
*)
public Probe Ge(Probe p1, Probe p2)
new Probe(this, Z3native.probe_ge ctx#gno p1#gno p2#gno)
(**
Create a probe that evaluates to "true" when the value returned by <paramref name="p1"/>
is equal to the value returned by <paramref name="p2"/>
*)
public Probe Eq(Probe p1, Probe p2)
new Probe(this, Z3native.probe_eq ctx#gno p1#gno p2#gno)
(**
Create a probe that evaluates to "true" when the value <paramref name="p1"/>
and <paramref name="p2"/> evaluate to "true".
*)
public Probe And(Probe p1, Probe p2)
new Probe(this, Z3native.probe_and ctx#gno p1#gno p2#gno)
(**
Create a probe that evaluates to "true" when the value <paramref name="p1"/>
or <paramref name="p2"/> evaluate to "true".
*)
public Probe Or(Probe p1, Probe p2)
new Probe(this, Z3native.probe_or ctx#gno p1#gno p2#gno)
(**
Create a probe that evaluates to "true" when the value <paramref name="p"/>
does not evaluate to "true".
*)
public Probe Not(Probe p)
new Probe(this, Z3native.probe_not ctx#gno p#gno)
(* SOLVERS *)
(**
Creates a new (incremental) solver.
<remarks>
This solver also uses a set of builtin tactics for handling the first
check-sat command, and check-sat commands that take more than a given
number of milliseconds to be solved.
*)
public Solver MkSolver(Symbol logic = null)
if (logic == null)
new Solver(this, Z3native.mk_solver ctx#gno)
else
new Solver(this, Z3native.mk_solver_for_logic ctx#gno logic#gno)
(**
Creates a new (incremental) solver.
*)
<seealso cref="MkSolver(Symbol)"/>
public Solver MkSolver(string logic)
MkSolver(MkSymbol(logic)
(**
Creates a new (incremental) solver.
*)
let mk_Simple_Solver( ctx : context ) ctx : context ) =
new Solver(this, Z3native.mk_simple_solver ctx#gno)
(**
Creates a solver that is implemented using the given tactic.
<remarks>
The solver supports the commands <c>Push</c> and <c>Pop</c>, but it
will always solve each check from scratch.
*)
public Solver MkSolver(Tactic t)
new Solver(this, Z3native.mk_solver_from_tactic ctx#gno t#gno)
(* FIXEDPOINTS *)
(**
Create a Fixedpoint context.
*)
public Fixedpoint MkFixedpoint ( ctx : context ) =
new Fixedpoint(this);
(* MISCELLANEOUS *)
(**
Wraps an AST.
*)
<remarks>This function is used for transitions between native and
managed objects. Note that <paramref name="nativeObject"/> must be a
native object obtained from Z3 (e.g., through <seealso cref="UnwrapAST"/>)
and that it must have a correct reference count (see e.g.,
<seealso cref="Z3native.inc_ref"/>.
<seealso cref="UnwrapAST"/>
@param nativeObject The native pointer to wrap.
public AST WrapAST(IntPtr nativeObject)
AST.Create(this, nativeObject);
(**
Unwraps an AST.
*)
<remarks>This function is used for transitions between native and
managed objects. It returns the native pointer to the AST. Note that
AST objects are reference counted and unwrapping an AST disables automatic
reference counting, i.e., all references to the IntPtr that is returned
must be handled externally and through native calls (see e.g.,
<seealso cref="Z3native.inc_ref"/>).
<seealso cref="WrapAST"/>
@param a The AST to unwrap.
public IntPtr UnwrapAST(AST a)
a#gno;
(**
a string describing all available parameters to <c>Expr.Simplify</c>.
*)
public string SimplifyHelp ( ctx : context ) =
Z3native.simplify_get_help ctx#gno);
(**
Retrieves parameter descriptions for simplifier.
*)
public ParamDescrs SimplifyParameterDescriptions
get {new ParamDescrs(this, Z3native.simplify_get_param_descrs ctx#gno)); }
(**
Enable/disable printing of warning messages to the console.
*)
<remarks>Note that this function is static and effects the behaviour of
all contexts globally.
public static void ToggleWarningMessages(bool enabled)
Z3native.toggle_warning_messages((enabled) ? 1 : 0);
(* ERROR HANDLING *)
(**
A delegate which is executed when an error is raised.
<remarks>
Note that it is possible for memory leaks to occur if error handlers
throw exceptions.
*)
public delegate void ErrorHandler(Context ctx, Z3_error_code errorCode, string errorString);
(**
The OnError event.
*)
public event ErrorHandler OnError = null;
(* PARAMETERS *)
(**
Update a mutable configuration parameter.
<remarks>
The list of all configuration parameters can be obtained using the Z3 executable:
<c>z3.exe -ini?</c>
Only a few configuration parameters are mutable once the context is created.
An exception is thrown when trying to modify an immutable parameter.
*)
<seealso cref="GetParamValue"/>
public void UpdateParamValue(string id, string value)
Z3native.update_param_value ctx#gno id, value);
(**
Get a configuration parameter.
<remarks>
Returns null if the parameter value does not exist.
<seealso cref="UpdateParamValue"/>
*)
public string GetParamValue(string id)
IntPtr res = IntPtr.Zero;
int r = Z3native.get_param_value ctx#gno id, out res);
if (r == (int)Z3_lbool.L_FALSE)
null;
else
Marshal.PtrToStringAnsi(res);
(* INTERNAL *)
internal IntPtr m_ctx = IntPtr.Zero;
internal Z3native.error_handler m_n_err_handler = null;
internal IntPtr nCtx { get {m_ctx)
internal void NativeErrorHandler(IntPtr ctx, Z3_error_code errorCode)
Do-nothing error handler. The wrappers in Z3.Native will throw exceptions upon errors.
internal void InitContext ( ctx : context ) =
PrintMode = Z3_ast_print_mode.Z3_PRINT_SMTLIB2_COMPLIANT;
m_n_err_handler = new Z3native.error_handler(NativeErrorHandler); keep reference so it doesn't get collected.
Z3native.set_error_handler(m_ctx, m_n_err_handler);
GC.SuppressFinalize(this);
*)