From 4ec4151e8210aee2af21ef21d5bb9332d36a20ab Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Mon, 3 Dec 2012 03:50:28 +0000 Subject: [PATCH 01/60] Change treatment of unsigned to avoid depending on unspecified behavior of recursive macros --- src/api/ml/build.sed | 6 +++--- src/api/ml/z3.idl | 5 ----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/api/ml/build.sed b/src/api/ml/build.sed index e4434a5a1..d53a13713 100644 --- a/src/api/ml/build.sed +++ b/src/api/ml/build.sed @@ -1,7 +1,7 @@ # attempt to clean up the mess with 'unsigned' -s/__in unsigned __/__in __/g -s/__out unsigned __/__out __/g -s/__out_opt unsigned __/__out_opt __/g +s/ unsigned/ unsigned int/g +s/unsigned int long/unsigned long/g +s/unsigned int __/unsigned __/g # '@name ' -> 'Section: ' diff --git a/src/api/ml/z3.idl b/src/api/ml/z3.idl index 2450e387d..555835c88 100644 --- a/src/api/ml/z3.idl +++ b/src/api/ml/z3.idl @@ -91,11 +91,6 @@ quote(c,"#define xstr(s) str(s)"); quote(c,"#define str(s) #s"); -// CamlIDL (1.05) has a bug where it does not accept [unsigned] as a type, -// only as a specifier, so unsigned is defined to be unsigned int. -#define unsigned unsigned int - - // Suppress "warning C4090: 'function' : different 'const' qualifiers" as // CamlIDL does not seem to get this right. quote(c,"#pragma warning(disable:4090)"); From ae5f96895dfd7454d1a3cb8770d0a180b956acda Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Mon, 3 Dec 2012 03:51:04 +0000 Subject: [PATCH 02/60] Change to avoid relying on sed supporting disjunction or escaped control characters --- src/api/ml/add_error_checking.V3.sed | 2 +- src/api/ml/add_error_checking.sed | 81 ++++++++++++++++++---------- src/api/ml/build.sed | 2 +- 3 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/api/ml/add_error_checking.V3.sed b/src/api/ml/add_error_checking.V3.sed index 170ca2d6b..7ec725b77 100644 --- a/src/api/ml/add_error_checking.V3.sed +++ b/src/api/ml/add_error_checking.V3.sed @@ -1,2 +1,2 @@ # Customize error handling for contexts created in ML: -s/Z3_API Z3_mk_context\(_rc\|\)(\(.*\))/Z3_API Z3_mk_context\1(\2) quote(dealloc,\"Z3_set_error_handler(_res, caml_z3_error_handler);\")/g +s/Z3_API Z3_mk_context(\(.*\))/Z3_API Z3_mk_context(\1) quote(dealloc,\"Z3_set_error_handler(_res, caml_z3_error_handler);\")/g diff --git a/src/api/ml/add_error_checking.sed b/src/api/ml/add_error_checking.sed index ede3275e1..71c06b9e4 100644 --- a/src/api/ml/add_error_checking.sed +++ b/src/api/ml/add_error_checking.sed @@ -3,14 +3,19 @@ # Add error checking epilogue for all Z3_API functions that accept two Z3_contexts :begincc -# add epilogue for two Z3_context parameters -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\|\))\(;\|\)[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5\6) quote(dealloc,\"check_error_code(\3);\")\7/g - -# if a match was found, done with all Z3_contexts and Z3_theorys +# add epilogue for two Z3_context parameters and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt +s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5\6) quote(dealloc,\"check_error_code(\3);\");/g +t endt +s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5) quote(dealloc,\"check_error_code(\3);\");/g +t endt +s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\))[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5\6) quote(dealloc,\"check_error_code(\3);\")/g +t endt +s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5) quote(dealloc,\"check_error_code(\3);\")/g t endt # if complete prototype, done with two Z3_contexts -/Z3_API .*(.*)\(;\|\)[ ]*$/b endcc +/Z3_API .*(.*);[ ]*$/b endcc +/Z3_API .*(.*)[ ]*$/b endcc # if incomplete prototype /Z3_API .*(.*/{ @@ -18,10 +23,14 @@ t endt # read another line N - # add epilogue for two Z3_context parameters - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\|\))\(;\|\)[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5\6) quote(dealloc,\"check_error_code(\3); check_error_code(\5);\")\7/g - - # if a match was found, done with all Z3_contexts and Z3_theorys + # add epilogue for two Z3_context parameters and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt + s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5\6) quote(dealloc,\"check_error_code(\3); check_error_code(\5);\");/g + t endt + s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5) quote(dealloc,\"check_error_code(\3); check_error_code(\5);\");/g + t endt + s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\))[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5\6) quote(dealloc,\"check_error_code(\3); check_error_code(\5);\")/g + t endt + s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\(.*\)Z3_context \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_context \3\4Z3_context \5) quote(dealloc,\"check_error_code(\3); check_error_code(\5);\")/g t endt # else keep looking for two Z3_contexts @@ -31,14 +40,19 @@ t endt # Add error checking epilogue for all Z3_API functions that accept one Z3_context :beginc -# add epilogue for one Z3_context parameter -s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\|\))\(;\|\)[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\")\5/g - -# if a match was found, done with all Z3_contexts and Z3_theorys +# add epilogue for one Z3_context parameter and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt +s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\");/g +t endt +s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_context \3) quote(dealloc,\"check_error_code(\3);\");/g +t endt +s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\)[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\")/g +t endt +s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_context \3) quote(dealloc,\"check_error_code(\3);\")/g t endt # if complete prototype, done with all Z3_contexts -/Z3_API .*(.*)\(;\|\)[ ]*$/b endc +/Z3_API .*(.*);[ ]*$/b endc +/Z3_API .*(.*)[ ]*$/b endc # if incomplete prototype /Z3_API .*(.*/{ @@ -46,10 +60,14 @@ t endt # read another line N - # add epilogue for one Z3_context parameter - s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\|\))\(;\|\)[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\")\5/g - - # if a match was found, done with all Z3_contexts and Z3_theorys + # add epilogue for one Z3_context parameter and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt + s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\");/g + t endt + s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_context \3) quote(dealloc,\"check_error_code(\3);\");/g + t endt + s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\)\([^a-zA-Z].*\))[ ]*$/Z3_API \1(\2Z3_context \3\4) quote(dealloc,\"check_error_code(\3);\")/g + t endt + s/Z3_API \(.*\)(\(.*\)Z3_context \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_context \3) quote(dealloc,\"check_error_code(\3);\")/g t endt # else keep looking for one Z3_context @@ -60,24 +78,33 @@ t endt # Add error checking epilogue for all Z3_API functions that accept a Z3_theory :begint -# add epilogue for one Z3_theory parameter -s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\)\([^a-zA-Z].*\|\))\(;\|\)[ ]*$/Z3_API \1(\2Z3_theory \3\4) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\")\5/g - -# if a match was found, done with all Z3_contexts and Z3_theorys +# add epilogue for one Z3_theory parameter and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt +s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_theory \3\4) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\");/g +t endt +s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_theory \3) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\");/g +t endt +s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\)\([^a-zA-Z].*\))[ ]*$/Z3_API \1(\2Z3_theory \3\4) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\")/g +t endt +s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_theory \3) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\")/g t endt # if complete prototype, done with all Z3_theorys -/Z3_API .*(.*)\(;\|\)[ ]*$/b endt +/Z3_API .*(.*);[ ]*$/b endt +/Z3_API .*(.*)[ ]*$/b endt /Z3_API .*(.*/{ # read another line N - # add epilogue for one Z3_theory parameter - s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\)\([^a-zA-Z].*\|\))\(;\|\)[ ]*$/Z3_API \1(\2Z3_theory \3\4) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\")\5/g - - # if a match was found, done with all Z3_theorys + # add epilogue for one Z3_theory parameter and if a match was found, done with all Z3_contexts and Z3_theorys so jump to endt + s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\)\([^a-zA-Z].*\));[ ]*$/Z3_API \1(\2Z3_theory \3\4) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\");/g + t endt + s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\));[ ]*$/Z3_API \1(\2Z3_theory \3) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\");/g + t endt + s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\)\([^a-zA-Z].*\))[ ]*$/Z3_API \1(\2Z3_theory \3\4) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\")/g + t endt + s/Z3_API \(.*\)(\(.*\)Z3_theory \([a-zA-Z]*\))[ ]*$/Z3_API \1(\2Z3_theory \3) quote(dealloc,\"check_error_code(Z3_theory_get_context(\3));\")/g t endt # else keep looking for one Z3_theory diff --git a/src/api/ml/build.sed b/src/api/ml/build.sed index d53a13713..c7d1fc804 100644 --- a/src/api/ml/build.sed +++ b/src/api/ml/build.sed @@ -43,7 +43,7 @@ s/\\ / /g s/\\c \([^ .,:]*\)/[\1]/g # '#Z3_' -> 'Z3.' -s/#Z3_\([^ \n\.\t,)]*\)/{!Z3.\1}/g +s/#Z3_\([^ \.,) ]*\)/{!Z3.\1}/g # '/*@}*/' -> '' s/\/\*@{\*\///g From 949317ccfcb7f43d2449c72448b31b2a172797a2 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Tue, 4 Dec 2012 03:23:10 +0000 Subject: [PATCH 03/60] Fixes for error handling in ml api --- src/api/ml/add_error_checking.V3.sed | 2 +- src/api/ml/error_handling.idl | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/api/ml/add_error_checking.V3.sed b/src/api/ml/add_error_checking.V3.sed index 7ec725b77..7df291520 100644 --- a/src/api/ml/add_error_checking.V3.sed +++ b/src/api/ml/add_error_checking.V3.sed @@ -1,2 +1,2 @@ # Customize error handling for contexts created in ML: -s/Z3_API Z3_mk_context(\(.*\))/Z3_API Z3_mk_context(\1) quote(dealloc,\"Z3_set_error_handler(_res, caml_z3_error_handler);\")/g +s/Z3_API Z3_mk_context(\(.*\))/Z3_API Z3_mk_context(\1) quote(dealloc,\"Z3_set_error_handler(_res, (void*)caml_z3_error_handler);\")/g diff --git a/src/api/ml/error_handling.idl b/src/api/ml/error_handling.idl index cc49a91e4..5a2ec9915 100644 --- a/src/api/ml/error_handling.idl +++ b/src/api/ml/error_handling.idl @@ -53,6 +53,12 @@ Author: #endif +// The V3 API uses a single handler irregardless of UNSAFE_ERRORS +quote(c," +/* All contexts share the same handler */ +static value caml_z3_error_handler = 0; +"); + #ifdef SAFE_ERRORS quote(mlmli," @@ -64,7 +70,7 @@ quote(mlmli," exception Error of context * error_code "); quote(ml," -/* Register dynamically-generated exception tag for use from C */ +(* Register dynamically-generated exception tag for use from C *) let _ = Callback.register_exception \"Z3.Error\" (Error (Obj.magic None, OK)) "); @@ -108,7 +114,7 @@ quote(mlmli," exception Error of context * error_code "); quote(ml," -/* Register dynamically-generated exception tag for use from C */ +(* Register dynamically-generated exception tag for use from C *) let _ = Callback.register_exception \"Z3.Error\" (Error (Obj.magic None, OK)) "); @@ -116,9 +122,6 @@ quote(c," /* Error checking routine that does nothing */ void check_error_code(Z3_context c) {} -/* All contexts share the same handler */ -static value caml_error_handler = 0; - static void error_handler_static (Z3_context c, Z3_error_code e) { static struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; @@ -126,8 +129,8 @@ static void error_handler_static (Z3_context c, Z3_error_code e) value ctx_err[2]; ctx_err[0] = c2ml_Z3_context(&c); ctx_err[1] = camlidl_c2ml_z3_Z3_error_code(&e, &_ctxs); - if (caml_error_handler) { - caml_callback2(caml_error_handler, ctx_err[0], ctx_err[1]); + if (caml_z3_error_handler) { + caml_callback2(caml_z3_error_handler, ctx_err[0], ctx_err[1]); } else { /* if no handler set, raise OCaml Error exception */ exn_tag = caml_named_value(\"Z3.Error\"); @@ -141,7 +144,7 @@ static void error_handler_static (Z3_context c, Z3_error_code e) void ml2c_Z3_error_handler (value ml_handler, void* c_handler) { - caml_error_handler = ml_handler; + caml_z3_error_handler = ml_handler; c_handler = (void*)error_handler_static; } From 6fad07e6e1f16c0c662092132e2141f690176d34 Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Tue, 4 Dec 2012 03:31:08 +0000 Subject: [PATCH 04/60] Update build system for ml api --- src/api/ml/Makefile | 14 +++++ src/api/ml/Makefile.build | 69 ++++++++++++++++++++++++ src/api/ml/generate_mlapi.sh | 53 ++++++++++++++++++ src/api/ml/postprocess.sed | 8 +++ src/api/ml/{build.sed => preprocess.sed} | 0 src/api/ml/reverse.sed | 3 ++ src/api/ml/{z3.idl => z3.0.idl} | 5 -- 7 files changed, 147 insertions(+), 5 deletions(-) create mode 100644 src/api/ml/Makefile create mode 100644 src/api/ml/Makefile.build create mode 100755 src/api/ml/generate_mlapi.sh create mode 100644 src/api/ml/postprocess.sed rename src/api/ml/{build.sed => preprocess.sed} (100%) create mode 100644 src/api/ml/reverse.sed rename src/api/ml/{z3.idl => z3.0.idl} (98%) diff --git a/src/api/ml/Makefile b/src/api/ml/Makefile new file mode 100644 index 000000000..55f89fe1c --- /dev/null +++ b/src/api/ml/Makefile @@ -0,0 +1,14 @@ +# to set ARGS, invoke as e.g.: $ make ARGS='-DUNSAFE_ERRORS -DLEAK_CONTEXTS' +ARGS= + + +default: z3.ml z3.mli z3_stubs.c + + +%.ml %.mli %_stubs.c: ../%_api.h %.0.idl x3.ml x3V3.ml x3V3.mli \ + error_handling.idl mlx_get_app_args.idl mlx_get_array_sort.idl mlx_get_datatype_sort.idl mlx_get_domains.idl mlx_get_error_msg.idl mlx_get_pattern_terms.idl mlx_get_tuple_sort.idl mlx_mk_context_x.idl mlx_mk_datatypes.idl mlx_mk_numeral.idl mlx_mk_sort.idl mlx_mk_symbol.idl mlx_model.idl mlx_numeral_refine.idl mlx_parse_smtlib.idl mlx_sort_refine.idl mlx_statistics.idl mlx_symbol_refine.idl mlx_term_refine.idl \ + generate_mlapi.sh add_error_checking.V3.sed add_error_checking.sed preprocess.sed postprocess.sed reverse.sed + ./generate_mlapi.sh $(ARGS) + +clean: + rm -f z3.ml z3.mli z3_stubs.c diff --git a/src/api/ml/Makefile.build b/src/api/ml/Makefile.build new file mode 100644 index 000000000..27c798bbf --- /dev/null +++ b/src/api/ml/Makefile.build @@ -0,0 +1,69 @@ +# Makefile to compile OCaml interface to Z3 +# +# Parameters: ARGS and DEPS environment variables +# ARGS is passed through to the Makefile that generates the OCaml interface +# DEPS is a sequence of files that are deleted when the OCaml interface changes + +SRC_ML=../../../src/api/ml +ifeq (${OS}, Windows_NT) +# the BLD_ML path ends up stored in z3.cm{,x}a, so it must be in windows format +BLD_ML=$(shell cygpath -m $(CURDIR)) +CFLAGS=-ccopt -wd4090 -ccopt -I$(SRC_ML)/.. +XCDBG=-g $(CFLAGS) +XCOPT=-ccopt -Ox -ccopt -Oy- $(CFLAGS) +# ole32 is needed by camlidl (COM support) +XLIB=-cclib ole32.lib +AR=lib /nologo /LIBPATH:../../build ../../z3.lib /out: +O=obj +A=lib +else +BLD_ML=$(CURDIR) +CFLAGS=-ccopt -Wno-discard-qual -ccopt -Wno-unused-variable -ccopt -I$(SRC_ML)/.. +XCDBG=-g -ccopt -g $(CFLAGS) +XCOPT=-ccopt -O3 -ccopt -fomit-frame-pointer $(CFLAGS) +XLIB= +AR=ar rcs # note trailing space is significant +O=o +A=a +endif + + +all: z3.cma z3.cmxa ocamlz3 + + +# keep these files to avoid repeatedly rebuilding them +.PRECIOUS: $(SRC_ML)/z3.ml $(SRC_ML)/z3.mli $(SRC_ML)/z3_stubs.c z3.ml z3.mli z3_stubs.c z3_theory_stubs.c + +# regenerate OCaml API if needed +$(SRC_ML)/%.mli $(SRC_ML)/%.ml $(SRC_ML)/%_stubs.c: $(SRC_ML)/Makefile + make -C $(SRC_ML) z3.mli z3.ml z3_stubs.c + +# copy OCaml API from src to build directories +%.mli %.ml %_stubs.c %_theory_stubs.c: $(SRC_ML)/%.mli $(SRC_ML)/%.ml $(SRC_ML)/%_stubs.c Makefile + cp $(SRC_ML)/z3.mli $(SRC_ML)/z3.ml $(SRC_ML)/z3_stubs.c $(SRC_ML)/z3_theory_stubs.c . + +# OCaml library module for native code clients +%.cmxa %.cmi lib%stubs.a %.a: %.mli %.ml %_stubs.c %_theory_stubs.c Makefile + rm -f $(DEPS) + ocamlopt.opt -c $(XCOPT) z3.mli z3.ml z3_stubs.c z3_theory_stubs.c + $(AR)libz3stubs.$(A) z3.$(O) z3_stubs.$(O) z3_theory_stubs.$(O) + ocamlopt.opt -a -cclib -L$(BLD_ML)/../.. $(XLIB) -cclib -lcamlidl -cclib -lz3 -cclib -lz3stubs z3.cmx -o z3.cmxa + rm -f z3_theory_stubs.$(O) z3_stubs.$(O) z3.$(O) z3.cmx + +# OCaml library module for byte code clients +%.cma %.cmi lib%stubs_dbg.a: %.mli %.ml %_stubs.c %_theory_stubs.c Makefile + rm -f $(DEPS) + ocamlc.opt -c $(XCDBG) z3.mli z3.ml z3_stubs.c z3_theory_stubs.c + $(AR)libz3stubs_dbg.$(A) z3_stubs.$(O) z3_theory_stubs.$(O) + ocamlc.opt -custom -a $(CXDBG) -cclib -L$(BLD_ML)/../.. $(XLIB) -cclib -lcamlidl -cclib -lz3 -cclib -lz3stubs_dbg z3.cmo -o z3.cma + rm -f z3_theory_stubs.$(O) z3_stubs.$(O) z3.cmo + + +# OCaml custom toplevel system pre-linked with Z3 +ocamlz3: z3.cma Makefile + ocamlmktop -o ocamlz3 z3.cma -cclib -L. + + +clean: Makefile + make -C $(SRC_ML) clean + rm -rf Makefile libz3stubs.$(A) libz3stubs_dbg.$(A) ocamlz3 ocamlz3.dSYM z3.$(O) z3.$(A) z3.cma z3.cmi z3.cmo z3.cmx z3.cmxa z3.ml z3.mli z3_stubs.$(O) z3_stubs.c z3_theory_stubs.$(O) z3_theory_stubs.c diff --git a/src/api/ml/generate_mlapi.sh b/src/api/ml/generate_mlapi.sh new file mode 100755 index 000000000..dd8692833 --- /dev/null +++ b/src/api/ml/generate_mlapi.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Script to generate the Z3 OCaml API +# +# Assumes that environment variables are set to provide access to the following commands: camlidl, gcc, grep, sed +# +# This script uses 'gcc -E' as the C preprocessor, other C preprocessors may work but have not been tested. +# +# Invoke with "-DUNSAFE_ERRORS" to build version that does not support recoverable errors, but avoids some error-checking overhead. +# Invoke with "-DLEAK_CONTEXTS" to build version that leaks Z3_context objects, but avoids some garbage-collection overhead. + + +# add calls to error checking routine +# convert from doxygen to ocamldoc markup and other syntactic munging +# ../z3_api.h -> z3V3_api.idl +sed -f add_error_checking.V3.sed -f preprocess.sed ../z3_api.h > z3V3_api.idl + +# z3.idl (z3V3_api.idl x3V3.mli x3V3.ml) -> z3V3_stubs.c, z3V3.mli, z3V3.ml +gcc -E -w -P -CC -xc -DCAMLIDL -DMLAPIV3 $@ z3.0.idl > z3V3.idl +camlidl -nocpp z3V3.idl + +# reverse.sed to reverse order of substitution of enums to avoid matching prefixes such as enum_1 of enum_10 +grep "^and z3_[a-zA-Z0-9_]* = [a-z][a-zA-Z0-9_]*$" z3V3.mli | sed -e "s|and z3_\([a-zA-Z0-9_]*\) = \([a-zA-Z0-9_]*\)|s/\2/\1/g|g" -f reverse.sed > /tmp/renameV3.sed +grep "^and z3_[a-zA-Z0-9_]* = [a-z][a-zA-Z0-9_ ]* option$" z3V3.mli | sed -e "s|and \(z3_[a-zA-Z0-9_]*\) = \([a-zA-Z0-9_ ]*\)|s/\1/\2/g|g" >> /tmp/renameV3.sed + +# rename.sed to substitute out type equations for enums and options, then postprocess +cp -f z3V3.mli z3V3.ml /tmp +sed -f /tmp/renameV3.sed -f postprocess.sed /tmp/z3V3.mli > z3V3.mli +sed -f /tmp/renameV3.sed -f postprocess.sed /tmp/z3V3.ml > z3V3.ml + +# ../z3_api.h -> z3_api.idl +sed -f add_error_checking.sed -f preprocess.sed ../z3_api.h > z3_api.idl + +# z3.idl (z3_api.idl x3.ml) -> z3_stubs.c, z3.mli, z3.ml +gcc -E -w -P -CC -xc -I. -DCAMLIDL $@ z3.0.idl > z3.idl +camlidl -nocpp z3.idl + +# reverse.sed to reverse order of substitution of enums to avoid matching prefixes such as enum_1 of enum_10 +grep "^and z3_[a-zA-Z0-9_]* = [a-z][a-zA-Z0-9_]*$" z3.mli | sed -e "s|and z3_\([a-zA-Z0-9_]*\) = \([a-zA-Z0-9_]*\)|s/\2/\1/g|g" -f reverse.sed > /tmp/rename.sed +grep "^and z3_[a-zA-Z0-9_]* = [a-z][a-zA-Z0-9_ ]* option$" z3.mli | sed -e "s|and \(z3_[a-zA-Z0-9_]*\) = \([a-zA-Z0-9_ ]*\)|s/\1/\2/g|g" >> /tmp/rename.sed + +# rename.sed to substitute out type equations for enums and options, then postprocess +cp z3.mli z3.ml /tmp +sed -f /tmp/rename.sed -f postprocess.sed /tmp/z3.mli > z3.mli +sed -f /tmp/rename.sed -f postprocess.sed /tmp/z3.ml > z3.ml + + +# append Z3.V3 module onto Z3 module +cat z3V3.mli >> z3.mli +cat z3V3.ml >> z3.ml +sed "1,22d" z3V3_stubs.c >> z3_stubs.c + +rm -f z3V3_api.idl z3V3.idl z3V3.ml z3V3.mli z3V3_stubs.c z3_api.idl z3.idl diff --git a/src/api/ml/postprocess.sed b/src/api/ml/postprocess.sed new file mode 100644 index 000000000..f25f70cb7 --- /dev/null +++ b/src/api/ml/postprocess.sed @@ -0,0 +1,8 @@ +# remove 'z3_' and 'Z3_' prefixes on names + +s/{\!Z3\./{\!/g +s/\([^_]\)[zZ]3_/\1/g + +# remove cyclic definitions introduced by substituting type equations + +s/^and \([a-z][a-zA-Z_ ]*\) = \1$//g diff --git a/src/api/ml/build.sed b/src/api/ml/preprocess.sed similarity index 100% rename from src/api/ml/build.sed rename to src/api/ml/preprocess.sed diff --git a/src/api/ml/reverse.sed b/src/api/ml/reverse.sed new file mode 100644 index 000000000..31ac563d2 --- /dev/null +++ b/src/api/ml/reverse.sed @@ -0,0 +1,3 @@ +# output lines of input in reverse order + +1!G;h;$!d diff --git a/src/api/ml/z3.idl b/src/api/ml/z3.0.idl similarity index 98% rename from src/api/ml/z3.idl rename to src/api/ml/z3.0.idl index 555835c88..3773a28e3 100644 --- a/src/api/ml/z3.idl +++ b/src/api/ml/z3.0.idl @@ -91,11 +91,6 @@ quote(c,"#define xstr(s) str(s)"); quote(c,"#define str(s) #s"); -// Suppress "warning C4090: 'function' : different 'const' qualifiers" as -// CamlIDL does not seem to get this right. -quote(c,"#pragma warning(disable:4090)"); - - #ifndef MLAPIV3 #define DEFINE_TYPE(T) typedef [abstract] void* T From 2f3daf14b51f993f5e8ed88f51b678c5d8e8c98d Mon Sep 17 00:00:00 2001 From: Josh Berdine Date: Thu, 6 Dec 2012 00:42:30 +0000 Subject: [PATCH 05/60] Regenerate ml api --- src/api/ml/z3.ml | 404 ++--- src/api/ml/z3.mli | 3498 ++++++++++------------------------------- src/api/ml/z3_stubs.c | 401 +++-- 3 files changed, 1196 insertions(+), 3107 deletions(-) diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 76536ef43..4d391c06f 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -293,13 +293,12 @@ let reset_memory () = () (** Exceptions raised by Z3. It is safe to continue interacting with Z3 after catching [Error] exceptions. - - {b See also}: {!get_error_msg} *) exception Error of context * error_code - +(* Register dynamically-generated exception tag for use from C *) let _ = Callback.register_exception "Z3.Error" (Error (Obj.magic None, OK)) external mk_context: (string * string) list -> context = "caml_z3_mk_context" @@ -349,7 +348,6 @@ external param_descrs_to_string : context -> param_descrs -> string (** Refined view of a {!symbol}. - - {b See also}: {!mk_symbol} - {b See also}: {!symbol_refine} *) @@ -368,33 +366,28 @@ external mk_string_symbol : context -> string -> symbol A datatype constructor descriptor. *) type datatype_constructor_desc = { - constructor_desc : symbol; (** name of the constructor function *) - recognizer_desc : symbol; (** name of the recognizer function *) - accessor_descs : (symbol * sort) array; (** names and sorts of the fields *) + constructor_desc : symbol; (** name of the constructor function *) + recognizer_desc : symbol; (** name of the recognizer function *) + accessor_descs : (symbol * sort) array; (** names and sorts of the fields *) } - (** A datatype is described by a name and constructor descriptors. *) type datatype_desc = symbol * datatype_constructor_desc array - (** A datatype constructor representation. *) type datatype_constructor = { - constructor : func_decl; (** constructor function *) - recognizer : func_decl; (** recognizer function *) - accessors : func_decl array; (** field accessor functions *) + constructor : func_decl; (** constructor function *) + recognizer : func_decl; (** recognizer function *) + accessors : func_decl array; (** field accessor functions *) } - (** A datatype is represented by a sort and constructors. *) type datatype = sort * datatype_constructor array - (** Refined view of a {!sort}. - - {b See also}: {!mk_sort} - {b See also}: {!sort_refine} *) @@ -751,9 +744,9 @@ external mk_set_subset : context -> ast -> ast -> ast Summary: \[ [ numeral_refined ] \] is the refined view of a numeral . *) type numeral_refined = - | Numeral_int of int * sort - | Numeral_int64 of int64 * sort - | Numeral_large of string * sort + | Numeral_int of int * sort + | Numeral_int64 of int64 * sort + | Numeral_large of string * sort | Numeral_rational of numeral_refined * numeral_refined external mk_numeral : context -> string -> sort -> ast @@ -930,21 +923,18 @@ external get_app_arg : context -> app -> int -> ast (** Summary: \[ [ binder_type ] \] is a universal or existential quantifier. - - {b See also}: {!term_refined} *) type binder_type = Forall | Exists - (** Summary: \[ [ term_refined ] \] is the refinement of a {!ast} . - - {b See also}: {!term_refine} *) type term_refined = - | Term_numeral of numeral_refined - | Term_app of decl_kind * func_decl * ast array + | Term_numeral of numeral_refined + | Term_app of decl_kind * func_decl * ast array | Term_quantifier of binder_type * int * ast array array * (symbol * sort) array * ast - | Term_var of int * sort + | Term_var of int * sort external is_eq_ast : context -> ast -> ast -> bool = "camlidl_z3_Z3_is_eq_ast" @@ -1220,12 +1210,6 @@ external get_smtlib_sort : context -> int -> sort external get_smtlib_error : context -> string = "camlidl_z3_Z3_get_smtlib_error" -external parse_z3_string : context -> string -> ast - = "camlidl_z3_Z3_parse_z3_string" - -external parse_z3_file : context -> string -> ast - = "camlidl_z3_Z3_parse_z3_file" - external set_error : context -> error_code -> unit = "camlidl_z3_Z3_set_error" @@ -1235,6 +1219,12 @@ external get_error_msg_ex : context -> error_code -> string external get_version : unit -> int * int * int * int = "camlidl_z3_Z3_get_version" +external enable_trace : string -> unit + = "camlidl_z3_Z3_enable_trace" + +external disable_trace : string -> unit + = "camlidl_z3_Z3_disable_trace" + external mk_fixedpoint : context -> fixedpoint = "camlidl_z3_Z3_mk_fixedpoint" @@ -1280,8 +1270,11 @@ external fixedpoint_register_relation : context -> fixedpoint -> func_decl -> un external fixedpoint_set_predicate_representation : context -> fixedpoint -> func_decl -> symbol array -> unit = "camlidl_z3_Z3_fixedpoint_set_predicate_representation" -external fixedpoint_simplify_rules : context -> fixedpoint -> ast array -> func_decl array -> ast_vector - = "camlidl_z3_Z3_fixedpoint_simplify_rules" +external fixedpoint_get_rules : context -> fixedpoint -> ast_vector + = "camlidl_z3_Z3_fixedpoint_get_rules" + +external fixedpoint_get_assertions : context -> fixedpoint -> ast_vector + = "camlidl_z3_Z3_fixedpoint_get_assertions" external fixedpoint_set_params : context -> fixedpoint -> params -> unit = "camlidl_z3_Z3_fixedpoint_set_params" @@ -1295,6 +1288,12 @@ external fixedpoint_get_param_descrs : context -> fixedpoint -> param_descrs external fixedpoint_to_string : context -> fixedpoint -> ast array -> string = "camlidl_z3_Z3_fixedpoint_to_string" +external fixedpoint_from_string : context -> fixedpoint -> string -> ast_vector + = "camlidl_z3_Z3_fixedpoint_from_string" + +external fixedpoint_from_file : context -> fixedpoint -> string -> ast_vector + = "camlidl_z3_Z3_fixedpoint_from_file" + external fixedpoint_push : context -> fixedpoint -> unit = "camlidl_z3_Z3_fixedpoint_push" @@ -1544,6 +1543,9 @@ external solver_get_num_scopes : context -> solver -> int external solver_assert : context -> solver -> ast -> unit = "camlidl_z3_Z3_solver_assert" +external solver_assert_and_track : context -> solver -> ast -> ast -> unit + = "camlidl_z3_Z3_solver_assert_and_track" + external solver_get_assertions : context -> solver -> ast_vector = "camlidl_z3_Z3_solver_get_assertions" @@ -1597,18 +1599,15 @@ external stats_get_double_value : context -> stats -> int -> float = "camlidl_z3_Z3_stats_get_double_value" - (* Internal auxiliary functions: *) (* (* Transform a pair of arrays into an array of pairs *) let array_combine a b = if Array.length a <> Array.length b then raise (Invalid_argument "array_combine"); Array.init (Array.length a) (fun i -> (a.(i), b.(i))) - (* [a |> b] is the pipeline operator for [b(a)] *) let ( |> ) x f = f x *) - (* Find the index of an element in an array, raises Not_found is missing *) let find equal x a = let len = Array.length a in @@ -1622,24 +1621,17 @@ let find equal x a = find_ (i+1) in find_ 0 - - (* Symbols *) - let symbol_refine c s = match get_symbol_kind c s with | INT_SYMBOL -> Symbol_int (get_symbol_int c s) | STRING_SYMBOL -> Symbol_string (get_symbol_string c s) - let mk_symbol c = function | Symbol_int(i) -> mk_int_symbol c i | Symbol_string(s) -> mk_string_symbol c s - - (* Sorts *) - -let get_datatype_sort c s = - Array.init (get_datatype_sort_num_constructors c s) (fun i -> +let get_datatype_sort c s = + Array.init (get_datatype_sort_num_constructors c s) (fun i -> let constructor = get_datatype_sort_constructor c s i in let recognizer = get_datatype_sort_recognizer c s i in let accessors = @@ -1648,7 +1640,6 @@ let get_datatype_sort c s = ) in {constructor; recognizer; accessors} ) - let sort_refine c s = match get_sort_kind c s with | UNINTERPRETED_SORT -> Sort_uninterpreted (get_sort_name c s) @@ -1665,7 +1656,6 @@ let sort_refine c s = | DATATYPE_SORT -> Sort_datatype (get_datatype_sort c s) | RELATION_SORT -> Sort_relation (Array.init (get_relation_arity c s) (fun i -> get_relation_column c s i)) | UNKNOWN_SORT -> Sort_unknown - let mk_sort c = function | Sort_uninterpreted(s) -> mk_uninterpreted_sort c s | Sort_bool -> mk_bool_sort c @@ -1677,10 +1667,7 @@ let mk_sort c = function | Sort_datatype(constructors) -> get_range c constructors.(0).constructor | Sort_relation(_) -> invalid_arg "Z3.mk_sort: cannot construct relation sorts" | Sort_unknown(_) -> invalid_arg "Z3.mk_sort: cannot construct unknown sorts" - - (* Replacement datatypes creation API *) - let mk_datatypes ctx generator = let usort0 = mk_uninterpreted_sort ctx (mk_int_symbol ctx 0) in @@ -1749,19 +1736,16 @@ let mk_datatypes ctx generator = ) ctorss ; datatypes - - (* Numerals *) - let rec numeral_refine c t = assert( get_ast_kind c t = NUMERAL_AST ); let sort = get_sort c t in let is_int, i = get_numeral_int c t in - if is_int then + if is_int then Numeral_int (i, sort) else let is_int64, i = get_numeral_int64 c t in - if is_int64 then + if is_int64 then Numeral_int64 (i, sort) else if get_sort_kind c sort <> REAL_SORT then @@ -1770,14 +1754,11 @@ let rec numeral_refine c t = let n = numeral_refine c (get_numerator c t) in let d = numeral_refine c (get_denominator c t) in Numeral_rational (n, d) - - let to_real c x = if get_sort_kind c (get_sort c x) = REAL_SORT then x else mk_int2real c x - let rec embed_numeral c = function | Numeral_int (i, s) -> mk_int c i s | Numeral_int64 (i, s) -> mk_int64 c i s @@ -1790,21 +1771,14 @@ let rec embed_numeral c = function let d_str = get_numeral_string c (embed_numeral c d) in mk_numeral c (n_str ^ " / " ^ d_str) (mk_real_sort c) *) - (* Terms *) - let get_app_args c a = Array.init (get_app_num_args c a) (get_app_arg c a);; - let get_domains c d = Array.init (get_domain_size c d) (get_domain c d);; - - -let get_pattern_terms c p = +let get_pattern_terms c p = Array.init (get_pattern_num_terms c p) (get_pattern c p) - - -let term_refine c t = +let term_refine c t = match get_ast_kind c t with | NUMERAL_AST -> Term_numeral (numeral_refine c t) @@ -1815,35 +1789,29 @@ let term_refine c t = let args = Array.init num_args (get_app_arg c t') in let k = get_decl_kind c f in Term_app (k, f, args) - | QUANTIFIER_AST -> + | QUANTIFIER_AST -> let bt = if is_quantifier_forall c t then Forall else Exists in - let w = get_quantifier_weight c t in - let np = get_quantifier_num_patterns c t in - let pats = Array.init np (get_quantifier_pattern_ast c t) in - let pats = Array.map (get_pattern_terms c) pats in - let nb = get_quantifier_num_bound c t in + let w = get_quantifier_weight c t in + let np = get_quantifier_num_patterns c t in + let pats = Array.init np (get_quantifier_pattern_ast c t) in + let pats = Array.map (get_pattern_terms c) pats in + let nb = get_quantifier_num_bound c t in let bound = Array.init nb (fun i -> (get_quantifier_bound_name c t i, get_quantifier_bound_sort c t i) ) in let body = get_quantifier_body c t in Term_quantifier (bt, w, pats, bound, body) - | VAR_AST -> + | VAR_AST -> Term_var (get_index_value c t, get_sort c t) | _ -> assert false - - (* let mk_term c = function *) -(* | Term_numeral (numeral, sort) -> mk_numeral c numeral sort *) -(* | Term_app (kind, decl, args) -> *) -(* | Term_quantifier (strength, weight, pats, bound, body) -> *) -(* | Term_var (index, sort) -> *) - - - +(* | Term_numeral (numeral, sort) -> mk_numeral c numeral sort *) +(* | Term_app (kind, decl, args) -> *) +(* | Term_quantifier (strength, weight, pats, bound, body) -> *) +(* | Term_var (index, sort) -> *) (* Refined model API *) - let model_refine c m = let num_sorts = model_get_num_sorts c m in let sorts = Hashtbl.create num_sorts in @@ -1903,49 +1871,33 @@ let model_refine c m = () done; {sorts; consts; arrays; funcs} - - (* Extended parser API *) - -let get_smtlib_formulas c = +let get_smtlib_formulas c = Array.init (get_smtlib_num_formulas c) (get_smtlib_formula c) - -let get_smtlib_assumptions c = +let get_smtlib_assumptions c = Array.init (get_smtlib_num_assumptions c) (get_smtlib_assumption c) - let get_smtlib_decls c = Array.init (get_smtlib_num_decls c) (get_smtlib_decl c) - let get_smtlib_parse_results c = (get_smtlib_formulas c, get_smtlib_assumptions c, get_smtlib_decls c) - -let parse_smtlib_string_x c a1 a2 a3 a4 a5 = +let parse_smtlib_string_x c a1 a2 a3 a4 a5 = parse_smtlib_string c a1 a2 a3 a4 a5 ; get_smtlib_parse_results c - -let parse_smtlib_file_x c a1 a2 a3 a4 a5 = +let parse_smtlib_file_x c a1 a2 a3 a4 a5 = parse_smtlib_file c a1 a2 a3 a4 a5 ; get_smtlib_parse_results c - -let parse_smtlib_string_formula c a1 a2 a3 a4 a5 = +let parse_smtlib_string_formula c a1 a2 a3 a4 a5 = parse_smtlib_string c a1 a2 a3 a4 a5 ; match get_smtlib_formulas c with [|f|] -> f | _ -> failwith "Z3: parse_smtlib_string_formula" - -let parse_smtlib_file_formula c a1 a2 a3 a4 a5 = +let parse_smtlib_file_formula c a1 a2 a3 a4 a5 = parse_smtlib_file c a1 a2 a3 a4 a5 ; match get_smtlib_formulas c with [|f|] -> f | _ -> failwith "Z3: parse_smtlib_file_formula" - - (* Error handling *) - let get_error_msg c e = match e with | PARSER_ERROR -> (get_error_msg_ex c e) ^ ": " ^ (get_smtlib_error c) | _ -> get_error_msg_ex c e - - (* Refined stats API *) - let stats_refine c s = let num_stats = stats_size c s in let tbl = Hashtbl.create num_stats in @@ -1970,7 +1922,7 @@ let _ = module V3 = struct -(* File generated from z3.idl *) +(* File generated from z3V3.idl *) type symbol and literals @@ -2205,6 +2157,15 @@ and ast_print_mode = | PRINT_SMTLIB2_COMPLIANT +external global_param_set : string -> string -> unit + = "camlidl_z3V3_Z3_global_param_set" + +external global_param_reset_all : unit -> unit + = "camlidl_z3V3_Z3_global_param_reset_all" + +external global_param_get : string -> string option + = "camlidl_z3V3_Z3_global_param_get" + external mk_config : unit -> config = "camlidl_z3V3_Z3_mk_config" @@ -2263,7 +2224,7 @@ external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_dec = "camlidl_z3V3_Z3_mk_list_sort" external mk_constructor : context -> symbol -> symbol -> symbol array -> sort array -> int array -> constructor - = "camlidl_z3_Z3_mk_constructor_bytecode" "camlidl_z3V3_Z3_mk_constructor" + = "camlidl_z3V3_Z3_mk_constructor_bytecode" "camlidl_z3V3_Z3_mk_constructor" external del_constructor : context -> constructor -> unit = "camlidl_z3V3_Z3_del_constructor" @@ -2587,16 +2548,16 @@ external mk_bound : context -> int -> sort -> ast = "camlidl_z3V3_Z3_mk_bound" external mk_forall : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_forall_bytecode" "camlidl_z3V3_Z3_mk_forall" + = "camlidl_z3V3_Z3_mk_forall_bytecode" "camlidl_z3V3_Z3_mk_forall" external mk_exists : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_exists_bytecode" "camlidl_z3V3_Z3_mk_exists" + = "camlidl_z3V3_Z3_mk_exists_bytecode" "camlidl_z3V3_Z3_mk_exists" external mk_quantifier : context -> bool -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_bytecode" "camlidl_z3V3_Z3_mk_quantifier" + = "camlidl_z3V3_Z3_mk_quantifier_bytecode" "camlidl_z3V3_Z3_mk_quantifier" external mk_quantifier_ex : context -> bool -> int -> symbol -> symbol -> pattern array -> ast array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_ex" + = "camlidl_z3V3_Z3_mk_quantifier_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_ex" external mk_forall_const : context -> int -> app array -> pattern array -> ast -> ast = "camlidl_z3V3_Z3_mk_forall_const" @@ -2605,10 +2566,10 @@ external mk_exists_const : context -> int -> app array -> pattern array -> ast - = "camlidl_z3V3_Z3_mk_exists_const" external mk_quantifier_const : context -> bool -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_const_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const" + = "camlidl_z3V3_Z3_mk_quantifier_const_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const" external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> app array -> pattern array -> ast array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_const_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const_ex" + = "camlidl_z3V3_Z3_mk_quantifier_const_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const_ex" external get_symbol_kind : context -> symbol -> symbol_kind = "camlidl_z3V3_Z3_get_symbol_kind" @@ -2890,19 +2851,19 @@ external model_to_string : context -> model -> string = "camlidl_z3V3_Z3_model_to_string" external benchmark_to_smtlib_string : context -> string -> string -> string -> string -> ast array -> ast -> string - = "camlidl_z3_Z3_benchmark_to_smtlib_string_bytecode" "camlidl_z3V3_Z3_benchmark_to_smtlib_string" + = "camlidl_z3V3_Z3_benchmark_to_smtlib_string_bytecode" "camlidl_z3V3_Z3_benchmark_to_smtlib_string" external parse_smtlib2_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3_Z3_parse_smtlib2_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_string" + = "camlidl_z3V3_Z3_parse_smtlib2_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_string" external parse_smtlib2_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3_Z3_parse_smtlib2_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_file" + = "camlidl_z3V3_Z3_parse_smtlib2_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_file" external parse_smtlib_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3_Z3_parse_smtlib_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib_string" + = "camlidl_z3V3_Z3_parse_smtlib_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib_string" external parse_smtlib_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3_Z3_parse_smtlib_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib_file" + = "camlidl_z3V3_Z3_parse_smtlib_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib_file" external get_smtlib_num_formulas : context -> int = "camlidl_z3V3_Z3_get_smtlib_num_formulas" @@ -2931,15 +2892,15 @@ external get_smtlib_sort : context -> int -> sort external get_smtlib_error : context -> string = "camlidl_z3V3_Z3_get_smtlib_error" -external parse_z3_string : context -> string -> ast - = "camlidl_z3_Z3_parse_z3V3_string" - -external parse_z3_file : context -> string -> ast - = "camlidl_z3_Z3_parse_z3V3_file" - external get_version : unit -> int * int * int * int = "camlidl_z3V3_Z3_get_version" +external enable_trace : string -> unit + = "camlidl_z3V3_Z3_enable_trace" + +external disable_trace : string -> unit + = "camlidl_z3V3_Z3_disable_trace" + external reset_memory : unit -> unit = "camlidl_z3V3_Z3_reset_memory" @@ -3121,114 +3082,85 @@ external get_context_assignment : context -> ast = "camlidl_z3V3_Z3_get_context_assignment" - - (* Internal auxillary functions: *) - (* Transform a pair of arrays into an array of pairs *) let array_combine a b = if Array.length a <> Array.length b then raise (Invalid_argument "array_combine"); Array.init (Array.length a) (fun i->(a.(i),b.(i)));; - (* [a |> b] is the pipeline operator for [b(a)] *) let ( |> ) x f = f x;; - - (* Extensions, except for refinement: *) -let mk_context_x configs = +let mk_context_x configs = let config = mk_config() in let f(param_id,param_value) = set_param_value config param_id param_value in Array.iter f configs; let context = mk_context config in del_config config; context;; - let get_app_args c a = Array.init (get_app_num_args c a) (get_app_arg c a);; - let get_domains c d = Array.init (get_domain_size c d) (get_domain c d);; - let get_array_sort c t = (get_array_sort_domain c t, get_array_sort_range c t);; - -let get_tuple_sort c ty = +let get_tuple_sort c ty = (get_tuple_sort_mk_decl c ty, Array.init (get_tuple_sort_num_fields c ty) (get_tuple_sort_field_decl c ty));; - -type datatype_constructor_refined = { - constructor : func_decl; - recognizer : func_decl; - accessors : func_decl array +type datatype_constructor_refined = { + constructor : func_decl; + recognizer : func_decl; + accessors : func_decl array } - -let get_datatype_sort c ty = +let get_datatype_sort c ty = Array.init (get_datatype_sort_num_constructors c ty) - (fun idx_c -> + (fun idx_c -> let constr = get_datatype_sort_constructor c ty idx_c in - let recog = get_datatype_sort_recognizer c ty idx_c in + let recog = get_datatype_sort_recognizer c ty idx_c in let num_acc = get_domain_size c constr in { constructor = constr; recognizer = recog; accessors = Array.init num_acc (get_datatype_sort_constructor_accessor c ty idx_c); }) - let get_model_constants c m = Array.init (get_model_num_constants c m) (get_model_constant c m);; - - let get_model_func_entry c m i j = (Array.init (get_model_func_entry_num_args c m i j) (get_model_func_entry_arg c m i j), get_model_func_entry_value c m i j);; - let get_model_func_entries c m i = Array.init (get_model_func_num_entries c m i) (get_model_func_entry c m i);; - let get_model_funcs c m = Array.init (get_model_num_funcs c m) (fun i->(get_model_func_decl c m i |> get_decl_name c, get_model_func_entries c m i, get_model_func_else c m i));; - -let get_smtlib_formulas c = +let get_smtlib_formulas c = Array.init (get_smtlib_num_formulas c) (get_smtlib_formula c);; - -let get_smtlib_assumptions c = +let get_smtlib_assumptions c = Array.init (get_smtlib_num_assumptions c) (get_smtlib_assumption c);; - let get_smtlib_decls c = Array.init (get_smtlib_num_decls c) (get_smtlib_decl c);; - let get_smtlib_parse_results c = (get_smtlib_formulas c, get_smtlib_assumptions c, get_smtlib_decls c);; - -let parse_smtlib_string_formula c a1 a2 a3 a4 a5 = +let parse_smtlib_string_formula c a1 a2 a3 a4 a5 = (parse_smtlib_string c a1 a2 a3 a4 a5; match get_smtlib_formulas c with [|f|] -> f | _ -> failwith "Z3: parse_smtlib_string_formula");; - -let parse_smtlib_file_formula c a1 a2 a3 a4 a5 = +let parse_smtlib_file_formula c a1 a2 a3 a4 a5 = (parse_smtlib_file c a1 a2 a3 a4 a5; match get_smtlib_formulas c with [|f|] -> f | _ -> failwith "Z3: parse_smtlib_file_formula");; - -let parse_smtlib_string_x c a1 a2 a3 a4 a5 = +let parse_smtlib_string_x c a1 a2 a3 a4 a5 = (parse_smtlib_string c a1 a2 a3 a4 a5; get_smtlib_parse_results c);; - -let parse_smtlib_file_x c a1 a2 a3 a4 a5 = +let parse_smtlib_file_x c a1 a2 a3 a4 a5 = (parse_smtlib_file c a1 a2 a3 a4 a5; get_smtlib_parse_results c);; - (* Refinement: *) - type symbol_refined = | Symbol_int of int | Symbol_string of string | Symbol_unknown;; - let symbol_refine c s = match get_symbol_kind c s with | INT_SYMBOL -> Symbol_int (get_symbol_int c s) | STRING_SYMBOL -> Symbol_string (get_symbol_string c s);; - type sort_refined = | Sort_uninterpreted of symbol | Sort_bool @@ -3240,7 +3172,6 @@ type sort_refined = | Sort_relation | Sort_finite_domain | Sort_unknown of symbol;; - let sort_refine c ty = match get_sort_kind c ty with | UNINTERPRETED_SORT -> Sort_uninterpreted (get_sort_name c ty) @@ -3250,56 +3181,50 @@ let sort_refine c ty = | BV_SORT -> Sort_bv (get_bv_sort_size c ty) | ARRAY_SORT -> Sort_array (get_array_sort_domain c ty, get_array_sort_range c ty) | DATATYPE_SORT -> Sort_datatype (get_datatype_sort c ty) - | RELATION_SORT -> Sort_relation + | RELATION_SORT -> Sort_relation | FINITE_DOMAIN_SORT -> Sort_finite_domain | UNKNOWN_SORT -> Sort_unknown (get_sort_name c ty);; - -let get_pattern_terms c p = +let get_pattern_terms c p = Array.init (get_pattern_num_terms c p) (get_pattern c p) - -type binder_type = | Forall | Exists - -type numeral_refined = - | Numeral_small of int64 * int64 - | Numeral_large of string - -type term_refined = - | Term_app of decl_kind * func_decl * ast array +type binder_type = | Forall | Exists +type numeral_refined = + | Numeral_small of int64 * int64 + | Numeral_large of string +type term_refined = + | Term_app of decl_kind * func_decl * ast array | Term_quantifier of binder_type * int * ast array array * (symbol *sort) array * ast - | Term_numeral of numeral_refined * sort - | Term_var of int * sort - -let term_refine c t = + | Term_numeral of numeral_refined * sort + | Term_var of int * sort +let term_refine c t = match get_ast_kind c t with - | NUMERAL_AST -> + | NUMERAL_AST -> let (is_small, n, d) = get_numeral_small c t in - if is_small then - Term_numeral(Numeral_small(n,d), get_sort c t) + if is_small then + Term_numeral(Numeral_small(n,d), get_sort c t) else - Term_numeral(Numeral_large(get_numeral_string c t), get_sort c t) - | APP_AST -> + Term_numeral(Numeral_large(get_numeral_string c t), get_sort c t) + | APP_AST -> let t' = to_app c t in - let f = get_app_decl c t' in + let f = get_app_decl c t' in let num_args = get_app_num_args c t' in let args = Array.init num_args (get_app_arg c t') in let k = get_decl_kind c f in Term_app (k, f, args) - | QUANTIFIER_AST -> + | QUANTIFIER_AST -> let bt = if is_quantifier_forall c t then Forall else Exists in - let w = get_quantifier_weight c t in - let np = get_quantifier_num_patterns c t in - let pats = Array.init np (get_quantifier_pattern_ast c t) in - let pats = Array.map (get_pattern_terms c) pats in - let nb = get_quantifier_num_bound c t in - let bound = Array.init nb - (fun i -> (get_quantifier_bound_name c t i, get_quantifier_bound_sort c t i)) in + let w = get_quantifier_weight c t in + let np = get_quantifier_num_patterns c t in + let pats = Array.init np (get_quantifier_pattern_ast c t) in + let pats = Array.map (get_pattern_terms c) pats in + let nb = get_quantifier_num_bound c t in + let bound = Array.init nb + (fun i -> (get_quantifier_bound_name c t i, get_quantifier_bound_sort c t i)) in let body = get_quantifier_body c t in Term_quantifier(bt, w, pats, bound, body) - | VAR_AST -> + | VAR_AST -> Term_var(get_index_value c t, get_sort c t) | _ -> assert false - -type theory_callbacks = +type theory_callbacks = { mutable delete_theory : unit -> unit; mutable reduce_eq : ast -> ast -> ast option; @@ -3318,8 +3243,7 @@ type theory_callbacks = mutable new_assignment: ast -> bool -> unit; mutable new_relevant : ast -> unit; } - -let mk_theory_callbacks() = +let mk_theory_callbacks() = { delete_theory = (fun () -> ()); reduce_eq = (fun _ _ -> None); @@ -3338,8 +3262,6 @@ let mk_theory_callbacks() = new_assignment = (fun _ _ -> ()); new_relevant = (fun _ -> ()); } - - external get_theory_callbacks : theory -> theory_callbacks = "get_theory_callbacks" external mk_theory_register : context -> string -> theory_callbacks -> theory = "mk_theory_register" external set_delete_callback_register : theory -> unit = "set_delete_callback_register" @@ -3358,146 +3280,116 @@ external set_new_eq_callback_register : theory -> unit = "set_new_eq_callback_re external set_new_diseq_callback_register : theory -> unit = "set_new_diseq_callback_register" external set_new_assignment_callback_register : theory -> unit = "set_new_assignment_callback_register" external set_new_relevant_callback_register : theory -> unit = "set_new_relevant_callback_register" - -let is_some opt = +let is_some opt = match opt with | Some v -> true - | None -> false - -let get_some opt = + | None -> false +let get_some opt = match opt with | Some v -> v - | None -> failwith "None unexpected" - - - - + | None -> failwith "None unexpected" let apply_delete (th:theory_callbacks) = th.delete_theory () -let set_delete_callback th cb = +let set_delete_callback th cb = let cbs = get_theory_callbacks th in cbs.delete_theory <- cb; set_delete_callback_register th - -let mk_theory context name = +let mk_theory context name = Callback.register "is_some" is_some; Callback.register "get_some" get_some; Callback.register "apply_delete" apply_delete; let cbs = mk_theory_callbacks() in mk_theory_register context name cbs - - let apply_reduce_app (th:theory_callbacks) f args = th.reduce_app f args -let set_reduce_app_callback th cb = +let set_reduce_app_callback th cb = Callback.register "apply_reduce_app" apply_reduce_app; let cbs = get_theory_callbacks th in cbs.reduce_app <- cb; set_reduce_app_callback_register th - let apply_reduce_eq (th:theory_callbacks) a b = th.reduce_eq a b -let set_reduce_eq_callback th cb = +let set_reduce_eq_callback th cb = Callback.register "apply_reduce_eq" apply_reduce_eq; let cbs = get_theory_callbacks th in cbs.reduce_eq <- cb; set_reduce_eq_callback_register th - let apply_reduce_distinct (th:theory_callbacks) args = th.reduce_distinct args -let set_reduce_distinct_callback th cb = +let set_reduce_distinct_callback th cb = Callback.register "apply_reduce_distinct" apply_reduce_distinct; let cbs = get_theory_callbacks th in cbs.reduce_distinct <- cb; set_reduce_distinct_callback_register th - - let apply_new_app (th:theory_callbacks) a = th.new_app a -let set_new_app_callback th cb = +let set_new_app_callback th cb = Callback.register "apply_new_app" apply_new_app; let cbs = get_theory_callbacks th in cbs.new_app <- cb; set_new_app_callback_register th - let apply_new_elem (th:theory_callbacks) a = th.new_elem a -let set_new_elem_callback th cb = +let set_new_elem_callback th cb = Callback.register "apply_new_elem" apply_new_elem; let cbs = get_theory_callbacks th in cbs.new_elem <- cb; set_new_elem_callback_register th - - let apply_init_search (th:theory_callbacks) = th.init_search() -let set_init_search_callback th cb = +let set_init_search_callback th cb = Callback.register "apply_init_search" apply_init_search; let cbs = get_theory_callbacks th in cbs.init_search <- cb; set_init_search_callback_register th - - let apply_push (th:theory_callbacks) = th.push() -let set_push_callback th cb = +let set_push_callback th cb = Callback.register "apply_push" apply_push; let cbs = get_theory_callbacks th in cbs.push <- cb; set_push_callback_register th - let apply_pop (th:theory_callbacks) = th.pop() -let set_pop_callback th cb = +let set_pop_callback th cb = Callback.register "apply_pop" apply_pop; let cbs = get_theory_callbacks th in cbs.pop <- cb; set_pop_callback_register th - - let apply_restart (th:theory_callbacks) = th.restart() -let set_restart_callback th cb = +let set_restart_callback th cb = Callback.register "apply_restart" apply_restart; let cbs = get_theory_callbacks th in cbs.restart <- cb; set_restart_callback_register th - - let apply_reset (th:theory_callbacks) = th.reset() -let set_reset_callback th cb = +let set_reset_callback th cb = Callback.register "apply_reset" apply_reset; let cbs = get_theory_callbacks th in cbs.reset <- cb; set_reset_callback_register th - let apply_final_check (th:theory_callbacks) = th.final_check() -let set_final_check_callback th cb = +let set_final_check_callback th cb = Callback.register "apply_final_check" apply_final_check; let cbs = get_theory_callbacks th in cbs.final_check <- cb; set_final_check_callback_register th - let apply_new_eq (th:theory_callbacks) a b = th.new_eq a b -let set_new_eq_callback th cb = +let set_new_eq_callback th cb = Callback.register "apply_new_eq" apply_new_eq; let cbs = get_theory_callbacks th in cbs.new_eq <- cb; set_new_eq_callback_register th - - let apply_new_diseq (th:theory_callbacks) a b = th.new_diseq a b -let set_new_diseq_callback th cb = +let set_new_diseq_callback th cb = Callback.register "apply_new_diseq" apply_new_diseq; let cbs = get_theory_callbacks th in cbs.new_diseq <- cb; set_new_diseq_callback_register th - let apply_new_assignment (th:theory_callbacks) a b = th.new_assignment a b -let set_new_assignment_callback th cb = +let set_new_assignment_callback th cb = Callback.register "apply_new_assignment" apply_new_assignment; let cbs = get_theory_callbacks th in cbs.new_assignment <- cb; set_new_assignment_callback_register th - let apply_new_relevant (th:theory_callbacks) a = th.new_relevant a -let set_new_relevant_callback th cb = +let set_new_relevant_callback th cb = Callback.register "apply_new_relevant" apply_new_relevant; let cbs = get_theory_callbacks th in cbs.new_relevant <- cb; set_new_relevant_callback_register th - end diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index b0935f03c..4dd3d5b14 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -268,24 +268,17 @@ and goal_prec = (** - - *) (** {2 {L Types}} - - - Most of the types in the API are abstract. - - + Most of the types in the API are abstract. - [context]: manager of all other Z3 objects, global configuration options, etc. - - [symbol]: Lisp-like symbol used to name types, constants, and functions. A symbol can be created using string or integers. + - [symbol]: Lisp-like symbol used to name types, constants, and functions. A symbol can be created using string or integers. - [ast]: abstract syntax tree node. That is, the data-structure used in Z3 to represent terms, formulas and types. - [sort]: kind of AST used to represent types. - [func_decl]: kind of AST used to represent function symbols. - [app]: kind of AST used to represent function applications. - [pattern]: kind of AST used to represent pattern and multi-patterns used to guide quantifier instantiation. - - [params]: parameter set used to configure many components such as: simplifiers, tactics, solvers, etc. - [model]: model for the constraints asserted into the logical context. - [func_interp]: interpretation of a function in a model. @@ -301,23 +294,21 @@ and goal_prec = - [stats]: statistical data for a solver. *) (** - {!lbool} + {!lbool} Lifted Boolean type: [false], [undefined], [true]. *) (** - {!symbol_kind} + {!symbol_kind} The different kinds of symbol. In Z3, a symbol can be represented using integers and strings (See {!get_symbol_kind}). - - {b See also}: {!mk_int_symbol} - {b See also}: {!mk_string_symbol} *) (** - {!parameter_kind} + {!parameter_kind} The different kinds of parameters that can be associated with function symbols. - {b See also}: {!get_decl_num_parameters} - {b See also}: {!get_decl_parameter_kind} - - PARAMETER_INT is used for integer parameters. - PARAMETER_DOUBLE is used for double parameters. - PARAMETER_RATIONAL is used for parameters that are rational numbers. @@ -327,229 +318,131 @@ and goal_prec = - PARAMETER_FUNC_DECL is used for function declaration parameters. *) (** - {!sort_kind} + {!sort_kind} The different kinds of Z3 types (See {!get_sort_kind}). *) (** - {!ast_kind} + {!ast_kind} The different kinds of Z3 AST (abstract syntax trees). That is, terms, formulas and types. - - - APP_AST: constant and applications - - NUMERAL_AST: numeral constants - - VAR_AST: bound variables - - QUANTIFIER_AST: quantifiers - - SORT_AST: sort - - FUNC_DECL_AST: function declaration - - UNKNOWN_AST: internal + - APP_AST: constant and applications + - NUMERAL_AST: numeral constants + - VAR_AST: bound variables + - QUANTIFIER_AST: quantifiers + - SORT_AST: sort + - FUNC_DECL_AST: function declaration + - UNKNOWN_AST: internal *) (** - {!decl_kind} + {!decl_kind} The different kinds of interpreted function kinds. - - OP_TRUE The constant true. - - OP_FALSE The constant false. - - OP_EQ The equality predicate. - - OP_DISTINCT The n-ary distinct predicate (every argument is mutually distinct). - - OP_ITE The ternary if-then-else term. - - OP_AND n-ary conjunction. - - OP_OR n-ary disjunction. - - OP_IFF equivalence (binary). - - OP_XOR Exclusive or. - - OP_NOT Negation. - - OP_IMPLIES Implication. - - OP_OEQ Binary equivalence modulo namings. This binary predicate is used in proof terms. It captures equisatisfiability and equivalence modulo renamings. - - OP_ANUM Arithmetic numeral. - - OP_AGNUM Arithmetic algebraic numeral. Algebraic numbers are used to represent irrational numbers in Z3. - - OP_LE <=. - - OP_GE >=. - - OP_LT <. - - OP_GT >. - - OP_ADD Addition - Binary. - - OP_SUB Binary subtraction. - - OP_UMINUS Unary minus. - - OP_MUL Multiplication - Binary. - - OP_DIV Division - Binary. - - OP_IDIV Integer division - Binary. - - OP_REM Remainder - Binary. - - OP_MOD Modulus - Binary. - - OP_TO_REAL Coercion of integer to real - Unary. - - OP_TO_INT Coercion of real to integer - Unary. - - OP_IS_INT Check if real is also an integer - Unary. - - OP_POWER Power operator x^y. - - OP_STORE Array store. It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. - - - OP_SELECT Array select. - + Array store takes at least 3 arguments. + - OP_SELECT Array select. - OP_CONST_ARRAY The constant array. For example, select(const(v),i) = v holds for every v and i. The function is unary. - - OP_ARRAY_DEFAULT Default value of arrays. For example default(const(v)) = v. The function is unary. - - OP_ARRAY_MAP Array map operator. It satisfies map[f](a1,..,a_n)[i] = f(a1[i],...,a_n[i]) for every i. - - OP_SET_UNION Set union between two Booelan arrays (two arrays whose range type is Boolean). The function is binary. - - OP_SET_INTERSECT Set intersection between two Boolean arrays. The function is binary. - - OP_SET_DIFFERENCE Set difference between two Boolean arrays. The function is binary. - - OP_SET_COMPLEMENT Set complement of a Boolean array. The function is unary. - - OP_SET_SUBSET Subset predicate between two Boolean arrays. The relation is binary. - - OP_AS_ARRAY An array value that behaves as the function graph of the function passed as parameter. - - OP_BNUM Bit-vector numeral. - - OP_BIT1 One bit bit-vector. - - OP_BIT0 Zero bit bit-vector. - - OP_BNEG Unary minus. - - OP_BADD Binary addition. - - OP_BSUB Binary subtraction. - - OP_BMUL Binary multiplication. - - OP_BSDIV Binary signed division. - - OP_BUDIV Binary unsigned int division. - - OP_BSREM Binary signed remainder. - - OP_BUREM Binary unsigned int remainder. - - OP_BSMOD Binary signed modulus. - - OP_BSDIV0 Unary function. bsdiv(x,0) is congruent to bsdiv0(x). - - OP_BUDIV0 Unary function. budiv(x,0) is congruent to budiv0(x). - - OP_BSREM0 Unary function. bsrem(x,0) is congruent to bsrem0(x). - - OP_BUREM0 Unary function. burem(x,0) is congruent to burem0(x). - - OP_BSMOD0 Unary function. bsmod(x,0) is congruent to bsmod0(x). - - OP_ULEQ Unsigned bit-vector <= - Binary relation. - - - OP_SLEQ Signed bit-vector <= - Binary relation. - - - OP_UGEQ Unsigned bit-vector >= - Binary relation. - - - OP_SGEQ Signed bit-vector >= - Binary relation. - - - OP_ULT Unsigned bit-vector < - Binary relation. - + - OP_SLEQ Signed bit-vector <= - Binary relation. + - OP_UGEQ Unsigned bit-vector >= - Binary relation. + - OP_SGEQ Signed bit-vector >= - Binary relation. + - OP_ULT Unsigned bit-vector < - Binary relation. - OP_SLT Signed bit-vector < - Binary relation. - - OP_UGT Unsigned bit-vector > - Binary relation. - - OP_SGT Signed bit-vector > - Binary relation. - - OP_BAND Bit-wise and - Binary. - - OP_BOR Bit-wise or - Binary. - - OP_BNOT Bit-wise not - Unary. - - OP_BXOR Bit-wise xor - Binary. - - OP_BNAND Bit-wise nand - Binary. - - OP_BNOR Bit-wise nor - Binary. - - OP_BXNOR Bit-wise xnor - Binary. - - OP_CONCAT Bit-vector concatenation - Binary. - - OP_SIGN_EXT Bit-vector sign extension. - - OP_ZERO_EXT Bit-vector zero extension. - - OP_EXTRACT Bit-vector extraction. - - OP_REPEAT Repeat bit-vector n times. - - OP_BREDOR Bit-vector reduce or - Unary. - - OP_BREDAND Bit-vector reduce and - Unary. - - OP_BCOMP . - - OP_BSHL Shift left. - - OP_BLSHR Logical shift right. - - OP_BASHR Arithmetical shift right. - - OP_ROTATE_LEFT Left rotation. - - OP_ROTATE_RIGHT Right rotation. - - OP_EXT_ROTATE_LEFT (extended) Left rotation. Similar to OP_ROTATE_LEFT, but it is a binary operator instead of a parametric one. - - OP_EXT_ROTATE_RIGHT (extended) Right rotation. Similar to OP_ROTATE_RIGHT, but it is a binary operator instead of a parametric one. - - OP_INT2BV Coerce integer to bit-vector. NB. This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. - - OP_BV2INT Coerce bit-vector to integer. NB. This function is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. - - - OP_CARRY Compute the carry bit in a full-adder. + - OP_CARRY 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))) - - OP_XOR3 Compute ternary XOR. The meaning is given by the equivalence (xor3 l1 l2 l3) <=> (xor (xor l1 l2) l3) - - OP_PR_UNDEF: Undef/Null proof object. - - OP_PR_TRUE: Proof for the expression 'true'. - - OP_PR_ASSERTED: Proof for a fact asserted by the user. - - OP_PR_GOAL: Proof for a fact (tagged as goal) asserted by the user. - - OP_PR_MODUS_PONENS: Given a proof for p and a proof for (implies p q), produces a proof for q. {e T1: p @@ -557,19 +450,16 @@ and goal_prec = [mp T1 T2]: q } The second antecedents may also be a proof for (iff p q). - - OP_PR_REFLEXIVITY: A proof for (R t t), where R is a reflexive relation. This proof object has no antecedents. - The only reflexive relations that are used are + The only reflexive relations that are used are equivalence modulo namings, equality and equivalence. That is, R is either '~', '=' or 'iff'. - - OP_PR_SYMMETRY: Given an symmetric relation R and a proof for (R t s), produces a proof for (R s t). {e T1: (R t s) [symmetry T1]: (R s t) } T1 is the antecedent of this proof object. - - OP_PR_TRANSITIVITY: Given a transitive relation R, and proofs for (R t s) and (R s u), produces a proof for (R t u). {e @@ -577,10 +467,8 @@ and goal_prec = T2: (R s u) [trans T1 T2]: (R t u) } - - OP_PR_TRANSITIVITY_STAR: Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. - + It combines several symmetry and transitivity proofs. Example: {e T1: (R a b) @@ -589,13 +477,11 @@ and goal_prec = [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, + 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. - - OP_PR_MONOTONICITY: Monotonicity proof object. {e T1: (R t_1 s_1) @@ -605,58 +491,42 @@ and goal_prec = } Remark: if t_i == s_i, then the antecedent Ti is suppressed. That is, reflexivity proofs are supressed to save space. - - OP_PR_QUANT_INTRO: 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)) - - - OP_PR_DISTRIBUTIVITY: Distributivity proof object. + - OP_PR_DISTRIBUTIVITY: Distributivity proof object. 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 + Remark. This rule is used by the CNF conversion pass and instantiated by f = or, and g = and. - - OP_PR_AND_ELIM: Given a proof for (and l_1 ... l_n), produces a proof for l_i - {e T1: (and l_1 ... l_n) [and-elim T1]: l_i } - OP_PR_NOT_OR_ELIM: Given a proof for (not (or l_1 ... l_n)), produces a proof for (not l_i). - {e T1: (not (or l_1 ... l_n)) [not-or-elim T1]: (not l_i) } - - OP_PR_REWRITE: 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), + 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: {e (= (+ x 0) x) (= (+ x 1 2) (+ 3 x)) (iff (or x false) x) } - - OP_PR_REWRITE_STAR: 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. @@ -666,44 +536,31 @@ and goal_prec = - 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) - - OP_PR_PULL_QUANT: A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. - - OP_PR_PULL_QUANT_STAR: 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 is only used if the parameter PROOF_MODE is 1. This proof object has no antecedents. - - OP_PR_PUSH_QUANT: A proof for: - {e (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. - - - OP_PR_ELIM_UNUSED_VARS: + - OP_PR_ELIM_UNUSED_VARS: 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])) - + (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. - - OP_PR_DER: A proof for destructive equality resolution: (iff (forall (x) (or (not (= x t)) P[x])) P[t]) if x does not occur in t. - This proof object has no antecedents. - Several variables can be eliminated simultaneously. - - OP_PR_QUANT_INST: A proof of (or (not (forall (x) (P x))) (P a)) - - OP_PR_HYPOTHESIS: Mark a hypothesis in a natural deduction style proof. - - - OP_PR_LEMMA: - + - OP_PR_LEMMA: {e T1: false [lemma T1]: (or (not l_1) ... (not l_n)) @@ -711,22 +568,19 @@ and goal_prec = 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. - - - OP_PR_UNIT_RESOLUTION: + - OP_PR_UNIT_RESOLUTION: {e - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) ... - T(n+1): (not l_n) + T(n+1): (not l_n) [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') } - - - OP_PR_IFF_TRUE: + - OP_PR_IFF_TRUE: {e T1: p [iff-true T1]: (iff p true) } - - OP_PR_IFF_FALSE: {e T1: (not p) @@ -736,14 +590,14 @@ and goal_prec = - OP_PR_COMMUTATIVITY: [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. - + - OP_PR_DEF_AXIOM: Proof object used to justify Tseitin's like axioms: - + {e (or (not (and p q)) p) (or (not (and p q)) q) @@ -772,7 +626,7 @@ and goal_prec = You can recover the propositional tautologies by unfolding the Boolean connectives in the axioms a small bounded number of steps (=3). - + - OP_PR_DEF_INTRO: 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: @@ -788,17 +642,17 @@ and goal_prec = [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) Otherwise: - [def-intro]: (= n e) + [def-intro]: (= n e) - - OP_PR_APPLY_DEF: + - OP_PR_APPLY_DEF: [apply-def T1]: F ~ n F is 'equivalent' to n, given that T1 is a proof that n is a name for F. - + - OP_PR_IFF_OEQ: T1: (iff p q) [iff~ T1]: (~ p q) - + - OP_PR_NNF_POS: Proof for a (positive) NNF step. Example: {e T1: (not s_1) ~ r_1 @@ -813,7 +667,7 @@ and goal_prec = The quantifier is retained (unless the bound variables are eliminated). Example {e - T1: q ~ q_new + 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 @@ -822,7 +676,7 @@ and goal_prec = NNF_NEG furthermore handles the case where negation is pushed over Boolean connectives 'and' and 'or'. - + - OP_PR_NFF_NEG: Proof for a (negative) NNF step. Examples: {e T1: (not s_1) ~ r_1 @@ -843,24 +697,24 @@ and goal_prec = (and (or r_1 r_2) (or r_1' r_2'))) } - OP_PR_NNF_STAR: 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 is only used if the parameter PROOF_MODE is 1. + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - OP_PR_CNF_STAR: 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. + 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. + + - OP_PR_SKOLEMIZE: Proof for: - - OP_PR_SKOLEMIZE: Proof for: - {e [sk]: (~ (not (forall x (p x y))) (not (p (sk y) y))) [sk]: (~ (exists x (p x y)) (p (sk y) y)) } This proof object has no antecedents. - + - OP_PR_MODUS_PONENS_OEQ: Modus ponens style rule for equi-satisfiability. {e T1: p @@ -873,9 +727,9 @@ and goal_prec = 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. + 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. @@ -906,7 +760,7 @@ and goal_prec = {e (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln-1)) } - In other words we use the following (Prolog style) convention for Horn + In other words we use the following (Prolog style) convention for Horn implications: The head of a Horn implication is position 0, the first conjunct in the body of an implication is position 1 @@ -929,16 +783,16 @@ and goal_prec = - OP_RA_STORE: Insert a record into a relation. - The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements + The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements correspond to the [n] columns of the relation. - - OP_RA_EMPTY: Creates the empty relation. - + - OP_RA_EMPTY: Creates the empty relation. + - OP_RA_IS_EMPTY: Tests if the relation is empty. - OP_RA_JOIN: Create the relational join. - - OP_RA_UNION: Create the union or convex hull of two relations. + - OP_RA_UNION: Create the union or convex hull of two relations. The function takes two arguments. - OP_RA_WIDEN: Widen two relations. @@ -948,7 +802,7 @@ and goal_prec = The function takes one argument. - OP_RA_FILTER: Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. + 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. @@ -963,23 +817,23 @@ and goal_prec = target are elements in x in pos, such that there is no y in neg that agrees with x on the columns c1, d1, .., cN, dN. - - - OP_RA_RENAME: rename columns in the relation. + + - OP_RA_RENAME: rename columns in the relation. The function takes one argument. The parameters contain the renaming as a cycle. - + - OP_RA_COMPLEMENT: Complement the relation. - OP_RA_SELECT: Check if a record is an element of the relation. The function takes [n+1] arguments, where the first argument is a relation, and the remaining [n] arguments correspond to a record. - - OP_RA_CLONE: Create a fresh copy (clone) of a relation. + - OP_RA_CLONE: Create a fresh copy (clone) of a relation. The function is logically the identity, but in the context of a register machine allows - for [OP_RA_UNION] + for [OP_RA_UNION] to perform destructive updates to the first argument. - + - OP_FD_LT: A less than predicate over the finite domain FINITE_DOMAIN_SORT. @@ -999,10 +853,10 @@ and goal_prec = - OP_UNINTERPRETED: kind used for uninterpreted symbols. *) (** - {!param_kind} + {!param_kind} The different kinds of parameters that can be associated with parameter sets. - (see {!mk_params}). + (see {!mk_params}). - PK_UINT integer parameters. - PK_BOOL boolean parameters. @@ -1013,140 +867,113 @@ and goal_prec = - PK_INVALID invalid parameter. *) (** - {!search_failure} + {!search_failure} The different kinds of search failure types. - - NO_FAILURE: The last search was successful - - UNKNOWN: Undocumented failure reason - - TIMEOUT: Timeout - - MEMOUT_WATERMAK: Search hit a memory high-watermak limit - - CANCELED: External cancel flag was set - - NUM_CONFLICTS: Maximum number of conflicts was reached - - THEORY: Theory is incomplete - - QUANTIFIERS: Logical context contains universal quantifiers + - NO_FAILURE: The last search was successful + - UNKNOWN: Undocumented failure reason + - TIMEOUT: Timeout + - MEMOUT_WATERMAK: Search hit a memory high-watermak limit + - CANCELED: External cancel flag was set + - NUM_CONFLICTS: Maximum number of conflicts was reached + - THEORY: Theory is incomplete + - QUANTIFIERS: Logical context contains universal quantifiers *) (** - {!ast_print_mode} + {!ast_print_mode} Z3 pretty printing modes (See {!set_ast_print_mode}). - - PRINT_SMTLIB_FULL: Print AST nodes in SMTLIB verbose format. - - PRINT_LOW_LEVEL: Print AST nodes using a low-level format. + - PRINT_SMTLIB_FULL: Print AST nodes in SMTLIB verbose format. + - PRINT_LOW_LEVEL: Print AST nodes using a low-level format. - PRINT_SMTLIB_COMPLIANT: Print AST nodes in SMTLIB 1.x compliant format. - PRINT_SMTLIB2_COMPLIANT: Print AST nodes in SMTLIB 2.x compliant format. *) (** - {!error_code} - Z3 error codes - - - OK: No error. - - SORT_ERROR: User tried to build an invalid (type incorrect) AST. - - IOB: Index out of bounds. - - INVALID_ARG: Invalid argument was provided. - - PARSER_ERROR: An error occurred when parsing a string or file. - - NO_PARSER: Parser output is not available, that is, user didn't invoke {!parse_smtlib_string} or {!parse_smtlib_file}. + {!error_code} + Z3 error codes + + - OK: No error. + - SORT_ERROR: User tried to build an invalid (type incorrect) AST. + - IOB: Index out of bounds. + - INVALID_ARG: Invalid argument was provided. + - PARSER_ERROR: An error occurred when parsing a string or file. + - NO_PARSER: Parser output is not available, that is, user didn't invoke {!parse_smtlib_string} or {!parse_smtlib_file}. - INVALID_PATTERN: Invalid pattern was used to build a quantifier. - - MEMOUT_FAIL: A memory allocation failure was encountered. + - MEMOUT_FAIL: A memory allocation failure was encountered. - FILE_ACCESS_ERRROR: A file could not be accessed. - - INVALID_USAGE: API call is invalid in the current state. + - INVALID_USAGE: API call is invalid in the current state. - INTERNAL_FATAL: An error internal to Z3 occurred. - DEC_REF_ERROR: Trying to decrement the reference counter of an AST that was deleted or the reference counter was not initialized. - - EXCEPTION: Internal Z3 exception. Additional details can be retrieved using {!get_error_msg}. + - EXCEPTION: Internal Z3 exception. Additional details can be retrieved using {!get_error_msg}. *) (** Definitions for update_api.py - - def_Type('CONFIG', 'config', 'Config') - def_Type('CONTEXT', 'context', 'ContextObj') - def_Type('AST', 'ast', 'Ast') - def_Type('APP', 'app', 'Ast') - def_Type('SORT', 'sort', 'Sort') - def_Type('FUNC_DECL', 'func_decl', 'FuncDecl') - def_Type('PATTERN', 'pattern', 'Pattern') - def_Type('MODEL', 'model', 'Model') - def_Type('LITERALS', 'literals', 'Literals') - def_Type('CONSTRUCTOR', 'constructor', 'Constructor') + + def_Type('CONFIG', 'config', 'Config') + def_Type('CONTEXT', 'context', 'ContextObj') + def_Type('AST', 'ast', 'Ast') + def_Type('APP', 'app', 'Ast') + def_Type('SORT', 'sort', 'Sort') + def_Type('FUNC_DECL', 'func_decl', 'FuncDecl') + def_Type('PATTERN', 'pattern', 'Pattern') + def_Type('MODEL', 'model', 'Model') + def_Type('LITERALS', 'literals', 'Literals') + def_Type('CONSTRUCTOR', 'constructor', 'Constructor') def_Type('CONSTRUCTOR_LIST', 'constructor_list', 'ConstructorList') - def_Type('THEORY', 'theory', 'ctypes.c_void_p') - def_Type('THEORY_DATA', 'theory_data', 'ctypes.c_void_p') - def_Type('SOLVER', 'solver', 'SolverObj') - def_Type('GOAL', 'goal', 'GoalObj') - def_Type('TACTIC', 'tactic', 'TacticObj') - def_Type('PARAMS', 'params', 'Params') - def_Type('PROBE', 'probe', 'ProbeObj') - def_Type('STATS', 'stats', 'StatsObj') - def_Type('AST_VECTOR', 'ast_vector', 'AstVectorObj') - def_Type('AST_MAP', 'ast_map', 'AstMapObj') - def_Type('APPLY_RESULT', 'apply_result', 'ApplyResultObj') - def_Type('FUNC_INTERP', 'func_interp', 'FuncInterpObj') - def_Type('FUNC_ENTRY', 'func_entry', 'FuncEntryObj') - def_Type('FIXEDPOINT', 'fixedpoint', 'FixedpointObj') - def_Type('PARAM_DESCRS', 'param_descrs', 'ParamDescrs') + def_Type('THEORY', 'theory', 'ctypes.c_void_p') + def_Type('THEORY_DATA', 'theory_data', 'ctypes.c_void_p') + def_Type('SOLVER', 'solver', 'SolverObj') + def_Type('GOAL', 'goal', 'GoalObj') + def_Type('TACTIC', 'tactic', 'TacticObj') + def_Type('PARAMS', 'params', 'Params') + def_Type('PROBE', 'probe', 'ProbeObj') + def_Type('STATS', 'stats', 'StatsObj') + def_Type('AST_VECTOR', 'ast_vector', 'AstVectorObj') + def_Type('AST_MAP', 'ast_map', 'AstMapObj') + def_Type('APPLY_RESULT', 'apply_result', 'ApplyResultObj') + def_Type('FUNC_INTERP', 'func_interp', 'FuncInterpObj') + def_Type('FUNC_ENTRY', 'func_entry', 'FuncEntryObj') + def_Type('FIXEDPOINT', 'fixedpoint', 'FixedpointObj') + def_Type('PARAM_DESCRS', 'param_descrs', 'ParamDescrs') *) (** Exceptions raised by Z3. It is safe to continue interacting with Z3 after catching [Error] exceptions. - - {b See also}: {!get_error_msg} *) exception Error of context * error_code (** - {!goal_prec} + {!goal_prec} A Goal is essentially a set of formulas. Z3 provide APIs for building strategies/tactics for solving and transforming Goals. Some of these transformations apply under/over approximations. - - - GOAL_PRECISE: Approximations/Relaxations were not applied on the goal (sat and unsat answers were preserved). - - GOAL_UNDER: Goal is the product of a under-approximation (sat answers are preserved). - - GOAL_OVER: Goal is the product of an over-approximation (unsat answers are preserved). + - GOAL_PRECISE: Approximations/Relaxations were not applied on the goal (sat and unsat answers were preserved). + - GOAL_UNDER: Goal is the product of a under-approximation (sat answers are preserved). + - GOAL_OVER: Goal is the product of an over-approximation (unsat answers are preserved). - GOAL_UNDER_OVER: Goal is garbage (it is the product of over- and under-approximations, sat and unsat answers are not preserved). *) (** {2 {L Create context}} *) (** - Summary: Create a context using the given configuration. - + Summary: Create a context using the given configuration. After a context is created, the configuration cannot be changed, although some parameters can be changed using {!update_param_value}. All main interaction with Z3 happens in the context of a [context]. - - - - - def_API('mk_context', CONTEXT, (_in(CONFIG),)) *) external mk_context: (string * string) list -> context = "caml_z3_mk_context" (** - Summary: Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - - {v - z3.exe -ini? - v} - - Only a few configuration parameters are mutable once the context is created. - The error handler is invoked when trying to modify an immutable parameter. - - - - {b See also}: {!mk_context } - + Summary: Set a value of a context parameter. + - {b See also}: {!global_param_set} def_API('update_param_value', VOID, (_in(CONTEXT), _in(STRING), _in(STRING))) *) external update_param_value : context -> string -> string -> unit = "camlidl_z3_Z3_update_param_value" (** - Summary: Get a configuration parameter. - - Returns [None] - if the parameter value does not exist. - - - - - {b See also}: {!mk_context } - + Summary: Return the value of a context parameter. + - {b See also}: {!global_param_get} def_API('get_param_value', BOOL, (_in(CONTEXT), _in(STRING), _out(STRING))) *) external get_param_value : context -> string -> string option @@ -1155,7 +982,6 @@ external get_param_value : context -> string -> string option (** Summary: Interrupt the execution of a Z3 procedure. This procedure can be used to interrupt: solvers, simplifiers and tactics. - def_API('interrupt', VOID, (_in(CONTEXT),)) *) external interrupt : context -> unit @@ -1168,10 +994,6 @@ external interrupt : context -> unit Summary: Create a Z3 (empty) parameter set. Starting at Z3 4.0, parameter sets are used to configure many components such as: simplifiers, tactics, solvers, etc. - - - - def_API('mk_params', PARAMS, (_in(CONTEXT),)) *) external mk_params : context -> params @@ -1179,7 +1001,6 @@ external mk_params : context -> params (** Summary: Add a Boolean parameter [k] with value [v] to the parameter set [p]. - def_API('params_set_bool', VOID, (_in(CONTEXT), _in(PARAMS), _in(SYMBOL), _in(BOOL))) *) external params_set_bool : context -> params -> symbol -> bool -> unit @@ -1187,7 +1008,6 @@ external params_set_bool : context -> params -> symbol -> bool -> unit (** Summary: Add a unsigned int parameter [k] with value [v] to the parameter set [p]. - def_API('params_set_uint', VOID, (_in(CONTEXT), _in(PARAMS), _in(SYMBOL), _in(UINT))) *) external params_set_uint : context -> params -> symbol -> int -> unit @@ -1195,7 +1015,6 @@ external params_set_uint : context -> params -> symbol -> int -> unit (** Summary: Add a double parameter [k] with value [v] to the parameter set [p]. - def_API('params_set_double', VOID, (_in(CONTEXT), _in(PARAMS), _in(SYMBOL), _in(DOUBLE))) *) external params_set_double : context -> params -> symbol -> float -> unit @@ -1203,7 +1022,6 @@ external params_set_double : context -> params -> symbol -> float -> unit (** Summary: Add a symbol parameter [k] with value [v] to the parameter set [p]. - def_API('params_set_symbol', VOID, (_in(CONTEXT), _in(PARAMS), _in(SYMBOL), _in(SYMBOL))) *) external params_set_symbol : context -> params -> symbol -> symbol -> unit @@ -1212,7 +1030,6 @@ external params_set_symbol : context -> params -> symbol -> symbol -> unit (** Summary: Convert a parameter set into a string. This function is mainly used for printing the contents of a parameter set. - def_API('params_to_string', STRING, (_in(CONTEXT), _in(PARAMS))) *) external params_to_string : context -> params -> string @@ -1220,9 +1037,7 @@ external params_to_string : context -> params -> string (** Summary: Validate the parameter set [p] against the parameter description set [d]. - The procedure invokes the error handler if [p] is invalid. - def_API('params_validate', VOID, (_in(CONTEXT), _in(PARAMS), _in(PARAM_DESCRS))) *) external params_validate : context -> params -> param_descrs -> unit @@ -1233,7 +1048,6 @@ external params_validate : context -> params -> param_descrs -> unit *) (** Summary: Return the kind associated with the given parameter name [n]. - def_API('param_descrs_get_kind', UINT, (_in(CONTEXT), _in(PARAM_DESCRS), _in(SYMBOL))) *) external param_descrs_get_kind : context -> param_descrs -> symbol -> param_kind @@ -1241,7 +1055,6 @@ external param_descrs_get_kind : context -> param_descrs -> symbol -> param_kind (** Summary: Return the number of parameters in the given parameter description set. - def_API('param_descrs_size', UINT, (_in(CONTEXT), _in(PARAM_DESCRS))) *) external param_descrs_size : context -> param_descrs -> int @@ -1249,9 +1062,7 @@ external param_descrs_size : context -> param_descrs -> int (** Summary: Return the number of parameters in the given parameter description set. - - {b Precondition}: i < param_descrs_size c p - def_API('param_descrs_get_name', SYMBOL, (_in(CONTEXT), _in(PARAM_DESCRS), _in(UINT))) *) external param_descrs_get_name : context -> param_descrs -> int -> symbol @@ -1260,7 +1071,6 @@ external param_descrs_get_name : context -> param_descrs -> int -> symbol (** Summary: Convert a parameter description set into a string. This function is mainly used for printing the contents of a parameter description set. - def_API('param_descrs_to_string', STRING, (_in(CONTEXT), _in(PARAM_DESCRS))) *) external param_descrs_to_string : context -> param_descrs -> string @@ -1272,7 +1082,6 @@ external param_descrs_to_string : context -> param_descrs -> string (** Refined view of a {!symbol}. - - {b See also}: {!mk_symbol} - {b See also}: {!symbol_refine} *) @@ -1283,24 +1092,19 @@ type symbol_refined = (** Summary: \[ [ mk_symbol c sr ] \] constructs the symbol described by [sr]. - - {b See also}: {!symbol_refine} *) val mk_symbol: context -> symbol_refined -> symbol (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** Summary: Create a Z3 symbol using an integer. - Symbols are used to name several term and type constructors. - NB. Not all integers can be passed to this function. The legal range of unsigned int integers is 0 to 2^30-1. - - {b See also}: {!mk_string_symbol} - def_API('mk_int_symbol', SYMBOL, (_in(CONTEXT), _in(INT))) *) external mk_int_symbol : context -> int -> symbol @@ -1308,11 +1112,8 @@ external mk_int_symbol : context -> int -> symbol (** Summary: Create a Z3 symbol using a C string. - Symbols are used to name several term and type constructors. - - {b See also}: {!mk_int_symbol} - def_API('mk_string_symbol', SYMBOL, (_in(CONTEXT), _in(STRING))) *) external mk_string_symbol : context -> string -> symbol @@ -1326,33 +1127,28 @@ external mk_string_symbol : context -> string -> symbol A datatype constructor descriptor. *) type datatype_constructor_desc = { - constructor_desc : symbol; (** name of the constructor function *) - recognizer_desc : symbol; (** name of the recognizer function *) - accessor_descs : (symbol * sort) array; (** names and sorts of the fields *) + constructor_desc : symbol; (** name of the constructor function *) + recognizer_desc : symbol; (** name of the recognizer function *) + accessor_descs : (symbol * sort) array; (** names and sorts of the fields *) } - (** A datatype is described by a name and constructor descriptors. *) type datatype_desc = symbol * datatype_constructor_desc array - (** A datatype constructor representation. *) type datatype_constructor = { - constructor : func_decl; (** constructor function *) - recognizer : func_decl; (** recognizer function *) - accessors : func_decl array; (** field accessor functions *) + constructor : func_decl; (** constructor function *) + recognizer : func_decl; (** recognizer function *) + accessors : func_decl array; (** field accessor functions *) } - (** A datatype is represented by a sort and constructors. *) type datatype = sort * datatype_constructor array - (** Refined view of a {!sort}. - - {b See also}: {!mk_sort} - {b See also}: {!sort_refine} *) @@ -1371,40 +1167,33 @@ type sort_refined = (** Summary: \[ [ mk_sort c sr ] \] constructs the sort described by [sr]. - - {b Precondition}: [sr] is not of form [Sort_relation] or [Sort_unknown], which cannot be directly constructed - {b See also}: {!mk_datatypes} - {b See also}: {!sort_refine} *) val mk_sort: context -> sort_refined -> sort - (** \[ [mk_datatypes ctx sorts_to_descriptors] \] creates mutually recursive datatypes described by [sorts_to_descriptors], which is a function from the sorts of the datatypes to be created to descriptors of the datatypes' constructors. - - {b See also}: {!Test_mlapi.forest_example} *) val mk_datatypes: context -> (sort array -> (datatype_desc array) option) -> datatype array (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** Summary: Create a free (uninterpreted) type using the given name (symbol). - Two free types are considered the same iff the have the same name. - def_API('mk_uninterpreted_sort', SORT, (_in(CONTEXT), _in(SYMBOL))) *) external mk_uninterpreted_sort : context -> symbol -> sort = "camlidl_z3_Z3_mk_uninterpreted_sort" (** - Summary: Create the Boolean type. - + Summary: Create the Boolean type. This type is used to create propositional variables and predicates. - def_API('mk_bool_sort', SORT, (_in(CONTEXT), )) *) external mk_bool_sort : context -> sort @@ -1412,24 +1201,19 @@ external mk_bool_sort : context -> sort (** Summary: Create the integer type. - This type is not the int type found in programming languages. A machine integer can be represented using bit-vectors. The function {!mk_bv_sort} creates a bit-vector type. - - {b See also}: {!mk_bv_sort} - def_API('mk_int_sort', SORT, (_in(CONTEXT), )) *) external mk_int_sort : context -> sort = "camlidl_z3_Z3_mk_int_sort" (** - Summary: Create the real type. - + Summary: Create the real type. This type is not a floating point number. Z3 does not have support for floating point numbers yet. - def_API('mk_real_sort', SORT, (_in(CONTEXT), )) *) external mk_real_sort : context -> sort @@ -1437,11 +1221,8 @@ external mk_real_sort : context -> sort (** Summary: Create a bit-vector type of the given size. - This type can also be seen as a machine integer. - - {b Remarks}: The size of the bitvector type must be greater than zero. - def_API('mk_bv_sort', SORT, (_in(CONTEXT), _in(UINT))) *) external mk_bv_sort : context -> int -> sort @@ -1449,27 +1230,21 @@ external mk_bv_sort : context -> int -> sort (** Summary: Create a named finite domain sort. - - To create constants that belong to the finite domain, + To create constants that belong to the finite domain, use the APIs for creating numerals and pass a numeric constant together with the sort returned by this call. - - - {b See also}: {!get_finite_domain_sort_size.} - + - {b See also}: {!get_finite_domain_sort_size} def_API('mk_finite_domain_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT64))) *) external mk_finite_domain_sort : context -> symbol -> int64 -> sort = "camlidl_z3_Z3_mk_finite_domain_sort" (** - Summary: Create an array type. - + Summary: Create an array type. We usually represent the array type as: {e [domain -> range] }. Arrays are usually used to model the heap/memory in software verification. - - {b See also}: {!mk_select} - {b See also}: {!mk_store} - def_API('mk_array_sort', SORT, (_in(CONTEXT), _in(SORT), _in(SORT))) *) external mk_array_sort : context -> sort -> sort -> sort @@ -1477,14 +1252,8 @@ external mk_array_sort : context -> sort -> sort -> sort (** Summary: Create a tuple type. - [mk_tuple_sort c name field_names field_sorts] creates a tuple with a constructor named [name], a [n] fields, where [n] is the size of the arrays [field_names] and [field_sorts]. - - - - - @param c logical context @param mk_tuple_name name of the constructor function associated with the tuple type. @param num_fields number of fields in the tuple type. @@ -1492,7 +1261,6 @@ external mk_array_sort : context -> sort -> sort -> sort @param field_sorts type of the tuple fields. @param mk_tuple_decl output parameter that will contain the constructor declaration. @param proj_decl output parameter that will contain the projection function declarations. This field must be a buffer of size [num_fields] allocated by the user. - def_API('mk_tuple_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _out(FUNC_DECL), _out_array(2, FUNC_DECL))) *) external mk_tuple_sort : context -> symbol -> symbol array -> sort array -> sort * func_decl * func_decl array @@ -1500,28 +1268,20 @@ external mk_tuple_sort : context -> symbol -> symbol array -> sort array -> sort (** Summary: Create a enumeration sort. - - [mk_enumeration_sort c enums] creates an enumeration sort with enumeration names [enums], + [mk_enumeration_sort c enums] creates an enumeration sort with enumeration names [enums], it also returns [n] predicates, where [n] is the number of [enums] corresponding to testing whether an element is one of the enumerants. - - - - - @param c logical context @param name name of the enumeration sort. @param n number of elemenets in enumeration sort. @param enum_names names of the enumerated elements. @param enum_consts constants corresponding to the enumerated elements. @param enum_testers predicates testing if terms of the enumeration sort correspond to an enumeration. - - For example, if this function is called with three symbols A, B, C and the name S, then - [s] is a sort whose name is S, and the function returns three terms corresponding to A, B, C in + For example, if this function is called with three symbols A, B, C and the name S, then + [s] is a sort whose name is S, and the function returns three terms corresponding to A, B, C in [enum_consts]. The array [enum_testers] has three predicates of type {e (s -> Bool) }. The first predicate (corresponding to A) is true when applied to A, and false otherwise. Similarly for the other predicates. - def_API('mk_enumeration_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SYMBOL), _out_array(2, FUNC_DECL), _out_array(2, FUNC_DECL))) *) external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_decl array * func_decl array @@ -1529,13 +1289,7 @@ external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_ (** Summary: Create a list sort - [mk_list_sort c name elem_sort] creates a list sort of [name], over elements of sort [elem_sort]. - - - - - @param c logical context @param name name of the list sort. @param elem_sort sort of list elements. @@ -1545,7 +1299,6 @@ external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_ @param is_cons_decl cons cell test. @param head_decl list head. @param tail_decl list tail. - def_API('mk_list_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(SORT), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL))) *) external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_decl * func_decl * func_decl * func_decl * func_decl @@ -1554,19 +1307,17 @@ external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_dec (* (** Summary: Create a constructor. - @param c logical context. @param name constructor name. @param recognizer name of recognizer function. @param num_fields number of fields in constructor. @param field_names names of the constructor fields. - @param sorts field sorts, [None] + @param sorts field sorts, [None] if the field sort refers to a recursive sort. @param sort_refs reference to datatype sort that is an argument to the constructor; if the corresponding - sort reference is [None], - then the value in sort_refs should be an index referring to - one of the recursive datatypes that is declared. - + sort reference is [None], + then the value in sort_refs should be an index referring to + one of the recursive datatypes that is declared. def_API('mk_constructor', CONSTRUCTOR, (_in(CONTEXT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(3, SYMBOL), _in_array(3, SORT), _in_array(3, UINT))) *) external mk_constructor : context -> symbol -> symbol -> symbol array -> sort option array -> int array -> constructor @@ -1574,24 +1325,20 @@ external mk_constructor : context -> symbol -> symbol -> symbol array -> sort op (** Summary: Reclaim memory allocated to constructor. - @param c logical context. @param constr constructor. - def_API('del_constructor', VOID, (_in(CONTEXT), _in(CONSTRUCTOR))) *) external del_constructor : context -> constructor -> unit = "camlidl_z3_Z3_del_constructor" (** - Summary: Create datatype, such as lists, trees, records, enumerations or unions of records. + Summary: Create datatype, such as lists, trees, records, enumerations or unions of records. The datatype may be recursive. Return the datatype sort. - @param c logical context. - @param name name of datatype. + @param name name of datatype. @param num_constructors number of constructors passed in. @param constructors array of constructor containers. - def_API('mk_datatype', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _inout_array(2, CONSTRUCTOR))) *) external mk_datatype : context -> symbol -> constructor array -> sort * constructor array @@ -1599,11 +1346,9 @@ external mk_datatype : context -> symbol -> constructor array -> sort * construc (** Summary: Create list of constructors. - @param c logical context. @param num_constructors number of constructors in list. @param constructors list of constructors. - def_API('mk_constructor_list', CONSTRUCTOR_LIST, (_in(CONTEXT), _in(UINT), _in_array(1, CONSTRUCTOR))) *) external mk_constructor_list : context -> constructor array -> constructor_list @@ -1611,12 +1356,9 @@ external mk_constructor_list : context -> constructor array -> constructor_list (** Summary: Reclaim memory allocated for constructor list. - Each constructor inside the constructor list must be independently reclaimed using {!del_constructor}. - @param c logical context. @param clist constructor list container. - def_API('del_constructor_list', VOID, (_in(CONTEXT), _in(CONSTRUCTOR_LIST))) *) external del_constructor_list : context -> constructor_list -> unit @@ -1624,28 +1366,24 @@ external del_constructor_list : context -> constructor_list -> unit (** Summary: Create mutually recursive datatypes. - @param c logical context. @param num_sorts number of datatype sorts. @param sort_names names of datatype sorts. - @param sorts array of datattype sorts. + @param sorts array of datatype sorts. @param constructor_lists list of constructors, one list per sort. - def_API('mk_datatypes', VOID, (_in(CONTEXT), _in(UINT), _in_array(1, SYMBOL), _out_array(1, SORT), _inout_array(1, CONSTRUCTOR_LIST))) *) external mk_datatypes : context -> symbol array -> constructor_list array -> sort array * constructor_list array = "camlidl_z3_Z3_mk_datatypes" (** - Summary: Query constructor for declared functions. - + Summary: Query constructor for declared functions. @param c logical context. @param constr constructor container. The container must have been passed in to a {!mk_datatype} call. @param num_fields number of accessor fields in the constructor. @param constructor constructor function declaration. @param tester constructor test function declaration. @param accessors array of accessor function declarations. - def_API('query_constructor', VOID, (_in(CONTEXT), _in(CONSTRUCTOR), _in(UINT), _out(FUNC_DECL), _out(FUNC_DECL), _out_array(2, FUNC_DECL))) *) external query_constructor : context -> constructor -> int -> func_decl * func_decl * func_decl array @@ -1657,22 +1395,17 @@ external query_constructor : context -> constructor -> int -> func_decl * func_d *) (** Summary: Declare a constant or function. - [mk_func_decl c n d r] creates a function with name [n], domain [d], and range [r]. - The arity of the function is the size of the array [d]. - + The arity of the function is the size of the array [d]. @param c logical context. @param s name of the constant or function. @param domain_size number of arguments. It is 0 when declaring a constant. @param domain array containing the sort of each argument. The array must contain domain_size elements. It is 0 when declaring a constant. @param range sort of the constant or the return sort of the function. - After declaring a constant or function, the function {!mk_app} can be used to create a constant or function application. - - {b See also}: {!mk_app} - def_API('mk_func_decl', FUNC_DECL, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SORT), _in(SORT))) *) external mk_func_decl : context -> symbol -> sort array -> sort -> func_decl @@ -1680,9 +1413,7 @@ external mk_func_decl : context -> symbol -> sort array -> sort -> func_decl (** Summary: Create a constant or function application. - - {b See also}: {!mk_func_decl} - def_API('mk_app', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT), _in_array(2, AST))) *) external mk_app : context -> func_decl -> ast array -> ast @@ -1690,18 +1421,9 @@ external mk_app : context -> func_decl -> ast array -> ast (** Summary: Declare and create a constant. - - - - - - - - [mk_const c s t] is a shorthand for [mk_app c (mk_func_decl c s [||] t) [||]] - + [mk_const c s t] is a shorthand for [mk_app c (mk_func_decl c s [||] t) [||]] - {b See also}: {!mk_func_decl} - {b See also}: {!mk_app} - def_API('mk_const', AST, (_in(CONTEXT), _in(SYMBOL), _in(SORT))) *) external mk_const : context -> symbol -> sort -> ast @@ -1709,14 +1431,8 @@ external mk_const : context -> symbol -> sort -> ast (** Summary: Declare a fresh constant or function. - Z3 will generate an unique name for this function declaration. - - - - - {b See also}: {!mk_func_decl} - def_API('mk_fresh_func_decl', FUNC_DECL, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SORT), _in(SORT))) *) external mk_fresh_func_decl : context -> string -> sort array -> sort -> func_decl @@ -1724,17 +1440,9 @@ external mk_fresh_func_decl : context -> string -> sort array -> sort -> func_de (** Summary: Declare and create a fresh constant. - - - - - [mk_fresh_const c p t] is a shorthand for [mk_app c (mk_fresh_func_decl c p [||] t) [||]]. - - - + [mk_fresh_const c p t] is a shorthand for [mk_app c (mk_fresh_func_decl c p [||] t) [||]]. - {b See also}: {!mk_func_decl} - {b See also}: {!mk_app} - def_API('mk_fresh_const', AST, (_in(CONTEXT), _in(STRING), _in(SORT))) *) external mk_fresh_const : context -> string -> sort -> ast @@ -1745,7 +1453,6 @@ external mk_fresh_const : context -> string -> sort -> ast *) (** Summary: Create an AST node representing [true]. - def_API('mk_true', AST, (_in(CONTEXT), )) *) external mk_true : context -> ast @@ -1753,7 +1460,6 @@ external mk_true : context -> ast (** Summary: Create an AST node representing [false]. - def_API('mk_false', AST, (_in(CONTEXT), )) *) external mk_false : context -> ast @@ -1762,51 +1468,40 @@ external mk_false : context -> ast (** Summary: \[ [ mk_eq c l r ] \] Create an AST node representing {e l = r }. - - The nodes [l] and [r] must have the same type. - + The nodes [l] and [r] must have the same type. def_API('mk_eq', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_eq : context -> ast -> ast -> ast = "camlidl_z3_Z3_mk_eq" (** - Summary: \[ [mk_distinct c [| t_1; ...; t_n |]] \] Create an AST node represeting a distinct construct. It is used for declaring - the arguments t_i pairwise distinct. - + the arguments t_i pairwise distinct. The [distinct] construct is used for declaring the arguments pairwise distinct. That is, {e Forall 0 <= i < j < num_args. not args[i] = args[j] }. - All arguments must have the same sort. - - {b Remarks}: The number of arguments of a distinct construct must be greater than one. - def_API('mk_distinct', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_distinct : context -> ast array -> ast = "camlidl_z3_Z3_mk_distinct" (** - Summary: \[ [ mk_not c a ] \] + Summary: \[ [ mk_not c a ] \] Create an AST node representing {e not(a) }. - The node [a] must have Boolean sort. - def_API('mk_not', AST, (_in(CONTEXT), _in(AST))) *) external mk_not : context -> ast -> ast = "camlidl_z3_Z3_mk_not" (** - Summary: \[ [ mk_ite c t1 t2 t2 ] \] + Summary: \[ [ mk_ite c t1 t2 t2 ] \] Create an AST node representing an if-then-else: {e ite(t1, t2, t3) }. - The node [t1] must have Boolean sort, [t2] and [t3] must have the same sort. The sort of the new node is equal to the sort of [t2] and [t3]. - def_API('mk_ite', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) *) external mk_ite : context -> ast -> ast -> ast -> ast @@ -1815,9 +1510,7 @@ external mk_ite : context -> ast -> ast -> ast -> ast (** Summary: \[ [ mk_iff c t1 t2 ] \] Create an AST node representing {e t1 iff t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_iff', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_iff : context -> ast -> ast -> ast @@ -1826,9 +1519,7 @@ external mk_iff : context -> ast -> ast -> ast (** Summary: \[ [ mk_implies c t1 t2 ] \] Create an AST node representing {e t1 implies t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_implies', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_implies : context -> ast -> ast -> ast @@ -1837,37 +1528,25 @@ external mk_implies : context -> ast -> ast -> ast (** Summary: \[ [ mk_xor c t1 t2 ] \] Create an AST node representing {e t1 xor t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_xor', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_xor : context -> ast -> ast -> ast = "camlidl_z3_Z3_mk_xor" (** - - Summary: \[ [mk_and c [| t_1; ...; t_n |]] \] Create the conjunction: {e t_1 and ... and t_n}. - - + Summary: \[ [mk_and c [| t_1; ...; t_n |]] \] Create the conjunction: {e t_1 and ... and t_n}. All arguments must have Boolean sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_and', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_and : context -> ast array -> ast = "camlidl_z3_Z3_mk_and" (** - - Summary: \[ [mk_or c [| t_1; ...; t_n |]] \] Create the disjunction: {e t_1 or ... or t_n}. - - + Summary: \[ [mk_or c [| t_1; ...; t_n |]] \] Create the disjunction: {e t_1 or ... or t_n}. All arguments must have Boolean sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_or', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_or : context -> ast array -> ast @@ -1877,110 +1556,78 @@ external mk_or : context -> ast array -> ast {2 {L Arithmetic: Integers and Reals}} *) (** - - Summary: \[ [mk_add c [| t_1; ...; t_n |]] \] Create the term: {e t_1 + ... + t_n}. - - + Summary: \[ [mk_add c [| t_1; ...; t_n |]] \] Create the term: {e t_1 + ... + t_n}. All arguments must have int or real sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_add', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_add : context -> ast array -> ast = "camlidl_z3_Z3_mk_add" (** - - Summary: \[ [mk_mul c [| t_1; ...; t_n |]] \] Create the term: {e t_1 * ... * t_n}. - - + Summary: \[ [mk_mul c [| t_1; ...; t_n |]] \] Create the term: {e t_1 * ... * t_n}. All arguments must have int or real sort. - - {b Remarks}: Z3 has limited support for non-linear arithmetic. - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_mul', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_mul : context -> ast array -> ast = "camlidl_z3_Z3_mk_mul" (** - - Summary: \[ [mk_sub c [| t_1; ...; t_n |]] \] Create the term: {e t_1 - ... - t_n}. - - + Summary: \[ [mk_sub c [| t_1; ...; t_n |]] \] Create the term: {e t_1 - ... - t_n}. All arguments must have int or real sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_sub', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_sub : context -> ast array -> ast = "camlidl_z3_Z3_mk_sub" (** - - Summary: \[ [mk_unary_minus c arg] \] Create the term: {e - arg}. - + Summary: \[ [mk_unary_minus c arg] \] Create the term: {e - arg}. The arguments must have int or real type. - def_API('mk_unary_minus', AST, (_in(CONTEXT), _in(AST))) *) external mk_unary_minus : context -> ast -> ast = "camlidl_z3_Z3_mk_unary_minus" (** - - Summary: \[ [mk_div c t_1 t_2] \] Create the term: {e t_1 div t_2}. - + Summary: \[ [mk_div c t_1 t_2] \] Create the term: {e t_1 div t_2}. The arguments must either both have int type or both have real type. If the arguments have int type, then the result type is an int type, otherwise the the result type is real. - def_API('mk_div', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_div : context -> ast -> ast -> ast = "camlidl_z3_Z3_mk_div" (** - - Summary: \[ [mk_mod c t_1 t_2] \] Create the term: {e t_1 mod t_2}. - + Summary: \[ [mk_mod c t_1 t_2] \] Create the term: {e t_1 mod t_2}. The arguments must have int type. - def_API('mk_mod', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_mod : context -> ast -> ast -> ast = "camlidl_z3_Z3_mk_mod" (** - - Summary: \[ [mk_rem c t_1 t_2] \] Create the term: {e t_1 rem t_2}. - + Summary: \[ [mk_rem c t_1 t_2] \] Create the term: {e t_1 rem t_2}. The arguments must have int type. - def_API('mk_rem', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_rem : context -> ast -> ast -> ast = "camlidl_z3_Z3_mk_rem" (** - - The arguments must have int or real type. - def_API('mk_power', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_power : context -> ast -> ast -> ast = "camlidl_z3_Z3_mk_power" (** - Summary: \[ [ mk_lt c t1 t2 ] \] + Summary: \[ [ mk_lt c t1 t2 ] \] Create less than. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_lt', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_lt : context -> ast -> ast -> ast @@ -1989,9 +1636,7 @@ external mk_lt : context -> ast -> ast -> ast (** Summary: \[ [ mk_le c t1 t2 ] \] Create less than or equal to. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_le', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_le : context -> ast -> ast -> ast @@ -2000,9 +1645,7 @@ external mk_le : context -> ast -> ast -> ast (** Summary: \[ [ mk_gt c t1 t2 ] \] Create greater than. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_gt', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_gt : context -> ast -> ast -> ast @@ -2011,9 +1654,7 @@ external mk_gt : context -> ast -> ast -> ast (** Summary: \[ [ mk_ge c t1 t2 ] \] Create greater than or equal to. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_ge', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_ge : context -> ast -> ast -> ast @@ -2022,19 +1663,14 @@ external mk_ge : context -> ast -> ast -> ast (** Summary: \[ [ mk_int2real c t1 ] \] Coerce an integer to a real. - 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 + You can take the floor of a real by creating an auxiliary integer constant [k] and - and asserting {e mk_int2real(k) <= t1 < mk_int2real(k)+1 }. - + and asserting {e mk_int2real(k) <= t1 < mk_int2real(k)+1 }. The node [t1] must have sort integer. - - {b See also}: {!mk_real2int} - {b See also}: {!mk_is_int} - def_API('mk_int2real', AST, (_in(CONTEXT), _in(AST))) *) external mk_int2real : context -> ast -> ast @@ -2043,13 +1679,10 @@ external mk_int2real : context -> ast -> ast (** Summary: \[ [ mk_real2int c t1 ] \] Coerce a real to an integer. - The semantics of this function follows the SMT-LIB standard for the function to_int - - {b See also}: {!mk_int2real} - {b See also}: {!mk_is_int} - def_API('mk_real2int', AST, (_in(CONTEXT), _in(AST))) *) external mk_real2int : context -> ast -> ast @@ -2058,10 +1691,8 @@ external mk_real2int : context -> ast -> ast (** Summary: \[ [ mk_is_int c t1 ] \] Check if a real number is an integer. - - {b See also}: {!mk_int2real} - {b See also}: {!mk_real2int} - def_API('mk_is_int', AST, (_in(CONTEXT), _in(AST))) *) external mk_is_int : context -> ast -> ast @@ -2073,9 +1704,7 @@ external mk_is_int : context -> ast -> ast (** Summary: \[ [ mk_bvnot c t1 ] \] Bitwise negation. - The node [t1] must have a bit-vector sort. - def_API('mk_bvnot', AST, (_in(CONTEXT), _in(AST))) *) external mk_bvnot : context -> ast -> ast @@ -2084,9 +1713,7 @@ external mk_bvnot : context -> ast -> ast (** Summary: \[ [ mk_bvredand c t1 ] \] Take conjunction of bits in vector, return vector of length 1. - The node [t1] must have a bit-vector sort. - def_API('mk_bvredand', AST, (_in(CONTEXT), _in(AST))) *) external mk_bvredand : context -> ast -> ast @@ -2095,9 +1722,7 @@ external mk_bvredand : context -> ast -> ast (** Summary: \[ [ mk_bvredor c t1 ] \] Take disjunction of bits in vector, return vector of length 1. - The node [t1] must have a bit-vector sort. - def_API('mk_bvredor', AST, (_in(CONTEXT), _in(AST))) *) external mk_bvredor : context -> ast -> ast @@ -2106,9 +1731,7 @@ external mk_bvredor : context -> ast -> ast (** Summary: \[ [ mk_bvand c t1 t2 ] \] Bitwise and. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvand', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvand : context -> ast -> ast -> ast @@ -2117,9 +1740,7 @@ external mk_bvand : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvor c t1 t2 ] \] Bitwise or. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvor', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvor : context -> ast -> ast -> ast @@ -2128,9 +1749,7 @@ external mk_bvor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvxor c t1 t2 ] \] Bitwise exclusive-or. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvxor', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvxor : context -> ast -> ast -> ast @@ -2138,10 +1757,8 @@ external mk_bvxor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvnand c t1 t2 ] \] - Bitwise nand. - + Bitwise nand. The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvnand', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvnand : context -> ast -> ast -> ast @@ -2149,10 +1766,8 @@ external mk_bvnand : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvnor c t1 t2 ] \] - Bitwise nor. - + Bitwise nor. The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvnor', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvnor : context -> ast -> ast -> ast @@ -2160,10 +1775,8 @@ external mk_bvnor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvxnor c t1 t2 ] \] - Bitwise xnor. - + Bitwise xnor. The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvxnor', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvxnor : context -> ast -> ast -> ast @@ -2172,9 +1785,7 @@ external mk_bvxnor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvneg c t1 ] \] Standard two's complement unary minus. - The node [t1] must have bit-vector sort. - def_API('mk_bvneg', AST, (_in(CONTEXT), _in(AST))) *) external mk_bvneg : context -> ast -> ast @@ -2183,9 +1794,7 @@ external mk_bvneg : context -> ast -> ast (** Summary: \[ [ mk_bvadd c t1 t2 ] \] Standard two's complement addition. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvadd : context -> ast -> ast -> ast @@ -2194,9 +1803,7 @@ external mk_bvadd : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsub c t1 t2 ] \] Standard two's complement subtraction. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsub : context -> ast -> ast -> ast @@ -2205,9 +1812,7 @@ external mk_bvsub : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvmul c t1 t2 ] \] Standard two's complement multiplication. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvmul : context -> ast -> ast -> ast @@ -2215,14 +1820,11 @@ external mk_bvmul : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvudiv c t1 t2 ] \] - Unsigned division. - + Unsigned division. It is defined as the [floor] of {e t1/t2 } if [t2] is different from zero. If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvudiv', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvudiv : context -> ast -> ast -> ast @@ -2231,17 +1833,11 @@ external mk_bvudiv : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsdiv c t1 t2 ] \] Two's complement signed division. - It is defined in the following way: - - The [floor] of {e t1/t2 } if [t2] is different from zero, and {e t1*t2 >= 0 }. - - The [ceiling] of {e t1/t2 } if [t2] is different from zero, and {e t1*t2 < 0 }. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsdiv', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsdiv : context -> ast -> ast -> ast @@ -2250,13 +1846,9 @@ external mk_bvsdiv : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvurem c t1 t2 ] \] Unsigned remainder. - It is defined as {e t1 - (t1 /u t2) * t2 }, where {e /u } represents unsigned int division. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvurem', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvurem : context -> ast -> ast -> ast @@ -2265,16 +1857,11 @@ external mk_bvurem : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsrem c t1 t2 ] \] Two's complement signed remainder (sign follows dividend). - It is defined as {e t1 - (t1 /s t2) * t2 }, where {e /s } represents signed division. The most significant bit (sign) of the result is equal to the most significant bit of [t1]. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - - {b See also}: {!mk_bvsmod} - def_API('mk_bvsrem', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsrem : context -> ast -> ast -> ast @@ -2283,13 +1870,9 @@ external mk_bvsrem : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsmod c t1 t2 ] \] Two's complement signed remainder (sign follows divisor). - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - - {b See also}: {!mk_bvsrem} - def_API('mk_bvsmod', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsmod : context -> ast -> ast -> ast @@ -2298,9 +1881,7 @@ external mk_bvsmod : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvult c t1 t2 ] \] Unsigned less than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvult', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvult : context -> ast -> ast -> ast @@ -2309,17 +1890,14 @@ external mk_bvult : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvslt c t1 t2 ] \] Two's complement signed less than. - It abbreviates: - {v + {v (or (and (= (extract[|m-1|:|m-1|] t1) bit1) (= (extract[|m-1|:|m-1|] t2) bit0)) (and (= (extract[|m-1|:|m-1|] t1) (extract[|m-1|:|m-1|] t2)) (bvult t1 t2))) v} - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvslt', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvslt : context -> ast -> ast -> ast @@ -2328,9 +1906,7 @@ external mk_bvslt : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvule c t1 t2 ] \] Unsigned less than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvule', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvule : context -> ast -> ast -> ast @@ -2339,9 +1915,7 @@ external mk_bvule : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsle c t1 t2 ] \] Two's complement signed less than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsle', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsle : context -> ast -> ast -> ast @@ -2350,9 +1924,7 @@ external mk_bvsle : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvuge c t1 t2 ] \] Unsigned greater than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvuge', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvuge : context -> ast -> ast -> ast @@ -2361,9 +1933,7 @@ external mk_bvuge : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsge c t1 t2 ] \] Two's complement signed greater than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsge', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsge : context -> ast -> ast -> ast @@ -2372,9 +1942,7 @@ external mk_bvsge : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvugt c t1 t2 ] \] Unsigned greater than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvugt', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvugt : context -> ast -> ast -> ast @@ -2383,9 +1951,7 @@ external mk_bvugt : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsgt c t1 t2 ] \] Two's complement signed greater than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsgt', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsgt : context -> ast -> ast -> ast @@ -2394,12 +1960,9 @@ external mk_bvsgt : context -> ast -> ast -> ast (** Summary: \[ [ mk_concat c t1 t2 ] \] Concatenate the given bit-vectors. - The nodes [t1] and [t2] must have (possibly different) bit-vector sorts - The result is a bit-vector of size {e n1+n2 }, where [n1] ([n2)] is the size of [t1] ([t2)]. - def_API('mk_concat', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_concat : context -> ast -> ast -> ast @@ -2410,9 +1973,7 @@ external mk_concat : context -> ast -> ast -> ast Extract the bits [high] down to [low] from a bitvector of size [m] to yield a new bitvector of size [n], where {e n = high - low + 1 }. - The node [t1] must have a bit-vector sort. - def_API('mk_extract', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in(AST))) *) external mk_extract : context -> int -> int -> ast -> ast @@ -2423,9 +1984,7 @@ external mk_extract : context -> int -> int -> ast -> ast Sign-extend of the given bit-vector to the (signed) equivalent bitvector of size {e m+i }, where [m] is the size of the given bit-vector. - The node [t1] must have a bit-vector sort. - def_API('mk_sign_ext', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_sign_ext : context -> int -> ast -> ast @@ -2433,12 +1992,10 @@ external mk_sign_ext : context -> int -> ast -> ast (** Summary: \[ [ mk_zero_ext c i t1 ] \] - Extend the given bit-vector with zeros to the (unsigned int) equivalent + Extend the given bit-vector with zeros to the (unsigned) equivalent bitvector of size {e m+i }, where [m] is the size of the given bit-vector. - - The node [t1] must have a bit-vector sort. - + The node [t1] must have a bit-vector sort. def_API('mk_zero_ext', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_zero_ext : context -> int -> ast -> ast @@ -2447,9 +2004,7 @@ external mk_zero_ext : context -> int -> ast -> ast (** Summary: \[ [ mk_repeat c i t1 ] \] Repeat the given bit-vector up length {e i }. - - The node [t1] must have a bit-vector sort. - + The node [t1] must have a bit-vector sort. def_API('mk_repeat', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_repeat : context -> int -> ast -> ast @@ -2458,16 +2013,12 @@ external mk_repeat : context -> int -> ast -> ast (** Summary: \[ [ mk_bvshl c t1 t2 ] \] Shift left. - It is equivalent to multiplication by {e 2^x } where [x] is the value of the third argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the + 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 nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvshl', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvshl : context -> ast -> ast -> ast @@ -2476,16 +2027,12 @@ external mk_bvshl : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvlshr c t1 t2 ] \] Logical shift right. - It is equivalent to unsigned int division by {e 2^x } where [x] is the value of the third argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the + 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 nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvlshr', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvlshr : context -> ast -> ast -> ast @@ -2494,17 +2041,13 @@ external mk_bvlshr : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvashr c t1 t2 ] \] Arithmetic shift right. - It is like logical shift right except that the most significant bits of the result always copy the most significant bit of the second argument. - - The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the + 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 nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvashr', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvashr : context -> ast -> ast -> ast @@ -2513,9 +2056,7 @@ external mk_bvashr : context -> ast -> ast -> ast (** Summary: \[ [ mk_rotate_left c i t1 ] \] Rotate bits of [t1] to the left [i] times. - - The node [t1] must have a bit-vector sort. - + The node [t1] must have a bit-vector sort. def_API('mk_rotate_left', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_rotate_left : context -> int -> ast -> ast @@ -2524,9 +2065,7 @@ external mk_rotate_left : context -> int -> ast -> ast (** Summary: \[ [ mk_rotate_right c i t1 ] \] Rotate bits of [t1] to the right [i] times. - - The node [t1] must have a bit-vector sort. - + The node [t1] must have a bit-vector sort. def_API('mk_rotate_right', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_rotate_right : context -> int -> ast -> ast @@ -2535,9 +2074,7 @@ external mk_rotate_right : context -> int -> ast -> ast (** Summary: \[ [ mk_ext_rotate_left c t1 t2 ] \] Rotate bits of [t1] to the left [t2] times. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_ext_rotate_left', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_ext_rotate_left : context -> ast -> ast -> ast @@ -2546,9 +2083,7 @@ external mk_ext_rotate_left : context -> ast -> ast -> ast (** Summary: \[ [ mk_ext_rotate_right c t1 t2 ] \] Rotate bits of [t1] to the right [t2] times. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_ext_rotate_right', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_ext_rotate_right : context -> ast -> ast -> ast @@ -2557,13 +2092,10 @@ external mk_ext_rotate_right : context -> ast -> ast -> ast (** Summary: \[ [ mk_int2bv c n t1 ] \] Create an [n] bit bit-vector from the integer argument [t1]. - - NB. This function is essentially treated as uninterpreted. + 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 node [t1] must have integer sort. - + The node [t1] must have integer sort. def_API('mk_int2bv', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_int2bv : context -> int -> ast -> ast @@ -2572,17 +2104,14 @@ external mk_int2bv : context -> int -> ast -> ast (** Summary: \[ [ mk_bv2int c t1 is_signed ] \] Create an integer from the bit-vector argument [t1]. - If [is_signed] is false, then the bit-vector [t1] is treated as unsigned int. + If [is_signed] is false, then the bit-vector [t1] is treated as unsigned int. So the result is non-negative and in the range {e [0..2^N-1] }, where N are the number of bits in [t1]. If [is_signed] is true, [t1] is treated as a signed bit-vector. - - This function is essentially treated as uninterpreted. + 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 node [t1] must have a bit-vector sort. - + The node [t1] must have a bit-vector sort. def_API('mk_bv2int', AST, (_in(CONTEXT), _in(AST), _in(BOOL))) *) external mk_bv2int : context -> ast -> bool -> ast @@ -2592,9 +2121,7 @@ external mk_bv2int : context -> ast -> bool -> ast Summary: \[ [ mk_bvadd_no_overflow c t1 t2 is_signed ] \] Create a predicate that checks that the bit-wise addition of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) *) external mk_bvadd_no_overflow : context -> ast -> ast -> bool -> ast @@ -2604,9 +2131,7 @@ external mk_bvadd_no_overflow : context -> ast -> ast -> bool -> ast Summary: \[ [ mk_bvadd_no_underflow c t1 t2 ] \] Create a predicate that checks that the bit-wise signed addition of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvadd_no_underflow : context -> ast -> ast -> ast @@ -2616,9 +2141,7 @@ external mk_bvadd_no_underflow : context -> ast -> ast -> ast Summary: \[ [ mk_bvsub_no_overflow c t1 t2 ] \] Create a predicate that checks that the bit-wise signed subtraction of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsub_no_overflow : context -> ast -> ast -> ast @@ -2628,9 +2151,7 @@ external mk_bvsub_no_overflow : context -> ast -> ast -> ast Summary: \[ [ mk_bvsub_no_underflow c t1 t2 is_signed ] \] Create a predicate that checks that the bit-wise subtraction of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) *) external mk_bvsub_no_underflow : context -> ast -> ast -> bool -> ast @@ -2638,11 +2159,9 @@ external mk_bvsub_no_underflow : context -> ast -> ast -> bool -> ast (** Summary: \[ [ mk_bvsdiv_no_overflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed division + Create a predicate that checks that the bit-wise signed division of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsdiv_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsdiv_no_overflow : context -> ast -> ast -> ast @@ -2650,11 +2169,9 @@ external mk_bvsdiv_no_overflow : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvneg_no_overflow c t1 ] \] - Check that bit-wise negation does not overflow when + Check that bit-wise negation does not overflow when [t1] is interpreted as a signed bit-vector. - The node [t1] must have bit-vector sort. - def_API('mk_bvneg_no_overflow', AST, (_in(CONTEXT), _in(AST))) *) external mk_bvneg_no_overflow : context -> ast -> ast @@ -2664,9 +2181,7 @@ external mk_bvneg_no_overflow : context -> ast -> ast Summary: \[ [ mk_bvmul_no_overflow c t1 t2 is_signed ] \] Create a predicate that checks that the bit-wise multiplication of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) *) external mk_bvmul_no_overflow : context -> ast -> ast -> bool -> ast @@ -2676,9 +2191,7 @@ external mk_bvmul_no_overflow : context -> ast -> ast -> bool -> ast Summary: \[ [ mk_bvmul_no_underflow c t1 t2 ] \] Create a predicate that checks that the bit-wise signed multiplication of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvmul_no_underflow : context -> ast -> ast -> ast @@ -2690,15 +2203,12 @@ external mk_bvmul_no_underflow : context -> ast -> ast -> ast (** Summary: \[ [ mk_select c a i ] \] Array read. - The argument [a] is the array and [i] is the index of the array that gets read. - - The node [a] must have an array sort {e [domain -> range] }, + The argument [a] is the array and [i] is the index of the array that gets read. + The node [a] must have an array sort {e [domain -> range] }, and [i] must have the sort [domain]. The sort of the result is [range]. - - {b See also}: {!mk_array_sort} - {b See also}: {!mk_store} - def_API('mk_select', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_select : context -> ast -> ast -> ast @@ -2707,18 +2217,15 @@ external mk_select : context -> ast -> ast -> ast (** Summary: \[ [ mk_store c a i v ] \] Array update. - The node [a] must have an array sort {e [domain -> range] }, [i] must have sort [domain], [v] must have sort range. The sort of the result is {e [domain -> range] }. The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http: + standard. See http://smtlib.org for more details. The result of this function is an array that is equal to [a] (with respect to [select)] - on all indices except for [i], where it maps to [v] (and the [select] of [a] with + on all indices except for [i], where it maps to [v] (and the [select] of [a] with respect to [i] may be a different value). - - {b See also}: {!mk_array_sort} - {b See also}: {!mk_select} - def_API('mk_store', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) *) external mk_store : context -> ast -> ast -> ast -> ast @@ -2726,14 +2233,11 @@ external mk_store : context -> ast -> ast -> ast -> ast (** Summary: Create the constant array. - - The resulting term is an array, such that a [select] on an arbitrary index + The resulting term is an array, such that a [select] on an arbitrary index produces the value [v]. - @param c logical context. @param domain domain sort for the array. @param v value that the array maps to. - def_API('mk_const_array', AST, (_in(CONTEXT), _in(SORT), _in(AST))) *) external mk_const_array : context -> sort -> ast -> ast @@ -2742,15 +2246,12 @@ external mk_const_array : context -> sort -> ast -> ast (** Summary: \[ [ mk_map f n args ] \] map f on the the argument arrays. - The [n] nodes [args] must be of array sorts {e [domain_i -> range_i] }. - The function declaration [f] must have type {e range_1 .. range_n -> range }. + The function declaration [f] must have type {e range_1 .. range_n -> range }. [v] must have sort range. The sort of the result is {e [domain_i -> range] }. - - {b See also}: {!mk_array_sort} - {b See also}: {!mk_store} - {b See also}: {!mk_select} - def_API('mk_map', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT), _in_array(2, AST))) *) external mk_map : context -> func_decl -> int -> ast -> ast @@ -2758,12 +2259,10 @@ external mk_map : context -> func_decl -> int -> ast -> ast (** Summary: Access the array default value. - Produces the default range value, for arrays that can be represented as + Produces the default range value, for arrays that can be represented as finite maps with a default range value. - @param c logical context. @param array array value whose default range value is accessed. - def_API('mk_array_default', AST, (_in(CONTEXT), _in(AST))) *) external mk_array_default : context -> ast -> ast @@ -2774,7 +2273,6 @@ external mk_array_default : context -> ast -> ast *) (** Summary: Create Set type. - def_API('mk_set_sort', SORT, (_in(CONTEXT), _in(SORT))) *) external mk_set_sort : context -> sort -> sort @@ -2782,7 +2280,6 @@ external mk_set_sort : context -> sort -> sort (** Summary: Create the empty set. - def_API('mk_empty_set', AST, (_in(CONTEXT), _in(SORT))) *) external mk_empty_set : context -> sort -> ast @@ -2790,7 +2287,6 @@ external mk_empty_set : context -> sort -> ast (** Summary: Create the full set. - def_API('mk_full_set', AST, (_in(CONTEXT), _in(SORT))) *) external mk_full_set : context -> sort -> ast @@ -2798,9 +2294,7 @@ external mk_full_set : context -> sort -> ast (** Summary: Add an element to a set. - The first argument must be a set, the second an element. - def_API('mk_set_add', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_set_add : context -> ast -> ast -> ast @@ -2808,9 +2302,7 @@ external mk_set_add : context -> ast -> ast -> ast (** Summary: Remove an element to a set. - The first argument must be a set, the second an element. - def_API('mk_set_del', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_set_del : context -> ast -> ast -> ast @@ -2818,7 +2310,6 @@ external mk_set_del : context -> ast -> ast -> ast (** Summary: Take the union of a list of sets. - def_API('mk_set_union', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_set_union : context -> ast array -> ast @@ -2826,7 +2317,6 @@ external mk_set_union : context -> ast array -> ast (** Summary: Take the intersection of a list of sets. - def_API('mk_set_intersect', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_set_intersect : context -> ast array -> ast @@ -2834,7 +2324,6 @@ external mk_set_intersect : context -> ast array -> ast (** Summary: Take the set difference between two sets. - def_API('mk_set_difference', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_set_difference : context -> ast -> ast -> ast @@ -2842,7 +2331,6 @@ external mk_set_difference : context -> ast -> ast -> ast (** Summary: Take the complement of a set. - def_API('mk_set_complement', AST, (_in(CONTEXT), _in(AST))) *) external mk_set_complement : context -> ast -> ast @@ -2850,9 +2338,7 @@ external mk_set_complement : context -> ast -> ast (** Summary: Check for set membership. - The first argument should be an element type of the set. - def_API('mk_set_member', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_set_member : context -> ast -> ast -> ast @@ -2860,7 +2346,6 @@ external mk_set_member : context -> ast -> ast -> ast (** Summary: Check for subsetness of sets. - def_API('mk_set_subset', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_set_subset : context -> ast -> ast -> ast @@ -2874,32 +2359,27 @@ external mk_set_subset : context -> ast -> ast -> ast Summary: \[ [ numeral_refined ] \] is the refined view of a numeral . *) type numeral_refined = - | Numeral_int of int * sort - | Numeral_int64 of int64 * sort - | Numeral_large of string * sort + | Numeral_int of int * sort + | Numeral_int64 of int64 * sort + | Numeral_large of string * sort | Numeral_rational of numeral_refined * numeral_refined (** Summary: \[ [ embed_numeral c nr ] \] constructs the numeral described by [nr]. - - {b See also}: {!numeral_refine} *) val embed_numeral: context -> numeral_refined -> ast (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** - Summary: Create a numeral of a given sort. - + Summary: Create a numeral of a given sort. @param c logical context. @param numeral A string representing the numeral value in decimal notation. If the given sort is a real, then the numeral can be a rational, that is, a string of the form {e [num]* / [num]* }. - @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, finite-domain, or bit-vectors of arbitrary size. - + @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, finite-domain, or bit-vectors of arbitrary size. - {b See also}: {!mk_int} - - def_API('mk_numeral', AST, (_in(CONTEXT), _in(STRING), _in(SORT))) *) external mk_numeral : context -> string -> sort -> ast @@ -2907,43 +2387,32 @@ external mk_numeral : context -> string -> sort -> ast (** Summary: Create a real from a fraction. - @param c logical context. @param num numerator of rational. @param den denomerator of rational. - - {b Precondition}: den != 0 - - {b See also}: {!mk_numeral} - {b See also}: {!mk_int} - - def_API('mk_real', AST, (_in(CONTEXT), _in(INT), _in(INT))) *) external mk_real : context -> int -> int -> ast = "camlidl_z3_Z3_mk_real" (** - Summary: Create a numeral of an int, bit-vector, or finite-domain sort. - + Summary: Create a numeral of an int, bit-vector, or finite-domain sort. This function can be use to create numerals that fit in a machine integer. It is slightly faster than {!mk_numeral} since it is not necessary to parse a string. - - {b See also}: {!mk_numeral} - def_API('mk_int', AST, (_in(CONTEXT), _in(INT), _in(SORT))) *) external mk_int : context -> int -> sort -> ast = "camlidl_z3_Z3_mk_int" (** - Summary: Create a numeral of a int, bit-vector, or finite-domain sort. - + Summary: Create a numeral of a int, bit-vector, or finite-domain sort. This function can be use to create numerals that fit in a machine long long integer. It is slightly faster than {!mk_numeral} since it is not necessary to parse a string. - - {b See also}: {!mk_numeral} - def_API('mk_int64', AST, (_in(CONTEXT), _in(INT64), _in(SORT))) *) external mk_int64 : context -> int64 -> sort -> ast @@ -2954,22 +2423,17 @@ external mk_int64 : context -> int64 -> sort -> ast *) (** Summary: Create a pattern for quantifier instantiation. - Z3 uses pattern matching to instantiate quantifiers. If a pattern is not provided for a quantifier, then Z3 will automatically compute a set of patterns for it. However, for optimal performance, the user should provide the patterns. - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is + non-empty. If the list comprises of more than one term, it is a called a multi-pattern. - In general, one can pass in a list of (multi-)patterns in the quantifier constructor. - - {b See also}: {!mk_forall} - {b See also}: {!mk_exists} - def_API('mk_pattern', PATTERN, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_pattern : context -> ast array -> pattern @@ -2977,12 +2441,10 @@ external mk_pattern : context -> ast array -> pattern (** Summary: Create a bound variable. - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain the meaning of de-Bruijn indices by indicating the compilation process from non-de-Bruijn formulas to de-Bruijn format. - - {v + {v 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 @@ -2990,18 +2452,14 @@ external mk_pattern : context -> ast array -> pattern 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)) v} - The last line is significant: the index of a bound variable is different depending on the scope in which it appears. The deeper x appears, the higher is its index. - @param c logical context @param index de-Bruijn index @param ty sort of the bound variable - - {b See also}: {!mk_forall} - {b See also}: {!mk_exists} - def_API('mk_bound', AST, (_in(CONTEXT), _in(UINT), _in(SORT))) *) external mk_bound : context -> int -> sort -> ast @@ -3010,21 +2468,17 @@ external mk_bound : context -> int -> sort -> ast (** Summary: Create a forall formula. It takes an expression [body] that contains bound variables of the same sorts as the sorts listed in the array [sorts]. The bound variables are de-Bruijn indices created - using {!mk_bound}. The array [decl_names] contains the names that the quantified formula uses for the + using {!mk_bound}. The array [decl_names] contains the names that the quantified formula uses for the bound variables. Z3 applies the convention that the last element in the [decl_names] and [sorts] array refers to the variable with index 0, the second to last element of [decl_names] and [sorts] refers to the variable with index 1, etc. - - [mk_forall c w p t n b] creates a forall formula, where [w] is the weight, [p] is an array of patterns, [t] is an array with the sorts of the bound variables, [n] is an array with the 'names' of the bound variables, and [b] is the body of the quantifier. Quantifiers are associated with weights indicating the importance of using the quantifier during - instantiation. - - + instantiation. @param c logical context. @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. @param num_patterns number of patterns. @@ -3033,11 +2487,9 @@ external mk_bound : context -> int -> sort -> ast @param sorts the sorts of the bound variables. @param decl_names names of the bound variables @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_bound} - {b See also}: {!mk_exists} - def_API('mk_forall', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, PATTERN), _in(UINT), _in_array(4, SORT), _in_array(4, SYMBOL), _in(AST))) *) external mk_forall : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast @@ -3045,21 +2497,18 @@ external mk_forall : context -> int -> pattern array -> sort array -> symbol arr (** Summary: Create an exists formula. Similar to {!mk_forall}. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_bound} - {b See also}: {!mk_forall} - {b See also}: {!mk_quantifier} - def_API('mk_exists', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, PATTERN), _in(UINT), _in_array(4, SORT), _in_array(4, SYMBOL), _in(AST))) *) external mk_exists : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast = "camlidl_z3_Z3_mk_exists_bytecode" "camlidl_z3_Z3_mk_exists" (** - Summary: Create a quantifier - universal or existential, with pattern hints. + Summary: Create a quantifier - universal or existential, with pattern hints. See the documentation for {!mk_forall} for an explanation of the parameters. - @param c logical context. @param is_forall flag to indicate if this is a universal or existential quantifier. @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. @@ -3069,12 +2518,10 @@ external mk_exists : context -> int -> pattern array -> sort array -> symbol arr @param sorts array of sorts of the bound variables. @param decl_names names of the bound variables. @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_bound} - {b See also}: {!mk_forall} - {b See also}: {!mk_exists} - def_API('mk_quantifier', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(UINT), _in_array(3, PATTERN), _in(UINT), _in_array(5, SORT), _in_array(5, SYMBOL), _in(AST))) *) external mk_quantifier : context -> bool -> int -> pattern array -> sort array -> symbol array -> ast -> ast @@ -3082,7 +2529,6 @@ external mk_quantifier : context -> bool -> int -> pattern array -> sort array - (** Summary: Create a quantifier - universal or existential, with pattern hints, no patterns, and attributes - @param c logical context. @param is_forall flag to indicate if this is a universal or existential quantifier. @param quantifier_id identifier to identify quantifier @@ -3096,12 +2542,10 @@ external mk_quantifier : context -> bool -> int -> pattern array -> sort array - @param sorts array of sorts of the bound variables. @param decl_names names of the bound variables. @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_bound} - {b See also}: {!mk_forall} - {b See also}: {!mk_exists} - def_API('mk_quantifier_ex', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(5, PATTERN), _in(UINT), _in_array(7, AST), _in(UINT), _in_array(9, SORT), _in_array(9, SYMBOL), _in(AST))) *) external mk_quantifier_ex : context -> bool -> int -> symbol -> symbol -> pattern array -> ast array -> sort array -> symbol array -> ast -> ast @@ -3110,19 +2554,16 @@ external mk_quantifier_ex : context -> bool -> int -> symbol -> symbol -> patter (** Summary: Create a universal quantifier using a list of constants that will form the set of bound variables. - @param c logical context. - @param weight quantifiers are associated with weights indicating the importance of using + @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. @param num_bound number of constants to be abstracted into bound variables. @param bound array of constants to be abstracted into bound variables. @param num_patterns number of patterns. @param patterns array containing the patterns created using {!mk_pattern}. @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_exists_const} - def_API('mk_forall_const', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, APP), _in(UINT), _in_array(4, PATTERN), _in(AST))) *) external mk_forall_const : context -> int -> app array -> pattern array -> ast -> ast @@ -3130,42 +2571,36 @@ external mk_forall_const : context -> int -> app array -> pattern array -> ast - (** Summary: Similar to {!mk_forall_const}. - Summary: Create an existential quantifier using a list of constants that will form the set of bound variables. - @param c logical context. - @param weight quantifiers are associated with weights indicating the importance of using + @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. @param num_bound number of constants to be abstracted into bound variables. @param bound array of constants to be abstracted into bound variables. @param num_patterns number of patterns. @param patterns array containing the patterns created using {!mk_pattern}. @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_forall_const} - def_API('mk_exists_const', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, APP), _in(UINT), _in_array(4, PATTERN), _in(AST))) *) external mk_exists_const : context -> int -> app array -> pattern array -> ast -> ast = "camlidl_z3_Z3_mk_exists_const" (** - Summary: Create a universal or existential + Summary: Create a universal or existential quantifier using a list of constants that will form the set of bound variables. - def_API('mk_quantifier_const', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(UINT), _in_array(3, APP), _in(UINT), _in_array(5, PATTERN), _in(AST))) *) external mk_quantifier_const : context -> bool -> int -> app array -> pattern array -> ast -> ast = "camlidl_z3_Z3_mk_quantifier_const_bytecode" "camlidl_z3_Z3_mk_quantifier_const" (** - Summary: Create a universal or existential + Summary: Create a universal or existential quantifier using a list of constants that will form the set of bound variables. - def_API('mk_quantifier_const_ex', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(5, APP), _in(UINT), _in_array(7, PATTERN), _in(UINT), _in_array(9, AST), _in(AST))) *) external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> app array -> pattern array -> ast array -> ast -> ast @@ -3175,7 +2610,7 @@ external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> {2 {L Accessors}} *) (** - {3 {L Symbols}} + {3 {L Symbols}} *) (** @@ -3184,13 +2619,12 @@ external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> val symbol_refine: context -> symbol -> symbol_refined (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** Summary: Return [INT_SYMBOL] if the symbol was constructed using {!mk_int_symbol}, and [STRING_SYMBOL] if the symbol was constructed using {!mk_string_symbol}. - def_API('get_symbol_kind', UINT, (_in(CONTEXT), _in(SYMBOL))) *) external get_symbol_kind : context -> symbol -> symbol_kind @@ -3198,12 +2632,9 @@ external get_symbol_kind : context -> symbol -> symbol_kind (** Summary: \[ [ get_symbol_int c s ] \] - Return the symbol int value. - + Return the symbol int value. - {b Precondition}: get_symbol_kind s == INT_SYMBOL - - {b See also}: {!mk_int_symbol} - def_API('get_symbol_int', INT, (_in(CONTEXT), _in(SYMBOL))) *) external get_symbol_int : context -> symbol -> int @@ -3211,23 +2642,16 @@ external get_symbol_int : context -> symbol -> int (** Summary: \[ [ get_symbol_string c s ] \] - Return the symbol name. - + Return the symbol name. - {b Precondition}: get_symbol_string s == STRING_SYMBOL - - - - - - {b See also}: {!mk_string_symbol} - def_API('get_symbol_string', STRING, (_in(CONTEXT), _in(SYMBOL))) *) external get_symbol_string : context -> symbol -> string = "camlidl_z3_Z3_get_symbol_string" (** - {3 {L Sorts}} + {3 {L Sorts}} *) (** @@ -3236,8 +2660,7 @@ external get_symbol_string : context -> symbol -> string val sort_refine: context -> sort -> sort_refined (** - Summary: Return the sort name as a symbol. - + Summary: Return the sort name as a symbol. def_API('get_sort_name', SYMBOL, (_in(CONTEXT), _in(SORT))) *) external get_sort_name : context -> sort -> symbol @@ -3245,20 +2668,18 @@ external get_sort_name : context -> sort -> symbol (** Summary: Return a unique identifier for [s]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - + - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. def_API('get_sort_id', UINT, (_in(CONTEXT), _in(SORT))) *) external get_sort_id : context -> sort -> int = "camlidl_z3_Z3_get_sort_id" (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** - Summary: Convert a [sort] into [ast]. - - {b Remarks}: [sort_to_ast c s] can be replaced by [(s :> ast)]. - + Summary: Convert a [sort] into [ast]. + - {b Remarks}: [sort_to_ast c s] can be replaced by [(s :> ast)]. def_API('sort_to_ast', AST, (_in(CONTEXT), _in(SORT))) *) external sort_to_ast : context -> sort -> ast @@ -3266,8 +2687,7 @@ external sort_to_ast : context -> sort -> ast (** Summary: compare sorts. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. def_API('is_eq_sort', BOOL, (_in(CONTEXT), _in(SORT), _in(SORT))) *) external is_eq_sort : context -> sort -> sort -> bool @@ -3275,9 +2695,7 @@ external is_eq_sort : context -> sort -> sort -> bool (** Summary: Return the sort kind (e.g., array, tuple, int, bool, etc). - - {b See also}: {!sort_kind} - def_API('get_sort_kind', UINT, (_in(CONTEXT), _in(SORT))) *) external get_sort_kind : context -> sort -> sort_kind @@ -3285,23 +2703,18 @@ external get_sort_kind : context -> sort -> sort_kind (** Summary: \[ [ get_bv_sort_size c t ] \] - Return the size of the given bit-vector sort. - + Return the size of the given bit-vector sort. - {b Precondition}: get_sort_kind c t == BV_SORT - - {b See also}: {!mk_bv_sort} - {b See also}: {!get_sort_kind} - def_API('get_bv_sort_size', UINT, (_in(CONTEXT), _in(SORT))) *) external get_bv_sort_size : context -> sort -> int = "camlidl_z3_Z3_get_bv_sort_size" (** - - Summary: Return the size of the sort in [r]. Return [None] if the call failed. + Summary: Return the size of the sort in [r]. Return [None] if the call failed. That is, get_sort_kind(s) == FINITE_DOMAIN_SORT - def_API('get_finite_domain_sort_size', BOOL, (_in(CONTEXT), _in(SORT), _out(UINT64))) *) external get_finite_domain_sort_size : context -> sort -> int64 option @@ -3310,26 +2723,20 @@ external get_finite_domain_sort_size : context -> sort -> int64 option (** Summary: \[ [ get_array_sort_domain c t ] \] Return the domain of the given array sort. - - {b Precondition}: get_sort_kind c t == ARRAY_SORT - - {b See also}: {!mk_array_sort} - {b See also}: {!get_sort_kind} - def_API('get_array_sort_domain', SORT, (_in(CONTEXT), _in(SORT))) *) external get_array_sort_domain : context -> sort -> sort = "camlidl_z3_Z3_get_array_sort_domain" (** - Summary: \[ [ get_array_sort_range c t ] \] - Return the range of the given array sort. - + Summary: \[ [ get_array_sort_range c t ] \] + Return the range of the given array sort. - {b Precondition}: get_sort_kind c t == ARRAY_SORT - - {b See also}: {!mk_array_sort} - {b See also}: {!get_sort_kind} - def_API('get_array_sort_range', SORT, (_in(CONTEXT), _in(SORT))) *) external get_array_sort_range : context -> sort -> sort @@ -3338,13 +2745,10 @@ external get_array_sort_range : context -> sort -> sort (** Summary: \[ [ get_tuple_sort_mk_decl c t ] \] Return the constructor declaration of the given tuple - sort. - + sort. - {b Precondition}: get_sort_kind c t == DATATYPE_SORT - - {b See also}: {!mk_tuple_sort} - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_mk_decl', FUNC_DECL, (_in(CONTEXT), _in(SORT))) *) external get_tuple_sort_mk_decl : context -> sort -> func_decl @@ -3352,13 +2756,10 @@ external get_tuple_sort_mk_decl : context -> sort -> func_decl (** Summary: \[ [ get_tuple_sort_num_fields c t ] \] - Return the number of fields of the given tuple sort. - + Return the number of fields of the given tuple sort. - {b Precondition}: get_sort_kind c t == DATATYPE_SORT - - {b See also}: {!mk_tuple_sort} - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_num_fields', UINT, (_in(CONTEXT), _in(SORT))) *) external get_tuple_sort_num_fields : context -> sort -> int @@ -3367,14 +2768,11 @@ external get_tuple_sort_num_fields : context -> sort -> int (** Summary: \[ [ get_tuple_sort_field_decl c t i ] \] Return the i-th field declaration (i.e., projection function declaration) - of the given tuple sort. - + of the given tuple sort. - {b Precondition}: get_sort_kind t == DATATYPE_SORT - {b Precondition}: i < get_tuple_sort_num_fields c t - - {b See also}: {!mk_tuple_sort} - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_field_decl', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) *) external get_tuple_sort_field_decl : context -> sort -> int -> func_decl @@ -3382,13 +2780,10 @@ external get_tuple_sort_field_decl : context -> sort -> int -> func_decl (** Summary: Return number of constructors for datatype. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b See also}: {!get_datatype_sort_constructor} - {b See also}: {!get_datatype_sort_recognizer} - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_num_constructors', UINT, (_in(CONTEXT), _in(SORT))) *) external get_datatype_sort_num_constructors : context -> sort -> int @@ -3396,14 +2791,11 @@ external get_datatype_sort_num_constructors : context -> sort -> int (** Summary: Return idx'th constructor. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - {b Precondition}: idx < get_datatype_sort_num_constructors c t - - {b See also}: {!get_datatype_sort_num_constructors} - {b See also}: {!get_datatype_sort_recognizer} - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_constructor', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) *) external get_datatype_sort_constructor : context -> sort -> int -> func_decl @@ -3411,14 +2803,11 @@ external get_datatype_sort_constructor : context -> sort -> int -> func_decl (** Summary: Return idx'th recognizer. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - {b Precondition}: idx < get_datatype_sort_num_constructors c t - - {b See also}: {!get_datatype_sort_num_constructors} - {b See also}: {!get_datatype_sort_constructor} - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_recognizer', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) *) external get_datatype_sort_recognizer : context -> sort -> int -> func_decl @@ -3426,15 +2815,12 @@ external get_datatype_sort_recognizer : context -> sort -> int -> func_decl (** Summary: Return idx_a'th accessor for the idx_c'th constructor. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - {b Precondition}: idx_c < get_datatype_sort_num_constructors c t - {b Precondition}: idx_a < get_domain_size c get_datatype_sort_constructor c idx_c - - {b See also}: {!get_datatype_sort_num_constructors} - {b See also}: {!get_datatype_sort_constructor} - {b See also}: {!get_datatype_sort_recognizer} - def_API('get_datatype_sort_constructor_accessor', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT), _in(UINT))) *) external get_datatype_sort_constructor_accessor : context -> sort -> int -> int -> func_decl @@ -3442,11 +2828,8 @@ external get_datatype_sort_constructor_accessor : context -> sort -> int -> int (** Summary: Return arity of relation. - - {b Precondition}: get_sort_kind s == RELATION_SORT - - {b See also}: {!get_relation_column} - def_API('get_relation_arity', UINT, (_in(CONTEXT), _in(SORT))) *) external get_relation_arity : context -> sort -> int @@ -3454,24 +2837,20 @@ external get_relation_arity : context -> sort -> int (** Summary: Return sort at i'th column of relation sort. - - {b Precondition}: get_sort_kind c s == RELATION_SORT - {b Precondition}: col < get_relation_arity c s - - {b See also}: {!get_relation_arity} - def_API('get_relation_column', SORT, (_in(CONTEXT), _in(SORT), _in(UINT))) *) external get_relation_column : context -> sort -> int -> sort = "camlidl_z3_Z3_get_relation_column" (** - {3 {L Function Declarations}} + {3 {L Function Declarations}} *) (** - Summary: Convert a [func_decl] into [ast]. - - {b Remarks}: [func_decl_to_ast c f] can be replaced by [(f :> ast)]. - + Summary: Convert a [func_decl] into [ast]. + - {b Remarks}: [func_decl_to_ast c f] can be replaced by [(f :> ast)]. def_API('func_decl_to_ast', AST, (_in(CONTEXT), _in(FUNC_DECL))) *) external func_decl_to_ast : context -> func_decl -> ast @@ -3479,8 +2858,7 @@ external func_decl_to_ast : context -> func_decl -> ast (** Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. def_API('is_eq_func_decl', BOOL, (_in(CONTEXT), _in(FUNC_DECL), _in(FUNC_DECL))) *) external is_eq_func_decl : context -> func_decl -> func_decl -> bool @@ -3488,16 +2866,14 @@ external is_eq_func_decl : context -> func_decl -> func_decl -> bool (** Summary: Return a unique identifier for [f]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - + - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. def_API('get_func_decl_id', UINT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_func_decl_id : context -> func_decl -> int = "camlidl_z3_Z3_get_func_decl_id" (** - Summary: Return the constant declaration name as a symbol. - + Summary: Return the constant declaration name as a symbol. def_API('get_decl_name', SYMBOL, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_decl_name : context -> func_decl -> symbol @@ -3505,7 +2881,6 @@ external get_decl_name : context -> func_decl -> symbol (** Summary: Return declaration kind corresponding to declaration. - def_API('get_decl_kind', UINT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_decl_kind : context -> func_decl -> decl_kind @@ -3513,9 +2888,7 @@ external get_decl_kind : context -> func_decl -> decl_kind (** Summary: Return the number of parameters of the given declaration. - - {b See also}: {!get_arity} - def_API('get_domain_size', UINT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_domain_size : context -> func_decl -> int @@ -3523,9 +2896,7 @@ external get_domain_size : context -> func_decl -> int (** Summary: Alias for [get_domain_size]. - - {b See also}: {!get_domain_size} - def_API('get_arity', UINT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_arity : context -> func_decl -> int @@ -3534,11 +2905,8 @@ external get_arity : context -> func_decl -> int (** Summary: \[ [ get_domain c d i ] \] Return the sort of the i-th parameter of the given function declaration. - - {b Precondition}: i < get_domain_size d - - {b See also}: {!get_domain_size} - def_API('get_domain', SORT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_domain : context -> func_decl -> int -> sort @@ -3547,7 +2915,6 @@ external get_domain : context -> func_decl -> int -> sort (** Summary: \[ [ get_domains c d ] \] is the array of parameters of [d]. - - {b See also}: {!get_domain_size} - {b See also}: {!get_domain} *) @@ -3555,11 +2922,9 @@ val get_domains: context -> func_decl -> sort array (** Summary: \[ [ get_range c d ] \] - Return the range of the given declaration. - + Return the range of the given declaration. If [d] is a constant (i.e., has zero arguments), then this function returns the sort of the constant. - def_API('get_range', SORT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_range : context -> func_decl -> sort @@ -3567,7 +2932,6 @@ external get_range : context -> func_decl -> sort (** Summary: Return the number of parameters associated with a declaration. - def_API('get_decl_num_parameters', UINT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_decl_num_parameters : context -> func_decl -> int @@ -3575,11 +2939,9 @@ external get_decl_num_parameters : context -> func_decl -> int (** Summary: Return the parameter type associated with a declaration. - @param c the context @param d the function declaration @param idx is the index of the named parameter it should be between 0 and the number of parameters. - def_API('get_decl_parameter_kind', UINT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_parameter_kind : context -> func_decl -> int -> parameter_kind @@ -3587,9 +2949,7 @@ external get_decl_parameter_kind : context -> func_decl -> int -> parameter_kind (** Summary: Return the integer value associated with an integer parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_INT - def_API('get_decl_int_parameter', INT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_int_parameter : context -> func_decl -> int -> int @@ -3597,9 +2957,7 @@ external get_decl_int_parameter : context -> func_decl -> int -> int (** Summary: Return the double value associated with an double parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_DOUBLE - def_API('get_decl_double_parameter', DOUBLE, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_double_parameter : context -> func_decl -> int -> float @@ -3607,9 +2965,7 @@ external get_decl_double_parameter : context -> func_decl -> int -> float (** Summary: Return the double value associated with an double parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_SYMBOL - def_API('get_decl_symbol_parameter', SYMBOL, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_symbol_parameter : context -> func_decl -> int -> symbol @@ -3617,9 +2973,7 @@ external get_decl_symbol_parameter : context -> func_decl -> int -> symbol (** Summary: Return the sort value associated with a sort parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_SORT - def_API('get_decl_sort_parameter', SORT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_sort_parameter : context -> func_decl -> int -> sort @@ -3627,9 +2981,7 @@ external get_decl_sort_parameter : context -> func_decl -> int -> sort (** Summary: Return the expresson value associated with an expression parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_AST - def_API('get_decl_ast_parameter', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_ast_parameter : context -> func_decl -> int -> ast @@ -3637,9 +2989,7 @@ external get_decl_ast_parameter : context -> func_decl -> int -> ast (** Summary: Return the expresson value associated with an expression parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_FUNC_DECL - def_API('get_decl_func_decl_parameter', FUNC_DECL, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_func_decl_parameter : context -> func_decl -> int -> func_decl @@ -3647,21 +2997,18 @@ external get_decl_func_decl_parameter : context -> func_decl -> int -> func_decl (** Summary: Return the rational value, as a string, associated with a rational parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_RATIONAL - def_API('get_decl_rational_parameter', STRING, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_rational_parameter : context -> func_decl -> int -> string = "camlidl_z3_Z3_get_decl_rational_parameter" (** - {3 {L Applications}} + {3 {L Applications}} *) (** - Summary: Convert a [app] into [ast]. - - {b Remarks}: [app_to_ast c a] can be replaced by [(a :> ast)]. - + Summary: Convert a [app] into [ast]. + - {b Remarks}: [app_to_ast c a] can be replaced by [(a :> ast)]. def_API('app_to_ast', AST, (_in(CONTEXT), _in(APP))) *) external app_to_ast : context -> app -> ast @@ -3669,7 +3016,6 @@ external app_to_ast : context -> app -> ast (** Summary: Return the declaration of a constant or function application. - def_API('get_app_decl', FUNC_DECL, (_in(CONTEXT), _in(APP))) *) external get_app_decl : context -> app -> func_decl @@ -3679,7 +3025,6 @@ external get_app_decl : context -> app -> func_decl Summary: \[ [ get_app_num_args c a ] \] Return the number of argument of an application. If [t] is an constant, then the number of arguments is 0. - def_API('get_app_num_args', UINT, (_in(CONTEXT), _in(APP))) *) external get_app_num_args : context -> app -> int @@ -3688,9 +3033,7 @@ external get_app_num_args : context -> app -> int (** Summary: \[ [ get_app_arg c a i ] \] Return the i-th argument of the given application. - - {b Precondition}: i < get_num_args c a - def_API('get_app_arg', AST, (_in(CONTEXT), _in(APP), _in(UINT))) *) external get_app_arg : context -> app -> int -> ast @@ -3699,44 +3042,37 @@ external get_app_arg : context -> app -> int -> ast (** Summary: \[ [ get_app_args c a ] \] is the array of arguments of an application. If [t] is a constant, then the array is empty. - - {b See also}: {!get_app_num_args} - {b See also}: {!get_app_arg} *) val get_app_args: context -> app -> ast array (** - {3 {L Terms}} + {3 {L Terms}} *) (** Summary: \[ [ binder_type ] \] is a universal or existential quantifier. - - {b See also}: {!term_refined} *) type binder_type = Forall | Exists - (** Summary: \[ [ term_refined ] \] is the refinement of a {!ast} . - - {b See also}: {!term_refine} *) type term_refined = - | Term_numeral of numeral_refined - | Term_app of decl_kind * func_decl * ast array + | Term_numeral of numeral_refined + | Term_app of decl_kind * func_decl * ast array | Term_quantifier of binder_type * int * ast array array * (symbol * sort) array * ast - | Term_var of int * sort + | Term_var of int * sort (** Summary: \[ [ mk_term c tr ] \] constructs the term described by [tr]. - - {b Precondition}: [tr] is not of form - {b See also}: {!term_refine} *) (* val mk_term: context -> term_refined -> ast *) - - (** Summary: \[ [ term_refine c a ] \] is the refined view of [a]. *) @@ -3744,8 +3080,7 @@ val term_refine : context -> ast -> term_refined (** Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. def_API('is_eq_ast', BOOL, (_in(CONTEXT), _in(AST), _in(AST))) *) external is_eq_ast : context -> ast -> ast -> bool @@ -3753,8 +3088,7 @@ external is_eq_ast : context -> ast -> ast -> bool (** Summary: Return a unique identifier for [t]. - - {b Remarks}: Implicitly used by [Pervasives.compare] for values of type [ast], [app], [sort], [func_decl], and [pattern]. - + - {b Remarks}: Implicitly used by [Pervasives.compare] for values of type [ast], [app], [sort], [func_decl], and [pattern]. def_API('get_ast_id', UINT, (_in(CONTEXT), _in(AST))) *) external get_ast_id : context -> ast -> int @@ -3762,8 +3096,7 @@ external get_ast_id : context -> ast -> int (** Summary: Return a hash code for the given AST. - - {b Remarks}: Implicitly used by [Hashtbl.hash] for values of type [ast], [app], [sort], [func_decl], and [pattern]. - + - {b Remarks}: Implicitly used by [Hashtbl.hash] for values of type [ast], [app], [sort], [func_decl], and [pattern]. def_API('get_ast_hash', UINT, (_in(CONTEXT), _in(AST))) *) external get_ast_hash : context -> ast -> int @@ -3771,9 +3104,7 @@ external get_ast_hash : context -> ast -> int (** Summary: Return the sort of an AST node. - The AST node must be a constant, application, numeral, bound variable, or quantifier. - def_API('get_sort', SORT, (_in(CONTEXT), _in(AST))) *) external get_sort : context -> ast -> sort @@ -3781,7 +3112,6 @@ external get_sort : context -> ast -> sort (** Summary: Return true if the given expression [t] is well sorted. - def_API('is_well_sorted', BOOL, (_in(CONTEXT), _in(AST))) *) external is_well_sorted : context -> ast -> bool @@ -3789,7 +3119,6 @@ external is_well_sorted : context -> ast -> bool (** Summary: Return L_TRUE if [a] is true, L_FALSE if it is false, and L_UNDEF otherwise. - def_API('get_bool_value', UINT, (_in(CONTEXT), _in(AST))) *) external get_bool_value : context -> ast -> lbool @@ -3797,14 +3126,13 @@ external get_bool_value : context -> ast -> lbool (** Summary: Return the kind of the given AST. - def_API('get_ast_kind', UINT, (_in(CONTEXT), _in(AST))) *) external get_ast_kind : context -> ast -> ast_kind = "camlidl_z3_Z3_get_ast_kind" (** - def_API('is_app', BOOL, (_in(CONTEXT), _in(AST))) + def_API('is_app', BOOL, (_in(CONTEXT), _in(AST))) *) external is_app : context -> ast -> bool = "camlidl_z3_Z3_is_app" @@ -3817,17 +3145,14 @@ external is_numeral_ast : context -> ast -> bool (** Summary: Return true if the give AST is a real algebraic number. - def_API('is_algebraic_number', BOOL, (_in(CONTEXT), _in(AST))) *) external is_algebraic_number : context -> ast -> bool = "camlidl_z3_Z3_is_algebraic_number" (** - Summary: Convert an [ast] into an [APP_AST]. - - - {b Precondition}: {v get_ast_kind c a == [APP_AST] v} - + Summary: Convert an [ast] into an [APP_AST]. + - {b Precondition}: {v get_ast_kind c a == [APP_AST] v} def_API('to_app', APP, (_in(CONTEXT), _in(AST))) *) external to_app : context -> ast -> app @@ -3835,33 +3160,28 @@ external to_app : context -> ast -> app (** Summary: Convert an AST into a FUNC_DECL_AST. This is just type casting. - - - {b Precondition}: {v get_ast_kind c a == FUNC_DECL_AST v} - + - {b Precondition}: {v get_ast_kind c a == FUNC_DECL_AST v} def_API('to_func_decl', FUNC_DECL, (_in(CONTEXT), _in(AST))) *) external to_func_decl : context -> ast -> func_decl = "camlidl_z3_Z3_to_func_decl" (** - {4 {L Numerals}} + {4 {L Numerals}} *) (** Summary: \[ [ numeral_refine c a ] \] is the refined view of [a]. - - {b Precondition}: [get_ast_kind c a = NUMERAL_AST] *) val numeral_refine : context -> ast -> numeral_refined (** - {5 {L Low-level API}} + {5 {L Low-level API}} *) (** Summary: Return numeral value, as a string of a numeric constant term - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_numeral_string', STRING, (_in(CONTEXT), _in(AST))) *) external get_numeral_string : context -> ast -> string @@ -3870,19 +3190,15 @@ external get_numeral_string : context -> ast -> string (** Summary: Return numeral as a string in decimal notation. The result has at most [precision] decimal places. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST || is_algebraic_number c a - - def_API('get_numeral_decimal_string', STRING, (_in(CONTEXT), _in(AST), _in(UINT))) + def_API('get_numeral_decimal_string', STRING, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_numeral_decimal_string : context -> ast -> int -> string = "camlidl_z3_Z3_get_numeral_decimal_string" (** Summary: Return the numerator (as a numeral AST) of a numeral AST of sort Real. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_numerator', AST, (_in(CONTEXT), _in(AST))) *) external get_numerator : context -> ast -> ast @@ -3890,9 +3206,7 @@ external get_numerator : context -> ast -> ast (** Summary: Return the denominator (as a numeral AST) of a numeral AST of sort Real. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_denominator', AST, (_in(CONTEXT), _in(AST))) *) external get_denominator : context -> ast -> ast @@ -3900,16 +3214,12 @@ external get_denominator : context -> ast -> ast (** Summary: Return numeral value, as a pair of 64 bit numbers if the representation fits. - @param c logical context. @param a term. @param num numerator. @param den denominator. - Return [TRUE] if the numeral value fits in 64 bit numerals, [FALSE] otherwise. - - {b Precondition}: get_ast_kind a == NUMERAL_AST - def_API('get_numeral_small', BOOL, (_in(CONTEXT), _in(AST), _out(INT64), _out(INT64))) *) external get_numeral_small : context -> ast -> bool * int64 * int64 @@ -3919,11 +3229,8 @@ external get_numeral_small : context -> ast -> bool * int64 * int64 Summary: \[ [ get_numeral_int c v ] \] Similar to {!get_numeral_string}, but only succeeds if the value can fit in a machine int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_int', BOOL, (_in(CONTEXT), _in(AST), _out(INT))) *) external get_numeral_int : context -> ast -> bool * int @@ -3933,11 +3240,8 @@ external get_numeral_int : context -> ast -> bool * int Summary: \[ [ get_numeral_int64 c v ] \] Similar to {!get_numeral_string}, but only succeeds if the value can fit in a machine long long int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64))) *) external get_numeral_int64 : context -> ast -> bool * int64 @@ -3947,47 +3251,39 @@ external get_numeral_int64 : context -> ast -> bool * int64 Summary: \[ [ get_numeral_rational_int64 c x y] \] Similar to {!get_numeral_string}, but only succeeds if the value can fit as a rational number as machine long long int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_rational_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64), _out(INT64))) *) external get_numeral_rational_int64 : context -> ast -> bool * int64 * int64 = "camlidl_z3_Z3_get_numeral_rational_int64" (** - Summary: Return a lower bound for the given real algebraic number. + Summary: Return a lower bound for the given real algebraic number. The interval isolating the number is smaller than 1/10^precision. The result is a numeral AST of sort Real. - - {b Precondition}: is_algebraic_number c a - def_API('get_algebraic_number_lower', AST, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_algebraic_number_lower : context -> ast -> int -> ast = "camlidl_z3_Z3_get_algebraic_number_lower" (** - Summary: Return a upper bound for the given real algebraic number. + Summary: Return a upper bound for the given real algebraic number. The interval isolating the number is smaller than 1/10^precision. The result is a numeral AST of sort Real. - - {b Precondition}: is_algebraic_number c a - def_API('get_algebraic_number_upper', AST, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_algebraic_number_upper : context -> ast -> int -> ast = "camlidl_z3_Z3_get_algebraic_number_upper" (** - {4 {L Patterns}} + {4 {L Patterns}} *) (** - Summary: Convert a pattern into ast. - - {b Remarks}: [pattern_to_ast c p] can be replaced by [(p :> ast)]. - + Summary: Convert a pattern into ast. + - {b Remarks}: [pattern_to_ast c p] can be replaced by [(p :> ast)]. def_API('pattern_to_ast', AST, (_in(CONTEXT), _in(PATTERN))) *) external pattern_to_ast : context -> pattern -> ast @@ -3996,7 +3292,6 @@ external pattern_to_ast : context -> pattern -> ast (** Summary: \[ [ get_pattern_terms c p ] \] is the ast's in pattern. - - {b See also}: {!get_pattern_num_terms} - {b See also}: {!get_pattern} *) @@ -4004,7 +3299,6 @@ val get_pattern_terms: context -> pattern -> ast array;; (** Summary: Return number of terms in pattern. - def_API('get_pattern_num_terms', UINT, (_in(CONTEXT), _in(PATTERN))) *) external get_pattern_num_terms : context -> pattern -> int @@ -4012,20 +3306,17 @@ external get_pattern_num_terms : context -> pattern -> int (** Summary: Return i'th ast in pattern. - def_API('get_pattern', AST, (_in(CONTEXT), _in(PATTERN), _in(UINT))) *) external get_pattern : context -> pattern -> int -> ast = "camlidl_z3_Z3_get_pattern" (** - {4 {L Quantifiers}} + {4 {L Quantifiers}} *) (** Summary: Return index of de-Brujin bound variable. - - {b Precondition}: get_ast_kind a == VAR_AST - def_API('get_index_value', UINT, (_in(CONTEXT), _in(AST))) *) external get_index_value : context -> ast -> int @@ -4033,29 +3324,23 @@ external get_index_value : context -> ast -> int (** Summary: Determine if quantifier is universal. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - - def_API('is_quantifier_forall', BOOL, (_in(CONTEXT), _in(AST))) + def_API('is_quantifier_forall', BOOL, (_in(CONTEXT), _in(AST))) *) external is_quantifier_forall : context -> ast -> bool = "camlidl_z3_Z3_is_quantifier_forall" (** Summary: Obtain weight of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - - def_API('get_quantifier_weight', UINT, (_in(CONTEXT), _in(AST))) + def_API('get_quantifier_weight', UINT, (_in(CONTEXT), _in(AST))) *) external get_quantifier_weight : context -> ast -> int = "camlidl_z3_Z3_get_quantifier_weight" (** Summary: Return number of patterns used in quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_patterns', UINT, (_in(CONTEXT), _in(AST))) *) external get_quantifier_num_patterns : context -> ast -> int @@ -4063,9 +3348,7 @@ external get_quantifier_num_patterns : context -> ast -> int (** Summary: Return i'th pattern. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_pattern_ast', PATTERN, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_quantifier_pattern_ast : context -> ast -> int -> pattern @@ -4073,9 +3356,7 @@ external get_quantifier_pattern_ast : context -> ast -> int -> pattern (** Summary: Return number of no_patterns used in quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_no_patterns', UINT, (_in(CONTEXT), _in(AST))) *) external get_quantifier_num_no_patterns : context -> ast -> int @@ -4083,9 +3364,7 @@ external get_quantifier_num_no_patterns : context -> ast -> int (** Summary: Return i'th no_pattern. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_no_pattern_ast', AST, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_quantifier_no_pattern_ast : context -> ast -> int -> ast @@ -4093,9 +3372,7 @@ external get_quantifier_no_pattern_ast : context -> ast -> int -> ast (** Summary: Return number of bound variables of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_bound', UINT, (_in(CONTEXT), _in(AST))) *) external get_quantifier_num_bound : context -> ast -> int @@ -4103,9 +3380,7 @@ external get_quantifier_num_bound : context -> ast -> int (** Summary: Return symbol of the i'th bound variable. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_bound_name', SYMBOL, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_quantifier_bound_name : context -> ast -> int -> symbol @@ -4113,9 +3388,7 @@ external get_quantifier_bound_name : context -> ast -> int -> symbol (** Summary: Return sort of the i'th bound variable. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_bound_sort', SORT, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_quantifier_bound_sort : context -> ast -> int -> sort @@ -4123,22 +3396,18 @@ external get_quantifier_bound_sort : context -> ast -> int -> sort (** Summary: Return body of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_body', AST, (_in(CONTEXT), _in(AST))) *) external get_quantifier_body : context -> ast -> ast = "camlidl_z3_Z3_get_quantifier_body" (** - {3 {L Simplification}} + {3 {L Simplification}} *) (** Summary: Interface to simplifier. - Provides an interface to the AST simplifier used by Z3. - def_API('simplify', AST, (_in(CONTEXT), _in(AST))) *) external simplify : context -> ast -> ast @@ -4146,11 +3415,9 @@ external simplify : context -> ast -> ast (** Summary: Interface to simplifier. - Provides an interface to the AST simplifier used by Z3. - This procedure is similar to {!simplify}, but the behavior of the simplifier + This procedure is similar to {!simplify}, but the behavior of the simplifier can be configured using the given parameter set. - def_API('simplify_ex', AST, (_in(CONTEXT), _in(AST), _in(PARAMS))) *) external simplify_ex : context -> ast -> params -> ast @@ -4158,7 +3425,6 @@ external simplify_ex : context -> ast -> params -> ast (** Summary: Return a string describing all available parameters. - def_API('simplify_get_help', STRING, (_in(CONTEXT),)) *) external simplify_get_help : context -> string @@ -4166,7 +3432,6 @@ external simplify_get_help : context -> string (** Summary: Return the parameter description set for the simplify procedure. - def_API('simplify_get_param_descrs', PARAM_DESCRS, (_in(CONTEXT),)) *) external simplify_get_param_descrs : context -> param_descrs @@ -4177,10 +3442,9 @@ external simplify_get_param_descrs : context -> param_descrs *) (** Summary: Update the arguments of term [a] using the arguments [args]. - The number of arguments [num_args] should coincide + The number of arguments [num_args] should coincide with the number of arguments to [a]. If [a] is a quantifier, then num_args has to be 1. - def_API('update_term', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST))) *) external update_term : context -> ast -> ast array -> ast @@ -4190,7 +3454,6 @@ external update_term : context -> ast -> ast array -> ast Summary: Substitute every occurrence of {e from[i] } in [a] with {e to[i] }, for [i] smaller than [num_exprs]. The result is the new AST. The arrays [from] and [to] must have size [num_exprs]. For every [i] smaller than [num_exprs], we must have that sort of {e from[i] } must be equal to sort of {e to[i] }. - def_API('substitute', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST), _in_array(2, AST))) *) external substitute : context -> ast -> ast array -> ast array -> ast @@ -4199,7 +3462,6 @@ external substitute : context -> ast -> ast array -> ast array -> ast (** Summary: Substitute the free variables in [a] with the expressions in [to]. For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term {e to[i] }. - def_API('substitute_vars', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST))) *) external substitute_vars : context -> ast -> ast array -> ast @@ -4209,7 +3471,6 @@ external substitute_vars : context -> ast -> ast array -> ast Summary: Translate/Copy the AST [a] from context [source] to context [target]. AST [a] must have been created using context [source]. - {b Precondition}: source != target - def_API('translate', AST, (_in(CONTEXT), _in(AST), _in(CONTEXT))) *) external translate : context -> ast -> context -> ast @@ -4232,45 +3493,36 @@ type model_refined = { } -(** +(** Summary: [model_refine c m] is the refined model of [m]. *) val model_refine : context -> model -> model_refined (** Summary: \[ [ model_eval c m t ] \] - Evaluate the AST node [t] in the given model. - - Return [None] if the term was not successfully evaluated. - + Evaluate the AST node [t] in the given model. + Return [None] if the term was not successfully evaluated. If [model_completion] is TRUE, then Z3 will assign an interpretation for any constant or function that does not have an interpretation in [m]. These constants and functions were essentially don't cares. - The evaluation may fail for the following reasons: - - [t] contains a quantifier. - - the model [m] is partial, that is, it doesn't have a complete interpretation for uninterpreted functions. That is, the option {e MODEL_PARTIAL=true } was used. - - [t] is type incorrect. - def_API('model_eval', BOOL, (_in(CONTEXT), _in(MODEL), _in(AST), _in(BOOL), _out(AST))) *) external model_eval : context -> model -> ast -> bool -> ast option = "camlidl_z3_Z3_model_eval" (** - {4 {L Low-level API}} + {4 {L Low-level API}} *) (** Summary: Return the interpretation (i.e., assignment) of constant [a] in the model [m]. - Return [None], - if the model does not assign an interpretation for [a]. + Return [None], + if the model does not assign an interpretation for [a]. That should be interpreted as: the value of [a] does not matter. - - {b Precondition}: get_arity c a == 0 - def_API('model_get_const_interp', AST, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL))) *) external model_get_const_interp : context -> model -> func_decl -> ast option @@ -4278,15 +3530,10 @@ external model_get_const_interp : context -> model -> func_decl -> ast option (** Summary: Return the interpretation of the function [f] in the model [m]. - Return [None], - if the model does not assign an interpretation for [f]. + Return [None], + if the model does not assign an interpretation for [f]. That should be interpreted as: the [f] does not matter. - - {b Precondition}: get_arity c f > 0 - - - - def_API('model_get_func_interp', FUNC_INTERP, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL))) *) external model_get_func_interp : context -> model -> func_decl -> func_interp option @@ -4294,9 +3541,7 @@ external model_get_func_interp : context -> model -> func_decl -> func_interp op (** Summary: Return the number of constants assigned by the given model. - - {b See also}: {!model_get_const_decl} - def_API('model_get_num_consts', UINT, (_in(CONTEXT), _in(MODEL))) *) external model_get_num_consts : context -> model -> int @@ -4304,12 +3549,9 @@ external model_get_num_consts : context -> model -> int (** Summary: \[ [ model_get_const_decl c m i ] \] - Return the i-th constant in the given model. - + Return the i-th constant in the given model. - {b Precondition}: i < model_get_num_consts c m - - {b See also}: {!model_eval} - def_API('model_get_const_decl', FUNC_DECL, (_in(CONTEXT), _in(MODEL), _in(UINT))) *) external model_get_const_decl : context -> model -> int -> func_decl @@ -4317,10 +3559,8 @@ external model_get_const_decl : context -> model -> int -> func_decl (** Summary: Return the number of function interpretations in the given model. - A function interpretation is represented as a finite map and an 'else' value. Each entry in the finite map represents the value of a function given a set of arguments. - def_API('model_get_num_funcs', UINT, (_in(CONTEXT), _in(MODEL))) *) external model_get_num_funcs : context -> model -> int @@ -4329,11 +3569,8 @@ external model_get_num_funcs : context -> model -> int (** Summary: \[ [ model_get_func_decl c m i ] \] Return the declaration of the i-th function in the given model. - - {b Precondition}: i < model_get_num_funcs c m - - {b See also}: {!model_get_num_funcs} - def_API('model_get_func_decl', FUNC_DECL, (_in(CONTEXT), _in(MODEL), _in(UINT))) *) external model_get_func_decl : context -> model -> int -> func_decl @@ -4341,14 +3578,11 @@ external model_get_func_decl : context -> model -> int -> func_decl (** Summary: Return the number of uninterpreted sorts that [m] assigs an interpretation to. - Z3 also provides an intepretation for uninterpreted sorts used in a formua. The interpretation for a sort [s] is a finite set of distinct values. We say this finite set is the "universe" of [s]. - - {b See also}: {!model_get_sort} - {b See also}: {!model_get_sort_universe} - def_API('model_get_num_sorts', UINT, (_in(CONTEXT), _in(MODEL))) *) external model_get_num_sorts : context -> model -> int @@ -4356,12 +3590,9 @@ external model_get_num_sorts : context -> model -> int (** Summary: Return a uninterpreted sort that [m] assigns an interpretation. - - {b Precondition}: i < model_get_num_sorts c m - - {b See also}: {!model_get_num_sorts} - {b See also}: {!model_get_sort_universe} - def_API('model_get_sort', SORT, (_in(CONTEXT), _in(MODEL), _in(UINT))) *) external model_get_sort : context -> model -> int -> sort @@ -4369,10 +3600,8 @@ external model_get_sort : context -> model -> int -> sort (** Summary: Return the finite set of distinct values that represent the interpretation for sort [s]. - - {b See also}: {!model_get_num_sorts} - {b See also}: {!model_get_sort} - def_API('model_get_sort_universe', AST_VECTOR, (_in(CONTEXT), _in(MODEL), _in(SORT))) *) external model_get_sort_universe : context -> model -> sort -> ast_vector @@ -4382,11 +3611,8 @@ external model_get_sort_universe : context -> model -> sort -> ast_vector Summary: The {e (_ as-array f) } AST node is a construct for assigning interpretations for arrays in Z3. It is the array such that forall indices [i] we have that {e (select (_ as-array f) i) } is equal to {e (f i) }. This procedure returns TRUE if the [a] is an [as-array] AST node. - - Z3 current solvers have minimal support for [as_array] nodes. - + Z3 current solvers have minimal support for [as_array] nodes. - {b See also}: {!get_as_array_func_decl} - def_API('is_as_array', BOOL, (_in(CONTEXT), _in(AST))) *) external is_as_array : context -> ast -> bool @@ -4394,9 +3620,7 @@ external is_as_array : context -> ast -> bool (** Summary: Return the function declaration [f] associated with a {e (_ as_array f) } node. - - {b See also}: {!is_as_array} - def_API('get_as_array_func_decl', FUNC_DECL, (_in(CONTEXT), _in(AST))) *) external get_as_array_func_decl : context -> ast -> func_decl @@ -4404,11 +3628,9 @@ external get_as_array_func_decl : context -> ast -> func_decl (** Summary: Return the number of entries in the given function interpretation. - A function interpretation is represented as a finite map and an 'else' value. Each entry in the finite map represents the value of a function given a set of arguments. This procedure return the number of element in the finite map of [f]. - def_API('func_interp_get_num_entries', UINT, (_in(CONTEXT), _in(FUNC_INTERP))) *) external func_interp_get_num_entries : context -> func_interp -> int @@ -4417,11 +3639,8 @@ external func_interp_get_num_entries : context -> func_interp -> int (** Summary: Return a "point" of the given function intepretation. It represents the value of [f] in a particular point. - - {b Precondition}: i < func_interp_get_num_entries c f - - {b See also}: {!func_interp_get_num_entries} - def_API('func_interp_get_entry', FUNC_ENTRY, (_in(CONTEXT), _in(FUNC_INTERP), _in(UINT))) *) external func_interp_get_entry : context -> func_interp -> int -> func_entry @@ -4429,10 +3648,8 @@ external func_interp_get_entry : context -> func_interp -> int -> func_entry (** Summary: Return the 'else' value of the given function interpretation. - A function interpretation is represented as a finite map and an 'else' value. This procedure returns the 'else' value. - def_API('func_interp_get_else', AST, (_in(CONTEXT), _in(FUNC_INTERP))) *) external func_interp_get_else : context -> func_interp -> ast @@ -4440,20 +3657,16 @@ external func_interp_get_else : context -> func_interp -> ast (** Summary: Return the arity (number of arguments) of the given function interpretation. - def_API('func_interp_get_arity', UINT, (_in(CONTEXT), _in(FUNC_INTERP))) *) external func_interp_get_arity : context -> func_interp -> int = "camlidl_z3_Z3_func_interp_get_arity" (** - Summary: Return the value of this point. - + Summary: Return the value of this point. A func_entry object represents an element in the finite map used to encode a function interpretation. - - {b See also}: {!func_interp_get_entry} - def_API('func_entry_get_value', AST, (_in(CONTEXT), _in(FUNC_ENTRY))) *) external func_entry_get_value : context -> func_entry -> ast @@ -4461,9 +3674,7 @@ external func_entry_get_value : context -> func_entry -> ast (** Summary: Return the number of arguments in a func_entry object. - - {b See also}: {!func_interp_get_entry} - def_API('func_entry_get_num_args', UINT, (_in(CONTEXT), _in(FUNC_ENTRY))) *) external func_entry_get_num_args : context -> func_entry -> int @@ -4471,11 +3682,8 @@ external func_entry_get_num_args : context -> func_entry -> int (** Summary: Return an argument of a func_entry object. - - {b Precondition}: i < func_entry_get_num_args c e - - {b See also}: {!func_interp_get_entry} - def_API('func_entry_get_arg', AST, (_in(CONTEXT), _in(FUNC_ENTRY), _in(UINT))) *) external func_entry_get_arg : context -> func_entry -> int -> ast @@ -4486,7 +3694,6 @@ external func_entry_get_arg : context -> func_entry -> int -> ast *) (** Summary: Log interaction to a file. - extra_API('open_log', INT, (_in(STRING),)) *) external open_log : string -> bool @@ -4494,11 +3701,9 @@ external open_log : string -> bool (** Summary: Append user-defined string to interaction log. - The interaction log is opened using open_log. It contains the formulas that are checked using Z3. You can use this command to append comments, for instance. - extra_API('append_log', VOID, (_in(STRING),)) *) external append_log : string -> unit @@ -4506,7 +3711,6 @@ external append_log : string -> unit (** Summary: Close interaction log. - extra_API('close_log', VOID, ()) *) external close_log : unit -> unit @@ -4514,10 +3718,8 @@ external close_log : unit -> unit (** Summary: Enable/disable printing warning messages to the console. - Warnings are printed after passing [true], warning messages are - suppressed after calling this method with [false]. - + suppressed after calling this method with [false]. def_API('toggle_warning_messages', VOID, (_in(BOOL),)) *) external toggle_warning_messages : bool -> unit @@ -4528,19 +3730,16 @@ external toggle_warning_messages : bool -> unit *) (** Summary: Select mode for the format used for pretty-printing AST nodes. - The default mode for pretty printing AST nodes is to produce - SMT-LIB style output where common subexpressions are printed + SMT-LIB style output where common subexpressions are printed at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, + To print shared common subexpressions only once, use the PRINT_LOW_LEVEL mode. To print in way that conforms to SMT-LIB standards and uses let expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - - {b See also}: {!ast_to_string} - {b See also}: {!pattern_to_string} - {b See also}: {!func_decl_to_string} - def_API('set_ast_print_mode', VOID, (_in(CONTEXT), _in(PRINT_MODE))) *) external set_ast_print_mode : context -> ast_print_mode -> unit @@ -4548,13 +3747,8 @@ external set_ast_print_mode : context -> ast_print_mode -> unit (** Summary: Convert the given AST node into a string. - - - - - {b See also}: {!pattern_to_string} - {b See also}: {!sort_to_string} - def_API('ast_to_string', STRING, (_in(CONTEXT), _in(AST))) *) external ast_to_string : context -> ast -> string @@ -4580,11 +3774,6 @@ external func_decl_to_string : context -> func_decl -> string (** Summary: Convert the given model into a string. - - - - - def_API('model_to_string', STRING, (_in(CONTEXT), _in(MODEL))) *) external model_to_string : context -> model -> string @@ -4592,20 +3781,14 @@ external model_to_string : context -> model -> string (** Summary: Convert the given benchmark into SMT-LIB formatted string. - - - - - @param c - context. @param name - name of benchmark. The argument is optional. - @param logic - the benchmark logic. + @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 num_assumptions - number of assumptions. @param assumptions - auxiliary assumptions. @param formula - formula to be checked for consistency in conjunction with assumptions. - def_API('benchmark_to_smtlib_string', STRING, (_in(CONTEXT), _in(STRING), _in(STRING), _in(STRING), _in(STRING), _in(UINT), _in_array(5, AST), _in(AST))) *) external benchmark_to_smtlib_string : context -> string -> string -> string -> string -> ast array -> ast -> string @@ -4616,11 +3799,9 @@ external benchmark_to_smtlib_string : context -> string -> string -> string -> s *) (** Summary: \[ [ parse_smtlib2_string c str ] \] - Parse the given string using the SMT-LIB2 parser. - + Parse the given string using the SMT-LIB2 parser. It returns a formula comprising of the conjunction of assertions in the scope (up to push/pop) at the end of the string. - def_API('parse_smtlib2_string', AST, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) *) external parse_smtlib2_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast @@ -4628,7 +3809,6 @@ external parse_smtlib2_string : context -> string -> symbol array -> sort array (** Summary: Similar to {!parse_smtlib2_string}, but reads the benchmark from a file. - def_API('parse_smtlib2_file', AST, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) *) external parse_smtlib2_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast @@ -4637,57 +3817,45 @@ external parse_smtlib2_file : context -> string -> symbol array -> sort array -> (** Summary: \[ [ parse_smtlib_string_x c str sort_names sorts decl_names decls ] \] - - Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. + Parse the given string using the SMT-LIB parser. + The symbol table of the parser can be initialized using the given sorts and declarations. The symbols in the arrays [sort_names] and [decl_names] don't need to match the names of the sorts and declarations in the arrays [sorts] and [decls]. This is an useful feature since we can use arbitrary names to reference sorts and declarations defined using the API. - - {b See also}: {!parse_smtlib_file_x} *) val parse_smtlib_string_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) - (** Summary: Similar to {!parse_smtlib_string_x}, but reads the benchmark from a file. - - {b See also}: {!parse_smtlib_string_x} *) val parse_smtlib_file_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) - (** Summary: \[ [ parse_smtlib_string_formula c ... ] \] calls [(parse_smtlib_string c ...)] and returns the single formula produced. - - {b See also}: {!parse_smtlib_file_formula} - {b See also}: {!parse_smtlib_string_x} *) val parse_smtlib_string_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - (** Summary: \[ [ parse_smtlib_file_formula c ... ] \] calls [(parse_smtlib_file c ...)] and returns the single formula produced. - - {b See also}: {!parse_smtlib_string_formula} - {b See also}: {!parse_smtlib_file_x} *) val parse_smtlib_file_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast (** - {4 {L Low-level API}} + {4 {L Low-level API}} *) (** Summary: \[ [ parse_smtlib_string c str sort_names sorts decl_names decls ] \] - Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. + Parse the given string using the SMT-LIB parser. + The symbol table of the parser can be initialized using the given sorts and declarations. The symbols in the arrays [sort_names] and [decl_names] don't need to match the names of the sorts and declarations in the arrays [sorts] and [decls]. This is an useful feature since we can use arbitrary names to reference sorts and declarations defined using the C API. - The formulas, assumptions and declarations defined in [str] can be extracted using the functions: - {!get_smtlib_num_formulas}, {!get_smtlib_formula}, {!get_smtlib_num_assumptions}, {!get_smtlib_assumption}, + {!get_smtlib_num_formulas}, {!get_smtlib_formula}, {!get_smtlib_num_assumptions}, {!get_smtlib_assumption}, {!get_smtlib_num_decls}, and {!get_smtlib_decl}. - def_API('parse_smtlib_string', VOID, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) *) external parse_smtlib_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit @@ -4695,7 +3863,6 @@ external parse_smtlib_string : context -> string -> symbol array -> sort array - (** Summary: Similar to {!parse_smtlib_string}, but reads the benchmark from a file. - def_API('parse_smtlib_file', VOID, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) *) external parse_smtlib_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit @@ -4703,7 +3870,6 @@ external parse_smtlib_file : context -> string -> symbol array -> sort array -> (** Summary: Return the number of SMTLIB formulas parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_formulas', UINT, (_in(CONTEXT), )) *) external get_smtlib_num_formulas : context -> int @@ -4712,9 +3878,7 @@ external get_smtlib_num_formulas : context -> int (** Summary: \[ [ get_smtlib_formula c i ] \] Return the i-th formula parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_formulas c - def_API('get_smtlib_formula', AST, (_in(CONTEXT), _in(UINT))) *) external get_smtlib_formula : context -> int -> ast @@ -4722,7 +3886,6 @@ external get_smtlib_formula : context -> int -> ast (** Summary: Return the number of SMTLIB assumptions parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_assumptions', UINT, (_in(CONTEXT), )) *) external get_smtlib_num_assumptions : context -> int @@ -4731,9 +3894,7 @@ external get_smtlib_num_assumptions : context -> int (** Summary: \[ [ get_smtlib_assumption c i ] \] Return the i-th assumption parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_assumptions c - def_API('get_smtlib_assumption', AST, (_in(CONTEXT), _in(UINT))) *) external get_smtlib_assumption : context -> int -> ast @@ -4741,7 +3902,6 @@ external get_smtlib_assumption : context -> int -> ast (** Summary: Return the number of declarations parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_decls', UINT, (_in(CONTEXT), )) *) external get_smtlib_num_decls : context -> int @@ -4750,9 +3910,7 @@ external get_smtlib_num_decls : context -> int (** Summary: \[ [ get_smtlib_decl c i ] \] Return the i-th declaration parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_decls c - def_API('get_smtlib_decl', FUNC_DECL, (_in(CONTEXT), _in(UINT))) *) external get_smtlib_decl : context -> int -> func_decl @@ -4760,7 +3918,6 @@ external get_smtlib_decl : context -> int -> func_decl (** Summary: Return the number of sorts parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_sorts', UINT, (_in(CONTEXT), )) *) external get_smtlib_num_sorts : context -> int @@ -4769,9 +3926,7 @@ external get_smtlib_num_sorts : context -> int (** Summary: \[ [ get_smtlib_sort c i ] \] Return the i-th sort parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_sorts c - def_API('get_smtlib_sort', SORT, (_in(CONTEXT), _in(UINT))) *) external get_smtlib_sort : context -> int -> sort @@ -4781,38 +3936,17 @@ external get_smtlib_sort : context -> int -> sort (** Summary: \[ [ get_smtlib_error c ] \] Retrieve that last error message information generated from parsing. - def_API('get_smtlib_error', STRING, (_in(CONTEXT), )) *) external get_smtlib_error : context -> string = "camlidl_z3_Z3_get_smtlib_error" *) -(** - Summary: \[ [ parse_z3_string c str ] \] - Parse the given string using the Z3 native parser. - - Return the conjunction of asserts made in the input. - - def_API('parse_z3_string', AST, (_in(CONTEXT), _in(STRING))) -*) -external parse_z3_string : context -> string -> ast - = "camlidl_z3_Z3_parse_z3_string" - -(** - Summary: Similar to {!parse_z3_string}, but reads the benchmark from a file. - - def_API('parse_z3_file', AST, (_in(CONTEXT), _in(STRING))) -*) -external parse_z3_file : context -> string -> ast - = "camlidl_z3_Z3_parse_z3_file" - (** {2 {L Error Handling}} *) (** Summary: Set an error. - def_API('set_error', VOID, (_in(CONTEXT), _in(ERROR_CODE))) *) external set_error : context -> error_code -> unit @@ -4821,7 +3955,6 @@ external set_error : context -> error_code -> unit (* (** Summary: Return a string describing the given error code. - def_API('get_error_msg_ex', STRING, (_in(CONTEXT), _in(ERROR_CODE))) *) external get_error_msg_ex : context -> error_code -> string @@ -4831,7 +3964,7 @@ external get_error_msg_ex : context -> error_code -> string (** Summary: Return a string describing the given error code. -*) +*) val get_error_msg: context -> error_code -> string (** @@ -4839,21 +3972,32 @@ val get_error_msg: context -> error_code -> string *) (** Summary: Return Z3 version number information. - def_API('get_version', VOID, (_out(UINT), _out(UINT), _out(UINT), _out(UINT))) *) external get_version : unit -> int * int * int * int = "camlidl_z3_Z3_get_version" +(** + Summary: Enable tracing messages tagged as [tag] when Z3 is compiled in debug mode. + It is a NOOP otherwise + def_API('enable_trace', VOID, (_in(STRING),)) +*) +external enable_trace : string -> unit + = "camlidl_z3_Z3_enable_trace" + +(** + Summary: Disable tracing messages tagged as [tag] when Z3 is compiled in debug mode. + It is a NOOP otherwise + def_API('disable_trace', VOID, (_in(STRING),)) +*) +external disable_trace : string -> unit + = "camlidl_z3_Z3_disable_trace" + (** {2 {L Fixedpoint facilities}} *) (** - Summary: Create a new fixedpoint context. - - - - + Summary: Create a new fixedpoint context. def_API('mk_fixedpoint', FIXEDPOINT, (_in(CONTEXT), )) *) external mk_fixedpoint : context -> fixedpoint @@ -4862,33 +4006,27 @@ external mk_fixedpoint : context -> fixedpoint (** Summary: Add a universal Horn clause as a named rule. The [horn_rule] should be of the form: - - {v + {v horn_rule ::= (forall (bound-vars) horn_rule) - | (=> atoms horn_rule) - | atom + | (=> atoms horn_rule) + | atom v} - def_API('fixedpoint_add_rule', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(AST), _in(SYMBOL))) *) external fixedpoint_add_rule : context -> fixedpoint -> ast -> symbol -> unit = "camlidl_z3_Z3_fixedpoint_add_rule" (** - Summary: Add a Database fact. - + Summary: Add a Database fact. @param c - context @param d - fixed point context @param r - relation signature for the row. - @param num_args - number of columns for the given row. + @param num_args - number of columns for the given row. @param args - array of the row elements. - - The number of arguments [num_args] should be equal to the number + The number of arguments [num_args] should be equal to the number of sorts in the domain of [r]. Each sort in the domain should be an integral (bit-vector, Boolean or or finite domain sort). - - The call has the same effect as adding a rule where is applied to the arguments. - + The call has the same effect as adding a rule where [r] is applied to the arguments. def_API('fixedpoint_add_fact', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(FUNC_DECL), _in(UINT), _in_array(3, UINT))) *) external fixedpoint_add_fact : context -> fixedpoint -> func_decl -> int array -> unit @@ -4896,10 +4034,8 @@ external fixedpoint_add_fact : context -> fixedpoint -> func_decl -> int array - (** Summary: Assert a constraint to the fixedpoint context. - The constraints are used as background axioms when the fixedpoint engine uses the PDR mode. They are ignored for standard Datalog mode. - def_API('fixedpoint_assert', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(AST))) *) external fixedpoint_assert : context -> fixedpoint -> ast -> unit @@ -4907,17 +4043,14 @@ external fixedpoint_assert : context -> fixedpoint -> ast -> unit (** Summary: Pose a query against the asserted rules. - - {v + {v query ::= (exists (bound-vars) query) - | literals + | literals v} - - query returns + query returns - L_FALSE if the query is unsatisfiable. - L_TRUE if the query is satisfiable. Obtain the answer by calling {!fixedpoint_get_answer}. - L_UNDEF if the query was interrupted, timed out or otherwise failed. - def_API('fixedpoint_query', INT, (_in(CONTEXT), _in(FIXEDPOINT), _in(AST))) *) external fixedpoint_query : context -> fixedpoint -> ast -> lbool @@ -4925,14 +4058,11 @@ external fixedpoint_query : context -> fixedpoint -> ast -> lbool (** Summary: Pose multiple queries against the asserted rules. - The queries are encoded as relations (function declarations). - - query returns + query returns - L_FALSE if the query is unsatisfiable. - L_TRUE if the query is satisfiable. Obtain the answer by calling {!fixedpoint_get_answer}. - L_UNDEF if the query was interrupted, timed out or otherwise failed. - def_API('fixedpoint_query_relations', INT, (_in(CONTEXT), _in(FIXEDPOINT), _in(UINT), _in_array(2, FUNC_DECL))) *) external fixedpoint_query_relations : context -> fixedpoint -> func_decl array -> lbool @@ -4940,14 +4070,10 @@ external fixedpoint_query_relations : context -> fixedpoint -> func_decl array - (** Summary: Retrieve a formula that encodes satisfying answers to the query. - - When used in Datalog mode, the returned answer is a disjunction of conjuncts. Each conjunct encodes values of the bound variables of the query that are satisfied. In PDR mode, the returned answer is a single conjunction. - The previous call to fixedpoint_query must have returned L_TRUE. - def_API('fixedpoint_get_answer', AST, (_in(CONTEXT), _in(FIXEDPOINT))) *) external fixedpoint_get_answer : context -> fixedpoint -> ast @@ -4955,18 +4081,15 @@ external fixedpoint_get_answer : context -> fixedpoint -> ast (** Summary: Retrieve a string that describes the last status returned by {!fixedpoint_query}. - Use this method when {!fixedpoint_query} returns L_UNDEF. - def_API('fixedpoint_get_reason_unknown', STRING, (_in(CONTEXT), _in(FIXEDPOINT) )) *) external fixedpoint_get_reason_unknown : context -> fixedpoint -> string = "camlidl_z3_Z3_fixedpoint_get_reason_unknown" (** - Summary: Update a named rule. + Summary: Update a named rule. A rule with the same name must have been previously created. - def_API('fixedpoint_update_rule', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(AST), _in(SYMBOL))) *) external fixedpoint_update_rule : context -> fixedpoint -> ast -> symbol -> unit @@ -4974,11 +4097,9 @@ external fixedpoint_update_rule : context -> fixedpoint -> ast -> symbol -> unit (** Summary: Query the PDR engine for the maximal levels properties are known about predicate. - - This call retrieves the maximal number of relevant unfoldings + This call retrieves the maximal number of relevant unfoldings of [pred] with respect to the current exploration state. Note: this functionality is PDR specific. - def_API('fixedpoint_get_num_levels', UINT, (_in(CONTEXT), _in(FIXEDPOINT), _in(FUNC_DECL))) *) external fixedpoint_get_num_levels : context -> fixedpoint -> func_decl -> int @@ -4989,9 +4110,7 @@ external fixedpoint_get_num_levels : context -> fixedpoint -> func_decl -> int Return just the delta that is known at [level]. To obtain the full set of properties of [pred] one should query at [level+1] , [level+2] etc, and include [level=-1]. - Note: this functionality is PDR specific. - def_API('fixedpoint_get_cover_delta', AST, (_in(CONTEXT), _in(FIXEDPOINT), _in(INT), _in(FUNC_DECL))) *) external fixedpoint_get_cover_delta : context -> fixedpoint -> int -> func_decl -> ast @@ -4999,14 +4118,11 @@ external fixedpoint_get_cover_delta : context -> fixedpoint -> int -> func_decl (** Summary: Add property about the predicate [pred]. - Add a property of predicate [pred] at [level]. + Add a property of predicate [pred] at [level]. It gets pushed forward when possible. - Note: level = -1 is treated as the fixedpoint. So passing -1 for the [level] means that the property is true of the fixed-point unfolding with respect to [pred]. - Note: this functionality is PDR specific. - def_API('fixedpoint_add_cover', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(INT), _in(FUNC_DECL), _in(AST))) *) external fixedpoint_add_cover : context -> fixedpoint -> int -> func_decl -> ast -> unit @@ -5014,7 +4130,6 @@ external fixedpoint_add_cover : context -> fixedpoint -> int -> func_decl -> ast (** Summary: Retrieve statistics information from the last call to {!fixedpoint_query}. - def_API('fixedpoint_get_statistics', STATS, (_in(CONTEXT), _in(FIXEDPOINT))) *) external fixedpoint_get_statistics : context -> fixedpoint -> stats @@ -5025,7 +4140,6 @@ external fixedpoint_get_statistics : context -> fixedpoint -> stats Fixedpoint defined relations have least-fixedpoint semantics. For example, the relation is empty if it does not occur in a head or a fact. - def_API('fixedpoint_register_relation', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(FUNC_DECL))) *) external fixedpoint_register_relation : context -> fixedpoint -> func_decl -> unit @@ -5033,29 +4147,30 @@ external fixedpoint_register_relation : context -> fixedpoint -> func_decl -> un (** Summary: Configure the predicate representation. - It sets the predicate to use a set of domains given by the list of symbols. The domains given by the list of symbols must belong to a set of built-in domains. - def_API('fixedpoint_set_predicate_representation', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(FUNC_DECL), _in(UINT), _in_array(3, SYMBOL))) *) external fixedpoint_set_predicate_representation : context -> fixedpoint -> func_decl -> symbol array -> unit = "camlidl_z3_Z3_fixedpoint_set_predicate_representation" (** - Summary: Simplify rules into a set of new rules that are returned. - The simplification routines apply inlining, quantifier elimination, and other - algebraic simplifications. - - def_API('fixedpoint_simplify_rules', AST_VECTOR, (_in(CONTEXT), _in(FIXEDPOINT), _in(UINT), _in_array(2,AST), _in(UINT), _in_array(4,FUNC_DECL))) + Summary: Retrieve set of rules from fixedpoint context. + def_API('fixedpoint_get_rules', AST_VECTOR, (_in(CONTEXT),_in(FIXEDPOINT))) *) -external fixedpoint_simplify_rules : context -> fixedpoint -> ast array -> func_decl array -> ast_vector - = "camlidl_z3_Z3_fixedpoint_simplify_rules" +external fixedpoint_get_rules : context -> fixedpoint -> ast_vector + = "camlidl_z3_Z3_fixedpoint_get_rules" (** - Summary: Set parameters on fixedpoint context. + Summary: Retrieve set of background assertions from fixedpoint context. + def_API('fixedpoint_get_assertions', AST_VECTOR, (_in(CONTEXT),_in(FIXEDPOINT))) +*) +external fixedpoint_get_assertions : context -> fixedpoint -> ast_vector + = "camlidl_z3_Z3_fixedpoint_get_assertions" +(** + Summary: Set parameters on fixedpoint context. def_API('fixedpoint_set_params', VOID, (_in(CONTEXT), _in(FIXEDPOINT), _in(PARAMS))) *) external fixedpoint_set_params : context -> fixedpoint -> params -> unit @@ -5063,7 +4178,6 @@ external fixedpoint_set_params : context -> fixedpoint -> params -> unit (** Summary: Return a string describing all fixedpoint available parameters. - def_API('fixedpoint_get_help', STRING, (_in(CONTEXT), _in(FIXEDPOINT))) *) external fixedpoint_get_help : context -> fixedpoint -> string @@ -5071,7 +4185,6 @@ external fixedpoint_get_help : context -> fixedpoint -> string (** Summary: Return the parameter description set for the given fixedpoint object. - def_API('fixedpoint_get_param_descrs', PARAM_DESCRS, (_in(CONTEXT), _in(FIXEDPOINT))) *) external fixedpoint_get_param_descrs : context -> fixedpoint -> param_descrs @@ -5083,20 +4196,40 @@ external fixedpoint_get_param_descrs : context -> fixedpoint -> param_descrs @param f - fixedpoint context. @param num_queries - number of additional queries to print. @param queries - additional queries. - def_API('fixedpoint_to_string', STRING, (_in(CONTEXT), _in(FIXEDPOINT), _in(UINT), _in_array(2, AST))) *) external fixedpoint_to_string : context -> fixedpoint -> ast array -> string = "camlidl_z3_Z3_fixedpoint_to_string" +(** + Summary: Parse an SMT-LIB2 string with fixedpoint rules. + Add the rules to the current fixedpoint context. + Return the set of queries in the file. + @param c - context. + @param f - fixedpoint context. + @param s - string containing SMT2 specification. + def_API('fixedpoint_from_string', AST_VECTOR, (_in(CONTEXT), _in(FIXEDPOINT), _in(STRING))) +*) +external fixedpoint_from_string : context -> fixedpoint -> string -> ast_vector + = "camlidl_z3_Z3_fixedpoint_from_string" + +(** + Summary: Parse an SMT-LIB2 file with fixedpoint rules. + Add the rules to the current fixedpoint context. + Return the set of queries in the file. + @param c - context. + @param f - fixedpoint context. + @param s - string containing SMT2 specification. + def_API('fixedpoint_from_file', AST_VECTOR, (_in(CONTEXT), _in(FIXEDPOINT), _in(STRING))) +*) +external fixedpoint_from_file : context -> fixedpoint -> string -> ast_vector + = "camlidl_z3_Z3_fixedpoint_from_file" + (** Summary: Create a backtracking point. - The fixedpoint solver contains a set of rules, added facts and assertions. The set of rules, facts and assertions are restored upon calling {!fixedpoint_pop}. - - {b See also}: {!fixedpoint_pop} - def_API('fixedpoint_push', VOID, (_in(CONTEXT), _in(FIXEDPOINT))) *) external fixedpoint_push : context -> fixedpoint -> unit @@ -5104,11 +4237,8 @@ external fixedpoint_push : context -> fixedpoint -> unit (** Summary: Backtrack one backtracking point. - - {b See also}: {!fixedpoint_push} - - {b Precondition}: The number of calls to pop cannot exceed calls to push. - def_API('fixedpoint_pop', VOID, (_in(CONTEXT), _in(FIXEDPOINT))) *) external fixedpoint_pop : context -> fixedpoint -> unit @@ -5119,10 +4249,6 @@ external fixedpoint_pop : context -> fixedpoint -> unit *) (** Summary: Return an empty AST vector. - - - - def_API('mk_ast_vector', AST_VECTOR, (_in(CONTEXT),)) *) external mk_ast_vector : context -> ast_vector @@ -5130,7 +4256,6 @@ external mk_ast_vector : context -> ast_vector (** Summary: Return the size of the given AST vector. - def_API('ast_vector_size', UINT, (_in(CONTEXT), _in(AST_VECTOR))) *) external ast_vector_size : context -> ast_vector -> int @@ -5138,27 +4263,22 @@ external ast_vector_size : context -> ast_vector -> int (** Summary: Return the AST at position [i] in the AST vector [v]. - - {b Precondition}: i < ast_vector_size c v - def_API('ast_vector_get', AST, (_in(CONTEXT), _in(AST_VECTOR), _in(UINT))) *) external ast_vector_get : context -> ast_vector -> int -> ast = "camlidl_z3_Z3_ast_vector_get" (** - Summary: Update position [i] of the AST vector [v] with the AST [a]. - + Summary: Update position [i] of the AST vector [v] with the AST [a]. - {b Precondition}: i < ast_vector_size c v - def_API('ast_vector_set', VOID, (_in(CONTEXT), _in(AST_VECTOR), _in(UINT), _in(AST))) *) external ast_vector_set : context -> ast_vector -> int -> ast -> unit = "camlidl_z3_Z3_ast_vector_set" (** - Summary: Resize the AST vector [v]. - + Summary: Resize the AST vector [v]. def_API('ast_vector_resize', VOID, (_in(CONTEXT), _in(AST_VECTOR), _in(UINT))) *) external ast_vector_resize : context -> ast_vector -> int -> unit @@ -5166,7 +4286,6 @@ external ast_vector_resize : context -> ast_vector -> int -> unit (** Summary: Add the AST [a] in the end of the AST vector [v]. The size of [v] is increased by one. - def_API('ast_vector_push', VOID, (_in(CONTEXT), _in(AST_VECTOR), _in(AST))) *) external ast_vector_push : context -> ast_vector -> ast -> unit @@ -5174,7 +4293,6 @@ external ast_vector_push : context -> ast_vector -> ast -> unit (** Summary: Translate the AST vector [v] from context [s] into an AST vector in context [t]. - def_API('ast_vector_translate', AST_VECTOR, (_in(CONTEXT), _in(AST_VECTOR), _in(CONTEXT))) *) external ast_vector_translate : context -> ast_vector -> context -> ast_vector @@ -5182,7 +4300,6 @@ external ast_vector_translate : context -> ast_vector -> context -> ast_vector (** Summary: Convert AST vector into a string. - def_API('ast_vector_to_string', STRING, (_in(CONTEXT), _in(AST_VECTOR))) *) external ast_vector_to_string : context -> ast_vector -> string @@ -5193,10 +4310,6 @@ external ast_vector_to_string : context -> ast_vector -> string *) (** Summary: Return an empty mapping from AST to AST - - - - def_API('mk_ast_map', AST_MAP, (_in(CONTEXT),) ) *) external mk_ast_map : context -> ast_map @@ -5204,7 +4317,6 @@ external mk_ast_map : context -> ast_map (** Summary: Return true if the map [m] contains the AST key [k]. - def_API('ast_map_contains', BOOL, (_in(CONTEXT), _in(AST_MAP), _in(AST))) *) external ast_map_contains : context -> ast_map -> ast -> bool @@ -5212,9 +4324,7 @@ external ast_map_contains : context -> ast_map -> ast -> bool (** Summary: Return the value associated with the key [k]. - The procedure invokes the error handler if [k] is not in the map. - def_API('ast_map_find', AST, (_in(CONTEXT), _in(AST_MAP), _in(AST))) *) external ast_map_find : context -> ast_map -> ast -> ast @@ -5222,7 +4332,6 @@ external ast_map_find : context -> ast_map -> ast -> ast (** Summary: Store/Replace a new key, value pair in the given map. - def_API('ast_map_insert', VOID, (_in(CONTEXT), _in(AST_MAP), _in(AST), _in(AST))) *) external ast_map_insert : context -> ast_map -> ast -> ast -> unit @@ -5230,7 +4339,6 @@ external ast_map_insert : context -> ast_map -> ast -> ast -> unit (** Summary: Erase a key from the map. - def_API('ast_map_erase', VOID, (_in(CONTEXT), _in(AST_MAP), _in(AST))) *) external ast_map_erase : context -> ast_map -> ast -> unit @@ -5238,7 +4346,6 @@ external ast_map_erase : context -> ast_map -> ast -> unit (** Summary: Remove all keys from the given map. - def_API('ast_map_reset', VOID, (_in(CONTEXT), _in(AST_MAP))) *) external ast_map_reset : context -> ast_map -> unit @@ -5246,7 +4353,6 @@ external ast_map_reset : context -> ast_map -> unit (** Summary: Return the size of the given map. - def_API('ast_map_size', UINT, (_in(CONTEXT), _in(AST_MAP))) *) external ast_map_size : context -> ast_map -> int @@ -5254,7 +4360,6 @@ external ast_map_size : context -> ast_map -> int (** Summary: Return the keys stored in the given map. - def_API('ast_map_keys', AST_VECTOR, (_in(CONTEXT), _in(AST_MAP))) *) external ast_map_keys : context -> ast_map -> ast_vector @@ -5262,7 +4367,6 @@ external ast_map_keys : context -> ast_map -> ast_vector (** Summary: Convert the given map into a string. - def_API('ast_map_to_string', STRING, (_in(CONTEXT), _in(AST_MAP))) *) external ast_map_to_string : context -> ast_map -> string @@ -5275,17 +4379,10 @@ external ast_map_to_string : context -> ast_map -> string Summary: Create a goal (aka problem). A goal is essentially a set of formulas, that can be solved and/or transformed using tactics and solvers. - If models == true, then model generation is enabled for the new goal. - If unsat_cores == true, then unsat core generation is enabled for the new goal. - - If proofs == true, then proof generation is enabled for the new goal. Remark, the + If proofs == true, then proof generation is enabled for the new goal. Remark, the Z3 context c must have been created with proof generation support. - - - - def_API('mk_goal', GOAL, (_in(CONTEXT), _in(BOOL), _in(BOOL), _in(BOOL))) *) external mk_goal : context -> bool -> bool -> bool -> goal @@ -5295,15 +4392,13 @@ external mk_goal : context -> bool -> bool -> bool -> goal Summary: Return the "precision" of the given goal. Goals can be transformed using over and under approximations. A 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. - def_API('goal_precision', UINT, (_in(CONTEXT), _in(GOAL))) *) external goal_precision : context -> goal -> goal_prec = "camlidl_z3_Z3_goal_precision" (** - Summary: Add a new formula [a] to the given goal. - + Summary: Add a new formula [a] to the given goal. def_API('goal_assert', VOID, (_in(CONTEXT), _in(GOAL), _in(AST))) *) external goal_assert : context -> goal -> ast -> unit @@ -5311,7 +4406,6 @@ external goal_assert : context -> goal -> ast -> unit (** Summary: Return true if the given goal contains the formula [false]. - def_API('goal_inconsistent', BOOL, (_in(CONTEXT), _in(GOAL))) *) external goal_inconsistent : context -> goal -> bool @@ -5319,7 +4413,6 @@ external goal_inconsistent : context -> goal -> bool (** Summary: Return the depth of the given goal. It tracks how many transformations were applied to it. - def_API('goal_depth', UINT, (_in(CONTEXT), _in(GOAL))) *) external goal_depth : context -> goal -> int @@ -5327,7 +4420,6 @@ external goal_depth : context -> goal -> int (** Summary: Erase all formulas from the given goal. - def_API('goal_reset', VOID, (_in(CONTEXT), _in(GOAL))) *) external goal_reset : context -> goal -> unit @@ -5335,7 +4427,6 @@ external goal_reset : context -> goal -> unit (** Summary: Return the number of formulas in the given goal. - def_API('goal_size', UINT, (_in(CONTEXT), _in(GOAL))) *) external goal_size : context -> goal -> int @@ -5343,9 +4434,7 @@ external goal_size : context -> goal -> int (** Summary: Return a formula from the given goal. - - {b Precondition}: idx < goal_size c g - def_API('goal_formula', AST, (_in(CONTEXT), _in(GOAL), _in(UINT))) *) external goal_formula : context -> goal -> int -> ast @@ -5353,7 +4442,6 @@ external goal_formula : context -> goal -> int -> ast (** Summary: Return the number of formulas, subformulas and terms in the given goal. - def_API('goal_num_exprs', UINT, (_in(CONTEXT), _in(GOAL))) *) external goal_num_exprs : context -> goal -> int @@ -5361,7 +4449,6 @@ external goal_num_exprs : context -> goal -> int (** Summary: Return true if the goal is empty, and it is precise or the product of a under approximation. - def_API('goal_is_decided_sat', BOOL, (_in(CONTEXT), _in(GOAL))) *) external goal_is_decided_sat : context -> goal -> bool @@ -5369,7 +4456,6 @@ external goal_is_decided_sat : context -> goal -> bool (** Summary: Return true if the goal contains false, and it is precise or the product of an over approximation. - def_API('goal_is_decided_unsat', BOOL, (_in(CONTEXT), _in(GOAL))) *) external goal_is_decided_unsat : context -> goal -> bool @@ -5377,7 +4463,6 @@ external goal_is_decided_unsat : context -> goal -> bool (** Summary: Copy a goal [g] from the context [source] to a the context [target]. - def_API('goal_translate', GOAL, (_in(CONTEXT), _in(GOAL), _in(CONTEXT))) *) external goal_translate : context -> goal -> context -> goal @@ -5385,7 +4470,6 @@ external goal_translate : context -> goal -> context -> goal (** Summary: Convert a goal into a string. - def_API('goal_to_string', STRING, (_in(CONTEXT), _in(GOAL))) *) external goal_to_string : context -> goal -> string @@ -5398,9 +4482,7 @@ external goal_to_string : context -> goal -> string Summary: Return a tactic associated with the given name. The complete list of tactics may be obtained using the procedures {!get_num_tactics} and {!get_tactic_name}. It may also be obtained using the command {e (help-tactics) } in the SMT 2.0 front-end. - Tactics are the basic building block for creating custom solvers for specific problem domains. - def_API('mk_tactic', TACTIC, (_in(CONTEXT), _in(STRING))) *) external mk_tactic : context -> string -> tactic @@ -5410,10 +4492,8 @@ external mk_tactic : context -> string -> tactic Summary: Return a probe associated with the given name. The complete list of probes may be obtained using the procedures {!get_num_probes} and {!get_probe_name}. It may also be obtained using the command {e (help-tactics) } in the SMT 2.0 front-end. - 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. - def_API('mk_probe', PROBE, (_in(CONTEXT), _in(STRING))) *) external mk_probe : context -> string -> probe @@ -5422,7 +4502,6 @@ external mk_probe : context -> string -> probe (** Summary: Return a tactic that applies [t1] to a given goal and [t2] to every subgoal produced by t1. - def_API('tactic_and_then', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(TACTIC))) *) external tactic_and_then : context -> tactic -> tactic -> tactic @@ -5431,7 +4510,6 @@ external tactic_and_then : context -> tactic -> tactic -> tactic (** Summary: Return a tactic that first applies [t1] to a given goal, if it fails then returns the result of [t2] applied to the given goal. - def_API('tactic_or_else', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(TACTIC))) *) external tactic_or_else : context -> tactic -> tactic -> tactic @@ -5439,7 +4517,6 @@ external tactic_or_else : context -> tactic -> tactic -> tactic (** Summary: Return a tactic that applies the given tactics in parallel. - def_API('tactic_par_or', TACTIC, (_in(CONTEXT), _in(UINT), _in_array(1, TACTIC))) *) external tactic_par_or : context -> tactic array -> tactic @@ -5448,7 +4525,6 @@ external tactic_par_or : context -> tactic array -> tactic (** Summary: Return a tactic that applies [t1] to a given goal and then [t2] to every subgoal produced by t1. The subgoals are processed in parallel. - def_API('tactic_par_and_then', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(TACTIC))) *) external tactic_par_and_then : context -> tactic -> tactic -> tactic @@ -5457,7 +4533,6 @@ external tactic_par_and_then : context -> tactic -> tactic -> tactic (** Summary: Return a tactic that applies [t] to a given goal for [ms] milliseconds. If [t] does not terminate in [ms] milliseconds, then it fails. - def_API('tactic_try_for', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(UINT))) *) external tactic_try_for : context -> tactic -> int -> tactic @@ -5466,7 +4541,6 @@ external tactic_try_for : context -> tactic -> int -> tactic (** Summary: Return a tactic that applies [t] to a given goal is the probe [p] evaluates to true. If [p] evaluates to false, then the new tactic behaves like the skip tactic. - def_API('tactic_when', TACTIC, (_in(CONTEXT), _in(PROBE), _in(TACTIC))) *) external tactic_when : context -> probe -> tactic -> tactic @@ -5475,7 +4549,6 @@ external tactic_when : context -> probe -> tactic -> tactic (** Summary: Return a tactic that applies [t1] to a given goal if the probe [p] evaluates to true, and [t2] if [p] evaluates to false. - def_API('tactic_cond', TACTIC, (_in(CONTEXT), _in(PROBE), _in(TACTIC), _in(TACTIC))) *) external tactic_cond : context -> probe -> tactic -> tactic -> tactic @@ -5484,7 +4557,6 @@ external tactic_cond : context -> probe -> tactic -> tactic -> tactic (** Summary: Return a tactic that keeps applying [t] until the goal is not modified anymore or the maximum number of iterations [max] is reached. - def_API('tactic_repeat', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(UINT))) *) external tactic_repeat : context -> tactic -> int -> tactic @@ -5492,7 +4564,6 @@ external tactic_repeat : context -> tactic -> int -> tactic (** Summary: Return a tactic that just return the given goal. - def_API('tactic_skip', TACTIC, (_in(CONTEXT),)) *) external tactic_skip : context -> tactic @@ -5500,7 +4571,6 @@ external tactic_skip : context -> tactic (** Summary: Return a tactic that always fails. - def_API('tactic_fail', TACTIC, (_in(CONTEXT),)) *) external tactic_fail : context -> tactic @@ -5508,7 +4578,6 @@ external tactic_fail : context -> tactic (** Summary: Return a tactic that fails if the probe [p] evaluates to false. - def_API('tactic_fail_if', TACTIC, (_in(CONTEXT), _in(PROBE))) *) external tactic_fail_if : context -> probe -> tactic @@ -5517,7 +4586,6 @@ external tactic_fail_if : context -> probe -> tactic (** Summary: Return a tactic that fails if the goal is not trivially satisfiable (i.e., empty) or trivially unsatisfiable (i.e., contains false). - def_API('tactic_fail_if_not_decided', TACTIC, (_in(CONTEXT),)) *) external tactic_fail_if_not_decided : context -> tactic @@ -5525,7 +4593,6 @@ external tactic_fail_if_not_decided : context -> tactic (** Summary: Return a tactic that applies [t] using the given set of parameters. - def_API('tactic_using_params', TACTIC, (_in(CONTEXT), _in(TACTIC), _in(PARAMS))) *) external tactic_using_params : context -> tactic -> params -> tactic @@ -5533,7 +4600,6 @@ external tactic_using_params : context -> tactic -> params -> tactic (** Summary: Return a probe that always evaluates to val. - def_API('probe_const', PROBE, (_in(CONTEXT), _in(DOUBLE))) *) external probe_const : context -> float -> probe @@ -5541,9 +4607,7 @@ external probe_const : context -> float -> probe (** Summary: Return a probe that evaluates to "true" when the value returned by [p1] is less than the value returned by [p2]. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_lt', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) *) external probe_lt : context -> probe -> probe -> probe @@ -5551,9 +4615,7 @@ external probe_lt : context -> probe -> probe -> probe (** Summary: Return a probe that evaluates to "true" when the value returned by [p1] is greater than the value returned by [p2]. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_gt', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) *) external probe_gt : context -> probe -> probe -> probe @@ -5561,9 +4623,7 @@ external probe_gt : context -> probe -> probe -> probe (** Summary: Return a probe that evaluates to "true" when the value returned by [p1] is less than or equal to the value returned by [p2]. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_le', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) *) external probe_le : context -> probe -> probe -> probe @@ -5571,19 +4631,15 @@ external probe_le : context -> probe -> probe -> probe (** Summary: Return a probe that evaluates to "true" when the value returned by [p1] is greater than or equal to the value returned by [p2]. - - {b Remarks}: For probes, "true" is any value different from 0.0. - - def_API('probe_ge', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) + def_API('probe_ge', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) *) external probe_ge : context -> probe -> probe -> probe = "camlidl_z3_Z3_probe_ge" (** Summary: Return a probe that evaluates to "true" when the value returned by [p1] is equal to the value returned by [p2]. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_eq', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) *) external probe_eq : context -> probe -> probe -> probe @@ -5591,9 +4647,7 @@ external probe_eq : context -> probe -> probe -> probe (** Summary: Return a probe that evaluates to "true" when [p1] and [p2] evaluates to true. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_and', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) *) external probe_and : context -> probe -> probe -> probe @@ -5601,9 +4655,7 @@ external probe_and : context -> probe -> probe -> probe (** Summary: Return a probe that evaluates to "true" when [p1] or [p2] evaluates to true. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_or', PROBE, (_in(CONTEXT), _in(PROBE), _in(PROBE))) *) external probe_or : context -> probe -> probe -> probe @@ -5611,9 +4663,7 @@ external probe_or : context -> probe -> probe -> probe (** Summary: Return a probe that evaluates to "true" when [p] does not evaluate to true. - - {b Remarks}: For probes, "true" is any value different from 0.0. - def_API('probe_not', PROBE, (_in(CONTEXT), _in(PROBE))) *) external probe_not : context -> probe -> probe @@ -5621,7 +4671,6 @@ external probe_not : context -> probe -> probe (** Summary: Return the number of builtin tactics available in Z3. - def_API('get_num_tactics', UINT, (_in(CONTEXT),)) *) external get_num_tactics : context -> int @@ -5629,9 +4678,7 @@ external get_num_tactics : context -> int (** Summary: Return the name of the idx tactic. - - {b Precondition}: i < get_num_tactics c - def_API('get_tactic_name', STRING, (_in(CONTEXT), _in(UINT))) *) external get_tactic_name : context -> int -> string @@ -5639,7 +4686,6 @@ external get_tactic_name : context -> int -> string (** Summary: Return the number of builtin probes available in Z3. - def_API('get_num_probes', UINT, (_in(CONTEXT),)) *) external get_num_probes : context -> int @@ -5647,9 +4693,7 @@ external get_num_probes : context -> int (** Summary: Return the name of the i probe. - - {b Precondition}: i < get_num_probes c - def_API('get_probe_name', STRING, (_in(CONTEXT), _in(UINT))) *) external get_probe_name : context -> int -> string @@ -5657,7 +4701,6 @@ external get_probe_name : context -> int -> string (** Summary: Return a string containing a description of parameters accepted by the given tactic. - def_API('tactic_get_help', STRING, (_in(CONTEXT), _in(TACTIC))) *) external tactic_get_help : context -> tactic -> string @@ -5665,7 +4708,6 @@ external tactic_get_help : context -> tactic -> string (** Summary: Return the parameter description set for the given tactic object. - def_API('tactic_get_param_descrs', PARAM_DESCRS, (_in(CONTEXT), _in(TACTIC))) *) external tactic_get_param_descrs : context -> tactic -> param_descrs @@ -5673,7 +4715,6 @@ external tactic_get_param_descrs : context -> tactic -> param_descrs (** Summary: Return a string containing a description of the tactic with the given name. - def_API('tactic_get_descr', STRING, (_in(CONTEXT), _in(STRING))) *) external tactic_get_descr : context -> string -> string @@ -5681,7 +4722,6 @@ external tactic_get_descr : context -> string -> string (** Summary: Return a string containing a description of the probe with the given name. - def_API('probe_get_descr', STRING, (_in(CONTEXT), _in(STRING))) *) external probe_get_descr : context -> string -> string @@ -5690,7 +4730,6 @@ external probe_get_descr : context -> string -> string (** Summary: Execute the probe over the goal. The probe always produce a double value. "Boolean" probes return 0.0 for false, and a value different from 0.0 for true. - def_API('probe_apply', DOUBLE, (_in(CONTEXT), _in(PROBE), _in(GOAL))) *) external probe_apply : context -> probe -> goal -> float @@ -5698,7 +4737,6 @@ external probe_apply : context -> probe -> goal -> float (** Summary: Apply tactic [t] to the goal [g]. - def_API('tactic_apply', APPLY_RESULT, (_in(CONTEXT), _in(TACTIC), _in(GOAL))) *) external tactic_apply : context -> tactic -> goal -> apply_result @@ -5706,7 +4744,6 @@ external tactic_apply : context -> tactic -> goal -> apply_result (** Summary: Apply tactic [t] to the goal [g] using the parameter set [p]. - def_API('tactic_apply_ex', APPLY_RESULT, (_in(CONTEXT), _in(TACTIC), _in(GOAL), _in(PARAMS))) *) external tactic_apply_ex : context -> tactic -> goal -> params -> apply_result @@ -5714,7 +4751,6 @@ external tactic_apply_ex : context -> tactic -> goal -> params -> apply_result (** Summary: Convert the [apply_result] object returned by {!tactic_apply} into a string. - def_API('apply_result_to_string', STRING, (_in(CONTEXT), _in(APPLY_RESULT))) *) external apply_result_to_string : context -> apply_result -> string @@ -5722,7 +4758,6 @@ external apply_result_to_string : context -> apply_result -> string (** Summary: Return the number of subgoals in the [apply_result] object returned by {!tactic_apply}. - def_API('apply_result_get_num_subgoals', UINT, (_in(CONTEXT), _in(APPLY_RESULT))) *) external apply_result_get_num_subgoals : context -> apply_result -> int @@ -5730,9 +4765,7 @@ external apply_result_get_num_subgoals : context -> apply_result -> int (** Summary: Return one of the subgoals in the [apply_result] object returned by {!tactic_apply}. - - {b Precondition}: i < apply_result_get_num_subgoals c r - def_API('apply_result_get_subgoal', GOAL, (_in(CONTEXT), _in(APPLY_RESULT), _in(UINT))) *) external apply_result_get_subgoal : context -> apply_result -> int -> goal @@ -5741,7 +4774,6 @@ external apply_result_get_subgoal : context -> apply_result -> int -> goal (** Summary: Convert a model for the subgoal [apply_result_get_subgoal(c], r, i) into a model for the original goal [g]. Where [g] is the goal used to create [r] using [tactic_apply(c], t, g). - def_API('apply_result_convert_model', MODEL, (_in(CONTEXT), _in(APPLY_RESULT), _in(UINT), _in(MODEL))) *) external apply_result_convert_model : context -> apply_result -> int -> model -> model @@ -5753,11 +4785,7 @@ external apply_result_convert_model : context -> apply_result -> int -> model -> (** Summary: Create a new (incremental) solver. 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. - - - - + check-sat commands that take more than a given number of milliseconds to be solved. def_API('mk_solver', SOLVER, (_in(CONTEXT),)) *) external mk_solver : context -> solver @@ -5765,7 +4793,6 @@ external mk_solver : context -> solver (** Summary: Create a new (incremental) solver. - def_API('mk_simple_solver', SOLVER, (_in(CONTEXT),)) *) external mk_simple_solver : context -> solver @@ -5774,10 +4801,6 @@ external mk_simple_solver : context -> solver (** Summary: Create a new solver customized for the given logic. It behaves like {!mk_solver} if the logic is unknown or unsupported. - - - - def_API('mk_solver_for_logic', SOLVER, (_in(CONTEXT), _in(SYMBOL))) *) external mk_solver_for_logic : context -> symbol -> solver @@ -5787,7 +4810,6 @@ external mk_solver_for_logic : context -> symbol -> solver Summary: Create a new solver that is implemented using the given tactic. The solver supports the commands {!solver_push} and {!solver_pop}, but it will always solve each {!solver_check} from scratch. - def_API('mk_solver_from_tactic', SOLVER, (_in(CONTEXT), _in(TACTIC))) *) external mk_solver_from_tactic : context -> tactic -> solver @@ -5795,7 +4817,6 @@ external mk_solver_from_tactic : context -> tactic -> solver (** Summary: Return a string describing all solver available parameters. - def_API('solver_get_help', STRING, (_in(CONTEXT), _in(SOLVER))) *) external solver_get_help : context -> solver -> string @@ -5803,7 +4824,6 @@ external solver_get_help : context -> solver -> string (** Summary: Return the parameter description set for the given solver object. - def_API('solver_get_param_descrs', PARAM_DESCRS, (_in(CONTEXT), _in(SOLVER))) *) external solver_get_param_descrs : context -> solver -> param_descrs @@ -5811,7 +4831,6 @@ external solver_get_param_descrs : context -> solver -> param_descrs (** Summary: Set the given solver using the given parameters. - def_API('solver_set_params', VOID, (_in(CONTEXT), _in(SOLVER), _in(PARAMS))) *) external solver_set_params : context -> solver -> params -> unit @@ -5819,11 +4838,8 @@ external solver_set_params : context -> solver -> params -> unit (** Summary: Create a backtracking point. - - The solver contains a stack of assertions. - + The solver contains a stack of assertions. - {b See also}: {!solver_pop} - def_API('solver_push', VOID, (_in(CONTEXT), _in(SOLVER))) *) external solver_push : context -> solver -> unit @@ -5831,11 +4847,8 @@ external solver_push : context -> solver -> unit (** Summary: Backtrack [n] backtracking points. - - {b See also}: {!solver_push} - - {b Precondition}: n <= solver_get_num_scopes c s - def_API('solver_pop', VOID, (_in(CONTEXT), _in(SOLVER), _in(UINT))) *) external solver_pop : context -> solver -> int -> unit @@ -5843,7 +4856,6 @@ external solver_pop : context -> solver -> int -> unit (** Summary: Remove all assertions from the solver. - def_API('solver_reset', VOID, (_in(CONTEXT), _in(SOLVER))) *) external solver_reset : context -> solver -> unit @@ -5851,10 +4863,8 @@ external solver_reset : context -> solver -> unit (** Summary: Return the number of backtracking points. - - {b See also}: {!solver_push} - {b See also}: {!solver_pop} - def_API('solver_get_num_scopes', UINT, (_in(CONTEXT), _in(SOLVER))) *) external solver_get_num_scopes : context -> solver -> int @@ -5862,34 +4872,42 @@ external solver_get_num_scopes : context -> solver -> int (** Summary: Assert a constraint into the solver. - The functions {!solver_check} and {!solver_check_assumptions} should be used to check whether the logical context is consistent or not. - def_API('solver_assert', VOID, (_in(CONTEXT), _in(SOLVER), _in(AST))) *) external solver_assert : context -> solver -> ast -> unit = "camlidl_z3_Z3_solver_assert" +(** + Summary: Assert a constraint [a] into the solver, and track it (in the unsat) core using + the Boolean constant [p]. + This API is an alternative to {!solver_check_assumptions} for extracting unsat cores. + Both APIs can be used in the same solver. The unsat core will contain a combination + of the Boolean variables provided using solver_assert_and_track and the Boolean literals + provided using {!solver_check_assumptions}. + - {b Precondition}: [a] must be a Boolean expression + - {b Precondition}: [p] must be a Boolean constant aka variable. + def_API('solver_assert_and_track', VOID, (_in(CONTEXT), _in(SOLVER), _in(AST), _in(AST))) +*) +external solver_assert_and_track : context -> solver -> ast -> ast -> unit + = "camlidl_z3_Z3_solver_assert_and_track" + (** Summary: Return the set of asserted formulas as a goal object. - - def_API('solver_get_assertions', AST_VECTOR, (_in(CONTEXT), _in(SOLVER))) + def_API('solver_get_assertions', AST_VECTOR, (_in(CONTEXT), _in(SOLVER))) *) external solver_get_assertions : context -> solver -> ast_vector = "camlidl_z3_Z3_solver_get_assertions" (** Summary: Check whether the assertions in a given solver are consistent or not. - The function {!solver_get_model} retrieves a model if the assertions are not unsatisfiable (i.e., the result is not \c L_FALSE) and model construction is enabled. - The function {!solver_get_proof} retrieves a proof if proof - generation was enabled when the context was created, and the + generation was enabled when the context was created, and the assertions are unsatisfiable (i.e., the result is [L_FALSE)]. - def_API('solver_check', INT, (_in(CONTEXT), _in(SOLVER))) *) external solver_check : context -> solver -> lbool @@ -5898,12 +4916,9 @@ external solver_check : context -> solver -> lbool (** Summary: Check whether the assertions in the given solver and optional assumptions are consistent or not. - - The function {!solver_get_unsat_core} retrieves the subset of the + The function {!solver_get_unsat_core} retrieves the subset of the assumptions used in the unsatisfiability proof produced by Z3. - - {b See also}: {!solver_check} - def_API('solver_check_assumptions', INT, (_in(CONTEXT), _in(SOLVER), _in(UINT), _in_array(2, AST))) *) external solver_check_assumptions : context -> solver -> ast array -> lbool @@ -5911,10 +4926,8 @@ external solver_check_assumptions : context -> solver -> ast array -> lbool (** Summary: Retrieve the model for the last {!solver_check} or {!solver_check_assumptions} - - The error handler is invoked if a model is not available because + The error handler is invoked if a model is not available because the commands above were not invoked for the given solver, or if the result was [L_FALSE]. - def_API('solver_get_model', MODEL, (_in(CONTEXT), _in(SOLVER))) *) external solver_get_model : context -> solver -> model @@ -5922,11 +4935,9 @@ external solver_get_model : context -> solver -> model (** Summary: Retrieve the proof for the last {!solver_check} or {!solver_check_assumptions} - The error handler is invoked if proof generation is not enabled, or if the commands above were not invoked for the given solver, or if the result was different from [L_FALSE]. - def_API('solver_get_proof', AST, (_in(CONTEXT), _in(SOLVER))) *) external solver_get_proof : context -> solver -> ast @@ -5935,7 +4946,6 @@ external solver_get_proof : context -> solver -> ast (** Summary: Retrieve the unsat core for the last {!solver_check_assumptions} The unsat core is a subset of the assumptions [a]. - def_API('solver_get_unsat_core', AST_VECTOR, (_in(CONTEXT), _in(SOLVER))) *) external solver_get_unsat_core : context -> solver -> ast_vector @@ -5944,7 +4954,6 @@ external solver_get_unsat_core : context -> solver -> ast_vector (** Summary: Return a brief justification for an "unknown" result (i.e., L_UNDEF) for the commands {!solver_check} and {!solver_check_assumptions} - def_API('solver_get_reason_unknown', STRING, (_in(CONTEXT), _in(SOLVER))) *) external solver_get_reason_unknown : context -> solver -> string @@ -5952,9 +4961,6 @@ external solver_get_reason_unknown : context -> solver -> string (** Summary: Return statistics for the given solver. - - - def_API('solver_get_statistics', STATS, (_in(CONTEXT), _in(SOLVER))) *) external solver_get_statistics : context -> solver -> stats @@ -5962,7 +4968,6 @@ external solver_get_statistics : context -> solver -> stats (** Summary: Convert a solver into a string. - def_API('solver_to_string', STRING, (_in(CONTEXT), _in(SOLVER))) *) external solver_to_string : context -> solver -> string @@ -5976,25 +4981,23 @@ type stat_datum = Stat_int of int | Stat_float of float type stats_refined = (string, stat_datum) Hashtbl.t -(** +(** Summary: [stats_refine c s] is the refined stats of [s]. *) val stats_refine : context -> stats -> stats_refined (** Summary: Convert a statistics into a string. - def_API('stats_to_string', STRING, (_in(CONTEXT), _in(STATS))) *) external stats_to_string : context -> stats -> string = "camlidl_z3_Z3_stats_to_string" (** - {4 {L Low-level API}} + {4 {L Low-level API}} *) (** Summary: Return the number of statistical data in [s]. - def_API('stats_size', UINT, (_in(CONTEXT), _in(STATS))) *) external stats_size : context -> stats -> int @@ -6002,9 +5005,7 @@ external stats_size : context -> stats -> int (** Summary: Return the key (a string) for a particular statistical data. - - {b Precondition}: idx < stats_size c s - def_API('stats_get_key', STRING, (_in(CONTEXT), _in(STATS), _in(UINT))) *) external stats_get_key : context -> stats -> int -> string @@ -6012,9 +5013,7 @@ external stats_get_key : context -> stats -> int -> string (** Summary: Return TRUE if the given statistical data is a unsigned int integer. - - {b Precondition}: idx < stats_size c s - def_API('stats_is_uint', BOOL, (_in(CONTEXT), _in(STATS), _in(UINT))) *) external stats_is_uint : context -> stats -> int -> bool @@ -6022,9 +5021,7 @@ external stats_is_uint : context -> stats -> int -> bool (** Summary: Return TRUE if the given statistical data is a double. - - {b Precondition}: idx < stats_size c s - def_API('stats_is_double', BOOL, (_in(CONTEXT), _in(STATS), _in(UINT))) *) external stats_is_double : context -> stats -> int -> bool @@ -6032,9 +5029,7 @@ external stats_is_double : context -> stats -> int -> bool (** Summary: Return the unsigned int value of the given statistical data. - - {b Precondition}: idx < stats_size c s && stats_is_uint c s - def_API('stats_get_uint_value', UINT, (_in(CONTEXT), _in(STATS), _in(UINT))) *) external stats_get_uint_value : context -> stats -> int -> int @@ -6042,25 +5037,22 @@ external stats_get_uint_value : context -> stats -> int -> int (** Summary: Return the double value of the given statistical data. - - {b Precondition}: idx < stats_size c s && stats_is_double c s - def_API('stats_get_double_value', DOUBLE, (_in(CONTEXT), _in(STATS), _in(UINT))) *) external stats_get_double_value : context -> stats -> int -> float = "camlidl_z3_Z3_stats_get_double_value" -(** - {2 {L Legacy V3 API}} -*) - +(** + {2 {L Legacy V3 API}} +*) module V3 : sig -(** - {2 {L Legacy V3 API}} -*) +(** + {2 {L Legacy V3 API}} +*) -(* File generated from z3.idl *) +(* File generated from z3V3.idl *) type symbol and literals @@ -6296,24 +5288,17 @@ and ast_print_mode = (** - - *) (** {2 {L Types}} - - - Most of the types in the API are abstract. - - + Most of the types in the API are abstract. - [context]: manager of all other Z3 objects, global configuration options, etc. - - [symbol]: Lisp-like symbol used to name types, constants, and functions. A symbol can be created using string or integers. + - [symbol]: Lisp-like symbol used to name types, constants, and functions. A symbol can be created using string or integers. - [ast]: abstract syntax tree node. That is, the data-structure used in Z3 to represent terms, formulas and types. - [sort]: kind of AST used to represent types. - [func_decl]: kind of AST used to represent function symbols. - [app]: kind of AST used to represent function applications. - [pattern]: kind of AST used to represent pattern and multi-patterns used to guide quantifier instantiation. - - [params]: parameter set used to configure many components such as: simplifiers, tactics, solvers, etc. - [model]: model for the constraints asserted into the logical context. - [func_interp]: interpretation of a function in a model. @@ -6329,23 +5314,21 @@ and ast_print_mode = - [stats]: statistical data for a solver. *) (** - {!lbool} + {!lbool} Lifted Boolean type: [false], [undefined], [true]. *) (** - {!symbol_kind} + {!symbol_kind} The different kinds of symbol. In Z3, a symbol can be represented using integers and strings (See {!get_symbol_kind}). - - {b See also}: {!mk_int_symbol} - {b See also}: {!mk_string_symbol} *) (** - {!parameter_kind} + {!parameter_kind} The different kinds of parameters that can be associated with function symbols. - {b See also}: {!get_decl_num_parameters} - {b See also}: {!get_decl_parameter_kind} - - PARAMETER_INT is used for integer parameters. - PARAMETER_DOUBLE is used for double parameters. - PARAMETER_RATIONAL is used for parameters that are rational numbers. @@ -6355,23 +5338,23 @@ and ast_print_mode = - PARAMETER_FUNC_DECL is used for function declaration parameters. *) (** - {!sort_kind} + {!sort_kind} The different kinds of Z3 types (See {!get_sort_kind}). *) (** - {!ast_kind} + {!ast_kind} The different kinds of Z3 AST (abstract syntax trees). That is, terms, formulas and types. - - APP_AST: constant and applications - - NUMERAL_AST: numeral constants - - VAR_AST: bound variables - - QUANTIFIER_AST: quantifiers - - SORT_AST: sort - - FUNC_DECL_AST: function declaration - - UNKNOWN_AST: internal + - APP_AST: constant and applications + - NUMERAL_AST: numeral constants + - VAR_AST: bound variables + - QUANTIFIER_AST: quantifiers + - SORT_AST: sort + - FUNC_DECL_AST: function declaration + - UNKNOWN_AST: internal *) (** - {!decl_kind} + {!decl_kind} The different kinds of interpreted function kinds. - OP_TRUE The constant true. @@ -6436,9 +5419,9 @@ and ast_print_mode = - OP_POWER Power operator x^y. - OP_STORE Array store. It satisfies select(store(a,i,v),j) = if i = j then v else select(a,j). - Array store takes at least 3 arguments. + Array store takes at least 3 arguments. - - OP_SELECT Array select. + - OP_SELECT Array select. - OP_CONST_ARRAY The constant array. For example, select(const(v),i) = v holds for every v and i. The function is unary. @@ -6473,7 +5456,7 @@ and ast_print_mode = - OP_BSUB Binary subtraction. - OP_BMUL Binary multiplication. - + - OP_BSDIV Binary signed division. - OP_BUDIV Binary unsigned int division. @@ -6493,16 +5476,16 @@ and ast_print_mode = - OP_BUREM0 Unary function. burem(x,0) is congruent to burem0(x). - OP_BSMOD0 Unary function. bsmod(x,0) is congruent to bsmod0(x). - + - OP_ULEQ Unsigned bit-vector <= - Binary relation. - - OP_SLEQ Signed bit-vector <= - Binary relation. + - OP_SLEQ Signed bit-vector <= - Binary relation. - - OP_UGEQ Unsigned bit-vector >= - Binary relation. + - OP_UGEQ Unsigned bit-vector >= - Binary relation. - - OP_SGEQ Signed bit-vector >= - Binary relation. + - OP_SGEQ Signed bit-vector >= - Binary relation. - - OP_ULT Unsigned bit-vector < - Binary relation. + - OP_ULT Unsigned bit-vector < - Binary relation. - OP_SLT Signed bit-vector < - Binary relation. @@ -6562,7 +5545,7 @@ and ast_print_mode = is not supported by the decision procedures. Only the most rudimentary simplification rules are applied to this function. - - OP_CARRY Compute the carry bit in a full-adder. + - OP_CARRY 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))) @@ -6575,7 +5558,7 @@ and ast_print_mode = - OP_PR_TRUE: Proof for the expression 'true'. - OP_PR_ASSERTED: Proof for a fact asserted by the user. - + - OP_PR_GOAL: Proof for a fact (tagged as goal) asserted by the user. - OP_PR_MODUS_PONENS: Given a proof for p and a proof for (implies p q), produces a proof for q. @@ -6587,7 +5570,7 @@ and ast_print_mode = The second antecedents may also be a proof for (iff p q). - OP_PR_REFLEXIVITY: A proof for (R t t), where R is a reflexive relation. This proof object has no antecedents. - The only reflexive relations that are used are + The only reflexive relations that are used are equivalence modulo namings, equality and equivalence. That is, R is either '~', '=' or 'iff'. @@ -6607,7 +5590,7 @@ and ast_print_mode = } - OP_PR_TRANSITIVITY_STAR: Condensed transitivity proof. This proof object is only used if the parameter PROOF_MODE is 1. - It combines several symmetry and transitivity proofs. + It combines several symmetry and transitivity proofs. Example: {e @@ -6620,7 +5603,7 @@ and ast_print_mode = 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, + 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. @@ -6638,8 +5621,8 @@ and ast_print_mode = T1: (~ p q) [quant-intro T1]: (~ (forall (x) p) (forall (x) q)) - - - OP_PR_DISTRIBUTIVITY: Distributivity proof object. + + - OP_PR_DISTRIBUTIVITY: Distributivity proof object. Given that f (= or) distributes over g (= and), produces a proof for (= (f a (g c d)) @@ -6653,11 +5636,11 @@ and ast_print_mode = 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 + Remark. This rule is used by the CNF conversion pass and instantiated by f = or, and g = and. - + - OP_PR_AND_ELIM: Given a proof for (and l_1 ... l_n), produces a proof for l_i - + {e T1: (and l_1 ... l_n) [and-elim T1]: l_i @@ -6673,10 +5656,10 @@ and ast_print_mode = 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), + 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: {e @@ -6698,22 +5681,22 @@ and ast_print_mode = - OP_PR_PULL_QUANT: A proof for (iff (f (forall (x) q(x)) r) (forall (x) (f (q x) r))). This proof object has no antecedents. - OP_PR_PULL_QUANT_STAR: 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 is only used if the parameter PROOF_MODE is 1. This proof object has no antecedents. - + - OP_PR_PUSH_QUANT: A proof for: {e (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. - - OP_PR_ELIM_UNUSED_VARS: + - OP_PR_ELIM_UNUSED_VARS: 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])) + (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. @@ -6723,14 +5706,14 @@ and ast_print_mode = if x does not occur in t. This proof object has no antecedents. - + Several variables can be eliminated simultaneously. - OP_PR_QUANT_INST: A proof of (or (not (forall (x) (P x))) (P a)) - OP_PR_HYPOTHESIS: Mark a hypothesis in a natural deduction style proof. - - OP_PR_LEMMA: + - OP_PR_LEMMA: {e T1: false @@ -6740,16 +5723,16 @@ and ast_print_mode = It converts the proof in a proof for (or (not l_1) ... (not l_n)), when T1 contains the hypotheses: l_1, ..., l_n. - - OP_PR_UNIT_RESOLUTION: + - OP_PR_UNIT_RESOLUTION: {e - T1: (or l_1 ... l_n l_1' ... l_m') - T2: (not l_1) + T1: (or l_1 ... l_n l_1' ... l_m') + T2: (not l_1) ... - T(n+1): (not l_n) + T(n+1): (not l_n) [unit-resolution T1 ... T(n+1)]: (or l_1' ... l_m') } - - OP_PR_IFF_TRUE: + - OP_PR_IFF_TRUE: {e T1: p [iff-true T1]: (iff p true) @@ -6764,14 +5747,14 @@ and ast_print_mode = - OP_PR_COMMUTATIVITY: [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. - + - OP_PR_DEF_AXIOM: Proof object used to justify Tseitin's like axioms: - + {e (or (not (and p q)) p) (or (not (and p q)) q) @@ -6800,7 +5783,7 @@ and ast_print_mode = You can recover the propositional tautologies by unfolding the Boolean connectives in the axioms a small bounded number of steps (=3). - + - OP_PR_DEF_INTRO: 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: @@ -6816,17 +5799,17 @@ and ast_print_mode = [def-intro]: (and (or (not cond) (= n th)) (or cond (= n el))) Otherwise: - [def-intro]: (= n e) + [def-intro]: (= n e) - - OP_PR_APPLY_DEF: + - OP_PR_APPLY_DEF: [apply-def T1]: F ~ n F is 'equivalent' to n, given that T1 is a proof that n is a name for F. - + - OP_PR_IFF_OEQ: T1: (iff p q) [iff~ T1]: (~ p q) - + - OP_PR_NNF_POS: Proof for a (positive) NNF step. Example: {e T1: (not s_1) ~ r_1 @@ -6841,7 +5824,7 @@ and ast_print_mode = The quantifier is retained (unless the bound variables are eliminated). Example {e - T1: q ~ q_new + 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 @@ -6850,7 +5833,7 @@ and ast_print_mode = NNF_NEG furthermore handles the case where negation is pushed over Boolean connectives 'and' and 'or'. - + - OP_PR_NFF_NEG: Proof for a (negative) NNF step. Examples: {e T1: (not s_1) ~ r_1 @@ -6871,24 +5854,24 @@ and ast_print_mode = (and (or r_1 r_2) (or r_1' r_2'))) } - OP_PR_NNF_STAR: 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 is only used if the parameter PROOF_MODE is 1. + This proof object may have n antecedents. Each antecedent is a PR_DEF_INTRO. - OP_PR_CNF_STAR: 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. + 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. + + - OP_PR_SKOLEMIZE: Proof for: - - OP_PR_SKOLEMIZE: Proof for: - {e [sk]: (~ (not (forall x (p x y))) (not (p (sk y) y))) [sk]: (~ (exists x (p x y)) (p (sk y) y)) } This proof object has no antecedents. - + - OP_PR_MODUS_PONENS_OEQ: Modus ponens style rule for equi-satisfiability. {e T1: p @@ -6901,9 +5884,9 @@ and ast_print_mode = 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. + 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. @@ -6934,7 +5917,7 @@ and ast_print_mode = {e (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln-1)) } - In other words we use the following (Prolog style) convention for Horn + In other words we use the following (Prolog style) convention for Horn implications: The head of a Horn implication is position 0, the first conjunct in the body of an implication is position 1 @@ -6957,16 +5940,16 @@ and ast_print_mode = - OP_RA_STORE: Insert a record into a relation. - The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements + The function takes [n+1] arguments, where the first argument is the relation and the remaining [n] elements correspond to the [n] columns of the relation. - - OP_RA_EMPTY: Creates the empty relation. - + - OP_RA_EMPTY: Creates the empty relation. + - OP_RA_IS_EMPTY: Tests if the relation is empty. - OP_RA_JOIN: Create the relational join. - - OP_RA_UNION: Create the union or convex hull of two relations. + - OP_RA_UNION: Create the union or convex hull of two relations. The function takes two arguments. - OP_RA_WIDEN: Widen two relations. @@ -6976,7 +5959,7 @@ and ast_print_mode = The function takes one argument. - OP_RA_FILTER: Filter (restrict) a relation with respect to a predicate. - The first argument is a relation. + 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. @@ -6991,23 +5974,23 @@ and ast_print_mode = target are elements in x in pos, such that there is no y in neg that agrees with x on the columns c1, d1, .., cN, dN. - - - OP_RA_RENAME: rename columns in the relation. + + - OP_RA_RENAME: rename columns in the relation. The function takes one argument. The parameters contain the renaming as a cycle. - + - OP_RA_COMPLEMENT: Complement the relation. - OP_RA_SELECT: Check if a record is an element of the relation. The function takes [n+1] arguments, where the first argument is a relation, and the remaining [n] arguments correspond to a record. - - OP_RA_CLONE: Create a fresh copy (clone) of a relation. + - OP_RA_CLONE: Create a fresh copy (clone) of a relation. The function is logically the identity, but in the context of a register machine allows - for [OP_RA_UNION] + for [OP_RA_UNION] to perform destructive updates to the first argument. - + - OP_FD_LT: A less than predicate over the finite domain FINITE_DOMAIN_SORT. @@ -7027,10 +6010,10 @@ and ast_print_mode = - OP_UNINTERPRETED: kind used for uninterpreted symbols. *) (** - {!param_kind} + {!param_kind} The different kinds of parameters that can be associated with parameter sets. - (see {!mk_params}). + (see {!mk_params}). - PK_UINT integer parameters. - PK_BOOL boolean parameters. @@ -7041,77 +6024,128 @@ and ast_print_mode = - PK_INVALID invalid parameter. *) (** - {!search_failure} + {!search_failure} The different kinds of search failure types. - - NO_FAILURE: The last search was successful - - UNKNOWN: Undocumented failure reason - - TIMEOUT: Timeout - - MEMOUT_WATERMAK: Search hit a memory high-watermak limit - - CANCELED: External cancel flag was set - - NUM_CONFLICTS: Maximum number of conflicts was reached - - THEORY: Theory is incomplete - - QUANTIFIERS: Logical context contains universal quantifiers + - NO_FAILURE: The last search was successful + - UNKNOWN: Undocumented failure reason + - TIMEOUT: Timeout + - MEMOUT_WATERMAK: Search hit a memory high-watermak limit + - CANCELED: External cancel flag was set + - NUM_CONFLICTS: Maximum number of conflicts was reached + - THEORY: Theory is incomplete + - QUANTIFIERS: Logical context contains universal quantifiers *) (** - {!ast_print_mode} + {!ast_print_mode} Z3 pretty printing modes (See {!set_ast_print_mode}). - - PRINT_SMTLIB_FULL: Print AST nodes in SMTLIB verbose format. - - PRINT_LOW_LEVEL: Print AST nodes using a low-level format. + - PRINT_SMTLIB_FULL: Print AST nodes in SMTLIB verbose format. + - PRINT_LOW_LEVEL: Print AST nodes using a low-level format. - PRINT_SMTLIB_COMPLIANT: Print AST nodes in SMTLIB 1.x compliant format. - PRINT_SMTLIB2_COMPLIANT: Print AST nodes in SMTLIB 2.x compliant format. *) (** Definitions for update_api.py - - def_Type('CONFIG', 'config', 'Config') - def_Type('CONTEXT', 'context', 'ContextObj') - def_Type('AST', 'ast', 'Ast') - def_Type('APP', 'app', 'Ast') - def_Type('SORT', 'sort', 'Sort') - def_Type('FUNC_DECL', 'func_decl', 'FuncDecl') - def_Type('PATTERN', 'pattern', 'Pattern') - def_Type('MODEL', 'model', 'Model') - def_Type('LITERALS', 'literals', 'Literals') - def_Type('CONSTRUCTOR', 'constructor', 'Constructor') + def_Type('CONFIG', 'config', 'Config') + def_Type('CONTEXT', 'context', 'ContextObj') + def_Type('AST', 'ast', 'Ast') + def_Type('APP', 'app', 'Ast') + def_Type('SORT', 'sort', 'Sort') + def_Type('FUNC_DECL', 'func_decl', 'FuncDecl') + def_Type('PATTERN', 'pattern', 'Pattern') + def_Type('MODEL', 'model', 'Model') + def_Type('LITERALS', 'literals', 'Literals') + def_Type('CONSTRUCTOR', 'constructor', 'Constructor') def_Type('CONSTRUCTOR_LIST', 'constructor_list', 'ConstructorList') - def_Type('THEORY', 'theory', 'ctypes.c_void_p') - def_Type('THEORY_DATA', 'theory_data', 'ctypes.c_void_p') - def_Type('SOLVER', 'solver', 'SolverObj') - def_Type('GOAL', 'goal', 'GoalObj') - def_Type('TACTIC', 'tactic', 'TacticObj') - def_Type('PARAMS', 'params', 'Params') - def_Type('PROBE', 'probe', 'ProbeObj') - def_Type('STATS', 'stats', 'StatsObj') - def_Type('AST_VECTOR', 'ast_vector', 'AstVectorObj') - def_Type('AST_MAP', 'ast_map', 'AstMapObj') - def_Type('APPLY_RESULT', 'apply_result', 'ApplyResultObj') - def_Type('FUNC_INTERP', 'func_interp', 'FuncInterpObj') - def_Type('FUNC_ENTRY', 'func_entry', 'FuncEntryObj') - def_Type('FIXEDPOINT', 'fixedpoint', 'FixedpointObj') - def_Type('PARAM_DESCRS', 'param_descrs', 'ParamDescrs') + def_Type('THEORY', 'theory', 'ctypes.c_void_p') + def_Type('THEORY_DATA', 'theory_data', 'ctypes.c_void_p') + def_Type('SOLVER', 'solver', 'SolverObj') + def_Type('GOAL', 'goal', 'GoalObj') + def_Type('TACTIC', 'tactic', 'TacticObj') + def_Type('PARAMS', 'params', 'Params') + def_Type('PROBE', 'probe', 'ProbeObj') + def_Type('STATS', 'stats', 'StatsObj') + def_Type('AST_VECTOR', 'ast_vector', 'AstVectorObj') + def_Type('AST_MAP', 'ast_map', 'AstMapObj') + def_Type('APPLY_RESULT', 'apply_result', 'ApplyResultObj') + def_Type('FUNC_INTERP', 'func_interp', 'FuncInterpObj') + def_Type('FUNC_ENTRY', 'func_entry', 'FuncEntryObj') + def_Type('FIXEDPOINT', 'fixedpoint', 'FixedpointObj') + def_Type('PARAM_DESCRS', 'param_descrs', 'ParamDescrs') *) +(** + {2 {L Configuration}} +*) +(** + Summary: Set a global (or module) parameter. + This setting is shared by all Z3 contexts. + When a Z3 module is initialized it will use the value of these parameters + when params objects are not provided. + The name of parameter can be composed of characters [a-z][A-Z], digits [0-9], '-' and '_'. + The character '.' is a delimiter (more later). + The parameter names are case-insensitive. The character '-' should be viewed as an "alias" for '_'. + Thus, the following parameter names are considered equivalent: "pp.decimal-precision" and "PP.DECIMAL_PRECISION". + This function can be used to set parameters for a specific Z3 module. + This can be done by using .. + For example: + global_param_set('pp.decimal', 'true') + will set the parameter "decimal" in the module "pp" to true. + def_API('global_param_set', VOID, (_in(STRING), _in(STRING))) +*) +external global_param_set : string -> string -> unit + = "camlidl_z3V3_Z3_global_param_set" + +(** + Summary: Restore the value of all global (and module) parameters. + This command will not affect already created objects (such as tactics and solvers). + - {b See also}: {!global_param_set} + def_API('global_param_reset_all', VOID, ()) +*) +external global_param_reset_all : unit -> unit + = "camlidl_z3V3_Z3_global_param_reset_all" + +(** + Summary: Get a global (or module) parameter. + Returns [None] + if the parameter value does not exist. + - {b See also}: {!global_param_set} + The caller must invoke {!global_param_del_value} to delete the value returned at [param_value]. + - {b Remarks}: This function cannot be invoked simultaneously from different threads without synchronization. + The result string stored in param_value is stored in shared location. + def_API('global_param_get', BOOL, (_in(STRING), _out(STRING))) +*) +external global_param_get : string -> string option + = "camlidl_z3V3_Z3_global_param_get" + (** {2 {L Create configuration}} *) (** - Summary: Create a configuration. - - Configurations are created in order to assign parameters prior to creating - contexts for Z3 interaction. For example, if the users wishes to use model + Summary: Create a configuration object for the Z3 context object. + Configurations are created in order to assign parameters prior to creating + contexts for Z3 interaction. For example, if the users wishes to use proof generation, then call: - - [set_param_value cfg "MODEL" "true"] - + [set_param_value cfg "proof" "true"] - {b Remarks}: Consider using {!mk_context_x} instead of using explicit configuration objects. The function {!mk_context_x} receives an array of string pairs. This array represents the - configuration options. - + configuration options. + - {b Remarks}: In previous versions of Z3, the [config] was used to store + global and module configurations. Now, we should use [global_param_set]. + The following parameters can be set: + - proof (Boolean) Enable proof generation + - debug_ref_count (Boolean) Enable debug support for ast reference counting + - trace (Boolean) Tracing support for VCC + - trace_file_name (String) Trace out file for VCC traces + - timeout (unsigned) default timeout (in milliseconds) used for solvers + - well_sorted_check type checker + - auto_config use heuristics to automatically select solver and configure it + - model model generation for solvers, this parameter can be overwritten when creating a solver + - model_validate validate models produced by solvers + - unsat_core unsat-core generation for solvers, this parameter can be overwritten when creating a solver - {b See also}: {!set_param_value} - {b See also}: {!del_config} - def_API('mk_config', CONFIG, ()) *) external mk_config : unit -> config @@ -7119,9 +6153,7 @@ external mk_config : unit -> config (** Summary: Delete the given configuration object. - - {b See also}: {!mk_config} - def_API('del_config', VOID, (_in(CONFIG),)) *) external del_config : config -> unit @@ -7129,15 +6161,8 @@ external del_config : config -> unit (** Summary: Set a configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - - {v - z3.exe -ini? - v} - + The following parameters can be set for - {b See also}: {!mk_config} - def_API('set_param_value', VOID, (_in(CONFIG), _in(STRING), _in(STRING))) *) external set_param_value : config -> string -> string -> unit @@ -7147,16 +6172,10 @@ external set_param_value : config -> string -> string -> unit {2 {L Create context}} *) (** - Summary: Create a context using the given configuration. - + Summary: Create a context using the given configuration. After a context is created, the configuration cannot be changed, although some parameters can be changed using {!update_param_value}. All main interaction with Z3 happens in the context of a [context]. - - - - - def_API('mk_context', CONTEXT, (_in(CONFIG),)) *) external mk_context : config -> context @@ -7164,44 +6183,23 @@ external mk_context : config -> context (** Summary: Delete the given logical context. - - {b See also}: {!mk_context} - def_API('del_context', VOID, (_in(CONTEXT),)) *) external del_context : context -> unit = "camlidl_z3V3_Z3_del_context" (** - Summary: Update a mutable configuration parameter. - - The list of all configuration parameters can be obtained using the Z3 executable: - - {v - z3.exe -ini? - v} - - Only a few configuration parameters are mutable once the context is created. - The error handler is invoked when trying to modify an immutable parameter. - - - - {b See also}: {!mk_context } - + Summary: Set a value of a context parameter. + - {b See also}: {!global_param_set} def_API('update_param_value', VOID, (_in(CONTEXT), _in(STRING), _in(STRING))) *) external update_param_value : context -> string -> string -> unit = "camlidl_z3V3_Z3_update_param_value" (** - Summary: Get a configuration parameter. - - Returns [None] - if the parameter value does not exist. - - - - - {b See also}: {!mk_context } - + Summary: Return the value of a context parameter. + - {b See also}: {!global_param_get} def_API('get_param_value', BOOL, (_in(CONTEXT), _in(STRING), _out(STRING))) *) external get_param_value : context -> string -> string option @@ -7211,18 +6209,14 @@ external get_param_value : context -> string -> string option {2 {L Symbols}} *) (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** Summary: Create a Z3 symbol using an integer. - Symbols are used to name several term and type constructors. - NB. Not all integers can be passed to this function. The legal range of unsigned int integers is 0 to 2^30-1. - - {b See also}: {!mk_string_symbol} - def_API('mk_int_symbol', SYMBOL, (_in(CONTEXT), _in(INT))) *) external mk_int_symbol : context -> int -> symbol @@ -7230,11 +6224,8 @@ external mk_int_symbol : context -> int -> symbol (** Summary: Create a Z3 symbol using a C string. - Symbols are used to name several term and type constructors. - - {b See also}: {!mk_int_symbol} - def_API('mk_string_symbol', SYMBOL, (_in(CONTEXT), _in(STRING))) *) external mk_string_symbol : context -> string -> symbol @@ -7244,23 +6235,19 @@ external mk_string_symbol : context -> string -> symbol {2 {L Sorts}} *) (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** Summary: Create a free (uninterpreted) type using the given name (symbol). - Two free types are considered the same iff the have the same name. - def_API('mk_uninterpreted_sort', SORT, (_in(CONTEXT), _in(SYMBOL))) *) external mk_uninterpreted_sort : context -> symbol -> sort = "camlidl_z3V3_Z3_mk_uninterpreted_sort" (** - Summary: Create the Boolean type. - + Summary: Create the Boolean type. This type is used to create propositional variables and predicates. - def_API('mk_bool_sort', SORT, (_in(CONTEXT), )) *) external mk_bool_sort : context -> sort @@ -7268,24 +6255,19 @@ external mk_bool_sort : context -> sort (** Summary: Create the integer type. - This type is not the int type found in programming languages. A machine integer can be represented using bit-vectors. The function {!mk_bv_sort} creates a bit-vector type. - - {b See also}: {!mk_bv_sort} - def_API('mk_int_sort', SORT, (_in(CONTEXT), )) *) external mk_int_sort : context -> sort = "camlidl_z3V3_Z3_mk_int_sort" (** - Summary: Create the real type. - + Summary: Create the real type. This type is not a floating point number. Z3 does not have support for floating point numbers yet. - def_API('mk_real_sort', SORT, (_in(CONTEXT), )) *) external mk_real_sort : context -> sort @@ -7293,11 +6275,8 @@ external mk_real_sort : context -> sort (** Summary: Create a bit-vector type of the given size. - This type can also be seen as a machine integer. - - {b Remarks}: The size of the bitvector type must be greater than zero. - def_API('mk_bv_sort', SORT, (_in(CONTEXT), _in(UINT))) *) external mk_bv_sort : context -> int -> sort @@ -7305,27 +6284,21 @@ external mk_bv_sort : context -> int -> sort (** Summary: Create a named finite domain sort. - - To create constants that belong to the finite domain, + To create constants that belong to the finite domain, use the APIs for creating numerals and pass a numeric constant together with the sort returned by this call. - - - {b See also}: {!get_finite_domain_sort_size.} - + - {b See also}: {!get_finite_domain_sort_size} def_API('mk_finite_domain_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT64))) *) external mk_finite_domain_sort : context -> symbol -> int64 -> sort = "camlidl_z3V3_Z3_mk_finite_domain_sort" (** - Summary: Create an array type. - + Summary: Create an array type. We usually represent the array type as: {e [domain -> range] }. Arrays are usually used to model the heap/memory in software verification. - - {b See also}: {!mk_select} - {b See also}: {!mk_store} - def_API('mk_array_sort', SORT, (_in(CONTEXT), _in(SORT), _in(SORT))) *) external mk_array_sort : context -> sort -> sort -> sort @@ -7333,14 +6306,8 @@ external mk_array_sort : context -> sort -> sort -> sort (** Summary: Create a tuple type. - [mk_tuple_sort c name field_names field_sorts] creates a tuple with a constructor named [name], a [n] fields, where [n] is the size of the arrays [field_names] and [field_sorts]. - - - - - @param c logical context @param mk_tuple_name name of the constructor function associated with the tuple type. @param num_fields number of fields in the tuple type. @@ -7348,7 +6315,6 @@ external mk_array_sort : context -> sort -> sort -> sort @param field_sorts type of the tuple fields. @param mk_tuple_decl output parameter that will contain the constructor declaration. @param proj_decl output parameter that will contain the projection function declarations. This field must be a buffer of size [num_fields] allocated by the user. - def_API('mk_tuple_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _out(FUNC_DECL), _out_array(2, FUNC_DECL))) *) external mk_tuple_sort : context -> symbol -> symbol array -> sort array -> sort * func_decl * func_decl array @@ -7356,28 +6322,20 @@ external mk_tuple_sort : context -> symbol -> symbol array -> sort array -> sort (** Summary: Create a enumeration sort. - - [mk_enumeration_sort c enums] creates an enumeration sort with enumeration names [enums], + [mk_enumeration_sort c enums] creates an enumeration sort with enumeration names [enums], it also returns [n] predicates, where [n] is the number of [enums] corresponding to testing whether an element is one of the enumerants. - - - - - @param c logical context @param name name of the enumeration sort. @param n number of elemenets in enumeration sort. @param enum_names names of the enumerated elements. @param enum_consts constants corresponding to the enumerated elements. @param enum_testers predicates testing if terms of the enumeration sort correspond to an enumeration. - - For example, if this function is called with three symbols A, B, C and the name S, then - [s] is a sort whose name is S, and the function returns three terms corresponding to A, B, C in + For example, if this function is called with three symbols A, B, C and the name S, then + [s] is a sort whose name is S, and the function returns three terms corresponding to A, B, C in [enum_consts]. The array [enum_testers] has three predicates of type {e (s -> Bool) }. The first predicate (corresponding to A) is true when applied to A, and false otherwise. Similarly for the other predicates. - def_API('mk_enumeration_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SYMBOL), _out_array(2, FUNC_DECL), _out_array(2, FUNC_DECL))) *) external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_decl array * func_decl array @@ -7385,13 +6343,7 @@ external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_ (** Summary: Create a list sort - [mk_list_sort c name elem_sort] creates a list sort of [name], over elements of sort [elem_sort]. - - - - - @param c logical context @param name name of the list sort. @param elem_sort sort of list elements. @@ -7401,7 +6353,6 @@ external mk_enumeration_sort : context -> symbol -> symbol array -> sort * func_ @param is_cons_decl cons cell test. @param head_decl list head. @param tail_decl list tail. - def_API('mk_list_sort', SORT, (_in(CONTEXT), _in(SYMBOL), _in(SORT), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL), _out(FUNC_DECL))) *) external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_decl * func_decl * func_decl * func_decl * func_decl @@ -7409,44 +6360,38 @@ external mk_list_sort : context -> symbol -> sort -> sort * func_decl * func_dec (** Summary: Create a constructor. - @param c logical context. @param name constructor name. @param recognizer name of recognizer function. @param num_fields number of fields in constructor. @param field_names names of the constructor fields. - @param sorts field sorts, [None] + @param sorts field sorts, [None] if the field sort refers to a recursive sort. @param sort_refs reference to datatype sort that is an argument to the constructor; if the corresponding - sort reference is [None], - then the value in sort_refs should be an index referring to - one of the recursive datatypes that is declared. - + sort reference is [None], + then the value in sort_refs should be an index referring to + one of the recursive datatypes that is declared. def_API('mk_constructor', CONSTRUCTOR, (_in(CONTEXT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(3, SYMBOL), _in_array(3, SORT), _in_array(3, UINT))) *) external mk_constructor : context -> symbol -> symbol -> symbol array -> sort array -> int array -> constructor - = "camlidl_z3_Z3_mk_constructor_bytecode" "camlidl_z3V3_Z3_mk_constructor" + = "camlidl_z3V3_Z3_mk_constructor_bytecode" "camlidl_z3V3_Z3_mk_constructor" (** Summary: Reclaim memory allocated to constructor. - @param c logical context. @param constr constructor. - def_API('del_constructor', VOID, (_in(CONTEXT), _in(CONSTRUCTOR))) *) external del_constructor : context -> constructor -> unit = "camlidl_z3V3_Z3_del_constructor" (** - Summary: Create datatype, such as lists, trees, records, enumerations or unions of records. + Summary: Create datatype, such as lists, trees, records, enumerations or unions of records. The datatype may be recursive. Return the datatype sort. - @param c logical context. - @param name name of datatype. + @param name name of datatype. @param num_constructors number of constructors passed in. @param constructors array of constructor containers. - def_API('mk_datatype', SORT, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _inout_array(2, CONSTRUCTOR))) *) external mk_datatype : context -> symbol -> constructor array -> sort * constructor array @@ -7454,11 +6399,9 @@ external mk_datatype : context -> symbol -> constructor array -> sort * construc (** Summary: Create list of constructors. - @param c logical context. @param num_constructors number of constructors in list. @param constructors list of constructors. - def_API('mk_constructor_list', CONSTRUCTOR_LIST, (_in(CONTEXT), _in(UINT), _in_array(1, CONSTRUCTOR))) *) external mk_constructor_list : context -> constructor array -> constructor_list @@ -7466,12 +6409,9 @@ external mk_constructor_list : context -> constructor array -> constructor_list (** Summary: Reclaim memory allocated for constructor list. - Each constructor inside the constructor list must be independently reclaimed using {!del_constructor}. - @param c logical context. @param clist constructor list container. - def_API('del_constructor_list', VOID, (_in(CONTEXT), _in(CONSTRUCTOR_LIST))) *) external del_constructor_list : context -> constructor_list -> unit @@ -7479,28 +6419,24 @@ external del_constructor_list : context -> constructor_list -> unit (** Summary: Create mutually recursive datatypes. - @param c logical context. @param num_sorts number of datatype sorts. @param sort_names names of datatype sorts. - @param sorts array of datattype sorts. + @param sorts array of datatype sorts. @param constructor_lists list of constructors, one list per sort. - def_API('mk_datatypes', VOID, (_in(CONTEXT), _in(UINT), _in_array(1, SYMBOL), _out_array(1, SORT), _inout_array(1, CONSTRUCTOR_LIST))) *) external mk_datatypes : context -> symbol array -> constructor_list array -> sort array * constructor_list array = "camlidl_z3V3_Z3_mk_datatypes" (** - Summary: Query constructor for declared functions. - + Summary: Query constructor for declared functions. @param c logical context. @param constr constructor container. The container must have been passed in to a {!mk_datatype} call. @param num_fields number of accessor fields in the constructor. @param constructor constructor function declaration. @param tester constructor test function declaration. @param accessors array of accessor function declarations. - def_API('query_constructor', VOID, (_in(CONTEXT), _in(CONSTRUCTOR), _in(UINT), _out(FUNC_DECL), _out(FUNC_DECL), _out_array(2, FUNC_DECL))) *) external query_constructor : context -> constructor -> int -> func_decl * func_decl * func_decl array @@ -7511,22 +6447,17 @@ external query_constructor : context -> constructor -> int -> func_decl * func_d *) (** Summary: Declare a constant or function. - [mk_func_decl c n d r] creates a function with name [n], domain [d], and range [r]. - The arity of the function is the size of the array [d]. - + The arity of the function is the size of the array [d]. @param c logical context. @param s name of the constant or function. @param domain_size number of arguments. It is 0 when declaring a constant. @param domain array containing the sort of each argument. The array must contain domain_size elements. It is 0 when declaring a constant. @param range sort of the constant or the return sort of the function. - After declaring a constant or function, the function {!mk_app} can be used to create a constant or function application. - - {b See also}: {!mk_app} - def_API('mk_func_decl', FUNC_DECL, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SORT), _in(SORT))) *) external mk_func_decl : context -> symbol -> sort array -> sort -> func_decl @@ -7534,9 +6465,7 @@ external mk_func_decl : context -> symbol -> sort array -> sort -> func_decl (** Summary: Create a constant or function application. - - {b See also}: {!mk_func_decl} - def_API('mk_app', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT), _in_array(2, AST))) *) external mk_app : context -> func_decl -> ast array -> ast @@ -7544,18 +6473,9 @@ external mk_app : context -> func_decl -> ast array -> ast (** Summary: Declare and create a constant. - - - - - - - - [mk_const c s t] is a shorthand for [mk_app c (mk_func_decl c s [||] t) [||]] - + [mk_const c s t] is a shorthand for [mk_app c (mk_func_decl c s [||] t) [||]] - {b See also}: {!mk_func_decl} - {b See also}: {!mk_app} - def_API('mk_const', AST, (_in(CONTEXT), _in(SYMBOL), _in(SORT))) *) external mk_const : context -> symbol -> sort -> ast @@ -7563,14 +6483,8 @@ external mk_const : context -> symbol -> sort -> ast (** Summary: Declare a fresh constant or function. - Z3 will generate an unique name for this function declaration. - - - - - {b See also}: {!mk_func_decl} - def_API('mk_fresh_func_decl', FUNC_DECL, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SORT), _in(SORT))) *) external mk_fresh_func_decl : context -> string -> sort array -> sort -> func_decl @@ -7578,17 +6492,9 @@ external mk_fresh_func_decl : context -> string -> sort array -> sort -> func_de (** Summary: Declare and create a fresh constant. - - - - - [mk_fresh_const c p t] is a shorthand for [mk_app c (mk_fresh_func_decl c p [||] t) [||]]. - - - + [mk_fresh_const c p t] is a shorthand for [mk_app c (mk_fresh_func_decl c p [||] t) [||]]. - {b See also}: {!mk_func_decl} - {b See also}: {!mk_app} - def_API('mk_fresh_const', AST, (_in(CONTEXT), _in(STRING), _in(SORT))) *) external mk_fresh_const : context -> string -> sort -> ast @@ -7599,7 +6505,6 @@ external mk_fresh_const : context -> string -> sort -> ast *) (** Summary: Create an AST node representing [true]. - def_API('mk_true', AST, (_in(CONTEXT), )) *) external mk_true : context -> ast @@ -7607,7 +6512,6 @@ external mk_true : context -> ast (** Summary: Create an AST node representing [false]. - def_API('mk_false', AST, (_in(CONTEXT), )) *) external mk_false : context -> ast @@ -7616,51 +6520,40 @@ external mk_false : context -> ast (** Summary: \[ [ mk_eq c l r ] \] Create an AST node representing {e l = r }. - - The nodes [l] and [r] must have the same type. - + The nodes [l] and [r] must have the same type. def_API('mk_eq', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_eq : context -> ast -> ast -> ast = "camlidl_z3V3_Z3_mk_eq" (** - Summary: \[ [mk_distinct c [| t_1; ...; t_n |]] \] Create an AST node represeting a distinct construct. It is used for declaring - the arguments t_i pairwise distinct. - + the arguments t_i pairwise distinct. The [distinct] construct is used for declaring the arguments pairwise distinct. That is, {e Forall 0 <= i < j < num_args. not args[i] = args[j] }. - All arguments must have the same sort. - - {b Remarks}: The number of arguments of a distinct construct must be greater than one. - def_API('mk_distinct', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_distinct : context -> ast array -> ast = "camlidl_z3V3_Z3_mk_distinct" (** - Summary: \[ [ mk_not c a ] \] + Summary: \[ [ mk_not c a ] \] Create an AST node representing {e not(a) }. - The node [a] must have Boolean sort. - def_API('mk_not', AST, (_in(CONTEXT), _in(AST))) *) external mk_not : context -> ast -> ast = "camlidl_z3V3_Z3_mk_not" (** - Summary: \[ [ mk_ite c t1 t2 t2 ] \] + Summary: \[ [ mk_ite c t1 t2 t2 ] \] Create an AST node representing an if-then-else: {e ite(t1, t2, t3) }. - The node [t1] must have Boolean sort, [t2] and [t3] must have the same sort. The sort of the new node is equal to the sort of [t2] and [t3]. - def_API('mk_ite', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) *) external mk_ite : context -> ast -> ast -> ast -> ast @@ -7669,9 +6562,7 @@ external mk_ite : context -> ast -> ast -> ast -> ast (** Summary: \[ [ mk_iff c t1 t2 ] \] Create an AST node representing {e t1 iff t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_iff', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_iff : context -> ast -> ast -> ast @@ -7680,9 +6571,7 @@ external mk_iff : context -> ast -> ast -> ast (** Summary: \[ [ mk_implies c t1 t2 ] \] Create an AST node representing {e t1 implies t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_implies', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_implies : context -> ast -> ast -> ast @@ -7691,37 +6580,25 @@ external mk_implies : context -> ast -> ast -> ast (** Summary: \[ [ mk_xor c t1 t2 ] \] Create an AST node representing {e t1 xor t2 }. - The nodes [t1] and [t2] must have Boolean sort. - def_API('mk_xor', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_xor : context -> ast -> ast -> ast = "camlidl_z3V3_Z3_mk_xor" (** - - Summary: \[ [mk_and c [| t_1; ...; t_n |]] \] Create the conjunction: {e t_1 and ... and t_n}. - - + Summary: \[ [mk_and c [| t_1; ...; t_n |]] \] Create the conjunction: {e t_1 and ... and t_n}. All arguments must have Boolean sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_and', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_and : context -> ast array -> ast = "camlidl_z3V3_Z3_mk_and" (** - - Summary: \[ [mk_or c [| t_1; ...; t_n |]] \] Create the disjunction: {e t_1 or ... or t_n}. - - + Summary: \[ [mk_or c [| t_1; ...; t_n |]] \] Create the disjunction: {e t_1 or ... or t_n}. All arguments must have Boolean sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_or', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_or : context -> ast array -> ast @@ -7731,110 +6608,78 @@ external mk_or : context -> ast array -> ast {2 {L Arithmetic: Integers and Reals}} *) (** - - Summary: \[ [mk_add c [| t_1; ...; t_n |]] \] Create the term: {e t_1 + ... + t_n}. - - + Summary: \[ [mk_add c [| t_1; ...; t_n |]] \] Create the term: {e t_1 + ... + t_n}. All arguments must have int or real sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_add', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_add : context -> ast array -> ast = "camlidl_z3V3_Z3_mk_add" (** - - Summary: \[ [mk_mul c [| t_1; ...; t_n |]] \] Create the term: {e t_1 * ... * t_n}. - - + Summary: \[ [mk_mul c [| t_1; ...; t_n |]] \] Create the term: {e t_1 * ... * t_n}. All arguments must have int or real sort. - - {b Remarks}: Z3 has limited support for non-linear arithmetic. - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_mul', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_mul : context -> ast array -> ast = "camlidl_z3V3_Z3_mk_mul" (** - - Summary: \[ [mk_sub c [| t_1; ...; t_n |]] \] Create the term: {e t_1 - ... - t_n}. - - + Summary: \[ [mk_sub c [| t_1; ...; t_n |]] \] Create the term: {e t_1 - ... - t_n}. All arguments must have int or real sort. - - {b Remarks}: The number of arguments must be greater than zero. - def_API('mk_sub', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_sub : context -> ast array -> ast = "camlidl_z3V3_Z3_mk_sub" (** - - Summary: \[ [mk_unary_minus c arg] \] Create the term: {e - arg}. - + Summary: \[ [mk_unary_minus c arg] \] Create the term: {e - arg}. The arguments must have int or real type. - def_API('mk_unary_minus', AST, (_in(CONTEXT), _in(AST))) *) external mk_unary_minus : context -> ast -> ast = "camlidl_z3V3_Z3_mk_unary_minus" (** - - Summary: \[ [mk_div c t_1 t_2] \] Create the term: {e t_1 div t_2}. - + Summary: \[ [mk_div c t_1 t_2] \] Create the term: {e t_1 div t_2}. The arguments must either both have int type or both have real type. If the arguments have int type, then the result type is an int type, otherwise the the result type is real. - def_API('mk_div', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_div : context -> ast -> ast -> ast = "camlidl_z3V3_Z3_mk_div" (** - - Summary: \[ [mk_mod c t_1 t_2] \] Create the term: {e t_1 mod t_2}. - + Summary: \[ [mk_mod c t_1 t_2] \] Create the term: {e t_1 mod t_2}. The arguments must have int type. - def_API('mk_mod', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_mod : context -> ast -> ast -> ast = "camlidl_z3V3_Z3_mk_mod" (** - - Summary: \[ [mk_rem c t_1 t_2] \] Create the term: {e t_1 rem t_2}. - + Summary: \[ [mk_rem c t_1 t_2] \] Create the term: {e t_1 rem t_2}. The arguments must have int type. - def_API('mk_rem', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_rem : context -> ast -> ast -> ast = "camlidl_z3V3_Z3_mk_rem" (** - - The arguments must have int or real type. - def_API('mk_power', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_power : context -> ast -> ast -> ast = "camlidl_z3V3_Z3_mk_power" (** - Summary: \[ [ mk_lt c t1 t2 ] \] + Summary: \[ [ mk_lt c t1 t2 ] \] Create less than. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_lt', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_lt : context -> ast -> ast -> ast @@ -7843,9 +6688,7 @@ external mk_lt : context -> ast -> ast -> ast (** Summary: \[ [ mk_le c t1 t2 ] \] Create less than or equal to. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_le', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_le : context -> ast -> ast -> ast @@ -7854,9 +6697,7 @@ external mk_le : context -> ast -> ast -> ast (** Summary: \[ [ mk_gt c t1 t2 ] \] Create greater than. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_gt', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_gt : context -> ast -> ast -> ast @@ -7865,9 +6706,7 @@ external mk_gt : context -> ast -> ast -> ast (** Summary: \[ [ mk_ge c t1 t2 ] \] Create greater than or equal to. - The nodes [t1] and [t2] must have the same sort, and must be int or real. - def_API('mk_ge', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_ge : context -> ast -> ast -> ast @@ -7876,19 +6715,14 @@ external mk_ge : context -> ast -> ast -> ast (** Summary: \[ [ mk_int2real c t1 ] \] Coerce an integer to a real. - 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 + You can take the floor of a real by creating an auxiliary integer constant [k] and - and asserting {e mk_int2real(k) <= t1 < mk_int2real(k)+1 }. - + and asserting {e mk_int2real(k) <= t1 < mk_int2real(k)+1 }. The node [t1] must have sort integer. - - {b See also}: {!mk_real2int} - {b See also}: {!mk_is_int} - def_API('mk_int2real', AST, (_in(CONTEXT), _in(AST))) *) external mk_int2real : context -> ast -> ast @@ -7897,13 +6731,10 @@ external mk_int2real : context -> ast -> ast (** Summary: \[ [ mk_real2int c t1 ] \] Coerce a real to an integer. - The semantics of this function follows the SMT-LIB standard for the function to_int - - {b See also}: {!mk_int2real} - {b See also}: {!mk_is_int} - def_API('mk_real2int', AST, (_in(CONTEXT), _in(AST))) *) external mk_real2int : context -> ast -> ast @@ -7912,10 +6743,8 @@ external mk_real2int : context -> ast -> ast (** Summary: \[ [ mk_is_int c t1 ] \] Check if a real number is an integer. - - {b See also}: {!mk_int2real} - {b See also}: {!mk_real2int} - def_API('mk_is_int', AST, (_in(CONTEXT), _in(AST))) *) external mk_is_int : context -> ast -> ast @@ -7927,9 +6756,7 @@ external mk_is_int : context -> ast -> ast (** Summary: \[ [ mk_bvnot c t1 ] \] Bitwise negation. - The node [t1] must have a bit-vector sort. - def_API('mk_bvnot', AST, (_in(CONTEXT), _in(AST))) *) external mk_bvnot : context -> ast -> ast @@ -7938,9 +6765,7 @@ external mk_bvnot : context -> ast -> ast (** Summary: \[ [ mk_bvredand c t1 ] \] Take conjunction of bits in vector, return vector of length 1. - The node [t1] must have a bit-vector sort. - def_API('mk_bvredand', AST, (_in(CONTEXT), _in(AST))) *) external mk_bvredand : context -> ast -> ast @@ -7949,9 +6774,7 @@ external mk_bvredand : context -> ast -> ast (** Summary: \[ [ mk_bvredor c t1 ] \] Take disjunction of bits in vector, return vector of length 1. - The node [t1] must have a bit-vector sort. - def_API('mk_bvredor', AST, (_in(CONTEXT), _in(AST))) *) external mk_bvredor : context -> ast -> ast @@ -7960,9 +6783,7 @@ external mk_bvredor : context -> ast -> ast (** Summary: \[ [ mk_bvand c t1 t2 ] \] Bitwise and. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvand', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvand : context -> ast -> ast -> ast @@ -7971,9 +6792,7 @@ external mk_bvand : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvor c t1 t2 ] \] Bitwise or. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvor', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvor : context -> ast -> ast -> ast @@ -7982,9 +6801,7 @@ external mk_bvor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvxor c t1 t2 ] \] Bitwise exclusive-or. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvxor', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvxor : context -> ast -> ast -> ast @@ -7992,10 +6809,8 @@ external mk_bvxor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvnand c t1 t2 ] \] - Bitwise nand. - + Bitwise nand. The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvnand', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvnand : context -> ast -> ast -> ast @@ -8003,10 +6818,8 @@ external mk_bvnand : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvnor c t1 t2 ] \] - Bitwise nor. - + Bitwise nor. The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvnor', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvnor : context -> ast -> ast -> ast @@ -8014,10 +6827,8 @@ external mk_bvnor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvxnor c t1 t2 ] \] - Bitwise xnor. - + Bitwise xnor. The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvxnor', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvxnor : context -> ast -> ast -> ast @@ -8026,9 +6837,7 @@ external mk_bvxnor : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvneg c t1 ] \] Standard two's complement unary minus. - The node [t1] must have bit-vector sort. - def_API('mk_bvneg', AST, (_in(CONTEXT), _in(AST))) *) external mk_bvneg : context -> ast -> ast @@ -8037,9 +6846,7 @@ external mk_bvneg : context -> ast -> ast (** Summary: \[ [ mk_bvadd c t1 t2 ] \] Standard two's complement addition. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvadd : context -> ast -> ast -> ast @@ -8048,9 +6855,7 @@ external mk_bvadd : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsub c t1 t2 ] \] Standard two's complement subtraction. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsub : context -> ast -> ast -> ast @@ -8059,9 +6864,7 @@ external mk_bvsub : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvmul c t1 t2 ] \] Standard two's complement multiplication. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvmul : context -> ast -> ast -> ast @@ -8069,14 +6872,11 @@ external mk_bvmul : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvudiv c t1 t2 ] \] - Unsigned division. - + Unsigned division. It is defined as the [floor] of {e t1/t2 } if [t2] is different from zero. If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvudiv', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvudiv : context -> ast -> ast -> ast @@ -8085,17 +6885,11 @@ external mk_bvudiv : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsdiv c t1 t2 ] \] Two's complement signed division. - It is defined in the following way: - - The [floor] of {e t1/t2 } if [t2] is different from zero, and {e t1*t2 >= 0 }. - - The [ceiling] of {e t1/t2 } if [t2] is different from zero, and {e t1*t2 < 0 }. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsdiv', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsdiv : context -> ast -> ast -> ast @@ -8104,13 +6898,9 @@ external mk_bvsdiv : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvurem c t1 t2 ] \] Unsigned remainder. - It is defined as {e t1 - (t1 /u t2) * t2 }, where {e /u } represents unsigned int division. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvurem', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvurem : context -> ast -> ast -> ast @@ -8119,16 +6909,11 @@ external mk_bvurem : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsrem c t1 t2 ] \] Two's complement signed remainder (sign follows dividend). - It is defined as {e t1 - (t1 /s t2) * t2 }, where {e /s } represents signed division. The most significant bit (sign) of the result is equal to the most significant bit of [t1]. - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - - {b See also}: {!mk_bvsmod} - def_API('mk_bvsrem', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsrem : context -> ast -> ast -> ast @@ -8137,13 +6922,9 @@ external mk_bvsrem : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsmod c t1 t2 ] \] Two's complement signed remainder (sign follows divisor). - If {e t2 } is zero, then the result is undefined. - The nodes [t1] and [t2] must have the same bit-vector sort. - - {b See also}: {!mk_bvsrem} - def_API('mk_bvsmod', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsmod : context -> ast -> ast -> ast @@ -8152,9 +6933,7 @@ external mk_bvsmod : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvult c t1 t2 ] \] Unsigned less than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvult', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvult : context -> ast -> ast -> ast @@ -8163,17 +6942,14 @@ external mk_bvult : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvslt c t1 t2 ] \] Two's complement signed less than. - It abbreviates: - {v + {v (or (and (= (extract[|m-1|:|m-1|] t1) bit1) (= (extract[|m-1|:|m-1|] t2) bit0)) (and (= (extract[|m-1|:|m-1|] t1) (extract[|m-1|:|m-1|] t2)) (bvult t1 t2))) v} - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvslt', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvslt : context -> ast -> ast -> ast @@ -8182,9 +6958,7 @@ external mk_bvslt : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvule c t1 t2 ] \] Unsigned less than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvule', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvule : context -> ast -> ast -> ast @@ -8193,9 +6967,7 @@ external mk_bvule : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsle c t1 t2 ] \] Two's complement signed less than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsle', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsle : context -> ast -> ast -> ast @@ -8204,9 +6976,7 @@ external mk_bvsle : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvuge c t1 t2 ] \] Unsigned greater than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvuge', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvuge : context -> ast -> ast -> ast @@ -8215,9 +6985,7 @@ external mk_bvuge : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsge c t1 t2 ] \] Two's complement signed greater than or equal to. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsge', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsge : context -> ast -> ast -> ast @@ -8226,9 +6994,7 @@ external mk_bvsge : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvugt c t1 t2 ] \] Unsigned greater than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvugt', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvugt : context -> ast -> ast -> ast @@ -8237,9 +7003,7 @@ external mk_bvugt : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvsgt c t1 t2 ] \] Two's complement signed greater than. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsgt', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsgt : context -> ast -> ast -> ast @@ -8248,12 +7012,9 @@ external mk_bvsgt : context -> ast -> ast -> ast (** Summary: \[ [ mk_concat c t1 t2 ] \] Concatenate the given bit-vectors. - The nodes [t1] and [t2] must have (possibly different) bit-vector sorts - The result is a bit-vector of size {e n1+n2 }, where [n1] ([n2)] is the size of [t1] ([t2)]. - def_API('mk_concat', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_concat : context -> ast -> ast -> ast @@ -8264,9 +7025,7 @@ external mk_concat : context -> ast -> ast -> ast Extract the bits [high] down to [low] from a bitvector of size [m] to yield a new bitvector of size [n], where {e n = high - low + 1 }. - The node [t1] must have a bit-vector sort. - def_API('mk_extract', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in(AST))) *) external mk_extract : context -> int -> int -> ast -> ast @@ -8277,9 +7036,7 @@ external mk_extract : context -> int -> int -> ast -> ast Sign-extend of the given bit-vector to the (signed) equivalent bitvector of size {e m+i }, where [m] is the size of the given bit-vector. - The node [t1] must have a bit-vector sort. - def_API('mk_sign_ext', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_sign_ext : context -> int -> ast -> ast @@ -8287,12 +7044,10 @@ external mk_sign_ext : context -> int -> ast -> ast (** Summary: \[ [ mk_zero_ext c i t1 ] \] - Extend the given bit-vector with zeros to the (unsigned int) equivalent + Extend the given bit-vector with zeros to the (unsigned) equivalent bitvector of size {e m+i }, where [m] is the size of the given bit-vector. - - The node [t1] must have a bit-vector sort. - + The node [t1] must have a bit-vector sort. def_API('mk_zero_ext', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_zero_ext : context -> int -> ast -> ast @@ -8301,9 +7056,7 @@ external mk_zero_ext : context -> int -> ast -> ast (** Summary: \[ [ mk_repeat c i t1 ] \] Repeat the given bit-vector up length {e i }. - - The node [t1] must have a bit-vector sort. - + The node [t1] must have a bit-vector sort. def_API('mk_repeat', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_repeat : context -> int -> ast -> ast @@ -8312,16 +7065,12 @@ external mk_repeat : context -> int -> ast -> ast (** Summary: \[ [ mk_bvshl c t1 t2 ] \] Shift left. - It is equivalent to multiplication by {e 2^x } where [x] is the value of the third argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the + 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 nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvshl', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvshl : context -> ast -> ast -> ast @@ -8330,16 +7079,12 @@ external mk_bvshl : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvlshr c t1 t2 ] \] Logical shift right. - It is equivalent to unsigned int division by {e 2^x } where [x] is the value of the third argument. - - NB. The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the + 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 nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvlshr', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvlshr : context -> ast -> ast -> ast @@ -8348,17 +7093,13 @@ external mk_bvlshr : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvashr c t1 t2 ] \] Arithmetic shift right. - It is like logical shift right except that the most significant bits of the result always copy the most significant bit of the second argument. - - The semantics of shift operations varies between environments. This - definition does not necessarily capture directly the semantics of the + 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 nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvashr', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvashr : context -> ast -> ast -> ast @@ -8367,9 +7108,7 @@ external mk_bvashr : context -> ast -> ast -> ast (** Summary: \[ [ mk_rotate_left c i t1 ] \] Rotate bits of [t1] to the left [i] times. - - The node [t1] must have a bit-vector sort. - + The node [t1] must have a bit-vector sort. def_API('mk_rotate_left', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_rotate_left : context -> int -> ast -> ast @@ -8378,9 +7117,7 @@ external mk_rotate_left : context -> int -> ast -> ast (** Summary: \[ [ mk_rotate_right c i t1 ] \] Rotate bits of [t1] to the right [i] times. - - The node [t1] must have a bit-vector sort. - + The node [t1] must have a bit-vector sort. def_API('mk_rotate_right', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_rotate_right : context -> int -> ast -> ast @@ -8389,9 +7126,7 @@ external mk_rotate_right : context -> int -> ast -> ast (** Summary: \[ [ mk_ext_rotate_left c t1 t2 ] \] Rotate bits of [t1] to the left [t2] times. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_ext_rotate_left', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_ext_rotate_left : context -> ast -> ast -> ast @@ -8400,9 +7135,7 @@ external mk_ext_rotate_left : context -> ast -> ast -> ast (** Summary: \[ [ mk_ext_rotate_right c t1 t2 ] \] Rotate bits of [t1] to the right [t2] times. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_ext_rotate_right', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_ext_rotate_right : context -> ast -> ast -> ast @@ -8411,13 +7144,10 @@ external mk_ext_rotate_right : context -> ast -> ast -> ast (** Summary: \[ [ mk_int2bv c n t1 ] \] Create an [n] bit bit-vector from the integer argument [t1]. - - NB. This function is essentially treated as uninterpreted. + 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 node [t1] must have integer sort. - + The node [t1] must have integer sort. def_API('mk_int2bv', AST, (_in(CONTEXT), _in(UINT), _in(AST))) *) external mk_int2bv : context -> int -> ast -> ast @@ -8426,17 +7156,14 @@ external mk_int2bv : context -> int -> ast -> ast (** Summary: \[ [ mk_bv2int c t1 is_signed ] \] Create an integer from the bit-vector argument [t1]. - If [is_signed] is false, then the bit-vector [t1] is treated as unsigned int. + If [is_signed] is false, then the bit-vector [t1] is treated as unsigned int. So the result is non-negative and in the range {e [0..2^N-1] }, where N are the number of bits in [t1]. If [is_signed] is true, [t1] is treated as a signed bit-vector. - - This function is essentially treated as uninterpreted. + 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 node [t1] must have a bit-vector sort. - + The node [t1] must have a bit-vector sort. def_API('mk_bv2int', AST, (_in(CONTEXT), _in(AST), _in(BOOL))) *) external mk_bv2int : context -> ast -> bool -> ast @@ -8446,9 +7173,7 @@ external mk_bv2int : context -> ast -> bool -> ast Summary: \[ [ mk_bvadd_no_overflow c t1 t2 is_signed ] \] Create a predicate that checks that the bit-wise addition of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) *) external mk_bvadd_no_overflow : context -> ast -> ast -> bool -> ast @@ -8458,9 +7183,7 @@ external mk_bvadd_no_overflow : context -> ast -> ast -> bool -> ast Summary: \[ [ mk_bvadd_no_underflow c t1 t2 ] \] Create a predicate that checks that the bit-wise signed addition of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvadd_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvadd_no_underflow : context -> ast -> ast -> ast @@ -8470,9 +7193,7 @@ external mk_bvadd_no_underflow : context -> ast -> ast -> ast Summary: \[ [ mk_bvsub_no_overflow c t1 t2 ] \] Create a predicate that checks that the bit-wise signed subtraction of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsub_no_overflow : context -> ast -> ast -> ast @@ -8482,9 +7203,7 @@ external mk_bvsub_no_overflow : context -> ast -> ast -> ast Summary: \[ [ mk_bvsub_no_underflow c t1 t2 is_signed ] \] Create a predicate that checks that the bit-wise subtraction of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsub_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) *) external mk_bvsub_no_underflow : context -> ast -> ast -> bool -> ast @@ -8492,11 +7211,9 @@ external mk_bvsub_no_underflow : context -> ast -> ast -> bool -> ast (** Summary: \[ [ mk_bvsdiv_no_overflow c t1 t2 ] \] - Create a predicate that checks that the bit-wise signed division + Create a predicate that checks that the bit-wise signed division of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvsdiv_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvsdiv_no_overflow : context -> ast -> ast -> ast @@ -8504,11 +7221,9 @@ external mk_bvsdiv_no_overflow : context -> ast -> ast -> ast (** Summary: \[ [ mk_bvneg_no_overflow c t1 ] \] - Check that bit-wise negation does not overflow when + Check that bit-wise negation does not overflow when [t1] is interpreted as a signed bit-vector. - The node [t1] must have bit-vector sort. - def_API('mk_bvneg_no_overflow', AST, (_in(CONTEXT), _in(AST))) *) external mk_bvneg_no_overflow : context -> ast -> ast @@ -8518,9 +7233,7 @@ external mk_bvneg_no_overflow : context -> ast -> ast Summary: \[ [ mk_bvmul_no_overflow c t1 t2 is_signed ] \] Create a predicate that checks that the bit-wise multiplication of [t1] and [t2] does not overflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul_no_overflow', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(BOOL))) *) external mk_bvmul_no_overflow : context -> ast -> ast -> bool -> ast @@ -8530,9 +7243,7 @@ external mk_bvmul_no_overflow : context -> ast -> ast -> bool -> ast Summary: \[ [ mk_bvmul_no_underflow c t1 t2 ] \] Create a predicate that checks that the bit-wise signed multiplication of [t1] and [t2] does not underflow. - The nodes [t1] and [t2] must have the same bit-vector sort. - def_API('mk_bvmul_no_underflow', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_bvmul_no_underflow : context -> ast -> ast -> ast @@ -8544,15 +7255,12 @@ external mk_bvmul_no_underflow : context -> ast -> ast -> ast (** Summary: \[ [ mk_select c a i ] \] Array read. - The argument [a] is the array and [i] is the index of the array that gets read. - - The node [a] must have an array sort {e [domain -> range] }, + The argument [a] is the array and [i] is the index of the array that gets read. + The node [a] must have an array sort {e [domain -> range] }, and [i] must have the sort [domain]. The sort of the result is [range]. - - {b See also}: {!mk_array_sort} - {b See also}: {!mk_store} - def_API('mk_select', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_select : context -> ast -> ast -> ast @@ -8561,18 +7269,15 @@ external mk_select : context -> ast -> ast -> ast (** Summary: \[ [ mk_store c a i v ] \] Array update. - The node [a] must have an array sort {e [domain -> range] }, [i] must have sort [domain], [v] must have sort range. The sort of the result is {e [domain -> range] }. The semantics of this function is given by the theory of arrays described in the SMT-LIB - standard. See http: + standard. See http://smtlib.org for more details. The result of this function is an array that is equal to [a] (with respect to [select)] - on all indices except for [i], where it maps to [v] (and the [select] of [a] with + on all indices except for [i], where it maps to [v] (and the [select] of [a] with respect to [i] may be a different value). - - {b See also}: {!mk_array_sort} - {b See also}: {!mk_select} - def_API('mk_store', AST, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) *) external mk_store : context -> ast -> ast -> ast -> ast @@ -8580,14 +7285,11 @@ external mk_store : context -> ast -> ast -> ast -> ast (** Summary: Create the constant array. - - The resulting term is an array, such that a [select] on an arbitrary index + The resulting term is an array, such that a [select] on an arbitrary index produces the value [v]. - @param c logical context. @param domain domain sort for the array. @param v value that the array maps to. - def_API('mk_const_array', AST, (_in(CONTEXT), _in(SORT), _in(AST))) *) external mk_const_array : context -> sort -> ast -> ast @@ -8596,15 +7298,12 @@ external mk_const_array : context -> sort -> ast -> ast (** Summary: \[ [ mk_map f n args ] \] map f on the the argument arrays. - The [n] nodes [args] must be of array sorts {e [domain_i -> range_i] }. - The function declaration [f] must have type {e range_1 .. range_n -> range }. + The function declaration [f] must have type {e range_1 .. range_n -> range }. [v] must have sort range. The sort of the result is {e [domain_i -> range] }. - - {b See also}: {!mk_array_sort} - {b See also}: {!mk_store} - {b See also}: {!mk_select} - def_API('mk_map', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT), _in_array(2, AST))) *) external mk_map : context -> func_decl -> int -> ast -> ast @@ -8612,12 +7311,10 @@ external mk_map : context -> func_decl -> int -> ast -> ast (** Summary: Access the array default value. - Produces the default range value, for arrays that can be represented as + Produces the default range value, for arrays that can be represented as finite maps with a default range value. - @param c logical context. @param array array value whose default range value is accessed. - def_API('mk_array_default', AST, (_in(CONTEXT), _in(AST))) *) external mk_array_default : context -> ast -> ast @@ -8628,7 +7325,6 @@ external mk_array_default : context -> ast -> ast *) (** Summary: Create Set type. - def_API('mk_set_sort', SORT, (_in(CONTEXT), _in(SORT))) *) external mk_set_sort : context -> sort -> sort @@ -8636,7 +7332,6 @@ external mk_set_sort : context -> sort -> sort (** Summary: Create the empty set. - def_API('mk_empty_set', AST, (_in(CONTEXT), _in(SORT))) *) external mk_empty_set : context -> sort -> ast @@ -8644,7 +7339,6 @@ external mk_empty_set : context -> sort -> ast (** Summary: Create the full set. - def_API('mk_full_set', AST, (_in(CONTEXT), _in(SORT))) *) external mk_full_set : context -> sort -> ast @@ -8652,9 +7346,7 @@ external mk_full_set : context -> sort -> ast (** Summary: Add an element to a set. - The first argument must be a set, the second an element. - def_API('mk_set_add', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_set_add : context -> ast -> ast -> ast @@ -8662,9 +7354,7 @@ external mk_set_add : context -> ast -> ast -> ast (** Summary: Remove an element to a set. - The first argument must be a set, the second an element. - def_API('mk_set_del', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_set_del : context -> ast -> ast -> ast @@ -8672,7 +7362,6 @@ external mk_set_del : context -> ast -> ast -> ast (** Summary: Take the union of a list of sets. - def_API('mk_set_union', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_set_union : context -> ast array -> ast @@ -8680,7 +7369,6 @@ external mk_set_union : context -> ast array -> ast (** Summary: Take the intersection of a list of sets. - def_API('mk_set_intersect', AST, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_set_intersect : context -> ast array -> ast @@ -8688,7 +7376,6 @@ external mk_set_intersect : context -> ast array -> ast (** Summary: Take the set difference between two sets. - def_API('mk_set_difference', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_set_difference : context -> ast -> ast -> ast @@ -8696,7 +7383,6 @@ external mk_set_difference : context -> ast -> ast -> ast (** Summary: Take the complement of a set. - def_API('mk_set_complement', AST, (_in(CONTEXT), _in(AST))) *) external mk_set_complement : context -> ast -> ast @@ -8704,9 +7390,7 @@ external mk_set_complement : context -> ast -> ast (** Summary: Check for set membership. - The first argument should be an element type of the set. - def_API('mk_set_member', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_set_member : context -> ast -> ast -> ast @@ -8714,7 +7398,6 @@ external mk_set_member : context -> ast -> ast -> ast (** Summary: Check for subsetness of sets. - def_API('mk_set_subset', AST, (_in(CONTEXT), _in(AST), _in(AST))) *) external mk_set_subset : context -> ast -> ast -> ast @@ -8724,18 +7407,14 @@ external mk_set_subset : context -> ast -> ast -> ast {2 {L Numerals}} *) (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** - Summary: Create a numeral of a given sort. - + Summary: Create a numeral of a given sort. @param c logical context. @param numeral A string representing the numeral value in decimal notation. If the given sort is a real, then the numeral can be a rational, that is, a string of the form {e [num]* / [num]* }. - @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, finite-domain, or bit-vectors of arbitrary size. - + @param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, finite-domain, or bit-vectors of arbitrary size. - {b See also}: {!mk_int} - - def_API('mk_numeral', AST, (_in(CONTEXT), _in(STRING), _in(SORT))) *) external mk_numeral : context -> string -> sort -> ast @@ -8743,43 +7422,32 @@ external mk_numeral : context -> string -> sort -> ast (** Summary: Create a real from a fraction. - @param c logical context. @param num numerator of rational. @param den denomerator of rational. - - {b Precondition}: den != 0 - - {b See also}: {!mk_numeral} - {b See also}: {!mk_int} - - def_API('mk_real', AST, (_in(CONTEXT), _in(INT), _in(INT))) *) external mk_real : context -> int -> int -> ast = "camlidl_z3V3_Z3_mk_real" (** - Summary: Create a numeral of an int, bit-vector, or finite-domain sort. - + Summary: Create a numeral of an int, bit-vector, or finite-domain sort. This function can be use to create numerals that fit in a machine integer. It is slightly faster than {!mk_numeral} since it is not necessary to parse a string. - - {b See also}: {!mk_numeral} - def_API('mk_int', AST, (_in(CONTEXT), _in(INT), _in(SORT))) *) external mk_int : context -> int -> sort -> ast = "camlidl_z3V3_Z3_mk_int" (** - Summary: Create a numeral of a int, bit-vector, or finite-domain sort. - + Summary: Create a numeral of a int, bit-vector, or finite-domain sort. This function can be use to create numerals that fit in a machine long long integer. It is slightly faster than {!mk_numeral} since it is not necessary to parse a string. - - {b See also}: {!mk_numeral} - def_API('mk_int64', AST, (_in(CONTEXT), _in(INT64), _in(SORT))) *) external mk_int64 : context -> int64 -> sort -> ast @@ -8790,22 +7458,17 @@ external mk_int64 : context -> int64 -> sort -> ast *) (** Summary: Create a pattern for quantifier instantiation. - Z3 uses pattern matching to instantiate quantifiers. If a pattern is not provided for a quantifier, then Z3 will automatically compute a set of patterns for it. However, for optimal performance, the user should provide the patterns. - Patterns comprise a list of terms. The list should be - non-empty. If the list comprises of more than one term, it is + non-empty. If the list comprises of more than one term, it is a called a multi-pattern. - In general, one can pass in a list of (multi-)patterns in the quantifier constructor. - - {b See also}: {!mk_forall} - {b See also}: {!mk_exists} - def_API('mk_pattern', PATTERN, (_in(CONTEXT), _in(UINT), _in_array(1, AST))) *) external mk_pattern : context -> ast array -> pattern @@ -8813,12 +7476,10 @@ external mk_pattern : context -> ast array -> pattern (** Summary: Create a bound variable. - Bound variables are indexed by de-Bruijn indices. It is perhaps easiest to explain the meaning of de-Bruijn indices by indicating the compilation process from non-de-Bruijn formulas to de-Bruijn format. - - {v + {v 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 @@ -8826,18 +7487,14 @@ external mk_pattern : context -> ast array -> pattern 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)) v} - The last line is significant: the index of a bound variable is different depending on the scope in which it appears. The deeper x appears, the higher is its index. - @param c logical context @param index de-Bruijn index @param ty sort of the bound variable - - {b See also}: {!mk_forall} - {b See also}: {!mk_exists} - def_API('mk_bound', AST, (_in(CONTEXT), _in(UINT), _in(SORT))) *) external mk_bound : context -> int -> sort -> ast @@ -8846,21 +7503,17 @@ external mk_bound : context -> int -> sort -> ast (** Summary: Create a forall formula. It takes an expression [body] that contains bound variables of the same sorts as the sorts listed in the array [sorts]. The bound variables are de-Bruijn indices created - using {!mk_bound}. The array [decl_names] contains the names that the quantified formula uses for the + using {!mk_bound}. The array [decl_names] contains the names that the quantified formula uses for the bound variables. Z3 applies the convention that the last element in the [decl_names] and [sorts] array refers to the variable with index 0, the second to last element of [decl_names] and [sorts] refers to the variable with index 1, etc. - - [mk_forall c w p t n b] creates a forall formula, where [w] is the weight, [p] is an array of patterns, [t] is an array with the sorts of the bound variables, [n] is an array with the 'names' of the bound variables, and [b] is the body of the quantifier. Quantifiers are associated with weights indicating the importance of using the quantifier during - instantiation. - - + instantiation. @param c logical context. @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. @param num_patterns number of patterns. @@ -8869,33 +7522,28 @@ external mk_bound : context -> int -> sort -> ast @param sorts the sorts of the bound variables. @param decl_names names of the bound variables @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_bound} - {b See also}: {!mk_exists} - def_API('mk_forall', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, PATTERN), _in(UINT), _in_array(4, SORT), _in_array(4, SYMBOL), _in(AST))) *) external mk_forall : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_forall_bytecode" "camlidl_z3V3_Z3_mk_forall" + = "camlidl_z3V3_Z3_mk_forall_bytecode" "camlidl_z3V3_Z3_mk_forall" (** Summary: Create an exists formula. Similar to {!mk_forall}. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_bound} - {b See also}: {!mk_forall} - {b See also}: {!mk_quantifier} - def_API('mk_exists', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, PATTERN), _in(UINT), _in_array(4, SORT), _in_array(4, SYMBOL), _in(AST))) *) external mk_exists : context -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_exists_bytecode" "camlidl_z3V3_Z3_mk_exists" + = "camlidl_z3V3_Z3_mk_exists_bytecode" "camlidl_z3V3_Z3_mk_exists" (** - Summary: Create a quantifier - universal or existential, with pattern hints. + Summary: Create a quantifier - universal or existential, with pattern hints. See the documentation for {!mk_forall} for an explanation of the parameters. - @param c logical context. @param is_forall flag to indicate if this is a universal or existential quantifier. @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. @@ -8905,20 +7553,17 @@ external mk_exists : context -> int -> pattern array -> sort array -> symbol arr @param sorts array of sorts of the bound variables. @param decl_names names of the bound variables. @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_bound} - {b See also}: {!mk_forall} - {b See also}: {!mk_exists} - def_API('mk_quantifier', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(UINT), _in_array(3, PATTERN), _in(UINT), _in_array(5, SORT), _in_array(5, SYMBOL), _in(AST))) *) external mk_quantifier : context -> bool -> int -> pattern array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_bytecode" "camlidl_z3V3_Z3_mk_quantifier" + = "camlidl_z3V3_Z3_mk_quantifier_bytecode" "camlidl_z3V3_Z3_mk_quantifier" (** Summary: Create a quantifier - universal or existential, with pattern hints, no patterns, and attributes - @param c logical context. @param is_forall flag to indicate if this is a universal or existential quantifier. @param quantifier_id identifier to identify quantifier @@ -8932,33 +7577,28 @@ external mk_quantifier : context -> bool -> int -> pattern array -> sort array - @param sorts array of sorts of the bound variables. @param decl_names names of the bound variables. @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_bound} - {b See also}: {!mk_forall} - {b See also}: {!mk_exists} - def_API('mk_quantifier_ex', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(5, PATTERN), _in(UINT), _in_array(7, AST), _in(UINT), _in_array(9, SORT), _in_array(9, SYMBOL), _in(AST))) *) external mk_quantifier_ex : context -> bool -> int -> symbol -> symbol -> pattern array -> ast array -> sort array -> symbol array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_ex" + = "camlidl_z3V3_Z3_mk_quantifier_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_ex" (** Summary: Create a universal quantifier using a list of constants that will form the set of bound variables. - @param c logical context. - @param weight quantifiers are associated with weights indicating the importance of using + @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. @param num_bound number of constants to be abstracted into bound variables. @param bound array of constants to be abstracted into bound variables. @param num_patterns number of patterns. @param patterns array containing the patterns created using {!mk_pattern}. @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_exists_const} - def_API('mk_forall_const', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, APP), _in(UINT), _in_array(4, PATTERN), _in(AST))) *) external mk_forall_const : context -> int -> app array -> pattern array -> ast -> ast @@ -8966,61 +7606,54 @@ external mk_forall_const : context -> int -> app array -> pattern array -> ast - (** Summary: Similar to {!mk_forall_const}. - Summary: Create an existential quantifier using a list of constants that will form the set of bound variables. - @param c logical context. - @param weight quantifiers are associated with weights indicating the importance of using + @param weight quantifiers are associated with weights indicating the importance of using the quantifier during instantiation. By default, pass the weight 0. @param num_bound number of constants to be abstracted into bound variables. @param bound array of constants to be abstracted into bound variables. @param num_patterns number of patterns. @param patterns array containing the patterns created using {!mk_pattern}. @param body the body of the quantifier. - - {b See also}: {!mk_pattern} - {b See also}: {!mk_forall_const} - def_API('mk_exists_const', AST, (_in(CONTEXT), _in(UINT), _in(UINT), _in_array(2, APP), _in(UINT), _in_array(4, PATTERN), _in(AST))) *) external mk_exists_const : context -> int -> app array -> pattern array -> ast -> ast = "camlidl_z3V3_Z3_mk_exists_const" (** - Summary: Create a universal or existential + Summary: Create a universal or existential quantifier using a list of constants that will form the set of bound variables. - def_API('mk_quantifier_const', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(UINT), _in_array(3, APP), _in(UINT), _in_array(5, PATTERN), _in(AST))) *) external mk_quantifier_const : context -> bool -> int -> app array -> pattern array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_const_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const" + = "camlidl_z3V3_Z3_mk_quantifier_const_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const" (** - Summary: Create a universal or existential + Summary: Create a universal or existential quantifier using a list of constants that will form the set of bound variables. - def_API('mk_quantifier_const_ex', AST, (_in(CONTEXT), _in(BOOL), _in(UINT), _in(SYMBOL), _in(SYMBOL), _in(UINT), _in_array(5, APP), _in(UINT), _in_array(7, PATTERN), _in(UINT), _in_array(9, AST), _in(AST))) *) external mk_quantifier_const_ex : context -> bool -> int -> symbol -> symbol -> app array -> pattern array -> ast array -> ast -> ast - = "camlidl_z3_Z3_mk_quantifier_const_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const_ex" + = "camlidl_z3V3_Z3_mk_quantifier_const_ex_bytecode" "camlidl_z3V3_Z3_mk_quantifier_const_ex" (** {2 {L Accessors}} *) (** - {3 {L Symbols}} + {3 {L Symbols}} *) (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** Summary: Return [INT_SYMBOL] if the symbol was constructed using {!mk_int_symbol}, and [STRING_SYMBOL] if the symbol was constructed using {!mk_string_symbol}. - def_API('get_symbol_kind', UINT, (_in(CONTEXT), _in(SYMBOL))) *) external get_symbol_kind : context -> symbol -> symbol_kind @@ -9028,12 +7661,9 @@ external get_symbol_kind : context -> symbol -> symbol_kind (** Summary: \[ [ get_symbol_int c s ] \] - Return the symbol int value. - + Return the symbol int value. - {b Precondition}: get_symbol_kind s == INT_SYMBOL - - {b See also}: {!mk_int_symbol} - def_API('get_symbol_int', INT, (_in(CONTEXT), _in(SYMBOL))) *) external get_symbol_int : context -> symbol -> int @@ -9041,27 +7671,19 @@ external get_symbol_int : context -> symbol -> int (** Summary: \[ [ get_symbol_string c s ] \] - Return the symbol name. - + Return the symbol name. - {b Precondition}: get_symbol_string s == STRING_SYMBOL - - - - - - {b See also}: {!mk_string_symbol} - def_API('get_symbol_string', STRING, (_in(CONTEXT), _in(SYMBOL))) *) external get_symbol_string : context -> symbol -> string = "camlidl_z3V3_Z3_get_symbol_string" (** - {3 {L Sorts}} + {3 {L Sorts}} *) (** - Summary: Return the sort name as a symbol. - + Summary: Return the sort name as a symbol. def_API('get_sort_name', SYMBOL, (_in(CONTEXT), _in(SORT))) *) external get_sort_name : context -> sort -> symbol @@ -9069,20 +7691,18 @@ external get_sort_name : context -> sort -> symbol (** Summary: Return a unique identifier for [s]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - + - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. def_API('get_sort_id', UINT, (_in(CONTEXT), _in(SORT))) *) external get_sort_id : context -> sort -> int = "camlidl_z3V3_Z3_get_sort_id" (** - {4 {L Redundant low-level API}} + {4 {L Redundant low-level API}} *) (** - Summary: Convert a [sort] into [ast]. - - {b Remarks}: [sort_to_ast c s] can be replaced by [(s :> ast)]. - + Summary: Convert a [sort] into [ast]. + - {b Remarks}: [sort_to_ast c s] can be replaced by [(s :> ast)]. def_API('sort_to_ast', AST, (_in(CONTEXT), _in(SORT))) *) external sort_to_ast : context -> sort -> ast @@ -9090,8 +7710,7 @@ external sort_to_ast : context -> sort -> ast (** Summary: compare sorts. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. def_API('is_eq_sort', BOOL, (_in(CONTEXT), _in(SORT), _in(SORT))) *) external is_eq_sort : context -> sort -> sort -> bool @@ -9099,9 +7718,7 @@ external is_eq_sort : context -> sort -> sort -> bool (** Summary: Return the sort kind (e.g., array, tuple, int, bool, etc). - - {b See also}: {!sort_kind} - def_API('get_sort_kind', UINT, (_in(CONTEXT), _in(SORT))) *) external get_sort_kind : context -> sort -> sort_kind @@ -9109,23 +7726,18 @@ external get_sort_kind : context -> sort -> sort_kind (** Summary: \[ [ get_bv_sort_size c t ] \] - Return the size of the given bit-vector sort. - + Return the size of the given bit-vector sort. - {b Precondition}: get_sort_kind c t == BV_SORT - - {b See also}: {!mk_bv_sort} - {b See also}: {!get_sort_kind} - def_API('get_bv_sort_size', UINT, (_in(CONTEXT), _in(SORT))) *) external get_bv_sort_size : context -> sort -> int = "camlidl_z3V3_Z3_get_bv_sort_size" (** - - Summary: Return the size of the sort in [r]. Return [None] if the call failed. + Summary: Return the size of the sort in [r]. Return [None] if the call failed. That is, get_sort_kind(s) == FINITE_DOMAIN_SORT - def_API('get_finite_domain_sort_size', BOOL, (_in(CONTEXT), _in(SORT), _out(UINT64))) *) external get_finite_domain_sort_size : context -> sort -> int64 option @@ -9134,26 +7746,20 @@ external get_finite_domain_sort_size : context -> sort -> int64 option (** Summary: \[ [ get_array_sort_domain c t ] \] Return the domain of the given array sort. - - {b Precondition}: get_sort_kind c t == ARRAY_SORT - - {b See also}: {!mk_array_sort} - {b See also}: {!get_sort_kind} - def_API('get_array_sort_domain', SORT, (_in(CONTEXT), _in(SORT))) *) external get_array_sort_domain : context -> sort -> sort = "camlidl_z3V3_Z3_get_array_sort_domain" (** - Summary: \[ [ get_array_sort_range c t ] \] - Return the range of the given array sort. - + Summary: \[ [ get_array_sort_range c t ] \] + Return the range of the given array sort. - {b Precondition}: get_sort_kind c t == ARRAY_SORT - - {b See also}: {!mk_array_sort} - {b See also}: {!get_sort_kind} - def_API('get_array_sort_range', SORT, (_in(CONTEXT), _in(SORT))) *) external get_array_sort_range : context -> sort -> sort @@ -9162,13 +7768,10 @@ external get_array_sort_range : context -> sort -> sort (** Summary: \[ [ get_tuple_sort_mk_decl c t ] \] Return the constructor declaration of the given tuple - sort. - + sort. - {b Precondition}: get_sort_kind c t == DATATYPE_SORT - - {b See also}: {!mk_tuple_sort} - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_mk_decl', FUNC_DECL, (_in(CONTEXT), _in(SORT))) *) external get_tuple_sort_mk_decl : context -> sort -> func_decl @@ -9176,13 +7779,10 @@ external get_tuple_sort_mk_decl : context -> sort -> func_decl (** Summary: \[ [ get_tuple_sort_num_fields c t ] \] - Return the number of fields of the given tuple sort. - + Return the number of fields of the given tuple sort. - {b Precondition}: get_sort_kind c t == DATATYPE_SORT - - {b See also}: {!mk_tuple_sort} - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_num_fields', UINT, (_in(CONTEXT), _in(SORT))) *) external get_tuple_sort_num_fields : context -> sort -> int @@ -9191,14 +7791,11 @@ external get_tuple_sort_num_fields : context -> sort -> int (** Summary: \[ [ get_tuple_sort_field_decl c t i ] \] Return the i-th field declaration (i.e., projection function declaration) - of the given tuple sort. - + of the given tuple sort. - {b Precondition}: get_sort_kind t == DATATYPE_SORT - {b Precondition}: i < get_tuple_sort_num_fields c t - - {b See also}: {!mk_tuple_sort} - {b See also}: {!get_sort_kind} - def_API('get_tuple_sort_field_decl', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) *) external get_tuple_sort_field_decl : context -> sort -> int -> func_decl @@ -9206,13 +7803,10 @@ external get_tuple_sort_field_decl : context -> sort -> int -> func_decl (** Summary: Return number of constructors for datatype. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - - {b See also}: {!get_datatype_sort_constructor} - {b See also}: {!get_datatype_sort_recognizer} - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_num_constructors', UINT, (_in(CONTEXT), _in(SORT))) *) external get_datatype_sort_num_constructors : context -> sort -> int @@ -9220,14 +7814,11 @@ external get_datatype_sort_num_constructors : context -> sort -> int (** Summary: Return idx'th constructor. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - {b Precondition}: idx < get_datatype_sort_num_constructors c t - - {b See also}: {!get_datatype_sort_num_constructors} - {b See also}: {!get_datatype_sort_recognizer} - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_constructor', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) *) external get_datatype_sort_constructor : context -> sort -> int -> func_decl @@ -9235,14 +7826,11 @@ external get_datatype_sort_constructor : context -> sort -> int -> func_decl (** Summary: Return idx'th recognizer. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - {b Precondition}: idx < get_datatype_sort_num_constructors c t - - {b See also}: {!get_datatype_sort_num_constructors} - {b See also}: {!get_datatype_sort_constructor} - {b See also}: {!get_datatype_sort_constructor_accessor} - def_API('get_datatype_sort_recognizer', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT))) *) external get_datatype_sort_recognizer : context -> sort -> int -> func_decl @@ -9250,15 +7838,12 @@ external get_datatype_sort_recognizer : context -> sort -> int -> func_decl (** Summary: Return idx_a'th accessor for the idx_c'th constructor. - - {b Precondition}: get_sort_kind t == DATATYPE_SORT - {b Precondition}: idx_c < get_datatype_sort_num_constructors c t - {b Precondition}: idx_a < get_domain_size c get_datatype_sort_constructor c idx_c - - {b See also}: {!get_datatype_sort_num_constructors} - {b See also}: {!get_datatype_sort_constructor} - {b See also}: {!get_datatype_sort_recognizer} - def_API('get_datatype_sort_constructor_accessor', FUNC_DECL, (_in(CONTEXT), _in(SORT), _in(UINT), _in(UINT))) *) external get_datatype_sort_constructor_accessor : context -> sort -> int -> int -> func_decl @@ -9266,11 +7851,8 @@ external get_datatype_sort_constructor_accessor : context -> sort -> int -> int (** Summary: Return arity of relation. - - {b Precondition}: get_sort_kind s == RELATION_SORT - - {b See also}: {!get_relation_column} - def_API('get_relation_arity', UINT, (_in(CONTEXT), _in(SORT))) *) external get_relation_arity : context -> sort -> int @@ -9278,24 +7860,20 @@ external get_relation_arity : context -> sort -> int (** Summary: Return sort at i'th column of relation sort. - - {b Precondition}: get_sort_kind c s == RELATION_SORT - {b Precondition}: col < get_relation_arity c s - - {b See also}: {!get_relation_arity} - def_API('get_relation_column', SORT, (_in(CONTEXT), _in(SORT), _in(UINT))) *) external get_relation_column : context -> sort -> int -> sort = "camlidl_z3V3_Z3_get_relation_column" (** - {3 {L Function Declarations}} + {3 {L Function Declarations}} *) (** - Summary: Convert a [func_decl] into [ast]. - - {b Remarks}: [func_decl_to_ast c f] can be replaced by [(f :> ast)]. - + Summary: Convert a [func_decl] into [ast]. + - {b Remarks}: [func_decl_to_ast c f] can be replaced by [(f :> ast)]. def_API('func_decl_to_ast', AST, (_in(CONTEXT), _in(FUNC_DECL))) *) external func_decl_to_ast : context -> func_decl -> ast @@ -9303,8 +7881,7 @@ external func_decl_to_ast : context -> func_decl -> ast (** Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. def_API('is_eq_func_decl', BOOL, (_in(CONTEXT), _in(FUNC_DECL), _in(FUNC_DECL))) *) external is_eq_func_decl : context -> func_decl -> func_decl -> bool @@ -9312,16 +7889,14 @@ external is_eq_func_decl : context -> func_decl -> func_decl -> bool (** Summary: Return a unique identifier for [f]. - - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. - + - {b Remarks}: Implicitly used by [Pervasives.( = )] and [Pervasives.compare]. def_API('get_func_decl_id', UINT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_func_decl_id : context -> func_decl -> int = "camlidl_z3V3_Z3_get_func_decl_id" (** - Summary: Return the constant declaration name as a symbol. - + Summary: Return the constant declaration name as a symbol. def_API('get_decl_name', SYMBOL, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_decl_name : context -> func_decl -> symbol @@ -9329,7 +7904,6 @@ external get_decl_name : context -> func_decl -> symbol (** Summary: Return declaration kind corresponding to declaration. - def_API('get_decl_kind', UINT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_decl_kind : context -> func_decl -> decl_kind @@ -9337,9 +7911,7 @@ external get_decl_kind : context -> func_decl -> decl_kind (** Summary: Return the number of parameters of the given declaration. - - {b See also}: {!get_arity} - def_API('get_domain_size', UINT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_domain_size : context -> func_decl -> int @@ -9347,9 +7919,7 @@ external get_domain_size : context -> func_decl -> int (** Summary: Alias for [get_domain_size]. - - {b See also}: {!get_domain_size} - def_API('get_arity', UINT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_arity : context -> func_decl -> int @@ -9358,11 +7928,8 @@ external get_arity : context -> func_decl -> int (** Summary: \[ [ get_domain c d i ] \] Return the sort of the i-th parameter of the given function declaration. - - {b Precondition}: i < get_domain_size d - - {b See also}: {!get_domain_size} - def_API('get_domain', SORT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_domain : context -> func_decl -> int -> sort @@ -9370,11 +7937,9 @@ external get_domain : context -> func_decl -> int -> sort (** Summary: \[ [ get_range c d ] \] - Return the range of the given declaration. - + Return the range of the given declaration. If [d] is a constant (i.e., has zero arguments), then this function returns the sort of the constant. - def_API('get_range', SORT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_range : context -> func_decl -> sort @@ -9382,7 +7947,6 @@ external get_range : context -> func_decl -> sort (** Summary: Return the number of parameters associated with a declaration. - def_API('get_decl_num_parameters', UINT, (_in(CONTEXT), _in(FUNC_DECL))) *) external get_decl_num_parameters : context -> func_decl -> int @@ -9390,11 +7954,9 @@ external get_decl_num_parameters : context -> func_decl -> int (** Summary: Return the parameter type associated with a declaration. - @param c the context @param d the function declaration @param idx is the index of the named parameter it should be between 0 and the number of parameters. - def_API('get_decl_parameter_kind', UINT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_parameter_kind : context -> func_decl -> int -> parameter_kind @@ -9402,9 +7964,7 @@ external get_decl_parameter_kind : context -> func_decl -> int -> parameter_kind (** Summary: Return the integer value associated with an integer parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_INT - def_API('get_decl_int_parameter', INT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_int_parameter : context -> func_decl -> int -> int @@ -9412,9 +7972,7 @@ external get_decl_int_parameter : context -> func_decl -> int -> int (** Summary: Return the double value associated with an double parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_DOUBLE - def_API('get_decl_double_parameter', DOUBLE, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_double_parameter : context -> func_decl -> int -> float @@ -9422,9 +7980,7 @@ external get_decl_double_parameter : context -> func_decl -> int -> float (** Summary: Return the double value associated with an double parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_SYMBOL - def_API('get_decl_symbol_parameter', SYMBOL, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_symbol_parameter : context -> func_decl -> int -> symbol @@ -9432,9 +7988,7 @@ external get_decl_symbol_parameter : context -> func_decl -> int -> symbol (** Summary: Return the sort value associated with a sort parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_SORT - def_API('get_decl_sort_parameter', SORT, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_sort_parameter : context -> func_decl -> int -> sort @@ -9442,9 +7996,7 @@ external get_decl_sort_parameter : context -> func_decl -> int -> sort (** Summary: Return the expresson value associated with an expression parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_AST - def_API('get_decl_ast_parameter', AST, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_ast_parameter : context -> func_decl -> int -> ast @@ -9452,9 +8004,7 @@ external get_decl_ast_parameter : context -> func_decl -> int -> ast (** Summary: Return the expresson value associated with an expression parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_FUNC_DECL - def_API('get_decl_func_decl_parameter', FUNC_DECL, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_func_decl_parameter : context -> func_decl -> int -> func_decl @@ -9462,21 +8012,18 @@ external get_decl_func_decl_parameter : context -> func_decl -> int -> func_decl (** Summary: Return the rational value, as a string, associated with a rational parameter. - - {b Precondition}: get_decl_parameter_kind c d idx == PARAMETER_RATIONAL - def_API('get_decl_rational_parameter', STRING, (_in(CONTEXT), _in(FUNC_DECL), _in(UINT))) *) external get_decl_rational_parameter : context -> func_decl -> int -> string = "camlidl_z3V3_Z3_get_decl_rational_parameter" (** - {3 {L Applications}} + {3 {L Applications}} *) (** - Summary: Convert a [app] into [ast]. - - {b Remarks}: [app_to_ast c a] can be replaced by [(a :> ast)]. - + Summary: Convert a [app] into [ast]. + - {b Remarks}: [app_to_ast c a] can be replaced by [(a :> ast)]. def_API('app_to_ast', AST, (_in(CONTEXT), _in(APP))) *) external app_to_ast : context -> app -> ast @@ -9484,7 +8031,6 @@ external app_to_ast : context -> app -> ast (** Summary: Return the declaration of a constant or function application. - def_API('get_app_decl', FUNC_DECL, (_in(CONTEXT), _in(APP))) *) external get_app_decl : context -> app -> func_decl @@ -9494,7 +8040,6 @@ external get_app_decl : context -> app -> func_decl Summary: \[ [ get_app_num_args c a ] \] Return the number of argument of an application. If [t] is an constant, then the number of arguments is 0. - def_API('get_app_num_args', UINT, (_in(CONTEXT), _in(APP))) *) external get_app_num_args : context -> app -> int @@ -9503,21 +8048,18 @@ external get_app_num_args : context -> app -> int (** Summary: \[ [ get_app_arg c a i ] \] Return the i-th argument of the given application. - - {b Precondition}: i < get_num_args c a - def_API('get_app_arg', AST, (_in(CONTEXT), _in(APP), _in(UINT))) *) external get_app_arg : context -> app -> int -> ast = "camlidl_z3V3_Z3_get_app_arg" (** - {3 {L Terms}} + {3 {L Terms}} *) (** Summary: compare terms. - - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. - + - {b Remarks}: [Pervasives.( = )] or [Pervasives.compare] can also be used. def_API('is_eq_ast', BOOL, (_in(CONTEXT), _in(AST), _in(AST))) *) external is_eq_ast : context -> ast -> ast -> bool @@ -9525,8 +8067,7 @@ external is_eq_ast : context -> ast -> ast -> bool (** Summary: Return a unique identifier for [t]. - - {b Remarks}: Implicitly used by [Pervasives.compare] for values of type [ast], [app], [sort], [func_decl], and [pattern]. - + - {b Remarks}: Implicitly used by [Pervasives.compare] for values of type [ast], [app], [sort], [func_decl], and [pattern]. def_API('get_ast_id', UINT, (_in(CONTEXT), _in(AST))) *) external get_ast_id : context -> ast -> int @@ -9534,8 +8075,7 @@ external get_ast_id : context -> ast -> int (** Summary: Return a hash code for the given AST. - - {b Remarks}: Implicitly used by [Hashtbl.hash] for values of type [ast], [app], [sort], [func_decl], and [pattern]. - + - {b Remarks}: Implicitly used by [Hashtbl.hash] for values of type [ast], [app], [sort], [func_decl], and [pattern]. def_API('get_ast_hash', UINT, (_in(CONTEXT), _in(AST))) *) external get_ast_hash : context -> ast -> int @@ -9543,9 +8083,7 @@ external get_ast_hash : context -> ast -> int (** Summary: Return the sort of an AST node. - The AST node must be a constant, application, numeral, bound variable, or quantifier. - def_API('get_sort', SORT, (_in(CONTEXT), _in(AST))) *) external get_sort : context -> ast -> sort @@ -9553,7 +8091,6 @@ external get_sort : context -> ast -> sort (** Summary: Return true if the given expression [t] is well sorted. - def_API('is_well_sorted', BOOL, (_in(CONTEXT), _in(AST))) *) external is_well_sorted : context -> ast -> bool @@ -9561,7 +8098,6 @@ external is_well_sorted : context -> ast -> bool (** Summary: Return L_TRUE if [a] is true, L_FALSE if it is false, and L_UNDEF otherwise. - def_API('get_bool_value', UINT, (_in(CONTEXT), _in(AST))) *) external get_bool_value : context -> ast -> lbool @@ -9569,14 +8105,13 @@ external get_bool_value : context -> ast -> lbool (** Summary: Return the kind of the given AST. - def_API('get_ast_kind', UINT, (_in(CONTEXT), _in(AST))) *) external get_ast_kind : context -> ast -> ast_kind = "camlidl_z3V3_Z3_get_ast_kind" (** - def_API('is_app', BOOL, (_in(CONTEXT), _in(AST))) + def_API('is_app', BOOL, (_in(CONTEXT), _in(AST))) *) external is_app : context -> ast -> bool = "camlidl_z3V3_Z3_is_app" @@ -9589,17 +8124,14 @@ external is_numeral_ast : context -> ast -> bool (** Summary: Return true if the give AST is a real algebraic number. - def_API('is_algebraic_number', BOOL, (_in(CONTEXT), _in(AST))) *) external is_algebraic_number : context -> ast -> bool = "camlidl_z3V3_Z3_is_algebraic_number" (** - Summary: Convert an [ast] into an [APP_AST]. - - - {b Precondition}: {v get_ast_kind c a == [APP_AST] v} - + Summary: Convert an [ast] into an [APP_AST]. + - {b Precondition}: {v get_ast_kind c a == [APP_AST] v} def_API('to_app', APP, (_in(CONTEXT), _in(AST))) *) external to_app : context -> ast -> app @@ -9607,25 +8139,21 @@ external to_app : context -> ast -> app (** Summary: Convert an AST into a FUNC_DECL_AST. This is just type casting. - - - {b Precondition}: {v get_ast_kind c a == FUNC_DECL_AST v} - + - {b Precondition}: {v get_ast_kind c a == FUNC_DECL_AST v} def_API('to_func_decl', FUNC_DECL, (_in(CONTEXT), _in(AST))) *) external to_func_decl : context -> ast -> func_decl = "camlidl_z3V3_Z3_to_func_decl" (** - {4 {L Numerals}} + {4 {L Numerals}} *) (** - {5 {L Low-level API}} + {5 {L Low-level API}} *) (** Summary: Return numeral value, as a string of a numeric constant term - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_numeral_string', STRING, (_in(CONTEXT), _in(AST))) *) external get_numeral_string : context -> ast -> string @@ -9634,19 +8162,15 @@ external get_numeral_string : context -> ast -> string (** Summary: Return numeral as a string in decimal notation. The result has at most [precision] decimal places. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST || is_algebraic_number c a - - def_API('get_numeral_decimal_string', STRING, (_in(CONTEXT), _in(AST), _in(UINT))) + def_API('get_numeral_decimal_string', STRING, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_numeral_decimal_string : context -> ast -> int -> string = "camlidl_z3V3_Z3_get_numeral_decimal_string" (** Summary: Return the numerator (as a numeral AST) of a numeral AST of sort Real. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_numerator', AST, (_in(CONTEXT), _in(AST))) *) external get_numerator : context -> ast -> ast @@ -9654,9 +8178,7 @@ external get_numerator : context -> ast -> ast (** Summary: Return the denominator (as a numeral AST) of a numeral AST of sort Real. - - {b Precondition}: get_ast_kind c a == NUMERAL_AST - def_API('get_denominator', AST, (_in(CONTEXT), _in(AST))) *) external get_denominator : context -> ast -> ast @@ -9664,16 +8186,12 @@ external get_denominator : context -> ast -> ast (** Summary: Return numeral value, as a pair of 64 bit numbers if the representation fits. - @param c logical context. @param a term. @param num numerator. @param den denominator. - Return [TRUE] if the numeral value fits in 64 bit numerals, [FALSE] otherwise. - - {b Precondition}: get_ast_kind a == NUMERAL_AST - def_API('get_numeral_small', BOOL, (_in(CONTEXT), _in(AST), _out(INT64), _out(INT64))) *) external get_numeral_small : context -> ast -> bool * int64 * int64 @@ -9683,11 +8201,8 @@ external get_numeral_small : context -> ast -> bool * int64 * int64 Summary: \[ [ get_numeral_int c v ] \] Similar to {!get_numeral_string}, but only succeeds if the value can fit in a machine int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_int', BOOL, (_in(CONTEXT), _in(AST), _out(INT))) *) external get_numeral_int : context -> ast -> bool * int @@ -9697,11 +8212,8 @@ external get_numeral_int : context -> ast -> bool * int Summary: \[ [ get_numeral_int64 c v ] \] Similar to {!get_numeral_string}, but only succeeds if the value can fit in a machine long long int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64))) *) external get_numeral_int64 : context -> ast -> bool * int64 @@ -9711,47 +8223,39 @@ external get_numeral_int64 : context -> ast -> bool * int64 Summary: \[ [ get_numeral_rational_int64 c x y] \] Similar to {!get_numeral_string}, but only succeeds if the value can fit as a rational number as machine long long int. Return TRUE if the call succeeded. - - {b Precondition}: get_ast_kind c v == NUMERAL_AST - - {b See also}: {!get_numeral_string} - def_API('get_numeral_rational_int64', BOOL, (_in(CONTEXT), _in(AST), _out(INT64), _out(INT64))) *) external get_numeral_rational_int64 : context -> ast -> bool * int64 * int64 = "camlidl_z3V3_Z3_get_numeral_rational_int64" (** - Summary: Return a lower bound for the given real algebraic number. + Summary: Return a lower bound for the given real algebraic number. The interval isolating the number is smaller than 1/10^precision. The result is a numeral AST of sort Real. - - {b Precondition}: is_algebraic_number c a - def_API('get_algebraic_number_lower', AST, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_algebraic_number_lower : context -> ast -> int -> ast = "camlidl_z3V3_Z3_get_algebraic_number_lower" (** - Summary: Return a upper bound for the given real algebraic number. + Summary: Return a upper bound for the given real algebraic number. The interval isolating the number is smaller than 1/10^precision. The result is a numeral AST of sort Real. - - {b Precondition}: is_algebraic_number c a - def_API('get_algebraic_number_upper', AST, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_algebraic_number_upper : context -> ast -> int -> ast = "camlidl_z3V3_Z3_get_algebraic_number_upper" (** - {4 {L Patterns}} + {4 {L Patterns}} *) (** - Summary: Convert a pattern into ast. - - {b Remarks}: [pattern_to_ast c p] can be replaced by [(p :> ast)]. - + Summary: Convert a pattern into ast. + - {b Remarks}: [pattern_to_ast c p] can be replaced by [(p :> ast)]. def_API('pattern_to_ast', AST, (_in(CONTEXT), _in(PATTERN))) *) external pattern_to_ast : context -> pattern -> ast @@ -9759,7 +8263,6 @@ external pattern_to_ast : context -> pattern -> ast (** Summary: Return number of terms in pattern. - def_API('get_pattern_num_terms', UINT, (_in(CONTEXT), _in(PATTERN))) *) external get_pattern_num_terms : context -> pattern -> int @@ -9767,20 +8270,17 @@ external get_pattern_num_terms : context -> pattern -> int (** Summary: Return i'th ast in pattern. - def_API('get_pattern', AST, (_in(CONTEXT), _in(PATTERN), _in(UINT))) *) external get_pattern : context -> pattern -> int -> ast = "camlidl_z3V3_Z3_get_pattern" (** - {4 {L Quantifiers}} + {4 {L Quantifiers}} *) (** Summary: Return index of de-Brujin bound variable. - - {b Precondition}: get_ast_kind a == VAR_AST - def_API('get_index_value', UINT, (_in(CONTEXT), _in(AST))) *) external get_index_value : context -> ast -> int @@ -9788,29 +8288,23 @@ external get_index_value : context -> ast -> int (** Summary: Determine if quantifier is universal. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - - def_API('is_quantifier_forall', BOOL, (_in(CONTEXT), _in(AST))) + def_API('is_quantifier_forall', BOOL, (_in(CONTEXT), _in(AST))) *) external is_quantifier_forall : context -> ast -> bool = "camlidl_z3V3_Z3_is_quantifier_forall" (** Summary: Obtain weight of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - - def_API('get_quantifier_weight', UINT, (_in(CONTEXT), _in(AST))) + def_API('get_quantifier_weight', UINT, (_in(CONTEXT), _in(AST))) *) external get_quantifier_weight : context -> ast -> int = "camlidl_z3V3_Z3_get_quantifier_weight" (** Summary: Return number of patterns used in quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_patterns', UINT, (_in(CONTEXT), _in(AST))) *) external get_quantifier_num_patterns : context -> ast -> int @@ -9818,9 +8312,7 @@ external get_quantifier_num_patterns : context -> ast -> int (** Summary: Return i'th pattern. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_pattern_ast', PATTERN, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_quantifier_pattern_ast : context -> ast -> int -> pattern @@ -9828,9 +8320,7 @@ external get_quantifier_pattern_ast : context -> ast -> int -> pattern (** Summary: Return number of no_patterns used in quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_no_patterns', UINT, (_in(CONTEXT), _in(AST))) *) external get_quantifier_num_no_patterns : context -> ast -> int @@ -9838,9 +8328,7 @@ external get_quantifier_num_no_patterns : context -> ast -> int (** Summary: Return i'th no_pattern. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_no_pattern_ast', AST, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_quantifier_no_pattern_ast : context -> ast -> int -> ast @@ -9848,9 +8336,7 @@ external get_quantifier_no_pattern_ast : context -> ast -> int -> ast (** Summary: Return number of bound variables of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_num_bound', UINT, (_in(CONTEXT), _in(AST))) *) external get_quantifier_num_bound : context -> ast -> int @@ -9858,9 +8344,7 @@ external get_quantifier_num_bound : context -> ast -> int (** Summary: Return symbol of the i'th bound variable. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_bound_name', SYMBOL, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_quantifier_bound_name : context -> ast -> int -> symbol @@ -9868,9 +8352,7 @@ external get_quantifier_bound_name : context -> ast -> int -> symbol (** Summary: Return sort of the i'th bound variable. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_bound_sort', SORT, (_in(CONTEXT), _in(AST), _in(UINT))) *) external get_quantifier_bound_sort : context -> ast -> int -> sort @@ -9878,22 +8360,18 @@ external get_quantifier_bound_sort : context -> ast -> int -> sort (** Summary: Return body of quantifier. - - {b Precondition}: get_ast_kind a == QUANTIFIER_AST - def_API('get_quantifier_body', AST, (_in(CONTEXT), _in(AST))) *) external get_quantifier_body : context -> ast -> ast = "camlidl_z3V3_Z3_get_quantifier_body" (** - {3 {L Simplification}} + {3 {L Simplification}} *) (** Summary: Interface to simplifier. - Provides an interface to the AST simplifier used by Z3. - def_API('simplify', AST, (_in(CONTEXT), _in(AST))) *) external simplify : context -> ast -> ast @@ -9904,10 +8382,9 @@ external simplify : context -> ast -> ast *) (** Summary: Update the arguments of term [a] using the arguments [args]. - The number of arguments [num_args] should coincide + The number of arguments [num_args] should coincide with the number of arguments to [a]. If [a] is a quantifier, then num_args has to be 1. - def_API('update_term', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST))) *) external update_term : context -> ast -> ast array -> ast @@ -9917,7 +8394,6 @@ external update_term : context -> ast -> ast array -> ast Summary: Substitute every occurrence of {e from[i] } in [a] with {e to[i] }, for [i] smaller than [num_exprs]. The result is the new AST. The arrays [from] and [to] must have size [num_exprs]. For every [i] smaller than [num_exprs], we must have that sort of {e from[i] } must be equal to sort of {e to[i] }. - def_API('substitute', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST), _in_array(2, AST))) *) external substitute : context -> ast -> ast array -> ast array -> ast @@ -9926,7 +8402,6 @@ external substitute : context -> ast -> ast array -> ast array -> ast (** Summary: Substitute the free variables in [a] with the expressions in [to]. For every [i] smaller than [num_exprs], the variable with de-Bruijn index [i] is replaced with term {e to[i] }. - def_API('substitute_vars', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST))) *) external substitute_vars : context -> ast -> ast array -> ast @@ -9937,7 +8412,6 @@ external substitute_vars : context -> ast -> ast array -> ast *) (** Summary: Log interaction to a file. - extra_API('open_log', INT, (_in(STRING),)) *) external open_log : string -> bool @@ -9945,11 +8419,9 @@ external open_log : string -> bool (** Summary: Append user-defined string to interaction log. - The interaction log is opened using open_log. It contains the formulas that are checked using Z3. You can use this command to append comments, for instance. - extra_API('append_log', VOID, (_in(STRING),)) *) external append_log : string -> unit @@ -9957,7 +8429,6 @@ external append_log : string -> unit (** Summary: Close interaction log. - extra_API('close_log', VOID, ()) *) external close_log : unit -> unit @@ -9965,10 +8436,8 @@ external close_log : unit -> unit (** Summary: Enable/disable printing warning messages to the console. - Warnings are printed after passing [true], warning messages are - suppressed after calling this method with [false]. - + suppressed after calling this method with [false]. def_API('toggle_warning_messages', VOID, (_in(BOOL),)) *) external toggle_warning_messages : bool -> unit @@ -9979,19 +8448,16 @@ external toggle_warning_messages : bool -> unit *) (** Summary: Select mode for the format used for pretty-printing AST nodes. - The default mode for pretty printing AST nodes is to produce - SMT-LIB style output where common subexpressions are printed + SMT-LIB style output where common subexpressions are printed at each occurrence. The mode is called PRINT_SMTLIB_FULL. - To print shared common subexpressions only once, + To print shared common subexpressions only once, use the PRINT_LOW_LEVEL mode. To print in way that conforms to SMT-LIB standards and uses let expressions to share common sub-expressions use PRINT_SMTLIB_COMPLIANT. - - {b See also}: {!ast_to_string} - {b See also}: {!pattern_to_string} - {b See also}: {!func_decl_to_string} - def_API('set_ast_print_mode', VOID, (_in(CONTEXT), _in(PRINT_MODE))) *) external set_ast_print_mode : context -> ast_print_mode -> unit @@ -9999,13 +8465,8 @@ external set_ast_print_mode : context -> ast_print_mode -> unit (** Summary: Convert the given AST node into a string. - - - - - {b See also}: {!pattern_to_string} - {b See also}: {!sort_to_string} - def_API('ast_to_string', STRING, (_in(CONTEXT), _in(AST))) *) external ast_to_string : context -> ast -> string @@ -10031,11 +8492,6 @@ external func_decl_to_string : context -> func_decl -> string (** Summary: Convert the given model into a string. - - - - - def_API('model_to_string', STRING, (_in(CONTEXT), _in(MODEL))) *) external model_to_string : context -> model -> string @@ -10043,80 +8499,66 @@ external model_to_string : context -> model -> string (** Summary: Convert the given benchmark into SMT-LIB formatted string. - - - - - @param c - context. @param name - name of benchmark. The argument is optional. - @param logic - the benchmark logic. + @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 num_assumptions - number of assumptions. @param assumptions - auxiliary assumptions. @param formula - formula to be checked for consistency in conjunction with assumptions. - def_API('benchmark_to_smtlib_string', STRING, (_in(CONTEXT), _in(STRING), _in(STRING), _in(STRING), _in(STRING), _in(UINT), _in_array(5, AST), _in(AST))) *) external benchmark_to_smtlib_string : context -> string -> string -> string -> string -> ast array -> ast -> string - = "camlidl_z3_Z3_benchmark_to_smtlib_string_bytecode" "camlidl_z3V3_Z3_benchmark_to_smtlib_string" + = "camlidl_z3V3_Z3_benchmark_to_smtlib_string_bytecode" "camlidl_z3V3_Z3_benchmark_to_smtlib_string" (** {2 {L Parser interface}} *) (** Summary: \[ [ parse_smtlib2_string c str ] \] - Parse the given string using the SMT-LIB2 parser. - + Parse the given string using the SMT-LIB2 parser. It returns a formula comprising of the conjunction of assertions in the scope (up to push/pop) at the end of the string. - def_API('parse_smtlib2_string', AST, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) *) external parse_smtlib2_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3_Z3_parse_smtlib2_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_string" + = "camlidl_z3V3_Z3_parse_smtlib2_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_string" (** Summary: Similar to {!parse_smtlib2_string}, but reads the benchmark from a file. - def_API('parse_smtlib2_file', AST, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) *) external parse_smtlib2_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - = "camlidl_z3_Z3_parse_smtlib2_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_file" + = "camlidl_z3V3_Z3_parse_smtlib2_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib2_file" (** - {4 {L Low-level API}} + {4 {L Low-level API}} *) (** Summary: \[ [ parse_smtlib_string c str sort_names sorts decl_names decls ] \] - Parse the given string using the SMT-LIB parser. - - The symbol table of the parser can be initialized using the given sorts and declarations. + Parse the given string using the SMT-LIB parser. + The symbol table of the parser can be initialized using the given sorts and declarations. The symbols in the arrays [sort_names] and [decl_names] don't need to match the names of the sorts and declarations in the arrays [sorts] and [decls]. This is an useful feature since we can use arbitrary names to reference sorts and declarations defined using the C API. - The formulas, assumptions and declarations defined in [str] can be extracted using the functions: - {!get_smtlib_num_formulas}, {!get_smtlib_formula}, {!get_smtlib_num_assumptions}, {!get_smtlib_assumption}, + {!get_smtlib_num_formulas}, {!get_smtlib_formula}, {!get_smtlib_num_assumptions}, {!get_smtlib_assumption}, {!get_smtlib_num_decls}, and {!get_smtlib_decl}. - def_API('parse_smtlib_string', VOID, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) *) external parse_smtlib_string : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3_Z3_parse_smtlib_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib_string" + = "camlidl_z3V3_Z3_parse_smtlib_string_bytecode" "camlidl_z3V3_Z3_parse_smtlib_string" (** Summary: Similar to {!parse_smtlib_string}, but reads the benchmark from a file. - def_API('parse_smtlib_file', VOID, (_in(CONTEXT), _in(STRING), _in(UINT), _in_array(2, SYMBOL), _in_array(2, SORT), _in(UINT), _in_array(5, SYMBOL), _in_array(5, FUNC_DECL))) *) external parse_smtlib_file : context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> unit - = "camlidl_z3_Z3_parse_smtlib_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib_file" + = "camlidl_z3V3_Z3_parse_smtlib_file_bytecode" "camlidl_z3V3_Z3_parse_smtlib_file" (** Summary: Return the number of SMTLIB formulas parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_formulas', UINT, (_in(CONTEXT), )) *) external get_smtlib_num_formulas : context -> int @@ -10125,9 +8567,7 @@ external get_smtlib_num_formulas : context -> int (** Summary: \[ [ get_smtlib_formula c i ] \] Return the i-th formula parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_formulas c - def_API('get_smtlib_formula', AST, (_in(CONTEXT), _in(UINT))) *) external get_smtlib_formula : context -> int -> ast @@ -10135,7 +8575,6 @@ external get_smtlib_formula : context -> int -> ast (** Summary: Return the number of SMTLIB assumptions parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_assumptions', UINT, (_in(CONTEXT), )) *) external get_smtlib_num_assumptions : context -> int @@ -10144,9 +8583,7 @@ external get_smtlib_num_assumptions : context -> int (** Summary: \[ [ get_smtlib_assumption c i ] \] Return the i-th assumption parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_assumptions c - def_API('get_smtlib_assumption', AST, (_in(CONTEXT), _in(UINT))) *) external get_smtlib_assumption : context -> int -> ast @@ -10154,7 +8591,6 @@ external get_smtlib_assumption : context -> int -> ast (** Summary: Return the number of declarations parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_decls', UINT, (_in(CONTEXT), )) *) external get_smtlib_num_decls : context -> int @@ -10163,9 +8599,7 @@ external get_smtlib_num_decls : context -> int (** Summary: \[ [ get_smtlib_decl c i ] \] Return the i-th declaration parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_decls c - def_API('get_smtlib_decl', FUNC_DECL, (_in(CONTEXT), _in(UINT))) *) external get_smtlib_decl : context -> int -> func_decl @@ -10173,7 +8607,6 @@ external get_smtlib_decl : context -> int -> func_decl (** Summary: Return the number of sorts parsed by {!parse_smtlib_string} or {!parse_smtlib_file}. - def_API('get_smtlib_num_sorts', UINT, (_in(CONTEXT), )) *) external get_smtlib_num_sorts : context -> int @@ -10182,9 +8615,7 @@ external get_smtlib_num_sorts : context -> int (** Summary: \[ [ get_smtlib_sort c i ] \] Return the i-th sort parsed by the last call to {!parse_smtlib_string} or {!parse_smtlib_file}. - - {b Precondition}: i < get_smtlib_num_sorts c - def_API('get_smtlib_sort', SORT, (_in(CONTEXT), _in(UINT))) *) external get_smtlib_sort : context -> int -> sort @@ -10193,50 +8624,43 @@ external get_smtlib_sort : context -> int -> sort (** Summary: \[ [ get_smtlib_error c ] \] Retrieve that last error message information generated from parsing. - def_API('get_smtlib_error', STRING, (_in(CONTEXT), )) *) external get_smtlib_error : context -> string = "camlidl_z3V3_Z3_get_smtlib_error" -(** - Summary: \[ [ parse_z3_string c str ] \] - Parse the given string using the Z3 native parser. - - Return the conjunction of asserts made in the input. - - def_API('parse_z3_string', AST, (_in(CONTEXT), _in(STRING))) -*) -external parse_z3_string : context -> string -> ast - = "camlidl_z3_Z3_parse_z3V3_string" - -(** - Summary: Similar to {!parse_z3_string}, but reads the benchmark from a file. - - def_API('parse_z3_file', AST, (_in(CONTEXT), _in(STRING))) -*) -external parse_z3_file : context -> string -> ast - = "camlidl_z3_Z3_parse_z3V3_file" - (** {2 {L Miscellaneous}} *) (** Summary: Return Z3 version number information. - def_API('get_version', VOID, (_out(UINT), _out(UINT), _out(UINT), _out(UINT))) *) external get_version : unit -> int * int * int * int = "camlidl_z3V3_Z3_get_version" (** - Summary: Reset all allocated resources. + Summary: Enable tracing messages tagged as [tag] when Z3 is compiled in debug mode. + It is a NOOP otherwise + def_API('enable_trace', VOID, (_in(STRING),)) +*) +external enable_trace : string -> unit + = "camlidl_z3V3_Z3_enable_trace" - Use this facility on out-of memory errors. +(** + Summary: Disable tracing messages tagged as [tag] when Z3 is compiled in debug mode. + It is a NOOP otherwise + def_API('disable_trace', VOID, (_in(STRING),)) +*) +external disable_trace : string -> unit + = "camlidl_z3V3_Z3_disable_trace" + +(** + Summary: Reset all allocated resources. + Use this facility on out-of memory errors. It allows discharging the previous state and resuming afresh. Any pointers previously returned by the API become invalid. - def_API('reset_memory', VOID, ()) *) external reset_memory : unit -> unit @@ -10277,15 +8701,12 @@ external theory_get_context : theory -> context (** Summary: Assert a theory axiom/lemmas during the search. - - An axiom added at search level [n] will remain in the logical context until - level [n] is backtracked. - + An axiom added at search level [n] will remain in the logical context until + level [n] is backtracked. The callbacks for push ({!set_push_callback}) and pop ({!set_pop_callback}) can be used to track when the search level is increased (i.e., new case-split) and decreased (i.e., case-split is backtracked). - Z3 tracks the theory axioms asserted. So, multiple assertions of the same axiom are ignored. *) @@ -10296,7 +8717,6 @@ external theory_assert_axiom : theory -> ast -> unit Summary: Inform to the logical context that [lhs] and [rhs] have the same interpretation in the model being built by theory [t]. If lhs = rhs is inconsistent with other theories, then the logical context will backtrack. - For more information, see the paper "Model-Based Theory Combination" in the Z3 website. *) external theory_assume_eq : theory -> ast -> ast -> unit @@ -10304,7 +8724,7 @@ external theory_assume_eq : theory -> ast -> ast -> unit (** Summary: Enable/disable the simplification of theory axioms asserted using {!theory_assert_axiom}. - By default, the simplification of theory specific operators is disabled. + By default, the simplification of theory specific operators is disabled. That is, the reduce theory callbacks are not invoked for theory axioms. The default behavior is useful when asserting axioms stating properties of theory operators. *) @@ -10319,12 +8739,11 @@ external theory_get_eqc_root : theory -> ast -> ast (** Summary: Return the next element in the equivalence class containing [n]. - The elements in an equivalence class are organized in a circular list. - You can traverse the list by calling this function multiple times + You can traverse the list by calling this function multiple times using the result from the previous call. This is illustrated in the code snippet below. - {v + {v ast curr = n; do curr = theory_get_eqc_next(theory, curr); @@ -10335,14 +8754,14 @@ external theory_get_eqc_next : theory -> ast -> ast = "camlidl_z3V3_Z3_theory_get_eqc_next" (** - Summary: Return the number of parents of [n] that are operators of the given theory. + Summary: Return the number of parents of [n] that are operators of the given theory. *) external theory_get_num_parents : theory -> ast -> int = "camlidl_z3V3_Z3_theory_get_num_parents" (** - Summary: Return the i-th parent of [n]. - See {!theory_get_num_parents}. + Summary: Return the i-th parent of [n]. + See {!theory_get_num_parents}. *) external theory_get_parent : theory -> ast -> int -> ast = "camlidl_z3V3_Z3_theory_get_parent" @@ -10369,7 +8788,6 @@ external theory_get_num_elems : theory -> int (** Summary: Return the i-th elem of the given theory in the logical context. - - {b See}: {!theory_get_num_elems} *) external theory_get_elem : theory -> int -> ast @@ -10385,7 +8803,6 @@ external theory_get_num_apps : theory -> int (** Summary: Return the i-th application of the given theory in the logical context. - - {b See}: {!theory_get_num_apps} *) external theory_get_app : theory -> int -> ast @@ -10396,11 +8813,9 @@ external theory_get_app : theory -> int -> ast *) (** Summary: Create injective function declaration - @deprecated This method just asserts a (universally quantified) formula that asserts that the new function is injective. It is compatible with the old interface for solving: {!assert_cnstr}, {!check_assumptions}, etc. - def_API('mk_injective_function', FUNC_DECL, (_in(CONTEXT), _in(SYMBOL), _in(UINT), _in_array(2, SORT), _in(SORT))) *) external mk_injective_function : context -> symbol -> sort array -> sort -> func_decl @@ -10414,9 +8829,7 @@ external mk_injective_function : context -> symbol -> sort array -> sort -> func It is incorrect to invoke this function after invoking {!check}, {!check_and_get_model}, {!check_assumptions} and {!push}. Return [TRUE] if the logic was changed successfully, and [FALSE] otherwise. - @deprecated Subsumed by {!mk_solver_for_logic} - def_API('set_logic', VOID, (_in(CONTEXT), _in(STRING))) *) external set_logic : context -> string -> bool @@ -10424,15 +8837,11 @@ external set_logic : context -> string -> bool (** Summary: Create a backtracking point. - - The logical context can be viewed as a stack of contexts. The + The logical context can be viewed as a stack of contexts. The scope level is the number of elements on this stack. The stack of contexts is simulated using trail (undo) stacks. - - {b See also}: {!pop} - @deprecated Subsumed by {!solver_push} - def_API('push', VOID, (_in(CONTEXT),)) *) external push : context -> unit @@ -10440,17 +8849,13 @@ external push : context -> unit (** Summary: Backtrack. - Restores the context from the top of the stack, and pops it off the - stack. Any changes to the logical context (by {!assert_cnstr} or + stack. Any changes to the logical context (by {!assert_cnstr} or other functions) between the matching {!push} and [pop] operators are flushed, and the context is completely restored to what it was right before the {!push}. - - {b See also}: {!push} - @deprecated Subsumed by {!solver_pop} - def_API('pop', VOID, (_in(CONTEXT), _in(UINT))) *) external pop : context -> int -> unit @@ -10458,38 +8863,17 @@ external pop : context -> int -> unit (** Summary: Retrieve the current scope level. - It retrieves the number of scopes that have been pushed, but not yet popped. - - {b See also}: {!push} - {b See also}: {!pop} - @deprecated Subsumed by {!solver_get_num_scopes}. - def_API('get_num_scopes', UINT, (_in(CONTEXT),)) *) external get_num_scopes : context -> int = "camlidl_z3V3_Z3_get_num_scopes" (** - - - - - - - - - - - - - - - - - @deprecated This function has no effect. - + @deprecated This function has no effect. def_API('persist_ast', VOID, (_in(CONTEXT), _in(AST), _in(UINT))) *) external persist_ast : context -> ast -> int -> unit @@ -10497,18 +8881,13 @@ external persist_ast : context -> ast -> int -> unit (** Summary: Assert a constraint into the logical context. - After one assertion, the logical context may become - inconsistent. - + inconsistent. The functions {!check} or {!check_and_get_model} should be used to check whether the logical context is consistent or not. - - {b See also}: {!check} - {b See also}: {!check_and_get_model} - @deprecated Subsumed by {!solver_assert} - def_API('assert_cnstr', VOID, (_in(CONTEXT), _in(AST))) *) external assert_cnstr : context -> ast -> unit @@ -10516,25 +8895,13 @@ external assert_cnstr : context -> ast -> unit (** Summary: Check whether the given logical context is consistent or not. - If the logical context is not unsatisfiable (i.e., the return value is different from [L_FALSE)] and model construction is enabled (see {!mk_config}), - - then a valid model is returned. Otherwise, it is unsafe to use the returned model. - - - - - - + then a valid model is returned. Otherwise, it is unsafe to use the returned model. - {b Remarks}: Model construction must be enabled using configuration parameters (See, {!mk_config}). - - {b See also}: {!check} - - @deprecated Subsumed by {!solver_check} - def_API('check_and_get_model', INT, (_in(CONTEXT), _out(MODEL))) *) external check_and_get_model : context -> lbool * model @@ -10542,13 +8909,9 @@ external check_and_get_model : context -> lbool * model (** Summary: Check whether the given logical context is consistent or not. - The function {!check_and_get_model} should be used when models are needed. - - {b See also}: {!check_and_get_model} - @deprecated Subsumed by {!solver_check} - def_API('check', INT, (_in(CONTEXT),)) *) external check : context -> lbool @@ -10556,40 +8919,23 @@ external check : context -> lbool (** Summary: Check whether the given logical context and optional assumptions is consistent or not. - If the logical context is not unsatisfiable (i.e., the return value is different from [L_FALSE)], - and model construction is enabled (see {!mk_config}), - - then a valid model is returned. Otherwise, it is unsafe to use the returned model. - - - - - + then a valid model is returned. Otherwise, it is unsafe to use the returned model. @param c logical context. @param num_assumptions number of auxiliary assumptions. @param assumptions array of auxiliary assumptions @param m optional pointer to a model. @param proof optional pointer to a proof term. - @param core_size size of unsatisfiable core. - @param core pointer to an array receiving unsatisfiable core. + @param core_size size of unsatisfiable core. + @param core pointer to an array receiving unsatisfiable core. The unsatisfiable core is a subset of the assumptions, so the array has the same size as the assumptions. The [core] array is not populated if [core_size] is set to 0. - - {b Precondition}: assumptions comprises of propositional literals. - In other words, you cannot use compound formulas for assumptions, + In other words, you cannot use compound formulas for assumptions, but should use propositional variables or negations of propositional variables. - - - - - - {b See also}: {!check} - - @deprecated Subsumed by {!solver_check_assumptions} - def_API('check_assumptions', INT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _out(MODEL), _out(AST), _out(UINT), _out_array2(1, 5, AST))) *) external check_assumptions : context -> ast array -> int -> ast array -> lbool * model * ast * int * ast array @@ -10597,25 +8943,20 @@ external check_assumptions : context -> ast array -> int -> ast array -> lbool * (** Summary: Retrieve congruence class representatives for terms. - The function can be used for relying on Z3 to identify equal terms under the current set of assumptions. The array of terms and array of class identifiers should have the same length. The class identifiers are numerals that are assigned to the same value for their corresponding terms if the current context forces the terms to be - equal. You cannot deduce that terms corresponding to different numerals must be all different, + equal. You cannot deduce that terms corresponding to different numerals must be all different, (especially when using non-convex theories). All implied equalities are returned by this call. This means that two terms map to the same class identifier if and only if the current context implies that they are equal. - A side-effect of the function is a satisfiability check. The function return L_FALSE if the current assertions are not satisfiable. - - {b See also}: {!check_and_get_model} - {b See also}: {!check} - @deprecated Subsumed by solver API - def_API('get_implied_equalities', UINT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _out_array(1, UINT))) *) external get_implied_equalities : context -> ast array -> lbool * int array @@ -10623,11 +8964,8 @@ external get_implied_equalities : context -> ast array -> lbool * int array (** Summary: Delete a model object. - - {b See also}: {!check_and_get_model} - @deprecated Subsumed by solver API - def_API('del_model', VOID, (_in(CONTEXT), _in(MODEL))) *) external del_model : context -> model -> unit @@ -10638,13 +8976,10 @@ external del_model : context -> model -> unit *) (** Summary: Cancel an ongoing check. - Notifies the current check to abort and return. This method should be called from a different thread than the one performing the check. - @deprecated Use {!interrupt} instead. - def_API('soft_check_cancel', VOID, (_in(CONTEXT), )) *) external soft_check_cancel : context -> unit @@ -10652,12 +8987,9 @@ external soft_check_cancel : context -> unit (** Summary: Retrieve reason for search failure. - - If a call to {!check} or {!check_and_get_model} returns L_UNDEF, + If a call to {!check} or {!check_and_get_model} returns L_UNDEF, use this facility to determine the more detailed cause of search failure. - @deprecated Subsumed by {!solver_get_reason_unknown} - def_API('get_search_failure', UINT, (_in(CONTEXT), )) *) external get_search_failure : context -> search_failure @@ -10668,20 +9000,16 @@ external get_search_failure : context -> search_failure *) (** Summary: Create a labeled formula. - @param c logical context. @param s name of the label. @param is_pos label polarity. @param f formula being labeled. - - A label behaves as an identity function, so the truth value of the - labeled formula is unchanged. Labels are used for identifying + A label behaves as an identity function, so the truth value of the + labeled formula is unchanged. Labels are used for identifying useful sub-formulas when generating counter-examples. - @deprecated Labels are only supported by the old Solver API. This feature is not essential (it can be simulated using auxiliary Boolean variables). It is only available for backward compatibility. - def_API('mk_label', AST, (_in(CONTEXT), _in(SYMBOL), _in(BOOL), _in(AST))) *) external mk_label : context -> symbol -> bool -> ast -> ast @@ -10690,14 +9018,11 @@ external mk_label : context -> symbol -> bool -> ast -> ast (** Summary: Retrieve the set of labels that were relevant in the context of the current satisfied context. - - {b See also}: {!del_literals} - {b See also}: {!get_num_literals} - {b See also}: {!get_label_symbol} - {b See also}: {!get_literal} - @deprecated This procedure is based on the old Solver API. - def_API('get_relevant_labels', LITERALS, (_in(CONTEXT), )) *) external get_relevant_labels : context -> literals @@ -10705,30 +9030,24 @@ external get_relevant_labels : context -> literals (** Summary: Retrieve the set of literals that satisfy the current context. - - {b See also}: {!del_literals} - {b See also}: {!get_num_literals} - {b See also}: {!get_label_symbol} - {b See also}: {!get_literal} - @deprecated This procedure is based on the old Solver API. - def_API('get_relevant_literals', LITERALS, (_in(CONTEXT), )) *) external get_relevant_literals : context -> literals = "camlidl_z3V3_Z3_get_relevant_literals" (** - Summary: Retrieve the set of literals that whose assignment were + Summary: Retrieve the set of literals that whose assignment were guess, but not propagated during the search. - - {b See also}: {!del_literals} - {b See also}: {!get_num_literals} - {b See also}: {!get_label_symbol} - {b See also}: {!get_literal} - @deprecated This procedure is based on the old Solver API. - def_API('get_guessed_literals', LITERALS, (_in(CONTEXT), )) *) external get_guessed_literals : context -> literals @@ -10736,11 +9055,8 @@ external get_guessed_literals : context -> literals (** Summary: Delete a labels context. - - {b See also}: {!get_relevant_labels} - @deprecated This procedure is based on the old Solver API. - def_API('del_literals', VOID, (_in(CONTEXT), _in(LITERALS))) *) external del_literals : context -> literals -> unit @@ -10748,11 +9064,8 @@ external del_literals : context -> literals -> unit (** Summary: Retrieve the number of label symbols that were returned. - - {b See also}: {!get_relevant_labels} - @deprecated This procedure is based on the old Solver API. - def_API('get_num_literals', UINT, (_in(CONTEXT), _in(LITERALS))) *) external get_num_literals : context -> literals -> int @@ -10760,9 +9073,7 @@ external get_num_literals : context -> literals -> int (** Summary: Retrieve label symbol at idx. - @deprecated This procedure is based on the old Solver API. - def_API('get_label_symbol', SYMBOL, (_in(CONTEXT), _in(LITERALS), _in(UINT))) *) external get_label_symbol : context -> literals -> int -> symbol @@ -10770,9 +9081,7 @@ external get_label_symbol : context -> literals -> int -> symbol (** Summary: Retrieve literal expression at idx. - @deprecated This procedure is based on the old Solver API. - def_API('get_literal', AST, (_in(CONTEXT), _in(LITERALS), _in(UINT))) *) external get_literal : context -> literals -> int -> ast @@ -10780,13 +9089,9 @@ external get_literal : context -> literals -> int -> ast (** Summary: Disable label. - The disabled label is not going to be used when blocking the subsequent search. - - {b See also}: {!block_literals} - @deprecated This procedure is based on the old Solver API. - def_API('disable_literal', VOID, (_in(CONTEXT), _in(LITERALS), _in(UINT))) *) external disable_literal : context -> literals -> int -> unit @@ -10794,9 +9099,7 @@ external disable_literal : context -> literals -> int -> unit (** Summary: Block subsequent checks using the remaining enabled labels. - @deprecated This procedure is based on the old Solver API. - def_API('block_literals', VOID, (_in(CONTEXT), _in(LITERALS))) *) external block_literals : context -> literals -> unit @@ -10807,13 +9110,9 @@ external block_literals : context -> literals -> unit *) (** Summary: Return the number of constants assigned by the given model. - - - {b Remarks}: Consider using {!get_model_constants}. - + - {b Remarks}: Consider using {!get_model_constants}. - {b See also}: {!get_model_constant} - @deprecated use {!model_get_num_consts} - def_API('get_model_num_constants', UINT, (_in(CONTEXT), _in(MODEL))) *) external get_model_num_constants : context -> model -> int @@ -10821,14 +9120,10 @@ external get_model_num_constants : context -> model -> int (** Summary: \[ [ get_model_constant c m i ] \] - Return the i-th constant in the given model. - - - {b Remarks}: Consider using {!get_model_constants}. - + Return the i-th constant in the given model. + - {b Remarks}: Consider using {!get_model_constants}. - {b Precondition}: i < get_model_num_constants c m - @deprecated use {!model_get_const_decl} - def_API('get_model_constant', FUNC_DECL, (_in(CONTEXT), _in(MODEL), _in(UINT))) *) external get_model_constant : context -> model -> int -> func_decl @@ -10836,12 +9131,9 @@ external get_model_constant : context -> model -> int -> func_decl (** Summary: Return the number of function interpretations in the given model. - A function interpretation is represented as a finite map and an 'else' value. Each entry in the finite map represents the value of a function given a set of arguments. - @deprecated use {!model_get_num_funcs} - def_API('get_model_num_funcs', UINT, (_in(CONTEXT), _in(MODEL))) *) external get_model_num_funcs : context -> model -> int @@ -10850,24 +9142,18 @@ external get_model_num_funcs : context -> model -> int (** Summary: \[ [ get_model_func_decl c m i ] \] Return the declaration of the i-th function in the given model. - - {b Precondition}: i < get_model_num_funcs c m - - {b See also}: {!get_model_num_funcs} - @deprecated use {!model_get_func_decl} - def_API('get_model_func_decl', FUNC_DECL, (_in(CONTEXT), _in(MODEL), _in(UINT))) *) external get_model_func_decl : context -> model -> int -> func_decl = "camlidl_z3V3_Z3_get_model_func_decl" (** - Summary: Return the value of the given constant or function + Summary: Return the value of the given constant or function in the given model. - @deprecated Consider using {!model_eval} or {!model_get_func_interp} - def_API('eval_func_decl', BOOL, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL), _out(AST))) *) external eval_func_decl : context -> model -> func_decl -> bool * ast @@ -10875,17 +9161,14 @@ external eval_func_decl : context -> model -> func_decl -> bool * ast (** Summary: \[ [ is_array_value c v ] \] - Determine whether the term encodes an array value. - A term encodes an array value if it is a nested sequence of + Determine whether the term encodes an array value. + A term encodes an array value if it is a nested sequence of applications of store on top of a constant array. The indices to the stores have to be values (for example, integer constants) so that equality between the indices can be evaluated. Array values are useful for representing interpretations for arrays. - Return the number of entries mapping to non-default values of the array. - @deprecated Use {!is_as_array} - def_API('is_array_value', BOOL, (_in(CONTEXT), _in(MODEL), _in(AST), _out(UINT))) *) external is_array_value : context -> model -> ast -> bool * int @@ -10895,11 +9178,8 @@ external is_array_value : context -> model -> ast -> bool * int Summary: \[ [ get_array_value c v ] \] An array values is represented as a dictionary plus a default (else) value. This function returns the array graph. - - - {b Precondition}: TRUE == is_array_value c v &num_entries - + - {b Precondition}: TRUE == is_array_value c v &num_entries @deprecated Use func_interp objects and {!get_as_array_func_decl} - def_API('get_array_value', VOID, (_in(CONTEXT), _in(MODEL), _in(AST), _in(UINT), _out_array(3, AST), _out_array(3, AST), _out (AST))) *) external get_array_value : context -> model -> ast -> ast array -> ast array -> ast array * ast array * ast @@ -10908,20 +9188,14 @@ external get_array_value : context -> model -> ast -> ast array -> ast array -> (** Summary: \[ [ get_model_func_else c m i ] \] Return the 'else' value of the i-th function interpretation in the given model. - A function interpretation is represented as a finite map and an 'else' value. - - - {b Remarks}: Consider using {!get_model_funcs}. - + - {b Remarks}: Consider using {!get_model_funcs}. - {b Precondition}: i < get_model_num_funcs c m - - {b See also}: {!get_model_num_funcs} - {b See also}: {!get_model_func_num_entries} - {b See also}: {!get_model_func_entry_num_args} - {b See also}: {!get_model_func_entry_arg} - @deprecated Use func_interp objects - def_API('get_model_func_else', AST, (_in(CONTEXT), _in(MODEL), _in(UINT))) *) external get_model_func_else : context -> model -> int -> ast @@ -10930,20 +9204,14 @@ external get_model_func_else : context -> model -> int -> ast (** Summary: \[ [ get_model_func_num_entries c m i ] \] Return the number of entries of the i-th function interpretation in the given model. - A function interpretation is represented as a finite map and an 'else' value. - - - {b Remarks}: Consider using {!get_model_funcs}. - + - {b Remarks}: Consider using {!get_model_funcs}. - {b Precondition}: i < get_model_num_funcs c m - - {b See also}: {!get_model_num_funcs} - {b See also}: {!get_model_func_else} - {b See also}: {!get_model_func_entry_num_args} - {b See also}: {!get_model_func_entry_arg} - @deprecated Use func_interp objects - def_API('get_model_func_num_entries', UINT, (_in(CONTEXT), _in(MODEL), _in(UINT))) *) external get_model_func_num_entries : context -> model -> int -> int @@ -10953,24 +9221,16 @@ external get_model_func_num_entries : context -> model -> int -> int Summary: \[ [ get_model_func_entry_num_args c m i j ] \] Return the number of arguments of the j-th entry of the i-th function interpretation in the given model. - A function interpretation is represented as a finite map and an 'else' value. This function returns the j-th entry of this map. - An entry represents the value of a function given a set of arguments. - - - - {b Remarks}: Consider using {!get_model_funcs}. - + - {b Remarks}: Consider using {!get_model_funcs}. - {b Precondition}: i < get_model_num_funcs c m - {b Precondition}: j < get_model_func_num_entries c m i - - {b See also}: {!get_model_num_funcs} - {b See also}: {!get_model_func_num_entries } - {b See also}: {!get_model_func_entry_arg} - @deprecated Use func_interp objects - def_API('get_model_func_entry_num_args', UINT, (_in(CONTEXT), _in(MODEL), _in(UINT), _in(UINT))) *) external get_model_func_entry_num_args : context -> model -> int -> int -> int @@ -10980,25 +9240,17 @@ external get_model_func_entry_num_args : context -> model -> int -> int -> int Summary: \[ [ get_model_func_entry_arg c m i j k ] \] Return the k-th argument of the j-th entry of the i-th function interpretation in the given model. - A function interpretation is represented as a finite map and an 'else' value. This function returns the j-th entry of this map. - An entry represents the value of a function given a set of arguments. - - - - {b Remarks}: Consider using {!get_model_funcs}. - + - {b Remarks}: Consider using {!get_model_funcs}. - {b Precondition}: i < get_model_num_funcs c m - {b Precondition}: j < get_model_func_num_entries c m i - {b Precondition}: k < get_model_func_entry_num_args c m i j - - {b See also}: {!get_model_num_funcs} - {b See also}: {!get_model_func_num_entries } - {b See also}: {!get_model_func_entry_num_args} - @deprecated Use func_interp objects - def_API('get_model_func_entry_arg', AST, (_in(CONTEXT), _in(MODEL), _in(UINT), _in(UINT), _in(UINT))) *) external get_model_func_entry_arg : context -> model -> int -> int -> int -> ast @@ -11008,23 +9260,15 @@ external get_model_func_entry_arg : context -> model -> int -> int -> int -> ast Summary: \[ [ get_model_func_entry_value c m i j ] \] Return the return value of the j-th entry of the i-th function interpretation in the given model. - A function interpretation is represented as a finite map and an 'else' value. This function returns the j-th entry of this map. - An entry represents the value of a function given a set of arguments. - - - - {b Remarks}: Consider using {!get_model_funcs}. - + - {b Remarks}: Consider using {!get_model_funcs}. - {b Precondition}: i < get_model_num_funcs c m - {b Precondition}: j < get_model_func_num_entries c m i - - {b See also}: {!get_model_num_funcs} - {b See also}: {!get_model_func_num_entries } - @deprecated Use func_interp objects - def_API('get_model_func_entry_value', AST, (_in(CONTEXT), _in(MODEL), _in(UINT), _in(UINT))) *) external get_model_func_entry_value : context -> model -> int -> int -> ast @@ -11032,21 +9276,14 @@ external get_model_func_entry_value : context -> model -> int -> int -> ast (** Summary: \[ [ eval c m t ] \] - Evaluate the AST node [t] in the given model. - - Return a pair: Boolean and value. The Boolean is true if the term was successfully evaluated. - + Evaluate the AST node [t] in the given model. + Return a pair: Boolean and value. The Boolean is true if the term was successfully evaluated. The evaluation may fail for the following reasons: - - [t] contains a quantifier. - - the model [m] is partial, that is, it doesn't have a complete interpretation for uninterpreted functions. That is, the option {e MODEL_PARTIAL=true } was used. - - [t] is type incorrect. - @deprecated Use {!model_eval} - def_API('eval', BOOL, (_in(CONTEXT), _in(MODEL), _in(AST), _out(AST))) *) external eval : context -> model -> ast -> bool * ast @@ -11054,12 +9291,9 @@ external eval : context -> model -> ast -> bool * ast (** Summary: Evaluate declaration given values. - Provides direct way to evaluate declarations without going over terms. - @deprecated Consider using {!model_eval} and {!substitute_vars} - def_API('eval_decl', BOOL, (_in(CONTEXT), _in(MODEL), _in(FUNC_DECL), _in(UINT), _in_array(3, AST), _out(AST))) *) external eval_decl : context -> model -> func_decl -> ast array -> bool * ast @@ -11070,17 +9304,10 @@ external eval_decl : context -> model -> func_decl -> ast array -> bool * ast *) (** Summary: Convert the given logical context into a string. - This function is mainly used for debugging purposes. It displays the internal structure of a logical context. - - - - - - @deprecated This method is obsolete. It just displays the internal representation of + @deprecated This method is obsolete. It just displays the internal representation of the global solver available for backward compatibility reasons. - def_API('context_to_string', STRING, (_in(CONTEXT),)) *) external context_to_string : context -> string @@ -11088,17 +9315,10 @@ external context_to_string : context -> string (** Summary: Return runtime statistics as a string. - This function is mainly used for debugging purposes. It displays statistics of the search activity. - - - - - - @deprecated This method is based on the old solver API. + @deprecated This method is based on the old solver API. Use {!stats_to_string} when using the new solver API. - def_API('statistics_to_string', STRING, (_in(CONTEXT),)) *) external statistics_to_string : context -> string @@ -11106,129 +9326,98 @@ external statistics_to_string : context -> string (** Summary: Extract satisfying assignment from context as a conjunction. - This function can be used for debugging purposes. It returns a conjunction of formulas that are assigned to true in the current context. This conjunction will contain not only the assertions that are set to true under the current assignment, but will also include additional literals - if there has been a call to {!check} or {!check_and_get_model}. - + if there has been a call to {!check} or {!check_and_get_model}. @deprecated This method is based on the old solver API. - def_API('get_context_assignment', AST, (_in(CONTEXT),)) *) external get_context_assignment : context -> ast = "camlidl_z3V3_Z3_get_context_assignment" - (** {2 {L ML Extensions}} *) - (** \[ [ mk_context_x configs] \] is a shorthand for the context with configurations in [configs]. *) val mk_context_x: (string * string) array -> context;; - (** \[ [ get_app_args c a ] \] is the array of arguments of an application. If [t] is a constant, then the array is empty. - - {b See also}: {!get_app_num_args} - {b See also}: {!get_app_arg} *) -val get_app_args: context -> app -> ast array - +val get_app_args: context -> app -> ast array (** \[ [ get_app_args c d ] \] is the array of parameters of [d]. - - {b See also}: {!get_domain_size} - {b See also}: {!get_domain} *) val get_domains: context -> func_decl -> sort array - (** \[ [ get_array_sort c t ] \] is the domain and the range of [t]. - - {b See also}: {!get_array_sort_domain} - {b See also}: {!get_array_sort_range} *) val get_array_sort: context -> sort -> sort * sort - (** \[ [ get_tuple_sort c ty ] \] is the pair [(mk_decl, fields)] where [mk_decl] is the constructor declaration of [ty], and [fields] is the array of fields in [ty]. - - {b See also}: {!get_tuple_sort_mk_decl} - {b See also}: {!get_tuple_sort_num_fields} - {b See also}: {!get_tuple_sort_field_decl} *) val get_tuple_sort: context -> sort -> (func_decl * func_decl array) - (** \[ [ datatype_constructor_refined ] \] is the refinement of a datatype constructor. - It contains the constructor declaration, recognizer, and list of accessor functions. *) -type datatype_constructor_refined = { - constructor : func_decl; - recognizer : func_decl; - accessors : func_decl array +type datatype_constructor_refined = { + constructor : func_decl; + recognizer : func_decl; + accessors : func_decl array } - (** \[ [ get_datatype_sort c ty ] \] is the array of triples [(constructor, recognizer, fields)] where [constructor] is the constructor declaration of [ty], [recognizer] is the recognizer for the [constructor], and [fields] is the array of fields in [ty]. - - {b See also}: {!get_datatype_sort_num_constructors} - {b See also}: {!get_datatype_sort_constructor} - {b See also}: {!get_datatype_sort_recognizer} - {b See also}: {!get_datatype_sort_constructor_accessor} *) - - val get_datatype_sort: context -> sort -> datatype_constructor_refined array - (** \[ [ get_model_constants c m ] \] is the array of constants in the model [m]. - - {b See also}: {!get_model_num_constants} - {b See also}: {!get_model_constant} *) val get_model_constants: context -> model -> func_decl array - - (** \[ [ get_model_func_entry c m i j ] \] is the [j]'th entry in the [i]'th function in the model [m]. - - {b See also}: {!get_model_func_entry_num_args} - {b See also}: {!get_model_func_entry_arg} - {b See also}: {!get_model_func_entry_value} *) val get_model_func_entry: context -> model -> int -> int -> (ast array * ast);; - (** \[ [ get_model_func_entries c m i ] \] is the array of entries in the [i]'th function in the model [m]. - - {b See also}: {!get_model_func_num_entries} - {b See also}: {!get_model_func_entry} *) val get_model_func_entries: context -> model -> int -> (ast array * ast) array;; - (** \[ [ get_model_funcs c m ] \] is the array of functions in the model [m]. Each function is represented by the triple [(decl, entries, else)], where [decl] is the declaration name for the function, [entries] is the array of entries in the function, and [else] is the default (else) value for the function. - - {b See also}: {!get_model_num_funcs} - {b See also}: {!get_model_func_decl} - {b See also}: {!get_model_func_entries} - {b See also}: {!get_model_func_else} *) -val get_model_funcs: context -> model -> +val get_model_funcs: context -> model -> (symbol * - (ast array * ast) array * + (ast array * ast) array * ast) array - (** \[ [ get_smtlib_formulas c ] \] is the array of formulas created by a preceding call to {!parse_smtlib_string} or {!parse_smtlib_file}. - Recommend use {!parse_smtlib_string_x} or {!parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_string_x} - {b See also}: {!parse_smtlib_file_x} - {b See also}: {!parse_smtlib_string} @@ -11237,13 +9426,9 @@ val get_model_funcs: context -> model -> - {b See also}: {!get_smtlib_formula} *) val get_smtlib_formulas: context -> ast array - (** \[ [get_smtlib_assumptions c] \] is the array of assumptions created by a preceding call to {!parse_smtlib_string} or {!parse_smtlib_file}. - Recommend use {!parse_smtlib_string_x} or {!parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - - {b See also}: {!parse_smtlib_string_x} - {b See also}: {!parse_smtlib_file_x} - {b See also}: {!parse_smtlib_string} @@ -11252,13 +9437,9 @@ val get_smtlib_formulas: context -> ast array - {b See also}: {!get_smtlib_assumption} *) val get_smtlib_assumptions: context -> ast array - (** \[ [ get_smtlib_decls c ] \] is the array of declarations created by a preceding call to {!parse_smtlib_string} or {!parse_smtlib_file}. - Recommend use {!parse_smtlib_string_x} or {!parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - - {b See also}: {!parse_smtlib_string_x} - {b See also}: {!parse_smtlib_file_x} - {b See also}: {!parse_smtlib_string} @@ -11267,13 +9448,9 @@ val get_smtlib_assumptions: context -> ast array - {b See also}: {!get_smtlib_decl} *) val get_smtlib_decls: context -> func_decl array - (** \[ [ get_smtlib_parse_results c ] \] is the triple [(get_smtlib_formulas c, get_smtlib_assumptions c, get_smtlib_decls c)]. - Recommend use {!parse_smtlib_string_x} or {!parse_smtlib_file_x} for functional style interface to the SMT-LIB parser. - - - {b See also}: {!parse_smtlib_string_x} - {b See also}: {!parse_smtlib_file_x} - {b See also}: {!parse_smtlib_string} @@ -11283,52 +9460,38 @@ val get_smtlib_decls: context -> func_decl array - {b See also}: {!get_smtlib_decls} *) val get_smtlib_parse_results: context -> (ast array * ast array * func_decl array) - (** - \[ [ parse_smtlib_string_formula c ... ] \] calls [(parse_smtlib_string c ...)] and returns the single formula produced. - + \[ [ parse_smtlib_string_formula c ... ] \] calls [(parse_smtlib_string c ...)] and returns the single formula produced. Recommended for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_file_formula} - {b See also}: {!parse_smtlib_string_x} *) val parse_smtlib_string_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - (** - \[ [ parse_smtlib_file_formula c ... ] \] calls [(parse_smtlib_file c ...)] and returns the single formula produced. - + \[ [ parse_smtlib_file_formula c ... ] \] calls [(parse_smtlib_file c ...)] and returns the single formula produced. Recommended for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_file_formula} - {b See also}: {!parse_smtlib_file_x} *) val parse_smtlib_file_formula: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> ast - (** \[ [ parse_smtlib_string_x c ... ] \] is [(parse_smtlib_string c ...; get_smtlib_parse_results c)] - Recommended for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_file_x} - {b See also}: {!parse_smtlib_string} - {b See also}: {!get_smtlib_parse_results} *) val parse_smtlib_string_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) - (** \[ [ parse_smtlib_file_x c ... ] \] is [(parse_smtlib_file c ...; get_smtlib_parse_results c)] - Recommended for functional style interface to the SMT-LIB parser. - - {b See also}: {!parse_smtlib_string_x} - {b See also}: {!parse_smtlib_file} - {b See also}: {!get_smtlib_parse_results} *) val parse_smtlib_file_x: context -> string -> symbol array -> sort array -> symbol array -> func_decl array -> (ast array * ast array * func_decl array) - (** \[ [ symbol_refined ] \] is the refinement of a {!symbol} . - - {b See also}: {!symbol_refine} - {b See also}: {!get_symbol_kind} *) @@ -11336,23 +9499,17 @@ type symbol_refined = | Symbol_int of int | Symbol_string of string | Symbol_unknown;; - (** \[ [ symbol_refine c s ] \] is the refined symbol of [s]. - - - {b See also}: {!symbol_refined} + - {b See also}: {!symbol_refined} - {b See also}: {!get_symbol_kind} *) val symbol_refine: context -> symbol -> symbol_refined;; - (** \[ [ sort_refined ] \] is the refinement of a {!sort} . - - {b See also}: {!sort_refine} - {b See also}: {!get_sort_kind} *) - - type sort_refined = | Sort_uninterpreted of symbol | Sort_bool @@ -11364,122 +9521,91 @@ type sort_refined = | Sort_relation | Sort_finite_domain | Sort_unknown of symbol - (** \[ [ sort_refine c t ] \] is the refined sort of [t]. - - - {b See also}: {!sort_refined} + - {b See also}: {!sort_refined} - {b See also}: {!get_sort_kind} *) val sort_refine: context -> sort -> sort_refined;; - (** \[ [ binder_type ] \] is a universal or existential quantifier. - - {b See also}: {!term_refined} *) -type binder_type = | Forall | Exists - +type binder_type = | Forall | Exists (** \[ [ numeral_refined ] \] is the refinement of a numeral . - Numerals whose fractional representation can be fit with 64 bit integers are treated as small. - *) -type numeral_refined = - | Numeral_small of int64 * int64 - | Numeral_large of string - +type numeral_refined = + | Numeral_small of int64 * int64 + | Numeral_large of string (** \[ [ term_refined ] \] is the refinement of a {!ast} . - - {b See also}: {!term_refine} *) -type term_refined = - | Term_app of decl_kind * func_decl * ast array +type term_refined = + | Term_app of decl_kind * func_decl * ast array | Term_quantifier of binder_type * int * ast array array * (symbol * sort) array * ast - | Term_numeral of numeral_refined * sort - | Term_var of int * sort - + | Term_numeral of numeral_refined * sort + | Term_var of int * sort (** \[ [ term_refine c a ] \] is the refined term of [a]. - - - {b See also}: {!term_refined} + - {b See also}: {!term_refined} *) val term_refine : context -> ast -> term_refined - -(** +(** \[ [mk_theory c name ] \] create a custom theory. - *) val mk_theory : context -> string -> theory - (** \[ [set_delete_callback th cb] \] set callback when theory gets deleted. *) val set_delete_callback : theory -> (unit -> unit) -> unit - (** \[ [set_reduce_app_callback th cb] \] set callback for simplifying theory terms. *) val set_reduce_app_callback : theory -> (func_decl -> ast array -> ast option) -> unit - (** \[ [set_reduce_eq_callback th cb] \] set callback for simplifying equalities over theory terms. *) val set_reduce_eq_callback : theory -> (ast -> ast -> ast option) -> unit - (** \[ [set_reduce_distinct_callback th cb] \] set callback for simplifying disequalities over theory terms. *) val set_reduce_distinct_callback : theory -> (ast array -> ast option) -> unit - (** \[ [set_new_app_callback th cb] \] set callback for registering new application. *) val set_new_app_callback : theory -> (ast -> unit) -> unit - (** \[ [set_new_elem_callback th cb] \] set callback for registering new element. - - - {b See also}: the help for the corresponding C API function. + - {b See also}: the help for the corresponding C API function. *) val set_new_elem_callback : theory -> (ast -> unit) -> unit - (** \[ [set_init_search_callback th cb] \] set callback when Z3 starts searching for a satisfying assignment. *) val set_init_search_callback : theory -> (unit -> unit) -> unit - (** \[ [set_push_callback th cb] \] set callback for a logical context push. *) val set_push_callback : theory -> (unit -> unit) -> unit - (** \[ [set_pop_callback th cb] \] set callback for a logical context pop. *) val set_pop_callback : theory -> (unit -> unit) -> unit - (** \[ [set_restart_callback th cb] \] set callback for search restart. *) val set_restart_callback : theory -> (unit -> unit) -> unit - val set_reset_callback : theory -> (unit -> unit) -> unit - val set_final_check_callback : theory -> (unit -> bool) -> unit - val set_new_eq_callback : theory -> (ast -> ast -> unit) -> unit - val set_new_diseq_callback : theory -> (ast -> ast -> unit) -> unit - val set_new_assignment_callback : theory -> (ast -> bool -> unit) -> unit - val set_new_relevant_callback : theory -> (ast -> unit) -> unit - end diff --git a/src/api/ml/z3_stubs.c b/src/api/ml/z3_stubs.c index 0f32cb20e..0cf20fb2e 100644 --- a/src/api/ml/z3_stubs.c +++ b/src/api/ml/z3_stubs.c @@ -18,16 +18,13 @@ #define xstr(s) str(s) #define str(s) #s -#pragma warning(disable:4090) void check_error_code (Z3_context c); - Z3_context last_ctx; - + // caml_final_register is the implementation of Gc.finalize value caml_final_register (value f, value v); - void register_finalizer(value** closure, char* name, Z3_context ctx, value v) { if (*closure == NULL) { @@ -39,7 +36,6 @@ Z3_context last_ctx; } caml_final_register(**closure, v); } - value c2ml_Z3_context (Z3_context* c) { static value* finalize_Z3_context_closure = NULL; @@ -50,13 +46,11 @@ Z3_context last_ctx; (Z3_context) *c, v); return v; } - void ml2c_Z3_context (value v, Z3_context* c) { *c = (Z3_context) Field(v, 0); last_ctx = *c; } - value finalize_Z3_context (value v) { Z3_context c; @@ -87,17 +81,15 @@ typedef struct _Z3_ast_context { Z3_ast ast; Z3_context ctx; } Z3_ast_context; - void ml2c_Z3_ast (value v, Z3_ast* c) { *c = ((Z3_ast_context*) Data_custom_val(v))->ast; } - static int compare_Z3_ast (value v1, value v2) { Z3_ast_context* ac1; Z3_ast_context* ac2; - unsigned int id1, id2; + unsigned id1, id2; ac1 = Data_custom_val(v1); ac2 = Data_custom_val(v2); id1 = Z3_get_ast_id(ac1->ctx, ac1->ast); @@ -106,11 +98,10 @@ static int compare_Z3_ast (value v1, value v2) check_error_code(ac2->ctx); return id2 - id1; } - static intnat hash_Z3_ast (value v) { Z3_ast_context* ac; - unsigned int hash; + unsigned hash; ac = Data_custom_val(v); hash = Z3_get_ast_hash(ac->ctx, ac->ast); check_error_code(ac->ctx); @@ -126,7 +117,6 @@ static intnat hash_Z3_ast (value v) check_error_code(ac->ctx); return Val_unit; } - static struct custom_operations cops_Z3_ast = { NULL, custom_finalize_default, @@ -135,7 +125,6 @@ static intnat hash_Z3_ast (value v) custom_serialize_default, custom_deserialize_default }; - value c2ml_Z3_ast (Z3_ast* c) { static value* finalize_Z3_ast_closure = NULL; @@ -156,7 +145,7 @@ static intnat hash_Z3_ast (value v) #define camlidl_c2ml_z3_Z3_ast(c,ctx) c2ml_Z3_ast(c) -#define DEFINE_SUBAST_OPS(T) void ml2c_ ## T (value v, T * a) { ml2c_Z3_ast(v, (Z3_ast*) a); } value c2ml_ ## T (T * a) { return c2ml_Z3_ast((Z3_ast*) a); } +#define DEFINE_SUBAST_OPS(T) void ml2c_ ## T (value v, T * a) { ml2c_Z3_ast(v, (Z3_ast*) a); } value c2ml_ ## T (T * a) { return c2ml_Z3_ast((Z3_ast*) a); } DEFINE_SUBAST_OPS(Z3_sort) #define camlidl_ml2c_z3_Z3_sort(v,c,ctx) ml2c_Z3_sort(v,c) @@ -177,7 +166,7 @@ DEFINE_SUBAST_OPS(Z3_pattern) #define camlidl_c2ml_z3_Z3_pattern(c,ctx) c2ml_Z3_pattern(c) -#define DEFINE_RC_OPS(T) value c2ml_ ## T (T * c) { static value* finalize_ ## T ## _closure = NULL; value v; check_error_code(last_ctx); v = caml_alloc_small(2, Abstract_tag); Field(v, 0) = (value) *c; Field(v, 1) = (value) last_ctx; register_finalizer(&finalize_ ## T ## _closure, xstr(finalize_ ## T), (Z3_context) *c, v); T ## _inc_ref(last_ctx, *c); return v; } void ml2c_ ## T (value v, T * c) { *c = (T) Field(v, 0); } value finalize_ ## T (value v) { Z3_context c; c = (Z3_context) Field(v, 1); T ## _dec_ref(c, (T) Field(v, 0)); check_error_code(c); return Val_unit; } + #define DEFINE_RC_OPS(T) value c2ml_ ## T (T * c) { static value* finalize_ ## T ## _closure = NULL; value v; check_error_code(last_ctx); v = caml_alloc_small(2, Abstract_tag); Field(v, 0) = (value) *c; Field(v, 1) = (value) last_ctx; register_finalizer(&finalize_ ## T ## _closure, xstr(finalize_ ## T), (Z3_context) *c, v); T ## _inc_ref(last_ctx, *c); return v; } void ml2c_ ## T (value v, T * c) { *c = (T) Field(v, 0); } value finalize_ ## T (value v) { Z3_context c; c = (Z3_context) Field(v, 1); T ## _dec_ref(c, (T) Field(v, 0)); check_error_code(c); return Val_unit; } DEFINE_RC_OPS(Z3_params) #define camlidl_ml2c_z3_Z3_params(v,c,ctx) ml2c_Z3_params(v,c) @@ -248,7 +237,7 @@ DEFINE_RC_OPS(Z3_stats) #define camlidl_c2ml_z3_Z3_stats(c,ctx) c2ml_Z3_stats(c) -#define DEFINE_OPT_OPS(T) void ml2c_ ## T ## _opt (value v, T* c) { struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; if (v != Val_int(0)) { camlidl_ml2c_z3_ ## T(Field(v, 0), c, _ctx); } else { *c = NULL; } } value c2ml_ ## T ## _opt (T* c) { struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; value v; value a; if (*c) { a = camlidl_c2ml_z3_ ## T(c, _ctx); Begin_root(a) v = caml_alloc_small(1, 0); Field(v, 0) = a; End_roots(); } else { v = Val_int(0); } return v; } +#define DEFINE_OPT_OPS(T) void ml2c_ ## T ## _opt (value v, T* c) { struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; if (v != Val_int(0)) { camlidl_ml2c_z3_ ## T(Field(v, 0), c, _ctx); } else { *c = NULL; } } value c2ml_ ## T ## _opt (T* c) { struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; value v; value a; if (*c) { a = camlidl_c2ml_z3_ ## T(c, _ctx); Begin_root(a) v = caml_alloc_small(1, 0); Field(v, 0) = a; End_roots(); } else { v = Val_int(0); } return v; } DEFINE_OPT_OPS(Z3_ast) #define camlidl_ml2c_z3_Z3_ast_opt(v,c,ctx) ml2c_Z3_ast_opt(v,c) @@ -682,9 +671,12 @@ value _v1; } +/* All contexts share the same handler */ +static value caml_z3_error_handler = 0; + + value camlidl_c2ml_z3_Z3_error_code(Z3_error_code * _c2, camlidl_ctx _ctx); - - +/* Error checking routine that raises OCaml Error exceptions */ void check_error_code (Z3_context c) { static struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; @@ -703,8 +695,7 @@ void check_error_code (Z3_context c) caml_raise_with_args(*exn_tag, 2, ctx_err); } } - - +/* Disable default error handler, all error checking is done by check_error_code */ void* error_handler_static = NULL; int camlidl_transl_table_z3_enum_11[4] = { @@ -743,9 +734,7 @@ value caml_z3_mk_context(value key_val_list) Z3_context _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - cfg = Z3_mk_config(); - while (key_val_list != Val_emptylist) { item = Field(key_val_list, 0); @@ -756,7 +745,6 @@ value caml_z3_mk_context(value key_val_list) Z3_set_param_value(cfg, ckey, cval); key_val_list = Field(key_val_list, 1); } - _res = Z3_mk_context_rc(cfg); Z3_del_config(cfg); _vres = camlidl_c2ml_z3_Z3_context(&_res, _ctx); @@ -1238,7 +1226,7 @@ value camlidl_z3_Z3_mk_finite_domain_sort( { Z3_context c; /*in*/ Z3_symbol name; /*in*/ - __int64 size; /*in*/ + unsigned long long size; /*in*/ Z3_sort _res; value _vres; @@ -4286,7 +4274,7 @@ value camlidl_z3_Z3_mk_int64( value _v_ty) { Z3_context c; /*in*/ - __int64 v; /*in*/ + long long v; /*in*/ Z3_sort ty; /*in*/ Z3_ast _res; value _vres; @@ -5105,8 +5093,8 @@ value camlidl_z3_Z3_get_finite_domain_sort_size( { Z3_context c; /*in*/ Z3_sort s; /*in*/ - __int64 *r; /*out*/ - __int64 _c1; + unsigned long long *r; /*out*/ + unsigned long long _c1; value _v2; value _vres; @@ -6273,13 +6261,13 @@ value camlidl_z3_Z3_get_numeral_small( { Z3_context c; /*in*/ Z3_ast a; /*in*/ - __int64 *num; /*out*/ - __int64 *den; /*out*/ + long long *num; /*out*/ + long long *den; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; - __int64 _c2; + long long _c1; + long long _c2; value _vresult; value _vres[3] = { 0, 0, 0, }; @@ -6342,11 +6330,11 @@ value camlidl_z3_Z3_get_numeral_int64( { Z3_context c; /*in*/ Z3_ast v; /*in*/ - __int64 *i; /*out*/ + long long *i; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; + long long _c1; value _vresult; value _vres[2] = { 0, 0, }; @@ -6374,13 +6362,13 @@ value camlidl_z3_Z3_get_numeral_rational_int64( { Z3_context c; /*in*/ Z3_ast v; /*in*/ - __int64 *num; /*out*/ - __int64 *den; /*out*/ + long long *num; /*out*/ + long long *den; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; - __int64 _c2; + long long _c1; + long long _c2; value _vresult; value _vres[3] = { 0, 0, 0, }; @@ -8170,50 +8158,6 @@ check_error_code(c); return _vres; } -value camlidl_z3_Z3_parse_z3_string( - value _v_c, - value _v_str) -{ - Z3_context c; /*in*/ - Z3_string str; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_str, &str, _ctx); - _res = Z3_parse_z3_string(c, str); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - -value camlidl_z3_Z3_parse_z3_file( - value _v_c, - value _v_file_name) -{ - Z3_context c; /*in*/ - Z3_string file_name; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3_Z3_string(_v_file_name, &file_name, _ctx); - _res = Z3_parse_z3_file(c, file_name); - _vres = camlidl_c2ml_z3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - /* begin user-supplied deallocation sequence */ -check_error_code(c); - /* end user-supplied deallocation sequence */ - return _vres; -} - value camlidl_z3_Z3_set_error( value _v_c, value _v_e) @@ -8286,6 +8230,30 @@ value camlidl_z3_Z3_get_version(value _unit) return _vresult; } +value camlidl_z3_Z3_enable_trace( + value _v_tag) +{ + Z3_string tag; /*in*/ + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + camlidl_ml2c_z3_Z3_string(_v_tag, &tag, _ctx); + Z3_enable_trace(tag); + camlidl_free(_ctx); + return Val_unit; +} + +value camlidl_z3_Z3_disable_trace( + value _v_tag) +{ + Z3_string tag; /*in*/ + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + camlidl_ml2c_z3_Z3_string(_v_tag, &tag, _ctx); + Z3_disable_trace(tag); + camlidl_free(_ctx); + return Val_unit; +} + value camlidl_z3_Z3_mk_fixedpoint( value _v_c) { @@ -8669,46 +8637,42 @@ check_error_code(c); return Val_unit; } -value camlidl_z3_Z3_fixedpoint_simplify_rules( +value camlidl_z3_Z3_fixedpoint_get_rules( value _v_c, - value _v_f, - value _v_rules, - value _v_outputs) + value _v_f) { Z3_context c; /*in*/ Z3_fixedpoint f; /*in*/ - unsigned int num_rules; /*in*/ - Z3_ast *rules; /*in*/ - unsigned int num_outputs; /*in*/ - Z3_func_decl *outputs; /*in*/ Z3_ast_vector _res; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - mlsize_t _c5; - value _v6; value _vres; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); - _c1 = Wosize_val(_v_rules); - rules = camlidl_malloc(_c1 * sizeof(Z3_ast ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_rules, _c2); - camlidl_ml2c_z3_Z3_ast(_v3, &rules[_c2], _ctx); - } - num_rules = _c1; - _c4 = Wosize_val(_v_outputs); - outputs = camlidl_malloc(_c4 * sizeof(Z3_func_decl ), _ctx); - for (_c5 = 0; _c5 < _c4; _c5++) { - _v6 = Field(_v_outputs, _c5); - camlidl_ml2c_z3_Z3_func_decl(_v6, &outputs[_c5], _ctx); - } - num_outputs = _c4; - _res = Z3_fixedpoint_simplify_rules(c, f, num_rules, rules, num_outputs, outputs); + _res = Z3_fixedpoint_get_rules(c, f); + _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); + camlidl_free(_ctx); + /* begin user-supplied deallocation sequence */ +check_error_code(c); + /* end user-supplied deallocation sequence */ + return _vres; +} + +value camlidl_z3_Z3_fixedpoint_get_assertions( + value _v_c, + value _v_f) +{ + Z3_context c; /*in*/ + Z3_fixedpoint f; /*in*/ + Z3_ast_vector _res; + value _vres; + + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); + camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); + _res = Z3_fixedpoint_get_assertions(c, f); _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); camlidl_free(_ctx); /* begin user-supplied deallocation sequence */ @@ -8817,6 +8781,56 @@ check_error_code(c); return _vres; } +value camlidl_z3_Z3_fixedpoint_from_string( + value _v_c, + value _v_f, + value _v_s) +{ + Z3_context c; /*in*/ + Z3_fixedpoint f; /*in*/ + Z3_string s; /*in*/ + Z3_ast_vector _res; + value _vres; + + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); + camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); + camlidl_ml2c_z3_Z3_string(_v_s, &s, _ctx); + _res = Z3_fixedpoint_from_string(c, f, s); + _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); + camlidl_free(_ctx); + /* begin user-supplied deallocation sequence */ +check_error_code(c); + /* end user-supplied deallocation sequence */ + return _vres; +} + +value camlidl_z3_Z3_fixedpoint_from_file( + value _v_c, + value _v_f, + value _v_s) +{ + Z3_context c; /*in*/ + Z3_fixedpoint f; /*in*/ + Z3_string s; /*in*/ + Z3_ast_vector _res; + value _vres; + + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); + camlidl_ml2c_z3_Z3_fixedpoint(_v_f, &f, _ctx); + camlidl_ml2c_z3_Z3_string(_v_s, &s, _ctx); + _res = Z3_fixedpoint_from_file(c, f, s); + _vres = camlidl_c2ml_z3_Z3_ast_vector(&_res, _ctx); + camlidl_free(_ctx); + /* begin user-supplied deallocation sequence */ +check_error_code(c); + /* end user-supplied deallocation sequence */ + return _vres; +} + value camlidl_z3_Z3_fixedpoint_push( value _v_c, value _v_d) @@ -10692,6 +10706,30 @@ check_error_code(c); return Val_unit; } +value camlidl_z3_Z3_solver_assert_and_track( + value _v_c, + value _v_s, + value _v_a, + value _v_p) +{ + Z3_context c; /*in*/ + Z3_solver s; /*in*/ + Z3_ast a; /*in*/ + Z3_ast p; /*in*/ + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); + camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); + camlidl_ml2c_z3_Z3_ast(_v_a, &a, _ctx); + camlidl_ml2c_z3_Z3_ast(_v_p, &p, _ctx); + Z3_solver_assert_and_track(c, s, a, p); + camlidl_free(_ctx); + /* begin user-supplied deallocation sequence */ +check_error_code(c); + /* end user-supplied deallocation sequence */ + return Val_unit; +} + value camlidl_z3_Z3_solver_get_assertions( value _v_c, value _v_s) @@ -11072,7 +11110,6 @@ check_error_code(c); return _vres; } -void caml_z3_error_handler(Z3_context c, Z3_error_code e) { static char buffer[128]; char * msg = Z3_get_error_msg_ex(c, e); if (strlen(msg) > 100) { failwith("Z3: error message is too big to fit in buffer"); } else { sprintf(buffer, "Z3: %s", msg); failwith(buffer); } } void camlidl_ml2c_z3V3_Z3_symbol(value _v1, Z3_symbol * _c2, camlidl_ctx _ctx) { *_c2 = *((Z3_symbol *) Bp_val(_v1)); @@ -11604,6 +11641,54 @@ value _v1; return _v1; } +value camlidl_z3V3_Z3_global_param_set( + value _v_param_id, + value _v_param_value) +{ + Z3_string param_id; /*in*/ + Z3_string param_value; /*in*/ + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + camlidl_ml2c_z3V3_Z3_string(_v_param_id, ¶m_id, _ctx); + camlidl_ml2c_z3V3_Z3_string(_v_param_value, ¶m_value, _ctx); + Z3_global_param_set(param_id, param_value); + camlidl_free(_ctx); + return Val_unit; +} + +value camlidl_z3V3_Z3_global_param_reset_all(value _unit) +{ + Z3_global_param_reset_all(); + return Val_unit; +} + +value camlidl_z3V3_Z3_global_param_get( + value _v_param_id) +{ + Z3_string param_id; /*in*/ + Z3_string *param_value; /*out*/ + Z3_string _c1; + value _v2; + value _vres; + + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + camlidl_ml2c_z3V3_Z3_string(_v_param_id, ¶m_id, _ctx); + param_value = &_c1; + Z3_global_param_get(param_id, param_value); + if (param_value == NULL) { + _vres = Val_int(0); + } else { + _v2 = camlidl_c2ml_z3V3_Z3_string(&*param_value, _ctx); + Begin_root(_v2) + _vres = camlidl_alloc_small(1, 0); + Field(_vres, 0) = _v2; + End_roots(); + } + camlidl_free(_ctx); + return _vres; +} + value camlidl_z3V3_Z3_mk_config(value _unit) { Z3_config _res; @@ -11661,7 +11746,7 @@ value camlidl_z3V3_Z3_mk_context( _vres = camlidl_c2ml_z3V3_Z3_context(&_res, _ctx); camlidl_free(_ctx); /* begin user-supplied deallocation sequence */ -Z3_set_error_handler(_res, caml_z3_error_handler); +Z3_set_error_handler(_res, (void*)caml_z3_error_handler); /* end user-supplied deallocation sequence */ return _vres; } @@ -11857,7 +11942,7 @@ value camlidl_z3V3_Z3_mk_finite_domain_sort( { Z3_context c; /*in*/ Z3_symbol name; /*in*/ - __int64 size; /*in*/ + unsigned long long size; /*in*/ Z3_sort _res; value _vres; @@ -14575,7 +14660,7 @@ value camlidl_z3V3_Z3_mk_int64( value _v_ty) { Z3_context c; /*in*/ - __int64 v; /*in*/ + long long v; /*in*/ Z3_sort ty; /*in*/ Z3_ast _res; value _vres; @@ -15334,8 +15419,8 @@ value camlidl_z3V3_Z3_get_finite_domain_sort_size( { Z3_context c; /*in*/ Z3_sort s; /*in*/ - __int64 *r; /*out*/ - __int64 _c1; + unsigned long long *r; /*out*/ + unsigned long long _c1; value _v2; value _vres; @@ -16352,13 +16437,13 @@ value camlidl_z3V3_Z3_get_numeral_small( { Z3_context c; /*in*/ Z3_ast a; /*in*/ - __int64 *num; /*out*/ - __int64 *den; /*out*/ + long long *num; /*out*/ + long long *den; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; - __int64 _c2; + long long _c1; + long long _c2; value _vresult; value _vres[3] = { 0, 0, 0, }; @@ -16415,11 +16500,11 @@ value camlidl_z3V3_Z3_get_numeral_int64( { Z3_context c; /*in*/ Z3_ast v; /*in*/ - __int64 *i; /*out*/ + long long *i; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; + long long _c1; value _vresult; value _vres[2] = { 0, 0, }; @@ -16444,13 +16529,13 @@ value camlidl_z3V3_Z3_get_numeral_rational_int64( { Z3_context c; /*in*/ Z3_ast v; /*in*/ - __int64 *num; /*out*/ - __int64 *den; /*out*/ + long long *num; /*out*/ + long long *den; /*out*/ int _res; struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; camlidl_ctx _ctx = &_ctxs; - __int64 _c1; - __int64 _c2; + long long _c1; + long long _c2; value _vresult; value _vres[3] = { 0, 0, 0, }; @@ -17570,44 +17655,6 @@ value camlidl_z3V3_Z3_get_smtlib_error( return _vres; } -value camlidl_z3_Z3_parse_z3V3_string( - value _v_c, - value _v_str) -{ - Z3_context c; /*in*/ - Z3_string str; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_str, &str, _ctx); - _res = Z3_parse_z3_string(c, str); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - -value camlidl_z3_Z3_parse_z3V3_file( - value _v_c, - value _v_file_name) -{ - Z3_context c; /*in*/ - Z3_string file_name; /*in*/ - Z3_ast _res; - value _vres; - - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - camlidl_ml2c_z3V3_Z3_string(_v_file_name, &file_name, _ctx); - _res = Z3_parse_z3_file(c, file_name); - _vres = camlidl_c2ml_z3V3_Z3_ast(&_res, _ctx); - camlidl_free(_ctx); - return _vres; -} - value camlidl_z3V3_Z3_get_version(value _unit) { unsigned int *major; /*out*/ @@ -17640,6 +17687,30 @@ value camlidl_z3V3_Z3_get_version(value _unit) return _vresult; } +value camlidl_z3V3_Z3_enable_trace( + value _v_tag) +{ + Z3_string tag; /*in*/ + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + camlidl_ml2c_z3V3_Z3_string(_v_tag, &tag, _ctx); + Z3_enable_trace(tag); + camlidl_free(_ctx); + return Val_unit; +} + +value camlidl_z3V3_Z3_disable_trace( + value _v_tag) +{ + Z3_string tag; /*in*/ + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + camlidl_ml2c_z3V3_Z3_string(_v_tag, &tag, _ctx); + Z3_disable_trace(tag); + camlidl_free(_ctx); + return Val_unit; +} + value camlidl_z3V3_Z3_reset_memory(value _unit) { Z3_reset_memory(); From 3cefa0a1f76a4ce1cfe53fe5782aa8d061691535 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Wed, 5 Dec 2012 16:53:54 -0800 Subject: [PATCH 06/60] making tests deterministic Signed-off-by: Leonardo de Moura --- src/api/python/z3.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index e690a9bff..6517de221 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -5787,8 +5787,15 @@ class Solver(Z3PPObject): >>> s.assert_and_track(x < 0, p3) >>> print s.check() unsat - >>> print s.unsat_core() - [p3, p1] + >>> c = s.unsat_core() + >>> len(c) + 2 + >>> Bool('p1') in c + True + >>> Bool('p2') in c + False + >>> p3 in c + True """ if isinstance(p, str): p = Bool(p, self.ctx) @@ -6985,9 +6992,9 @@ def solve(*args, **keywords): configure it using the options in `keywords`, adds the constraints in `args`, and invokes check. - >>> a, b = Ints('a b') - >>> solve(a + b == 3, Or(a == 0, a == 1), a != 0) - [b = 2, a = 1] + >>> a = Int('a') + >>> solve(a > 0, a < 2) + [a = 1] """ s = Solver() s.set(**keywords) From 6bdde9047aae6b0b12ea85b19f6c6218a0e8f5e6 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 5 Dec 2012 12:01:03 -0800 Subject: [PATCH 07/60] fixing unit tests Signed-off-by: Nikolaj Bjorner --- src/muz_qe/rel_context.h | 3 +-- src/smt/smt_model_checker.cpp | 1 + src/test/dl_context.cpp | 2 +- src/test/dl_product_relation.cpp | 9 +++++---- src/test/dl_query.cpp | 8 ++++---- src/test/dl_relation.cpp | 4 ++-- src/test/dl_table.cpp | 4 ++-- 7 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/muz_qe/rel_context.h b/src/muz_qe/rel_context.h index 5fa2486b4..b05532d14 100644 --- a/src/muz_qe/rel_context.h +++ b/src/muz_qe/rel_context.h @@ -41,8 +41,6 @@ namespace datalog { fact_vector m_table_facts; void reset_negated_tables(); - - lbool saturate(); relation_plugin & get_ordinary_relation_plugin(symbol relation_name); @@ -109,6 +107,7 @@ namespace datalog { void display_output_facts(std::ostream & out) const; void display_facts(std::ostream & out) const; + lbool saturate(); }; }; diff --git a/src/smt/smt_model_checker.cpp b/src/smt/smt_model_checker.cpp index 53f3af961..cefdacef5 100644 --- a/src/smt/smt_model_checker.cpp +++ b/src/smt/smt_model_checker.cpp @@ -283,6 +283,7 @@ namespace smt { if (!m_fparams) { m_fparams = alloc(smt_params, m_context->get_fparams()); m_fparams->m_relevancy_lvl = 0; // no relevancy since the model checking problems are quantifier free + m_fparams->m_proof_mode = m_manager.proof_mode(); } if (!m_aux_context) { symbol logic; diff --git a/src/test/dl_context.cpp b/src/test/dl_context.cpp index ff7548abc..d5fcddb71 100644 --- a/src/test/dl_context.cpp +++ b/src/test/dl_context.cpp @@ -60,7 +60,7 @@ void dl_context_saturate_file(params_ref & params, const char * f) { } dealloc(parser); std::cerr << "Saturating...\n"; - ctx.dl_saturate(); + ctx.get_rel_context().saturate(); std::cerr << "Done\n"; } diff --git a/src/test/dl_product_relation.cpp b/src/test/dl_product_relation.cpp index e58634ec8..ef43258ad 100644 --- a/src/test/dl_product_relation.cpp +++ b/src/test/dl_product_relation.cpp @@ -22,11 +22,12 @@ namespace datalog { void test_functional_columns(smt_params fparams, params_ref& params) { ast_manager m; context ctx(m, fparams); + rel_context& rctx = ctx.get_rel_context(); ctx.updt_params(params); - relation_manager & rmgr(ctx.get_rmanager()); + relation_manager & rmgr(rctx.get_rmanager()); sparse_table_plugin & plugin = - static_cast(*ctx.get_rmanager().get_table_plugin(symbol("sparse"))); + static_cast(*rctx.get_rmanager().get_table_plugin(symbol("sparse"))); SASSERT(&plugin); table_signature sig2; sig2.push_back(2); @@ -126,9 +127,9 @@ namespace datalog { context ctx(m, fparams); ctx.updt_params(params); dl_decl_util dl_util(m); - relation_manager & rmgr = ctx.get_rmanager(); + relation_manager & rmgr = ctx.get_rel_context().get_rmanager(); - relation_plugin & rel_plugin = *ctx.get_rmanager().get_relation_plugin(params.get_sym("default_relation", symbol("sparse"))); + relation_plugin & rel_plugin = *rmgr.get_relation_plugin(params.get_sym("default_relation", symbol("sparse"))); SASSERT(&rel_plugin); finite_product_relation_plugin plg(rel_plugin, rmgr); diff --git a/src/test/dl_query.cpp b/src/test/dl_query.cpp index ad21247af..4dc770056 100644 --- a/src/test/dl_query.cpp +++ b/src/test/dl_query.cpp @@ -57,7 +57,7 @@ void dl_query_test(ast_manager & m, smt_params & fparams, params_ref& params, TRUSTME( p->parse_file(problem_file) ); dealloc(p); } - relation_manager & rel_mgr_q = ctx_b.get_rmanager(); + relation_manager & rel_mgr_q = ctx_b.get_rel_context().get_rmanager(); decl_set out_preds = ctx_b.get_output_predicates(); decl_set::iterator it = out_preds.begin(); @@ -68,10 +68,10 @@ void dl_query_test(ast_manager & m, smt_params & fparams, params_ref& params, func_decl * pred_q = ctx_q.try_get_predicate_decl(symbol(pred_b->get_name().bare_str())); SASSERT(pred_q); - relation_base & rel_b = ctx_b.get_relation(pred_b); + relation_base & rel_b = ctx_b.get_rel_context().get_relation(pred_b); relation_signature sig_b = rel_b.get_signature(); - relation_signature sig_q = ctx_q.get_relation(pred_q).get_signature(); + relation_signature sig_q = ctx_q.get_rel_context().get_relation(pred_q).get_signature(); SASSERT(sig_b.size()==sig_q.size()); std::cerr << "Queries on random facts...\n"; @@ -209,7 +209,7 @@ void tst_dl_query() { TRUSTME( p->parse_file(problem_file) ); dealloc(p); } - ctx_base.dl_saturate(); + ctx_base.get_rel_context().saturate(); for(unsigned use_restarts=0; use_restarts<=1; use_restarts++) { params.set_uint("initial_restart_timeout", use_restarts ? 100 : 0); diff --git a/src/test/dl_relation.cpp b/src/test/dl_relation.cpp index fe8ba1730..5daf3dc9b 100644 --- a/src/test/dl_relation.cpp +++ b/src/test/dl_relation.cpp @@ -12,7 +12,7 @@ namespace datalog { ast_manager ast_m; context ctx(ast_m, params); arith_util autil(ast_m); - relation_manager & m = ctx.get_rmanager(); + relation_manager & m = ctx.get_rel_context().get_rmanager(); m.register_plugin(alloc(interval_relation_plugin, m)); interval_relation_plugin& ip = dynamic_cast(*m.get_relation_plugin(symbol("interval_relation"))); SASSERT(&ip); @@ -115,7 +115,7 @@ namespace datalog { ast_manager ast_m; context ctx(ast_m, params); arith_util autil(ast_m); - relation_manager & m = ctx.get_rmanager(); + relation_manager & m = ctx.get_rel_context().get_rmanager(); m.register_plugin(alloc(bound_relation_plugin, m)); bound_relation_plugin& br = dynamic_cast(*m.get_relation_plugin(symbol("bound_relation"))); SASSERT(&br); diff --git a/src/test/dl_table.cpp b/src/test/dl_table.cpp index 6383dc1ab..0c8afcdc2 100644 --- a/src/test/dl_table.cpp +++ b/src/test/dl_table.cpp @@ -27,9 +27,9 @@ static void test_table(mk_table_fn mk_table) { smt_params params; ast_manager ast_m; datalog::context ctx(ast_m, params); - datalog::relation_manager & m = ctx.get_rmanager(); + datalog::relation_manager & m = ctx.get_rel_context().get_rmanager(); - ctx.get_rmanager().register_plugin(alloc(datalog::bitvector_table_plugin, ctx.get_rmanager())); + m.register_plugin(alloc(datalog::bitvector_table_plugin, m)); datalog::table_base* _tbl = mk_table(m, sig); datalog::table_base& table = *_tbl; From dbde71c2905db352dbb83d8b5e177aa68e6762ea Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 5 Dec 2012 12:05:07 -0800 Subject: [PATCH 08/60] fixing unit tests Signed-off-by: Nikolaj Bjorner --- src/smt/smt_model_checker.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/smt/smt_model_checker.cpp b/src/smt/smt_model_checker.cpp index cefdacef5..53f3af961 100644 --- a/src/smt/smt_model_checker.cpp +++ b/src/smt/smt_model_checker.cpp @@ -283,7 +283,6 @@ namespace smt { if (!m_fparams) { m_fparams = alloc(smt_params, m_context->get_fparams()); m_fparams->m_relevancy_lvl = 0; // no relevancy since the model checking problems are quantifier free - m_fparams->m_proof_mode = m_manager.proof_mode(); } if (!m_aux_context) { symbol logic; From 75739fdf7b35e79f6403c5c28c28340c7019ff7f Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 6 Dec 2012 08:19:42 -0800 Subject: [PATCH 09/60] fixed memory smash Signed-off-by: Leonardo de Moura --- src/ast/rewriter/th_rewriter.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ast/rewriter/th_rewriter.cpp b/src/ast/rewriter/th_rewriter.cpp index 07ee7698d..29034d396 100644 --- a/src/ast/rewriter/th_rewriter.cpp +++ b/src/ast/rewriter/th_rewriter.cpp @@ -483,10 +483,13 @@ struct th_rewriter_cfg : public default_rewriter_cfg { f = to_app(t1)->get_decl(); return unify_core(to_app(t1), t2, new_t1, new_t2, c, first); } - else { + else if (is_arith_bv_app(t2)) { f = to_app(t2)->get_decl(); return unify_core(to_app(t2), t1, new_t2, new_t1, c, first); } + else { + return false; + } } // Apply transformations of the form From 68b97024e2638317d3980308c1eb65d3299ad2cd Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 6 Dec 2012 08:54:00 -0800 Subject: [PATCH 10/60] added missing option Signed-off-by: Leonardo de Moura --- src/smt/params/preprocessor_params.cpp | 3 ++- src/smt/params/smt_params_helper.pyg | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/smt/params/preprocessor_params.cpp b/src/smt/params/preprocessor_params.cpp index 375fef787..4799b8b9f 100644 --- a/src/smt/params/preprocessor_params.cpp +++ b/src/smt/params/preprocessor_params.cpp @@ -21,7 +21,8 @@ Revision History: void preprocessor_params::updt_local_params(params_ref const & _p) { smt_params_helper p(_p); - m_macro_finder = p.macro_finder(); + m_macro_finder = p.macro_finder(); + m_pull_nested_quantifiers = p.pull_nested_quantifiers(); } void preprocessor_params::updt_params(params_ref const & p) { diff --git a/src/smt/params/smt_params_helper.pyg b/src/smt/params/smt_params_helper.pyg index ee583ff85..071d843a3 100644 --- a/src/smt/params/smt_params_helper.pyg +++ b/src/smt/params/smt_params_helper.pyg @@ -13,6 +13,7 @@ def_module_params(module_name='smt', ('case_split', UINT, 1, '0 - case split based on variable activity, 1 - similar to 0, but delay case splits created during the search, 2 - similar to 0, but cache the relevancy, 3 - case split based on relevancy (structural splitting), 4 - case split on relevancy and activity, 5 - case split on relevancy and current goal'), ('delay_units', BOOL, False, 'if true then z3 will not restart when a unit clause is learned'), ('delay_units_threshold', UINT, 32, 'maximum number of learned unit clauses before restarting, ingored if delay_units is false'), + ('pull_nested_quantifiers', BOOL, False, 'pull nested quantifiers'), ('mbqi', BOOL, True, 'model based quantifier instantiation (MBQI)'), ('mbqi.max_cexs', UINT, 1, 'initial maximal number of counterexamples used in MBQI, each counterexample generates a quantifier instantiation'), ('mbqi.max_cexs_incr', UINT, 0, 'increment for MBQI_MAX_CEXS, the increment is performed after each round of MBQI'), From fdb3e225605f478435570c818083b6df7f44e681 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 6 Dec 2012 13:57:35 -0800 Subject: [PATCH 11/60] fixed mk_make problem on Windows Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 98fae665a..3605537fd 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -88,6 +88,9 @@ def is_osx(): def unix_path2dos(path): return string.join(path.split('/'), '\\') +def to_unix_path(path): + return string.join(path.split('\\'), '/') + def which(program): import os def is_exe(fpath): @@ -440,7 +443,7 @@ def extract_c_includes(fname): # Given a path dir1/subdir2/subdir3 returns ../../.. def reverse_path(p): - l = p.split('/') + l = to_unix_path(p).split('/') n = len(l) r = '..' for i in range(1, n): From db6e20b2ea48d34069737c535bd5a5e4ea9a8740 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 6 Dec 2012 14:57:07 -0800 Subject: [PATCH 12/60] cleaning mk_make Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 234 ++++++++++++++++++++++----------------------- 1 file changed, 117 insertions(+), 117 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 3605537fd..8c727e0ec 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -447,7 +447,7 @@ def reverse_path(p): n = len(l) r = '..' for i in range(1, n): - r = '%s/%s' % (r, '..') + r = os.path.join(r, '..') return r def mk_dir(d): @@ -461,7 +461,7 @@ def set_build_dir(d): def set_z3py_dir(p): global SRC_DIR, Z3PY_SRC_DIR - full = '%s/%s' % (SRC_DIR, p) + full = os.path.join(SRC_DIR, p) if not os.path.exists(full): raise MKException("Python bindings directory '%s' does not exist" % full) Z3PY_SRC_DIR = full @@ -562,19 +562,19 @@ class Component: self.path = path self.deps = find_all_deps(name, deps) self.build_dir = path - self.src_dir = '%s/%s' % (SRC_DIR, path) - self.to_src_dir = '%s/%s' % (REV_BUILD_DIR, self.src_dir) + self.src_dir = os.path.join(SRC_DIR, path) + self.to_src_dir = os.path.join(REV_BUILD_DIR, self.src_dir) # Find fname in the include paths for the given component. # ownerfile is only used for creating error messages. # That is, we were looking for fname when processing ownerfile def find_file(self, fname, ownerfile): - full_fname = '%s/%s' % (self.src_dir, fname) + full_fname = os.path.join(self.src_dir, fname) if os.path.exists(full_fname): return self for dep in self.deps: c_dep = get_component(dep) - full_fname = '%s/%s' % (c_dep.src_dir, fname) + full_fname = os.path.join(c_dep.src_dir, fname) if os.path.exists(full_fname): return c_dep raise MKException("Failed to find include file '%s' for '%s' when processing '%s'." % (fname, ownerfile, self.name)) @@ -582,15 +582,15 @@ class Component: # Display all dependencies of file basename located in the given component directory. # The result is displayed at out def add_cpp_h_deps(self, out, basename): - includes = extract_c_includes('%s/%s' % (self.src_dir, basename)) - out.write('%s/%s' % (self.to_src_dir, basename)) + includes = extract_c_includes(os.path.join(self.src_dir, basename)) + out.write(os.path.join(self.to_src_dir, basename)) for include in includes: owner = self.find_file(include, basename) - out.write(' %s/%s.node' % (owner.build_dir, include)) + out.write(' %s.node' % os.path.join(owner.build_dir, include)) # Add a rule for each #include directive in the file basename located at the current component. def add_rule_for_each_include(self, out, basename): - fullname = '%s/%s' % (self.src_dir, basename) + fullname = os.path.join(self.src_dir, basename) includes = extract_c_includes(fullname) for include in includes: owner = self.find_file(include, fullname) @@ -602,12 +602,12 @@ class Component: # ast/ast_pp.h.node : ../src/util/ast_pp.h util/util.h.node ast/ast.h.node # @echo "done" > ast/ast_pp.h.node def add_h_rule(self, out, include): - include_src_path = '%s/%s' % (self.to_src_dir, include) + include_src_path = os.path.join(self.to_src_dir, include) if include_src_path in _Processed_Headers: return _Processed_Headers.add(include_src_path) self.add_rule_for_each_include(out, include) - include_node = '%s/%s.node' % (self.build_dir, include) + include_node = '%s.node' % os.path.join(self.build_dir, include) out.write('%s: ' % include_node) self.add_cpp_h_deps(out, include) out.write('\n') @@ -615,13 +615,13 @@ class Component: def add_cpp_rules(self, out, include_defs, cppfile): self.add_rule_for_each_include(out, cppfile) - objfile = '%s/%s$(OBJ_EXT)' % (self.build_dir, os.path.splitext(cppfile)[0]) - srcfile = '%s/%s' % (self.to_src_dir, cppfile) + objfile = '%s$(OBJ_EXT)' % os.path.join(self.build_dir, os.path.splitext(cppfile)[0]) + srcfile = os.path.join(self.to_src_dir, cppfile) out.write('%s: ' % objfile) self.add_cpp_h_deps(out, cppfile) out.write('\n') if SHOW_CPPS: - out.write('\t@echo %s/%s\n' % (self.src_dir, cppfile)) + out.write('\t@echo %s\n' % os.path.join(self.src_dir, cppfile)) out.write('\t@$(CXX) $(CXXFLAGS) $(%s) $(CXX_OUT_FLAG)%s %s\n' % (include_defs, objfile, srcfile)) def mk_makefile(self, out): @@ -630,7 +630,7 @@ class Component: for dep in self.deps: out.write(' -I%s' % get_component(dep).to_src_dir) out.write('\n') - mk_dir('%s/%s' % (BUILD_DIR, self.build_dir)) + mk_dir(os.path.join(BUILD_DIR, self.build_dir)) for cppfile in get_cpp_files(self.src_dir): self.add_cpp_rules(out, include_defs, cppfile) @@ -679,10 +679,10 @@ class LibComponent(Component): # generate rule for lib objs = [] for cppfile in get_cpp_files(self.src_dir): - objfile = '%s/%s$(OBJ_EXT)' % (self.build_dir, os.path.splitext(cppfile)[0]) + objfile = '%s$(OBJ_EXT)' % os.path.join(self.build_dir, os.path.splitext(cppfile)[0]) objs.append(objfile) - libfile = '%s/%s$(LIB_EXT)' % (self.build_dir, self.name) + libfile = '%s$(LIB_EXT)' % os.path.join(self.build_dir, self.name) out.write('%s:' % libfile) for obj in objs: out.write(' ') @@ -697,17 +697,17 @@ class LibComponent(Component): def mk_install(self, out): for include in self.includes2install: - out.write('\t@cp %s/%s $(PREFIX)/include/%s\n' % (self.to_src_dir, include, include)) + out.write('\t@cp %s %s\n' % (os.path.join(self.to_src_dir, include), os.path.join('$(PREFIX)', 'include', include))) def mk_uninstall(self, out): for include in self.includes2install: - out.write('\t@rm -f $(PREFIX)/include/%s\n' % include) + out.write('\t@rm -f %s\n' % os.path.join('$(PREFIX)', 'include', include)) def mk_win_dist(self, build_path, dist_path): - mk_dir('%s/include' % dist_path) + mk_dir(os.path.join(dist_path, 'include')) for include in self.includes2install: - shutil.copy('%s/%s' % (self.src_dir, include), - '%s/include/%s' % (dist_path, include)) + shutil.copy(os.path.join(self.src_dir, include), + os.path.join(dist_path, 'include', include)) # "Library" containing only .h files. This is just a placeholder for includes files to be installed. class HLibComponent(LibComponent): @@ -744,14 +744,14 @@ class ExeComponent(Component): deps = sort_components(self.deps) objs = [] for cppfile in get_cpp_files(self.src_dir): - objfile = '%s/%s$(OBJ_EXT)' % (self.build_dir, os.path.splitext(cppfile)[0]) + objfile = '%s$(OBJ_EXT)' % os.path.join(self.build_dir, os.path.splitext(cppfile)[0]) objs.append(objfile) for obj in objs: out.write(' ') out.write(obj) for dep in deps: c_dep = get_component(dep) - out.write(' %s/%s$(LIB_EXT)' % (c_dep.build_dir, c_dep.name)) + out.write(' %s$(LIB_EXT)' % os.path.join(c_dep.build_dir, c_dep.name)) out.write('\n') out.write('\t$(LINK) $(LINK_OUT_FLAG)%s $(LINK_FLAGS)' % exefile) for obj in objs: @@ -759,7 +759,7 @@ class ExeComponent(Component): out.write(obj) for dep in deps: c_dep = get_component(dep) - out.write(' %s/%s$(LIB_EXT)' % (c_dep.build_dir, c_dep.name)) + out.write(' %s$(LIB_EXT)' % os.path.join(c_dep.build_dir, c_dep.name)) out.write(' $(LINK_EXTRA_FLAGS)\n') out.write('%s: %s\n\n' % (self.name, exefile)) @@ -776,17 +776,17 @@ class ExeComponent(Component): def mk_install(self, out): if self.install: exefile = '%s$(EXE_EXT)' % self.exe_name - out.write('\t@cp %s $(PREFIX)/bin/%s\n' % (exefile, exefile)) + out.write('\t@cp %s %s\n' % (exefile, os.path.join('$(PREFIX)', 'bin', exefile))) def mk_uninstall(self, out): exefile = '%s$(EXE_EXT)' % self.exe_name - out.write('\t@rm -f $(PREFIX)/bin/%s\n' % exefile) + out.write('\t@rm -f %s\n' % os.path.join('$(PREFIX)', 'bin', exefile)) def mk_win_dist(self, build_path, dist_path): if self.install: - mk_dir('%s/bin' % dist_path) - shutil.copy('%s/%s.exe' % (build_path, self.exe_name), - '%s/bin/%s.exe' % (dist_path, self.exe_name)) + mk_dir(os.path.join(dist_path, 'bin')) + shutil.copy('%s.exe' % os.path.join(build_path, self.exe_name), + '%s.exe' % os.path.join(dist_path, 'bin', self.exe_name)) class ExtraExeComponent(ExeComponent): @@ -815,13 +815,13 @@ class DLLComponent(Component): deps = sort_components(self.deps) objs = [] for cppfile in get_cpp_files(self.src_dir): - objfile = '%s/%s$(OBJ_EXT)' % (self.build_dir, os.path.splitext(cppfile)[0]) + objfile = '%s$(OBJ_EXT)' % os.path.join(self.build_dir, os.path.splitext(cppfile)[0]) objs.append(objfile) # Explicitly include obj files of reexport. This fixes problems with exported symbols on Linux and OSX. for reexport in self.reexports: reexport = get_component(reexport) for cppfile in get_cpp_files(reexport.src_dir): - objfile = '%s/%s$(OBJ_EXT)' % (reexport.build_dir, os.path.splitext(cppfile)[0]) + objfile = '%s$(OBJ_EXT)' % os.path.join(reexport.build_dir, os.path.splitext(cppfile)[0]) objs.append(objfile) for obj in objs: out.write(' ') @@ -829,7 +829,7 @@ class DLLComponent(Component): for dep in deps: if not dep in self.reexports: c_dep = get_component(dep) - out.write(' %s/%s$(LIB_EXT)' % (c_dep.build_dir, c_dep.name)) + out.write(' %s$(LIB_EXT)' % os.path.join(c_dep.build_dir, c_dep.name)) out.write('\n') out.write('\t$(LINK) $(SLINK_OUT_FLAG)%s $(SLINK_FLAGS)' % dllfile) for obj in objs: @@ -838,10 +838,10 @@ class DLLComponent(Component): for dep in deps: if not dep in self.reexports: c_dep = get_component(dep) - out.write(' %s/%s$(LIB_EXT)' % (c_dep.build_dir, c_dep.name)) + out.write(' %s$(LIB_EXT)' % os.path.join(c_dep.build_dir, c_dep.name)) out.write(' $(SLINK_EXTRA_FLAGS)') if IS_WINDOWS: - out.write(' /DEF:%s/%s.def' % (self.to_src_dir, self.name)) + out.write(' /DEF:%s.def' % os.path.join(self.to_src_dir, self.name)) out.write('\n') if self.static: self.mk_static(out) @@ -854,13 +854,13 @@ class DLLComponent(Component): # generate rule for lib objs = [] for cppfile in get_cpp_files(self.src_dir): - objfile = '%s/%s$(OBJ_EXT)' % (self.build_dir, os.path.splitext(cppfile)[0]) + objfile = '%s$(OBJ_EXT)' % os.path.join(self.build_dir, os.path.splitext(cppfile)[0]) objs.append(objfile) # we have to "reexport" all object files for dep in self.deps: dep = get_component(dep) for cppfile in get_cpp_files(dep.src_dir): - objfile = '%s/%s$(OBJ_EXT)' % (dep.build_dir, os.path.splitext(cppfile)[0]) + objfile = '%s$(OBJ_EXT)' % os.path.join(dep.build_dir, os.path.splitext(cppfile)[0]) objs.append(objfile) libfile = '%s$(LIB_EXT)' % self.dll_name out.write('%s:' % libfile) @@ -889,29 +889,29 @@ class DLLComponent(Component): def mk_install(self, out): if self.install: dllfile = '%s$(SO_EXT)' % self.dll_name - out.write('\t@cp %s $(PREFIX)/lib/%s\n' % (dllfile, dllfile)) - out.write('\t@cp %s %s/%s\n' % (dllfile, PYTHON_PACKAGE_DIR, dllfile)) + out.write('\t@cp %s %s\n' % (dllfile, os.path.join('$(PREFIX)', 'lib', dllfile))) + out.write('\t@cp %s %s\n' % (dllfile, os.path.join(PYTHON_PACKAGE_DIR, dllfile))) if self.static: libfile = '%s$(LIB_EXT)' % self.dll_name - out.write('\t@cp %s $(PREFIX)/lib/%s\n' % (libfile, libfile)) + out.write('\t@cp %s %s\n' % (libfile, os.path.join('$(PREFIX)', 'lib', libfile))) def mk_uninstall(self, out): dllfile = '%s$(SO_EXT)' % self.dll_name - out.write('\t@rm -f $(PREFIX)/lib/%s\n' % dllfile) - out.write('\t@rm -f %s/%s\n' % (PYTHON_PACKAGE_DIR, dllfile)) + out.write('\t@rm -f %s\n' % os.path.join('$(PREFIX)', 'lib', dllfile)) + out.write('\t@rm -f %s\n' % os.path.join(PYTHON_PACKAGE_DIR, dllfile)) libfile = '%s$(LIB_EXT)' % self.dll_name - out.write('\t@rm -f $(PREFIX)/lib/%s\n' % libfile) + out.write('\t@rm -f %s\n' % os.path.join('$(PREFIX)', 'lib', libfile)) def mk_win_dist(self, build_path, dist_path): if self.install: - mk_dir('%s/bin' % dist_path) - shutil.copy('%s/%s.dll' % (build_path, self.dll_name), - '%s/bin/%s.dll' % (dist_path, self.dll_name)) + mk_dir(os.path.join(dist_path, 'bin')) + shutil.copy('%s.dll' % os.path.join(build_path, self.dll_name), + '%s.dll' % os.path.join(dist_path, 'bin', self.dll_name)) if self.static: - mk_dir('%s/bin' % dist_path) - shutil.copy('%s/%s.lib' % (build_path, self.dll_name), - '%s/bin/%s.lib' % (dist_path, self.dll_name)) + mk_dir(os.path.join(dist_path, 'bin')) + shutil.copy('%s.lib' % os.path.join(build_path, self.dll_name), + '%s.lib' % os.path.join(dist_path, 'bin', self.dll_name)) class DotNetDLLComponent(Component): def __init__(self, name, dll_name, path, deps, assembly_info_dir): @@ -928,12 +928,12 @@ class DotNetDLLComponent(Component): cs_fp_files = [] cs_files = [] for cs_file in get_cs_files(self.src_dir): - cs_fp_files.append('%s/%s' % (self.to_src_dir, cs_file)) + cs_fp_files.append(os.path.join(self.to_src_dir, cs_file)) cs_files.append(cs_file) if self.assembly_info_dir != '.': - for cs_file in get_cs_files('%s/%s' % (self.src_dir, self.assembly_info_dir)): - cs_fp_files.append('%s/%s/%s' % (self.to_src_dir, self.assembly_info_dir, cs_file)) - cs_files.append('%s\%s' % (self.assembly_info_dir, cs_file)) + for cs_file in get_cs_files(os.path.join(self.src_dir, self.assembly_info_dir)): + cs_fp_files.append(os.path.join(self.to_src_dir, self.assembly_info_dir, cs_file)) + cs_files.append(os.path.join(self.assembly_info_dir, cs_file)) dllfile = '%s.dll' % self.dll_name out.write('%s:' % dllfile) for cs_file in cs_fp_files: @@ -947,8 +947,8 @@ class DotNetDLLComponent(Component): out.write('\n') # HACK win_to_src_dir = self.to_src_dir.replace('/', '\\') - out.write(' move %s\%s\n' % (win_to_src_dir, dllfile)) - out.write(' move %s\%s.pdb\n' % (win_to_src_dir, self.dll_name)) + out.write(' move %s\n' % os.path.join(win_to_src_dir, dllfile)) + out.write(' move %s.pdb\n' % os.path.join(win_to_src_dir, self.dll_name)) out.write('%s: %s\n\n' % (self.name, dllfile)) return @@ -961,9 +961,9 @@ class DotNetDLLComponent(Component): def mk_win_dist(self, build_path, dist_path): if DOTNET_ENABLED: # Assuming all DotNET dll should be in the distribution - mk_dir('%s/bin' % dist_path) - shutil.copy('%s/%s.dll' % (build_path, self.dll_name), - '%s/bin/%s.dll' % (dist_path, self.dll_name)) + mk_dir(os.path.join(dist_path, 'bin')) + shutil.copy('%s.dll' % os.path.join(build_path, self.dll_name), + '%s.dll' % os.path.join(dist_path, 'bin', self.dll_name)) class JavaDLLComponent(Component): @@ -977,9 +977,9 @@ class JavaDLLComponent(Component): def mk_makefile(self, out): if is_java_enabled(): - mk_dir(BUILD_DIR+'/api/java/classes') + mk_dir(os.path.join(BUILD_DIR, 'api', 'java', 'classes')) dllfile = '%s$(SO_EXT)' % self.dll_name - out.write('libz3java$(SO_EXT): libz3$(SO_EXT) %s/Native.cpp\n' % self.to_src_dir) + out.write('libz3java$(SO_EXT): libz3$(SO_EXT) %s\n' % os.path.join(self.to_src_dir, 'Native.cpp')) t = '\t$(CXX) $(CXXFLAGS) $(CXX_OUT_FLAG)api/java/Native$(OBJ_EXT) -I"%s/include" -I"%s/include/PLATFORM" -I%s %s/Native.cpp\n' % (JAVA_HOME, JAVA_HOME, get_component('api').to_src_dir, self.to_src_dir) if IS_OSX: t = t.replace('PLATFORM', 'darwin') @@ -995,9 +995,9 @@ class JavaDLLComponent(Component): out.write('%s.jar: libz3java$(SO_EXT) ' % self.package_name) deps = '' for jfile in get_java_files(self.src_dir): - deps += ('%s/%s ' % (self.to_src_dir, jfile)) - for jfile in get_java_files((self.src_dir + "/enumerations")): - deps += ('%s/enumerations/%s ' % (self.to_src_dir, jfile)) + deps += ('%s ' % os.path.join(self.to_src_dir, jfile)) + for jfile in get_java_files(os.path.join(self.src_dir, "enumerations")): + deps += '%s ' % os.path.join(self.to_src_dir, 'enumerations', jfile) if IS_WINDOWS: deps = deps.replace('/', '\\') out.write(deps) out.write('\n') @@ -1017,8 +1017,8 @@ class JavaDLLComponent(Component): class ExampleComponent(Component): def __init__(self, name, path): Component.__init__(self, name, path, []) - self.ex_dir = '%s/%s' % (EXAMPLE_DIR, self.path) - self.to_ex_dir = '%s/%s' % (REV_BUILD_DIR, self.ex_dir) + self.ex_dir = os.path.join(EXAMPLE_DIR, self.path) + self.to_ex_dir = os.path.join(REV_BUILD_DIR, self.ex_dir) def is_example(self): return True @@ -1041,7 +1041,7 @@ class CppExampleComponent(ExampleComponent): out.write('%s: %s' % (exefile, dll)) for cppfile in self.src_files(): out.write(' ') - out.write('%s/%s' % (self.to_ex_dir, cppfile)) + out.write(os.path.join(self.to_ex_dir, cppfile)) out.write('\n') out.write('\t%s $(LINK_OUT_FLAG)%s $(LINK_FLAGS)' % (self.compiler(), exefile)) # Add include dir components @@ -1049,7 +1049,7 @@ class CppExampleComponent(ExampleComponent): out.write(' -I%s' % get_component(CPP_COMPONENT).to_src_dir) for cppfile in self.src_files(): out.write(' ') - out.write('%s/%s' % (self.to_ex_dir, cppfile)) + out.write(os.path.join(self.to_ex_dir, cppfile)) out.write(' ') if IS_WINDOWS: out.write('%s.lib' % dll_name) @@ -1083,7 +1083,7 @@ class DotNetExampleComponent(ExampleComponent): out.write('%s: %s' % (exefile, dll)) for csfile in get_cs_files(self.ex_dir): out.write(' ') - out.write('%s/%s' % (self.to_ex_dir, csfile)) + out.write(os.path.join(self.to_ex_dir, csfile)) out.write('\n') out.write('\tcsc /out:%s /reference:%s /debug:full /reference:System.Numerics.dll' % (exefile, dll)) if VS_X64: @@ -1094,7 +1094,7 @@ class DotNetExampleComponent(ExampleComponent): out.write(' ') # HACK win_ex_dir = self.to_ex_dir.replace('/', '\\') - out.write('%s\\%s' % (win_ex_dir, csfile)) + out.write(os.path.join(win_ex_dir, csfile)) out.write('\n') out.write('_ex_%s: %s\n\n' % (self.name, exefile)) @@ -1111,7 +1111,7 @@ class JavaExampleComponent(ExampleComponent): out.write('_ex_%s: %s' % (self.name, pkg)) deps = '' for jfile in get_java_files(self.ex_dir): - out.write(' %s/%s' % (self.to_ex_dir, jfile)) + out.write(os.path.join(self.to_ex_dir, jfile)) if IS_WINDOWS: deps = deps.replace('/', '\\') out.write('%s\n' % deps) @@ -1119,7 +1119,7 @@ class JavaExampleComponent(ExampleComponent): win_ex_dir = self.to_ex_dir for javafile in get_java_files(self.ex_dir): out.write(' ') - out.write('%s/%s' % (win_ex_dir, javafile)) + out.write(os.path.join(win_ex_dir, javafile)) out.write(' -d .\n\n') class PythonExampleComponent(ExampleComponent): @@ -1129,9 +1129,9 @@ class PythonExampleComponent(ExampleComponent): # Python examples are just placeholders, we just copy the *.py files when mk_makefile is invoked. # We don't need to include them in the :examples rule def mk_makefile(self, out): - full = '%s/%s' % (EXAMPLE_DIR, self.path) + full = os.path.join(EXAMPLE_DIR, self.path) for py in filter(lambda f: f.endswith('.py'), os.listdir(full)): - shutil.copyfile('%s/%s' % (full, py), '%s/%s' % (BUILD_DIR, py)) + shutil.copyfile(os.path.join(full, py), os.path.join(BUILD_DIR, py)) if is_verbose(): print "Copied Z3Py example '%s' to '%s'" % (py, BUILD_DIR) out.write('_ex_%s: \n\n' % self.name) @@ -1198,7 +1198,7 @@ def add_z3py_example(name, path=None): def mk_config(): if ONLY_MAKEFILES: return - config = open('%s/config.mk' % BUILD_DIR, 'w') + config = open(os.path.join(BUILD_DIR, 'config.mk'), 'w') if IS_WINDOWS: config.write( 'CC=cl\n' @@ -1351,9 +1351,9 @@ def mk_config(): def mk_install(out): out.write('install:\n') - out.write('\t@mkdir -p $(PREFIX)/bin\n') - out.write('\t@mkdir -p $(PREFIX)/include\n') - out.write('\t@mkdir -p $(PREFIX)/lib\n') + out.write('\t@mkdir -p %s\n' % os.path.join('$(PREFIX)', 'bin')) + out.write('\t@mkdir -p %s\n' % os.path.join('$(PREFIX)', 'include')) + out.write('\t@mkdir -p %s\n' % os.path.join('$(PREFIX)', 'lib')) for c in get_components(): c.mk_install(out) out.write('\t@cp z3*.pyc %s\n' % PYTHON_PACKAGE_DIR) @@ -1364,7 +1364,7 @@ def mk_uninstall(out): out.write('uninstall:\n') for c in get_components(): c.mk_uninstall(out) - out.write('\t@rm -f %s/z3*.pyc\n' % PYTHON_PACKAGE_DIR) + out.write('\t@rm -f %s*.pyc\n' % os.path.join(PYTHON_PACKAGE_DIR, 'z3')) out.write('\t@echo Z3 was successfully uninstalled.\n') out.write('\n') @@ -1373,9 +1373,9 @@ def mk_makefile(): mk_dir(BUILD_DIR) mk_config() if VERBOSE: - print "Writing %s/Makefile" % BUILD_DIR - out = open('%s/Makefile' % BUILD_DIR, 'w') - out.write('# Automatically generated file. Generator: scripts/mk_make.py\n') + print "Writing %s" % os.path.join(BUILD_DIR, 'Makefile') + out = open(os.path.join(BUILD_DIR, 'Makefile'), 'w') + out.write('# Automatically generated file.\n') out.write('include config.mk\n') # Generate :all rule out.write('all:') @@ -1415,7 +1415,7 @@ def mk_makefile(): else: print " platform: x86" print "To build Z3, open a [Visual Studio Command Prompt], then" - print "type 'cd %s/%s && nmake'\n" % (os.getcwd(), BUILD_DIR) + print "type 'cd %s && nmake'\n" % os.path.join(os.getcwd(), BUILD_DIR) print 'Remark: to open a Visual Studio Command Prompt, go to: "Start > All Programs > Visual Studio > Visual Studio Tools"' else: print "Type 'cd %s; make' to build Z3" % BUILD_DIR @@ -1535,14 +1535,14 @@ def exec_pyg_scripts(): # database.smt ==> database.h def mk_pat_db(): c = get_component(PATTERN_COMPONENT) - fin = open('%s/database.smt2' % c.src_dir, 'r') - fout = open('%s/database.h' % c.src_dir, 'w') + fin = open(os.path.join(c.src_dir, 'database.smt2'), 'r') + fout = open(os.path.join(c.src_dir, 'database.h'), 'w') fout.write('char const * g_pattern_database =\n') for line in fin: fout.write('"%s\\n"\n' % line.strip('\n')) fout.write(';\n') if VERBOSE: - print "Generated '%s/database.h'" % c.src_dir + print "Generated '%s'" % os.path.join(c.src_dir, 'database.h') # Update version numbers def update_version(): @@ -1560,32 +1560,32 @@ def update_version(): # Update files with the version number def mk_version_dot_h(major, minor, build, revision): c = get_component(UTIL_COMPONENT) - fout = open('%s/version.h' % c.src_dir, 'w') + fout = open(os.path.join(c.src_dir, 'version.h'), 'w') fout.write('// automatically generated file.\n') fout.write('#define Z3_MAJOR_VERSION %s\n' % major) fout.write('#define Z3_MINOR_VERSION %s\n' % minor) fout.write('#define Z3_BUILD_NUMBER %s\n' % build) fout.write('#define Z3_REVISION_NUMBER %s\n' % revision) if VERBOSE: - print "Generated '%s/version.h'" % c.src_dir + print "Generated '%s'" % os.path.join(c.src_dir, 'version.h') # Update version number in AssemblyInfo.cs files def update_all_assembly_infos(major, minor, build, revision): for c in get_components(): if c.has_assembly_info(): - assembly = '%s/%s/AssemblyInfo.cs' % (c.src_dir, c.assembly_info_dir) + assembly = os.path.join(c.src_dir, c.assembly_info_dir, 'AssemblyInfo.cs') if os.path.exists(assembly): # It is a CS file update_assembly_info_version(assembly, major, minor, build, revision, False) else: - assembly = '%s/%s/AssemblyInfo.cpp' % (c.src_dir, c.assembly_info_dir) + assembly = os.path.join(c.src_dir, c.assembly_info_dir, 'AssemblyInfo.cs') if os.path.exists(assembly): # It is a cpp file update_assembly_info_version(assembly, major, minor, build, revision, True) else: - raise MKException("Failed to find assembly info file at '%s/%s'" % (c.src_dir, c.assembly_info_dir)) + raise MKException("Failed to find assembly info file at '%s'" % os.path.join(c.src_dir, c.assembly_info_dir)) # Update version number in the given AssemblyInfo.cs files @@ -1644,7 +1644,7 @@ def mk_install_tactic_cpp(cnames, path): global ADD_TACTIC_DATA, ADD_PROBE_DATA ADD_TACTIC_DATA = [] ADD_PROBE_DATA = [] - fullname = '%s/install_tactic.cpp' % path + fullname = os.path.join(path, 'install_tactic.cpp') fout = open(fullname, 'w') fout.write('// Automatically generated file.\n') fout.write('#include"tactic.h"\n') @@ -1657,7 +1657,7 @@ def mk_install_tactic_cpp(cnames, path): h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(c.src_dir)) for h_file in h_files: added_include = False - fin = open("%s/%s" % (c.src_dir, h_file), 'r') + fin = open(os.path.join(c.src_dir, h_file), 'r') for line in fin: if tactic_pat.match(line): if not added_include: @@ -1710,7 +1710,7 @@ def mk_all_install_tactic_cpps(): def mk_mem_initializer_cpp(cnames, path): initializer_cmds = [] finalizer_cmds = [] - fullname = '%s/mem_initializer.cpp' % path + fullname = os.path.join(path, 'mem_initializer.cpp') fout = open(fullname, 'w') fout.write('// Automatically generated file.\n') initializer_pat = re.compile('[ \t]*ADD_INITIALIZER\(\'([^\']*)\'\)') @@ -1722,7 +1722,7 @@ def mk_mem_initializer_cpp(cnames, path): h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(c.src_dir)) for h_file in h_files: added_include = False - fin = open("%s/%s" % (c.src_dir, h_file), 'r') + fin = open(os.path.join(c.src_dir, h_file), 'r') for line in fin: m = initializer_pat.match(line) if m: @@ -1773,7 +1773,7 @@ def mk_gparams_register_modules(cnames, path): cmds = [] mod_cmds = [] mod_descrs = [] - fullname = '%s/gparams_register_modules.cpp' % path + fullname = os.path.join(path, 'gparams_register_modules.cpp') fout = open(fullname, 'w') fout.write('// Automatically generated file.\n') fout.write('#include"gparams.h"\n') @@ -1785,7 +1785,7 @@ def mk_gparams_register_modules(cnames, path): h_files = filter(lambda f: f.endswith('.h') or f.endswith('.hpp'), os.listdir(c.src_dir)) for h_file in h_files: added_include = False - fin = open("%s/%s" % (c.src_dir, h_file), 'r') + fin = open(os.path.join(c.src_dir, h_file), 'r') for line in fin: m = reg_pat.match(line) if m: @@ -1825,13 +1825,13 @@ def mk_all_gparams_register_modules(): # Generate a .def based on the files at c.export_files slot. def mk_def_file(c): pat1 = re.compile(".*Z3_API.*") - defname = '%s/%s.def' % (c.src_dir, c.name) + defname = '%s.def' % os.path.join(c.src_dir, c.name) fout = open(defname, 'w') fout.write('LIBRARY "%s"\nEXPORTS\n' % c.dll_name) num = 1 for dot_h in c.export_files: dot_h_c = c.find_file(dot_h, c.name) - api = open('%s/%s' % (dot_h_c.src_dir, dot_h), 'r') + api = open(os.path.join(dot_h_c.src_dir, dot_h), 'r') for line in api: m = pat1.match(line) if m: @@ -1858,11 +1858,11 @@ def cp_z3pyc_to_build(): raise MKException("failed to compile Z3Py sources") for pyc in filter(lambda f: f.endswith('.pyc'), os.listdir(Z3PY_SRC_DIR)): try: - os.remove('%s/%s' % (BUILD_DIR, pyc)) + os.remove(os.path.join(BUILD_DIR, pyc)) except: pass - shutil.copyfile('%s/%s' % (Z3PY_SRC_DIR, pyc), '%s/%s' % (BUILD_DIR, pyc)) - os.remove('%s/%s' % (Z3PY_SRC_DIR, pyc)) + shutil.copyfile(os.path.join(Z3PY_SRC_DIR, pyc), os.path.join(BUILD_DIR, pyc)) + os.remove(os.path.join(Z3PY_SRC_DIR, pyc)) if is_verbose(): print "Generated '%s'" % pyc @@ -1874,13 +1874,13 @@ def mk_bindings(api_files): api = get_component(API_COMPONENT) for api_file in api_files: api_file_path = api.find_file(api_file, api.name) - new_api_files.append('%s/%s' % (api_file_path.src_dir, api_file)) + new_api_files.append(os.path.join(api_file_path.src_dir, api_file)) g = {} g["API_FILES"] = new_api_files if is_java_enabled(): check_java() mk_z3consts_java(api_files) - execfile('scripts/update_api.py', g) # HACK + execfile(os.path.join('scripts', 'update_api.py'), g) # HACK cp_z3pyc_to_build() # Extract enumeration types from API files, and add python definitions. @@ -1895,14 +1895,14 @@ def mk_z3consts_py(api_files): openbrace_pat = re.compile("{ *") closebrace_pat = re.compile("}.*;") - z3consts = open('%s/z3consts.py' % Z3PY_SRC_DIR, 'w') + z3consts = open(os.path.join(Z3PY_SRC_DIR, 'z3consts.py'), 'w') z3consts.write('# Automatically generated file\n\n') api_dll = get_component(Z3_DLL_COMPONENT) for api_file in api_files: api_file_c = api_dll.find_file(api_file, api_dll.name) - api_file = '%s/%s' % (api_file_c.src_dir, api_file) + api_file = os.path.join(api_file_c.src_dir, api_file) api = open(api_file, 'r') SEARCHING = 0 @@ -1958,7 +1958,7 @@ def mk_z3consts_py(api_files): idx = idx + 1 linenum = linenum + 1 if VERBOSE: - print "Generated '%s'" % ('%s/z3consts.py' % Z3PY_SRC_DIR) + print "Generated '%s'" % os.path.join(Z3PY_SRC_DIR, 'z3consts.py') # Extract enumeration types from z3_api.h, and add .Net definitions @@ -1973,7 +1973,7 @@ def mk_z3consts_dotnet(api_files): dotnet = get_component(DOTNET_COMPONENT) DeprecatedEnums = [ 'Z3_search_failure' ] - z3consts = open('%s/Enumerations.cs' % dotnet.src_dir, 'w') + z3consts = open(os.path.join(dotnet.src_dir, 'Enumerations.cs'), 'w') z3consts.write('// Automatically generated file\n\n') z3consts.write('using System;\n\n' '#pragma warning disable 1591\n\n' @@ -1982,7 +1982,7 @@ def mk_z3consts_dotnet(api_files): for api_file in api_files: api_file_c = dotnet.find_file(api_file, dotnet.name) - api_file = '%s/%s' % (api_file_c.src_dir, api_file) + api_file = os.path.join(api_file_c.src_dir, api_file) api = open(api_file, 'r') @@ -2043,7 +2043,7 @@ def mk_z3consts_dotnet(api_files): linenum = linenum + 1 z3consts.write('}\n'); if VERBOSE: - print "Generated '%s'" % ('%s/Enumerations.cs' % dotnet.src_dir) + print "Generated '%s'" % os.path.join(dotnet.src_dir, 'Enumerations.cs') # Extract enumeration types from z3_api.h, and add Java definitions @@ -2058,13 +2058,13 @@ def mk_z3consts_java(api_files): java = get_component(JAVA_COMPONENT) DeprecatedEnums = [ 'Z3_search_failure' ] - gendir = java.src_dir + "/enumerations" + gendir = os.path.join(java.src_dir, "enumerations") if not os.path.exists(gendir): os.mkdir(gendir) for api_file in api_files: api_file_c = java.find_file(api_file, java.name) - api_file = '%s/%s' % (api_file_c.src_dir, api_file) + api_file = os.path.join(api_file_c.src_dir, api_file) api = open(api_file, 'r') @@ -2107,7 +2107,7 @@ def mk_z3consts_java(api_files): if m: name = words[1] if name not in DeprecatedEnums: - efile = open('%s/%s.java' % (gendir, name), 'w') + efile = open('%s.java' % os.path.join(gendir, name), 'w') efile.write('/**\n * Automatically generated file\n **/\n\n') efile.write('package %s.enumerations;\n\n' % java.package_name); @@ -2156,7 +2156,7 @@ def mk_gui_str(id): def mk_vs_proj(name, components): if not VS_PROJ: return - proj_name = '%s/%s.vcxproj' % (BUILD_DIR, name) + proj_name = '%s.vcxproj' % os.path.join(BUILD_DIR, name) modes=['Debug', 'Release'] PLATFORMS=['Win32'] f = open(proj_name, 'w') @@ -2228,7 +2228,7 @@ def mk_vs_proj(name, components): for dep in deps: dep = get_component(dep) for cpp in filter(lambda f: f.endswith('.cpp'), os.listdir(dep.src_dir)): - f.write(' \n' % (dep.to_src_dir, cpp)) + f.write(' \n' % os.path.join(dep.to_src_dir, cpp)) f.write(' \n') f.write(' \n') f.write(' \n') @@ -2242,8 +2242,8 @@ def mk_win_dist(build_path, dist_path): c.mk_win_dist(build_path, dist_path) # Add Z3Py to lib directory for pyc in filter(lambda f: f.endswith('.pyc'), os.listdir(build_path)): - shutil.copy('%s/%s' % (build_path, pyc), - '%s/bin/%s' % (dist_path, pyc)) + shutil.copy(os.path.join(build_path, pyc), + os.path.join(dist_path, 'bin', pyc)) if __name__ == '__main__': From 017176c7206a49ad6315e7257abe0f9a07298276 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 6 Dec 2012 15:33:43 -0800 Subject: [PATCH 13/60] fixed messy directory separator in mk_util Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 32 ++++++++++++++++++-------------- scripts/update_api.py | 24 ++++++++++++------------ 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 8c727e0ec..5fe083935 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -85,11 +85,9 @@ def is_linux(): def is_osx(): return IS_OSX -def unix_path2dos(path): - return string.join(path.split('/'), '\\') - -def to_unix_path(path): - return string.join(path.split('\\'), '/') +def norm_path(p): + # We use '/' on mk_project for convenience + return os.path.join(*(p.split('/'))) def which(program): import os @@ -443,7 +441,7 @@ def extract_c_includes(fname): # Given a path dir1/subdir2/subdir3 returns ../../.. def reverse_path(p): - l = to_unix_path(p).split('/') + l = p.split(os.sep) n = len(l) r = '..' for i in range(1, n): @@ -461,6 +459,7 @@ def set_build_dir(d): def set_z3py_dir(p): global SRC_DIR, Z3PY_SRC_DIR + p = norm_path(p) full = os.path.join(SRC_DIR, p) if not os.path.exists(full): raise MKException("Python bindings directory '%s' does not exist" % full) @@ -559,6 +558,7 @@ class Component: if path == None: path = name self.name = name + path = norm_path(path) self.path = path self.deps = find_all_deps(name, deps) self.build_dir = path @@ -989,25 +989,29 @@ class JavaDLLComponent(Component): t = t.replace('PLATFORM', 'win32') out.write(t) if IS_WINDOWS: # On Windows, CL creates a .lib file to link against. - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) api/java/Native$(OBJ_EXT) libz3$(LIB_EXT)\n') + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % + os.join.path('api', 'java', 'Native')) else: - out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) api/java/Native$(OBJ_EXT) libz3$(SO_EXT)\n') + out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % + os.join.path('api', 'java', 'Native')) out.write('%s.jar: libz3java$(SO_EXT) ' % self.package_name) deps = '' for jfile in get_java_files(self.src_dir): deps += ('%s ' % os.path.join(self.to_src_dir, jfile)) for jfile in get_java_files(os.path.join(self.src_dir, "enumerations")): deps += '%s ' % os.path.join(self.to_src_dir, 'enumerations', jfile) - if IS_WINDOWS: deps = deps.replace('/', '\\') out.write(deps) out.write('\n') - t = ('\t%s %s/enumerations/*.java -d api/java/classes\n' % (JAVAC, self.to_src_dir)) - if IS_WINDOWS: t = t.replace('/','\\') + t = ('\t%s %s.java -d %s\n' % (JAVAC, os.join.path(self.to_src_dir, 'enumerations', '*'), os.join.path('api', 'java', 'classes'))) out.write(t) - t = ('\t%s -cp api/java/classes %s/*.java -d api/java/classes\n' % (JAVAC, self.to_src_dir)) - if IS_WINDOWS: t = t.replace('/','\\') + t = ('\t%s -cp api/java/classes %s.java -d %s\n' % (JAVAC, + os.join.path('api', 'java', 'classes'), + os.join.path(self.to_src_dir, '*'), + os.join.path('api', 'java', 'classes'))) out.write(t) - out.write('\tjar cfm %s.jar %s/manifest -C api/java/classes .\n' % (self.package_name, self.to_src_dir)) + out.write('\tjar cfm %s.jar %s -C %s .\n' % (self.package_name, + os.join.path(self.to_src_dir, 'manifest'), + os.join.path('api', 'java', 'classes'))) out.write('java: %s.jar\n\n' % self.package_name) def main_component(self): diff --git a/scripts/update_api.py b/scripts/update_api.py index d7dbb7bcf..a636a1a02 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -24,11 +24,11 @@ from mk_exception import * api_dir = get_component('api').src_dir dotnet_dir = get_component('dotnet').src_dir -log_h = open('%s/api_log_macros.h' % api_dir, 'w') -log_c = open('%s/api_log_macros.cpp' % api_dir, 'w') -exe_c = open('%s/api_commands.cpp' % api_dir, 'w') -core_py = open('%s/z3core.py' % get_z3py_dir(), 'w') -dotnet_fileout = '%s/Native.cs' % dotnet_dir +log_h = open(os.path.join(api_dir, 'api_log_macros.h'), 'w') +log_c = open(os.path.join(api_dir, 'api_log_macros.cpp'), 'w') +exe_c = open(os.path.join(api_dir, 'api_commands.cpp'), 'w') +core_py = open(os.path.join(get_z3py_dir(), 'z3core.py'), 'w') +dotnet_fileout = os.path.join(dotnet_dir, 'Native.cs') ## log_h.write('// Automatically generated file\n') log_h.write('#include\"z3.h\"\n') @@ -479,8 +479,8 @@ def mk_java(): if not is_java_enabled(): return java_dir = get_component('java').src_dir - java_nativef = '%s/Native.java' % java_dir - java_wrapperf = '%s/Native.cpp' % java_dir + java_nativef = os.path.join(java_dir, 'Native.java') + java_wrapperf = os.path.join(java_dir, 'Native.cpp') java_native = open(java_nativef, 'w') java_native.write('// Automatically generated file\n') java_native.write('package %s;\n' % get_component('java').package_name) @@ -981,8 +981,8 @@ exe_c.close() core_py.close() if is_verbose(): - print "Generated '%s'" % ('%s/api_log_macros.h' % api_dir) - print "Generated '%s'" % ('%s/api_log_macros.cpp' % api_dir) - print "Generated '%s'" % ('%s/api_commands.cpp' % api_dir) - print "Generated '%s'" % ('%s/z3core.py' % get_z3py_dir()) - print "Generated '%s'" % ('%s/Native.cs' % dotnet_dir) + print "Generated '%s'" % os.path.join(api_dir, 'api_log_macros.h') + print "Generated '%s'" % os.path.join(api_dir, 'api_log_macros.cpp') + print "Generated '%s'" % os.path.join(api_dir, 'api_commands.cpp') + print "Generated '%s'" % os.path.join(get_z3py_dir(), 'z3core.py') + print "Generated '%s'" % os.path.join(dotnet_dir, 'Native.cs') From 26f616268e12ae751bc01de3a2d8f318b93e4943 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 6 Dec 2012 15:35:28 -0800 Subject: [PATCH 14/60] fixed warning in 32bit sys Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 98fae665a..a81a693e7 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1459,7 +1459,10 @@ def pyg_default_as_c_literal(p): return '"%s"' % p[2] elif p[1] == SYMBOL: return 'symbol("%s")' % p[2] - return p[2] + elif p[1] == UINT: + return '%su' % p[2] + else: + return p[2] def to_c_method(s): return s.replace('.', '_') From 60b920748551230145c029199be6376176222ab6 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 6 Dec 2012 15:40:31 -0800 Subject: [PATCH 15/60] fixed more problems Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index cf94731f3..5944f015f 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -990,10 +990,10 @@ class JavaDLLComponent(Component): out.write(t) if IS_WINDOWS: # On Windows, CL creates a .lib file to link against. out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(LIB_EXT)\n' % - os.join.path('api', 'java', 'Native')) + os.path.join('api', 'java', 'Native')) else: out.write('\t$(SLINK) $(SLINK_OUT_FLAG)libz3java$(SO_EXT) $(SLINK_FLAGS) %s$(OBJ_EXT) libz3$(SO_EXT)\n' % - os.join.path('api', 'java', 'Native')) + os.path.join('api', 'java', 'Native')) out.write('%s.jar: libz3java$(SO_EXT) ' % self.package_name) deps = '' for jfile in get_java_files(self.src_dir): @@ -1002,16 +1002,16 @@ class JavaDLLComponent(Component): deps += '%s ' % os.path.join(self.to_src_dir, 'enumerations', jfile) out.write(deps) out.write('\n') - t = ('\t%s %s.java -d %s\n' % (JAVAC, os.join.path(self.to_src_dir, 'enumerations', '*'), os.join.path('api', 'java', 'classes'))) + t = ('\t%s %s.java -d %s\n' % (JAVAC, os.path.join(self.to_src_dir, 'enumerations', '*'), os.path.join('api', 'java', 'classes'))) out.write(t) - t = ('\t%s -cp api/java/classes %s.java -d %s\n' % (JAVAC, - os.join.path('api', 'java', 'classes'), - os.join.path(self.to_src_dir, '*'), - os.join.path('api', 'java', 'classes'))) + t = ('\t%s -cp %s %s.java -d %s\n' % (JAVAC, + os.path.join('api', 'java', 'classes'), + os.path.join(self.to_src_dir, '*'), + os.path.join('api', 'java', 'classes'))) out.write(t) out.write('\tjar cfm %s.jar %s -C %s .\n' % (self.package_name, - os.join.path(self.to_src_dir, 'manifest'), - os.join.path('api', 'java', 'classes'))) + os.path.join(self.to_src_dir, 'manifest'), + os.path.join('api', 'java', 'classes'))) out.write('java: %s.jar\n\n' % self.package_name) def main_component(self): From fc20eba9457000ebb9defc6c656cf3cb42e34526 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 6 Dec 2012 15:46:36 -0800 Subject: [PATCH 16/60] another dir issue Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 5944f015f..8165ba5db 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -454,7 +454,7 @@ def mk_dir(d): def set_build_dir(d): global BUILD_DIR, REV_BUILD_DIR - BUILD_DIR = d + BUILD_DIR = norm_path(d) REV_BUILD_DIR = reverse_path(d) def set_z3py_dir(p): From 44ae1a2d70424a5d01658c253cbd1bcb8467f98b Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 6 Dec 2012 16:09:10 -0800 Subject: [PATCH 17/60] fixed problem reported by Dejan Signed-off-by: Leonardo de Moura --- README | 5 +-- RELEASE_NOTES | 4 +++ scripts/mk_util.py | 83 ++++++++++++++++++++++++---------------------- 3 files changed, 51 insertions(+), 41 deletions(-) diff --git a/README b/README index 42f6b1e58..13f3d4fa4 100644 --- a/README +++ b/README @@ -20,9 +20,10 @@ Execute: It will install z3 executable at /usr/bin, libraries at /usr/lib, and include files at /usr/include. You can change the installation p -Use the following commands to install in a different prefix (e.g., /home/leo). +Use the following commands to install in a different prefix (e.g., /home/leo), and the Z3 python +bindings in a different python package directory. - python scripts/mk_make.py --prefix=/home/leo + python scripts/mk_make.py --prefix=/home/leo --pydir=/home/leo/python cd build make sudo make install diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 4c74b41a5..e2703bdcb 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -3,6 +3,8 @@ RELEASE NOTES Version 4.3.2 ============= +- New parameter setting infrastructure. Now, it is possible to set parameter for Z3 internal modules. Several parameter names changed. Execute `z3 -p` for the new parameter list. + - Added get_version() and get_version_string() to Z3Py - Added support for FreeBSD. Z3 can be compiled on FreeBSD using g++. @@ -20,6 +22,8 @@ Version 4.3.2 - Fixed crash when parsing incorrect formulas. The crash was introduced when support for "arithmetic coercions" was added in Z3 4.3.0. +- Added new option to mk_make to allow users to specify where python bindings (Z3Py) will be installed. (Thanks to Dejan Jovanovic for reporting the problem). + Version 4.3.1 ============= diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 5944f015f..2886651ae 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -341,6 +341,7 @@ def display_help(exit_code): print " -s, --silent do not print verbose messages." if not IS_WINDOWS: print " -p , --prefix= installation prefix (default: %s)." % PREFIX + print " -y , --pydir= installation prefix for Z3 python bindings (default: %s)." % PYTHON_PACKAGE_DIR print " -b , --build= subdirectory where Z3 will be built (default: build)." print " -d, --debug compile Z3 in debug mode." print " -t, --trace enable tracing in release mode." @@ -371,52 +372,56 @@ def display_help(exit_code): # Parse configuration option for mk_make script def parse_options(): global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE - global DOTNET_ENABLED, JAVA_ENABLED, STATIC_LIB, PREFIX, GMP + global DOTNET_ENABLED, JAVA_ENABLED, STATIC_LIB, PREFIX, GMP, PYTHON_PACKAGE_DIR try: options, remainder = getopt.gnu_getopt(sys.argv[1:], - 'b:dsxhmcvtnp:gj', + 'b:dsxhmcvtnp:gjy:', ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', - 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'java']) - for opt, arg in options: - if opt in ('-b', '--build'): - if arg == 'src': - raise MKException('The src directory should not be used to host the Makefile') - set_build_dir(arg) - elif opt in ('-s', '--silent'): - VERBOSE = False - elif opt in ('-d', '--debug'): - DEBUG_MODE = True - elif opt in ('-x', '--x64'): - if not IS_WINDOWS: - raise MKException('x64 compilation mode can only be specified when using Visual Studio') - VS_X64 = True - elif opt in ('-h', '--help'): - display_help(0) - elif opt in ('-m', '--onlymakefiles'): - ONLY_MAKEFILES = True - elif opt in ('-c', '--showcpp'): - SHOW_CPPS = True - elif opt in ('-v', '--vsproj'): - VS_PROJ = True - elif opt in ('-t', '--trace'): - TRACE = True - elif opt in ('-n', '--nodotnet'): - DOTNET_ENABLED = False - elif opt in ('--staticlib'): - STATIC_LIB = True - elif opt in ('-p', '--prefix'): - PREFIX = arg - elif opt in ('-g', '--gmp'): - GMP = True - elif opt in ('-j', '--java'): - JAVA_ENABLED = True - else: - print "ERROR: Invalid command line option '%s'" % opt - display_help(1) + 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'java', 'pydir=']) except: print "ERROR: Invalid command line option" display_help(1) + for opt, arg in options: + if opt in ('-b', '--build'): + if arg == 'src': + raise MKException('The src directory should not be used to host the Makefile') + set_build_dir(arg) + elif opt in ('-s', '--silent'): + VERBOSE = False + elif opt in ('-d', '--debug'): + DEBUG_MODE = True + elif opt in ('-x', '--x64'): + if not IS_WINDOWS: + raise MKException('x64 compilation mode can only be specified when using Visual Studio') + VS_X64 = True + elif opt in ('-h', '--help'): + display_help(0) + elif opt in ('-m', '--onlymakefiles'): + ONLY_MAKEFILES = True + elif opt in ('-c', '--showcpp'): + SHOW_CPPS = True + elif opt in ('-v', '--vsproj'): + VS_PROJ = True + elif opt in ('-t', '--trace'): + TRACE = True + elif opt in ('-n', '--nodotnet'): + DOTNET_ENABLED = False + elif opt in ('--staticlib'): + STATIC_LIB = True + elif opt in ('-p', '--prefix'): + PREFIX = arg + elif opt in ('-y', '--pydir'): + PYTHON_PACKAGE_DIR = arg + mk_dir(PYTHON_PACKAGE_DIR) + elif opt in ('-g', '--gmp'): + GMP = True + elif opt in ('-j', '--java'): + JAVA_ENABLED = True + else: + print "ERROR: Invalid command line option '%s'" % opt + display_help(1) + # Return a list containing a file names included using '#include' in # the given C/C++ file named fname. def extract_c_includes(fname): From 1ad7458d9fb87c3fe77bb31425168633ca782b03 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Thu, 6 Dec 2012 18:38:18 -0800 Subject: [PATCH 18/60] missing space Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 085ca2ad1..19331ee50 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1120,7 +1120,7 @@ class JavaExampleComponent(ExampleComponent): out.write('_ex_%s: %s' % (self.name, pkg)) deps = '' for jfile in get_java_files(self.ex_dir): - out.write(os.path.join(self.to_ex_dir, jfile)) + out.write(' %s' % os.path.join(self.to_ex_dir, jfile)) if IS_WINDOWS: deps = deps.replace('/', '\\') out.write('%s\n' % deps) From 8d45de02c5ab155354fb0e5405f89e16580b4df1 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 06:07:57 -0800 Subject: [PATCH 19/60] Fixed timer bug on freebsd Signed-off-by: Leonardo de Moura --- src/util/scoped_timer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/scoped_timer.cpp b/src/util/scoped_timer.cpp index 4b191505f..d475e5489 100644 --- a/src/util/scoped_timer.cpp +++ b/src/util/scoped_timer.cpp @@ -43,7 +43,7 @@ Revision History: #define CLOCKID CLOCK_PROCESS_CPUTIME_ID #else // FreeBSD does not support CLOCK_PROCESS_CPUTIME_ID - #define CLOCKID CLOCK_PROF + #define CLOCKID CLOCK_MONOTONIC #endif #define SIG SIGRTMIN // --------- From 60ebc5c4dd840a2ae482f5fbf4827b9db5d47ea7 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 06:59:54 -0800 Subject: [PATCH 20/60] added missing #ifndef to automatically generated hpp files Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 19331ee50..01d594adf 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1487,6 +1487,8 @@ def def_module_params(module_name, export, params, class_name=None, description= hpp = os.path.join(dirname, '%s.hpp' % class_name) out = open(hpp, 'w') out.write('// Automatically generated file\n') + out.write('#ifndef __%s_HPP_\n' % class_name.upper()) + out.write('#define __%s_HPP_\n' % class_name.upper()) out.write('#include"params.h"\n') if export: out.write('#include"gparams.h"\n') @@ -1518,6 +1520,7 @@ def def_module_params(module_name, export, params, class_name=None, description= out.write(' %s %s() const { return p.%s("%s", %s); }\n' % (TYPE2CTYPE[param[1]], to_c_method(param[0]), TYPE2GETTER[param[1]], param[0], pyg_default_as_c_literal(param))) out.write('};\n') + out.write('#endif\n') if is_verbose(): print "Generated '%s'" % hpp From ac03c9eff717e51c8b951556a1fdbb2f4a9cdd00 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 08:27:17 -0800 Subject: [PATCH 21/60] chasing parameter setting bug Signed-off-by: Leonardo de Moura --- src/api/api_solver.cpp | 12 +----------- src/cmd_context/cmd_context.cpp | 10 ++-------- src/cmd_context/context_params.cpp | 22 ++++++++++++++++++++++ src/cmd_context/context_params.h | 18 ++++++++++++++++++ src/cmd_context/tactic_cmds.cpp | 6 +++--- src/tactic/tactical.cpp | 3 +-- 6 files changed, 47 insertions(+), 24 deletions(-) diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index 67d083704..89bfd9519 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -36,17 +36,7 @@ extern "C" { static void init_solver_core(Z3_context c, Z3_solver _s) { ast_manager & m = mk_c(c)->m(); Z3_solver_ref * s = to_solver(_s); - s->m_solver->set_produce_proofs(mk_c(c)->produce_proofs()); - s->m_solver->set_produce_unsat_cores(s->m_params.get_bool("unsat_core", mk_c(c)->produce_unsat_cores())); - s->m_solver->set_produce_models(s->m_params.get_bool("model", mk_c(c)->produce_models())); - if (!mk_c(c)->use_auto_config()) { - params_ref p = s->m_params; - p.set_bool("auto_config", false); - s->m_solver->updt_params(p); - } - else { - s->m_solver->updt_params(s->m_params); - } + mk_c(c)->params().init_solver_params(mk_c(c)->m(), *(s->m_solver), s->m_params); s->m_solver->init(m, s->m_logic); s->m_initialized = true; } diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 0380e91ea..e14d5139c 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -1444,15 +1444,9 @@ void cmd_context::validate_model() { } void cmd_context::init_solver_options(solver * s) { - m_solver->set_produce_unsat_cores(produce_unsat_cores()); - m_solver->set_produce_models(produce_models()); - m_solver->set_produce_proofs(produce_proofs()); + params_ref p; + m_params.init_solver_params(m(), *m_solver, p); m_solver->init(m(), m_logic); - if (!m_params.m_auto_config) { - params_ref p; - p.set_bool("auto_config", false); - m_solver->updt_params(p); - } } void cmd_context::set_solver(solver * s) { diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index 495f73b75..96af5b52a 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -20,6 +20,8 @@ Notes: #include"context_params.h" #include"gparams.h" #include"params.h" +#include"ast.h" +#include"solver.h" context_params::context_params() { updt_params(); @@ -112,3 +114,23 @@ void context_params::collect_param_descrs(param_descrs & d) { d.insert("unsat_core", CPK_BOOL, "unsat-core generation for solvers, this parameter can be overwritten when creating a solver, not every solver in Z3 supports unsat core generation", "false"); d.insert("debug_ref_count", CPK_BOOL, "debug support for AST reference counting", "false"); } + +params_ref context_params::merge_default_params(params_ref const & p) { + if (!m_auto_config && !p.contains("auto_config")) { + params_ref new_p = p; + new_p.set_bool("auto_config", false); + return new_p; + } + else { + return p; + } +} + +void context_params::init_solver_params(ast_manager & m, solver & s, params_ref const & p) { + s.set_produce_proofs(m.proofs_enabled() && m_proof); + s.set_produce_models(p.get_bool("model", m_model)); + s.set_produce_unsat_cores(p.get_bool("unsat_core", m_unsat_core)); + s.updt_params(merge_default_params(p)); +} + + diff --git a/src/cmd_context/context_params.h b/src/cmd_context/context_params.h index 6b42b5b50..b3933dc23 100644 --- a/src/cmd_context/context_params.h +++ b/src/cmd_context/context_params.h @@ -21,6 +21,8 @@ Notes: #define _CONTEXT_PARAMS_H_ #include"params.h" +class ast_manager; +class solver; class context_params { void set_bool(bool & opt, char const * param, char const * value); @@ -45,6 +47,22 @@ public: /* REG_PARAMS('context_params::collect_param_descrs') */ + + /** + \brief Goodie for updating the solver params + based on the configuration of the context_params object. + + This method is used when creating solvers from the + cmd_context and API. + */ + void init_solver_params(ast_manager & m, solver & s, params_ref const & p); + + /** + \brief Include in p parameters derived from this context_params. + These are parameters that are meaningful for tactics and solvers. + Example: auto_config + */ + params_ref merge_default_params(params_ref const & p); }; diff --git a/src/cmd_context/tactic_cmds.cpp b/src/cmd_context/tactic_cmds.cpp index ca87406c7..27014bca9 100644 --- a/src/cmd_context/tactic_cmds.cpp +++ b/src/cmd_context/tactic_cmds.cpp @@ -36,7 +36,7 @@ tactic_cmd::~tactic_cmd() { dealloc(m_factory); } -tactic * tactic_cmd::mk(ast_manager & m) { +tactic * tactic_cmd::mk(ast_manager & m) { return (*m_factory)(m, params_ref()); } @@ -185,7 +185,7 @@ public: } virtual void execute(cmd_context & ctx) { - params_ref p = ps(); + params_ref p = ctx.params().merge_default_params(ps()); tactic_ref tref = using_params(sexpr2tactic(ctx, m_tactic), p); tref->set_logic(ctx.get_logic()); ast_manager & m = ctx.m(); @@ -295,7 +295,7 @@ public: } virtual void execute(cmd_context & ctx) { - params_ref p = ps(); + params_ref p = ctx.params().merge_default_params(ps()); tactic_ref tref = using_params(sexpr2tactic(ctx, m_tactic), p); { tactic & t = *(tref.get()); diff --git a/src/tactic/tactical.cpp b/src/tactic/tactical.cpp index 0d61f0916..d8ece6a52 100644 --- a/src/tactic/tactical.cpp +++ b/src/tactic/tactical.cpp @@ -1242,8 +1242,7 @@ public: virtual void updt_params(params_ref const & p) { TRACE("using_params", tout << "before p: " << p << "\n"; - tout << "m_params: " << m_params << "\n"; - ;); + tout << "m_params: " << m_params << "\n";); params_ref new_p = p; new_p.append(m_params); From 0a1ba9a9e0922b0ed90d210d80454c04b7159624 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 09:27:19 -0800 Subject: [PATCH 22/60] added openmp test, stopped using the compiler name to decide whether openmp will be used or not. Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 01d594adf..ceae95fab 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -139,7 +139,9 @@ def exec_cmd(cmd): if e != "": se = e.split(' ') if len(se) > 1: - new_cmd.extend(se) + for e2 in se: + if e2 != "": + new_cmd.append(e2) else: new_cmd.append(e) cmd = new_cmd @@ -179,10 +181,18 @@ def test_c_compiler(cc): def test_gmp(cc): if is_verbose(): print "Testing GMP..." - t = TempFile('tst.cpp') + t = TempFile('tstgmp.cpp') t.add('#include\nint main() { mpz_t t; mpz_init(t); mpz_clear(t); return 0; }\n') t.commit() - return exec_compiler_cmd([cc, CPPFLAGS, CXXFLAGS, 'tst.cpp', LDFLAGS, '-lgmp']) == 0 + return exec_compiler_cmd([cc, CPPFLAGS, 'tstgmp.cpp', LDFLAGS, '-lgmp']) == 0 + +def test_openmp(cc): + if is_verbose(): + print "Testing OpenMP..." + t = TempFile('tstomp.cpp') + t.add('#include\nint main() { return omp_in_parallel() ? 1 : 0; }\n') + t.commit() + return exec_compiler_cmd([cc, CPPFLAGS, 'tstomp.cpp', LDFLAGS, '-fopenmp']) == 0 def check_java(): t = TempFile('Hello.java') @@ -1280,12 +1290,12 @@ def mk_config(): else: CPPFLAGS = '%s -D_MP_INTERNAL' % CPPFLAGS CXXFLAGS = '%s -c' % CXXFLAGS - if is_CXX_gpp(): + HAS_OMP = test_openmp(CXX) + if HAS_OMP: CXXFLAGS = '%s -fopenmp -mfpmath=sse' % CXXFLAGS LDFLAGS = '%s -fopenmp' % LDFLAGS SLIBEXTRAFLAGS = '-fopenmp' else: - # CLang does not support OMP CXXFLAGS = '%s -D_NO_OMP_' % CXXFLAGS SLIBEXTRAFLAGS = '' sysname = os.uname()[0] @@ -1351,6 +1361,7 @@ def mk_config(): print 'C++ Compiler: %s' % CXX print 'C Compiler : %s' % CC print 'Arithmetic: %s' % ARITH + print 'OpenMP: %s' % HAS_OMP print 'Prefix: %s' % PREFIX print '64-bit: %s' % is64() if is_java_enabled(): From e055e0b47cd97d4f4e9af2bb9ee3a93047d004aa Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 10:41:50 -0800 Subject: [PATCH 23/60] Fixed other parameter setting problems Signed-off-by: Leonardo de Moura --- src/smt/tactic/smt_tactic.cpp | 1 + src/tactic/ufbv/ufbv_tactic.cpp | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/smt/tactic/smt_tactic.cpp b/src/smt/tactic/smt_tactic.cpp index 2c7d58b1a..95b150a8c 100644 --- a/src/smt/tactic/smt_tactic.cpp +++ b/src/smt/tactic/smt_tactic.cpp @@ -139,6 +139,7 @@ public: ast_manager & m = in->m(); TRACE("smt_tactic", tout << this << "\nAUTO_CONFIG: " << fparams().m_auto_config << " HIDIV0: " << fparams().m_hi_div0 << " " << " PREPROCESS: " << fparams().m_preprocess << "\n"; + tout << "RELEVANCY: " << fparams().m_relevancy_lvl << "\n"; tout << "fail-if-inconclusive: " << m_fail_if_inconclusive << "\n"; tout << "params_ref: " << m_params_ref << "\n";); TRACE("smt_tactic_detail", in->display(tout);); diff --git a/src/tactic/ufbv/ufbv_tactic.cpp b/src/tactic/ufbv/ufbv_tactic.cpp index 80d403b67..9d16d7f9a 100644 --- a/src/tactic/ufbv/ufbv_tactic.cpp +++ b/src/tactic/ufbv/ufbv_tactic.cpp @@ -62,9 +62,8 @@ tactic * mk_ufbv_preprocessor_tactic(ast_manager & m, params_ref const & p) { tactic * mk_ufbv_tactic(ast_manager & m, params_ref const & p) { params_ref main_p(p); main_p.set_bool("mbqi", true); - main_p.set_uint("mbqi_max_iterations", -1); + main_p.set_uint("mbqi.max_iterations", UINT_MAX); main_p.set_bool("elim_and", true); - main_p.set_bool("solver", true); tactic * t = and_then(repeat(mk_ufbv_preprocessor_tactic(m, main_p), 2), mk_smt_tactic_using(false, main_p)); From bd0366eef70508f27ac0f91e0081f4dbc8f45a4a Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 11:09:14 -0800 Subject: [PATCH 24/60] Fixed problems in the new parameter setting. Many thanks to Nuno Lopes for sending a benchmark that exposed the problem, a noticing the discrepancy between unstable and master branches. Signed-off-by: Leonardo de Moura --- src/ast/pattern/pattern_inference_params_helper.pyg | 2 +- src/smt/params/smt_params_helper.pyg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ast/pattern/pattern_inference_params_helper.pyg b/src/ast/pattern/pattern_inference_params_helper.pyg index 5d64e8e52..52c6c653e 100644 --- a/src/ast/pattern/pattern_inference_params_helper.pyg +++ b/src/ast/pattern/pattern_inference_params_helper.pyg @@ -5,7 +5,7 @@ def_module_params(class_name='pattern_inference_params_helper', params=(('max_multi_patterns', UINT, 0, 'when patterns are not provided, the prover uses a heuristic to infer them, this option sets the threshold on the number of extra multi-patterns that can be created; by default, the prover creates at most one multi-pattern when there is no unary pattern'), ('block_loop_patterns', BOOL, True, 'block looping patterns during pattern inference'), ('arith', UINT, 1, '0 - do not infer patterns with arithmetic terms, 1 - use patterns with arithmetic terms if there is no other pattern, 2 - always use patterns with arithmetic terms'), - ('use_database', BOOL, True, 'use pattern database'), + ('use_database', BOOL, False, 'use pattern database'), ('arith_weight', UINT, 5, 'default weight for quantifiers where the only available pattern has nested arithmetic terms'), ('non_nested_arith_weight', UINT, 10, 'default weight for quantifiers where the only available pattern has non nested arithmetic terms'), ('pull_quantifiers', BOOL, True, 'pull nested quantifiers, if no pattern was found'), diff --git a/src/smt/params/smt_params_helper.pyg b/src/smt/params/smt_params_helper.pyg index 071d843a3..1b8058b44 100644 --- a/src/smt/params/smt_params_helper.pyg +++ b/src/smt/params/smt_params_helper.pyg @@ -7,7 +7,7 @@ def_module_params(module_name='smt', ('relevancy', UINT, 2, 'relevancy propagation heuristic: 0 - disabled, 1 - relevancy is tracked by only affects quantifier instantiation, 2 - relevancy is tracked, and an atom is only asserted if it is relevant'), ('macro_finder', BOOL, False, 'try to find universally quantified formulas that can be viewed as macros'), ('ematching', BOOL, True, 'E-Matching based quantifier instantiation'), - ('phase_selection', UINT, 4, 'phase selection heuristic: 0 - always false, 1 - always true, 2 - phase caching, 3 - phase caching conservative, 4 - phase caching conservative 2, 5 - random, 6 - number of occurrences'), + ('phase_selection', UINT, 3, 'phase selection heuristic: 0 - always false, 1 - always true, 2 - phase caching, 3 - phase caching conservative, 4 - phase caching conservative 2, 5 - random, 6 - number of occurrences'), ('restart_strategy', UINT, 1, '0 - geometric, 1 - inner-outer-geometric, 2 - luby, 3 - fixed, 4 - arithmetic'), ('restart_factor', DOUBLE, 1.1, 'when using geometric (or inner-outer-geometric) progression of restarts, it specifies the constant used to multiply the currect restart threshold'), ('case_split', UINT, 1, '0 - case split based on variable activity, 1 - similar to 0, but delay case splits created during the search, 2 - similar to 0, but cache the relevancy, 3 - case split based on relevancy (structural splitting), 4 - case split on relevancy and activity, 5 - case split on relevancy and current goal'), From a07b459fdf4562288816d947315469da81447f27 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 12:53:51 -0800 Subject: [PATCH 25/60] Added is_unique_value. Its semantics is equal to the old is_value method. The contract for is_value changed. See comments at ast.h for more information. Signed-off-by: Leonardo de Moura --- src/ast/arith_decl_plugin.cpp | 46 +++++++++++++----- src/ast/arith_decl_plugin.h | 12 +++-- src/ast/ast.cpp | 29 ++++++++++++ src/ast/ast.h | 47 +++++++++++++++++-- src/ast/bv_decl_plugin.h | 4 +- src/ast/datatype_decl_plugin.h | 3 ++ src/ast/dl_decl_plugin.h | 3 +- src/ast/float_decl_plugin.h | 1 + src/ast/rewriter/bool_rewriter.cpp | 2 +- src/ast/rewriter/th_rewriter.cpp | 7 ++- src/ast/seq_decl_plugin.h | 5 +- .../simplifier/array_simplifier_plugin.cpp | 20 ++++---- src/model/func_interp.cpp | 8 ++-- src/model/func_interp.h | 4 +- src/smt/proto_model/proto_model.cpp | 2 +- src/smt/smt_internalizer.cpp | 2 +- src/smt/user_plugin/user_decl_plugin.h | 2 + src/tactic/core/cofactor_elim_term_ite.cpp | 4 +- src/tactic/core/reduce_args_tactic.cpp | 6 +-- 19 files changed, 157 insertions(+), 50 deletions(-) diff --git a/src/ast/arith_decl_plugin.cpp b/src/ast/arith_decl_plugin.cpp index 4aadafae2..a89cc18d0 100644 --- a/src/ast/arith_decl_plugin.cpp +++ b/src/ast/arith_decl_plugin.cpp @@ -38,13 +38,6 @@ struct arith_decl_plugin::algebraic_numbers_wrapper { unsigned mk_id(algebraic_numbers::anum const & val) { SASSERT(!m_amanager.is_rational(val)); - // TODO: avoid linear scan. Use hashtable based on the floor of val - unsigned sz = m_nums.size(); - for (unsigned i = 0; i < sz; i++) { - algebraic_numbers::anum const & other = m_nums.get(i); - if (m_amanager.eq(val, other)) - return i; - } unsigned new_id = m_id_gen.mk(); m_nums.reserve(new_id+1); m_amanager.set(m_nums[new_id], val); @@ -71,13 +64,13 @@ struct arith_decl_plugin::algebraic_numbers_wrapper { }; -arith_decl_plugin::algebraic_numbers_wrapper & arith_decl_plugin::aw() { +arith_decl_plugin::algebraic_numbers_wrapper & arith_decl_plugin::aw() const { if (m_aw == 0) - m_aw = alloc(algebraic_numbers_wrapper); + const_cast(this)->m_aw = alloc(algebraic_numbers_wrapper); return *m_aw; } -algebraic_numbers::manager & arith_decl_plugin::am() { +algebraic_numbers::manager & arith_decl_plugin::am() const { return aw().m_amanager; } @@ -509,16 +502,43 @@ void arith_decl_plugin::get_op_names(svector& op_names, symbol con } } -bool arith_decl_plugin::is_value(app* e) const { - return is_app_of(e, m_family_id, OP_NUM); +bool arith_decl_plugin::is_value(app * e) const { + return + is_app_of(e, m_family_id, OP_NUM) || + is_app_of(e, m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM) || + is_app_of(e, m_family_id, OP_PI) || + is_app_of(e, m_family_id, OP_E); } -bool arith_decl_plugin::are_distinct(app* a, app* b) const { +bool arith_decl_plugin::is_unique_value(app * e) const { + return + is_app_of(e, m_family_id, OP_NUM) || + is_app_of(e, m_family_id, OP_PI) || + is_app_of(e, m_family_id, OP_E); +} + +bool arith_decl_plugin::are_equal(app * a, app * b) const { + if (decl_plugin::are_equal(a, b)) { + return true; + } + + if (is_app_of(a, m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM) && is_app_of(b, m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM)) { + return am().eq(aw().to_anum(a->get_decl()), aw().to_anum(b->get_decl())); + } + + return false; +} + +bool arith_decl_plugin::are_distinct(app * a, app * b) const { TRACE("are_distinct_bug", tout << mk_ismt2_pp(a, *m_manager) << "\n" << mk_ismt2_pp(b, *m_manager) << "\n";); if (decl_plugin::are_distinct(a,b)) { return true; } + if (is_app_of(a, m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM) && is_app_of(b, m_family_id, OP_IRRATIONAL_ALGEBRAIC_NUM)) { + return am().neq(aw().to_anum(a->get_decl()), aw().to_anum(b->get_decl())); + } + #define is_non_zero(e) is_app_of(e,m_family_id, OP_NUM) && !to_app(e)->get_decl()->get_parameter(0).get_rational().is_zero() if (is_app_of(a, m_family_id, OP_ADD) && diff --git a/src/ast/arith_decl_plugin.h b/src/ast/arith_decl_plugin.h index 6a377c577..b8ad11506 100644 --- a/src/ast/arith_decl_plugin.h +++ b/src/ast/arith_decl_plugin.h @@ -141,8 +141,8 @@ public: virtual ~arith_decl_plugin(); virtual void finalize(); - algebraic_numbers::manager & am(); - algebraic_numbers_wrapper & aw(); + algebraic_numbers::manager & am() const; + algebraic_numbers_wrapper & aw() const; virtual void del(parameter const & p); virtual parameter translate(parameter const & p, decl_plugin & target); @@ -159,9 +159,13 @@ public: virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned num_args, expr * const * args, sort * range); - virtual bool is_value(app* e) const; + virtual bool is_value(app * e) const; - virtual bool are_distinct(app* a, app* b) const; + virtual bool is_unique_value(app * e) const; + + virtual bool are_equal(app * a, app * b) const; + + virtual bool are_distinct(app * a, app * b) const; virtual void get_op_names(svector & op_names, symbol const & logic); diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index ae82dcadf..bd5ffaf35 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -872,6 +872,10 @@ bool basic_decl_plugin::is_value(app* a) const { return a->get_decl() == m_true_decl || a->get_decl() == m_false_decl; } +bool basic_decl_plugin::is_unique_value(app* a) const { + return is_value(a); +} + void basic_decl_plugin::finalize() { #define DEC_REF(FIELD) if (FIELD) { m_manager->dec_ref(FIELD); } #define DEC_ARRAY_REF(FIELD) m_manager->dec_array_ref(FIELD.size(), FIELD.begin()) @@ -1151,6 +1155,10 @@ bool model_value_decl_plugin::is_value(app* n) const { return is_app_of(n, m_family_id, OP_MODEL_VALUE); } +bool model_value_decl_plugin::is_unique_value(app* n) const { + return is_value(n); +} + // ----------------------------------- // // user_sort_plugin @@ -1442,6 +1450,27 @@ bool ast_manager::is_value(expr* e) const { return false; } +bool ast_manager::is_unique_value(expr* e) const { + decl_plugin const * p = 0; + if (is_app(e)) { + p = get_plugin(to_app(e)->get_family_id()); + return p && p->is_unique_value(to_app(e)); + } + return false; +} + +bool ast_manager::are_equal(expr * a, expr * b) const { + if (is_app(a) && is_app(b)) { + app* ap = to_app(a), *bp = to_app(b); + decl_plugin const * p = get_plugin(ap->get_family_id()); + if (!p) { + p = get_plugin(bp->get_family_id()); + } + return p && p->are_equal(ap, bp); + } + return false; +} + bool ast_manager::are_distinct(expr* a, expr* b) const { if (is_app(a) && is_app(b)) { app* ap = to_app(a), *bp = to_app(b); diff --git a/src/ast/ast.h b/src/ast/ast.h index 2a0872721..0ca47ccec 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -933,9 +933,39 @@ public: virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const* parameters, unsigned num_args, expr * const * args, sort * range); - virtual bool is_value(app*) const { return false; } + /** + \brief Return true if the plugin can decide whether two + interpreted constants are equal or not. + + For all a, b: + If is_value(a) and is_value(b) + Then, + are_equal(a, b) != are_distinct(a, b) + + The may be much more expensive than checking a pointer. - virtual bool are_distinct(app* a, app* b) const { return a != b && is_value(a) && is_value(b); } + We need this because some plugin values are too expensive too canonize. + */ + virtual bool is_value(app * a) const { return false; } + + /** + \brief Return true if \c a is a unique plugin value. + The following property should hold for unique theory values: + + For all a, b: + If is_unique_value(a) and is_unique_value(b) + Then, + a == b (pointer equality) + IFF + the interpretations of these theory terms are equal. + + \remark This is a stronger version of is_value. + */ + virtual bool is_unique_value(app * a) const { return false; } + + virtual bool are_equal(app * a, app * b) const { return a == b && is_unique_value(a) && is_unique_value(b); } + + virtual bool are_distinct(app * a, app * b) const { return a != b && is_unique_value(a) && is_unique_value(b); } virtual void get_op_names(svector & op_names, symbol const & logic = symbol()) {} @@ -1080,6 +1110,8 @@ public: virtual void get_sort_names(svector & sort_names, symbol const & logic); virtual bool is_value(app* a) const; + + virtual bool is_unique_value(app* a) const; sort * mk_bool_sort() const { return m_bool_sort; } sort * mk_proof_sort() const { return m_proof_sort; } @@ -1116,7 +1148,6 @@ public: virtual decl_plugin * mk_fresh() { return alloc(label_decl_plugin); } - virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters); /** @@ -1198,6 +1229,8 @@ public: unsigned arity, sort * const * domain, sort * range); virtual bool is_value(app* n) const; + + virtual bool is_unique_value(app* a) const; }; // ----------------------------------- @@ -1442,9 +1475,13 @@ public: */ void set_next_expr_id(unsigned id); - bool is_value(expr* e) const; + bool is_value(expr * e) const; + + bool is_unique_value(expr * e) const; - bool are_distinct(expr* a, expr* b) const; + bool are_equal(expr * a, expr * b) const; + + bool are_distinct(expr * a, expr * b) const; bool contains(ast * a) const { return m_ast_table.contains(a); } diff --git a/src/ast/bv_decl_plugin.h b/src/ast/bv_decl_plugin.h index a98f39323..34f2baf6b 100644 --- a/src/ast/bv_decl_plugin.h +++ b/src/ast/bv_decl_plugin.h @@ -260,8 +260,10 @@ public: virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, unsigned num_args, expr * const * args, sort * range); - virtual bool is_value(app* e) const; + virtual bool is_value(app * e) const; + virtual bool is_unique_value(app * e) const { return is_value(e); } + virtual void get_op_names(svector & op_names, symbol const & logic); virtual void get_sort_names(svector & sort_names, symbol const & logic); diff --git a/src/ast/datatype_decl_plugin.h b/src/ast/datatype_decl_plugin.h index a8bd28d8e..96b678fb2 100644 --- a/src/ast/datatype_decl_plugin.h +++ b/src/ast/datatype_decl_plugin.h @@ -146,6 +146,9 @@ public: virtual bool is_fully_interp(sort const * s) const; virtual bool is_value(app* e) const; + + virtual bool is_unique_value(app * e) const { return is_value(e); } + private: bool is_value_visit(expr * arg, ptr_buffer & todo) const; }; diff --git a/src/ast/dl_decl_plugin.h b/src/ast/dl_decl_plugin.h index 32e3c6da9..559aff7bd 100644 --- a/src/ast/dl_decl_plugin.h +++ b/src/ast/dl_decl_plugin.h @@ -130,7 +130,8 @@ namespace datalog { virtual void get_sort_names(svector & sort_names, symbol const & logic); - virtual bool is_value(app* e) const { return is_app_of(e, m_family_id, OP_DL_CONSTANT); } + virtual bool is_value(app * e) const { return is_app_of(e, m_family_id, OP_DL_CONSTANT); } + virtual bool is_unique_value(app * e) const { return is_value(e); } }; diff --git a/src/ast/float_decl_plugin.h b/src/ast/float_decl_plugin.h index c4503349b..6f1ef5ec2 100644 --- a/src/ast/float_decl_plugin.h +++ b/src/ast/float_decl_plugin.h @@ -141,6 +141,7 @@ public: virtual void get_op_names(svector & op_names, symbol const & logic); virtual void get_sort_names(svector & sort_names, symbol const & logic); virtual bool is_value(app* e) const; + virtual bool is_unique_value(app* e) const { return is_value(e); } mpf_manager & fm() { return m_fm; } func_decl * mk_value_decl(mpf const & v); diff --git a/src/ast/rewriter/bool_rewriter.cpp b/src/ast/rewriter/bool_rewriter.cpp index 4fcaf02fe..b5f18a461 100644 --- a/src/ast/rewriter/bool_rewriter.cpp +++ b/src/ast/rewriter/bool_rewriter.cpp @@ -732,7 +732,7 @@ br_status bool_rewriter::mk_distinct_core(unsigned num_args, expr * const * args return BR_DONE; } visited.mark(arg); - if (!m().is_value(arg)) + if (!m().is_unique_value(arg)) all_value = false; } if (all_value) { diff --git a/src/ast/rewriter/th_rewriter.cpp b/src/ast/rewriter/th_rewriter.cpp index 29034d396..966544b78 100644 --- a/src/ast/rewriter/th_rewriter.cpp +++ b/src/ast/rewriter/th_rewriter.cpp @@ -200,7 +200,12 @@ struct th_rewriter_cfg : public default_rewriter_cfg { expr * mk_eq_value(expr * lhs, expr * value) { SASSERT(m().is_value(value)); if (m().is_value(lhs)) { - return lhs == value ? m().mk_true() : m().mk_false(); + if (m().are_equal(lhs, value)) { + return m().mk_true(); + } + else if (m().are_distinct(lhs, value)) { + return m().mk_false(); + } } return m().mk_eq(lhs, value); } diff --git a/src/ast/seq_decl_plugin.h b/src/ast/seq_decl_plugin.h index c055694eb..1bb3f3581 100644 --- a/src/ast/seq_decl_plugin.h +++ b/src/ast/seq_decl_plugin.h @@ -112,7 +112,10 @@ public: virtual void get_sort_names(svector & sort_names, symbol const & logic); - virtual bool is_value(app* e) const; + virtual bool is_value(app * e) const; + + virtual bool is_unique_value(app * e) const { return is_value(e); } + }; diff --git a/src/ast/simplifier/array_simplifier_plugin.cpp b/src/ast/simplifier/array_simplifier_plugin.cpp index 75c3cdbce..bf9ca8ffe 100644 --- a/src/ast/simplifier/array_simplifier_plugin.cpp +++ b/src/ast/simplifier/array_simplifier_plugin.cpp @@ -293,7 +293,7 @@ bool array_simplifier_plugin::all_const_array(unsigned num_args, expr* const* ar bool array_simplifier_plugin::all_values(unsigned num_args, expr* const* args) const { for (unsigned i = 0; i < num_args; ++i) { - if (!m_manager.is_value(args[i])) { + if (!m_manager.is_unique_value(args[i])) { return false; } } @@ -331,7 +331,7 @@ lbool array_simplifier_plugin::eq_default(expr* def, unsigned arity, unsigned nu if (st[i][arity] == def) { continue; } - if (m_manager.is_value(st[i][arity]) && m_manager.is_value(def)) { + if (m_manager.is_unique_value(st[i][arity]) && m_manager.is_unique_value(def)) { return l_false; } return l_undef; @@ -342,7 +342,7 @@ lbool array_simplifier_plugin::eq_default(expr* def, unsigned arity, unsigned nu bool array_simplifier_plugin::insert_table(expr* def, unsigned arity, unsigned num_st, expr*const* const* st, arg_table& table) { for (unsigned i = 0; i < num_st; ++i ) { for (unsigned j = 0; j < arity; ++j) { - if (!m_manager.is_value(st[i][j])) { + if (!m_manager.is_unique_value(st[i][j])) { return false; } } @@ -380,12 +380,12 @@ lbool array_simplifier_plugin::eq_stores(expr* def, unsigned arity, unsigned num table2.erase(e1); continue; } - if (m_manager.is_value(v1) && m_manager.is_value(v2)) { + if (m_manager.is_unique_value(v1) && m_manager.is_unique_value(v2)) { return l_false; } return l_undef; } - else if (m_manager.is_value(v1) && m_manager.is_value(def) && v1 != def) { + else if (m_manager.is_unique_value(v1) && m_manager.is_unique_value(def) && v1 != def) { return l_false; } } @@ -394,7 +394,7 @@ lbool array_simplifier_plugin::eq_stores(expr* def, unsigned arity, unsigned num for (; it != end; ++it) { args_entry const & e = *it; expr* v = e.m_args[arity]; - if (m_manager.is_value(v) && m_manager.is_value(def) && v != def) { + if (m_manager.is_unique_value(v) && m_manager.is_unique_value(def) && v != def) { return l_false; } } @@ -431,7 +431,7 @@ bool array_simplifier_plugin::reduce_eq(expr * lhs, expr * rhs, expr_ref & resul return false; } } - else if (m_manager.is_value(c1) && m_manager.is_value(c2)) { + else if (m_manager.is_unique_value(c1) && m_manager.is_unique_value(c2)) { result = m_manager.mk_false(); return true; } @@ -464,7 +464,7 @@ array_simplifier_plugin::mk_select_const(expr* m, app* index, expr_ref& result) // // Unfold and cache the store while searching for value of index. // - while (is_store(a) && m_manager.is_value(to_app(a)->get_arg(1))) { + while (is_store(a) && m_manager.is_unique_value(to_app(a)->get_arg(1))) { app* b = to_app(a); app* c = to_app(b->get_arg(1)); @@ -728,7 +728,7 @@ void array_simplifier_plugin::mk_select(unsigned num_args, expr * const * args, return; } - bool is_const_select = num_args == 2 && m_manager.is_value(args[1]); + bool is_const_select = num_args == 2 && m_manager.is_unique_value(args[1]); app* const_index = is_const_select?to_app(args[1]):0; unsigned num_const_stores = 0; expr_ref tmp(m_manager); @@ -766,7 +766,7 @@ void array_simplifier_plugin::mk_select(unsigned num_args, expr * const * args, expr * else_branch = 0; entry[0] = nested_array; if (is_const_select) { - if (m_manager.is_value(to_app(m)->get_arg(1))) { + if (m_manager.is_unique_value(to_app(m)->get_arg(1))) { app* const_index2 = to_app(to_app(m)->get_arg(1)); // // we found the value, all other stores are different. diff --git a/src/model/func_interp.cpp b/src/model/func_interp.cpp index 678d95c86..ae4c657bd 100644 --- a/src/model/func_interp.cpp +++ b/src/model/func_interp.cpp @@ -49,10 +49,10 @@ void func_entry::set_result(ast_manager & m, expr * r) { m_result = r; } -bool func_entry::eq_args(unsigned arity, expr * const * args) const { +bool func_entry::eq_args(ast_manager & m, unsigned arity, expr * const * args) const { unsigned i = 0; for (; i < arity; i++) { - if (m_args[i] != args[i]) + if (!m.are_equal(m_args[i], args[i])) return false; } return true; @@ -131,7 +131,7 @@ bool func_interp::is_constant() const { } /** - \brief Return a func_entry e such that e.m_args[i] == args[i] for all i in [0, m_arity). + \brief Return a func_entry e such that m().are_equal(e.m_args[i], args[i]) for all i in [0, m_arity). If such entry does not exist then return 0, and store set args_are_values to true if for all entries e e.args_are_values() is true. */ @@ -140,7 +140,7 @@ func_entry * func_interp::get_entry(expr * const * args) const { ptr_vector::const_iterator end = m_entries.end(); for (; it != end; ++it) { func_entry * curr = *it; - if (curr->eq_args(m_arity, args)) + if (curr->eq_args(m(), m_arity, args)) return curr; } return 0; diff --git a/src/model/func_interp.h b/src/model/func_interp.h index b10fe0dad..fd21a6a7c 100644 --- a/src/model/func_interp.h +++ b/src/model/func_interp.h @@ -58,9 +58,9 @@ public: expr * get_arg(unsigned idx) const { return m_args[idx]; } expr * const * get_args() const { return m_args; } /** - \brief Return true if m_args[i] == args[i] for all i in [0, arity) + \brief Return true if m.are_equal(m_args[i], args[i]) for all i in [0, arity) */ - bool eq_args(unsigned arity, expr * const * args) const; + bool eq_args(ast_manager & m, unsigned arity, expr * const * args) const; }; class func_interp { diff --git a/src/smt/proto_model/proto_model.cpp b/src/smt/proto_model/proto_model.cpp index 34742e3a0..92110bc1a 100644 --- a/src/smt/proto_model/proto_model.cpp +++ b/src/smt/proto_model/proto_model.cpp @@ -155,7 +155,7 @@ bool eval(func_interp & fi, simplifier & s, expr * const * args, expr_ref & resu basic_simplifier_plugin * bs = static_cast(s.get_plugin(fi.m().get_basic_family_id())); for (unsigned k = 0; k < fi.num_entries(); k++) { func_entry const * curr = fi.get_entry(k); - SASSERT(!curr->eq_args(fi.get_arity(), args)); + SASSERT(!curr->eq_args(fi.m(), fi.get_arity(), args)); if (!actuals_are_values || !curr->args_are_values()) { expr_ref_buffer eqs(fi.m()); unsigned i = fi.get_arity(); diff --git a/src/smt/smt_internalizer.cpp b/src/smt/smt_internalizer.cpp index 556222c33..b3f16a3ce 100644 --- a/src/smt/smt_internalizer.cpp +++ b/src/smt/smt_internalizer.cpp @@ -907,7 +907,7 @@ namespace smt { } enode * e = enode::mk(m_manager, m_region, m_app2enode, n, generation, suppress_args, merge_tf, m_scope_lvl, cgc_enabled, true); TRACE("mk_enode_detail", tout << "e.get_num_args() = " << e->get_num_args() << "\n";); - if (n->get_num_args() == 0 && m_manager.is_value(n)) + if (n->get_num_args() == 0 && m_manager.is_unique_value(n)) e->mark_as_interpreted(); TRACE("mk_var_bug", tout << "mk_enode: " << id << "\n";); TRACE("generation", tout << "mk_enode: " << id << " " << generation << "\n";); diff --git a/src/smt/user_plugin/user_decl_plugin.h b/src/smt/user_plugin/user_decl_plugin.h index dc2fd55a1..9e6bd70c4 100644 --- a/src/smt/user_plugin/user_decl_plugin.h +++ b/src/smt/user_plugin/user_decl_plugin.h @@ -49,6 +49,8 @@ public: virtual bool is_value(app*) const; + virtual bool is_unique_value(app * a) const { return is_value(a); } + bool is_value(func_decl *) const; virtual void get_op_names(svector & op_names, symbol const & logic); diff --git a/src/tactic/core/cofactor_elim_term_ite.cpp b/src/tactic/core/cofactor_elim_term_ite.cpp index 78d532357..d81b4fa13 100644 --- a/src/tactic/core/cofactor_elim_term_ite.cpp +++ b/src/tactic/core/cofactor_elim_term_ite.cpp @@ -355,12 +355,12 @@ struct cofactor_elim_term_ite::imp { expr * lhs; expr * rhs; if (m.is_eq(t, lhs, rhs)) { - if (m.is_value(lhs)) { + if (m.is_unique_value(lhs)) { m_term = rhs; m_value = to_app(lhs); TRACE("set_cofactor_atom", tout << "term:\n" << mk_ismt2_pp(m_term, m) << "\nvalue: " << mk_ismt2_pp(m_value, m) << "\n";); } - else if (m.is_value(rhs)) { + else if (m.is_unique_value(rhs)) { m_term = lhs; m_value = to_app(rhs); TRACE("set_cofactor_atom", tout << "term:\n" << mk_ismt2_pp(m_term, m) << "\nvalue: " << mk_ismt2_pp(m_value, m) << "\n";); diff --git a/src/tactic/core/reduce_args_tactic.cpp b/src/tactic/core/reduce_args_tactic.cpp index 686c5128d..59ed2dcd3 100644 --- a/src/tactic/core/reduce_args_tactic.cpp +++ b/src/tactic/core/reduce_args_tactic.cpp @@ -128,7 +128,7 @@ struct reduce_args_tactic::imp { unsigned j = n->get_num_args(); while (j > 0) { --j; - if (m_manager.is_value(n->get_arg(j))) + if (m_manager.is_unique_value(n->get_arg(j))) return; } m_non_cadidates.insert(d); @@ -185,13 +185,13 @@ struct reduce_args_tactic::imp { it->m_value.reserve(j); while (j > 0) { --j; - it->m_value.set(j, m_manager.is_value(n->get_arg(j))); + it->m_value.set(j, m_manager.is_unique_value(n->get_arg(j))); } } else { SASSERT(j == it->m_value.size()); while (j > 0) { --j; - it->m_value.set(j, it->m_value.get(j) && m_manager.is_value(n->get_arg(j))); + it->m_value.set(j, it->m_value.get(j) && m_manager.is_unique_value(n->get_arg(j))); } } } From cba449b75e5e0aaffcbb5df533afabb3151608e3 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 15:16:46 -0800 Subject: [PATCH 26/60] more parameter issues Signed-off-by: Leonardo de Moura --- scripts/mk_win_dist.py | 2 +- src/cmd_context/cmd_context.cpp | 3 +++ src/smt/params/smt_params.cpp | 2 +- src/smt/params/smt_params_helper.pyg | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index 3cebce7f6..57ae66b03 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -100,7 +100,7 @@ def mk_build_dirs(): def check_vc_cmd_prompt(): try: DEVNULL = open(os.devnull, 'wb') - subprocess.call(['cl'], stdin=DEVNULL, stderr=DEVNULL) + subprocess.call(['cl'], stdout=DEVNULL, stderr=DEVNULL) except: raise MKException("You must execute the mk_win_dist.py script on a Visual Studio Command Prompt") diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index e14d5139c..ae375fc99 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -37,6 +37,7 @@ Notes: #include"well_sorted.h" #include"model_evaluator.h" #include"for_each_expr.h" +#include"scoped_timer.h" func_decls::func_decls(ast_manager & m, func_decl * f): m_decls(TAG(func_decl*, f, 0)) { @@ -1304,9 +1305,11 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions if (m_solver) { m_check_sat_result = m_solver.get(); // solver itself stores the result. m_solver->set_progress_callback(this); + unsigned timeout = m_params.m_timeout; scoped_watch sw(*this); cancel_eh eh(*m_solver); scoped_ctrl_c ctrlc(eh); + scoped_timer timer(timeout, &eh); lbool r; try { r = m_solver->check_sat(num_assumptions, assumptions); diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp index 22122cd83..ec2fbc93c 100644 --- a/src/smt/params/smt_params.cpp +++ b/src/smt/params/smt_params.cpp @@ -32,6 +32,7 @@ void smt_params::updt_local_params(params_ref const & _p) { m_delay_units = p.delay_units(); m_delay_units_threshold = p.delay_units_threshold(); m_preprocess = _p.get_bool("preprocess", true); // hidden parameter + m_soft_timeout = p.soft_timeout(); if (_p.get_bool("arith.greatest_error_pivot", false)) m_arith_pivot_strategy = ARITH_PIVOT_GREATEST_ERROR; else if (_p.get_bool("arith.least_error_pivot", false)) @@ -48,7 +49,6 @@ void smt_params::updt_params(params_ref const & p) { void smt_params::updt_params(context_params const & p) { m_auto_config = p.m_auto_config; - m_soft_timeout = p.m_timeout; m_model = p.m_model; m_model_validate = p.m_model_validate; } diff --git a/src/smt/params/smt_params_helper.pyg b/src/smt/params/smt_params_helper.pyg index 1b8058b44..43dd1b586 100644 --- a/src/smt/params/smt_params_helper.pyg +++ b/src/smt/params/smt_params_helper.pyg @@ -14,6 +14,7 @@ def_module_params(module_name='smt', ('delay_units', BOOL, False, 'if true then z3 will not restart when a unit clause is learned'), ('delay_units_threshold', UINT, 32, 'maximum number of learned unit clauses before restarting, ingored if delay_units is false'), ('pull_nested_quantifiers', BOOL, False, 'pull nested quantifiers'), + ('soft_timeout', UINT, 0, 'soft timeout (0 means no timeout)'), ('mbqi', BOOL, True, 'model based quantifier instantiation (MBQI)'), ('mbqi.max_cexs', UINT, 1, 'initial maximal number of counterexamples used in MBQI, each counterexample generates a quantifier instantiation'), ('mbqi.max_cexs_incr', UINT, 0, 'increment for MBQI_MAX_CEXS, the increment is performed after each round of MBQI'), From c350943c783c8bf23148f2ec88130e69252e64d0 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 15:59:54 -0800 Subject: [PATCH 27/60] fixed bug introduced today Signed-off-by: Leonardo de Moura --- src/api/api_ast.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index c604927fd..404d9d9ac 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -324,7 +324,8 @@ extern "C" { switch (_a->get_kind()) { case AST_APP: { expr * e = to_expr(_a); - if (is_numeral_sort(c, of_sort(mk_c(c)->m().get_sort(e))) && mk_c(c)->m().is_value(e)) + // Real algebraic numbers are not considered Z3_NUMERAL_AST + if (is_numeral_sort(c, of_sort(mk_c(c)->m().get_sort(e))) && mk_c(c)->m().is_unique_value(e)) return Z3_NUMERAL_AST; return Z3_APP_AST; } From c011b05b61b1aaab47880f54a2ba3790c243bf88 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 17:48:57 -0800 Subject: [PATCH 28/60] exposing algebraic numbers in the API (working in progress) Signed-off-by: Leonardo de Moura --- scripts/mk_project.py | 4 +- src/api/api_algebraic.cpp | 198 +++++++++++++++++++++++++++++++ src/api/api_context.cpp | 1 + src/api/z3.h | 1 + src/api/z3_algebraic.h | 226 ++++++++++++++++++++++++++++++++++++ src/ast/arith_decl_plugin.h | 2 +- src/ast/ast.cpp | 6 + src/ast/ast.h | 5 + 8 files changed, 440 insertions(+), 3 deletions(-) create mode 100644 src/api/api_algebraic.cpp create mode 100644 src/api/z3_algebraic.h diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 707d067e2..3405d8751 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -59,10 +59,10 @@ def init_project_def(): add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa', 'aig_tactic', 'muz_qe', 'sls_tactic', 'subpaving_tactic'], 'tactic/portfolio') add_lib('smtparser', ['portfolio'], 'parsers/smt') add_lib('api', ['portfolio', 'user_plugin', 'smtparser'], - includes2install=['z3.h', 'z3_api.h', 'z3_v1.h', 'z3_macros.h']) + includes2install=['z3.h', 'z3_api.h', 'z3_v1.h', 'z3_macros.h', 'z3_algebraic.h']) add_exe('shell', ['api', 'sat', 'extra_cmds'], exe_name='z3') add_exe('test', ['api', 'fuzzing'], exe_name='test-z3', install=False) - API_files = ['z3_api.h'] + API_files = ['z3_api.h', 'z3_algebraic.h'] add_dll('api_dll', ['api', 'sat', 'extra_cmds'], 'api/dll', reexports=['api'], dll_name='libz3', diff --git a/src/api/api_algebraic.cpp b/src/api/api_algebraic.cpp new file mode 100644 index 000000000..5511332b1 --- /dev/null +++ b/src/api/api_algebraic.cpp @@ -0,0 +1,198 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + api_algebraic.cpp + +Abstract: + + Additional APIs for handling Z3 algebraic numbers encoded as + Z3_ASTs + +Author: + + Leonardo de Moura (leonardo) 2012-12-07 + +Notes: + +--*/ +#include +#include"z3.h" +#include"api_log_macros.h" +#include"api_context.h" + +extern "C" { + + Z3_bool Z3_API Z3_algebraic_is_value(Z3_context c, Z3_ast a) { + Z3_TRY; + LOG_Z3_algebraic_is_value(c, a); + RESET_ERROR_CODE(); + // TODO + return Z3_FALSE; + Z3_CATCH_RETURN(Z3_FALSE); + } + + Z3_bool Z3_API Z3_algebraic_is_pos(Z3_context c, Z3_ast a) { + Z3_TRY; + LOG_Z3_algebraic_is_pos(c, a); + RESET_ERROR_CODE(); + // TODO + return Z3_FALSE; + Z3_CATCH_RETURN(Z3_FALSE); + } + + Z3_bool Z3_API Z3_algebraic_is_neg(Z3_context c, Z3_ast a) { + Z3_TRY; + LOG_Z3_algebraic_is_neg(c, a); + RESET_ERROR_CODE(); + // TODO + return Z3_FALSE; + Z3_CATCH_RETURN(Z3_FALSE); + } + + Z3_bool Z3_API Z3_algebraic_is_zero(Z3_context c, Z3_ast a) { + Z3_TRY; + LOG_Z3_algebraic_is_zero(c, a); + RESET_ERROR_CODE(); + // TODO + return Z3_FALSE; + Z3_CATCH_RETURN(Z3_FALSE); + } + + int Z3_API Z3_algebraic_sign(Z3_context c, Z3_ast a) { + Z3_TRY; + LOG_Z3_algebraic_sign(c, a); + RESET_ERROR_CODE(); + // TODO + return 0; + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_algebraic_add(Z3_context c, Z3_ast a, Z3_ast b) { + Z3_TRY; + LOG_Z3_algebraic_add(c, a, b); + RESET_ERROR_CODE(); + // TODO + return 0; + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_algebraic_sub(Z3_context c, Z3_ast a, Z3_ast b) { + Z3_TRY; + LOG_Z3_algebraic_sub(c, a, b); + RESET_ERROR_CODE(); + // TODO + return 0; + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_algebraic_mul(Z3_context c, Z3_ast a, Z3_ast b) { + Z3_TRY; + LOG_Z3_algebraic_mul(c, a, b); + RESET_ERROR_CODE(); + // TODO + return 0; + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_algebraic_div(Z3_context c, Z3_ast a, Z3_ast b) { + Z3_TRY; + LOG_Z3_algebraic_div(c, a, b); + RESET_ERROR_CODE(); + // TODO + return 0; + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_algebraic_root(Z3_context c, Z3_ast a, unsigned k) { + Z3_TRY; + LOG_Z3_algebraic_root(c, a, k); + RESET_ERROR_CODE(); + // TODO + return 0; + Z3_CATCH_RETURN(0); + } + + Z3_ast Z3_API Z3_algebraic_power(Z3_context c, Z3_ast a, unsigned k) { + Z3_TRY; + LOG_Z3_algebraic_power(c, a, k); + RESET_ERROR_CODE(); + // TODO + return 0; + Z3_CATCH_RETURN(0); + } + + Z3_bool Z3_API Z3_algebraic_lt(Z3_context c, Z3_ast a, Z3_ast b) { + Z3_TRY; + LOG_Z3_algebraic_lt(c, a, b); + RESET_ERROR_CODE(); + // TODO + return Z3_FALSE; + Z3_CATCH_RETURN(Z3_FALSE); + } + + Z3_bool Z3_API Z3_algebraic_gt(Z3_context c, Z3_ast a, Z3_ast b) { + Z3_TRY; + LOG_Z3_algebraic_gt(c, a, b); + RESET_ERROR_CODE(); + // TODO + return Z3_FALSE; + Z3_CATCH_RETURN(Z3_FALSE); + } + + Z3_bool Z3_API Z3_algebraic_le(Z3_context c, Z3_ast a, Z3_ast b) { + Z3_TRY; + LOG_Z3_algebraic_le(c, a, b); + RESET_ERROR_CODE(); + // TODO + return Z3_FALSE; + Z3_CATCH_RETURN(Z3_FALSE); + } + + Z3_bool Z3_API Z3_algebraic_ge(Z3_context c, Z3_ast a, Z3_ast b) { + Z3_TRY; + LOG_Z3_algebraic_ge(c, a, b); + RESET_ERROR_CODE(); + // TODO + return Z3_FALSE; + Z3_CATCH_RETURN(0); + } + + Z3_bool Z3_API Z3_algebraic_eq(Z3_context c, Z3_ast a, Z3_ast b) { + Z3_TRY; + LOG_Z3_algebraic_eq(c, a, b); + RESET_ERROR_CODE(); + // TODO + return Z3_FALSE; + Z3_CATCH_RETURN(0); + } + + Z3_bool Z3_API Z3_algebraic_neq(Z3_context c, Z3_ast a, Z3_ast b) { + Z3_TRY; + LOG_Z3_algebraic_neq(c, a, b); + RESET_ERROR_CODE(); + // TODO + return Z3_FALSE; + Z3_CATCH_RETURN(0); + } + + Z3_ast_vector Z3_API Z3_algebraic_roots(Z3_context c, Z3_ast p, unsigned n, Z3_ast a[]) { + Z3_TRY; + LOG_Z3_algebraic_roots(c, p, n, a); + RESET_ERROR_CODE(); + // TODO + return 0; + Z3_CATCH_RETURN(0); + } + + int Z3_API Z3_algebraic_eval(Z3_context c, Z3_ast p, unsigned n, Z3_ast a[]) { + Z3_TRY; + LOG_Z3_algebraic_eval(c, p, n, a); + RESET_ERROR_CODE(); + // TODO + return 0; + Z3_CATCH_RETURN(0); + } + +}; diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 69b7ea999..1d2b22059 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -143,6 +143,7 @@ namespace api { { if (m_interruptable) (*m_interruptable)(); + m_manager.set_cancel(true); } } diff --git a/src/api/z3.h b/src/api/z3.h index 8df894f40..15f0a5985 100644 --- a/src/api/z3.h +++ b/src/api/z3.h @@ -24,6 +24,7 @@ Notes: #include #include"z3_macros.h" #include"z3_api.h" +#include"z3_algebraic.h" #undef __in #undef __out diff --git a/src/api/z3_algebraic.h b/src/api/z3_algebraic.h new file mode 100644 index 000000000..eef791170 --- /dev/null +++ b/src/api/z3_algebraic.h @@ -0,0 +1,226 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + z3_algebraic.h + +Abstract: + + Additional APIs for handling Z3 algebraic numbers encoded as + Z3_ASTs + +Author: + + Leonardo de Moura (leonardo) 2012-12-07 + +Notes: + +--*/ + +#ifndef _Z3_ALGEBRAIC_H_ +#define _Z3_ALGEBRAIC_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + /** + \brief Return Z3_TRUE if \c can be used as value in the Z3 real algebraic + number package. + + def_API('Z3_algebraic_is_value', BOOL, (_in(CONTEXT), _in(AST))) + */ + Z3_bool Z3_API Z3_algebraic_is_value(__in Z3_context c, __in Z3_ast a); + + /** + \brief Return the Z3_TRUE if \c a is positive, and Z3_FALSE otherwise. + + \pre Z3_algebraic_is_value(c, a) + + def_API('Z3_algebraic_is_pos', BOOL, (_in(CONTEXT), _in(AST))) + */ + Z3_bool Z3_API Z3_algebraic_is_pos(__in Z3_context c, __in Z3_ast a); + + /** + \brief Return the Z3_TRUE if \c a is negative, and Z3_FALSE otherwise. + + \pre Z3_algebraic_is_value(c, a) + + def_API('Z3_algebraic_is_neg', BOOL, (_in(CONTEXT), _in(AST))) + */ + Z3_bool Z3_API Z3_algebraic_is_neg(__in Z3_context c, __in Z3_ast a); + + /** + \brief Return the Z3_TRUE if \c a is zero, and Z3_FALSE otherwise. + + \pre Z3_algebraic_is_value(c, a) + + def_API('Z3_algebraic_is_zero', BOOL, (_in(CONTEXT), _in(AST))) + */ + Z3_bool Z3_API Z3_algebraic_is_zero(__in Z3_context c, __in Z3_ast a); + + /** + \brief Return 1 if \c a is positive, 0 if \c a is zero, and -1 if \c a is negative. + + \pre Z3_algebraic_is_value(c, a) + + def_API('Z3_algebraic_sign', INT, (_in(CONTEXT), _in(AST))) + */ + int Z3_API Z3_algebraic_sign(__in Z3_context c, __in Z3_ast a); + + /** + \brief Return the value a + b. + + \pre Z3_algebraic_is_value(c, a) + \pre Z3_algebraic_is_value(c, b) + \post Z3_algebraic_is_value(c, result) + + def_API('Z3_algebraic_add', AST, (_in(CONTEXT), _in(AST), _in(AST))) + */ + Z3_ast Z3_API Z3_algebraic_add(__in Z3_context c, __in Z3_ast a, __in Z3_ast b); + + /** + \brief Return the value a - b. + + \pre Z3_algebraic_is_value(c, a) + \pre Z3_algebraic_is_value(c, b) + \post Z3_algebraic_is_value(c, result) + + def_API('Z3_algebraic_sub', AST, (_in(CONTEXT), _in(AST), _in(AST))) + */ + Z3_ast Z3_API Z3_algebraic_sub(__in Z3_context c, __in Z3_ast a, __in Z3_ast b); + + /** + \brief Return the value a * b. + + \pre Z3_algebraic_is_value(c, a) + \pre Z3_algebraic_is_value(c, b) + \post Z3_algebraic_is_value(c, result) + + def_API('Z3_algebraic_mul', AST, (_in(CONTEXT), _in(AST), _in(AST))) + */ + Z3_ast Z3_API Z3_algebraic_mul(__in Z3_context c, __in Z3_ast a, __in Z3_ast b); + + /** + \brief Return the value a / b. + + \pre Z3_algebraic_is_value(c, a) + \pre Z3_algebraic_is_value(c, b) + \pre !Z3_algebraic_is_zero(c, b) + \post Z3_algebraic_is_value(c, result) + + def_API('Z3_algebraic_div', AST, (_in(CONTEXT), _in(AST), _in(AST))) + */ + Z3_ast Z3_API Z3_algebraic_div(__in Z3_context c, __in Z3_ast a, __in Z3_ast b); + + /** + \brief Return the a^(1/k) + + \pre Z3_algebraic_is_value(c, a) + \pre k is even => !Z3_algebraic_is_neg(c, a) + \post Z3_algebraic_is_value(c, result) + + def_API('Z3_algebraic_root', AST, (_in(CONTEXT), _in(AST), _in(UINT))) + */ + Z3_ast Z3_API Z3_algebraic_root(__in Z3_context c, __in Z3_ast a, __in unsigned k); + + /** + \brief Return the a^k + + \pre Z3_algebraic_is_value(c, a) + \post Z3_algebraic_is_value(c, result) + + def_API('Z3_algebraic_power', AST, (_in(CONTEXT), _in(AST), _in(UINT))) + */ + Z3_ast Z3_API Z3_algebraic_power(__in Z3_context c, __in Z3_ast a, __in unsigned k); + + /** + \brief Return Z3_TRUE if a < b, and Z3_FALSE otherwise. + + \pre Z3_algebraic_is_value(c, a) + \pre Z3_algebraic_is_value(c, b) + + def_API('Z3_algebraic_lt', BOOL, (_in(CONTEXT), _in(AST), _in(AST))) + */ + Z3_bool Z3_API Z3_algebraic_lt(__in Z3_context c, __in Z3_ast a, __in Z3_ast b); + + /** + \brief Return Z3_TRUE if a > b, and Z3_FALSE otherwise. + + \pre Z3_algebraic_is_value(c, a) + \pre Z3_algebraic_is_value(c, b) + + def_API('Z3_algebraic_gt', BOOL, (_in(CONTEXT), _in(AST), _in(AST))) + */ + Z3_bool Z3_API Z3_algebraic_gt(__in Z3_context c, __in Z3_ast a, __in Z3_ast b); + + /** + \brief Return Z3_TRUE if a <= b, and Z3_FALSE otherwise. + + \pre Z3_algebraic_is_value(c, a) + \pre Z3_algebraic_is_value(c, b) + + def_API('Z3_algebraic_le', BOOL, (_in(CONTEXT), _in(AST), _in(AST))) + */ + Z3_bool Z3_API Z3_algebraic_le(__in Z3_context c, __in Z3_ast a, __in Z3_ast b); + + /** + \brief Return Z3_TRUE if a >= b, and Z3_FALSE otherwise. + + \pre Z3_algebraic_is_value(c, a) + \pre Z3_algebraic_is_value(c, b) + + def_API('Z3_algebraic_ge', BOOL, (_in(CONTEXT), _in(AST), _in(AST))) + */ + Z3_bool Z3_API Z3_algebraic_ge(__in Z3_context c, __in Z3_ast a, __in Z3_ast b); + + /** + \brief Return Z3_TRUE if a == b, and Z3_FALSE otherwise. + + \pre Z3_algebraic_is_value(c, a) + \pre Z3_algebraic_is_value(c, b) + + def_API('Z3_algebraic_eq', BOOL, (_in(CONTEXT), _in(AST), _in(AST))) + */ + Z3_bool Z3_API Z3_algebraic_eq(__in Z3_context c, __in Z3_ast a, __in Z3_ast b); + + /** + \brief Return Z3_TRUE if a != b, and Z3_FALSE otherwise. + + \pre Z3_algebraic_is_value(c, a) + \pre Z3_algebraic_is_value(c, b) + + def_API('Z3_algebraic_neq', BOOL, (_in(CONTEXT), _in(AST), _in(AST))) + */ + Z3_bool Z3_API Z3_algebraic_neq(__in Z3_context c, __in Z3_ast a, __in Z3_ast b); + + /** + \brief Given a multivariate polynomial p(x_0, ..., x_{n-1}, x_n), returns the + roots of the univariate polynomial p(a[0], ..., a[n-1], x_n). + + \pre p is a Z3 expression that contains only arithmetic terms and free variables. + \pre forall i in [0, n) Z3_algebraic_is_value(c, a[i]) + \post forall r in result Z3_algebraic_is_value(c, result) + + def_API('Z3_algebraic_roots', AST_VECTOR, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST))) + */ + Z3_ast_vector Z3_API Z3_algebraic_roots(__in Z3_context c, __in Z3_ast p, __in unsigned n, __in Z3_ast a[]); + + /** + \brief Given a multivariate polynomial p(x_0, ..., x_{n-1}), return the + sign of p(a[0], ..., a[n-1]). + + \pre p is a Z3 expression that contains only arithmetic terms and free variables. + \pre forall i in [0, n) Z3_algebraic_is_value(c, a[i]) + + def_API('Z3_algebraic_eval', INT, (_in(CONTEXT), _in(AST), _in(UINT), _in_array(2, AST))) + */ + int Z3_API Z3_algebraic_eval(__in Z3_context c, __in Z3_ast p, __in unsigned n, __in Z3_ast a[]); + + +#ifdef __cplusplus +}; +#endif // __cplusplus + +#endif diff --git a/src/ast/arith_decl_plugin.h b/src/ast/arith_decl_plugin.h index b8ad11506..c39768d4c 100644 --- a/src/ast/arith_decl_plugin.h +++ b/src/ast/arith_decl_plugin.h @@ -184,7 +184,7 @@ public: virtual expr * get_some_value(sort * s); - void set_cancel(bool f); + virtual void set_cancel(bool f); }; class arith_util { diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index bd5ffaf35..3fb422a2e 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -1336,6 +1336,12 @@ ast_manager::~ast_manager() { } } +void ast_manager::set_cancel(bool f) { + for (unsigned i = 0; i < m_plugins.size(); i++) { + m_plugins[i]->set_cancel(f); + } +} + void ast_manager::compact_memory() { m_alloc.consolidate(); unsigned capacity = m_ast_table.capacity(); diff --git a/src/ast/ast.h b/src/ast/ast.h index 0ca47ccec..e9da41377 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -921,6 +921,8 @@ public: virtual ~decl_plugin() {} virtual void finalize() {} + virtual void set_cancel(bool f) {} + virtual decl_plugin * mk_fresh() = 0; family_id get_family_id() const { return m_family_id; } @@ -1400,6 +1402,9 @@ public: ast_manager(ast_manager const & src, bool disable_proofs = false); ~ast_manager(); + // propagate cancellation signal to decl_plugins + void set_cancel(bool f); + bool has_trace_stream() const { return m_trace_stream != 0; } std::ostream & trace_stream() { SASSERT(has_trace_stream()); return *m_trace_stream; } From 4e2a9e7caf15dcc6011bf10389f5897112a3c6d1 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 18:44:03 -0800 Subject: [PATCH 29/60] working on api Signed-off-by: Leonardo de Moura --- src/api/api_algebraic.cpp | 202 +++++++++++++++++++++++++++----------- 1 file changed, 145 insertions(+), 57 deletions(-) diff --git a/src/api/api_algebraic.cpp b/src/api/api_algebraic.cpp index 5511332b1..eff020bfc 100644 --- a/src/api/api_algebraic.cpp +++ b/src/api/api_algebraic.cpp @@ -21,78 +21,165 @@ Notes: #include"z3.h" #include"api_log_macros.h" #include"api_context.h" +#include"algebraic_numbers.h" extern "C" { + bool Z3_algebraic_is_value_core(Z3_context c, Z3_ast a) { + api::context * _c = mk_c(c); + return + is_expr(a) && + (_c->autil().is_numeral(to_expr(a)) || + _c->autil().is_irrational_algebraic_numeral(to_expr(a))); + } + +#define CHECK_IS_ALGEBRAIC(ARG, RET) { \ + if (!Z3_algebraic_is_value_core(c, ARG)) { \ + SET_ERROR_CODE(Z3_INVALID_ARG); \ + return RET; \ + } \ +} + +#define CHECK_IS_ALGEBRAIC_X(ARG, RET) { \ + if (!Z3_algebraic_is_value_core(c, ARG)) { \ + SET_ERROR_CODE(Z3_INVALID_ARG); \ + RETURN_Z3(RET); \ + } \ +} + + static arith_util & au(Z3_context c) { + return mk_c(c)->autil(); + } + + static algebraic_numbers::manager & am(Z3_context c) { + return au(c).am(); + } + + static bool is_rational(Z3_context c, Z3_ast a) { + return au(c).is_numeral(to_expr(a)); + } + + static bool is_irrational(Z3_context c, Z3_ast a) { + return au(c).is_irrational_algebraic_numeral(to_expr(a)); + } + + static rational get_rational(Z3_context c, Z3_ast a) { + SASSERT(is_rational(c, a)); + rational r; + VERIFY(au(c).is_numeral(to_expr(a), r)); + return r; + } + + static algebraic_numbers::anum const & get_irrational(Z3_context c, Z3_ast a) { + SASSERT(is_irrational(c, a)); + return au(c).to_irrational_algebraic_numeral(to_expr(a)); + } + Z3_bool Z3_API Z3_algebraic_is_value(Z3_context c, Z3_ast a) { Z3_TRY; LOG_Z3_algebraic_is_value(c, a); RESET_ERROR_CODE(); - // TODO - return Z3_FALSE; + return Z3_algebraic_is_value_core(c, a) ? Z3_TRUE : Z3_FALSE; Z3_CATCH_RETURN(Z3_FALSE); } Z3_bool Z3_API Z3_algebraic_is_pos(Z3_context c, Z3_ast a) { - Z3_TRY; - LOG_Z3_algebraic_is_pos(c, a); - RESET_ERROR_CODE(); - // TODO - return Z3_FALSE; - Z3_CATCH_RETURN(Z3_FALSE); + return Z3_algebraic_sign(c, a) > 0; } Z3_bool Z3_API Z3_algebraic_is_neg(Z3_context c, Z3_ast a) { - Z3_TRY; - LOG_Z3_algebraic_is_neg(c, a); - RESET_ERROR_CODE(); - // TODO - return Z3_FALSE; - Z3_CATCH_RETURN(Z3_FALSE); + return Z3_algebraic_sign(c, a) < 0; } Z3_bool Z3_API Z3_algebraic_is_zero(Z3_context c, Z3_ast a) { - Z3_TRY; - LOG_Z3_algebraic_is_zero(c, a); - RESET_ERROR_CODE(); - // TODO - return Z3_FALSE; - Z3_CATCH_RETURN(Z3_FALSE); + return Z3_algebraic_sign(c, a) == 0; } int Z3_API Z3_algebraic_sign(Z3_context c, Z3_ast a) { Z3_TRY; LOG_Z3_algebraic_sign(c, a); RESET_ERROR_CODE(); - // TODO - return 0; + CHECK_IS_ALGEBRAIC(a, 0); + if (is_rational(c, a)) { + rational v = get_rational(c, a); + if (v.is_pos()) return 1; + else if (v.is_neg()) return -1; + else return 0; + } + else { + algebraic_numbers::anum const & v = get_irrational(c, a); + if (am(c).is_pos(v)) return 1; + else if (am(c).is_neg(v)) return -1; + else return 0; + } Z3_CATCH_RETURN(0); } +#define BIN_OP(RAT_OP, IRAT_OP) \ + algebraic_numbers::manager & _am = am(c); \ + ast * r = 0; \ + if (is_rational(c, a)) { \ + rational av = get_rational(c, a); \ + if (is_rational(c, b)) { \ + rational bv = get_rational(c, b); \ + r = au(c).mk_numeral(av RAT_OP bv, false); \ + } \ + else { \ + algebraic_numbers::anum const & bv = get_irrational(c, b); \ + scoped_anum _av(_am); \ + _am.set(_av, av.to_mpq()); \ + scoped_anum _r(_am); \ + _am.IRAT_OP(_av, bv, _r); \ + r = au(c).mk_numeral(_r, false); \ + } \ + } \ + else { \ + algebraic_numbers::anum const & av = get_irrational(c, a); \ + if (is_rational(c, b)) { \ + rational bv = get_rational(c, b); \ + scoped_anum _bv(_am); \ + _am.set(_bv, bv.to_mpq()); \ + scoped_anum _r(_am); \ + _am.IRAT_OP(av, _bv, _r); \ + r = au(c).mk_numeral(_r, false); \ + } \ + else { \ + algebraic_numbers::anum const & bv = get_irrational(c, b); \ + scoped_anum _r(_am); \ + _am.IRAT_OP(av, bv, _r); \ + r = au(c).mk_numeral(_r, false); \ + } \ + } \ + RETURN_Z3(of_ast(r)); + + Z3_ast Z3_API Z3_algebraic_add(Z3_context c, Z3_ast a, Z3_ast b) { Z3_TRY; LOG_Z3_algebraic_add(c, a, b); - RESET_ERROR_CODE(); - // TODO - return 0; + RESET_ERROR_CODE(); + CHECK_IS_ALGEBRAIC_X(a, 0); + CHECK_IS_ALGEBRAIC_X(b, 0); + BIN_OP(+,add); Z3_CATCH_RETURN(0); } Z3_ast Z3_API Z3_algebraic_sub(Z3_context c, Z3_ast a, Z3_ast b) { Z3_TRY; LOG_Z3_algebraic_sub(c, a, b); - RESET_ERROR_CODE(); - // TODO - return 0; + RESET_ERROR_CODE(); + CHECK_IS_ALGEBRAIC_X(a, 0); + CHECK_IS_ALGEBRAIC_X(b, 0); + BIN_OP(-,sub); Z3_CATCH_RETURN(0); } Z3_ast Z3_API Z3_algebraic_mul(Z3_context c, Z3_ast a, Z3_ast b) { Z3_TRY; LOG_Z3_algebraic_mul(c, a, b); - RESET_ERROR_CODE(); - // TODO - return 0; + RESET_ERROR_CODE(); + CHECK_IS_ALGEBRAIC_X(a, 0); + CHECK_IS_ALGEBRAIC_X(b, 0); + BIN_OP(*,mul); Z3_CATCH_RETURN(0); } @@ -100,8 +187,14 @@ extern "C" { Z3_TRY; LOG_Z3_algebraic_div(c, a, b); RESET_ERROR_CODE(); - // TODO - return 0; + CHECK_IS_ALGEBRAIC_X(a, 0); + CHECK_IS_ALGEBRAIC_X(b, 0); + if ((is_rational(c, b) && get_rational(c, b).is_zero()) || + (!is_rational(c, b) && am(c).is_zero(get_irrational(c, b)))) { + SET_ERROR_CODE(Z3_INVALID_ARG); + RETURN_Z3(0); + } + BIN_OP(/,div); Z3_CATCH_RETURN(0); } @@ -109,6 +202,14 @@ extern "C" { Z3_TRY; LOG_Z3_algebraic_root(c, a, k); RESET_ERROR_CODE(); + CHECK_IS_ALGEBRAIC_X(a, 0); + if (k % 2 == 0) { + if ((is_rational(c, a) && get_rational(c, a).is_neg()) || + (!is_rational(c, a) && am(c).is_neg(get_irrational(c, a)))) { + SET_ERROR_CODE(Z3_INVALID_ARG); + RETURN_Z3(0); + } + } // TODO return 0; Z3_CATCH_RETURN(0); @@ -118,6 +219,7 @@ extern "C" { Z3_TRY; LOG_Z3_algebraic_power(c, a, k); RESET_ERROR_CODE(); + CHECK_IS_ALGEBRAIC_X(a, 0); // TODO return 0; Z3_CATCH_RETURN(0); @@ -127,54 +229,40 @@ extern "C" { Z3_TRY; LOG_Z3_algebraic_lt(c, a, b); RESET_ERROR_CODE(); + CHECK_IS_ALGEBRAIC(a, 0); + CHECK_IS_ALGEBRAIC(b, 0); + // TODO return Z3_FALSE; Z3_CATCH_RETURN(Z3_FALSE); } Z3_bool Z3_API Z3_algebraic_gt(Z3_context c, Z3_ast a, Z3_ast b) { - Z3_TRY; - LOG_Z3_algebraic_gt(c, a, b); - RESET_ERROR_CODE(); - // TODO - return Z3_FALSE; - Z3_CATCH_RETURN(Z3_FALSE); + return Z3_algebraic_lt(c, b, a); } Z3_bool Z3_API Z3_algebraic_le(Z3_context c, Z3_ast a, Z3_ast b) { - Z3_TRY; - LOG_Z3_algebraic_le(c, a, b); - RESET_ERROR_CODE(); - // TODO - return Z3_FALSE; - Z3_CATCH_RETURN(Z3_FALSE); + return !Z3_algebraic_lt(c, b, a); } Z3_bool Z3_API Z3_algebraic_ge(Z3_context c, Z3_ast a, Z3_ast b) { - Z3_TRY; - LOG_Z3_algebraic_ge(c, a, b); - RESET_ERROR_CODE(); - // TODO - return Z3_FALSE; - Z3_CATCH_RETURN(0); + return !Z3_algebraic_lt(c, a, b); } Z3_bool Z3_API Z3_algebraic_eq(Z3_context c, Z3_ast a, Z3_ast b) { Z3_TRY; LOG_Z3_algebraic_eq(c, a, b); RESET_ERROR_CODE(); + CHECK_IS_ALGEBRAIC(a, 0); + CHECK_IS_ALGEBRAIC(b, 0); + // TODO return Z3_FALSE; Z3_CATCH_RETURN(0); } Z3_bool Z3_API Z3_algebraic_neq(Z3_context c, Z3_ast a, Z3_ast b) { - Z3_TRY; - LOG_Z3_algebraic_neq(c, a, b); - RESET_ERROR_CODE(); - // TODO - return Z3_FALSE; - Z3_CATCH_RETURN(0); + return !Z3_algebraic_eq(c, a, b); } Z3_ast_vector Z3_API Z3_algebraic_roots(Z3_context c, Z3_ast p, unsigned n, Z3_ast a[]) { From 189fc46b6d978a3a90c668e3007967844f09ec23 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Fri, 7 Dec 2012 19:06:48 -0800 Subject: [PATCH 30/60] working on api for algebraic numbers Signed-off-by: Leonardo de Moura --- src/api/api_algebraic.cpp | 70 +++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/src/api/api_algebraic.cpp b/src/api/api_algebraic.cpp index eff020bfc..3bb33638f 100644 --- a/src/api/api_algebraic.cpp +++ b/src/api/api_algebraic.cpp @@ -210,8 +210,19 @@ extern "C" { RETURN_Z3(0); } } - // TODO - return 0; + algebraic_numbers::manager & _am = am(c); + scoped_anum _r(_am); + if (is_rational(c, a)) { + scoped_anum av(_am); + _am.set(av, get_rational(c, a).to_mpq()); + _am.root(av, k, _r); + } + else { + algebraic_numbers::anum const & av = get_irrational(c, a); + _am.root(av, k, _r); + } + expr * r = au(c).mk_numeral(_r, false); + RETURN_Z3(of_ast(r)); Z3_CATCH_RETURN(0); } @@ -220,20 +231,61 @@ extern "C" { LOG_Z3_algebraic_power(c, a, k); RESET_ERROR_CODE(); CHECK_IS_ALGEBRAIC_X(a, 0); - // TODO - return 0; + algebraic_numbers::manager & _am = am(c); + scoped_anum _r(_am); + if (is_rational(c, a)) { + scoped_anum av(_am); + _am.set(av, get_rational(c, a).to_mpq()); + _am.power(av, k, _r); + } + else { + algebraic_numbers::anum const & av = get_irrational(c, a); + _am.power(av, k, _r); + } + expr * r = au(c).mk_numeral(_r, false); + RETURN_Z3(of_ast(r)); Z3_CATCH_RETURN(0); } +#define BIN_PRED(RAT_PRED, IRAT_PRED) \ + algebraic_numbers::manager & _am = am(c); \ + bool r; \ + if (is_rational(c, a)) { \ + rational av = get_rational(c, a); \ + if (is_rational(c, b)) { \ + rational bv = get_rational(c, b); \ + r = av RAT_PRED bv; \ + } \ + else { \ + algebraic_numbers::anum const & bv = get_irrational(c, b); \ + scoped_anum _av(_am); \ + _am.set(_av, av.to_mpq()); \ + r = _am.IRAT_PRED(_av, bv); \ + } \ + } \ + else { \ + algebraic_numbers::anum const & av = get_irrational(c, a); \ + if (is_rational(c, b)) { \ + rational bv = get_rational(c, b); \ + scoped_anum _bv(_am); \ + _am.set(_bv, bv.to_mpq()); \ + r = _am.IRAT_PRED(av, _bv); \ + } \ + else { \ + algebraic_numbers::anum const & bv = get_irrational(c, b); \ + r = _am.IRAT_PRED(av, bv); \ + } \ + } \ + return r ? Z3_TRUE : Z3_FALSE; + + Z3_bool Z3_API Z3_algebraic_lt(Z3_context c, Z3_ast a, Z3_ast b) { Z3_TRY; LOG_Z3_algebraic_lt(c, a, b); RESET_ERROR_CODE(); CHECK_IS_ALGEBRAIC(a, 0); CHECK_IS_ALGEBRAIC(b, 0); - - // TODO - return Z3_FALSE; + BIN_PRED(<,lt); Z3_CATCH_RETURN(Z3_FALSE); } @@ -255,9 +307,7 @@ extern "C" { RESET_ERROR_CODE(); CHECK_IS_ALGEBRAIC(a, 0); CHECK_IS_ALGEBRAIC(b, 0); - - // TODO - return Z3_FALSE; + BIN_PRED(==,eq); Z3_CATCH_RETURN(0); } From 47edff2076688abd210c4ee2ebe05bf47d921d7a Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sat, 8 Dec 2012 08:32:06 -0800 Subject: [PATCH 31/60] fixed bugs Signed-off-by: Leonardo de Moura --- src/api/api_algebraic.cpp | 3 +++ src/util/basic_interval.h | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/api/api_algebraic.cpp b/src/api/api_algebraic.cpp index 3bb33638f..38f0289e6 100644 --- a/src/api/api_algebraic.cpp +++ b/src/api/api_algebraic.cpp @@ -150,6 +150,7 @@ extern "C" { r = au(c).mk_numeral(_r, false); \ } \ } \ + mk_c(c)->save_ast_trail(r); \ RETURN_Z3(of_ast(r)); @@ -222,6 +223,7 @@ extern "C" { _am.root(av, k, _r); } expr * r = au(c).mk_numeral(_r, false); + mk_c(c)->save_ast_trail(r); RETURN_Z3(of_ast(r)); Z3_CATCH_RETURN(0); } @@ -243,6 +245,7 @@ extern "C" { _am.power(av, k, _r); } expr * r = au(c).mk_numeral(_r, false); + mk_c(c)->save_ast_trail(r); RETURN_Z3(of_ast(r)); Z3_CATCH_RETURN(0); } diff --git a/src/util/basic_interval.h b/src/util/basic_interval.h index 2bf5a8f30..ef414149c 100644 --- a/src/util/basic_interval.h +++ b/src/util/basic_interval.h @@ -260,8 +260,8 @@ public: \brief c <- a - b */ void sub(interval const & a, interval const & b, interval & c) { - m().sub(a.m_lower, b.m_lower, c.m_lower); - m().sub(a.m_upper, b.m_upper, c.m_upper); + m().sub(a.m_lower, b.m_upper, c.m_lower); + m().sub(a.m_upper, b.m_lower, c.m_upper); } private: From 277244098cba798dd70ec6ae6c4c9831495eef00 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sat, 8 Dec 2012 10:57:05 -0800 Subject: [PATCH 32/60] Adding python interface for computing with algebraic numbers Signed-off-by: Leonardo de Moura --- src/api/python/z3num.py | 489 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 489 insertions(+) create mode 100644 src/api/python/z3num.py diff --git a/src/api/python/z3num.py b/src/api/python/z3num.py new file mode 100644 index 000000000..06dec8695 --- /dev/null +++ b/src/api/python/z3num.py @@ -0,0 +1,489 @@ +############################################ +# Copyright (c) 2012 Microsoft Corporation +# +# Z3 Python interface for Z3 numerals +# +# Author: Leonardo de Moura (leonardo) +############################################ +from z3 import * +from z3core import * +from z3printer import * + +def _to_algebraic(num, ctx=None): + if isinstance(num, Numeral): + return num + else: + return Numeral(num, ctx) + +class Numeral: + """ + A Z3 numeral can be used to perform computations over arbitrary + precision integers, rationals and real algebraic numbers. + It also automatically converts python numeric values. + + >>> Numeral(2) + 2 + >>> Numeral("3/2") + 1 + 5/2 + >>> Numeral(Sqrt(2)) + 1.4142135623? + >>> Numeral(Sqrt(2)) + 2 + 3.4142135623? + >>> Numeral(Sqrt(2)) + Numeral(Sqrt(3)) + 3.1462643699? + + Z3 numerals can be used to perform computations with + values in a Z3 model. + + >>> s = Solver() + >>> x = Real('x') + >>> s.add(x*x == 2) + >>> s.add(x > 0) + >>> s.check() + sat + >>> m = s.model() + >>> m[x] + 1.4142135623? + >>> m[x] + 1 + 1.4142135623? + 1 + + The previous result is a Z3 expression. + + >>> (m[x] + 1).sexpr() + '(+ (root-obj (+ (^ x 2) (- 2)) 2) 1.0)' + + >>> Numeral(m[x]) + 1 + 2.4142135623? + >>> Numeral(m[x]).is_pos() + True + >>> Numeral(m[x])**2 + 2 + """ + def __init__(self, num, ctx=None): + if isinstance(num, Ast): + self.ast = num + self.ctx = z3._get_ctx(ctx) + elif isinstance(num, RatNumRef) or isinstance(num, AlgebraicNumRef): + self.ast = num.ast + self.ctx = num.ctx + elif isinstance(num, ArithRef): + r = simplify(num) + self.ast = r.ast + self.ctx = r.ctx + else: + v = RealVal(num, ctx) + self.ast = v.ast + self.ctx = v.ctx + Z3_inc_ref(self.ctx_ref(), self.as_ast()) + assert Z3_algebraic_is_value(self.ctx_ref(), self.ast) + + def __del__(self): + Z3_dec_ref(self.ctx_ref(), self.as_ast()) + + def __str__(self): + if Z3_is_numeral_ast(self.ctx_ref(), self.ast): + return str(RatNumRef(self.ast, self.ctx)) + else: + return str(AlgebraicNumRef(self.ast, self.ctx)) + + def __repr__(self): + return self.__str__() + + def sexpr(self): + return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) + + def as_ast(self): + return self.ast + + def ctx_ref(self): + return self.ctx.ref() + + def is_integer(self): + """ Return True if the numeral is integer. + + >>> Numeral(2).is_integer() + True + >>> (Numeral(Sqrt(2)) * Numeral(Sqrt(2))).is_integer() + True + >>> Numeral(Sqrt(2)).is_integer() + False + >>> Numeral("2/3").is_integer() + False + """ + return self.is_rational() and self.denominator() == 1 + + def is_rational(self): + """ Return True if the numeral is rational. + + >>> Numeral(2).is_rational() + True + >>> Numeral("2/3").is_rational() + True + >>> Numeral(Sqrt(2)).is_rational() + False + + """ + return Z3_get_ast_kind(self.ctx_ref(), self.as_ast()) == Z3_NUMERAL_AST + + def denominator(self): + """ Return the denominator if `self` is rational. + + >>> Numeral("2/3").denominator() + 3 + """ + assert(self.is_rational()) + return Numeral(Z3_get_denominator(self.ctx_ref(), self.as_ast()), self.ctx) + + def numerator(self): + """ Return the numerator if `self` is rational. + + >>> Numeral("2/3").numerator() + 2 + """ + assert(self.is_rational()) + return Numeral(Z3_get_numerator(self.ctx_ref(), self.as_ast()), self.ctx) + + + def is_irrational(self): + """ Return True if the numeral is irrational. + + >>> Numeral(2).is_irrational() + False + >>> Numeral("2/3").is_irrational() + False + >>> Numeral(Sqrt(2)).is_irrational() + True + """ + return not self.is_rational() + + def as_long(self): + """ Return a numeral (that is an integer) as a Python long. + + >>> (Numeral(10)**20).as_long() + 100000000000000000000L + """ + assert(self.is_integer()) + return long(Z3_get_numeral_string(self.ctx_ref(), self.as_ast())) + + def approx(self, precision=10): + """Return a numeral that approximates the numeral `self`. + The result `r` is such that |r - self| <= 1/10^precision + + If `self` is rational, then the result is `self`. + + >>> x = Numeral(2).root(2) + >>> x.approx(20) + 6838717160008073720548335/4835703278458516698824704 + >>> x.approx(5) + 2965821/2097152 + >>> Numeral(2).approx(10) + 2 + """ + return self.upper(precision) + + def upper(self, precision=10): + """Return a upper bound that approximates the numeral `self`. + The result `r` is such that r - self <= 1/10^precision + + If `self` is rational, then the result is `self`. + + >>> x = Numeral(2).root(2) + >>> x.upper(20) + 6838717160008073720548335/4835703278458516698824704 + >>> x.upper(5) + 2965821/2097152 + >>> Numeral(2).upper(10) + 2 + """ + if self.is_rational(): + return self + else: + return Numeral(Z3_get_algebraic_number_upper(self.ctx_ref(), self.as_ast(), precision), self.ctx) + + def lower(self, precision=10): + """Return a lower bound that approximates the numeral `self`. + The result `r` is such that self - r <= 1/10^precision + + If `self` is rational, then the result is `self`. + + >>> x = Numeral(2).root(2) + >>> x.lower(20) + 1709679290002018430137083/1208925819614629174706176 + >>> Numeral("2/3").lower(10) + 2/3 + """ + if self.is_rational(): + return self + else: + return Numeral(Z3_get_algebraic_number_lower(self.ctx_ref(), self.as_ast(), precision), self.ctx) + + def sign(self): + """ Return the sign of the numeral. + + >>> Numeral(2).sign() + 1 + >>> Numeral(-3).sign() + -1 + >>> Numeral(0).sign() + 0 + """ + return Z3_algebraic_sign(self.ctx_ref(), self.ast) + + def is_pos(self): + """ Return True if the numeral is positive. + + >>> Numeral(2).is_pos() + True + >>> Numeral(-3).is_pos() + False + >>> Numeral(0).is_pos() + False + """ + return Z3_algebraic_is_pos(self.ctx_ref(), self.ast) + + def is_neg(self): + """ Return True if the numeral is negative. + + >>> Numeral(2).is_neg() + False + >>> Numeral(-3).is_neg() + True + >>> Numeral(0).is_neg() + False + """ + return Z3_algebraic_is_neg(self.ctx_ref(), self.ast) + + def is_zero(self): + """ Return True if the numeral is zero. + + >>> Numeral(2).is_zero() + False + >>> Numeral(-3).is_zero() + False + >>> Numeral(0).is_zero() + True + >>> sqrt2 = Numeral(2).root(2) + >>> sqrt2.is_zero() + False + >>> (sqrt2 - sqrt2).is_zero() + True + """ + return Z3_algebraic_is_zero(self.ctx_ref(), self.ast) + + def __add__(self, other): + """ Return the numeral `self + other`. + + >>> Numeral(2) + 3 + 5 + >>> Numeral(2) + Numeral(4) + 6 + >>> Numeral("2/3") + 1 + 5/3 + """ + return Numeral(Z3_algebraic_add(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + + def __radd__(self, other): + """ Return the numeral `other + self`. + + >>> 3 + Numeral(2) + 5 + """ + return Numeral(Z3_algebraic_add(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + + def __sub__(self, other): + """ Return the numeral `self - other`. + + >>> Numeral(2) - 3 + -1 + """ + return Numeral(Z3_algebraic_sub(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + + def __rsub__(self, other): + """ Return the numeral `other - self`. + + >>> 3 - Numeral(2) + 1 + """ + return Numeral(Z3_algebraic_sub(self.ctx_ref(), _to_algebraic(other, self.ctx).ast, self.ast), self.ctx) + + def __mul__(self, other): + """ Return the numeral `self * other`. + >>> Numeral(2) * 3 + 6 + """ + return Numeral(Z3_algebraic_mul(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + + def __rmul__(self, other): + """ Return the numeral `other * mul`. + >>> 3 * Numeral(2) + 6 + """ + return Numeral(Z3_algebraic_mul(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + + def __div__(self, other): + """ Return the numeral `self / other`. + >>> Numeral(2) / 3 + 2/3 + >>> Numeral(2).root(2) / 3 + 0.4714045207? + >>> Numeral(Sqrt(2)) / Numeral(Sqrt(3)) + 0.8164965809? + """ + return Numeral(Z3_algebraic_div(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + + def __rdiv__(self, other): + """ Return the numeral `other / self`. + >>> 3 / Numeral(2) + 3/2 + >>> 3 / Numeral(2).root(2) + 2.1213203435? + """ + return Numeral(Z3_algebraic_div(self.ctx_ref(), _to_algebraic(other, self.ctx).ast, self.ast), self.ctx) + + def root(self, k): + """ Return the numeral `self^(1/k)`. + + >>> sqrt2 = Numeral(2).root(2) + >>> sqrt2 + 1.4142135623? + >>> sqrt2 * sqrt2 + 2 + >>> sqrt2 * 2 + 1 + 3.8284271247? + >>> (sqrt2 * 2 + 1).sexpr() + '(root-obj (+ (^ x 2) (* (- 2) x) (- 7)) 2)' + """ + return Numeral(Z3_algebraic_root(self.ctx_ref(), self.ast, k), self.ctx) + + def power(self, k): + """ Return the numeral `self^k`. + + >>> sqrt3 = Numeral(3).root(2) + >>> sqrt3 + 1.7320508075? + >>> sqrt3.power(2) + 3 + """ + return Numeral(Z3_algebraic_power(self.ctx_ref(), self.ast, k), self.ctx) + + def __pow__(self, k): + """ Return the numeral `self^k`. + + >>> sqrt3 = Numeral(3).root(2) + >>> sqrt3 + 1.7320508075? + >>> sqrt3**2 + 3 + """ + return self.power(k) + + def __lt__(self, other): + """ Return True if `self < other`. + + >>> Numeral(Sqrt(2)) < 2 + True + >>> Numeral(Sqrt(3)) < Numeral(Sqrt(2)) + False + >>> Numeral(Sqrt(2)) < Numeral(Sqrt(2)) + False + """ + return Z3_algebraic_lt(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + + def __rlt__(self, other): + """ Return True if `other < self`. + + >>> 2 < Numeral(Sqrt(2)) + False + """ + return self > other + + def __gt__(self, other): + """ Return True if `self > other`. + + >>> Numeral(Sqrt(2)) > 2 + False + >>> Numeral(Sqrt(3)) > Numeral(Sqrt(2)) + True + >>> Numeral(Sqrt(2)) > Numeral(Sqrt(2)) + False + """ + return Z3_algebraic_gt(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + + def __rgt__(self, other): + """ Return True if `other > self`. + + >>> 2 > Numeral(Sqrt(2)) + True + """ + return self < other + + + def __le__(self, other): + """ Return True if `self <= other`. + + >>> Numeral(Sqrt(2)) <= 2 + True + >>> Numeral(Sqrt(3)) <= Numeral(Sqrt(2)) + False + >>> Numeral(Sqrt(2)) <= Numeral(Sqrt(2)) + True + """ + return Z3_algebraic_le(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + + def __rle__(self, other): + """ Return True if `other <= self`. + + >>> 2 <= Numeral(Sqrt(2)) + False + """ + return self >= other + + def __ge__(self, other): + """ Return True if `self >= other`. + + >>> Numeral(Sqrt(2)) >= 2 + False + >>> Numeral(Sqrt(3)) >= Numeral(Sqrt(2)) + True + >>> Numeral(Sqrt(2)) >= Numeral(Sqrt(2)) + True + """ + return Z3_algebraic_ge(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + + def __rge__(self, other): + """ Return True if `other >= self`. + + >>> 2 >= Numeral(Sqrt(2)) + True + """ + return self <= other + + def __eq__(self, other): + """ Return True if `self == other`. + + >>> Numeral(Sqrt(2)) == 2 + False + >>> Numeral(Sqrt(3)) == Numeral(Sqrt(2)) + False + >>> Numeral(Sqrt(2)) == Numeral(Sqrt(2)) + True + """ + return Z3_algebraic_eq(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + + def __ne__(self, other): + """ Return True if `self != other`. + + >>> Numeral(Sqrt(2)) != 2 + True + >>> Numeral(Sqrt(3)) != Numeral(Sqrt(2)) + True + >>> Numeral(Sqrt(2)) != Numeral(Sqrt(2)) + False + """ + return Z3_algebraic_neq(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + + +if __name__ == "__main__": + import doctest + doctest.testmod() + From bf2340850a86a3c134716f46c6a59032e929d9f4 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sat, 8 Dec 2012 11:11:53 -0800 Subject: [PATCH 33/60] minor change Signed-off-by: Leonardo de Moura --- src/api/python/z3num.py | 70 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/api/python/z3num.py b/src/api/python/z3num.py index 06dec8695..27244a018 100644 --- a/src/api/python/z3num.py +++ b/src/api/python/z3num.py @@ -9,7 +9,7 @@ from z3 import * from z3core import * from z3printer import * -def _to_algebraic(num, ctx=None): +def _to_numeral(num, ctx=None): if isinstance(num, Numeral): return num else: @@ -80,24 +80,6 @@ class Numeral: def __del__(self): Z3_dec_ref(self.ctx_ref(), self.as_ast()) - def __str__(self): - if Z3_is_numeral_ast(self.ctx_ref(), self.ast): - return str(RatNumRef(self.ast, self.ctx)) - else: - return str(AlgebraicNumRef(self.ast, self.ctx)) - - def __repr__(self): - return self.__str__() - - def sexpr(self): - return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) - - def as_ast(self): - return self.ast - - def ctx_ref(self): - return self.ctx.ref() - def is_integer(self): """ Return True if the numeral is integer. @@ -280,7 +262,7 @@ class Numeral: >>> Numeral("2/3") + 1 5/3 """ - return Numeral(Z3_algebraic_add(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + return Numeral(Z3_algebraic_add(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx) def __radd__(self, other): """ Return the numeral `other + self`. @@ -288,7 +270,7 @@ class Numeral: >>> 3 + Numeral(2) 5 """ - return Numeral(Z3_algebraic_add(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + return Numeral(Z3_algebraic_add(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx) def __sub__(self, other): """ Return the numeral `self - other`. @@ -296,7 +278,7 @@ class Numeral: >>> Numeral(2) - 3 -1 """ - return Numeral(Z3_algebraic_sub(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + return Numeral(Z3_algebraic_sub(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx) def __rsub__(self, other): """ Return the numeral `other - self`. @@ -304,21 +286,21 @@ class Numeral: >>> 3 - Numeral(2) 1 """ - return Numeral(Z3_algebraic_sub(self.ctx_ref(), _to_algebraic(other, self.ctx).ast, self.ast), self.ctx) + return Numeral(Z3_algebraic_sub(self.ctx_ref(), _to_numeral(other, self.ctx).ast, self.ast), self.ctx) def __mul__(self, other): """ Return the numeral `self * other`. >>> Numeral(2) * 3 6 """ - return Numeral(Z3_algebraic_mul(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + return Numeral(Z3_algebraic_mul(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx) def __rmul__(self, other): """ Return the numeral `other * mul`. >>> 3 * Numeral(2) 6 """ - return Numeral(Z3_algebraic_mul(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + return Numeral(Z3_algebraic_mul(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx) def __div__(self, other): """ Return the numeral `self / other`. @@ -329,7 +311,7 @@ class Numeral: >>> Numeral(Sqrt(2)) / Numeral(Sqrt(3)) 0.8164965809? """ - return Numeral(Z3_algebraic_div(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast), self.ctx) + return Numeral(Z3_algebraic_div(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast), self.ctx) def __rdiv__(self, other): """ Return the numeral `other / self`. @@ -338,7 +320,7 @@ class Numeral: >>> 3 / Numeral(2).root(2) 2.1213203435? """ - return Numeral(Z3_algebraic_div(self.ctx_ref(), _to_algebraic(other, self.ctx).ast, self.ast), self.ctx) + return Numeral(Z3_algebraic_div(self.ctx_ref(), _to_numeral(other, self.ctx).ast, self.ast), self.ctx) def root(self, k): """ Return the numeral `self^(1/k)`. @@ -387,7 +369,7 @@ class Numeral: >>> Numeral(Sqrt(2)) < Numeral(Sqrt(2)) False """ - return Z3_algebraic_lt(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + return Z3_algebraic_lt(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast) def __rlt__(self, other): """ Return True if `other < self`. @@ -407,7 +389,7 @@ class Numeral: >>> Numeral(Sqrt(2)) > Numeral(Sqrt(2)) False """ - return Z3_algebraic_gt(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + return Z3_algebraic_gt(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast) def __rgt__(self, other): """ Return True if `other > self`. @@ -428,7 +410,7 @@ class Numeral: >>> Numeral(Sqrt(2)) <= Numeral(Sqrt(2)) True """ - return Z3_algebraic_le(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + return Z3_algebraic_le(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast) def __rle__(self, other): """ Return True if `other <= self`. @@ -448,7 +430,7 @@ class Numeral: >>> Numeral(Sqrt(2)) >= Numeral(Sqrt(2)) True """ - return Z3_algebraic_ge(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + return Z3_algebraic_ge(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast) def __rge__(self, other): """ Return True if `other >= self`. @@ -468,7 +450,7 @@ class Numeral: >>> Numeral(Sqrt(2)) == Numeral(Sqrt(2)) True """ - return Z3_algebraic_eq(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) + return Z3_algebraic_eq(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast) def __ne__(self, other): """ Return True if `self != other`. @@ -480,10 +462,28 @@ class Numeral: >>> Numeral(Sqrt(2)) != Numeral(Sqrt(2)) False """ - return Z3_algebraic_neq(self.ctx_ref(), self.ast, _to_algebraic(other, self.ctx).ast) - + return Z3_algebraic_neq(self.ctx_ref(), self.ast, _to_numeral(other, self.ctx).ast) + + def __str__(self): + if Z3_is_numeral_ast(self.ctx_ref(), self.ast): + return str(RatNumRef(self.ast, self.ctx)) + else: + return str(AlgebraicNumRef(self.ast, self.ctx)) + + def __repr__(self): + return self.__str__() + + def sexpr(self): + return Z3_ast_to_string(self.ctx_ref(), self.as_ast()) + + def as_ast(self): + return self.ast + + def ctx_ref(self): + return self.ctx.ref() if __name__ == "__main__": import doctest - doctest.testmod() + if doctest.testmod().failed: + exit(1) From 0d230375be955d61c07aed0cb0fb26726e13ae5c Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sat, 8 Dec 2012 20:39:16 -0800 Subject: [PATCH 34/60] added polynomial evaluation at algebraic point Signed-off-by: Leonardo de Moura --- src/api/api_algebraic.cpp | 57 +++++++++++++++++- src/api/api_context.h | 10 ++++ src/api/api_polynomial.cpp | 34 +++++++++++ src/api/api_polynomial.h | 39 ++++++++++++ src/api/python/z3.py | 21 +++++++ src/api/python/z3num.py | 24 ++++++++ src/ast/expr2polynomial.cpp | 80 ++++++++++++++++++------- src/ast/expr2polynomial.h | 25 +++++++- src/math/polynomial/algebraic_numbers.h | 2 + 9 files changed, 266 insertions(+), 26 deletions(-) create mode 100644 src/api/api_polynomial.cpp create mode 100644 src/api/api_polynomial.h diff --git a/src/api/api_algebraic.cpp b/src/api/api_algebraic.cpp index 38f0289e6..f5a52a6ea 100644 --- a/src/api/api_algebraic.cpp +++ b/src/api/api_algebraic.cpp @@ -22,6 +22,9 @@ Notes: #include"api_log_macros.h" #include"api_context.h" #include"algebraic_numbers.h" +#include"expr2polynomial.h" +#include"cancel_eh.h" +#include"scoped_timer.h" extern "C" { @@ -318,6 +321,34 @@ extern "C" { return !Z3_algebraic_eq(c, a, b); } + static bool to_anum_vector(Z3_context c, unsigned n, Z3_ast a[], scoped_anum_vector & as) { + algebraic_numbers::manager & _am = am(c); + scoped_anum tmp(_am); + for (unsigned i = 0; i < n; i++) { + if (is_rational(c, a[i])) { + _am.set(tmp, get_rational(c, a[i]).to_mpq()); + as.push_back(tmp); + } + else if (is_irrational(c, a[i])) { + as.push_back(get_irrational(c, a[i])); + } + else { + return false; + } + } + return true; + } + + class vector_var2anum : public polynomial::var2anum { + scoped_anum_vector const & m_as; + public: + vector_var2anum(scoped_anum_vector & as):m_as(as) {} + virtual ~vector_var2anum() {} + virtual algebraic_numbers::manager & m() const { return m_as.m(); } + virtual bool contains(polynomial::var x) const { return static_cast(x) < m_as.size(); } + virtual algebraic_numbers::anum const & operator()(polynomial::var x) const { return m_as.get(x); } + }; + Z3_ast_vector Z3_API Z3_algebraic_roots(Z3_context c, Z3_ast p, unsigned n, Z3_ast a[]) { Z3_TRY; LOG_Z3_algebraic_roots(c, p, n, a); @@ -331,8 +362,30 @@ extern "C" { Z3_TRY; LOG_Z3_algebraic_eval(c, p, n, a); RESET_ERROR_CODE(); - // TODO - return 0; + polynomial::manager & pm = mk_c(c)->pm(); + polynomial_ref _p(pm); + polynomial::scoped_numeral d(pm.m()); + expr2polynomial converter(mk_c(c)->m(), pm, 0, true); + if (!converter.to_polynomial(to_expr(p), _p, d)) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + algebraic_numbers::manager & _am = am(c); + scoped_anum_vector as(_am); + if (!to_anum_vector(c, n, a, as)) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + { + cancel_eh eh(_am); + api::context::set_interruptable(*(mk_c(c)), eh); + scoped_timer timer(mk_c(c)->params().m_timeout, &eh); + vector_var2anum v2a(as); + int r = _am.eval_sign_at(_p, v2a); + if (r > 0) return 1; + else if (r < 0) return -1; + else return 0; + } Z3_CATCH_RETURN(0); } diff --git a/src/api/api_context.h b/src/api/api_context.h index a126f0790..02768556d 100644 --- a/src/api/api_context.h +++ b/src/api/api_context.h @@ -32,6 +32,7 @@ Revision History: #include"event_handler.h" #include"tactic_manager.h" #include"context_params.h" +#include"api_polynomial.h" namespace smtlib { class parser; @@ -81,6 +82,8 @@ namespace api { Z3_ast_print_mode m_print_mode; event_handler * m_interruptable; // Reference to an object that can be interrupted by Z3_interrupt + + pmanager m_pmanager; public: // Scoped obj for setting m_interruptable class set_interruptable { @@ -167,6 +170,13 @@ namespace api { void check_sorts(ast * n); + // ------------------------ + // + // Polynomial manager & caches + // + // ----------------------- + polynomial::manager & pm() { return m_pmanager.pm(); } + // ------------------------ // // Solver interface for backward compatibility diff --git a/src/api/api_polynomial.cpp b/src/api/api_polynomial.cpp new file mode 100644 index 000000000..af5803369 --- /dev/null +++ b/src/api/api_polynomial.cpp @@ -0,0 +1,34 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + api_polynomial.cpp + +Abstract: + + Polynomial manager and caches for the external API. + +Author: + + Leonardo de Moura (leonardo) 2012-12-08 + +Notes: + +--*/ +#include"api_polynomial.h" + +namespace api { + + pmanager::pmanager(): + m_pm(m_nm) { + } + + pmanager::~pmanager() { + } + + void pmanager::set_cancel(bool f) { + m_pm.set_cancel(f); + } + +}; diff --git a/src/api/api_polynomial.h b/src/api/api_polynomial.h new file mode 100644 index 000000000..27317a7dd --- /dev/null +++ b/src/api/api_polynomial.h @@ -0,0 +1,39 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + api_polynomial.h + +Abstract: + + Polynomial manager and caches for the external API. + +Author: + + Leonardo de Moura (leonardo) 2012-12-08 + +Notes: + +--*/ +#ifndef _API_POLYNOMIAL_H_ +#define _API_POLYNOMIAL_H_ + +#include"polynomial.h" + +namespace api { + + class pmanager { + unsynch_mpz_manager m_nm; + polynomial::manager m_pm; + // TODO: add support for caching expressions -> polynomial and back + public: + pmanager(); + virtual ~pmanager(); + polynomial::manager & pm() { return m_pm; } + void set_cancel(bool f); + }; + +}; + +#endif diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 6517de221..924ac0ea5 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -1126,6 +1126,27 @@ def Var(idx, s): _z3_assert(is_sort(s), "Z3 sort expected") return _to_expr_ref(Z3_mk_bound(s.ctx_ref(), idx, s.ast), s.ctx) +def RealVar(idx, ctx=None): + """ + Create a real free variable. Free variables are used to create quantified formulas. + They are also used to create polynomials. + + >>> RealVar(0) + Var(0) + """ + return Var(idx, RealSort(ctx)) + +def RealVarVector(n, ctx=None): + """ + Create a list of Real free variables. + The variables have ids: 0, 1, ..., n-1 + + >>> x0, x1, x2, x3 = RealVarVector(4) + >>> x2 + Var(2) + """ + return [ RealVar(i, ctx) for i in range(n) ] + ######################################### # # Booleans diff --git a/src/api/python/z3num.py b/src/api/python/z3num.py index 27244a018..de30e9e7a 100644 --- a/src/api/python/z3num.py +++ b/src/api/python/z3num.py @@ -481,6 +481,30 @@ class Numeral: def ctx_ref(self): return self.ctx.ref() + +def eval_sign_at(p, vs): + """ + Evaluate the sign of the polynomial `p` at `vs`. `p` is a Z3 + Expression containing arithmetic operators: +, -, *, ^k where k is + an integer; and free variables x that is_var(x) is True. Moreover, + all variables must be real. + + The result is 1 if the polynomial is positive at the given point, + -1 if negative, and 0 if zero. + + >>> x0, x1, x2 = RealVarVector(3) + >>> eval_sign_at(x0**2 + x1*x2 + 1, (Numeral(0), Numeral(1), Numeral(2))) + 1 + >>> eval_sign_at(x0**2 - 2, [ Numeral(Sqrt(2)) ]) + 0 + >>> eval_sign_at((x0 + x1)*(x0 + x2), (Numeral(0), Numeral(Sqrt(2)), Numeral(Sqrt(3)))) + 1 + """ + num = len(vs) + _vs = (Ast * num)() + for i in range(num): + _vs[i] = vs[i].ast + return Z3_algebraic_eval(p.ctx_ref(), p.as_ast(), num, _vs) if __name__ == "__main__": import doctest diff --git a/src/ast/expr2polynomial.cpp b/src/ast/expr2polynomial.cpp index 72bd72aa7..fbabcb150 100644 --- a/src/ast/expr2polynomial.cpp +++ b/src/ast/expr2polynomial.cpp @@ -49,21 +49,24 @@ struct expr2polynomial::imp { polynomial::polynomial_ref_vector m_presult_stack; polynomial::scoped_numeral_vector m_dresult_stack; + bool m_use_var_idxs; + volatile bool m_cancel; - imp(expr2polynomial & w, ast_manager & am, polynomial::manager & pm, expr2var * e2v): + imp(expr2polynomial & w, ast_manager & am, polynomial::manager & pm, expr2var * e2v, bool use_var_idxs): m_wrapper(w), m_am(am), m_autil(am), m_pm(pm), - m_expr2var(e2v == 0 ? alloc(expr2var, am) : e2v), - m_expr2var_owner(e2v == 0), + m_expr2var(e2v == 0 && !use_var_idxs ? alloc(expr2var, am) : e2v), + m_expr2var_owner(e2v == 0 && !use_var_idxs), m_var2expr(am), m_cached_domain(am), m_cached_polynomials(pm), m_cached_denominators(pm.m()), m_presult_stack(pm), m_dresult_stack(pm.m()), + m_use_var_idxs(use_var_idxs), m_cancel(false) { } @@ -95,6 +98,14 @@ struct expr2polynomial::imp { cooperate("expr2polynomial"); } + void throw_not_polynomial() { + throw default_exception("the given expression is not a polynomial"); + } + + void throw_no_int_var() { + throw default_exception("integer variables are not allowed in the given polynomial"); + } + void push_frame(app * t) { m_frame_stack.push_back(frame(t)); } @@ -127,14 +138,26 @@ struct expr2polynomial::imp { } void store_var_poly(expr * t) { - polynomial::var x = m_expr2var->to_var(t); - if (x == UINT_MAX) { - bool is_int = m_autil.is_int(t); - x = m_wrapper.mk_var(is_int); - m_expr2var->insert(t, x); - if (x >= m_var2expr.size()) - m_var2expr.resize(x+1, 0); - m_var2expr.set(x, t); + polynomial::var x; + if (m_use_var_idxs) { + SASSERT(::is_var(t)); + if (m_autil.is_int(t)) + throw_no_int_var(); + unsigned idx = to_var(t)->get_idx(); + while (idx >= m_pm.num_vars()) + m_pm.mk_var(); + x = static_cast(idx); + } + else { + x = m_expr2var->to_var(t); + if (x == UINT_MAX) { + bool is_int = m_autil.is_int(t); + x = m_wrapper.mk_var(is_int); + m_expr2var->insert(t, x); + if (x >= m_var2expr.size()) + m_var2expr.resize(x+1, 0); + m_var2expr.set(x, t); + } } polynomial::numeral one(1); store_result(t, pm().mk_polynomial(x), one); @@ -160,7 +183,10 @@ struct expr2polynomial::imp { rational k; SASSERT(t->get_num_args() == 2); if (!m_autil.is_numeral(t->get_arg(1), k) || !k.is_int() || !k.is_unsigned()) { - store_var_poly(t); + if (m_use_var_idxs) + throw_not_polynomial(); + else + store_var_poly(t); return true; } push_frame(t); @@ -168,6 +194,8 @@ struct expr2polynomial::imp { } default: // can't handle operator + if (m_use_var_idxs) + throw_not_polynomial(); store_var_poly(t); return true; } @@ -190,6 +218,8 @@ struct expr2polynomial::imp { SASSERT(is_app(t)); if (!m_autil.is_arith_expr(t)) { + if (m_use_var_idxs) + throw_not_polynomial(); store_var_poly(t); return true; } @@ -378,19 +408,25 @@ struct expr2polynomial::imp { for (unsigned i = 0; i < sz; i++) { margs.reset(); - polynomial::monomial * m = pm().get_monomial(p, i); + polynomial::monomial * _m = pm().get_monomial(p, i); polynomial::numeral const & a = pm().coeff(p, i); if (!nm().is_one(a)) { margs.push_back(m_autil.mk_numeral(rational(a), is_int)); } - unsigned msz = pm().size(m); + unsigned msz = pm().size(_m); for (unsigned j = 0; j < msz; j++) { - polynomial::var x = pm().get_var(m, j); - expr * t = m_var2expr.get(x); - if (m_wrapper.is_int(x) && !is_int) { - t = m_autil.mk_to_real(t); + polynomial::var x = pm().get_var(_m, j); + expr * t; + if (m_use_var_idxs) { + t = m().mk_var(x, m_autil.mk_real()); } - unsigned d = pm().degree(m, j); + else { + t = m_var2expr.get(x); + if (m_wrapper.is_int(x) && !is_int) { + t = m_autil.mk_to_real(t); + } + } + unsigned d = pm().degree(_m, j); if (use_power && d > 1) { margs.push_back(m_autil.mk_power(t, m_autil.mk_numeral(rational(d), is_int))); } @@ -426,8 +462,8 @@ struct expr2polynomial::imp { } }; -expr2polynomial::expr2polynomial(ast_manager & am, polynomial::manager & pm, expr2var * e2v) { - m_imp = alloc(imp, *this, am, pm, e2v); +expr2polynomial::expr2polynomial(ast_manager & am, polynomial::manager & pm, expr2var * e2v, bool use_var_idxs) { + m_imp = alloc(imp, *this, am, pm, e2v, use_var_idxs); } expr2polynomial::~expr2polynomial() { @@ -451,10 +487,12 @@ void expr2polynomial::to_expr(polynomial::polynomial_ref const & p, bool use_pow } bool expr2polynomial::is_var(expr * t) const { + SASSERT(!m_imp->m_use_var_idxs); return m_imp->m_expr2var->is_var(t); } expr2var const & expr2polynomial::get_mapping() const { + SASSERT(!m_imp->m_use_var_idxs); return *(m_imp->m_expr2var); } diff --git a/src/ast/expr2polynomial.h b/src/ast/expr2polynomial.h index fbeda019d..8934f3f24 100644 --- a/src/ast/expr2polynomial.h +++ b/src/ast/expr2polynomial.h @@ -29,7 +29,24 @@ class expr2polynomial { struct imp; imp * m_imp; public: - expr2polynomial(ast_manager & am, polynomial::manager & pm, expr2var * e2v); + expr2polynomial(ast_manager & am, + polynomial::manager & pm, + expr2var * e2v, + /* + If true, the expressions converted into + polynomials should only contain Z3 free variables. + A Z3 variable x, with idx i, is converted into + the variable i of the polynomial manager pm. + + An exception is thrown if there is a mismatch between + the sorts x and the variable in the polynomial manager. + + The argument e2v is ignored when use_var_idxs is true. + + Moreover, only real variables are allowed. + */ + bool use_var_idxs = false + ); virtual ~expr2polynomial(); ast_manager & m() const; @@ -63,6 +80,8 @@ public: /** \brief Return the mapping from expressions to variables + + \pre the object was created using use_var_idxs = false. */ expr2var const & get_mapping() const; @@ -74,10 +93,10 @@ public: /** \brief Return true if the variable is associated with an expression of integer sort. */ - virtual bool is_int(polynomial::var x) const = 0; + virtual bool is_int(polynomial::var x) const { UNREACHABLE(); return false; } protected: - virtual polynomial::var mk_var(bool is_int) = 0; + virtual polynomial::var mk_var(bool is_int) { UNREACHABLE(); return polynomial::null_var; } }; class default_expr2polynomial : public expr2polynomial { diff --git a/src/math/polynomial/algebraic_numbers.h b/src/math/polynomial/algebraic_numbers.h index 4735a875b..a4669eae6 100644 --- a/src/math/polynomial/algebraic_numbers.h +++ b/src/math/polynomial/algebraic_numbers.h @@ -64,6 +64,8 @@ namespace algebraic_numbers { static void collect_param_descrs(param_descrs & r) { get_param_descrs(r); } void set_cancel(bool f); + + void cancel() { set_cancel(true); } void updt_params(params_ref const & p); From 7a31c6bc743cfa0fc5ffa1c76e506e15c07427c5 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sat, 8 Dec 2012 21:07:17 -0800 Subject: [PATCH 35/60] exposed root isolation algorithm in the API Signed-off-by: Leonardo de Moura --- src/api/api_algebraic.cpp | 35 ++++++++++++++++++++++++++++++++--- src/api/python/z3num.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/api/api_algebraic.cpp b/src/api/api_algebraic.cpp index f5a52a6ea..3751c82ee 100644 --- a/src/api/api_algebraic.cpp +++ b/src/api/api_algebraic.cpp @@ -25,6 +25,7 @@ Notes: #include"expr2polynomial.h" #include"cancel_eh.h" #include"scoped_timer.h" +#include"api_ast_vector.h" extern "C" { @@ -353,8 +354,35 @@ extern "C" { Z3_TRY; LOG_Z3_algebraic_roots(c, p, n, a); RESET_ERROR_CODE(); - // TODO - return 0; + polynomial::manager & pm = mk_c(c)->pm(); + polynomial_ref _p(pm); + polynomial::scoped_numeral d(pm.m()); + expr2polynomial converter(mk_c(c)->m(), pm, 0, true); + if (!converter.to_polynomial(to_expr(p), _p, d) || + static_cast(max_var(_p)) >= n + 1) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + algebraic_numbers::manager & _am = am(c); + scoped_anum_vector as(_am); + if (!to_anum_vector(c, n, a, as)) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + scoped_anum_vector roots(_am); + { + cancel_eh eh(_am); + api::context::set_interruptable(*(mk_c(c)), eh); + scoped_timer timer(mk_c(c)->params().m_timeout, &eh); + vector_var2anum v2a(as); + _am.isolate_roots(_p, v2a, roots); + } + Z3_ast_vector_ref* result = alloc(Z3_ast_vector_ref, mk_c(c)->m()); + mk_c(c)->save_object(result); + for (unsigned i = 0; i < roots.size(); i++) { + result->m_ast_vector.push_back(au(c).mk_numeral(roots.get(i), false)); + } + RETURN_Z3(of_ast_vector(result)); Z3_CATCH_RETURN(0); } @@ -366,7 +394,8 @@ extern "C" { polynomial_ref _p(pm); polynomial::scoped_numeral d(pm.m()); expr2polynomial converter(mk_c(c)->m(), pm, 0, true); - if (!converter.to_polynomial(to_expr(p), _p, d)) { + if (!converter.to_polynomial(to_expr(p), _p, d) || + static_cast(max_var(_p)) >= n) { SET_ERROR_CODE(Z3_INVALID_ARG); return 0; } diff --git a/src/api/python/z3num.py b/src/api/python/z3num.py index de30e9e7a..99f336050 100644 --- a/src/api/python/z3num.py +++ b/src/api/python/z3num.py @@ -505,6 +505,34 @@ def eval_sign_at(p, vs): for i in range(num): _vs[i] = vs[i].ast return Z3_algebraic_eval(p.ctx_ref(), p.as_ast(), num, _vs) + +def isolate_roots(p, vs=[]): + """ + Given a multivariate polynomial p(x_0, ..., x_{n-1}, x_n), returns the + roots of the univariate polynomial p(vs[0], ..., vs[len(vs)-1], x_n). + + Remarks: + * p is a Z3 expression that contains only arithmetic terms and free variables. + * forall i in [0, n) vs is a numeral. + + The result is a list of numerals + + >>> x0 = RealVar(0) + >>> isolate_roots(x0**5 - x0 - 1) + [1.1673039782?] + >>> x1 = RealVar(1) + >>> isolate_roots(x0**2 - x1**4 - 1, [ Numeral(Sqrt(3)) ]) + [-1.1892071150?, 1.1892071150?] + >>> x2 = RealVar(2) + >>> isolate_roots(x2**2 + x0 - x1, [ Numeral(Sqrt(3)), Numeral(Sqrt(2)) ]) + [] + """ + num = len(vs) + _vs = (Ast * num)() + for i in range(num): + _vs[i] = vs[i].ast + _roots = AstVector(Z3_algebraic_roots(p.ctx_ref(), p.as_ast(), num, _vs), p.ctx) + return [ Numeral(r) for r in _roots ] if __name__ == "__main__": import doctest From 7ffba3ebf4cc06467bc1d510553aef0ab02076e7 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sun, 9 Dec 2012 08:02:12 -0800 Subject: [PATCH 36/60] more examples Signed-off-by: Leonardo de Moura --- src/api/python/z3num.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/api/python/z3num.py b/src/api/python/z3num.py index 99f336050..581536e44 100644 --- a/src/api/python/z3num.py +++ b/src/api/python/z3num.py @@ -58,6 +58,29 @@ class Numeral: True >>> Numeral(m[x])**2 2 + + We can also isolate the roots of polynomials. + + >>> x0, x1, x2 = RealVarVector(3) + >>> r0 = isolate_roots(x0**5 - x0 - 1) + >>> r0 + [1.1673039782?] + + In the following example, we are isolating the roots + of a univariate polynomial (on x1) obtained after substituting + x0 -> r0[0] + + >>> r1 = isolate_roots(x1**2 - x0 + 1, [ r0[0] ]) + >>> r1 + [-0.4090280898?, 0.4090280898?] + + Similarly, in the next example we isolate the roots of + a univariate polynomial (on x2) obtained after substituting + x0 -> r0[0] and x1 -> r1[0] + + >>> isolate_roots(x1*x2 + x0, [ r0[0], r1[0] ]) + [2.8538479564?] + """ def __init__(self, num, ctx=None): if isinstance(num, Ast): From 33234a4162edbda9abdfb1416bdad3c288baed98 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sun, 9 Dec 2012 12:23:35 -0800 Subject: [PATCH 37/60] Fixed issue http://z3.codeplex.com/workitem/10 Signed-off-by: Leonardo de Moura --- src/smt/mam.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/smt/mam.cpp b/src/smt/mam.cpp index 24b8e2e7c..c9d6ead88 100644 --- a/src/smt/mam.cpp +++ b/src/smt/mam.cpp @@ -142,6 +142,14 @@ namespace smt { } }; + struct initn : public instruction { + // We need that because starting at Z3 3.0, some associative + // operators (e.g., + and *) are represented using n-ary + // applications. + // We do not need the extra field for INIT1, ..., INIT6. + unsigned m_num_args; + }; + struct compare : public instruction { unsigned m_reg1; unsigned m_reg2; @@ -608,7 +616,18 @@ namespace smt { instruction * mk_init(unsigned n) { SASSERT(n >= 1); opcode op = n <= 6 ? static_cast(INIT1 + n - 1) : INITN; - return mk_instr(op, sizeof(instruction)); + if (op == INITN) { + // We store the actual number of arguments for INITN. + // Starting at Z3 3.0, some associative operators + // (e.g., + and *) are represented using n-ary + // applications. + initn * r = mk_instr(op, sizeof(initn)); + r->m_num_args = n; + return r; + } + else { + return mk_instr(op, sizeof(instruction)); + } } public: @@ -2345,6 +2364,8 @@ namespace smt { case INITN: m_app = m_registers[0]; m_num_args = m_app->get_num_args(); + if (m_num_args != static_cast(m_pc)->m_num_args) + goto backtrack; for (unsigned i = 0; i < m_num_args; i++) m_registers[i+1] = m_app->get_arg(i); m_pc = m_pc->m_next; @@ -3982,3 +4003,8 @@ namespace smt { } }; +#ifdef Z3DEBUG +void pp(smt::code_tree * c) { + c->display(std::cout); +} +#endif From 84e79035cb365fe4904887acb7b97e539b85c129 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sun, 9 Dec 2012 12:24:14 -0800 Subject: [PATCH 38/60] Updated release notes Signed-off-by: Leonardo de Moura --- RELEASE_NOTES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE_NOTES b/RELEASE_NOTES index e2703bdcb..7ac026673 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -24,6 +24,8 @@ Version 4.3.2 - Added new option to mk_make to allow users to specify where python bindings (Z3Py) will be installed. (Thanks to Dejan Jovanovic for reporting the problem). +- Fixed crash reported at http://z3.codeplex.com/workitem/10 + Version 4.3.1 ============= From 9b7946e52dd8f6e999d7498a1ec4333937d33857 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sun, 9 Dec 2012 14:24:37 -0800 Subject: [PATCH 39/60] added method for creating ast_manager based on context_params configuration Signed-off-by: Leonardo de Moura --- src/api/api_context.cpp | 44 +++++++++++++----------------- src/api/api_context.h | 6 ++-- src/cmd_context/cmd_context.cpp | 7 +---- src/cmd_context/context_params.cpp | 16 +++++++++++ src/cmd_context/context_params.h | 6 ++++ src/parsers/smt2/smt2parser.cpp | 2 +- src/parsers/smt2/smt2scanner.cpp | 7 ++--- src/parsers/smt2/smt2scanner.h | 2 +- src/parsers/util/parser_params.pyg | 2 +- 9 files changed, 51 insertions(+), 41 deletions(-) diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 1d2b22059..7dc8d1a12 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -82,13 +82,13 @@ namespace api { context::context(context_params * p, bool user_ref_count): m_params(p != 0 ? *p : context_params()), m_user_ref_count(user_ref_count), - m_manager(m_params.m_proof ? PGM_FINE : PGM_DISABLED, m_params.m_trace ? m_params.m_trace_file_name.c_str() : 0), - m_plugins(m_manager), - m_arith_util(m_manager), - m_bv_util(m_manager), - m_datalog_util(m_manager), - m_last_result(m_manager), - m_ast_trail(m_manager), + m_manager(m_params.mk_ast_manager()), + m_plugins(m()), + m_arith_util(m()), + m_bv_util(m()), + m_datalog_util(m()), + m_last_result(m()), + m_ast_trail(m()), m_replay_stack() { m_solver = 0; @@ -102,22 +102,16 @@ namespace api { m_smtlib_parser_has_decls = false; z3_bound_num_procs(); - // - // Configuration parameter settings. - // - if (m_params.m_debug_ref_count) { - m_manager.debug_ref_count(); - } m_error_handler = &default_error_handler; - m_basic_fid = m_manager.get_basic_family_id(); - m_arith_fid = m_manager.get_family_id("arith"); - m_bv_fid = m_manager.get_family_id("bv"); - m_array_fid = m_manager.get_family_id("array"); - m_dt_fid = m_manager.get_family_id("datatype"); - m_datalog_fid = m_manager.get_family_id("datalog_relation"); - m_dt_plugin = static_cast(m_manager.get_plugin(m_dt_fid)); + m_basic_fid = m().get_basic_family_id(); + m_arith_fid = m().get_family_id("arith"); + m_bv_fid = m().get_family_id("bv"); + m_array_fid = m().get_family_id("array"); + m_dt_fid = m().get_family_id("datatype"); + m_datalog_fid = m().get_family_id("datalog_relation"); + m_dt_plugin = static_cast(m().get_plugin(m_dt_fid)); if (!m_user_ref_count) { m_replay_stack.push_back(0); @@ -143,7 +137,7 @@ namespace api { { if (m_interruptable) (*m_interruptable)(); - m_manager.set_cancel(true); + m().set_cancel(true); } } @@ -196,12 +190,12 @@ namespace api { expr * context::mk_and(unsigned num_exprs, expr * const * exprs) { switch(num_exprs) { case 0: - return m_manager.mk_true(); + return m().mk_true(); case 1: save_ast_trail(exprs[0]); return exprs[0]; default: { - expr * a = m_manager.mk_and(num_exprs, exprs); + expr * a = m().mk_and(num_exprs, exprs); save_ast_trail(a); return a; } } @@ -217,7 +211,7 @@ namespace api { SASSERT(m_replay_stack.size() > num_scopes); unsigned j = m_replay_stack.size() - num_scopes - 1; if (!m_replay_stack[j]) { - m_replay_stack[j] = alloc(ast_ref_vector, m_manager); + m_replay_stack[j] = alloc(ast_ref_vector, m()); } m_replay_stack[j]->push_back(n); } @@ -325,7 +319,7 @@ namespace api { smt::kernel & context::get_smt_kernel() { if (!m_solver) { m_fparams.updt_params(m_params); - m_solver = alloc(smt::kernel, m_manager, m_fparams); + m_solver = alloc(smt::kernel, m(), m_fparams); } return *m_solver; } diff --git a/src/api/api_context.h b/src/api/api_context.h index 02768556d..edb79b2d5 100644 --- a/src/api/api_context.h +++ b/src/api/api_context.h @@ -46,7 +46,7 @@ namespace api { struct add_plugins { add_plugins(ast_manager & m); }; context_params m_params; bool m_user_ref_count; //!< if true, the user is responsible for managing referenc counters. - ast_manager m_manager; + scoped_ptr m_manager; add_plugins m_plugins; arith_util m_arith_util; @@ -101,10 +101,10 @@ namespace api { context(context_params * p, bool user_ref_count = false); ~context(); - ast_manager & m() { return m_manager; } + ast_manager & m() const { return *(m_manager.get()); } context_params & params() { return m_params; } - bool produce_proofs() const { return m_manager.proofs_enabled(); } + bool produce_proofs() const { return m().proofs_enabled(); } bool produce_models() const { return m_params.m_model; } bool produce_unsat_cores() const { return m_params.m_unsat_core; } bool use_auto_config() const { return m_params.m_auto_config; } diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index ae375fc99..828cc3a68 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -592,14 +592,9 @@ void cmd_context::init_manager() { SASSERT(m_manager == 0); SASSERT(m_pmanager == 0); m_check_sat_result = 0; - m_manager = alloc(ast_manager, - produce_proofs() ? PGM_FINE : PGM_DISABLED, - m_params.m_trace ? m_params.m_trace_file_name.c_str() : 0); + m_manager = m_params.mk_ast_manager(); m_pmanager = alloc(pdecl_manager, *m_manager); init_manager_core(true); - // PARAM-TODO - // if (params().m_smtlib2_compliant) - // m_manager->enable_int_real_coercions(false); } void cmd_context::init_external_manager() { diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index 96af5b52a..41ad5a423 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -79,6 +79,9 @@ void context_params::set(char const * param, char const * value) { else if (p == "debug_ref_count") { set_bool(m_debug_ref_count, param, value); } + else if (p == "smtlib2_compliant") { + set_bool(m_smtlib2_compliant, param, value); + } else { throw default_exception("unknown parameter '%s'", p.c_str()); } @@ -99,6 +102,7 @@ void context_params::updt_params(params_ref const & p) { m_trace_file_name = p.get_str("trace_file_name", "z3.log"); m_unsat_core = p.get_bool("unsat_core", false); m_debug_ref_count = p.get_bool("debug_ref_count", false); + m_smtlib2_compliant = p.get_bool("smtlib2_compliant", false); } void context_params::collect_param_descrs(param_descrs & d) { @@ -113,6 +117,7 @@ void context_params::collect_param_descrs(param_descrs & d) { d.insert("trace_file_name", CPK_STRING, "trace out file name (see option 'trace')", "z3.log"); d.insert("unsat_core", CPK_BOOL, "unsat-core generation for solvers, this parameter can be overwritten when creating a solver, not every solver in Z3 supports unsat core generation", "false"); d.insert("debug_ref_count", CPK_BOOL, "debug support for AST reference counting", "false"); + d.insert("smtlib2_compliant", CPK_BOOL, "enable/disable SMT-LIB 2.0 compliance", "false"); } params_ref context_params::merge_default_params(params_ref const & p) { @@ -133,4 +138,15 @@ void context_params::init_solver_params(ast_manager & m, solver & s, params_ref s.updt_params(merge_default_params(p)); } +ast_manager * context_params::mk_ast_manager() { + ast_manager * r = alloc(ast_manager, + m_proof ? PGM_FINE : PGM_DISABLED, + m_trace ? m_trace_file_name.c_str() : 0); + if (m_smtlib2_compliant) + r->enable_int_real_coercions(false); + if (m_debug_ref_count) + r->debug_ref_count(); + return r; +} + diff --git a/src/cmd_context/context_params.h b/src/cmd_context/context_params.h index b3933dc23..dd60b9616 100644 --- a/src/cmd_context/context_params.h +++ b/src/cmd_context/context_params.h @@ -37,6 +37,7 @@ public: bool m_model; bool m_model_validate; bool m_unsat_core; + bool m_smtlib2_compliant; // it must be here because it enable/disable the use of coercions in the ast_manager. unsigned m_timeout; context_params(); @@ -63,6 +64,11 @@ public: Example: auto_config */ params_ref merge_default_params(params_ref const & p); + + /** + \brief Create an AST manager using this configuration. + */ + ast_manager * mk_ast_manager(); }; diff --git a/src/parsers/smt2/smt2parser.cpp b/src/parsers/smt2/smt2parser.cpp index ee93dca2f..c99c362bd 100644 --- a/src/parsers/smt2/smt2parser.cpp +++ b/src/parsers/smt2/smt2parser.cpp @@ -2365,7 +2365,7 @@ namespace smt2 { parser(cmd_context & ctx, std::istream & is, bool interactive, params_ref const & p): m_ctx(ctx), m_params(p), - m_scanner(ctx, is, interactive, p), + m_scanner(ctx, is, interactive), m_curr(scanner::NULL_TOKEN), m_curr_cmd(0), m_num_bindings(0), diff --git a/src/parsers/smt2/smt2scanner.cpp b/src/parsers/smt2/smt2scanner.cpp index e2b2030ac..0f6101a93 100644 --- a/src/parsers/smt2/smt2scanner.cpp +++ b/src/parsers/smt2/smt2scanner.cpp @@ -242,7 +242,7 @@ namespace smt2 { } } - scanner::scanner(cmd_context & ctx, std::istream& stream, bool interactive, params_ref const & _p): + scanner::scanner(cmd_context & ctx, std::istream& stream, bool interactive): m_ctx(ctx), m_interactive(interactive), m_spos(0), @@ -254,9 +254,8 @@ namespace smt2 { m_bend(0), m_stream(stream), m_cache_input(false) { - - parser_params p(_p); - m_smtlib2_compliant = p.smt2_compliant(); + + m_smtlib2_compliant = ctx.params().m_smtlib2_compliant; for (int i = 0; i < 256; ++i) { m_normalized[i] = (char) i; diff --git a/src/parsers/smt2/smt2scanner.h b/src/parsers/smt2/smt2scanner.h index c63a09ff1..7b74c752f 100644 --- a/src/parsers/smt2/smt2scanner.h +++ b/src/parsers/smt2/smt2scanner.h @@ -76,7 +76,7 @@ namespace smt2 { EOF_TOKEN }; - scanner(cmd_context & ctx, std::istream& stream, bool interactive = false, params_ref const & p = params_ref()); + scanner(cmd_context & ctx, std::istream& stream, bool interactive = false); ~scanner() {} diff --git a/src/parsers/util/parser_params.pyg b/src/parsers/util/parser_params.pyg index fa8f17a00..3f7495f43 100644 --- a/src/parsers/util/parser_params.pyg +++ b/src/parsers/util/parser_params.pyg @@ -3,4 +3,4 @@ def_module_params('parser', params=(('ignore_user_patterns', BOOL, False, 'ignore patterns provided by the user'), ('ignore_bad_patterns', BOOL, True, 'ignore malformed patterns'), ('error_for_visual_studio', BOOL, False, 'display error messages in Visual Studio format'), - ('smt2_compliant', BOOL, False, 'enable/disable SMT-LIB 2.0 compliance'))) + )) From 6ae64142366e57976ea0709cb8ef24bcc534c682 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sun, 9 Dec 2012 15:04:14 -0800 Subject: [PATCH 40/60] avoiding clang warning messages Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 8 ++++---- src/tactic/tactical.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index ceae95fab..112096271 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1298,6 +1298,10 @@ def mk_config(): else: CXXFLAGS = '%s -D_NO_OMP_' % CXXFLAGS SLIBEXTRAFLAGS = '' + if DEBUG_MODE: + CXXFLAGS = '%s -g -Wall' % CXXFLAGS + else: + CXXFLAGS = '%s -O3 -D _EXTERNAL_RELEASE -fomit-frame-pointer' % CXXFLAGS sysname = os.uname()[0] if sysname == 'Darwin': SO_EXT = '.dylib' @@ -1331,10 +1335,6 @@ def mk_config(): CPPFLAGS = '%s -DZ3DEBUG' % CPPFLAGS if TRACE or DEBUG_MODE: CPPFLAGS = '%s -D_TRACE' % CPPFLAGS - if DEBUG_MODE: - CXXFLAGS = '%s -g -Wall' % CXXFLAGS - else: - CXXFLAGS = '%s -O3 -D _EXTERNAL_RELEASE -fomit-frame-pointer' % CXXFLAGS CXXFLAGS = '%s -msse -msse2' % CXXFLAGS config.write('PREFIX=%s\n' % PREFIX) config.write('CC=%s\n' % CC) diff --git a/src/tactic/tactical.cpp b/src/tactic/tactical.cpp index d8ece6a52..785a9d82e 100644 --- a/src/tactic/tactical.cpp +++ b/src/tactic/tactical.cpp @@ -559,10 +559,10 @@ public: ts.push_back(m_ts.get(i)->translate(*new_m)); } - unsigned finished_id = UINT_MAX; - par_exception_kind ex_kind; + unsigned finished_id = UINT_MAX; + par_exception_kind ex_kind = DEFAULT_EX; std::string ex_msg; - unsigned error_code; + unsigned error_code = 0; #pragma omp parallel for for (int i = 0; i < static_cast(sz); i++) { @@ -734,8 +734,8 @@ public: bool found_solution = false; bool failed = false; - par_exception_kind ex_kind; - unsigned error_code; + par_exception_kind ex_kind = DEFAULT_EX; + unsigned error_code = 0; std::string ex_msg; #pragma omp parallel for From d6a1ea82e1e5aab6d7752197ea2d7ade352f62e3 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sun, 9 Dec 2012 16:47:37 -0800 Subject: [PATCH 41/60] exposed subresultants aka psc-chain procedure Signed-off-by: Leonardo de Moura --- scripts/mk_project.py | 4 +-- src/api/api_algebraic.cpp | 2 +- src/api/api_polynomial.cpp | 50 ++++++++++++++++++++++++++++++++ src/api/python/z3poly.py | 37 +++++++++++++++++++++++ src/api/z3.h | 1 + src/api/z3_polynomial.h | 45 ++++++++++++++++++++++++++++ src/math/polynomial/polynomial.h | 1 + 7 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 src/api/python/z3poly.py create mode 100644 src/api/z3_polynomial.h diff --git a/scripts/mk_project.py b/scripts/mk_project.py index 3405d8751..0ebcfe45d 100644 --- a/scripts/mk_project.py +++ b/scripts/mk_project.py @@ -58,11 +58,11 @@ def init_project_def(): add_lib('ufbv_tactic', ['normal_forms', 'core_tactics', 'macros', 'smt_tactic', 'rewriter'], 'tactic/ufbv') add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa', 'aig_tactic', 'muz_qe', 'sls_tactic', 'subpaving_tactic'], 'tactic/portfolio') add_lib('smtparser', ['portfolio'], 'parsers/smt') + API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h'] add_lib('api', ['portfolio', 'user_plugin', 'smtparser'], - includes2install=['z3.h', 'z3_api.h', 'z3_v1.h', 'z3_macros.h', 'z3_algebraic.h']) + includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files) add_exe('shell', ['api', 'sat', 'extra_cmds'], exe_name='z3') add_exe('test', ['api', 'fuzzing'], exe_name='test-z3', install=False) - API_files = ['z3_api.h', 'z3_algebraic.h'] add_dll('api_dll', ['api', 'sat', 'extra_cmds'], 'api/dll', reexports=['api'], dll_name='libz3', diff --git a/src/api/api_algebraic.cpp b/src/api/api_algebraic.cpp index 3751c82ee..a3c6726f2 100644 --- a/src/api/api_algebraic.cpp +++ b/src/api/api_algebraic.cpp @@ -21,11 +21,11 @@ Notes: #include"z3.h" #include"api_log_macros.h" #include"api_context.h" +#include"api_ast_vector.h" #include"algebraic_numbers.h" #include"expr2polynomial.h" #include"cancel_eh.h" #include"scoped_timer.h" -#include"api_ast_vector.h" extern "C" { diff --git a/src/api/api_polynomial.cpp b/src/api/api_polynomial.cpp index af5803369..3148f972b 100644 --- a/src/api/api_polynomial.cpp +++ b/src/api/api_polynomial.cpp @@ -16,7 +16,16 @@ Author: Notes: --*/ +#include +#include"z3.h" +#include"api_log_macros.h" +#include"api_context.h" #include"api_polynomial.h" +#include"api_ast_vector.h" +#include"expr2polynomial.h" +#include"cancel_eh.h" +#include"scoped_timer.h" +#include"expr2var.h" namespace api { @@ -32,3 +41,44 @@ namespace api { } }; + +extern "C" { + + Z3_ast_vector Z3_API Z3_polynomial_subresultants(Z3_context c, Z3_ast p, Z3_ast q, Z3_ast x) { + Z3_TRY; + LOG_Z3_polynomial_subresultants(c, p, q, x); + RESET_ERROR_CODE(); + polynomial::manager & pm = mk_c(c)->pm(); + polynomial_ref _p(pm), _q(pm); + polynomial::scoped_numeral d(pm.m()); + default_expr2polynomial converter(mk_c(c)->m(), pm); + if (!converter.to_polynomial(to_expr(p), _p, d) || + !converter.to_polynomial(to_expr(q), _q, d)) { + SET_ERROR_CODE(Z3_INVALID_ARG); + return 0; + } + Z3_ast_vector_ref* result = alloc(Z3_ast_vector_ref, mk_c(c)->m()); + mk_c(c)->save_object(result); + if (converter.is_var(to_expr(x))) { + expr2var const & mapping = converter.get_mapping(); + unsigned v_x = mapping.to_var(to_expr(x)); + polynomial_ref_vector rs(pm); + polynomial_ref r(pm); + expr_ref _r(mk_c(c)->m()); + { + cancel_eh eh(pm); + api::context::set_interruptable(*(mk_c(c)), eh); + scoped_timer timer(mk_c(c)->params().m_timeout, &eh); + pm.psc_chain(_p, _q, v_x, rs); + } + for (unsigned i = 0; i < rs.size(); i++) { + r = rs.get(i); + converter.to_expr(r, true, _r); + result->m_ast_vector.push_back(_r); + } + } + RETURN_Z3(of_ast_vector(result)); + Z3_CATCH_RETURN(0); + } + +}; diff --git a/src/api/python/z3poly.py b/src/api/python/z3poly.py new file mode 100644 index 000000000..0b8bf9457 --- /dev/null +++ b/src/api/python/z3poly.py @@ -0,0 +1,37 @@ +############################################ +# Copyright (c) 2012 Microsoft Corporation +# +# Z3 Python interface for Z3 polynomials +# +# Author: Leonardo de Moura (leonardo) +############################################ +from z3 import * + +def subresultants(p, q, x): + """ + Return the non-constant subresultants of 'p' and 'q' with respect to the "variable" 'x'. + + 'p', 'q' and 'x' are Z3 expressions where 'p' and 'q' are arithmetic terms. + Note that, any subterm that cannot be viewed as a polynomial is assumed to be a variable. + Example: f(a) is a considered to be a variable b in the polynomial + + f(a)*f(a) + 2*f(a) + 1 + + >>> x, y = Reals('x y') + >>> subresultants(2*x + y, 3*x - 2*y + 2, x) + [-7*y + 4] + >>> r = subresultants(3*y*x**2 + y**3 + 1, 2*x**3 + y + 3, x) + >>> r[0] + 4*y**9 + 12*y**6 + 27*y**5 + 162*y**4 + 255*y**3 + 4 + >>> r[1] + -6*y**4 + -6*y + """ + return AstVector(Z3_polynomial_subresultants(p.ctx_ref(), p.as_ast(), q.as_ast(), x.as_ast()), p.ctx) + +if __name__ == "__main__": + import doctest + if doctest.testmod().failed: + exit(1) + + + diff --git a/src/api/z3.h b/src/api/z3.h index 15f0a5985..c3e38e3f1 100644 --- a/src/api/z3.h +++ b/src/api/z3.h @@ -25,6 +25,7 @@ Notes: #include"z3_macros.h" #include"z3_api.h" #include"z3_algebraic.h" +#include"z3_polynomial.h" #undef __in #undef __out diff --git a/src/api/z3_polynomial.h b/src/api/z3_polynomial.h new file mode 100644 index 000000000..614e654f9 --- /dev/null +++ b/src/api/z3_polynomial.h @@ -0,0 +1,45 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + z3_polynomial.h + +Abstract: + + Additional APIs for polynomials. + +Author: + + Leonardo de Moura (leonardo) 2012-12-09 + +Notes: + +--*/ + +#ifndef _Z3_POLYNOMIAL_H_ +#define _Z3_POLYNOMIAL_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + + /** + \brief Return the nonzero subresultants of \c p and \c q with respect to the "variable" \c x. + + \pre \c p, \c q and \c x are Z3 expressions where \c p and \c q are arithmetic terms. + Note that, any subterm that cannot be viewed as a polynomial is assumed to be a variable. + Example: f(a) is a considered to be a variable in the polynomial + + f(a)*f(a) + 2*f(a) + 1 + + def_API('Z3_polynomial_subresultants', AST_VECTOR, (_in(CONTEXT), _in(AST), _in(AST), _in(AST))) + */ + Z3_ast_vector Z3_API Z3_polynomial_subresultants(__in Z3_context c, __in Z3_ast p, __in Z3_ast q, __in Z3_ast x); + + +#ifdef __cplusplus +}; +#endif // __cplusplus + +#endif diff --git a/src/math/polynomial/polynomial.h b/src/math/polynomial/polynomial.h index 7cefe6f56..d17d2ac5a 100644 --- a/src/math/polynomial/polynomial.h +++ b/src/math/polynomial/polynomial.h @@ -219,6 +219,7 @@ namespace polynomial { void set_zp(uint64 p); void set_cancel(bool f); + void cancel() { set_cancel(true); } /** \brief Abstract event handler. From 840d0aef6daa0b4f358c3f3f7b56a396ca7ddcd7 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Sun, 9 Dec 2012 18:59:32 -0800 Subject: [PATCH 42/60] fixed bug in generated code Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 2 +- src/util/params.cpp | 2 ++ src/util/params.h | 6 +++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 112096271..d5f1b055b 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1507,7 +1507,7 @@ def def_module_params(module_name, export, params, class_name=None, description= out.write(' params_ref const & p;\n') if export: out.write(' params_ref g;\n') - out.write(' %s(params_ref const & _p = params_ref()):\n' % class_name) + out.write(' %s(params_ref const & _p = params_ref::get_empty()):\n' % class_name) out.write(' p(_p)') if export: out.write(', g(gparams::get_module("%s"))' % module_name) diff --git a/src/util/params.cpp b/src/util/params.cpp index f302f7721..d9878c70a 100644 --- a/src/util/params.cpp +++ b/src/util/params.cpp @@ -21,6 +21,8 @@ Notes: #include"symbol.h" #include"dictionary.h" +params_ref params_ref::g_empty_params_ref; + std::string norm_param_name(char const * n) { if (n == 0) return "_"; diff --git a/src/util/params.h b/src/util/params.h index 13850758c..15be825b0 100644 --- a/src/util/params.h +++ b/src/util/params.h @@ -31,6 +31,8 @@ class params; class param_descrs; class params_ref { + static params_ref g_empty_params_ref; + params * m_params; void init(); void copy_core(params const * p); @@ -38,7 +40,9 @@ public: params_ref():m_params(0) {} params_ref(params_ref const & p); ~params_ref(); - + + static params_ref const & get_empty() { return g_empty_params_ref; } + params_ref & operator=(params_ref const & p); // copy params from src From af37aa27430b4802ef448db471b93a02097d2d43 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 10 Dec 2012 06:30:26 -0800 Subject: [PATCH 43/60] improving java bindings build Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index d5f1b055b..7cf67f9db 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -216,7 +216,7 @@ def find_java_home(): if JAVA_HOME != None: if is_verbose(): print "Checking jni.h..." - if os.path.exists('%s%sinclude%sjni.h' % (JAVA_HOME, os.sep, os.sep)): + if os.path.exists(os.path.join(JAVA_HOME, 'include', 'jni.h')): return if is_verbose(): print "Finding JAVA_HOME..." @@ -238,8 +238,8 @@ def find_java_home(): path = string.join(tmp[:len(tmp) - 3], os.sep) if is_verbose(): print "Checking jni.h..." - if not os.path.exists('%s%sinclude%sjni.h' % (path, os.sep, os.sep)): - raise MKException("Failed to detect jni.h at '%s%sinclude'" % (path, os.sep)) + if not os.path.exists(os.path.join(path, 'include', 'jni.h')): + raise MKException("Failed to detect jni.h at '%s'" % os.path.join(path, 'include')) JAVA_HOME = path return raise MKException('Failed to find JAVA_HOME') From 1fb0fec7d12428373b0378028d18ff0fd6c27fb6 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 10 Dec 2012 06:43:57 -0800 Subject: [PATCH 44/60] improved jni.h detection Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 7cf67f9db..f3523ec28 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -211,6 +211,13 @@ def check_java(): raise MKException('Failed testing Java program. Set environment variable JAVA with the path to the Java virtual machine') find_java_home() +def find_jni_h(path): + for root, dirs, files in os.walk(path): + for f in files: + if f == 'jni.h': + return root + return False + def find_java_home(): global JAVA_HOME if JAVA_HOME != None: @@ -238,9 +245,12 @@ def find_java_home(): path = string.join(tmp[:len(tmp) - 3], os.sep) if is_verbose(): print "Checking jni.h..." - if not os.path.exists(os.path.join(path, 'include', 'jni.h')): - raise MKException("Failed to detect jni.h at '%s'" % os.path.join(path, 'include')) - JAVA_HOME = path + jni_dir = find_jni_h(path) + if not jni_dir: + raise MKException("Failed to detect jni.h at '%s'.Possible solution: set JAVA_HOME with the path to JDK." % os.path.join(path, 'include')) + JAVA_HOME = os.path.split(jni_dir)[0] + if is_verbose(): + print 'JAVA_HOME=%s' % JAVA_HOME return raise MKException('Failed to find JAVA_HOME') From 4981134fd71d954623ca3fb238352119770365b2 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 10 Dec 2012 06:52:56 -0800 Subject: [PATCH 45/60] Fixing VS warning Signed-off-by: Leonardo de Moura --- src/api/api_algebraic.cpp | 63 ++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/src/api/api_algebraic.cpp b/src/api/api_algebraic.cpp index a3c6726f2..7716cbb59 100644 --- a/src/api/api_algebraic.cpp +++ b/src/api/api_algebraic.cpp @@ -27,15 +27,6 @@ Notes: #include"cancel_eh.h" #include"scoped_timer.h" -extern "C" { - - bool Z3_algebraic_is_value_core(Z3_context c, Z3_ast a) { - api::context * _c = mk_c(c); - return - is_expr(a) && - (_c->autil().is_numeral(to_expr(a)) || - _c->autil().is_irrational_algebraic_numeral(to_expr(a))); - } #define CHECK_IS_ALGEBRAIC(ARG, RET) { \ if (!Z3_algebraic_is_value_core(c, ARG)) { \ @@ -51,32 +42,42 @@ extern "C" { } \ } - static arith_util & au(Z3_context c) { - return mk_c(c)->autil(); - } +static arith_util & au(Z3_context c) { + return mk_c(c)->autil(); +} - static algebraic_numbers::manager & am(Z3_context c) { - return au(c).am(); - } +static algebraic_numbers::manager & am(Z3_context c) { + return au(c).am(); +} - static bool is_rational(Z3_context c, Z3_ast a) { - return au(c).is_numeral(to_expr(a)); - } +static bool is_rational(Z3_context c, Z3_ast a) { + return au(c).is_numeral(to_expr(a)); +} - static bool is_irrational(Z3_context c, Z3_ast a) { - return au(c).is_irrational_algebraic_numeral(to_expr(a)); - } +static bool is_irrational(Z3_context c, Z3_ast a) { + return au(c).is_irrational_algebraic_numeral(to_expr(a)); +} - static rational get_rational(Z3_context c, Z3_ast a) { - SASSERT(is_rational(c, a)); - rational r; - VERIFY(au(c).is_numeral(to_expr(a), r)); - return r; - } - - static algebraic_numbers::anum const & get_irrational(Z3_context c, Z3_ast a) { - SASSERT(is_irrational(c, a)); - return au(c).to_irrational_algebraic_numeral(to_expr(a)); +static rational get_rational(Z3_context c, Z3_ast a) { + SASSERT(is_rational(c, a)); + rational r; + VERIFY(au(c).is_numeral(to_expr(a), r)); + return r; +} + +static algebraic_numbers::anum const & get_irrational(Z3_context c, Z3_ast a) { + SASSERT(is_irrational(c, a)); + return au(c).to_irrational_algebraic_numeral(to_expr(a)); +} + +extern "C" { + + bool Z3_algebraic_is_value_core(Z3_context c, Z3_ast a) { + api::context * _c = mk_c(c); + return + is_expr(a) && + (_c->autil().is_numeral(to_expr(a)) || + _c->autil().is_irrational_algebraic_numeral(to_expr(a))); } Z3_bool Z3_API Z3_algebraic_is_value(Z3_context c, Z3_ast a) { From 99d0449272c82e04141875c857245620d155ca5c Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 10 Dec 2012 07:51:45 -0800 Subject: [PATCH 46/60] added Java docs Signed-off-by: Leonardo de Moura --- doc/website.dox | 1 + doc/z3api.dox | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/website.dox b/doc/website.dox index efbf71f56..6936b4f77 100644 --- a/doc/website.dox +++ b/doc/website.dox @@ -13,6 +13,7 @@ - \ref capi - \ref cppapi - .NET API + - Java API - Python API (also available in pydoc format). - Try Z3 online at RiSE4Fun using Python or SMT 2.0. */ diff --git a/doc/z3api.dox b/doc/z3api.dox index 07c7fe0dc..0233e6d83 100644 --- a/doc/z3api.dox +++ b/doc/z3api.dox @@ -687,6 +687,7 @@ WARN_LOGFILE = # with spaces. INPUT = ../src/api/dotnet \ + ../src/api/java \ ../src/api/c++ \ ./tmp @@ -740,7 +741,8 @@ FILE_PATTERNS = website.dox \ Util.cs \ Version.cs \ Z3Exception.cs \ - Z3Object.cs + Z3Object.cs \ + *.java # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. From 8015d8b79abb6fb80079e3d7ad325f5f21df9836 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 10 Dec 2012 07:52:14 -0800 Subject: [PATCH 47/60] Updated Java README Signed-off-by: Leonardo de Moura --- src/api/java/README | 1 - 1 file changed, 1 deletion(-) diff --git a/src/api/java/README b/src/api/java/README index 0591eec88..7afe098fb 100644 --- a/src/api/java/README +++ b/src/api/java/README @@ -1,4 +1,3 @@ Java bindings ------------- -This is currently "working in progress". \ No newline at end of file From 7f210d55be7498f26e12497c5d19338c0f269c45 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 10 Dec 2012 07:52:33 -0800 Subject: [PATCH 48/60] fixed warnings on Win64 Signed-off-by: Leonardo de Moura --- src/cmd_context/context_params.cpp | 2 +- src/util/gparams.cpp | 2 +- src/util/params.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index 41ad5a423..6d9222a37 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -41,7 +41,7 @@ void context_params::set_bool(bool & opt, char const * param, char const * value void context_params::set(char const * param, char const * value) { std::string p = param; - unsigned n = p.size(); + unsigned n = static_cast(p.size()); for (unsigned i = 0; i < n; i++) { if (p[i] >= 'A' && p[i] <= 'Z') p[i] = p[i] - 'A' + 'a'; diff --git a/src/util/gparams.cpp b/src/util/gparams.cpp index b81531798..1305a1e02 100644 --- a/src/util/gparams.cpp +++ b/src/util/gparams.cpp @@ -165,7 +165,7 @@ public: if (*name == ':') name++; std::string tmp = name; - unsigned n = tmp.size(); + unsigned n = static_cast(tmp.size()); for (unsigned i = 0; i < n; i++) { if (tmp[i] >= 'A' && tmp[i] <= 'Z') tmp[i] = tmp[i] - 'A' + 'a'; diff --git a/src/util/params.cpp b/src/util/params.cpp index d9878c70a..0ee42868d 100644 --- a/src/util/params.cpp +++ b/src/util/params.cpp @@ -29,7 +29,7 @@ std::string norm_param_name(char const * n) { if (*n == ':') n++; std::string r = n; - unsigned sz = r.size(); + unsigned sz = static_cast(r.size()); if (sz == 0) return "_"; for (unsigned i = 0; i < sz; i++) { @@ -135,7 +135,7 @@ struct param_descrs::imp { if (smt2_style) out << ':'; char const * s = it2->bare_str(); - unsigned n = strlen(s); + unsigned n = static_cast(strlen(s)); for (unsigned i = 0; i < n; i++) { if (smt2_style && s[i] == '_') out << '-'; From 8bfbdf1e680d2fbfa64e7f60e28ba4eede7f5d6a Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 10 Dec 2012 19:04:21 +0000 Subject: [PATCH 49/60] fixing clang warnings on OSX Signed-off-by: Leonardo de Moura --- scripts/mk_util.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index f3523ec28..381f92def 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -1312,14 +1312,14 @@ def mk_config(): CXXFLAGS = '%s -g -Wall' % CXXFLAGS else: CXXFLAGS = '%s -O3 -D _EXTERNAL_RELEASE -fomit-frame-pointer' % CXXFLAGS + if is_CXX_clangpp(): + CXXFLAGS = '%s -Wno-unknown-pragmas -Wno-overloaded-virtual -Wno-unused-value' % CXXFLAGS sysname = os.uname()[0] if sysname == 'Darwin': SO_EXT = '.dylib' SLIBFLAGS = '-dynamiclib' elif sysname == 'Linux': CXXFLAGS = '%s -fno-strict-aliasing -D_LINUX_' % CXXFLAGS - if is_CXX_clangpp(): - CXXFLAGS = '%s -Wno-unknown-pragmas -Wno-overloaded-virtual -Wno-unused-value' % CXXFLAGS SO_EXT = '.so' LDFLAGS = '%s -lrt' % LDFLAGS SLIBFLAGS = '-shared' From 271c143de58df38da8c9fc4a65df8564b80a1d40 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 10 Dec 2012 11:13:04 -0800 Subject: [PATCH 50/60] update unstable branch with qhc changes that don't have dependencies Signed-off-by: Nikolaj Bjorner --- src/muz_qe/dl_bmc_engine.cpp | 2361 ++++++++++++--------- src/muz_qe/dl_bmc_engine.h | 72 +- src/muz_qe/dl_context.cpp | 2 + src/muz_qe/dl_mk_array_blast.cpp | 15 +- src/muz_qe/dl_mk_coalesce.cpp | 12 +- src/muz_qe/dl_mk_extract_quantifiers2.cpp | 366 ++++ src/muz_qe/dl_mk_extract_quantifiers2.h | 91 + src/muz_qe/dl_mk_rule_inliner.cpp | 6 +- src/muz_qe/dl_rule.cpp | 11 +- src/muz_qe/dl_rule.h | 2 +- src/muz_qe/pdr_quantifiers.cpp | 2 +- 11 files changed, 1881 insertions(+), 1059 deletions(-) create mode 100644 src/muz_qe/dl_mk_extract_quantifiers2.cpp create mode 100644 src/muz_qe/dl_mk_extract_quantifiers2.h diff --git a/src/muz_qe/dl_bmc_engine.cpp b/src/muz_qe/dl_bmc_engine.cpp index 27161320e..b5ffa808a 100644 --- a/src/muz_qe/dl_bmc_engine.cpp +++ b/src/muz_qe/dl_bmc_engine.cpp @@ -29,30 +29,1382 @@ Revision History: #include "model_smt2_pp.h" #include "ast_smt_pp.h" #include "well_sorted.h" +#include "rewriter_def.h" namespace datalog { + + // --------------------------------------------------------------------------- + // Basic linear BMC based on indexed variables using quantified bit-vector domains. + + class bmc::qlinear { + bmc& b; + ast_manager& m; + bv_util m_bv; + unsigned m_bit_width; + public: + qlinear(bmc& b): b(b), m(b.m), m_bv(m), m_bit_width(1) {} + + + lbool check() { + setup(); + m_bit_width = 4; + lbool res = l_false; + while (res == l_false) { + b.m_solver.push(); + IF_VERBOSE(1, verbose_stream() << "bit_width: " << m_bit_width << "\n";); + compile(); + b.checkpoint(); + func_decl_ref q = mk_q_func_decl(b.m_query_pred); + expr* T = m.mk_const(symbol("T"), mk_index_sort()); + expr_ref fml(m.mk_app(q, T), m); + b.assert_expr(fml); + res = b.m_solver.check(); + + if (res == l_true) { + res = get_model(); + } + b.m_solver.pop(1); + ++m_bit_width; + } + return res; + } + private: + + sort_ref mk_index_sort() { + return sort_ref(m_bv.mk_sort(m_bit_width), m); + } + + var_ref mk_index_var() { + return var_ref(m.mk_var(0, mk_index_sort()), m); + } + + void compile() { + sort_ref index_sort = mk_index_sort(); + var_ref var = mk_index_var(); + sort* index_sorts[1] = { index_sort }; + symbol tick("T"); + rule_set::decl2rules::iterator it = b.m_rules.begin_grouped_rules(); + rule_set::decl2rules::iterator end = b.m_rules.end_grouped_rules(); + for (; it != end; ++it) { + func_decl* p = it->m_key; + rule_vector const& rls = *it->m_value; + // Assert: forall level . p(T) => body of rule i + equalities for head of rule i + func_decl_ref pr = mk_q_func_decl(p); + expr_ref pred = expr_ref(m.mk_app(pr, var.get()), m); + expr_ref_vector rules(m), sub(m), conjs(m); + expr_ref trm(m), rule_body(m), rule_i(m); + for (unsigned i = 0; i < rls.size(); ++i) { + sub.reset(); + conjs.reset(); + rule& r = *rls[i]; + rule_i = m.mk_app(mk_q_rule(p, i), var.get()); + rules.push_back(rule_i); + + mk_qrule_vars(r, i, sub); + + // apply substitution to body. + var_subst vs(m, false); + for (unsigned k = 0; k < p->get_arity(); ++k) { + vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr(), trm); + conjs.push_back(m.mk_eq(trm, mk_q_arg(p, k, true))); + } + for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { + func_decl* q = r.get_decl(j); + for (unsigned k = 0; k < q->get_arity(); ++k) { + vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr(), trm); + conjs.push_back(m.mk_eq(trm, mk_q_arg(q, k, false))); + } + func_decl_ref qr = mk_q_func_decl(q); + conjs.push_back(m.mk_app(qr, m_bv.mk_bv_sub(var, mk_q_one()))); + } + for (unsigned j = r.get_uninterpreted_tail_size(); j < r.get_tail_size(); ++j) { + vs(r.get_tail(j), sub.size(), sub.c_ptr(), trm); + conjs.push_back(trm); + } + if (r.get_uninterpreted_tail_size() > 0) { + conjs.push_back(m_bv.mk_ule(mk_q_one(), var)); + } + bool_rewriter(m).mk_and(conjs.size(), conjs.c_ptr(), rule_body); + trm = m.mk_implies(rule_i, rule_body); + trm = m.mk_forall(1, index_sorts, &tick, trm, 1); + b.assert_expr(trm); + } + bool_rewriter(m).mk_or(rules.size(), rules.c_ptr(), trm); + trm = m.mk_implies(pred, trm); + trm = m.mk_forall(1, index_sorts, &tick, trm, 1); + SASSERT(is_well_sorted(m, trm)); + b.assert_expr(trm); + } + } + + void setup() { + b.m_fparams.m_relevancy_lvl = 2; + b.m_fparams.m_model = true; + b.m_fparams.m_model_compact = true; + b.m_fparams.m_mbqi = true; + } + + void mk_qrule_vars(datalog::rule const& r, unsigned rule_id, expr_ref_vector& sub) { + ptr_vector sorts; + r.get_vars(sorts); + // populate substitution of bound variables. + sub.reset(); + sub.resize(sorts.size()); + + for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) { + expr* arg = r.get_head()->get_arg(k); + if (is_var(arg)) { + unsigned idx = to_var(arg)->get_idx(); + if (!sub[idx].get()) { + sub[idx] = mk_q_arg(r.get_decl(), k, true); + } + } + } + for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { + func_decl* q = r.get_decl(j); + for (unsigned k = 0; k < q->get_arity(); ++k) { + expr* arg = r.get_tail(j)->get_arg(k); + if (is_var(arg)) { + unsigned idx = to_var(arg)->get_idx(); + if (!sub[idx].get()) { + sub[idx] = mk_q_arg(q, k, false); + } + } + } + } + for (unsigned j = 0, idx = 0; j < sorts.size(); ++j) { + if (sorts[j] && !sub[j].get()) { + sub[j] = mk_q_var(r.get_decl(), sorts[j], rule_id, idx++); + } + } + } + + expr_ref mk_q_var(func_decl* pred, sort* s, unsigned rule_id, unsigned idx) { + std::stringstream _name; + _name << pred->get_name() << "#" << rule_id << "_" << idx; + symbol nm(_name.str().c_str()); + var_ref var = mk_index_var(); + return expr_ref(m.mk_app(m.mk_func_decl(nm, mk_index_sort(), s), var), m); + } + + expr_ref mk_q_arg(func_decl* pred, unsigned idx, bool is_current) { + SASSERT(idx < pred->get_arity()); + std::stringstream _name; + _name << pred->get_name() << "#" << idx; + symbol nm(_name.str().c_str()); + expr_ref var(mk_index_var(), m); + if (!is_current) { + var = m_bv.mk_bv_sub(var, mk_q_one()); + } + return expr_ref(m.mk_app(m.mk_func_decl(nm, mk_index_sort(), pred->get_domain(idx)), var), m); + } + + expr_ref mk_q_one() { + return mk_q_num(1); + } + + expr_ref mk_q_num(unsigned i) { + return expr_ref(m_bv.mk_numeral(i, m_bit_width), m); + } + + func_decl_ref mk_q_func_decl(func_decl* f) { + std::stringstream _name; + _name << f->get_name() << "#"; + symbol nm(_name.str().c_str()); + return func_decl_ref(m.mk_func_decl(nm, mk_index_sort(), f->get_range()), m); + } + + func_decl_ref mk_q_rule(func_decl* f, unsigned rule_id) { + std::stringstream _name; + _name << f->get_name() << "#" << rule_id; + symbol nm(_name.str().c_str()); + return func_decl_ref(m.mk_func_decl(nm, mk_index_sort(), m.mk_bool_sort()), m); + } + + + expr_ref eval_q(model_ref& model, func_decl* f, unsigned i) { + func_decl_ref fn = mk_q_func_decl(f); + expr_ref t(m), result(m); + t = m.mk_app(mk_q_func_decl(f).get(), mk_q_num(i)); + model->eval(t, result); + return result; + } + + expr_ref eval_q(model_ref& model, expr* t, unsigned i) { + expr_ref tmp(m), result(m), num(m); + var_subst vs(m, false); + num = mk_q_num(i); + expr* nums[1] = { num }; + vs(t, 1, nums, tmp); + model->eval(tmp, result); + return result; + } + + lbool get_model() { + rule_manager& rm = b.m_ctx.get_rule_manager(); + func_decl_ref q = mk_q_func_decl(b.m_query_pred); + expr_ref T(m), rule_i(m), vl(m); + model_ref md; + proof_ref pr(m); + rule_unifier unifier(b.m_ctx); + rational num; + unsigned level, bv_size; + + b.m_solver.get_model(md); + func_decl* pred = b.m_query_pred; + dl_decl_util util(m); + T = m.mk_const(symbol("T"), mk_index_sort()); + md->eval(T, vl); + VERIFY (m_bv.is_numeral(vl, num, bv_size)); + SASSERT(num.is_unsigned()); + level = num.get_unsigned(); + SASSERT(m.is_true(eval_q(md, b.m_query_pred, level))); + TRACE("bmc", model_smt2_pp(tout, m, *md, 0);); + + rule_ref r0(rm), r1(rm), r2(rm); + while (true) { + TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";); + expr_ref_vector sub(m); + rule_vector const& rls = b.m_rules.get_predicate_rules(pred); + rule* r = 0; + unsigned i = 0; + for (; i < rls.size(); ++i) { + rule_i = m.mk_app(mk_q_rule(pred, i), mk_q_num(level).get()); + TRACE("bmc", rls[i]->display(b.m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " ");); + if (m.is_true(eval_q(md, rule_i, level))) { + r = rls[i]; + break; + } + } + SASSERT(r); + mk_qrule_vars(*r, i, sub); + // we have rule, we have variable names of rule. + + // extract values for the variables in the rule. + for (unsigned j = 0; j < sub.size(); ++j) { + expr_ref vl = eval_q(md, sub[j].get(), i); + if (vl) { + // vl can be 0 if the interpretation does not assign a value to it. + sub[j] = vl; + } + else { + sub[j] = m.mk_var(j, m.get_sort(sub[j].get())); + } + } + svector > positions; + vector substs; + expr_ref fml(m), concl(m); + + r->to_formula(fml); + r2 = r; + rm.substitute(r2, sub.size(), sub.c_ptr()); + if (r0) { + VERIFY(unifier.unify_rules(*r0.get(), 0, *r2.get())); + expr_ref_vector sub1 = unifier.get_rule_subst(*r0.get(), true); + expr_ref_vector sub2 = unifier.get_rule_subst(*r2.get(), false); + apply_subst(sub, sub2); + unifier.apply(*r0.get(), 0, *r2.get(), r1); + r1->to_formula(concl); + scoped_coarse_proof _sp(m); + + proof* p = m.mk_asserted(fml); + proof* premises[2] = { pr, p }; + + positions.push_back(std::make_pair(0, 1)); + + substs.push_back(sub1); + substs.push_back(sub); + pr = m.mk_hyper_resolve(2, premises, concl, positions, substs); + r0 = r1; + } + else { + r2->to_formula(concl); + scoped_coarse_proof _sp(m); + proof* p = m.mk_asserted(fml); + if (sub.empty()) { + pr = p; + } + else { + substs.push_back(sub); + pr = m.mk_hyper_resolve(1, &p, concl, positions, substs); + } + r0 = r2; + } + + if (level == 0) { + SASSERT(r->get_uninterpreted_tail_size() == 0); + break; + } + --level; + SASSERT(r->get_uninterpreted_tail_size() == 1); + pred = r->get_decl(0); + } + scoped_coarse_proof _sp(m); + apply(m, b.m_pc.get(), pr); + b.m_answer = pr; + return l_true; + } + }; + + + // -------------------------------------------------------------------------- + // Basic non-linear BMC based on compiling into quantifiers. + + class bmc::nonlinear { + bmc& b; + ast_manager& m; + + public: + + nonlinear(bmc& b): b(b), m(b.m) {} + + lbool check() { + setup(); + for (unsigned i = 0; ; ++i) { + IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";); + b.checkpoint(); + expr_ref_vector fmls(m); + compile(b.m_rules, fmls, i); + assert_fmls(fmls); + lbool res = check(i); + if (res == l_undef) { + return res; + } + if (res == l_true) { + get_model(i); + return res; + } + } + } + + expr_ref compile_query(func_decl* query_pred, unsigned level) { + expr_ref_vector vars(m); + func_decl_ref level_p = mk_level_predicate(query_pred, level); + for (unsigned i = 0; i < level_p->get_arity(); ++i) { + std::stringstream _name; + _name << query_pred->get_name() << "#" << level << "_" << i; + symbol nm(_name.str().c_str()); + vars.push_back(m.mk_const(nm, level_p->get_domain(i))); + } + return expr_ref(m.mk_app(level_p, vars.size(), vars.c_ptr()), m); + } + + void compile(rule_set const& rules, expr_ref_vector& result, unsigned level) { + bool_rewriter br(m); + rule_set::decl2rules::iterator it = rules.begin_grouped_rules(); + rule_set::decl2rules::iterator end = rules.end_grouped_rules(); + for (; it != end; ++it) { + func_decl* p = it->m_key; + rule_vector const& rls = *it->m_value; + + // Assert: p_level(vars) => r1_level(vars) \/ r2_level(vars) \/ r3_level(vars) \/ ... + // Assert: r_i_level(vars) => exists aux_vars . body of rule i for level + + func_decl_ref level_pred = mk_level_predicate(p, level); + expr_ref_vector rules(m); + expr_ref body(m), head(m); + for (unsigned i = 0; i < rls.size(); ++i) { + rule& r = *rls[i]; + func_decl_ref rule_i = mk_level_rule(p, i, level); + rules.push_back(apply_vars(rule_i)); + + ptr_vector rule_vars; + expr_ref_vector args(m), conjs(m); + + r.get_vars(rule_vars); + obj_hashtable used_vars; + unsigned num_vars = 0; + for (unsigned i = 0; i < r.get_decl()->get_arity(); ++i) { + expr* arg = r.get_head()->get_arg(i); + if (is_var(arg) && !used_vars.contains(arg)) { + used_vars.insert(arg); + args.push_back(arg); + rule_vars[to_var(arg)->get_idx()] = 0; + } + else { + sort* srt = m.get_sort(arg); + args.push_back(m.mk_var(rule_vars.size()+num_vars, srt)); + conjs.push_back(m.mk_eq(args.back(), arg)); + ++num_vars; + } + } + head = m.mk_app(rule_i, args.size(), args.c_ptr()); + for (unsigned i = 0; i < r.get_tail_size(); ++i) { + conjs.push_back(r.get_tail(i)); + } + br.mk_and(conjs.size(), conjs.c_ptr(), body); + + replace_by_level_predicates(level, body); + body = skolemize_vars(r, args, rule_vars, body); + body = m.mk_implies(head, body); + body = bind_vars(body, head); + result.push_back(body); + } + br.mk_or(rules.size(), rules.c_ptr(), body); + head = apply_vars(level_pred); + body = m.mk_implies(head, body); + body = bind_vars(body, head); + result.push_back(body); + } + } + + private: + + void assert_fmls(expr_ref_vector const& fmls) { + for (unsigned i = 0; i < fmls.size(); ++i) { + b.assert_expr(fmls[i]); + } + } + + void setup() { + b.m_fparams.m_model = true; + b.m_fparams.m_model_compact = true; + b.m_fparams.m_mbqi = true; + b.m_fparams.m_relevancy_lvl = 2; + } + + lbool check(unsigned level) { + expr_ref p = compile_query(b.m_query_pred, level); + expr_ref q(m), q_at_level(m); + q = m.mk_fresh_const("q",m.mk_bool_sort()); + q_at_level = m.mk_implies(q, p); + b.assert_expr(q_at_level); + expr* qr = q.get(); + return b.m_solver.check(1, &qr); + } + + proof_ref get_proof(model_ref& md, func_decl* pred, app* prop, unsigned level) { + TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";); + + expr_ref prop_r(m), prop_v(m), fml(m), prop_body(m), tmp(m), body(m); + expr_ref_vector args(m); + proof_ref_vector prs(m); + proof_ref pr(m); + + // find the rule that was triggered by evaluating the arguments to prop. + rule_vector const& rls = b.m_rules.get_predicate_rules(pred); + rule* r = 0; + for (unsigned i = 0; i < rls.size(); ++i) { + func_decl_ref rule_i = mk_level_rule(pred, i, level); + TRACE("bmc", rls[i]->display(b.m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " ");); + prop_r = m.mk_app(rule_i, prop->get_num_args(), prop->get_args()); + md->eval(prop_r, prop_v); + if (m.is_true(prop_v)) { + r = rls[i]; + break; + } + } + SASSERT(r); + r->to_formula(fml); + IF_VERBOSE(1, verbose_stream() << mk_pp(fml, m) << "\n";); + prs.push_back(m.mk_asserted(fml)); + unsigned sz = r->get_uninterpreted_tail_size(); + + ptr_vector rule_vars; + r->get_vars(rule_vars); + args.append(prop->get_num_args(), prop->get_args()); + expr_ref_vector sub = mk_skolem_binding(*r, rule_vars, args); + if (sub.empty() && sz == 0) { + pr = prs[0].get(); + return pr; + } + for (unsigned j = 0; j < sub.size(); ++j) { + md->eval(sub[j].get(), tmp); + sub[j] = tmp; + } + + svector > positions; + vector substs; + var_subst vs(m, false); + + substs.push_back(sub); + for (unsigned j = 0; j < sz; ++j) { + func_decl* head_j = r->get_decl(j); + app* body_j = r->get_tail(j); + vs(body_j, sub.size(), sub.c_ptr(), prop_body); + prs.push_back(get_proof(md, head_j, to_app(prop_body), level-1)); + positions.push_back(std::make_pair(j+1,0)); + substs.push_back(expr_ref_vector(m)); + } + pr = m.mk_hyper_resolve(sz+1, prs.c_ptr(), prop, positions, substs); + return pr; + } + + void get_model(unsigned level) { + scoped_coarse_proof _sp(m); + expr_ref level_query = compile_query(b.m_query_pred, level); + model_ref md; + b.m_solver.get_model(md); + IF_VERBOSE(2, model_smt2_pp(verbose_stream(), m, *md, 0);); + proof_ref pr = get_proof(md, b.m_query_pred, to_app(level_query), level); + apply(m, b.m_pc.get(), pr); + b.m_answer = pr; + } + + func_decl_ref mk_level_predicate(func_decl* p, unsigned level) { + std::stringstream _name; + _name << p->get_name() << "#" << level; + symbol nm(_name.str().c_str()); + return func_decl_ref(m.mk_func_decl(nm, p->get_arity(), p->get_domain(), m.mk_bool_sort()), m); + } + + func_decl_ref mk_level_rule(func_decl* p, unsigned rule_idx, unsigned level) { + std::stringstream _name; + _name << "rule:" << p->get_name() << "#" << level << "_" << rule_idx; + symbol nm(_name.str().c_str()); + return func_decl_ref(m.mk_func_decl(nm, p->get_arity(), p->get_domain(), m.mk_bool_sort()), m); + } + + expr_ref apply_vars(func_decl* p) { + expr_ref_vector vars(m); + for (unsigned i = 0; i < p->get_arity(); ++i) { + vars.push_back(m.mk_var(i, p->get_domain(i))); + } + return expr_ref(m.mk_app(p, vars.size(), vars.c_ptr()), m); + } + + // remove variables from dst that are in src. + void subtract_vars(ptr_vector& dst, ptr_vector const& src) { + for (unsigned i = 0; i < dst.size(); ++i) { + if (i >= src.size()) { + break; + } + if (src[i]) { + dst[i] = 0; + } + } + } + + expr_ref_vector mk_skolem_binding(rule& r, ptr_vector const& vars, expr_ref_vector const& args) { + expr_ref_vector binding(m); + ptr_vector arg_sorts; + for (unsigned i = 0; i < args.size(); ++i) { + arg_sorts.push_back(m.get_sort(args[i])); + } + for (unsigned i = 0; i < vars.size(); ++i) { + if (vars[i]) { + func_decl_ref f = mk_body_func(r, arg_sorts, i, vars[i]); + binding.push_back(m.mk_app(f, args.size(), args.c_ptr())); + } + else { + binding.push_back(0); + } + } + return binding; + } + + expr_ref skolemize_vars(rule& r, expr_ref_vector const& args, ptr_vector const& vars, expr* e) { + expr_ref result(m); + expr_ref_vector binding = mk_skolem_binding(r, vars, args); + var_subst vs(m, false); + vs(e, binding.size(), binding.c_ptr(), result); + return result; + } + + func_decl_ref mk_body_func(rule& r, ptr_vector const& args, unsigned index, sort* s) { + std::stringstream _name; + _name << r.get_decl()->get_name() << "@" << index; + symbol name(_name.str().c_str()); + func_decl* f = m.mk_func_decl(name, args.size(), args.c_ptr(), s); + return func_decl_ref(f, m); + } + + expr_ref bind_vars(expr* e, expr* pat) { + ptr_vector vars, sorts; + svector names; + expr_ref_vector binding(m), patterns(m); + expr_ref tmp(m), head(m); + get_free_vars(e, vars); + for (unsigned i = 0; i < vars.size(); ++i) { + if (vars[i]) { + binding.push_back(m.mk_var(sorts.size(), vars[i])); + sorts.push_back(vars[i]); + names.push_back(symbol(i)); + } + else { + binding.push_back(0); + } + } + sorts.reverse(); + if (sorts.empty()) { + return expr_ref(e, m); + } + var_subst vs(m, false); + vs(e, binding.size(), binding.c_ptr(), tmp); + vs(pat, binding.size(), binding.c_ptr(), head); + patterns.push_back(m.mk_pattern(to_app(head))); + symbol qid, skid; + return expr_ref(m.mk_forall(sorts.size(), sorts.c_ptr(), names.c_ptr(), tmp, 1, qid, skid, 1, patterns.c_ptr()), m); + } + + public: + class level_replacer { + nonlinear& n; + unsigned m_level; + bool is_predicate(func_decl* f) { + return n.b.m_ctx.is_predicate(f); + } + public: + level_replacer(nonlinear& n, unsigned level): n(n), m_level(level) {} + + br_status mk_app_core(func_decl* f, unsigned num_args, expr* const* args, expr_ref& result) { + if (is_predicate(f)) { + if (m_level > 0) { + result = n.m.mk_app(n.mk_level_predicate(f, m_level-1), num_args, args); + } + else { + result = n.m.mk_false(); + } + return BR_DONE; + } + return BR_FAILED; + } + + bool reduce_quantifier(quantifier* old_q, expr* new_body, expr_ref& result) { + if (is_ground(new_body)) { + result = new_body; + } + else { + expr * const * no_pats = &new_body; + result = n.m.update_quantifier(old_q, 0, 0, 1, no_pats, new_body); + } + return true; + } + }; + + struct level_replacer_cfg : public default_rewriter_cfg { + level_replacer m_r; + + level_replacer_cfg(nonlinear& nl, unsigned level): + m_r(nl, level) {} + + bool rewrite_patterns() const { return false; } + br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) { + return m_r.mk_app_core(f, num, args, result); + } + bool reduce_quantifier(quantifier * old_q, + expr * new_body, + expr * const * new_patterns, + expr * const * new_no_patterns, + expr_ref & result, + proof_ref & result_pr) { + return m_r.reduce_quantifier(old_q, new_body, result); + } + + }; + + class level_replacer_star : public rewriter_tpl { + level_replacer_cfg m_cfg; + public: + level_replacer_star(nonlinear& nl, unsigned level): + rewriter_tpl(nl.m, false, m_cfg), + m_cfg(nl, level) + {} + }; + + private: + + void replace_by_level_predicates(unsigned level, expr_ref& fml) { + level_replacer_star rep(*this, level); + expr_ref tmp(m); + rep(fml, tmp); + fml = tmp; + } + + + }; + + // -------------------------------------------------------------------------- + // Basic non-linear BMC based on compiling into data-types (it is inefficient) + + class bmc::nonlinear_dt { + bmc& b; + ast_manager& m; + ast_ref_vector m_pinned; + sort_ref m_path_sort; + obj_map m_pred2sort; + obj_map m_sort2pred; + + + public: + nonlinear_dt(bmc& b): b(b), m(b.m), m_pinned(m), m_path_sort(m) {} + + lbool check() { + setup(); + declare_datatypes(); + compile(); + return check_query(); + } + + private: + void setup() { + m_pred2sort.reset(); + m_pinned.reset(); + m_sort2pred.reset(); + b.m_fparams.m_relevancy_lvl = 0; + b.m_fparams.m_model = true; + b.m_fparams.m_model_compact = true; + b.m_fparams.m_mbqi = false; + b.m_fparams.m_relevancy_lvl = 2; + } + + func_decl_ref mk_predicate(func_decl* pred) { + std::stringstream _name; + _name << pred->get_name() << "#"; + symbol nm(_name.str().c_str()); + sort* pred_trace_sort = m_pred2sort.find(pred); + return func_decl_ref(m.mk_func_decl(nm, pred_trace_sort, m_path_sort, m.mk_bool_sort()), m); + } + + func_decl_ref mk_rule(func_decl* p, unsigned rule_idx) { + std::stringstream _name; + _name << "rule:" << p->get_name() << "#" << rule_idx; + symbol nm(_name.str().c_str()); + sort* pred_trace_sort = m_pred2sort.find(p); + return func_decl_ref(m.mk_func_decl(nm, pred_trace_sort, m_path_sort, m.mk_bool_sort()), m); + } + + expr_ref mk_var(func_decl* pred, sort*s, unsigned idx, expr* path_arg, expr* trace_arg) { + std::stringstream _name; + _name << pred->get_name() << "#V_" << idx; + symbol nm(_name.str().c_str()); + func_decl_ref fn(m); + fn = m.mk_func_decl(nm, m_pred2sort.find(pred), m_path_sort, s); + return expr_ref(m.mk_app(fn, trace_arg, path_arg), m); + } + + expr_ref mk_arg(func_decl* pred, unsigned idx, expr* path_arg, expr* trace_arg) { + SASSERT(idx < pred->get_arity()); + std::stringstream _name; + _name << pred->get_name() << "#X_" << idx; + symbol nm(_name.str().c_str()); + func_decl_ref fn(m); + fn = m.mk_func_decl(nm, m_pred2sort.find(pred), m_path_sort, pred->get_domain(idx)); + return expr_ref(m.mk_app(fn, trace_arg, path_arg), m); + } + + void mk_subst(datalog::rule& r, expr* path, app* trace, expr_ref_vector& sub) { + datatype_util dtu(m); + ptr_vector sorts; + func_decl* p = r.get_decl(); + ptr_vector const& succs = *dtu.get_datatype_constructors(m.get_sort(path)); + // populate substitution of bound variables. + r.get_vars(sorts); + sub.reset(); + sub.resize(sorts.size()); + for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) { + expr* arg = r.get_head()->get_arg(k); + if (is_var(arg)) { + unsigned idx = to_var(arg)->get_idx(); + if (!sub[idx].get()) { + sub[idx] = mk_arg(p, k, path, trace); + } + } + } + for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { + func_decl* q = r.get_decl(j); + expr_ref path_arg(m); + if (j == 0) { + path_arg = path; + } + else { + path_arg = m.mk_app(succs[j], path); + } + for (unsigned k = 0; k < q->get_arity(); ++k) { + expr* arg = r.get_tail(j)->get_arg(k); + if (is_var(arg)) { + unsigned idx = to_var(arg)->get_idx(); + if (!sub[idx].get()) { + sub[idx] = mk_arg(q, k, path_arg, trace->get_arg(j)); + } + } + } + } + for (unsigned j = 0, idx = 0; j < sorts.size(); ++j) { + if (sorts[j] && !sub[j].get()) { + sub[j] = mk_var(r.get_decl(), sorts[j], idx++, path, trace); + } + } + } + + /** + \brief compile Horn rule into co-Horn implication. + forall args . R(path_var, rule_i(trace_vars)) => Body[X(path_var, rule_i(trace_vars)), Y(S_j(path_var), trace_vars_j)] + */ + void compile() { + datatype_util dtu(m); + + rule_set::decl2rules::iterator it = b.m_rules.begin_grouped_rules(); + rule_set::decl2rules::iterator end = b.m_rules.end_grouped_rules(); + for (; it != end; ++it) { + func_decl* p = it->m_key; + rule_vector const& rls = *it->m_value; + + // Assert: p_level => r1_level \/ r2_level \/ r3_level \/ ... + // where: r_i_level = body of rule i for level + equalities for head of rule i + + expr_ref rule_body(m), tmp(m), pred(m), trace_arg(m), fml(m); + var_ref path_var(m), trace_var(m); + expr_ref_vector rules(m), sub(m), conjs(m), vars(m), patterns(m); + sort* pred_sort = m_pred2sort.find(p); + path_var = m.mk_var(0, m_path_sort); + trace_var = m.mk_var(1, pred_sort); + // sort* sorts[2] = { pred_sort, m_path_sort }; + ptr_vector const& cnstrs = *dtu.get_datatype_constructors(pred_sort); + ptr_vector const& succs = *dtu.get_datatype_constructors(m_path_sort); + SASSERT(cnstrs.size() == rls.size()); + pred = m.mk_app(mk_predicate(p), trace_var.get(), path_var.get()); + for (unsigned i = 0; i < rls.size(); ++i) { + sub.reset(); + conjs.reset(); + vars.reset(); + rule& r = *rls[i]; + func_decl_ref rule_pred_i = mk_rule(p, i); + + // Create cnstr_rule_i(Vars) + func_decl* cnstr = cnstrs[i]; + rules.push_back(m.mk_app(rule_pred_i, trace_var.get(), path_var.get())); + unsigned arity = cnstr->get_arity(); + for (unsigned j = 0; j < arity; ++j) { + vars.push_back(m.mk_var(arity-j,cnstr->get_domain(j))); + } + trace_arg = m.mk_app(cnstr, vars.size(), vars.c_ptr()); + + mk_subst(r, path_var, to_app(trace_arg), sub); + + // apply substitution to body. + var_subst vs(m, false); + for (unsigned k = 0; k < p->get_arity(); ++k) { + vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr(), tmp); + expr_ref arg = mk_arg(p, k, path_var, trace_arg); + conjs.push_back(m.mk_eq(tmp, arg)); + } + for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { + expr_ref path_arg(m); + if (j == 0) { + path_arg = path_var.get(); + } + else { + path_arg = m.mk_app(succs[j], path_var.get()); + } + func_decl* q = r.get_decl(j); + for (unsigned k = 0; k < q->get_arity(); ++k) { + vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr(), tmp); + expr_ref arg = mk_arg(q, k, path_arg, vars[j].get()); + conjs.push_back(m.mk_eq(tmp, arg)); + } + func_decl_ref q_pred = mk_predicate(q); + conjs.push_back(m.mk_app(q_pred, vars[j].get(), path_arg)); + } + for (unsigned j = r.get_uninterpreted_tail_size(); j < r.get_tail_size(); ++j) { + vs(r.get_tail(j), sub.size(), sub.c_ptr(), tmp); + conjs.push_back(tmp); + } + bool_rewriter(m).mk_and(conjs.size(), conjs.c_ptr(), rule_body); + ptr_vector q_sorts; + vector names; + for (unsigned i = 0; i < vars.size(); ++i) { + q_sorts.push_back(m.get_sort(vars[i].get())); + names.push_back(symbol(i+1)); + } + vars.push_back(path_var); + q_sorts.push_back(m.get_sort(path_var)); + names.push_back(symbol("path")); + SASSERT(names.size() == q_sorts.size()); + SASSERT(vars.size() == names.size()); + symbol qid = r.name(), skid; + tmp = m.mk_app(mk_predicate(p), trace_arg.get(), path_var.get()); + patterns.reset(); + patterns.push_back(m.mk_pattern(to_app(tmp))); + fml = m.mk_implies(tmp, rule_body); + fml = m.mk_forall(vars.size(), q_sorts.c_ptr(), names.c_ptr(), fml, 1, qid, skid, 1, patterns.c_ptr()); + b.assert_expr(fml); + } + } + } + + void declare_datatypes() { + rule_set::decl2rules::iterator it = b.m_rules.begin_grouped_rules(); + rule_set::decl2rules::iterator end = b.m_rules.end_grouped_rules(); + datatype_util dtu(m); + ptr_vector dts; + + obj_map pred_idx; + for (unsigned i = 0; it != end; ++it, ++i) { + pred_idx.insert(it->m_key, i); + } + + it = b.m_rules.begin_grouped_rules(); + for (; it != end; ++it) { + rule_vector const& rls = *it->m_value; + func_decl* pred = it->m_key; + ptr_vector cnstrs; + for (unsigned i = 0; i < rls.size(); ++i) { + rule* r = rls[i]; + ptr_vector accs; + for (unsigned j = 0; j < r->get_uninterpreted_tail_size(); ++j) { + func_decl* q = r->get_decl(j); + unsigned idx = pred_idx.find(q); + std::stringstream _name; + _name << pred->get_name() << "_" << q->get_name() << j; + symbol name(_name.str().c_str()); + type_ref tr(idx); + accs.push_back(mk_accessor_decl(name, tr)); + } + std::stringstream _name; + _name << pred->get_name() << "_" << i; + symbol name(_name.str().c_str()); + _name << "?"; + symbol is_name(_name.str().c_str()); + cnstrs.push_back(mk_constructor_decl(name, is_name, accs.size(), accs.c_ptr())); + } + dts.push_back(mk_datatype_decl(pred->get_name(), cnstrs.size(), cnstrs.c_ptr())); + } + + + sort_ref_vector new_sorts(m); + family_id dfid = m.get_family_id("datatype"); + datatype_decl_plugin* dtp = static_cast(m.get_plugin(dfid)); + VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts)); + + it = b.m_rules.begin_grouped_rules(); + for (unsigned i = 0; it != end; ++it, ++i) { + m_pred2sort.insert(it->m_key, new_sorts[i].get()); + m_sort2pred.insert(new_sorts[i].get(), it->m_key); + m_pinned.push_back(new_sorts[i].get()); + } + if (new_sorts.size() > 0) { + TRACE("bmc", dtu.display_datatype(new_sorts[0].get(), tout);); + } + del_datatype_decls(dts.size(), dts.c_ptr()); + + // declare path data-type. + { + new_sorts.reset(); + dts.reset(); + ptr_vector cnstrs; + unsigned max_arity = 0; + rule_set::iterator it = b.m_rules.begin(); + rule_set::iterator end = b.m_rules.end(); + for (; it != end; ++it) { + rule* r = *it; + unsigned sz = r->get_uninterpreted_tail_size(); + max_arity = std::max(sz, max_arity); + } + cnstrs.push_back(mk_constructor_decl(symbol("Z#"), symbol("Z#?"), 0, 0)); + + for (unsigned i = 0; i + 1 < max_arity; ++i) { + std::stringstream _name; + _name << "succ#" << i; + symbol name(_name.str().c_str()); + _name << "?"; + symbol is_name(_name.str().c_str()); + std::stringstream _name2; + _name2 << "get_succ#" << i; + symbol acc_name(_name2.str().c_str()); + ptr_vector accs; + type_ref tr(0); + accs.push_back(mk_accessor_decl(name, tr)); + cnstrs.push_back(mk_constructor_decl(name, is_name, accs.size(), accs.c_ptr())); + } + dts.push_back(mk_datatype_decl(symbol("Path"), cnstrs.size(), cnstrs.c_ptr())); + VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts)); + m_path_sort = new_sorts[0].get(); + } + } + + proof_ref get_proof(model_ref& md, app* trace, app* path) { + datatype_util dtu(m); + sort* trace_sort = m.get_sort(trace); + func_decl* p = m_sort2pred.find(trace_sort); + datalog::rule_vector const& rules = b.m_rules.get_predicate_rules(p); + ptr_vector const& cnstrs = *dtu.get_datatype_constructors(trace_sort); + ptr_vector const& succs = *dtu.get_datatype_constructors(m_path_sort); + for (unsigned i = 0; i < cnstrs.size(); ++i) { + if (trace->get_decl() == cnstrs[i]) { + svector > positions; + scoped_coarse_proof _sc(m); + proof_ref_vector prs(m); + expr_ref_vector sub(m); + vector substs; + proof_ref pr(m); + expr_ref fml(m), head(m), tmp(m); + app_ref path1(m); + + var_subst vs(m, false); + mk_subst(*rules[i], path, trace, sub); + rules[i]->to_formula(fml); + prs.push_back(m.mk_asserted(fml)); + unsigned sz = trace->get_num_args(); + if (sub.empty() && sz == 0) { + pr = prs[0].get(); + return pr; + } + for (unsigned j = 0; j < sub.size(); ++j) { + md->eval(sub[j].get(), tmp); + sub[j] = tmp; + } + rule_ref rl(b.m_ctx.get_rule_manager()); + rl = rules[i]; + b.m_ctx.get_rule_manager().substitute(rl, sub.size(), sub.c_ptr()); + + substs.push_back(sub); + + for (unsigned j = 0; j < sz; ++j) { + if (j == 0) { + path1 = path; + } + else { + path1 = m.mk_app(succs[j], path); + } + + prs.push_back(get_proof(md, to_app(trace->get_arg(j)), path1)); + positions.push_back(std::make_pair(j+1,0)); + substs.push_back(expr_ref_vector(m)); + } + head = rl->get_head(); + pr = m.mk_hyper_resolve(sz+1, prs.c_ptr(), head, positions, substs); + return pr; + } + } + UNREACHABLE(); + return proof_ref(0, m); + } + + // instantiation of algebraic data-types takes care of the rest. + lbool check_query() { + sort* trace_sort = m_pred2sort.find(b.m_query_pred); + func_decl_ref q = mk_predicate(b.m_query_pred); + expr_ref trace(m), path(m), fml(m); + trace = m.mk_const(symbol("trace"), trace_sort); + path = m.mk_const(symbol("path"), m_path_sort); + fml = m.mk_app(q, trace.get(), path.get()); + b.assert_expr(fml); + while (true) { + lbool is_sat = b.m_solver.check(); + model_ref md; + if (is_sat == l_false) { + return is_sat; + } + b.m_solver.get_model(md); + mk_answer(md, trace, path); + return l_true; + } + } + + bool check_model(model_ref& md, expr* trace) { + expr_ref trace_val(m), eq(m); + md->eval(trace, trace_val); + eq = m.mk_eq(trace, trace_val); + b.m_solver.push(); + b.m_solver.assert_expr(eq); + lbool is_sat = b.m_solver.check(); + if (is_sat != l_false) { + b.m_solver.get_model(md); + } + b.m_solver.pop(1); + if (is_sat == l_false) { + IF_VERBOSE(1, verbose_stream() << "infeasible trace " << mk_pp(trace_val, m) << "\n";); + eq = m.mk_not(eq); + b.assert_expr(eq); + } + return is_sat != l_false; + } + + void mk_answer(model_ref& md, expr_ref& trace, expr_ref& path) { + proof_ref pr(m); + IF_VERBOSE(2, model_smt2_pp(verbose_stream(), m, *md, 0);); + md->eval(trace, trace); + md->eval(path, path); + IF_VERBOSE(2, verbose_stream() << mk_pp(trace, m) << "\n"; + for (unsigned i = 0; i < b.m_solver.size(); ++i) { + verbose_stream() << mk_pp(b.m_solver.get_formulas()[i], m) << "\n"; + }); + b.m_answer = get_proof(md, to_app(trace), to_app(path)); + } + + }; + + // -------------------------------------------------------------------------- + // Basic linear BMC based on incrementally unfolding the transition relation. + + class bmc::linear { + bmc& b; + ast_manager& m; + + public: + linear(bmc& b): b(b), m(b.m) {} + + lbool check() { + setup(); + for (unsigned i = 0; ; ++i) { + IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";); + b.checkpoint(); + compile(i); + lbool res = check(i); + if (res == l_undef) { + return res; + } + if (res == l_true) { + get_model(i); + return res; + } + } + } + + private: + + void get_model(unsigned level) { + rule_manager& rm = b.m_ctx.get_rule_manager(); + expr_ref level_query = mk_level_predicate(b.m_query_pred, level); + model_ref md; + proof_ref pr(m); + rule_unifier unifier(b.m_ctx); + b.m_solver.get_model(md); + func_decl* pred = b.m_query_pred; + SASSERT(m.is_true(md->get_const_interp(to_app(level_query)->get_decl()))); + + TRACE("bmc", model_smt2_pp(tout, m, *md, 0);); + + rule_ref r0(rm), r1(rm), r2(rm); + while (true) { + TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";); + expr_ref_vector sub(m); + rule_vector const& rls = b.m_rules.get_predicate_rules(pred); + rule* r = 0; + unsigned i = 0; + for (; i < rls.size(); ++i) { + expr_ref rule_i = mk_level_rule(pred, i, level); + TRACE("bmc", rls[i]->display(b.m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " ");); + if (m.is_true(md->get_const_interp(to_app(rule_i)->get_decl()))) { + r = rls[i]; + break; + } + } + SASSERT(r); + mk_rule_vars(*r, level, i, sub); + // we have rule, we have variable names of rule. + + // extract values for the variables in the rule. + for (unsigned j = 0; j < sub.size(); ++j) { + expr* vl = md->get_const_interp(to_app(sub[j].get())->get_decl()); + if (vl) { + // vl can be 0 if the interpretation does not assign a value to it. + sub[j] = vl; + } + else { + sub[j] = m.mk_var(j, m.get_sort(sub[j].get())); + } + } + svector > positions; + vector substs; + expr_ref fml(m), concl(m); + + r->to_formula(fml); + r2 = r; + rm.substitute(r2, sub.size(), sub.c_ptr()); + if (r0) { + VERIFY(unifier.unify_rules(*r0.get(), 0, *r2.get())); + expr_ref_vector sub1 = unifier.get_rule_subst(*r0.get(), true); + expr_ref_vector sub2 = unifier.get_rule_subst(*r2.get(), false); + apply_subst(sub, sub2); + unifier.apply(*r0.get(), 0, *r2.get(), r1); + r1->to_formula(concl); + scoped_coarse_proof _sp(m); + + proof* p = m.mk_asserted(fml); + proof* premises[2] = { pr, p }; + + positions.push_back(std::make_pair(0, 1)); + + substs.push_back(sub1); + substs.push_back(sub); + pr = m.mk_hyper_resolve(2, premises, concl, positions, substs); + r0 = r1; + } + else { + r2->to_formula(concl); + scoped_coarse_proof _sp(m); + proof* p = m.mk_asserted(fml); + if (sub.empty()) { + pr = p; + } + else { + substs.push_back(sub); + pr = m.mk_hyper_resolve(1, &p, concl, positions, substs); + } + r0 = r2; + } + + if (level == 0) { + SASSERT(r->get_uninterpreted_tail_size() == 0); + break; + } + --level; + SASSERT(r->get_uninterpreted_tail_size() == 1); + pred = r->get_decl(0); + } + scoped_coarse_proof _sp(m); + apply(m, b.m_pc.get(), pr); + b.m_answer = pr; + } + + + void setup() { + b.m_fparams.m_relevancy_lvl = 0; + b.m_fparams.m_model = true; + b.m_fparams.m_model_compact = true; + b.m_fparams.m_mbqi = false; + // m_fparams.m_auto_config = false; + } + + + lbool check(unsigned level) { + expr_ref level_query = mk_level_predicate(b.m_query_pred, level); + expr* q = level_query.get(); + return b.m_solver.check(1, &q); + } + + expr_ref mk_level_predicate(func_decl* p, unsigned level) { + return mk_level_predicate(p->get_name(), level); + } + + expr_ref mk_level_predicate(symbol const& name, unsigned level) { + std::stringstream _name; + _name << name << "#" << level; + symbol nm(_name.str().c_str()); + return expr_ref(m.mk_const(nm, m.mk_bool_sort()), m); + } + + expr_ref mk_level_arg(func_decl* pred, unsigned idx, unsigned level) { + SASSERT(idx < pred->get_arity()); + std::stringstream _name; + _name << pred->get_name() << "#" << level << "_" << idx; + symbol nm(_name.str().c_str()); + return expr_ref(m.mk_const(nm, pred->get_domain(idx)), m); + } + + expr_ref mk_level_var(func_decl* pred, sort* s, unsigned rule_id, unsigned idx, unsigned level) { + std::stringstream _name; + _name << pred->get_name() << "#" << level << "_" << rule_id << "_" << idx; + symbol nm(_name.str().c_str()); + return expr_ref(m.mk_const(nm, s), m); + } + + expr_ref mk_level_rule(func_decl* p, unsigned rule_idx, unsigned level) { + std::stringstream _name; + _name << "rule:" << p->get_name() << "#" << level << "_" << rule_idx; + symbol nm(_name.str().c_str()); + return expr_ref(m.mk_const(nm, m.mk_bool_sort()), m); + } + + void mk_rule_vars(rule& r, unsigned level, unsigned rule_id, expr_ref_vector& sub) { + ptr_vector sorts; + r.get_vars(sorts); + // populate substitution of bound variables. + sub.reset(); + sub.resize(sorts.size()); + + for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) { + expr* arg = r.get_head()->get_arg(k); + if (is_var(arg)) { + unsigned idx = to_var(arg)->get_idx(); + if (!sub[idx].get()) { + sub[idx] = mk_level_arg(r.get_decl(), k, level); + } + } + } + for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { + SASSERT(level > 0); + func_decl* q = r.get_decl(j); + for (unsigned k = 0; k < q->get_arity(); ++k) { + expr* arg = r.get_tail(j)->get_arg(k); + if (is_var(arg)) { + unsigned idx = to_var(arg)->get_idx(); + if (!sub[idx].get()) { + sub[idx] = mk_level_arg(q, k, level-1); + } + } + } + } + for (unsigned j = 0, idx = 0; j < sorts.size(); ++j) { + if (sorts[j] && !sub[j].get()) { + sub[j] = mk_level_var(r.get_decl(), sorts[j], rule_id, idx++, level); + } + } + } + + void compile(unsigned level) { + rule_set::decl2rules::iterator it = b.m_rules.begin_grouped_rules(); + rule_set::decl2rules::iterator end = b.m_rules.end_grouped_rules(); + for (; it != end; ++it) { + func_decl* p = it->m_key; + rule_vector const& rls = *it->m_value; + + // Assert: p_level => r1_level \/ r2_level \/ r3_level \/ ... + // Assert: r_i_level => body of rule i for level + equalities for head of rule i + + expr_ref level_pred = mk_level_predicate(p, level); + expr_ref_vector rules(m), sub(m), conjs(m); + expr_ref rule_body(m), tmp(m); + for (unsigned i = 0; i < rls.size(); ++i) { + sub.reset(); + conjs.reset(); + rule& r = *rls[i]; + expr_ref rule_i = mk_level_rule(p, i, level); + rules.push_back(rule_i); + if (level == 0 && r.get_uninterpreted_tail_size() > 0) { + tmp = m.mk_not(rule_i); + b.assert_expr(tmp); + continue; + } + + mk_rule_vars(r, level, i, sub); + + // apply substitution to body. + var_subst vs(m, false); + for (unsigned k = 0; k < p->get_arity(); ++k) { + vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr(), tmp); + conjs.push_back(m.mk_eq(tmp, mk_level_arg(p, k, level))); + } + for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { + SASSERT(level > 0); + func_decl* q = r.get_decl(j); + for (unsigned k = 0; k < q->get_arity(); ++k) { + vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr(), tmp); + conjs.push_back(m.mk_eq(tmp, mk_level_arg(q, k, level-1))); + } + conjs.push_back(mk_level_predicate(q, level-1)); + } + for (unsigned j = r.get_uninterpreted_tail_size(); j < r.get_tail_size(); ++j) { + vs(r.get_tail(j), sub.size(), sub.c_ptr(), tmp); + conjs.push_back(tmp); + } + bool_rewriter(m).mk_and(conjs.size(), conjs.c_ptr(), rule_body); + rule_body = m.mk_implies(rule_i, rule_body); + b.assert_expr(rule_body); + } + bool_rewriter(m).mk_or(rules.size(), rules.c_ptr(), tmp); + tmp = m.mk_implies(level_pred, tmp); + b.assert_expr(tmp); + } + } + }; + bmc::bmc(context& ctx): m_ctx(ctx), m(ctx.get_manager()), m_solver(m, m_fparams), - m_pinned(m), m_rules(ctx), m_query_pred(m), m_answer(m), - m_cancel(false), - m_path_sort(m), - m_bv(m) { - } + m_cancel(false) { + } bmc::~bmc() {} lbool bmc::query(expr* query) { m_solver.reset(); - m_pinned.reset(); - m_pred2sort.reset(); - m_sort2pred.reset(); - m_pred2newpred.reset(); - m_pred2args.reset(); m_answer = 0; m_ctx.ensure_opened(); @@ -93,984 +1445,39 @@ namespace datalog { if (is_linear()) { if (m_ctx.get_engine() == QBMC_ENGINE) { - return check_qlinear(); + qlinear ql(*this); + return ql.check(); + } + else { + linear lin(*this); + return lin.check(); } - return check_linear(); } else { IF_VERBOSE(0, verbose_stream() << "WARNING: non-linear BMC is highly inefficient\n";); - return check_nonlinear(); + nonlinear nl(*this); + return nl.check(); } } + void bmc::assert_expr(expr* e) { + TRACE("bmc", tout << mk_pp(e, m) << "\n";); + m_solver.assert_expr(e); + } + bool bmc::is_linear() const { unsigned sz = m_rules.get_num_rules(); for (unsigned i = 0; i < sz; ++i) { if (m_rules.get_rule(i)->get_uninterpreted_tail_size() > 1) { return false; } + if (m_rules.get_rule(i)->has_quantifiers()) { + return false; + } } return true; } - // -------------------------------------------------------------------------- - // Basic linear BMC based on incrementally unfolding the transition relation. - - void bmc::get_model_linear(unsigned level) { - rule_manager& rm = m_ctx.get_rule_manager(); - expr_ref level_query = mk_level_predicate(m_query_pred, level); - model_ref md; - proof_ref pr(m); - rule_unifier unifier(m_ctx); - m_solver.get_model(md); - func_decl* pred = m_query_pred; - SASSERT(m.is_true(md->get_const_interp(to_app(level_query)->get_decl()))); - dl_decl_util util(m); - - TRACE("bmc", model_smt2_pp(tout, m, *md, 0);); - - rule_ref r0(rm), r1(rm), r2(rm); - while (true) { - TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";); - expr_ref_vector sub(m); - rule_vector const& rls = m_rules.get_predicate_rules(pred); - rule* r = 0; - unsigned i = 0; - for (; i < rls.size(); ++i) { - expr_ref rule_i = mk_level_rule(pred, i, level); - TRACE("bmc", rls[i]->display(m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " ");); - if (m.is_true(md->get_const_interp(to_app(rule_i)->get_decl()))) { - r = rls[i]; - break; - } - } - SASSERT(r); - mk_rule_vars(*r, level, i, sub); - // we have rule, we have variable names of rule. - - // extract values for the variables in the rule. - for (unsigned j = 0; j < sub.size(); ++j) { - expr* vl = md->get_const_interp(to_app(sub[j].get())->get_decl()); - if (vl) { - // vl can be 0 if the interpretation does not assign a value to it. - sub[j] = vl; - } - else { - sub[j] = m.mk_var(j, m.get_sort(sub[j].get())); - } - } - svector > positions; - vector substs; - expr_ref fml(m), concl(m); - - r->to_formula(fml); - r2 = r; - rm.substitute(r2, sub.size(), sub.c_ptr()); - if (r0) { - VERIFY(unifier.unify_rules(*r0.get(), 0, *r2.get())); - expr_ref_vector sub1 = unifier.get_rule_subst(*r0.get(), true); - expr_ref_vector sub2 = unifier.get_rule_subst(*r2.get(), false); - apply_subst(sub, sub2); - unifier.apply(*r0.get(), 0, *r2.get(), r1); - r1->to_formula(concl); - scoped_coarse_proof _sp(m); - - proof* p = m.mk_asserted(fml); - proof* premises[2] = { pr, p }; - - positions.push_back(std::make_pair(0, 1)); - - substs.push_back(sub1); - substs.push_back(sub); - pr = m.mk_hyper_resolve(2, premises, concl, positions, substs); - r0 = r1; - } - else { - r2->to_formula(concl); - scoped_coarse_proof _sp(m); - proof* p = m.mk_asserted(fml); - if (sub.empty()) { - pr = p; - } - else { - substs.push_back(sub); - pr = m.mk_hyper_resolve(1, &p, concl, positions, substs); - } - r0 = r2; - } - - if (level == 0) { - SASSERT(r->get_uninterpreted_tail_size() == 0); - break; - } - --level; - SASSERT(r->get_uninterpreted_tail_size() == 1); - pred = r->get_decl(0); - } - scoped_coarse_proof _sp(m); - apply(m, m_pc.get(), pr); - m_answer = pr; - } - - - void bmc::setup_linear() { - m_fparams.m_relevancy_lvl = 0; - m_fparams.m_model = true; - m_fparams.m_model_compact = true; - m_fparams.m_mbqi = false; - // m_fparams.m_auto_config = false; - } - - lbool bmc::check_linear() { - setup_linear(); - for (unsigned i = 0; ; ++i) { - IF_VERBOSE(1, verbose_stream() << "level: " << i << "\n";); - checkpoint(); - compile_linear(i); - lbool res = check_linear(i); - if (res == l_undef) { - return res; - } - if (res == l_true) { - get_model_linear(i); - return res; - } - } - } - - lbool bmc::check_linear(unsigned level) { - expr_ref level_query = mk_level_predicate(m_query_pred, level); - expr* q = level_query.get(); - return m_solver.check(1, &q); - } - - void bmc::assert_expr(expr* e) { - TRACE("bmc", tout << mk_pp(e, m) << "\n";); - m_solver.assert_expr(e); - } - - expr_ref bmc::mk_level_predicate(func_decl* p, unsigned level) { - return mk_level_predicate(p->get_name(), level); - } - - expr_ref bmc::mk_level_predicate(symbol const& name, unsigned level) { - std::stringstream _name; - _name << name << "#" << level; - symbol nm(_name.str().c_str()); - return expr_ref(m.mk_const(nm, m.mk_bool_sort()), m); - } - - expr_ref bmc::mk_level_arg(func_decl* pred, unsigned idx, unsigned level) { - SASSERT(idx < pred->get_arity()); - std::stringstream _name; - _name << pred->get_name() << "#" << level << "_" << idx; - symbol nm(_name.str().c_str()); - return expr_ref(m.mk_const(nm, pred->get_domain(idx)), m); - } - - expr_ref bmc::mk_level_var(func_decl* pred, sort* s, unsigned rule_id, unsigned idx, unsigned level) { - std::stringstream _name; - _name << pred->get_name() << "#" << level << "_" << rule_id << "_" << idx; - symbol nm(_name.str().c_str()); - return expr_ref(m.mk_const(nm, s), m); - } - - expr_ref bmc::mk_level_rule(func_decl* p, unsigned rule_idx, unsigned level) { - std::stringstream _name; - _name << "rule:" << p->get_name() << "#" << level << "_" << rule_idx; - symbol nm(_name.str().c_str()); - return expr_ref(m.mk_const(nm, m.mk_bool_sort()), m); - } - - void bmc::mk_rule_vars(rule& r, unsigned level, unsigned rule_id, expr_ref_vector& sub) { - sort_ref_vector sorts(m); - r.get_vars(sorts); - // populate substitution of bound variables. - sub.reset(); - sub.resize(sorts.size()); - - for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) { - expr* arg = r.get_head()->get_arg(k); - if (is_var(arg)) { - unsigned idx = to_var(arg)->get_idx(); - if (!sub[idx].get()) { - sub[idx] = mk_level_arg(r.get_decl(), k, level); - } - } - } - for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { - SASSERT(level > 0); - func_decl* q = r.get_decl(j); - for (unsigned k = 0; k < q->get_arity(); ++k) { - expr* arg = r.get_tail(j)->get_arg(k); - if (is_var(arg)) { - unsigned idx = to_var(arg)->get_idx(); - if (!sub[idx].get()) { - sub[idx] = mk_level_arg(q, k, level-1); - } - } - } - } - for (unsigned j = 0, idx = 0; j < sorts.size(); ++j) { - if (sorts[j].get() && !sub[j].get()) { - sub[j] = mk_level_var(r.get_decl(), sorts[j].get(), rule_id, idx++, level); - } - } - } - - void bmc::compile_linear(unsigned level) { - rule_set::decl2rules::iterator it = m_rules.begin_grouped_rules(); - rule_set::decl2rules::iterator end = m_rules.end_grouped_rules(); - for (; it != end; ++it) { - func_decl* p = it->m_key; - rule_vector const& rls = *it->m_value; - - // Assert: p_level => r1_level \/ r2_level \/ r3_level \/ ... - // Assert: r_i_level => body of rule i for level + equalities for head of rule i - - expr_ref level_pred = mk_level_predicate(p, level); - expr_ref_vector rules(m), sub(m), conjs(m); - expr_ref rule_body(m), tmp(m); - for (unsigned i = 0; i < rls.size(); ++i) { - sub.reset(); - conjs.reset(); - rule& r = *rls[i]; - expr_ref rule_i = mk_level_rule(p, i, level); - rules.push_back(rule_i); - if (level == 0 && r.get_uninterpreted_tail_size() > 0) { - tmp = m.mk_not(rule_i); - assert_expr(tmp); - continue; - } - - mk_rule_vars(r, level, i, sub); - - // apply substitution to body. - var_subst vs(m, false); - for (unsigned k = 0; k < p->get_arity(); ++k) { - vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr(), tmp); - conjs.push_back(m.mk_eq(tmp, mk_level_arg(p, k, level))); - } - for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { - SASSERT(level > 0); - func_decl* q = r.get_decl(j); - for (unsigned k = 0; k < q->get_arity(); ++k) { - vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr(), tmp); - conjs.push_back(m.mk_eq(tmp, mk_level_arg(q, k, level-1))); - } - conjs.push_back(mk_level_predicate(q, level-1)); - } - for (unsigned j = r.get_uninterpreted_tail_size(); j < r.get_tail_size(); ++j) { - vs(r.get_tail(j), sub.size(), sub.c_ptr(), tmp); - conjs.push_back(tmp); - } - bool_rewriter(m).mk_and(conjs.size(), conjs.c_ptr(), rule_body); - rule_body = m.mk_implies(rule_i, rule_body); - assert_expr(rule_body); - } - bool_rewriter(m).mk_or(rules.size(), rules.c_ptr(), tmp); - tmp = m.mk_implies(level_pred, tmp); - assert_expr(tmp); - } - } - - // --------------------------------------------------------------------------- - // Basic linear BMC based on indexed variables using quantified bit-vector domains. - - lbool bmc::check_qlinear() { - setup_qlinear(); - m_bit_width = 4; - lbool res = l_false; - while (res == l_false) { - m_solver.push(); - IF_VERBOSE(1, verbose_stream() << "bit_width: " << m_bit_width << "\n";); - compile_qlinear(); - checkpoint(); - func_decl_ref q = mk_q_func_decl(m_query_pred); - expr* T = m.mk_const(symbol("T"), mk_index_sort()); - expr_ref fml(m.mk_app(q, T), m); - assert_expr(fml); - res = m_solver.check(); - - if (res == l_true) { - res = get_model_qlinear(); - } - m_solver.pop(1); - ++m_bit_width; - } - return res; - } - - sort_ref bmc::mk_index_sort() { - return sort_ref(m_bv.mk_sort(m_bit_width), m); - } - - var_ref bmc::mk_index_var() { - return var_ref(m.mk_var(0, mk_index_sort()), m); - } - - void bmc::compile_qlinear() { - sort_ref index_sort = mk_index_sort(); - var_ref var = mk_index_var(); - sort* index_sorts[1] = { index_sort }; - symbol tick("T"); - rule_set::decl2rules::iterator it = m_rules.begin_grouped_rules(); - rule_set::decl2rules::iterator end = m_rules.end_grouped_rules(); - for (; it != end; ++it) { - func_decl* p = it->m_key; - rule_vector const& rls = *it->m_value; - // Assert: forall level . p(T) => body of rule i + equalities for head of rule i - func_decl_ref pr = mk_q_func_decl(p); - expr_ref pred = expr_ref(m.mk_app(pr, var.get()), m); - expr_ref_vector rules(m), sub(m), conjs(m); - expr_ref trm(m), rule_body(m), rule_i(m); - for (unsigned i = 0; i < rls.size(); ++i) { - sub.reset(); - conjs.reset(); - rule& r = *rls[i]; - rule_i = m.mk_app(mk_q_rule(p, i), var.get()); - rules.push_back(rule_i); - - mk_qrule_vars(r, i, sub); - - // apply substitution to body. - var_subst vs(m, false); - for (unsigned k = 0; k < p->get_arity(); ++k) { - vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr(), trm); - conjs.push_back(m.mk_eq(trm, mk_q_arg(p, k, true))); - } - for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { - func_decl* q = r.get_decl(j); - for (unsigned k = 0; k < q->get_arity(); ++k) { - vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr(), trm); - conjs.push_back(m.mk_eq(trm, mk_q_arg(q, k, false))); - } - func_decl_ref qr = mk_q_func_decl(q); - conjs.push_back(m.mk_app(qr, m_bv.mk_bv_sub(var, mk_q_one()))); - } - for (unsigned j = r.get_uninterpreted_tail_size(); j < r.get_tail_size(); ++j) { - vs(r.get_tail(j), sub.size(), sub.c_ptr(), trm); - conjs.push_back(trm); - } - if (r.get_uninterpreted_tail_size() > 0) { - conjs.push_back(m_bv.mk_ule(mk_q_one(), var)); - } - bool_rewriter(m).mk_and(conjs.size(), conjs.c_ptr(), rule_body); - trm = m.mk_implies(rule_i, rule_body); - trm = m.mk_forall(1, index_sorts, &tick, trm, 1); - assert_expr(trm); - } - bool_rewriter(m).mk_or(rules.size(), rules.c_ptr(), trm); - trm = m.mk_implies(pred, trm); - trm = m.mk_forall(1, index_sorts, &tick, trm, 1); - SASSERT(is_well_sorted(m, trm)); - assert_expr(trm); - } - } - - void bmc::setup_qlinear() { - m_fparams.m_relevancy_lvl = 2; - m_fparams.m_model = true; - m_fparams.m_model_compact = true; - m_fparams.m_mbqi = true; - } - - void bmc::mk_qrule_vars(datalog::rule const& r, unsigned rule_id, expr_ref_vector& sub) { - sort_ref_vector sorts(m); - r.get_vars(sorts); - // populate substitution of bound variables. - sub.reset(); - sub.resize(sorts.size()); - - for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) { - expr* arg = r.get_head()->get_arg(k); - if (is_var(arg)) { - unsigned idx = to_var(arg)->get_idx(); - if (!sub[idx].get()) { - sub[idx] = mk_q_arg(r.get_decl(), k, true); - } - } - } - for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { - func_decl* q = r.get_decl(j); - for (unsigned k = 0; k < q->get_arity(); ++k) { - expr* arg = r.get_tail(j)->get_arg(k); - if (is_var(arg)) { - unsigned idx = to_var(arg)->get_idx(); - if (!sub[idx].get()) { - sub[idx] = mk_q_arg(q, k, false); - } - } - } - } - for (unsigned j = 0, idx = 0; j < sorts.size(); ++j) { - if (sorts[j].get() && !sub[j].get()) { - sub[j] = mk_q_var(r.get_decl(), sorts[j].get(), rule_id, idx++); - } - } - } - - expr_ref bmc::mk_q_var(func_decl* pred, sort* s, unsigned rule_id, unsigned idx) { - std::stringstream _name; - _name << pred->get_name() << "#" << rule_id << "_" << idx; - symbol nm(_name.str().c_str()); - var_ref var = mk_index_var(); - return expr_ref(m.mk_app(m.mk_func_decl(nm, mk_index_sort(), s), var), m); - } - - expr_ref bmc::mk_q_arg(func_decl* pred, unsigned idx, bool is_current) { - SASSERT(idx < pred->get_arity()); - std::stringstream _name; - _name << pred->get_name() << "#" << idx; - symbol nm(_name.str().c_str()); - expr_ref var(mk_index_var(), m); - if (!is_current) { - var = m_bv.mk_bv_sub(var, mk_q_one()); - } - return expr_ref(m.mk_app(m.mk_func_decl(nm, mk_index_sort(), pred->get_domain(idx)), var), m); - } - - expr_ref bmc::mk_q_one() { - return mk_q_num(1); - } - - expr_ref bmc::mk_q_num(unsigned i) { - return expr_ref(m_bv.mk_numeral(i, m_bit_width), m); - } - - func_decl_ref bmc::mk_q_func_decl(func_decl* f) { - std::stringstream _name; - _name << f->get_name() << "#"; - symbol nm(_name.str().c_str()); - return func_decl_ref(m.mk_func_decl(nm, mk_index_sort(), f->get_range()), m); - } - - func_decl_ref bmc::mk_q_rule(func_decl* f, unsigned rule_id) { - std::stringstream _name; - _name << f->get_name() << "#" << rule_id; - symbol nm(_name.str().c_str()); - return func_decl_ref(m.mk_func_decl(nm, mk_index_sort(), m.mk_bool_sort()), m); - } - - - expr_ref bmc::eval_q(model_ref& model, func_decl* f, unsigned i) { - func_decl_ref fn = mk_q_func_decl(f); - expr_ref t(m), result(m); - t = m.mk_app(mk_q_func_decl(f).get(), mk_q_num(i)); - model->eval(t, result); - return result; - } - - expr_ref bmc::eval_q(model_ref& model, expr* t, unsigned i) { - expr_ref tmp(m), result(m), num(m); - var_subst vs(m, false); - num = mk_q_num(i); - expr* nums[1] = { num }; - vs(t, 1, nums, tmp); - model->eval(tmp, result); - return result; - } - - lbool bmc::get_model_qlinear() { - rule_manager& rm = m_ctx.get_rule_manager(); - func_decl_ref q = mk_q_func_decl(m_query_pred); - expr_ref T(m), rule_i(m), vl(m); - model_ref md; - proof_ref pr(m); - rule_unifier unifier(m_ctx); - rational num; - unsigned level, bv_size; - - m_solver.get_model(md); - func_decl* pred = m_query_pred; - dl_decl_util util(m); - T = m.mk_const(symbol("T"), mk_index_sort()); - md->eval(T, vl); - VERIFY (m_bv.is_numeral(vl, num, bv_size)); - SASSERT(num.is_unsigned()); - level = num.get_unsigned(); - SASSERT(m.is_true(eval_q(md, m_query_pred, level))); - TRACE("bmc", model_smt2_pp(tout, m, *md, 0);); - - rule_ref r0(rm), r1(rm), r2(rm); - while (true) { - TRACE("bmc", tout << "Predicate: " << pred->get_name() << "\n";); - expr_ref_vector sub(m); - rule_vector const& rls = m_rules.get_predicate_rules(pred); - rule* r = 0; - unsigned i = 0; - for (; i < rls.size(); ++i) { - rule_i = m.mk_app(mk_q_rule(pred, i), mk_q_num(level).get()); - TRACE("bmc", rls[i]->display(m_ctx, tout << "Checking rule " << mk_pp(rule_i, m) << " ");); - if (m.is_true(eval_q(md, rule_i, level))) { - r = rls[i]; - break; - } - } - SASSERT(r); - mk_qrule_vars(*r, i, sub); - // we have rule, we have variable names of rule. - - // extract values for the variables in the rule. - for (unsigned j = 0; j < sub.size(); ++j) { - expr_ref vl = eval_q(md, sub[j].get(), i); - if (vl) { - // vl can be 0 if the interpretation does not assign a value to it. - sub[j] = vl; - } - else { - sub[j] = m.mk_var(j, m.get_sort(sub[j].get())); - } - } - svector > positions; - vector substs; - expr_ref fml(m), concl(m); - - r->to_formula(fml); - r2 = r; - rm.substitute(r2, sub.size(), sub.c_ptr()); - if (r0) { - VERIFY(unifier.unify_rules(*r0.get(), 0, *r2.get())); - expr_ref_vector sub1 = unifier.get_rule_subst(*r0.get(), true); - expr_ref_vector sub2 = unifier.get_rule_subst(*r2.get(), false); - apply_subst(sub, sub2); - unifier.apply(*r0.get(), 0, *r2.get(), r1); - r1->to_formula(concl); - scoped_coarse_proof _sp(m); - - proof* p = m.mk_asserted(fml); - proof* premises[2] = { pr, p }; - - positions.push_back(std::make_pair(0, 1)); - - substs.push_back(sub1); - substs.push_back(sub); - pr = m.mk_hyper_resolve(2, premises, concl, positions, substs); - r0 = r1; - } - else { - r2->to_formula(concl); - scoped_coarse_proof _sp(m); - proof* p = m.mk_asserted(fml); - if (sub.empty()) { - pr = p; - } - else { - substs.push_back(sub); - pr = m.mk_hyper_resolve(1, &p, concl, positions, substs); - } - r0 = r2; - } - - if (level == 0) { - SASSERT(r->get_uninterpreted_tail_size() == 0); - break; - } - --level; - SASSERT(r->get_uninterpreted_tail_size() == 1); - pred = r->get_decl(0); - } - scoped_coarse_proof _sp(m); - apply(m, m_pc.get(), pr); - m_answer = pr; - return l_true; - } - - // -------------------------------------------------------------------------- - // Basic non-linear BMC based on compiling into data-types (it is inefficient) - - - lbool bmc::check_nonlinear() { - setup_nonlinear(); - declare_datatypes(); - compile_nonlinear(); - return check_query(); - } - - void bmc::setup_nonlinear() { - setup_linear(); - m_fparams.m_relevancy_lvl = 2; - } - - func_decl_ref bmc::mk_predicate(func_decl* pred) { - std::stringstream _name; - _name << pred->get_name() << "#"; - symbol nm(_name.str().c_str()); - sort* pred_trace_sort = m_pred2sort.find(pred); - return func_decl_ref(m.mk_func_decl(nm, pred_trace_sort, m_path_sort, m.mk_bool_sort()), m); - } - - func_decl_ref bmc::mk_rule(func_decl* p, unsigned rule_idx) { - std::stringstream _name; - _name << "rule:" << p->get_name() << "#" << rule_idx; - symbol nm(_name.str().c_str()); - sort* pred_trace_sort = m_pred2sort.find(p); - return func_decl_ref(m.mk_func_decl(nm, pred_trace_sort, m_path_sort, m.mk_bool_sort()), m); - } - - expr_ref bmc::mk_var_nonlinear(func_decl* pred, sort*s, unsigned idx, expr* path_arg, expr* trace_arg) { - std::stringstream _name; - _name << pred->get_name() << "#V_" << idx; - symbol nm(_name.str().c_str()); - func_decl_ref fn(m); - fn = m.mk_func_decl(nm, m_pred2sort.find(pred), m_path_sort, s); - return expr_ref(m.mk_app(fn, trace_arg, path_arg), m); - } - - expr_ref bmc::mk_arg_nonlinear(func_decl* pred, unsigned idx, expr* path_arg, expr* trace_arg) { - SASSERT(idx < pred->get_arity()); - std::stringstream _name; - _name << pred->get_name() << "#X_" << idx; - symbol nm(_name.str().c_str()); - func_decl_ref fn(m); - fn = m.mk_func_decl(nm, m_pred2sort.find(pred), m_path_sort, pred->get_domain(idx)); - return expr_ref(m.mk_app(fn, trace_arg, path_arg), m); - } - - void bmc::mk_subst(datalog::rule& r, expr* path, app* trace, expr_ref_vector& sub) { - datatype_util dtu(m); - sort_ref_vector sorts(m); - func_decl* p = r.get_decl(); - ptr_vector const& succs = *dtu.get_datatype_constructors(m.get_sort(path)); - // populate substitution of bound variables. - r.get_vars(sorts); - sub.reset(); - sub.resize(sorts.size()); - for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) { - expr* arg = r.get_head()->get_arg(k); - if (is_var(arg)) { - unsigned idx = to_var(arg)->get_idx(); - if (!sub[idx].get()) { - sub[idx] = mk_arg_nonlinear(p, k, path, trace); - } - } - } - for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { - func_decl* q = r.get_decl(j); - expr_ref path_arg(m); - if (j == 0) { - path_arg = path; - } - else { - path_arg = m.mk_app(succs[j], path); - } - for (unsigned k = 0; k < q->get_arity(); ++k) { - expr* arg = r.get_tail(j)->get_arg(k); - if (is_var(arg)) { - unsigned idx = to_var(arg)->get_idx(); - if (!sub[idx].get()) { - sub[idx] = mk_arg_nonlinear(q, k, path_arg, trace->get_arg(j)); - } - } - } - } - for (unsigned j = 0, idx = 0; j < sorts.size(); ++j) { - if (sorts[j].get() && !sub[j].get()) { - sub[j] = mk_var_nonlinear(r.get_decl(), sorts[j].get(), idx++, path, trace); - } - } - } - - /** - \brief compile Horn rule into co-Horn implication. - forall args . R(path_var, rule_i(trace_vars)) => Body[X(path_var, rule_i(trace_vars)), Y(S_j(path_var), trace_vars_j)] - */ - void bmc::compile_nonlinear() { - datatype_util dtu(m); - - rule_set::decl2rules::iterator it = m_rules.begin_grouped_rules(); - rule_set::decl2rules::iterator end = m_rules.end_grouped_rules(); - for (; it != end; ++it) { - func_decl* p = it->m_key; - rule_vector const& rls = *it->m_value; - - // Assert: p_level => r1_level \/ r2_level \/ r3_level \/ ... - // where: r_i_level = body of rule i for level + equalities for head of rule i - - expr_ref rule_body(m), tmp(m), pred(m), trace_arg(m), fml(m); - var_ref path_var(m), trace_var(m); - expr_ref_vector rules(m), sub(m), conjs(m), vars(m), patterns(m); - sort* pred_sort = m_pred2sort.find(p); - path_var = m.mk_var(0, m_path_sort); - trace_var = m.mk_var(1, pred_sort); - // sort* sorts[2] = { pred_sort, m_path_sort }; - ptr_vector const& cnstrs = *dtu.get_datatype_constructors(pred_sort); - ptr_vector const& succs = *dtu.get_datatype_constructors(m_path_sort); - SASSERT(cnstrs.size() == rls.size()); - pred = m.mk_app(mk_predicate(p), trace_var.get(), path_var.get()); - for (unsigned i = 0; i < rls.size(); ++i) { - sub.reset(); - conjs.reset(); - vars.reset(); - rule& r = *rls[i]; - func_decl_ref rule_pred_i = mk_rule(p, i); - - // Create cnstr_rule_i(Vars) - func_decl* cnstr = cnstrs[i]; - rules.push_back(m.mk_app(rule_pred_i, trace_var.get(), path_var.get())); - unsigned arity = cnstr->get_arity(); - for (unsigned j = 0; j < arity; ++j) { - vars.push_back(m.mk_var(arity-j,cnstr->get_domain(j))); - } - trace_arg = m.mk_app(cnstr, vars.size(), vars.c_ptr()); - - mk_subst(r, path_var, to_app(trace_arg), sub); - - // apply substitution to body. - var_subst vs(m, false); - for (unsigned k = 0; k < p->get_arity(); ++k) { - vs(r.get_head()->get_arg(k), sub.size(), sub.c_ptr(), tmp); - expr_ref arg = mk_arg_nonlinear(p, k, path_var, trace_arg); - conjs.push_back(m.mk_eq(tmp, arg)); - } - for (unsigned j = 0; j < r.get_uninterpreted_tail_size(); ++j) { - expr_ref path_arg(m); - if (j == 0) { - path_arg = path_var.get(); - } - else { - path_arg = m.mk_app(succs[j], path_var.get()); - } - func_decl* q = r.get_decl(j); - for (unsigned k = 0; k < q->get_arity(); ++k) { - vs(r.get_tail(j)->get_arg(k), sub.size(), sub.c_ptr(), tmp); - expr_ref arg = mk_arg_nonlinear(q, k, path_arg, vars[j].get()); - conjs.push_back(m.mk_eq(tmp, arg)); - } - func_decl_ref q_pred = mk_predicate(q); - conjs.push_back(m.mk_app(q_pred, vars[j].get(), path_arg)); - } - for (unsigned j = r.get_uninterpreted_tail_size(); j < r.get_tail_size(); ++j) { - vs(r.get_tail(j), sub.size(), sub.c_ptr(), tmp); - conjs.push_back(tmp); - } - bool_rewriter(m).mk_and(conjs.size(), conjs.c_ptr(), rule_body); - ptr_vector q_sorts; - vector names; - for (unsigned i = 0; i < vars.size(); ++i) { - q_sorts.push_back(m.get_sort(vars[i].get())); - names.push_back(symbol(i+1)); - } - vars.push_back(path_var); - q_sorts.push_back(m.get_sort(path_var)); - names.push_back(symbol("path")); - SASSERT(names.size() == q_sorts.size()); - SASSERT(vars.size() == names.size()); - symbol qid = r.name(), skid; - tmp = m.mk_app(mk_predicate(p), trace_arg.get(), path_var.get()); - patterns.reset(); - patterns.push_back(m.mk_pattern(to_app(tmp))); - fml = m.mk_implies(tmp, rule_body); - fml = m.mk_forall(vars.size(), q_sorts.c_ptr(), names.c_ptr(), fml, 1, qid, skid, 1, patterns.c_ptr()); - assert_expr(fml); - - } - } - } - - void bmc::declare_datatypes() { - rule_set::decl2rules::iterator it = m_rules.begin_grouped_rules(); - rule_set::decl2rules::iterator end = m_rules.end_grouped_rules(); - datatype_util dtu(m); - ptr_vector dts; - - obj_map pred_idx; - for (unsigned i = 0; it != end; ++it, ++i) { - pred_idx.insert(it->m_key, i); - } - - it = m_rules.begin_grouped_rules(); - for (; it != end; ++it) { - rule_vector const& rls = *it->m_value; - func_decl* pred = it->m_key; - ptr_vector cnstrs; - for (unsigned i = 0; i < rls.size(); ++i) { - rule* r = rls[i]; - ptr_vector accs; - for (unsigned j = 0; j < r->get_uninterpreted_tail_size(); ++j) { - func_decl* q = r->get_decl(j); - unsigned idx = pred_idx.find(q); - std::stringstream _name; - _name << pred->get_name() << "_" << q->get_name() << j; - symbol name(_name.str().c_str()); - type_ref tr(idx); - accs.push_back(mk_accessor_decl(name, tr)); - } - std::stringstream _name; - _name << pred->get_name() << "_" << i; - symbol name(_name.str().c_str()); - _name << "?"; - symbol is_name(_name.str().c_str()); - cnstrs.push_back(mk_constructor_decl(name, is_name, accs.size(), accs.c_ptr())); - } - dts.push_back(mk_datatype_decl(pred->get_name(), cnstrs.size(), cnstrs.c_ptr())); - } - - - sort_ref_vector new_sorts(m); - family_id dfid = m.get_family_id("datatype"); - datatype_decl_plugin* dtp = static_cast(m.get_plugin(dfid)); - VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts)); - - it = m_rules.begin_grouped_rules(); - for (unsigned i = 0; it != end; ++it, ++i) { - m_pred2sort.insert(it->m_key, new_sorts[i].get()); - m_sort2pred.insert(new_sorts[i].get(), it->m_key); - m_pinned.push_back(new_sorts[i].get()); - } - if (new_sorts.size() > 0) { - TRACE("bmc", dtu.display_datatype(new_sorts[0].get(), tout);); - } - del_datatype_decls(dts.size(), dts.c_ptr()); - - // declare path data-type. - { - new_sorts.reset(); - dts.reset(); - ptr_vector cnstrs; - unsigned max_arity = 0; - rule_set::iterator it = m_rules.begin(); - rule_set::iterator end = m_rules.end(); - for (; it != end; ++it) { - rule* r = *it; - unsigned sz = r->get_uninterpreted_tail_size(); - max_arity = std::max(sz, max_arity); - } - cnstrs.push_back(mk_constructor_decl(symbol("Z#"), symbol("Z#?"), 0, 0)); - - for (unsigned i = 0; i + 1 < max_arity; ++i) { - std::stringstream _name; - _name << "succ#" << i; - symbol name(_name.str().c_str()); - _name << "?"; - symbol is_name(_name.str().c_str()); - std::stringstream _name2; - _name2 << "get_succ#" << i; - symbol acc_name(_name2.str().c_str()); - ptr_vector accs; - type_ref tr(0); - accs.push_back(mk_accessor_decl(name, tr)); - cnstrs.push_back(mk_constructor_decl(name, is_name, accs.size(), accs.c_ptr())); - } - dts.push_back(mk_datatype_decl(symbol("Path"), cnstrs.size(), cnstrs.c_ptr())); - VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts)); - m_path_sort = new_sorts[0].get(); - } - } - - proof_ref bmc::get_proof(model_ref& md, app* trace, app* path) { - datatype_util dtu(m); - sort* trace_sort = m.get_sort(trace); - func_decl* p = m_sort2pred.find(trace_sort); - datalog::rule_vector const& rules = m_rules.get_predicate_rules(p); - ptr_vector const& cnstrs = *dtu.get_datatype_constructors(trace_sort); - ptr_vector const& succs = *dtu.get_datatype_constructors(m_path_sort); - // bool found = false; - for (unsigned i = 0; i < cnstrs.size(); ++i) { - if (trace->get_decl() == cnstrs[i]) { - // found = true; - svector > positions; - scoped_coarse_proof _sc(m); - proof_ref_vector prs(m); - expr_ref_vector sub(m); - vector substs; - proof_ref pr(m); - expr_ref fml(m), head(m), tmp(m); - app_ref path1(m); - - var_subst vs(m, false); - mk_subst(*rules[i], path, trace, sub); - rules[i]->to_formula(fml); - prs.push_back(m.mk_asserted(fml)); - unsigned sz = trace->get_num_args(); - if (sub.empty() && sz == 0) { - pr = prs[0].get(); - return pr; - } - for (unsigned j = 0; j < sub.size(); ++j) { - md->eval(sub[j].get(), tmp); - sub[j] = tmp; - } - rule_ref rl(m_ctx.get_rule_manager()); - rl = rules[i]; - m_ctx.get_rule_manager().substitute(rl, sub.size(), sub.c_ptr()); - - substs.push_back(sub); - - for (unsigned j = 0; j < sz; ++j) { - if (j == 0) { - path1 = path; - } - else { - path1 = m.mk_app(succs[j], path); - } - - prs.push_back(get_proof(md, to_app(trace->get_arg(j)), path1)); - positions.push_back(std::make_pair(j+1,0)); - substs.push_back(expr_ref_vector(m)); - } - head = rl->get_head(); - pr = m.mk_hyper_resolve(sz+1, prs.c_ptr(), head, positions, substs); - return pr; - } - } - UNREACHABLE(); - return proof_ref(0, m); - } - - // instantiation of algebraic data-types takes care of the rest. - lbool bmc::check_query() { - sort* trace_sort = m_pred2sort.find(m_query_pred); - func_decl_ref q = mk_predicate(m_query_pred); - expr_ref trace(m), path(m), fml(m); - trace = m.mk_const(symbol("trace"), trace_sort); - path = m.mk_const(symbol("path"), m_path_sort); - fml = m.mk_app(q, trace.get(), path.get()); - assert_expr(fml); - while (true) { - lbool is_sat = m_solver.check(); - model_ref md; - if (is_sat == l_false) { - return is_sat; - } - m_solver.get_model(md); - mk_answer_nonlinear(md, trace, path); - return l_true; - } - } - - bool bmc::check_model_nonlinear(model_ref& md, expr* trace) { - expr_ref trace_val(m), eq(m); - md->eval(trace, trace_val); - eq = m.mk_eq(trace, trace_val); - m_solver.push(); - m_solver.assert_expr(eq); - lbool is_sat = m_solver.check(); - if (is_sat != l_false) { - m_solver.get_model(md); - } - m_solver.pop(1); - if (is_sat == l_false) { - IF_VERBOSE(1, verbose_stream() << "infeasible trace " << mk_pp(trace_val, m) << "\n";); - eq = m.mk_not(eq); - m_solver.assert_expr(eq); - } - return is_sat != l_false; - } - - void bmc::mk_answer_nonlinear(model_ref& md, expr_ref& trace, expr_ref& path) { - proof_ref pr(m); - IF_VERBOSE(2, model_smt2_pp(verbose_stream(), m, *md, 0);); - md->eval(trace, trace); - md->eval(path, path); - IF_VERBOSE(2, verbose_stream() << mk_pp(trace, m) << "\n"; - for (unsigned i = 0; i < m_solver.size(); ++i) { - verbose_stream() << mk_pp(m_solver.get_formulas()[i], m) << "\n"; - }); - m_answer = get_proof(md, to_app(trace), to_app(path)); - } - - void bmc::checkpoint() { if (m_cancel) { throw default_exception("bmc canceled"); @@ -1103,4 +1510,16 @@ namespace datalog { return m_answer; } + void bmc::compile(rule_set const& rules, expr_ref_vector& fmls, unsigned level) { + nonlinear nl(*this); + nl.compile(rules, fmls, level); + } + + expr_ref bmc::compile_query(func_decl* query_pred, unsigned level) { + nonlinear nl(*this); + return nl.compile_query(query_pred, level); + } + }; + +template class rewriter_tpl; diff --git a/src/muz_qe/dl_bmc_engine.h b/src/muz_qe/dl_bmc_engine.h index 5b6e433cd..06901a160 100644 --- a/src/muz_qe/dl_bmc_engine.h +++ b/src/muz_qe/dl_bmc_engine.h @@ -35,83 +35,23 @@ namespace datalog { ast_manager& m; smt_params m_fparams; smt::kernel m_solver; - obj_map m_pred2sort; - obj_map m_sort2pred; - obj_map m_pred2newpred; - obj_map > m_pred2args; - ast_ref_vector m_pinned; rule_set m_rules; func_decl_ref m_query_pred; expr_ref m_answer; volatile bool m_cancel; proof_converter_ref m_pc; - sort_ref m_path_sort; - bv_util m_bv; - unsigned m_bit_width; - - lbool check_query(); - - proof_ref get_proof(model_ref& md, app* trace, app* path); void checkpoint(); - void declare_datatypes(); - - void compile_nonlinear(); - - void mk_rule_vars_nonlinear(rule& r, unsigned rule_id, expr* trace_arg, expr* path_arg, expr_ref_vector& sub); - - expr_ref mk_var_nonlinear(func_decl* pred, sort* s, unsigned idx, expr* path_arg, expr* trace_arg); - - expr_ref mk_arg_nonlinear(func_decl* pred, unsigned idx, expr* path_arg, expr* trace_arg); - - void mk_subst(rule& r, expr* path, app* trace, expr_ref_vector& sub); + class nonlinear_dt; + class nonlinear; + class qlinear; + class linear; bool is_linear() const; - - lbool check_nonlinear(); - void setup_nonlinear(); - bool check_model_nonlinear(model_ref& md, expr* trace); - void mk_answer_nonlinear(model_ref& md, expr_ref& trace, expr_ref& path); - func_decl_ref mk_predicate(func_decl* p); - - func_decl_ref mk_rule(func_decl* p, unsigned rule_idx); - - // linear check - lbool check_linear(); - lbool check_linear(unsigned level); - void compile_linear(); - void compile_linear(unsigned level); - void compile_linear(rule& r, unsigned level); - expr_ref mk_level_predicate(symbol const& name, unsigned level); - expr_ref mk_level_predicate(func_decl* p, unsigned level); - expr_ref mk_level_arg(func_decl* pred, unsigned idx, unsigned level); - expr_ref mk_level_rule(func_decl* p, unsigned rule_idx, unsigned level); - expr_ref mk_level_var(func_decl* pred, sort* s, unsigned rule_id, unsigned idx, unsigned level); - void get_model_linear(unsigned level); - void setup_linear(); - void assert_expr(expr* e); - void mk_rule_vars(rule& r, unsigned level, unsigned rule_id, expr_ref_vector& sub); - - // quantified linear check - void compile_qlinear(); - void setup_qlinear(); - lbool check_qlinear(); - lbool get_model_qlinear(); - sort_ref mk_index_sort(); - var_ref mk_index_var(); - void mk_qrule_vars(datalog::rule const& r, unsigned i, expr_ref_vector& sub); - expr_ref mk_q_var(func_decl* pred, sort* s, unsigned rule_id, unsigned idx); - expr_ref mk_q_arg(func_decl* pred, unsigned idx, bool is_current); - expr_ref mk_q_one(); - expr_ref mk_q_num(unsigned i); - expr_ref eval_q(model_ref& model, expr* t, unsigned i); - expr_ref eval_q(model_ref& model, func_decl* f, unsigned i); - func_decl_ref mk_q_rule(func_decl* f, unsigned rule_id); - func_decl_ref mk_q_func_decl(func_decl* f); public: bmc(context& ctx); @@ -131,6 +71,10 @@ namespace datalog { void reset_statistics(); expr_ref get_answer(); + + // direct access to (new) non-linear compiler. + void compile(rule_set const& rules, expr_ref_vector& fmls, unsigned level); + expr_ref compile_query(func_decl* query_pred, unsigned level); }; }; diff --git a/src/muz_qe/dl_context.cpp b/src/muz_qe/dl_context.cpp index 7a46228ce..5581732c8 100644 --- a/src/muz_qe/dl_context.cpp +++ b/src/muz_qe/dl_context.cpp @@ -715,6 +715,8 @@ namespace datalog { check_positive_predicates(r); break; case BMC_ENGINE: + check_positive_predicates(r); + break; case QBMC_ENGINE: check_existential_tail(r); check_positive_predicates(r); diff --git a/src/muz_qe/dl_mk_array_blast.cpp b/src/muz_qe/dl_mk_array_blast.cpp index a5259ba8a..880f196a2 100644 --- a/src/muz_qe/dl_mk_array_blast.cpp +++ b/src/muz_qe/dl_mk_array_blast.cpp @@ -18,7 +18,8 @@ Revision History: --*/ #include "dl_mk_array_blast.h" -#include "expr_replacer.h" +#include "expr_safe_replace.h" + namespace datalog { @@ -54,9 +55,10 @@ namespace datalog { unsigned tsz = r.get_tail_size(); expr_ref_vector conjs(m), new_conjs(m); expr_ref tmp(m); - expr_substitution sub(m); + expr_safe_replace sub(m); uint_set lhs_vars, rhs_vars; bool change = false; + bool inserted = false; for (unsigned i = 0; i < utsz; ++i) { new_conjs.push_back(r.get_tail(i)); @@ -81,6 +83,7 @@ namespace datalog { } else { sub.insert(x, y); + inserted = true; } } else { @@ -89,7 +92,7 @@ namespace datalog { new_conjs.push_back(tmp); } } - if (sub.empty() && !change) { + if (!inserted && !change) { rules.add_rule(&r); return false; } @@ -99,11 +102,9 @@ namespace datalog { r.to_formula(fml1); body = m.mk_and(new_conjs.size(), new_conjs.c_ptr()); head = r.get_head(); - scoped_ptr replace = mk_default_expr_replacer(m); - replace->set_substitution(&sub); - (*replace)(body); + sub(body); m_rewriter(body); - (*replace)(head); + sub(head); m_rewriter(head); fml2 = m.mk_implies(body, head); rm.mk_rule(fml2, new_rules, r.name()); diff --git a/src/muz_qe/dl_mk_coalesce.cpp b/src/muz_qe/dl_mk_coalesce.cpp index 251988a84..222881bc4 100644 --- a/src/muz_qe/dl_mk_coalesce.cpp +++ b/src/muz_qe/dl_mk_coalesce.cpp @@ -60,7 +60,7 @@ namespace datalog { obj_map indices; bool_rewriter bwr(m); rule_ref r(const_cast(&rl), rm); - sort_ref_vector sorts(m); + ptr_vector sorts; expr_ref_vector revsub(m), conjs(m); rl.get_vars(sorts); revsub.resize(sorts.size()); @@ -72,8 +72,8 @@ namespace datalog { if (is_var(e)) { unsigned v = to_var(e)->get_idx(); SASSERT(v < valid.size()); - if (sorts[v].get()) { - SASSERT(s == sorts[v].get()); + if (sorts[v]) { + SASSERT(s == sorts[v]); if (valid[v]) { revsub[v] = w; valid[v] = false; @@ -92,8 +92,8 @@ namespace datalog { } } for (unsigned i = 0; i < sorts.size(); ++i) { - if (valid[i] && sorts[i].get() && !revsub[i].get()) { - revsub[i] = m.mk_var(m_idx++, sorts[i].get()); + if (valid[i] && sorts[i] && !revsub[i].get()) { + revsub[i] = m.mk_var(m_idx++, sorts[i]); } } var_subst vs(m, false); @@ -112,7 +112,7 @@ namespace datalog { app_ref pred(m), head(m); expr_ref fml1(m), fml2(m), fml(m); app_ref_vector tail(m); - sort_ref_vector sorts1(m), sorts2(m); + ptr_vector sorts1, sorts2; expr_ref_vector conjs1(m), conjs(m); rule_ref res(rm); bool_rewriter bwr(m); diff --git a/src/muz_qe/dl_mk_extract_quantifiers2.cpp b/src/muz_qe/dl_mk_extract_quantifiers2.cpp new file mode 100644 index 000000000..97976a6be --- /dev/null +++ b/src/muz_qe/dl_mk_extract_quantifiers2.cpp @@ -0,0 +1,366 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + dl_mk_extract_quantifiers2.cpp + +Abstract: + + Remove universal quantifiers over interpreted predicates in the body. + +Author: + + Nikolaj Bjorner (nbjorner) 2012-11-21 + +Revision History: + +--*/ + +#include"dl_mk_extract_quantifiers2.h" +#include"ast_pp.h" +#include"dl_bmc_engine.h" +#include"smt_quantifier.h" +#include"smt_context.h" + +namespace datalog { + + + mk_extract_quantifiers2::mk_extract_quantifiers2(context & ctx) : + rule_transformer::plugin(101, false), + m_ctx(ctx), + m(ctx.get_manager()), + rm(ctx.get_rule_manager()), + m_query_pred(m), + m_quantifiers(m), + m_refs(m) + {} + + mk_extract_quantifiers2::~mk_extract_quantifiers2() { + reset(); + } + + void mk_extract_quantifiers2::set_query(func_decl* q) { + m_query_pred = q; + } + + bool mk_extract_quantifiers2::matches_signature(func_decl* head, expr_ref_vector const& binding) { + unsigned sz = head->get_arity(); + if (sz != binding.size()) { + return false; + } + for (unsigned i = 0; i < sz; ++i) { + if (head->get_domain(i) != m.get_sort(binding[sz-i-1])) { + return false; + } + } + return true; + } + + bool mk_extract_quantifiers2::matches_quantifier(quantifier* q, expr_ref_vector const& binding) { + unsigned sz = q->get_num_decls(); + if (sz != binding.size()) { + return false; + } + for (unsigned i = 0; i < sz; ++i) { + if (q->get_decl_sort(i) != m.get_sort(binding[sz-i-1])) { + return false; + } + } + return true; + } + + bool mk_extract_quantifiers2::mk_abstract_expr(expr_ref& term) { + if (!is_app(term)) { + return false; + } + expr* r; + if (m_map.find(term, r)) { + term = r; + return true; + } + if (to_app(term)->get_family_id() == null_family_id) { + return false; + } + expr_ref_vector args(m); + expr_ref tmp(m); + for (unsigned i = 0; i < to_app(term)->get_num_args(); ++i) { + tmp = to_app(term)->get_arg(i); + if (!mk_abstract_expr(tmp)) { + return false; + } + args.push_back(tmp); + } + tmp = m.mk_app(to_app(term)->get_decl(), args.size(), args.c_ptr()); + m_refs.push_back(tmp); + m_map.insert(term, tmp); + term = tmp; + return true; + } + + bool mk_extract_quantifiers2::mk_abstract_binding(expr_ref_vector const& binding, expr_ref_vector& result) { + for (unsigned i = 0; i < binding.size(); ++i) { + expr_ref tmp(m); + tmp = binding[i]; + if (!mk_abstract_expr(tmp)) { + return false; + } + result.push_back(tmp); + } + return true; + } + + void mk_extract_quantifiers2::mk_abstraction_map(rule& r, expr_ref_vector const& binding) { + m_map.reset(); + unsigned sz = binding.size(); + SASSERT(sz == r.get_decl()->get_arity()); + for (unsigned i = 0; i < sz; ++i) { + m_map.insert(binding[sz-i-1], r.get_head()->get_arg(i)); + SASSERT(m.get_sort(binding[sz-i-1]) == m.get_sort(r.get_head()->get_arg(i))); + } + // todo: also make bindings for variables in rule body. + } + + void mk_extract_quantifiers2::match_bindings(unsigned i, unsigned j, unsigned k) { + expr_ref_vector resb(m); + rule* r = m_qrules[i]; + quantifier* q = m_quantifiers[i].get(); + expr_ref_vector const& ruleb = m_rule_bindings[i][j]; + expr_ref_vector const& quantb = m_quantifier_bindings[i][k]; + mk_abstraction_map(*r, ruleb); + if (!mk_abstract_binding(quantb, resb)) { + return; + } + expr_ref inst(m), tmp(m); + var_shifter shift(m); + + for (unsigned l = 0; l < resb.size(); ++l) { + tmp = resb[l].get(); + shift(tmp, q->get_num_decls(), tmp); + resb[l] = tmp; + } + + instantiate(m, q, resb.c_ptr(), inst); + if (!m_seen.contains(r)) { + m_seen.insert(r, alloc(obj_hashtable)); + } + obj_hashtable& seen = *m_seen.find(r); + if (seen.contains(inst)) { + return; + } + seen.insert(inst); + m_refs.push_back(inst); + if (!m_quantifier_instantiations.contains(r, q)) { + m_quantifier_instantiations.insert(r, q, alloc(expr_ref_vector, m)); + } + expr_ref_vector* vec = 0; + VERIFY(m_quantifier_instantiations.find(r, q, vec)); + vec->push_back(inst); + TRACE("dl", tout << "matched: " << mk_pp(q, m) << "\n" << mk_pp(inst, m) << "\n";); + } + + app_ref mk_extract_quantifiers2::ensure_app(expr* e) { + if (is_app(e)) { + return app_ref(to_app(e), m); + } + else { + return app_ref(m.mk_eq(e, m.mk_true()), m); + } + } + + void mk_extract_quantifiers2::extract(rule& r, rule_set& new_rules) { + unsigned utsz = r.get_uninterpreted_tail_size(); + unsigned tsz = r.get_tail_size(); + bool has_quantifier = false; + expr_ref_vector conjs(m); + for (unsigned i = utsz; i < tsz; ++i) { + conjs.push_back(r.get_tail(i)); + } + datalog::flatten_and(conjs); + for (unsigned j = 0; j < conjs.size(); ++j) { + expr* e = conjs[j].get(); + quantifier* q; + if (rule_manager::is_forall(m, e, q)) { + m_quantifiers.push_back(q); + m_qrules.push_back(&r); + m_rule_bindings.push_back(vector()); + m_quantifier_bindings.push_back(vector()); + has_quantifier = true; + } + } + if (!has_quantifier) { + new_rules.add_rule(&r); + } + } + + void mk_extract_quantifiers2::apply(rule& r, rule_set& new_rules) { + expr_ref_vector tail(m), conjs(m); + expr_ref fml(m); + unsigned utsz = r.get_uninterpreted_tail_size(); + unsigned tsz = r.get_tail_size(); + for (unsigned i = 0; i < utsz; ++i) { + SASSERT(!r.is_neg_tail(i)); + tail.push_back(r.get_tail(i)); + } + bool has_quantifier = false; + for (unsigned i = utsz; i < tsz; ++i) { + conjs.push_back(r.get_tail(i)); + } + datalog::flatten_and(conjs); + for (unsigned j = 0; j < conjs.size(); ++j) { + expr* e = conjs[j].get(); + quantifier* q; + if (rule_manager::is_forall(m, e, q)) { + expr_ref_vector* ls; + if (m_quantifier_instantiations.find(&r,q,ls)) { + tail.append(*ls); + } + has_quantifier = true; + } + else { + tail.push_back(e); + } + } + if (has_quantifier) { + fml = m.mk_implies(m.mk_and(tail.size(), tail.c_ptr()), r.get_head()); + rule_ref_vector rules(rm); + rm.mk_rule(fml, rules, r.name()); + for (unsigned i = 0; i < rules.size(); ++i) { + new_rules.add_rule(rules[i].get()); + } + } + } + +#if 0 + class mk_extract_quantifiers2::instance_plugin : public smt::quantifier_instance_plugin { + mk_extract_quantifiers2& ex; + ast_manager& m; + expr_ref_vector m_refs; + obj_hashtable m_bindings; + public: + instance_plugin(mk_extract_quantifiers2& ex): ex(ex), m(ex.m), m_refs(m) {} + + virtual void operator()(quantifier* q, unsigned num_bindings, smt::enode*const* bindings) { + expr_ref_vector binding(m); + ptr_vector sorts; + for (unsigned i = 0; i < num_bindings; ++i) { + binding.push_back(bindings[i]->get_owner()); + sorts.push_back(m.get_sort(binding[i].get())); + } + func_decl* f = m.mk_func_decl(symbol("T"), sorts.size(), sorts.c_ptr(), m.mk_bool_sort()); + expr_ref tup(m); + tup = m.mk_app(f, binding.size(), binding.c_ptr()); + if (!m_bindings.contains(tup)) { + m_bindings.insert(tup); + m_refs.push_back(tup); + ex.m_bindings.push_back(binding); + TRACE("dl", tout << "insert\n" << mk_pp(q, m) << "\n" << mk_pp(tup, m) << "\n";); + } + } + }; + +#endif + + void mk_extract_quantifiers2::reset() { + { + obj_pair_map::iterator + it = m_quantifier_instantiations.begin(), + end = m_quantifier_instantiations.end(); + for (; it != end; ++it) { + dealloc(it->get_value()); + } + } + { + obj_map*>::iterator + it = m_seen.begin(), + end = m_seen.end(); + for (; it != end; ++it) { + dealloc(it->m_value); + } + } + m_quantifier_instantiations.reset(); + m_seen.reset(); + m_has_quantifiers = false; + m_quantifiers.reset(); + m_qrules.reset(); + m_bindings.reset(); + m_rule_bindings.reset(); + m_quantifier_bindings.reset(); + m_refs.reset(); + } + + rule_set * mk_extract_quantifiers2::operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc) { + reset(); + rule_set::iterator it = source.begin(), end = source.end(); + for (; !m_has_quantifiers && it != end; ++it) { + m_has_quantifiers = (*it)->has_quantifiers(); + } + if (!m_has_quantifiers) { + return 0; + } + + rule_set* rules = alloc(rule_set, m_ctx); + it = source.begin(); + for (; it != end; ++it) { + extract(**it, *rules); + } + + bmc bmc(m_ctx); + expr_ref_vector fmls(m); + bmc.compile(source, fmls, 0); // TBD: use cancel_eh to terminate without base-case. + bmc.compile(source, fmls, 1); + bmc.compile(source, fmls, 2); +// bmc.compile(source, fmls, 3); + expr_ref query = bmc.compile_query(m_query_pred, 2); + fmls.push_back(query); + smt_params fparams; + fparams.m_relevancy_lvl = 0; + fparams.m_model = true; + fparams.m_model_compact = true; + fparams.m_mbqi = true; + smt::kernel solver(m, fparams); + TRACE("dl", + for (unsigned i = 0; i < fmls.size(); ++i) { + tout << mk_pp(fmls[i].get(), m) << "\n"; + }); + + for (unsigned i = 0; i < fmls.size(); ++i) { + solver.assert_expr(fmls[i].get()); + } +#if 0 + smt::context& ctx = solver.get_context(); + smt::quantifier_manager* qm = ctx.get_quantifier_manager(); + qm->get_plugin()->set_instance_plugin(alloc(instance_plugin, *this)); +#endif + lbool res = solver.check(); + + for (unsigned i = 0; i < m_bindings.size(); ++i) { + expr_ref_vector& binding = m_bindings[i]; + for (unsigned j = 0; j < m_qrules.size(); ++j) { + rule* r = m_qrules[j]; + if (matches_signature(r->get_decl(), binding)) { + m_rule_bindings[j].push_back(binding); + } + else if (matches_quantifier(m_quantifiers[j].get(), binding)) { + m_quantifier_bindings[j].push_back(binding); + } + } + } + for (unsigned i = 0; i < m_qrules.size(); ++i) { + for (unsigned j = 0; j < m_rule_bindings[i].size(); ++j) { + for (unsigned k = 0; k < m_quantifier_bindings[i].size(); ++k) { + match_bindings(i, j, k); + } + } + } + it = source.begin(); + for (; it != end; ++it) { + apply(**it, *rules); + } + + return rules; + } + +}; + + diff --git a/src/muz_qe/dl_mk_extract_quantifiers2.h b/src/muz_qe/dl_mk_extract_quantifiers2.h new file mode 100644 index 000000000..30c15b313 --- /dev/null +++ b/src/muz_qe/dl_mk_extract_quantifiers2.h @@ -0,0 +1,91 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + dl_mk_extract_quantifiers2.h + +Abstract: + + Replace universal quantifiers over interpreted predicates in the body + by instantiations mined using bounded model checking search. + +Author: + + Nikolaj Bjorner (nbjorner) 2012-11-21 + +Revision History: + +--*/ +#ifndef _DL_MK_EXTRACT_QUANTIFIERS2_H_ +#define _DL_MK_EXTRACT_QUANTIFIERS2_H_ + +#include"dl_context.h" +#include"dl_rule_set.h" +#include"dl_rule_transformer.h" +#include"obj_pair_hashtable.h" + +namespace datalog { + + /** + \brief Extract universal quantifiers from rules. + */ + class mk_extract_quantifiers2 : public rule_transformer::plugin { + context& m_ctx; + ast_manager& m; + rule_manager& rm; + func_decl_ref m_query_pred; + quantifier_ref_vector m_quantifiers; + ptr_vector m_qrules; + vectorm_bindings; + vector > m_rule_bindings; + vector > m_quantifier_bindings; + obj_pair_map m_quantifier_instantiations; + obj_map*> m_seen; + + bool m_has_quantifiers; + obj_map m_map; + expr_ref_vector m_refs; + + class instance_plugin; + + void reset(); + + void extract(rule& r, rule_set& new_rules); + + void apply(rule& r, rule_set& new_rules); + + app_ref ensure_app(expr* e); + + bool matches_signature(func_decl* head, expr_ref_vector const& binding); + + bool matches_quantifier(quantifier* q, expr_ref_vector const& binding); + + void match_bindings(unsigned i, unsigned j, unsigned k); + + bool mk_abstract_expr(expr_ref& term); + + bool mk_abstract_binding(expr_ref_vector const& binding, expr_ref_vector& result); + + void mk_abstraction_map(rule& r, expr_ref_vector const& binding); + + public: + /** + \brief Create rule transformer that extracts universal quantifiers (over recursive predicates). + */ + mk_extract_quantifiers2(context & ctx); + + virtual ~mk_extract_quantifiers2(); + + void set_query(func_decl* q); + + rule_set * operator()(rule_set const & source, model_converter_ref& mc, proof_converter_ref& pc); + + bool has_quantifiers() { return m_has_quantifiers; } + + }; + +}; + +#endif /* _DL_MK_EXTRACT_QUANTIFIERS2_H_ */ + diff --git a/src/muz_qe/dl_mk_rule_inliner.cpp b/src/muz_qe/dl_mk_rule_inliner.cpp index fa532ee6c..24ddd9ba5 100644 --- a/src/muz_qe/dl_mk_rule_inliner.cpp +++ b/src/muz_qe/dl_mk_rule_inliner.cpp @@ -136,14 +136,14 @@ namespace datalog { expr_ref_vector rule_unifier::get_rule_subst(const rule& r, bool is_tgt) { SASSERT(m_ready); expr_ref_vector result(m); - sort_ref_vector sorts(m); + ptr_vector sorts; expr_ref v(m), w(m); r.get_vars(sorts); for (unsigned i = 0; i < sorts.size(); ++i) { - if (!sorts[i].get()) { + if (!sorts[i]) { sorts[i] = m.mk_bool_sort(); } - v = m.mk_var(i, sorts[i].get()); + v = m.mk_var(i, sorts[i]); m_subst.apply(2, m_deltas, expr_offset(v, is_tgt?0:1), w); result.push_back(w); } diff --git a/src/muz_qe/dl_rule.cpp b/src/muz_qe/dl_rule.cpp index dedd37a78..bd7131fea 100644 --- a/src/muz_qe/dl_rule.cpp +++ b/src/muz_qe/dl_rule.cpp @@ -41,6 +41,7 @@ Revision History: #include"expr_replacer.h" #include"bool_rewriter.h" #include"qe_lite.h" +#include"expr_safe_replace.h" namespace datalog { @@ -130,17 +131,15 @@ namespace datalog { return index; } // replace vars by de-bruijn indices - expr_substitution sub(m); + expr_safe_replace rep(m); for (unsigned i = 0; i < vars.size(); ++i) { app* v = vars[i].get(); if (names) { names->push_back(v->get_decl()->get_name()); } - sub.insert(v, m.mk_var(index++,m.get_sort(v))); + rep.insert(v, m.mk_var(index++,m.get_sort(v))); } - scoped_ptr rep = mk_default_expr_replacer(m); - rep->set_substitution(&sub); - (*rep)(fml); + rep(fml); return index; } @@ -936,7 +935,7 @@ namespace datalog { } } - void rule::get_vars(sort_ref_vector& sorts) const { + void rule::get_vars(ptr_vector& sorts) const { sorts.reset(); used_vars used; get_used_vars(used); diff --git a/src/muz_qe/dl_rule.h b/src/muz_qe/dl_rule.h index 79a46052c..a9e360344 100644 --- a/src/muz_qe/dl_rule.h +++ b/src/muz_qe/dl_rule.h @@ -244,7 +244,7 @@ namespace datalog { void norm_vars(rule_manager & rm); - void get_vars(sort_ref_vector& sorts) const; + void get_vars(ptr_vector& sorts) const; void to_formula(expr_ref& result) const; diff --git a/src/muz_qe/pdr_quantifiers.cpp b/src/muz_qe/pdr_quantifiers.cpp index 2816a58d4..9233f6314 100644 --- a/src/muz_qe/pdr_quantifiers.cpp +++ b/src/muz_qe/pdr_quantifiers.cpp @@ -440,7 +440,7 @@ namespace pdr { unsigned ut_size = r.get_uninterpreted_tail_size(); unsigned t_size = r.get_tail_size(); var_subst vs(m, false); - sort_ref_vector vars(m); + ptr_vector vars; uint_set empty_index_set; qe_lite qe(m); From 0831e020e39349134ef46a54bd55ab66f2b136bb Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 10 Dec 2012 17:25:28 -0800 Subject: [PATCH 51/60] add qe-lite tatic Signed-off-by: Nikolaj Bjorner --- src/muz_qe/qe_lite.cpp | 207 ++++++++++++++++++++++++++++++++++++----- src/muz_qe/qe_lite.h | 10 ++ 2 files changed, 195 insertions(+), 22 deletions(-) diff --git a/src/muz_qe/qe_lite.cpp b/src/muz_qe/qe_lite.cpp index 8880a9ba5..3e15818e4 100644 --- a/src/muz_qe/qe_lite.cpp +++ b/src/muz_qe/qe_lite.cpp @@ -35,7 +35,7 @@ Revision History: #include "dl_util.h" #include "for_each_expr.h" #include "expr_safe_replace.h" - +#include "cooperate.h" class is_variable_proc { public: @@ -91,6 +91,7 @@ namespace eq { expr_ref_vector m_subst_map; expr_ref_buffer m_new_args; th_rewriter m_rewriter; + volatile bool m_cancel; void der_sort_vars(ptr_vector & vars, ptr_vector & definitions, unsigned_vector & order) { order.reset(); @@ -530,6 +531,7 @@ namespace eq { // Find all definitions for (unsigned i = 0; i < num_args; i++) { + checkpoint(); if (is_var_def(is_exists, args[i], v, t)) { unsigned idx = v->get_idx(); if(m_map.get(idx, 0) == 0) { @@ -569,6 +571,12 @@ namespace eq { return false; } + void checkpoint() { + cooperate("der"); + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + } + public: der(ast_manager & m): m(m), a(m), m_is_variable(0), m_subst(m), m_new_exprs(m), m_subst_map(m), m_new_args(m), m_rewriter(m) {} @@ -588,6 +596,7 @@ namespace eq { r = q; // Keep applying reduce_quantifier1 until r doesn't change anymore do { + checkpoint(); proof_ref curr_pr(m); q = to_quantifier(r); reduce_quantifier1(q, r, curr_pr); @@ -605,6 +614,12 @@ namespace eq { } ast_manager& get_manager() const { return m; } + + void set_cancel(bool f) { + m_rewriter.set_cancel(f); + m_cancel = f; + } + }; }; // namespace eq @@ -618,6 +633,7 @@ namespace ar { is_variable_proc* m_is_variable; ptr_vector m_todo; expr_mark m_visited; + volatile bool m_cancel; bool is_variable(expr * e) const { return (*m_is_variable)(e); @@ -723,13 +739,19 @@ namespace ar { return false; } + void checkpoint() { + cooperate("der"); + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + } public: - der(ast_manager& m): m(m), a(m), m_is_variable(0) {} + der(ast_manager& m): m(m), a(m), m_is_variable(0), m_cancel(false) {} void operator()(expr_ref_vector& fmls) { for (unsigned i = 0; i < fmls.size(); ++i) { + checkpoint(); solve_select(fmls, i, fmls[i].get()); solve_neq_select(fmls, i, fmls[i].get()); } @@ -738,6 +760,10 @@ namespace ar { void operator()(expr* e) {} void set_is_variable_proc(is_variable_proc& proc) { m_is_variable = &proc;} + + void set_cancel(bool f) { + m_cancel = f; + } }; }; // namespace ar @@ -866,7 +892,6 @@ namespace fm { unsigned m_fm_cutoff2; unsigned m_fm_extra; bool m_fm_occ; - unsigned long long m_max_memory; unsigned m_counter; bool m_inconsistent; expr_dependency_ref m_inconsistent_core; @@ -1243,7 +1268,7 @@ namespace fm { // // --------------------------- - fm(ast_manager & _m, params_ref const & p): + fm(ast_manager & _m): m(_m), m_allocator("fm-elim"), m_util(m), @@ -1251,7 +1276,6 @@ namespace fm { m_var2expr(m), m_new_fmls(m), m_inconsistent_core(m) { - updt_params(p); m_cancel = false; } @@ -1259,14 +1283,13 @@ namespace fm { reset_constraints(); } - void updt_params(params_ref const & p) { - m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX)); - m_fm_real_only = p.get_bool("fm_real_only", true); - m_fm_limit = p.get_uint("fm_limit", 5000000); - m_fm_cutoff1 = p.get_uint("fm_cutoff1", 8); - m_fm_cutoff2 = p.get_uint("fm_cutoff2", 256); - m_fm_extra = p.get_uint("fm_extra", 0); - m_fm_occ = p.get_bool("fm_occ", false); + void updt_params() { + m_fm_real_only = true; + m_fm_limit = 5000000; + m_fm_cutoff1 = 8; + m_fm_cutoff2 = 256; + m_fm_extra = 0; + m_fm_occ = false; } void set_cancel(bool f) { @@ -2010,11 +2033,9 @@ namespace fm { } void checkpoint() { - // cooperate("fm"); + cooperate("fm"); if (m_cancel) throw tactic_exception(TACTIC_CANCELED_MSG); - if (memory::get_allocation_size() > m_max_memory) - throw tactic_exception(TACTIC_MAX_MEMORY_MSG); } public: @@ -2084,7 +2105,6 @@ namespace fm { class qe_lite::impl { ast_manager& m; - params_ref m_params; eq::der m_der; fm::fm m_fm; ar::der m_array_der; @@ -2106,7 +2126,7 @@ class qe_lite::impl { } public: - impl(ast_manager& m): m(m), m_der(m), m_fm(m, m_params), m_array_der(m) {} + impl(ast_manager& m): m(m), m_der(m), m_fm(m), m_array_der(m) {} void operator()(app_ref_vector& vars, expr_ref& fml) { if (vars.empty()) { @@ -2148,10 +2168,18 @@ public: } void operator()(expr_ref& fml, proof_ref& pr) { - // TODO apply der everywhere as a rewriting rule. - // TODO add cancel method. - if (is_quantifier(fml)) { - m_der(to_quantifier(fml), fml, pr); + if (is_exists(fml)) { + quantifier* q = to_quantifier(fml); + expr_ref body(m); + body = q->get_expr(); + uint_set indices; + for (unsigned i = 0; i < q->get_num_decls(); ++i) { + indices.insert(i); + } + (*this)(indices, true, body); + fml = m.update_quantifier(q, body); + th_rewriter rewriter(m); + rewriter(fml); } } @@ -2195,6 +2223,12 @@ public: TRACE("qe_lite", for (unsigned i = 0; i < fmls.size(); ++i) tout << mk_pp(fmls[i].get(), m) << "\n";); } + void set_cancel(bool f) { + m_der.set_cancel(f); + m_array_der.set_cancel(f); + m_fm.set_cancel(f); + } + }; qe_lite::qe_lite(ast_manager& m) { @@ -2209,6 +2243,10 @@ void qe_lite::operator()(app_ref_vector& vars, expr_ref& fml) { (*m_impl)(vars, fml); } +void qe_lite::set_cancel(bool f) { + m_impl->set_cancel(f); +} + void qe_lite::operator()(expr_ref& fml, proof_ref& pr) { (*m_impl)(fml, pr); } @@ -2220,3 +2258,128 @@ void qe_lite::operator()(uint_set const& index_set, bool index_of_bound, expr_re void qe_lite::operator()(uint_set const& index_set, bool index_of_bound, expr_ref_vector& fmls) { (*m_impl)(index_set, index_of_bound, fmls); } + +class qe_lite_tactic : public tactic { + + struct imp { + ast_manager& m; + qe_lite m_qe; + volatile bool m_cancel; + + imp(ast_manager& m, params_ref const& p): + m(m), + m_qe(m), + m_cancel(false) + {} + + void set_cancel(bool f) { + m_cancel = f; + m_qe.set_cancel(f); + } + + void checkpoint() { + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + cooperate("qe-lite"); + } + + void operator()(goal_ref const & g, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + SASSERT(g->is_well_sorted()); + mc = 0; pc = 0; core = 0; + tactic_report report("qe-lite", *g); + proof_ref new_pr(m); + expr_ref new_f(m); + bool produce_proofs = g->proofs_enabled(); + + unsigned sz = g->size(); + for (unsigned i = 0; i < sz; i++) { + checkpoint(); + if (g->inconsistent()) + break; + expr * f = g->form(i); + if (!has_quantifiers(f)) + continue; + new_f = f; + m_qe(new_f, new_pr); + if (produce_proofs) { + new_pr = m.mk_modus_ponens(g->pr(i), new_pr); + } + g->update(i, new_f, new_pr, g->dep(i)); + } + g->inc_depth(); + result.push_back(g.get()); + TRACE("qe", g->display(tout);); + SASSERT(g->is_well_sorted()); + } + + }; + + params_ref m_params; + imp * m_imp; + +public: + qe_lite_tactic(ast_manager & m, params_ref const & p): + m_params(p) { + m_imp = alloc(imp, m, p); + } + + virtual tactic * translate(ast_manager & m) { + return alloc(qe_lite_tactic, m, m_params); + } + + virtual ~qe_lite_tactic() { + dealloc(m_imp); + } + + virtual void updt_params(params_ref const & p) { + m_params = p; + // m_imp->updt_params(p); + } + + + virtual void collect_param_descrs(param_descrs & r) { + // m_imp->collect_param_descrs(r); + } + + virtual void operator()(goal_ref const & in, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + (*m_imp)(in, result, mc, pc, core); + } + + + virtual void collect_statistics(statistics & st) const { + // m_imp->collect_statistics(st); + } + + virtual void reset_statistics() { + // m_imp->reset_statistics(); + } + + + virtual void cleanup() { + ast_manager & m = m_imp->m; + imp * d = m_imp; + #pragma omp critical (tactic_cancel) + { + m_imp = 0; + } + dealloc(d); + d = alloc(imp, m, m_params); + #pragma omp critical (tactic_cancel) + { + m_imp = d; + } + } + +}; + +tactic * mk_qe_lite_tactic(ast_manager & m, params_ref const & p) { + return alloc(qe_lite_tactic, m, p); +} diff --git a/src/muz_qe/qe_lite.h b/src/muz_qe/qe_lite.h index 3ffbf8fad..7d9239fa7 100644 --- a/src/muz_qe/qe_lite.h +++ b/src/muz_qe/qe_lite.h @@ -23,6 +23,9 @@ Revision History: #include "ast.h" #include "uint_set.h" +#include "params.h" + +class tactic; class qe_lite { class impl; @@ -56,6 +59,13 @@ public: \brief full rewriting based light-weight quantifier elimination round. */ void operator()(expr_ref& fml, proof_ref& pr); + + void set_cancel(bool f); }; +tactic * mk_qe_lite_tactic(ast_manager & m, params_ref const & p = params_ref()); +/* + ADD_TACTIC("qe-light", "apply light-weight quantifier elimination.", "mk_qe_lite_tactic(m, p)") +*/ + #endif From 589f2c6bb36c85b70353d3cfbfc2c28f9674ede5 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Mon, 10 Dec 2012 18:46:02 -0800 Subject: [PATCH 52/60] improved unknown parameter error msg Signed-off-by: Leonardo de Moura --- src/util/gparams.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/gparams.cpp b/src/util/gparams.cpp index 1305a1e02..8b1fbe40e 100644 --- a/src/util/gparams.cpp +++ b/src/util/gparams.cpp @@ -52,6 +52,7 @@ char const * g_params_renames[] = { "qi_cost", "smt.qi.cost", "qi_eager_threshold", "smt.qi.eager_threshold", "nl_arith", "smt.arith.nl", + "pull_nested_quantifiers", "smt.pull_nested_quantifiers", "nnf_sk_hack", "nnf.sk_hack", "model_v2", "model.v2", "pi_non_nested_arith_weight", "pi.non_nested_arith_weight", From 730801e2f01a71cc184008506789d8444eca5b8d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 10 Dec 2012 21:21:02 -0800 Subject: [PATCH 53/60] fix unintialized variable Signed-off-by: Nikolaj Bjorner --- src/muz_qe/qe_lite.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/muz_qe/qe_lite.cpp b/src/muz_qe/qe_lite.cpp index 3e15818e4..cced1ed50 100644 --- a/src/muz_qe/qe_lite.cpp +++ b/src/muz_qe/qe_lite.cpp @@ -578,7 +578,7 @@ namespace eq { } public: - der(ast_manager & m): m(m), a(m), m_is_variable(0), m_subst(m), m_new_exprs(m), m_subst_map(m), m_new_args(m), m_rewriter(m) {} + der(ast_manager & m): m(m), a(m), m_is_variable(0), m_subst(m), m_new_exprs(m), m_subst_map(m), m_new_args(m), m_rewriter(m), m_cancel(false) {} void set_is_variable_proc(is_variable_proc& proc) { m_is_variable = &proc;} From b6459a8a92a347ec326e07052e5220406fb8a2f2 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 11 Dec 2012 10:53:21 -0800 Subject: [PATCH 54/60] add solver object to get_implied_equalities Signed-off-by: Nikolaj Bjorner --- src/api/api_solver_old.cpp | 7 +++++-- src/api/z3_api.h | 7 ++++--- src/smt/smt_implied_equalities.cpp | 32 ++++++++++++++---------------- src/smt/smt_implied_equalities.h | 7 +++++-- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/api/api_solver_old.cpp b/src/api/api_solver_old.cpp index cd4b797e3..d43e103c2 100644 --- a/src/api/api_solver_old.cpp +++ b/src/api/api_solver_old.cpp @@ -24,6 +24,7 @@ Revision History: #include"api_model.h" #include"smt_implied_equalities.h" #include"cancel_eh.h" +#include"api_solver.h" extern "C" { @@ -113,14 +114,16 @@ extern "C" { } Z3_lbool Z3_API Z3_get_implied_equalities(Z3_context c, + Z3_solver s, unsigned num_terms, Z3_ast const terms[], unsigned class_ids[]) { Z3_TRY; - LOG_Z3_get_implied_equalities(c, num_terms, terms, class_ids); + LOG_Z3_get_implied_equalities(c, s, num_terms, terms, class_ids); + ast_manager& m = mk_c(c)->m(); RESET_ERROR_CODE(); CHECK_SEARCHING(c); - lbool result = smt::implied_equalities(mk_c(c)->get_smt_kernel(), num_terms, to_exprs(terms), class_ids); + lbool result = smt::implied_equalities(m, *to_solver_ref(s), num_terms, to_exprs(terms), class_ids); return static_cast(result); Z3_CATCH_RETURN(Z3_L_UNDEF); } diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 49d59e125..e12ce3591 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -7123,18 +7123,19 @@ END_MLAPI_EXCLUDE This means that two terms map to the same class identifier if and only if the current context implies that they are equal. - A side-effect of the function is a satisfiability check. + A side-effect of the function is a satisfiability check on the assertions on the solver that is passed in. The function return Z3_L_FALSE if the current assertions are not satisfiable. \sa Z3_check_and_get_model \sa Z3_check - \deprecated Subsumed by Z3_solver API + \deprecated To be moved outside of API. - def_API('Z3_get_implied_equalities', UINT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _out_array(1, UINT))) + def_API('Z3_get_implied_equalities', UINT, (_in(CONTEXT), _in(SOLVER), _in(UINT), _in_array(2, AST), _out_array(2, UINT))) */ Z3_lbool Z3_API Z3_get_implied_equalities( __in Z3_context c, + __in Z3_solver s, __in unsigned num_terms, __in_ecount(num_terms) Z3_ast const terms[], __out_ecount(num_terms) unsigned class_ids[] diff --git a/src/smt/smt_implied_equalities.cpp b/src/smt/smt_implied_equalities.cpp index c6f28d4b2..70229ccab 100644 --- a/src/smt/smt_implied_equalities.cpp +++ b/src/smt/smt_implied_equalities.cpp @@ -21,23 +21,21 @@ Revision History: #include "smt_implied_equalities.h" #include "union_find.h" -#include "cmd_context.h" -#include "parametric_cmd.h" #include "ast_pp.h" -#include "arith_decl_plugin.h" -#include "datatype_decl_plugin.h" #include "array_decl_plugin.h" #include "uint_set.h" -#include "model_v2_pp.h" #include "smt_value_sort.h" - +#include "model_smt2_pp.h" +#include "stopwatch.h" +#include "model.h" +#include "solver.h" namespace smt { class get_implied_equalities_impl { ast_manager& m; - smt::kernel& m_solver; + solver& m_solver; union_find_default_ctx m_df; union_find m_uf; array_util m_array_util; @@ -98,7 +96,7 @@ namespace smt { ++m_stats_calls; m_solver.push(); m_solver.assert_expr(m.mk_not(m.mk_eq(s, t))); - bool is_eq = l_false == m_solver.check(); + bool is_eq = l_false == m_solver.check_sat(0,0); m_solver.pop(1); TRACE("get_implied_equalities", tout << mk_pp(t, m) << " = " << mk_pp(s, m) << " " << (is_eq?"eq":"unrelated") << "\n";); if (is_eq) { @@ -125,7 +123,7 @@ namespace smt { m_stats_timer.start(); m_solver.push(); m_solver.assert_expr(m.mk_not(m.mk_eq(s, t))); - bool is_eq = l_false == m_solver.check(); + bool is_eq = l_false == m_solver.check_sat(0,0); m_solver.pop(1); m_stats_timer.stop(); TRACE("get_implied_equalities", tout << mk_pp(t, m) << " = " << mk_pp(s, m) << " " << (is_eq?"eq":"unrelated") << "\n";); @@ -168,7 +166,7 @@ namespace smt { terms[i].term = m.mk_app(m_array_util.get_family_id(), OP_SELECT, 0, 0, args.size(), args.c_ptr()); } assert_relevant(terms); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); model_ref model1; m_solver.get_model(model1); SASSERT(model1.get()); @@ -218,7 +216,7 @@ namespace smt { expr* s = terms[vec[j]].term; m_solver.push(); m_solver.assert_expr(m.mk_not(m.mk_eq(t, s))); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); m_solver.pop(1); TRACE("get_implied_equalities", tout << mk_pp(t, m) << " = " << mk_pp(s, m) << " " << is_sat << "\n";); if (is_sat == l_false) { @@ -237,7 +235,7 @@ namespace smt { if (!non_values.empty()) { - TRACE("get_implied_equalities", model_v2_pp(tout, *model, true);); + TRACE("get_implied_equalities", model_smt2_pp(tout, m, *model, 0);); get_implied_equalities_filter_basic(non_values, terms); //get_implied_equalities_basic(terms); } @@ -321,7 +319,7 @@ namespace smt { public: - get_implied_equalities_impl(smt::kernel& s) : m(s.m()), m_solver(s), m_uf(m_df), m_array_util(m), m_stats_calls(0) {} + get_implied_equalities_impl(ast_manager& m, solver& s) : m(m), m_solver(s), m_uf(m_df), m_array_util(m), m_stats_calls(0) {} lbool operator()(unsigned num_terms, expr* const* terms, unsigned* class_ids) { params_ref p; @@ -338,7 +336,7 @@ namespace smt { m_solver.push(); assert_relevant(num_terms, terms); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); if (is_sat != l_false) { model_ref model; @@ -374,8 +372,8 @@ namespace smt { stopwatch get_implied_equalities_impl::s_timer; stopwatch get_implied_equalities_impl::s_stats_val_eq_timer; - lbool implied_equalities(smt::kernel& solver, unsigned num_terms, expr* const* terms, unsigned* class_ids) { - get_implied_equalities_impl gi(solver); + lbool implied_equalities(ast_manager& m, solver& solver, unsigned num_terms, expr* const* terms, unsigned* class_ids) { + get_implied_equalities_impl gi(m, solver); return gi(num_terms, terms, class_ids); } }; @@ -552,7 +550,7 @@ namespace smt { m_solver.assert_expr(m.mk_implies(eq_lit, eq)); } m_solver.assert_expr(m.mk_not(m.mk_and(eqs.size(), eqs.c_ptr()))); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); switch(is_sat) { case l_false: for (unsigned i = 0; i + 1 < terms.size(); ++i) { diff --git a/src/smt/smt_implied_equalities.h b/src/smt/smt_implied_equalities.h index 6fc002ff1..ec9b4bd21 100644 --- a/src/smt/smt_implied_equalities.h +++ b/src/smt/smt_implied_equalities.h @@ -23,13 +23,16 @@ Revision History: #ifndef __SMT_IMPLIED_EQUALITIES_H__ #define __SMT_IMPLIED_EQUALITIES_H__ -#include"smt_kernel.h" +#include"smt_solver.h" +#include"lbool.h" +#include"ast.h" namespace smt { lbool implied_equalities( - kernel & solver, + ast_manager & m, + solver & solver, unsigned num_terms, expr* const* terms, unsigned* class_ids); From 2c9b14ada8549152fcaf60f3b9cec0148ea3e960 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 11 Dec 2012 11:37:29 -0800 Subject: [PATCH 55/60] removed private API based on deprecated features Signed-off-by: Leonardo de Moura --- src/api/api_parsers.cpp | 74 ----------------------------------------- src/api/z3_private.h | 32 ------------------ 2 files changed, 106 deletions(-) diff --git a/src/api/api_parsers.cpp b/src/api/api_parsers.cpp index 69ca1fc81..8f6eb1125 100644 --- a/src/api/api_parsers.cpp +++ b/src/api/api_parsers.cpp @@ -252,42 +252,6 @@ extern "C" { // --------------- // Support for SMTLIB2 - class z3_context_solver : public solver_na2as { - api::context & m_ctx; - smt::kernel & ctx() const { return m_ctx.get_smt_kernel(); } - public: - virtual ~z3_context_solver() {} - z3_context_solver(api::context& c) : m_ctx(c) {} - virtual void init_core(ast_manager & m, symbol const & logic) {} - virtual void collect_statistics(statistics & st) const {} - virtual void reset_core() { ctx().reset(); } - virtual void assert_expr(expr * t) { ctx().assert_expr(t); } - virtual void push_core() { ctx().push(); } - virtual void pop_core(unsigned n) { ctx().pop(n); } - virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) { - return ctx().check(num_assumptions, assumptions); - } - virtual void get_unsat_core(ptr_vector & r) { - unsigned sz = ctx().get_unsat_core_size(); - for (unsigned i = 0; i < sz; i++) - r.push_back(ctx().get_unsat_core_expr(i)); - } - virtual void get_model(model_ref & m) { ctx().get_model(m); } - virtual proof * get_proof() { return ctx().get_proof(); } - virtual std::string reason_unknown() const { return ctx().last_failure_as_string(); } - virtual void get_labels(svector & r) { - buffer tmp; - ctx().get_relevant_labels(0, tmp); - r.append(tmp.size(), tmp.c_ptr()); - } - - // These are controlled by the main API - virtual void set_cancel(bool f) { } - void cancel() { set_cancel(true); } - void reset_cancel() { set_cancel(false); } - virtual void set_progress_callback(progress_callback * callback) {} - }; - Z3_ast parse_smtlib2_stream(bool exec, Z3_context c, std::istream& is, unsigned num_sorts, Z3_symbol const sort_names[], @@ -298,9 +262,6 @@ extern "C" { Z3_TRY; cmd_context ctx(false, &(mk_c(c)->m())); ctx.set_ignore_check(true); - if (exec) { - ctx.set_solver(alloc(z3_context_solver, *mk_c(c))); - } for (unsigned i = 0; i < num_decls; ++i) { ctx.insert(to_symbol(decl_names[i]), to_func_decl(decls[i])); } @@ -353,39 +314,4 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } - - Z3_ast Z3_API Z3_exec_smtlib2_string(Z3_context c, Z3_string str, - unsigned num_sorts, - Z3_symbol sort_names[], - Z3_sort sorts[], - unsigned num_decls, - Z3_symbol decl_names[], - Z3_func_decl decls[]) { - Z3_TRY; - cmd_context ctx(false, &(mk_c(c)->m())); - std::string s(str); - std::istringstream is(s); - // No logging for this one, since it private. - return parse_smtlib2_stream(true, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - Z3_CATCH_RETURN(0); - } - - Z3_ast Z3_API Z3_exec_smtlib2_file(Z3_context c, Z3_string file_name, - unsigned num_sorts, - Z3_symbol sort_names[], - Z3_sort sorts[], - unsigned num_decls, - Z3_symbol decl_names[], - Z3_func_decl decls[]) { - Z3_TRY; - std::ifstream is(file_name); - if (!is) { - SET_ERROR_CODE(Z3_PARSER_ERROR); - return 0; - } - // No logging for this one, since it private. - return parse_smtlib2_stream(true, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - Z3_CATCH_RETURN(0); - } - }; diff --git a/src/api/z3_private.h b/src/api/z3_private.h index 17075a6c6..91becd158 100644 --- a/src/api/z3_private.h +++ b/src/api/z3_private.h @@ -36,38 +36,6 @@ extern "C" { Z3_bool Z3_API Z3_get_numeral_rational(__in Z3_context c, __in Z3_ast a, rational& r); - /** - \brief \mlh exec_smtlib2_string c str \endmlh - Parse the given string using the SMT-LIB2 parser and execute its commands. - - It returns a formula comprising of the conjunction of assertions in the scope - (up to push/pop) at the end of the string. - The returned formula is also asserted to the logical context on return. - */ - Z3_ast Z3_API Z3_exec_smtlib2_string(__in Z3_context c, - __in Z3_string str, - __in unsigned num_sorts, - __in_ecount(num_sorts) Z3_symbol sort_names[], - __in_ecount(num_sorts) Z3_sort sorts[], - __in unsigned num_decls, - __in_ecount(num_decls) Z3_symbol decl_names[], - __in_ecount(num_decls) Z3_func_decl decls[] - ); - - /** - \brief Similar to #Z3_exec_smtlib2_string, but reads the commands from a file. - */ - Z3_ast Z3_API Z3_exec_smtlib2_file(__in Z3_context c, - __in Z3_string file_name, - __in unsigned num_sorts, - __in_ecount(num_sorts) Z3_symbol sort_names[], - __in_ecount(num_sorts) Z3_sort sorts[], - __in unsigned num_decls, - __in_ecount(num_decls) Z3_symbol decl_names[], - __in_ecount(num_decls) Z3_func_decl decls[] - ); - - #ifndef CAMLIDL #ifdef __cplusplus }; From 299c5eb94726d4d6855ac2fe1ec865eeadbe9b89 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 11 Dec 2012 16:41:25 -0800 Subject: [PATCH 56/60] make qe-light routine do a little more about traversal Signed-off-by: Nikolaj Bjorner --- src/muz_qe/qe_lite.cpp | 76 +++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/src/muz_qe/qe_lite.cpp b/src/muz_qe/qe_lite.cpp index cced1ed50..df4a55475 100644 --- a/src/muz_qe/qe_lite.cpp +++ b/src/muz_qe/qe_lite.cpp @@ -2104,10 +2104,56 @@ namespace fm { } // namespace fm class qe_lite::impl { +public: + struct elim_cfg : public default_rewriter_cfg { + impl& m_imp; + ast_manager& m; + public: + elim_cfg(impl& i): m_imp(i), m(i.m) {} + + bool reduce_quantifier(quantifier * q, + expr * new_body, + expr * const * new_patterns, + expr * const * new_no_patterns, + expr_ref & result, + proof_ref & result_pr) { + result = new_body; + if (is_forall(q)) { + result = m.mk_not(result); + } + uint_set indices; + for (unsigned i = 0; i < q->get_num_decls(); ++i) { + indices.insert(i); + } + m_imp(indices, true, result); + if (is_forall(q)) { + result = m.mk_not(result); + } + result = m.update_quantifier( + q, + q->get_num_patterns(), new_patterns, + q->get_num_no_patterns(), new_no_patterns, result); + m_imp.m_rewriter(result); + return true; + } + }; + + class elim_star : public rewriter_tpl { + elim_cfg m_cfg; + public: + elim_star(impl& i): + rewriter_tpl(i.m, false, m_cfg), + m_cfg(i) + {} + }; + +private: ast_manager& m; eq::der m_der; fm::fm m_fm; ar::der m_array_der; + elim_star m_elim_star; + th_rewriter m_rewriter; bool has_unique_non_ground(expr_ref_vector const& fmls, unsigned& index) { index = fmls.size(); @@ -2126,7 +2172,13 @@ class qe_lite::impl { } public: - impl(ast_manager& m): m(m), m_der(m), m_fm(m), m_array_der(m) {} + impl(ast_manager& m): + m(m), + m_der(m), + m_fm(m), + m_array_der(m), + m_elim_star(*this), + m_rewriter(m) {} void operator()(app_ref_vector& vars, expr_ref& fml) { if (vars.empty()) { @@ -2165,22 +2217,12 @@ public: else { fml = tmp; } - } + } void operator()(expr_ref& fml, proof_ref& pr) { - if (is_exists(fml)) { - quantifier* q = to_quantifier(fml); - expr_ref body(m); - body = q->get_expr(); - uint_set indices; - for (unsigned i = 0; i < q->get_num_decls(); ++i) { - indices.insert(i); - } - (*this)(indices, true, body); - fml = m.update_quantifier(q, body); - th_rewriter rewriter(m); - rewriter(fml); - } + expr_ref tmp(m); + m_elim_star(fml, tmp, pr); + fml = tmp; } void operator()(uint_set const& index_set, bool index_of_bound, expr_ref& fml) { @@ -2227,6 +2269,8 @@ public: m_der.set_cancel(f); m_array_der.set_cancel(f); m_fm.set_cancel(f); + m_elim_star.set_cancel(f); + m_rewriter.set_cancel(f); } }; @@ -2383,3 +2427,5 @@ public: tactic * mk_qe_lite_tactic(ast_manager & m, params_ref const & p) { return alloc(qe_lite_tactic, m, p); } + +template class rewriter_tpl; From 639f902ad170a96ec534b7c833c0ab3507eaa37a Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 11 Dec 2012 17:01:00 -0800 Subject: [PATCH 57/60] fix bug in difference logic recognizer, assert in proof_util Signed-off-by: Nikolaj Bjorner --- src/muz_qe/pdr_util.cpp | 6 +++++- src/muz_qe/proof_utils.cpp | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/muz_qe/pdr_util.cpp b/src/muz_qe/pdr_util.cpp index fd08b1aad..1ea705e6e 100644 --- a/src/muz_qe/pdr_util.cpp +++ b/src/muz_qe/pdr_util.cpp @@ -1129,7 +1129,11 @@ namespace pdr { if (a.is_numeral(lhs) || a.is_numeral(rhs)) { return test_ineq(e); } - return test_term(lhs) && test_term(rhs); + return + test_term(lhs) && + test_term(rhs) && + !a.is_mul(lhs) && + !a.is_mul(rhs); } bool test_term(expr* e) const { diff --git a/src/muz_qe/proof_utils.cpp b/src/muz_qe/proof_utils.cpp index 75c9cbb15..1e837b578 100644 --- a/src/muz_qe/proof_utils.cpp +++ b/src/muz_qe/proof_utils.cpp @@ -312,9 +312,10 @@ public: }; void proof_utils::reduce_hypotheses(proof_ref& pr) { - class reduce_hypotheses reduce(pr.get_manager()); + ast_manager& m = pr.get_manager(); + class reduce_hypotheses reduce(m); reduce(pr); - SASSERT(is_closed(pr.get_manager(), pr)); + CTRACE("proof_utils", !is_closed(m, pr), tout << mk_pp(pr, m) << "\n";); } class proof_is_closed { From 8198e62cbd0627ef698084a6fe2edf04b55101bc Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 11 Dec 2012 17:47:27 -0800 Subject: [PATCH 58/60] solver factories, cleanup solver API, simplified strategic solver, added combined solver Signed-off-by: Leonardo de Moura --- src/api/api_solver.cpp | 37 +- src/api/api_solver.h | 15 +- src/cmd_context/cmd_context.cpp | 21 +- src/cmd_context/cmd_context.h | 6 +- src/cmd_context/context_params.cpp | 10 +- src/cmd_context/context_params.h | 9 +- src/parsers/smt/smtlib_solver.cpp | 2 +- src/shell/smtlib_frontend.cpp | 6 +- src/smt/smt_solver.cpp | 138 +++----- src/smt/smt_solver.h | 9 +- src/solver/combined_solver.cpp | 289 ++++++++++++++++ src/solver/combined_solver.h | 32 ++ src/solver/combined_solver_params.pyg | 9 + src/solver/solver.h | 31 +- src/solver/solver_na2as.cpp | 29 +- src/solver/solver_na2as.h | 8 +- src/solver/strategic_solver.cpp | 2 + src/solver/strategic_solver.h | 7 +- src/solver/tactic2solver.cpp | 326 ++++++++++-------- src/solver/tactic2solver.h | 96 +----- src/tactic/portfolio/smt_strategic_solver.cpp | 124 ++++--- src/tactic/portfolio/smt_strategic_solver.h | 6 +- 22 files changed, 720 insertions(+), 492 deletions(-) create mode 100644 src/solver/combined_solver.cpp create mode 100644 src/solver/combined_solver.h create mode 100644 src/solver/combined_solver_params.pyg diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index 89bfd9519..6bf184708 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -34,15 +34,15 @@ Revision History: extern "C" { static void init_solver_core(Z3_context c, Z3_solver _s) { - ast_manager & m = mk_c(c)->m(); Z3_solver_ref * s = to_solver(_s); - mk_c(c)->params().init_solver_params(mk_c(c)->m(), *(s->m_solver), s->m_params); - s->m_solver->init(m, s->m_logic); - s->m_initialized = true; + bool proofs_enabled, models_enabled, unsat_core_enabled; + params_ref p = s->m_params; + mk_c(c)->params().get_solver_params(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled); + s->m_solver = (*(s->m_solver_factory))(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled, s->m_logic); } static void init_solver(Z3_context c, Z3_solver s) { - if (!to_solver(s)->m_initialized) + if (to_solver(s)->m_solver.get() == 0) init_solver_core(c, s); } @@ -50,8 +50,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_simple_solver(c); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref); - s->m_solver = mk_smt_solver(); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_smt_solver_factory()); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -62,8 +61,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_solver(c); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref); - s->m_solver = mk_smt_strategic_solver(); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_smt_strategic_solver_factory()); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -74,8 +72,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_solver_for_logic(c, logic); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref, to_symbol(logic)); - s->m_solver = mk_smt_strategic_solver(true /* force solver to use tactics even when auto_config is disabled */); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_smt_strategic_solver_factory(to_symbol(logic))); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -86,8 +83,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_solver_from_tactic(c, t); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref); - s->m_solver = alloc(tactic2solver, to_tactic_ref(t)); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_tactic2solver_factory(to_tactic_ref(t))); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -100,7 +96,12 @@ extern "C" { RESET_ERROR_CODE(); std::ostringstream buffer; param_descrs descrs; + bool initialized = to_solver(s)->m_solver.get() != 0; + if (!initialized) + init_solver(c, s); to_solver_ref(s)->collect_param_descrs(descrs); + if (!initialized) + to_solver(s)->m_solver = 0; descrs.display(buffer); return mk_c(c)->mk_external_string(buffer.str()); Z3_CATCH_RETURN(""); @@ -112,7 +113,12 @@ extern "C" { RESET_ERROR_CODE(); Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref); mk_c(c)->save_object(d); + bool initialized = to_solver(s)->m_solver.get() != 0; + if (!initialized) + init_solver(c, s); to_solver_ref(s)->collect_param_descrs(d->m_descrs); + if (!initialized) + to_solver(s)->m_solver = 0; Z3_param_descrs r = of_param_descrs(d); RETURN_Z3(r); Z3_CATCH_RETURN(0); @@ -122,7 +128,7 @@ extern "C" { Z3_TRY; LOG_Z3_solver_set_params(c, s, p); RESET_ERROR_CODE(); - if (to_solver(s)->m_initialized) { + if (to_solver(s)->m_solver) { bool old_model = to_solver(s)->m_params.get_bool("model", true); bool new_model = to_param_ref(p).get_bool("model", true); if (old_model != new_model) @@ -176,8 +182,7 @@ extern "C" { Z3_TRY; LOG_Z3_solver_reset(c, s); RESET_ERROR_CODE(); - to_solver_ref(s)->reset(); - to_solver(s)->m_initialized = false; + to_solver(s)->m_solver = 0; Z3_CATCH; } diff --git a/src/api/api_solver.h b/src/api/api_solver.h index 1569ef0da..f11c9bfd8 100644 --- a/src/api/api_solver.h +++ b/src/api/api_solver.h @@ -22,17 +22,16 @@ Revision History: #include"solver.h" struct Z3_solver_ref : public api::object { - solver * m_solver; - params_ref m_params; - bool m_initialized; - symbol m_logic; - Z3_solver_ref():m_solver(0), m_initialized(false), m_logic(symbol::null) {} - Z3_solver_ref(symbol const & logic):m_solver(0), m_initialized(false), m_logic(logic) {} - virtual ~Z3_solver_ref() { dealloc(m_solver); } + scoped_ptr m_solver_factory; + ref m_solver; + params_ref m_params; + symbol m_logic; + Z3_solver_ref(solver_factory * f):m_solver_factory(f), m_solver(0), m_logic(symbol::null) {} + virtual ~Z3_solver_ref() {} }; inline Z3_solver_ref * to_solver(Z3_solver s) { return reinterpret_cast(s); } inline Z3_solver of_solver(Z3_solver_ref * s) { return reinterpret_cast(s); } -inline solver * to_solver_ref(Z3_solver s) { return to_solver(s)->m_solver; } +inline solver * to_solver_ref(Z3_solver s) { return to_solver(s)->m_solver.get(); } #endif diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 828cc3a68..e86e56b69 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -582,8 +582,8 @@ void cmd_context::init_manager_core(bool new_manager) { // it prevents clashes with builtin types. insert(pm().mk_plist_decl()); } - if (m_solver) { - init_solver_options(m_solver.get()); + if (m_solver_factory) { + mk_solver(); } m_check_logic.set_logic(m(), m_logic); } @@ -1119,7 +1119,7 @@ void cmd_context::reset(bool finalize) { reset_func_decls(); restore_assertions(0); if (m_solver) - m_solver->reset(); + m_solver = 0; m_pp_env = 0; m_dt_eh = 0; if (m_manager) { @@ -1441,17 +1441,18 @@ void cmd_context::validate_model() { } } -void cmd_context::init_solver_options(solver * s) { +void cmd_context::mk_solver() { + bool proofs_enabled, models_enabled, unsat_core_enabled; params_ref p; - m_params.init_solver_params(m(), *m_solver, p); - m_solver->init(m(), m_logic); + m_params.get_solver_params(m(), p, proofs_enabled, models_enabled, unsat_core_enabled); + m_solver = (*m_solver_factory)(m(), p, proofs_enabled, models_enabled, unsat_core_enabled, m_logic); } -void cmd_context::set_solver(solver * s) { +void cmd_context::set_solver_factory(solver_factory * f) { + m_solver_factory = f; m_check_sat_result = 0; - m_solver = s; - if (has_manager() && s != 0) { - init_solver_options(s); + if (has_manager() && f != 0) { + mk_solver(); // assert formulas and create scopes in the new solver. unsigned lim = 0; svector::iterator it = m_scopes.begin(); diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 2edc87ca6..63e5e7040 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -185,6 +185,7 @@ protected: }; svector m_scopes; + scoped_ptr m_solver_factory; ref m_solver; ref m_check_sat_result; @@ -243,7 +244,7 @@ protected: void print_unsupported_msg() { regular_stream() << "unsupported" << std::endl; } void print_unsupported_info(symbol const& s) { if (s != symbol::null) diagnostic_stream() << "; " << s << std::endl;} - void init_solver_options(solver * s); + void mk_solver(); public: cmd_context(bool main_ctx = true, ast_manager * m = 0, symbol const & l = symbol::null); @@ -289,8 +290,7 @@ public: pdecl_manager & pm() const { if (!m_pmanager) const_cast(this)->init_manager(); return *m_pmanager; } sexpr_manager & sm() const { if (!m_sexpr_manager) const_cast(this)->m_sexpr_manager = alloc(sexpr_manager); return *m_sexpr_manager; } - void set_solver(solver * s); - solver * get_solver() const { return m_solver.get(); } + void set_solver_factory(solver_factory * s); void set_check_sat_result(check_sat_result * r) { m_check_sat_result = r; } check_sat_result * get_check_sat_result() const { return m_check_sat_result.get(); } check_sat_state cs_state() const; diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index 6d9222a37..2752967dd 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -131,11 +131,11 @@ params_ref context_params::merge_default_params(params_ref const & p) { } } -void context_params::init_solver_params(ast_manager & m, solver & s, params_ref const & p) { - s.set_produce_proofs(m.proofs_enabled() && m_proof); - s.set_produce_models(p.get_bool("model", m_model)); - s.set_produce_unsat_cores(p.get_bool("unsat_core", m_unsat_core)); - s.updt_params(merge_default_params(p)); +void context_params::get_solver_params(ast_manager const & m, params_ref & p, bool & proofs_enabled, bool & models_enabled, bool & unsat_core_enabled) { + proofs_enabled = m.proofs_enabled() && p.get_bool("proof", m_proof); + models_enabled = p.get_bool("model", m_model); + unsat_core_enabled = p.get_bool("unsat_core", m_unsat_core); + p = merge_default_params(p); } ast_manager * context_params::mk_ast_manager() { diff --git a/src/cmd_context/context_params.h b/src/cmd_context/context_params.h index dd60b9616..526b4f517 100644 --- a/src/cmd_context/context_params.h +++ b/src/cmd_context/context_params.h @@ -22,7 +22,6 @@ Notes: #include"params.h" class ast_manager; -class solver; class context_params { void set_bool(bool & opt, char const * param, char const * value); @@ -50,13 +49,9 @@ public: */ /** - \brief Goodie for updating the solver params - based on the configuration of the context_params object. - - This method is used when creating solvers from the - cmd_context and API. + \brief Goodies for extracting parameters for creating a solver object. */ - void init_solver_params(ast_manager & m, solver & s, params_ref const & p); + void get_solver_params(ast_manager const & m, params_ref & p, bool & proofs_enabled, bool & models_enabled, bool & unsat_core_enabled); /** \brief Include in p parameters derived from this context_params. diff --git a/src/parsers/smt/smtlib_solver.cpp b/src/parsers/smt/smtlib_solver.cpp index ef28216bf..7c8572ad8 100644 --- a/src/parsers/smt/smtlib_solver.cpp +++ b/src/parsers/smt/smtlib_solver.cpp @@ -86,7 +86,7 @@ namespace smtlib { benchmark.add_formula(m_ast_manager.mk_true()); } m_ctx = alloc(cmd_context, true, &m_ast_manager, benchmark.get_logic()); - m_ctx->set_solver(mk_smt_strategic_solver(false)); + m_ctx->set_solver_factory(mk_smt_strategic_solver_factory()); theory::expr_iterator fit = benchmark.begin_formulas(); theory::expr_iterator fend = benchmark.end_formulas(); for (; fit != fend; ++fit) diff --git a/src/shell/smtlib_frontend.cpp b/src/shell/smtlib_frontend.cpp index 1551329c6..ef0b4ad6b 100644 --- a/src/shell/smtlib_frontend.cpp +++ b/src/shell/smtlib_frontend.cpp @@ -30,9 +30,6 @@ Revision History: #include"subpaving_cmds.h" #include"smt_strategic_solver.h" -#include"tactic2solver.h" -#include"qfnra_nlsat_tactic.h" - extern bool g_display_statistics; extern void display_config(); static clock_t g_start_time; @@ -98,8 +95,7 @@ unsigned read_smtlib2_commands(char const * file_name) { signal(SIGINT, on_ctrl_c); cmd_context ctx; - solver * s = mk_smt_strategic_solver(false); - ctx.set_solver(s); + ctx.set_solver_factory(mk_smt_strategic_solver_factory()); install_dl_cmds(ctx); install_dbg_cmds(ctx); diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp index e8c1c6698..1fbb58847 100644 --- a/src/smt/smt_solver.cpp +++ b/src/smt/smt_solver.cpp @@ -25,166 +25,114 @@ namespace smt { class solver : public solver_na2as { smt_params m_params; - smt::kernel * m_context; + smt::kernel m_context; progress_callback * m_callback; + symbol m_logic; public: - solver():m_context(0), m_callback(0) {} - + solver(ast_manager & m, params_ref const & p, symbol const & l): + solver_na2as(m), + m_params(p), + m_context(m, m_params) { + m_logic = l; + if (m_logic != symbol::null) + m_context.set_logic(m_logic); + } + virtual ~solver() { - if (m_context != 0) - dealloc(m_context); } virtual void updt_params(params_ref const & p) { m_params.updt_params(p); - if (m_context == 0) - return; - m_context->updt_params(p); + m_context.updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - if (m_context == 0) { - ast_manager m; - reg_decl_plugins(m); - smt::kernel s(m, m_params); - s.collect_param_descrs(r); - } - else { - m_context->collect_param_descrs(r); - } - } - - virtual void init_core(ast_manager & m, symbol const & logic) { - reset(); - // We can throw exceptions when creating a smt::kernel object - // So, we should create the smt::kernel outside of the criticial section - // block. OMP does not allow exceptions to cross critical section boundaries. - smt::kernel * new_kernel = alloc(smt::kernel, m, m_params); - #pragma omp critical (solver) - { - m_context = new_kernel; - if (m_callback) - m_context->set_progress_callback(m_callback); - } - if (logic != symbol::null) - m_context->set_logic(logic); + m_context.collect_param_descrs(r); } virtual void collect_statistics(statistics & st) const { - if (m_context == 0) { - return; - } - else { - m_context->collect_statistics(st); - } - } - - virtual void reset_core() { - if (m_context != 0) { - #pragma omp critical (solver) - { - dealloc(m_context); - m_context = 0; - } - } - } - - // An exception may be thrown when creating a smt::kernel. - // So, there is no guarantee that m_context != 0 when - // using smt_solver from the SMT 2.0 command line frontend. - void check_context() const { - if (m_context == 0) - throw default_exception("Z3 failed to create solver, check previous error messages"); + m_context.collect_statistics(st); } virtual void assert_expr(expr * t) { - check_context(); - m_context->assert_expr(t); + m_context.assert_expr(t); } virtual void push_core() { - check_context(); - m_context->push(); + m_context.push(); } virtual void pop_core(unsigned n) { - check_context(); - m_context->pop(n); + m_context.pop(n); } virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) { - check_context(); TRACE("solver_na2as", tout << "smt_solver::check_sat_core: " << num_assumptions << "\n";); - return m_context->check(num_assumptions, assumptions); + return m_context.check(num_assumptions, assumptions); } virtual void get_unsat_core(ptr_vector & r) { - check_context(); - unsigned sz = m_context->get_unsat_core_size(); + unsigned sz = m_context.get_unsat_core_size(); for (unsigned i = 0; i < sz; i++) - r.push_back(m_context->get_unsat_core_expr(i)); + r.push_back(m_context.get_unsat_core_expr(i)); } virtual void get_model(model_ref & m) { - check_context(); - m_context->get_model(m); + m_context.get_model(m); } virtual proof * get_proof() { - check_context(); - return m_context->get_proof(); + return m_context.get_proof(); } virtual std::string reason_unknown() const { - check_context(); - return m_context->last_failure_as_string(); + return m_context.last_failure_as_string(); } virtual void get_labels(svector & r) { - check_context(); buffer tmp; - m_context->get_relevant_labels(0, tmp); + m_context.get_relevant_labels(0, tmp); r.append(tmp.size(), tmp.c_ptr()); } virtual void set_cancel(bool f) { -#pragma omp critical (solver) - { - if (m_context) - m_context->set_cancel(f); - } + m_context.set_cancel(f); } virtual void set_progress_callback(progress_callback * callback) { m_callback = callback; - if (m_context) - m_context->set_progress_callback(callback); + m_context.set_progress_callback(callback); } virtual unsigned get_num_assertions() const { - if (m_context) - return m_context->size(); - else - return 0; + return m_context.size(); } virtual expr * get_assertion(unsigned idx) const { - SASSERT(m_context); SASSERT(idx < get_num_assertions()); - return m_context->get_formulas()[idx]; + return m_context.get_formulas()[idx]; } virtual void display(std::ostream & out) const { - if (m_context) - m_context->display(out); - else - out << "(solver)"; + m_context.display(out); } }; }; -solver * mk_smt_solver() { - return alloc(smt::solver); +solver * mk_smt_solver(ast_manager & m, params_ref const & p, symbol const & logic) { + return alloc(smt::solver, m, p, logic); } + +class smt_solver_factory : public solver_factory { +public: + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + return mk_smt_solver(m, p, logic); + } +}; + +solver_factory * mk_smt_solver_factory() { + return alloc(smt_solver_factory); +} + diff --git a/src/smt/smt_solver.h b/src/smt/smt_solver.h index e9af9aafa..81c9a1319 100644 --- a/src/smt/smt_solver.h +++ b/src/smt/smt_solver.h @@ -21,8 +21,13 @@ Notes: #ifndef _SMT_SOLVER_H_ #define _SMT_SOLVER_H_ -class solver; +#include"ast.h" +#include"params.h" -solver * mk_smt_solver(); +class solver; +class solver_factory; + +solver * mk_smt_solver(ast_manager & m, params_ref const & p, symbol const & logic); +solver_factory * mk_smt_solver_factory(); #endif diff --git a/src/solver/combined_solver.cpp b/src/solver/combined_solver.cpp new file mode 100644 index 000000000..cd4191e76 --- /dev/null +++ b/src/solver/combined_solver.cpp @@ -0,0 +1,289 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + combined_solver.cpp + +Abstract: + + Implements the solver API by combining two solvers. + + This is a replacement for the strategic_solver class. + +Author: + + Leonardo (leonardo) 2012-12-11 + +Notes: + +--*/ +#include"solver.h" +#include"scoped_timer.h" +#include"combined_solver_params.hpp" +#define PS_VB_LVL 15 + +/** + \brief Implementation of the solver API that combines two given solvers. + + The combined solver has two modes: + - non-incremental + - incremental + In non-incremental mode, the first solver is used. + In incremental mode, the second one is used. + + A timeout for the second solver can be specified. + If the timeout is reached, then the first solver is executed. + + The object switches to incremental when: + - push is used + - assertions are peformed after a check_sat + - parameter ignore_solver1==false +*/ +class combined_solver : public solver { +public: + // Behavior when the incremental solver returns unknown. + enum inc_unknown_behavior { + IUB_RETURN_UNDEF, // just return unknown + IUB_USE_TACTIC_IF_QF, // invoke tactic if problem is quantifier free + IUB_USE_TACTIC // invoke tactic + }; + +private: + bool m_inc_mode; + bool m_check_sat_executed; + bool m_use_solver1_results; + ref m_solver1; + ref m_solver2; + + bool m_ignore_solver1; + inc_unknown_behavior m_inc_unknown_behavior; + unsigned m_inc_timeout; + + void switch_inc_mode() { + m_inc_mode = true; + } + + struct aux_timeout_eh : public event_handler { + solver * m_solver; + volatile bool m_canceled; + aux_timeout_eh(solver * s):m_solver(s), m_canceled(false) {} + virtual void operator()() { + m_solver->cancel(); + m_canceled = true; + } + }; + + void updt_local_params(params_ref const & _p) { + combined_solver_params p(_p); + m_inc_timeout = p.solver2_timeout(); + m_ignore_solver1 = p.ignore_solver1(); + m_inc_unknown_behavior = static_cast(p.solver2_unknown()); + } + + bool has_quantifiers() const { + unsigned sz = get_num_assertions(); + for (unsigned i = 0; i < sz; i++) { + if (::has_quantifiers(get_assertion(i))) + return true; + } + return false; + } + + bool use_solver1_when_undef() const { + switch (m_inc_unknown_behavior) { + case IUB_RETURN_UNDEF: return false; + case IUB_USE_TACTIC_IF_QF: return !has_quantifiers(); + case IUB_USE_TACTIC: return true; + default: + UNREACHABLE(); + return false; + } + } + +public: + combined_solver(solver * s1, solver * s2, params_ref const & p) { + m_solver1 = s1; + m_solver2 = s2; + updt_local_params(p); + m_inc_mode = false; + m_check_sat_executed = false; + m_use_solver1_results = true; + } + + virtual void updt_params(params_ref const & p) { + m_solver1->updt_params(p); + m_solver2->updt_params(p); + updt_local_params(p); + } + + virtual void collect_param_descrs(param_descrs & r) { + m_solver1->collect_param_descrs(r); + m_solver2->collect_param_descrs(r); + combined_solver_params::collect_param_descrs(r); + } + + virtual void set_produce_models(bool f) { + m_solver1->set_produce_models(f); + m_solver2->set_produce_models(f); + } + + virtual void assert_expr(expr * t) { + if (m_check_sat_executed) + switch_inc_mode(); + m_solver1->assert_expr(t); + m_solver2->assert_expr(t); + } + + virtual void assert_expr(expr * t, expr * a) { + if (m_check_sat_executed) + switch_inc_mode(); + m_solver1->assert_expr(t, a); + m_solver2->assert_expr(t, a); + } + + virtual void push() { + switch_inc_mode(); + m_solver1->push(); + m_solver2->push(); + } + + virtual void pop(unsigned n) { + switch_inc_mode(); + m_solver1->pop(n); + m_solver2->pop(n); + } + + virtual unsigned get_scope_level() const { + return m_solver1->get_scope_level(); + } + + virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) { + m_check_sat_executed = true; + + if (num_assumptions > 0 || // assumptions were provided + m_ignore_solver1) { + // must use incremental solver + switch_inc_mode(); + m_use_solver1_results = false; + return m_solver2->check_sat(num_assumptions, assumptions); + } + + if (m_inc_mode) { + if (m_inc_timeout == UINT_MAX) { + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (without a timeout)\")\n";); + lbool r = m_solver2->check_sat(0, 0); + if (r != l_undef || !use_solver1_when_undef()) { + m_use_solver1_results = false; + return r; + } + } + else { + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (with timeout)\")\n";); + aux_timeout_eh eh(m_solver2.get()); + lbool r; + { + scoped_timer timer(m_inc_timeout, &eh); + r = m_solver2->check_sat(0, 0); + } + if ((r != l_undef || !use_solver1_when_undef()) && !eh.m_canceled) { + m_use_solver1_results = false; + return r; + } + } + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"solver 2 failed, trying solver1\")\n";); + } + + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 1\")\n";); + m_use_solver1_results = true; + return m_solver1->check_sat(0, 0); + } + + virtual void set_cancel(bool f) { + m_solver1->set_cancel(f); + m_solver2->set_cancel(f); + } + + virtual void set_progress_callback(progress_callback * callback) { + m_solver1->set_progress_callback(callback); + m_solver2->set_progress_callback(callback); + } + + virtual unsigned get_num_assertions() const { + return m_solver1->get_num_assertions(); + } + + virtual expr * get_assertion(unsigned idx) const { + return m_solver1->get_assertion(idx); + } + + virtual void display(std::ostream & out) const { + m_solver1->display(out); + } + + virtual void collect_statistics(statistics & st) const { + if (m_use_solver1_results) + m_solver1->collect_statistics(st); + else + m_solver2->collect_statistics(st); + } + + virtual void get_unsat_core(ptr_vector & r) { + if (m_use_solver1_results) + m_solver1->get_unsat_core(r); + else + m_solver2->get_unsat_core(r); + } + + virtual void get_model(model_ref & m) { + if (m_use_solver1_results) + m_solver1->get_model(m); + else + m_solver2->get_model(m); + } + + virtual proof * get_proof() { + if (m_use_solver1_results) + return m_solver1->get_proof(); + else + return m_solver2->get_proof(); + } + + virtual std::string reason_unknown() const { + if (m_use_solver1_results) + return m_solver1->reason_unknown(); + else + return m_solver2->reason_unknown(); + } + + virtual void get_labels(svector & r) { + if (m_use_solver1_results) + return m_solver1->get_labels(r); + else + return m_solver2->get_labels(r); + } + +}; + + +solver * mk_combined_solver(solver * s1, solver * s2, params_ref const & p) { + return alloc(combined_solver, s1, s2, p); +} + +class combined_solver_factory : public solver_factory { + scoped_ptr m_f1; + scoped_ptr m_f2; +public: + combined_solver_factory(solver_factory * f1, solver_factory * f2):m_f1(f1), m_f2(f2) {} + virtual ~combined_solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + return mk_combined_solver((*m_f1)(m, p, proofs_enabled, models_enabled, unsat_core_enabled, logic), + (*m_f2)(m, p, proofs_enabled, models_enabled, unsat_core_enabled, logic), + p); + } +}; + +solver_factory * mk_combined_solver_factory(solver_factory * f1, solver_factory * f2) { + return alloc(combined_solver_factory, f1, f2); +} diff --git a/src/solver/combined_solver.h b/src/solver/combined_solver.h new file mode 100644 index 000000000..2ccace7f0 --- /dev/null +++ b/src/solver/combined_solver.h @@ -0,0 +1,32 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + combined_solver.cpp + +Abstract: + + Implements the solver API by combining two solvers. + + This is a replacement for the strategic_solver class. + +Author: + + Leonardo (leonardo) 2012-12-11 + +Notes: + +--*/ +#ifndef _COMBINED_SOLVER_H_ +#define _COMBINED_SOLVER_H_ + +#include"params.h" + +class solver; +class solver_factory; + +solver * mk_combined_solver(solver * s1, solver * s2, params_ref const & p); +solver_factory * mk_combined_solver_factory(solver_factory * f1, solver_factory * f2); + +#endif diff --git a/src/solver/combined_solver_params.pyg b/src/solver/combined_solver_params.pyg new file mode 100644 index 000000000..7e1635c16 --- /dev/null +++ b/src/solver/combined_solver_params.pyg @@ -0,0 +1,9 @@ +def_module_params('combined_solver', + description='combines two solvers: non-incremental (solver1) and incremental (solver2)', + export=True, + params=(('solver2_timeout', UINT, UINT_MAX, "fallback to solver 1 after timeout even when in incremental model"), + ('ignore_solver1', BOOL, False, "if true, solver 2 is always used"), + ('solver2_unknown', UINT, 1, "what should be done when solver 2 returns unknown: 0 - just return unknown, 1 - execute solver 1 if quantifier free problem, 2 - execute solver 1") + )) + + diff --git a/src/solver/solver.h b/src/solver/solver.h index 5cd3da52b..e047bace1 100644 --- a/src/solver/solver.h +++ b/src/solver/solver.h @@ -23,6 +23,14 @@ Notes: #include"progress_callback.h" #include"params.h" +class solver; + +class solver_factory { +public: + virtual ~solver_factory() {} + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) = 0; +}; + /** \brief Abstract interface for making solvers available in the Z3 API and front-ends such as SMT 2.0 and (legacy) SMT 1.0. @@ -34,7 +42,6 @@ Notes: - statistics - results based on check_sat_result API - interruption (set_cancel) - - resets */ class solver : public check_sat_result { public: @@ -50,12 +57,6 @@ public: */ virtual void collect_param_descrs(param_descrs & r) {} - /** - \brief Enable/Disable proof production for this solver object. - - It is invoked before init(m, logic). - */ - virtual void set_produce_proofs(bool f) {} /** \brief Enable/Disable model generation for this solver object. @@ -63,23 +64,7 @@ public: The user may optionally invoke it after init(m, logic). */ virtual void set_produce_models(bool f) {} - /** - \brief Enable/Disable unsat core generation for this solver object. - - It is invoked before init(m, logic). - */ - virtual void set_produce_unsat_cores(bool f) {} - /** - \brief Initialize the solver object with the given ast_manager and logic. - */ - virtual void init(ast_manager & m, symbol const & logic) = 0; - - /** - \brief Reset the solver internal state. All assertions should be removed. - */ - virtual void reset() = 0; - /** \brief Add a new formula to the assertion stack. */ diff --git a/src/solver/solver_na2as.cpp b/src/solver/solver_na2as.cpp index e71a9873b..9889b5872 100644 --- a/src/solver/solver_na2as.cpp +++ b/src/solver/solver_na2as.cpp @@ -22,8 +22,8 @@ Notes: #include"solver_na2as.h" #include"ast_smt2_pp.h" -solver_na2as::solver_na2as() { - m_manager = 0; +solver_na2as::solver_na2as(ast_manager & m): + m_manager(m) { } solver_na2as::~solver_na2as() { @@ -35,23 +35,16 @@ void solver_na2as::assert_expr(expr * t, expr * a) { assert_expr(t); } else { - SASSERT(m_manager != 0); SASSERT(is_uninterp_const(a)); - SASSERT(m_manager->is_bool(a)); - TRACE("solver_na2as", tout << "asserting\n" << mk_ismt2_pp(t, *m_manager) << "\n" << mk_ismt2_pp(a, *m_manager) << "\n";); - m_manager->inc_ref(a); + SASSERT(m_manager.is_bool(a)); + TRACE("solver_na2as", tout << "asserting\n" << mk_ismt2_pp(t, m_manager) << "\n" << mk_ismt2_pp(a, m_manager) << "\n";); + m_manager.inc_ref(a); m_assumptions.push_back(a); - expr_ref new_t(*m_manager); - new_t = m_manager->mk_implies(a, t); + expr_ref new_t(m_manager); + new_t = m_manager.mk_implies(a, t); assert_expr(new_t); } } - -void solver_na2as::init(ast_manager & m, symbol const & logic) { - SASSERT(m_assumptions.empty()); - m_manager = &m; - init_core(m, logic); -} struct append_assumptions { ptr_vector & m_assumptions; @@ -89,9 +82,9 @@ void solver_na2as::pop(unsigned n) { } void solver_na2as::restore_assumptions(unsigned old_sz) { - SASSERT(old_sz == 0 || m_manager != 0); + SASSERT(old_sz == 0); for (unsigned i = old_sz; i < m_assumptions.size(); i++) { - m_manager->dec_ref(m_assumptions[i]); + m_manager.dec_ref(m_assumptions[i]); } m_assumptions.shrink(old_sz); } @@ -100,7 +93,3 @@ unsigned solver_na2as::get_scope_level() const { return m_scopes.size(); } -void solver_na2as::reset() { - reset_core(); - restore_assumptions(0); -} diff --git a/src/solver/solver_na2as.h b/src/solver/solver_na2as.h index eb12479fc..15750344a 100644 --- a/src/solver/solver_na2as.h +++ b/src/solver/solver_na2as.h @@ -25,30 +25,26 @@ Notes: #include"solver.h" class solver_na2as : public solver { - ast_manager * m_manager; + ast_manager & m_manager; ptr_vector m_assumptions; unsigned_vector m_scopes; void restore_assumptions(unsigned old_sz); public: - solver_na2as(); + solver_na2as(ast_manager & m); virtual ~solver_na2as(); virtual void assert_expr(expr * t, expr * a); virtual void assert_expr(expr * t) = 0; // Subclasses of solver_na2as should redefine the following *_core methods instead of these ones. - virtual void init(ast_manager & m, symbol const & logic); virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions); virtual void push(); virtual void pop(unsigned n); virtual unsigned get_scope_level() const; - virtual void reset(); protected: - virtual void init_core(ast_manager & m, symbol const & logic) = 0; virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) = 0; virtual void push_core() = 0; virtual void pop_core(unsigned n) = 0; - virtual void reset_core() = 0; }; diff --git a/src/solver/strategic_solver.cpp b/src/solver/strategic_solver.cpp index 40d77066e..fa7458ea3 100644 --- a/src/solver/strategic_solver.cpp +++ b/src/solver/strategic_solver.cpp @@ -16,6 +16,7 @@ Author: Notes: --*/ +#if 0 #include"strategic_solver.h" #include"scoped_timer.h" #include"ast_smt2_pp.h" @@ -526,6 +527,7 @@ void strategic_solver::display(std::ostream & out) const { } } +#endif diff --git a/src/solver/strategic_solver.h b/src/solver/strategic_solver.h index 1883a88cd..0bae8b254 100644 --- a/src/solver/strategic_solver.h +++ b/src/solver/strategic_solver.h @@ -61,7 +61,8 @@ private: bool m_force_tactic; // use tactics even when auto_config = false bool m_inc_mode; bool m_check_sat_executed; - scoped_ptr m_inc_solver; + scoped_ptr m_inc_solver_factory; + ref m_inc_solver; unsigned m_inc_solver_timeout; inc_unknown_behavior m_inc_unknown_behavior; scoped_ptr m_default_fct; @@ -107,12 +108,12 @@ private: bool use_tactic_when_undef() const; public: - strategic_solver(); + strategic_solver(ast_manager & m, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic); ~strategic_solver(); ast_manager & m() const { SASSERT(m_manager); return *m_manager; } - void set_inc_solver(solver * s); + void set_inc_solver_factory(solver_factory * s); void set_inc_solver_timeout(unsigned timeout); void set_default_tactic(tactic_factory * fct); void set_tactic_for(symbol const & logic, tactic_factory * fct); diff --git a/src/solver/tactic2solver.cpp b/src/solver/tactic2solver.cpp index e630f9c78..1268fbcea 100644 --- a/src/solver/tactic2solver.cpp +++ b/src/solver/tactic2solver.cpp @@ -19,96 +19,115 @@ Author: Notes: --*/ -#include"tactic2solver.h" +#include"solver_na2as.h" +#include"tactic.h" #include"ast_smt2_pp.h" -tactic2solver_core::ctx::ctx(ast_manager & m, symbol const & logic): - m_logic(logic), +/** + \brief Simulates the incremental solver interface using a tactic. + + Every query will be solved from scratch. So, this is not a good + option for applications trying to solve many easy queries that a + similar to each other. +*/ +class tactic2solver : public solver_na2as { + expr_ref_vector m_assertions; + unsigned_vector m_scopes; + ref m_result; + tactic_ref m_tactic; + symbol m_logic; + params_ref m_params; + bool m_produce_models; + bool m_produce_proofs; + bool m_produce_unsat_cores; +public: + tactic2solver(ast_manager & m, tactic * t, params_ref const & p, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic); + virtual ~tactic2solver(); + + virtual void updt_params(params_ref const & p); + virtual void collect_param_descrs(param_descrs & r); + + virtual void set_produce_models(bool f) { m_produce_models = f; } + + virtual void assert_expr(expr * t); + + virtual void push_core(); + virtual void pop_core(unsigned n); + virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions); + + virtual void set_cancel(bool f); + + virtual void collect_statistics(statistics & st) const; + virtual void get_unsat_core(ptr_vector & r); + virtual void get_model(model_ref & m); + virtual proof * get_proof(); + virtual std::string reason_unknown() const; + virtual void get_labels(svector & r) {} + + virtual void set_progress_callback(progress_callback * callback) {} + + virtual unsigned get_num_assertions() const; + virtual expr * get_assertion(unsigned idx) const; + + virtual void display(std::ostream & out) const; +}; + +tactic2solver::tactic2solver(ast_manager & m, tactic * t, params_ref const & p, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic): + solver_na2as(m), m_assertions(m) { + + m_tactic = t; + m_logic = logic; + m_params = p; + + m_produce_models = produce_models; + m_produce_proofs = produce_proofs; + m_produce_unsat_cores = produce_unsat_cores; } -tactic2solver_core::~tactic2solver_core() { +tactic2solver::~tactic2solver() { } -void tactic2solver_core::init_core(ast_manager & m, symbol const & logic) { - m_ctx = alloc(ctx, m, logic); -} - -void tactic2solver_core::updt_params(params_ref const & p) { +void tactic2solver::updt_params(params_ref const & p) { m_params = p; } -void tactic2solver_core::collect_param_descrs(param_descrs & r) { - if (m_ctx) { - if (!m_ctx->m_tactic) { - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = get_tactic(m_ctx->m(), m_params); - } - - if (m_ctx->m_tactic) { - m_ctx->m_tactic->collect_param_descrs(r); - } - - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = 0; - } - } - else { - m_ctx->m_tactic->collect_param_descrs(r); - } - } +void tactic2solver::collect_param_descrs(param_descrs & r) { + if (m_tactic.get()) + m_tactic->collect_param_descrs(r); } -void tactic2solver_core::reset_core() { - SASSERT(m_ctx); - m_ctx->m_assertions.reset(); - m_ctx->m_scopes.reset(); - m_ctx->m_result = 0; +void tactic2solver::assert_expr(expr * t) { + m_assertions.push_back(t); + m_result = 0; } -void tactic2solver_core::assert_expr(expr * t) { - SASSERT(m_ctx); - m_ctx->m_assertions.push_back(t); - m_ctx->m_result = 0; +void tactic2solver::push_core() { + m_scopes.push_back(m_assertions.size()); + m_result = 0; } -void tactic2solver_core::push_core() { - SASSERT(m_ctx); - m_ctx->m_scopes.push_back(m_ctx->m_assertions.size()); - m_ctx->m_result = 0; +void tactic2solver::pop_core(unsigned n) { + unsigned new_lvl = m_scopes.size() - n; + unsigned old_sz = m_scopes[new_lvl]; + m_assertions.shrink(old_sz); + m_scopes.shrink(new_lvl); + m_result = 0; } -void tactic2solver_core::pop_core(unsigned n) { - SASSERT(m_ctx); - unsigned new_lvl = m_ctx->m_scopes.size() - n; - unsigned old_sz = m_ctx->m_scopes[new_lvl]; - m_ctx->m_assertions.shrink(old_sz); - m_ctx->m_scopes.shrink(new_lvl); - m_ctx->m_result = 0; -} - -lbool tactic2solver_core::check_sat_core(unsigned num_assumptions, expr * const * assumptions) { - SASSERT(m_ctx); - ast_manager & m = m_ctx->m(); - params_ref p = m_params; - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = get_tactic(m, p); - if (m_ctx->m_tactic) { - m_ctx->m_result = alloc(simple_check_sat_result, m); - } - } - if (!m_ctx->m_tactic) - return l_undef; - tactic & t = *(m_ctx->m_tactic); - simple_check_sat_result & result = *(m_ctx->m_result); +lbool tactic2solver::check_sat_core(unsigned num_assumptions, expr * const * assumptions) { + if (m_tactic.get() == 0) + return l_false; + ast_manager & m = m_assertions.m(); + m_result = alloc(simple_check_sat_result, m); + m_tactic->cleanup(); + m_tactic->updt_params(m_params); + m_tactic->set_logic(m_logic); goal_ref g = alloc(goal, m, m_produce_proofs, m_produce_models, m_produce_unsat_cores); - t.set_logic(m_ctx->m_logic); - unsigned sz = m_ctx->m_assertions.size(); + + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz; i++) { - g->assert_expr(m_ctx->m_assertions.get(i)); + g->assert_expr(m_assertions.get(i)); } for (unsigned i = 0; i < num_assumptions; i++) { g->assert_expr(assumptions[i], m.mk_asserted(assumptions[i]), m.mk_leaf(assumptions[i])); @@ -119,17 +138,17 @@ lbool tactic2solver_core::check_sat_core(unsigned num_assumptions, expr * const expr_dependency_ref core(m); std::string reason_unknown = "unknown"; try { - switch (::check_sat(t, g, md, pr, core, reason_unknown)) { + switch (::check_sat(*m_tactic, g, md, pr, core, reason_unknown)) { case l_true: - result.set_status(l_true); + m_result->set_status(l_true); break; case l_false: - result.set_status(l_false); + m_result->set_status(l_false); break; default: - result.set_status(l_undef); + m_result->set_status(l_undef); if (reason_unknown != "") - result.m_unknown = reason_unknown; + m_result->m_unknown = reason_unknown; break; } } @@ -137,112 +156,115 @@ lbool tactic2solver_core::check_sat_core(unsigned num_assumptions, expr * const throw ex; } catch (z3_exception & ex) { - TRACE("tactic2solver_core", tout << "exception: " << ex.msg() << "\n";); - result.set_status(l_undef); - result.m_unknown = ex.msg(); + TRACE("tactic2solver", tout << "exception: " << ex.msg() << "\n";); + m_result->set_status(l_undef); + m_result->m_unknown = ex.msg(); } - t.collect_statistics(result.m_stats); - result.m_model = md; - result.m_proof = pr; + m_tactic->collect_statistics(m_result->m_stats); + m_result->m_model = md; + m_result->m_proof = pr; if (m_produce_unsat_cores) { ptr_vector core_elems; m.linearize(core, core_elems); - result.m_core.append(core_elems.size(), core_elems.c_ptr()); + m_result->m_core.append(core_elems.size(), core_elems.c_ptr()); } - - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = 0; - } - return result.status(); + m_tactic->cleanup(); + return m_result->status(); } -void tactic2solver_core::set_cancel(bool f) { - #pragma omp critical (tactic2solver_core) - { - if (m_ctx && m_ctx->m_tactic) - m_ctx->m_tactic->set_cancel(f); - } +void tactic2solver::set_cancel(bool f) { + if (m_tactic.get()) + m_tactic->set_cancel(f); } -void tactic2solver_core::collect_statistics(statistics & st) const { - if (m_ctx->m_result.get()) - m_ctx->m_result->collect_statistics(st); +void tactic2solver::collect_statistics(statistics & st) const { + if (m_result.get()) + m_result->collect_statistics(st); } -void tactic2solver_core::get_unsat_core(ptr_vector & r) { - if (m_ctx->m_result.get()) - m_ctx->m_result->get_unsat_core(r); +void tactic2solver::get_unsat_core(ptr_vector & r) { + if (m_result.get()) + m_result->get_unsat_core(r); } -void tactic2solver_core::get_model(model_ref & m) { - if (m_ctx->m_result.get()) - m_ctx->m_result->get_model(m); +void tactic2solver::get_model(model_ref & m) { + if (m_result.get()) + m_result->get_model(m); } -proof * tactic2solver_core::get_proof() { - if (m_ctx->m_result.get()) - return m_ctx->m_result->get_proof(); +proof * tactic2solver::get_proof() { + if (m_result.get()) + return m_result->get_proof(); else return 0; } -std::string tactic2solver_core::reason_unknown() const { - if (m_ctx->m_result.get()) - return m_ctx->m_result->reason_unknown(); +std::string tactic2solver::reason_unknown() const { + if (m_result.get()) + return m_result->reason_unknown(); else return std::string("unknown"); } -unsigned tactic2solver_core::get_num_assertions() const { - if (m_ctx) - return m_ctx->m_assertions.size(); - else - return 0; +unsigned tactic2solver::get_num_assertions() const { + return m_assertions.size(); } -expr * tactic2solver_core::get_assertion(unsigned idx) const { - SASSERT(m_ctx); - return m_ctx->m_assertions.get(idx); +expr * tactic2solver::get_assertion(unsigned idx) const { + return m_assertions.get(idx); } -void tactic2solver_core::display(std::ostream & out) const { - if (m_ctx) { - ast_manager & m = m_ctx->m_assertions.m(); - unsigned num = m_ctx->m_assertions.size(); - out << "(solver"; - for (unsigned i = 0; i < num; i++) { - out << "\n " << mk_ismt2_pp(m_ctx->m_assertions.get(i), m, 2); - } - out << ")"; +void tactic2solver::display(std::ostream & out) const { + ast_manager & m = m_assertions.m(); + unsigned num = m_assertions.size(); + out << "(solver"; + for (unsigned i = 0; i < num; i++) { + out << "\n " << mk_ismt2_pp(m_assertions.get(i), m, 2); } - else { - out << "(solver)"; + out << ")"; +} + +solver * mk_tactic2solver(ast_manager & m, + tactic * t, + params_ref const & p, + bool produce_proofs, + bool produce_models, + bool produce_unsat_cores, + symbol const & logic) { + return alloc(tactic2solver, m, t, p, produce_proofs, produce_models, produce_unsat_cores, logic); +} + +class tactic2solver_factory : public solver_factory { + ref m_tactic; +public: + tactic2solver_factory(tactic * t):m_tactic(t) { } + + virtual ~tactic2solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + return mk_tactic2solver(m, m_tactic.get(), p, proofs_enabled, models_enabled, unsat_core_enabled, logic); + } +}; + +class tactic_factory2solver_factory : public solver_factory { + scoped_ptr m_factory; +public: + tactic_factory2solver_factory(tactic_factory * f):m_factory(f) { + } + + virtual ~tactic_factory2solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + tactic * t = (*m_factory)(m, p); + return mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, logic); + } +}; + +solver_factory * mk_tactic2solver_factory(tactic * t) { + return alloc(tactic2solver_factory, t); } -tactic2solver::tactic2solver(tactic * t): - m_tactic(t) { -} - -tactic2solver::~tactic2solver() { -} - -tactic * tactic2solver::get_tactic(ast_manager & m, params_ref const & p) { - m_tactic->cleanup(); - m_tactic->updt_params(p); - return m_tactic.get(); -} - -tactic_factory2solver::~tactic_factory2solver() { -} - -void tactic_factory2solver::set_tactic(tactic_factory * f) { - m_tactic_factory = f; -} - -tactic * tactic_factory2solver::get_tactic(ast_manager & m, params_ref const & p) { - if (m_tactic_factory == 0) - return 0; - return (*m_tactic_factory)(m, p); +solver_factory * mk_tactic_factory2solver_factory(tactic_factory * f) { + return alloc(tactic_factory2solver_factory, f); } diff --git a/src/solver/tactic2solver.h b/src/solver/tactic2solver.h index 0a057b04b..f20b1c4dd 100644 --- a/src/solver/tactic2solver.h +++ b/src/solver/tactic2solver.h @@ -22,88 +22,22 @@ Notes: #ifndef _TACTIC2SOLVER_H_ #define _TACTIC2SOLVER_H_ -#include"solver_na2as.h" -#include"tactic.h" +#include"params.h" +class ast_manager; +class tactic; +class tactic_factory; +class solver; +class solver_factory; -/** - \brief Simulates the incremental solver interface using a tactic. - - Every query will be solved from scratch. So, this is not a good - option for applications trying to solve many easy queries that a - similar to each other. -*/ -class tactic2solver_core : public solver_na2as { - struct ctx { - symbol m_logic; - expr_ref_vector m_assertions; - unsigned_vector m_scopes; - ref m_result; - tactic_ref m_tactic; - ctx(ast_manager & m, symbol const & logic); - ast_manager & m() const { return m_assertions.m(); } - }; - scoped_ptr m_ctx; - params_ref m_params; - bool m_produce_models; - bool m_produce_proofs; - bool m_produce_unsat_cores; -public: - tactic2solver_core():m_ctx(0), m_produce_models(false), m_produce_proofs(false), m_produce_unsat_cores(false) {} - virtual ~tactic2solver_core(); - - virtual tactic * get_tactic(ast_manager & m, params_ref const & p) = 0; - - virtual void updt_params(params_ref const & p); - virtual void collect_param_descrs(param_descrs & r); - - virtual void set_produce_proofs(bool f) { m_produce_proofs = f; } - virtual void set_produce_models(bool f) { m_produce_models = f; } - virtual void set_produce_unsat_cores(bool f) { m_produce_unsat_cores = f; } - - virtual void assert_expr(expr * t); - - virtual void init_core(ast_manager & m, symbol const & logic); - virtual void reset_core(); - virtual void push_core(); - virtual void pop_core(unsigned n); - virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions); - - virtual void set_cancel(bool f); - - virtual void collect_statistics(statistics & st) const; - virtual void get_unsat_core(ptr_vector & r); - virtual void get_model(model_ref & m); - virtual proof * get_proof(); - virtual std::string reason_unknown() const; - virtual void get_labels(svector & r) {} - - virtual void set_progress_callback(progress_callback * callback) {} - - virtual unsigned get_num_assertions() const; - virtual expr * get_assertion(unsigned idx) const; - - virtual void display(std::ostream & out) const; -}; - -class tactic2solver : public tactic2solver_core { - tactic_ref m_tactic; -public: - tactic2solver(tactic * t); - virtual ~tactic2solver(); - virtual tactic * get_tactic(ast_manager & m, params_ref const & p); -}; - - -class tactic_factory2solver : public tactic2solver_core { - scoped_ptr m_tactic_factory; -public: - virtual ~tactic_factory2solver(); - /** - \brief Set tactic that will be used to process the satisfiability queries. - */ - void set_tactic(tactic_factory * f); - virtual tactic * get_tactic(ast_manager & m, params_ref const & p); -}; +solver * mk_tactic2solver(ast_manager & m, + tactic * t = 0, + params_ref const & p = params_ref(), + bool produce_proofs = false, + bool produce_models = true, + bool produce_unsat_cores = false, + symbol const & logic = symbol::null); +solver_factory * mk_tactic2solver_factory(tactic * t); +solver_factory * mk_tactic_factory2solver_factory(tactic_factory * f); #endif diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index 7a274a830..3d83d8815 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -18,7 +18,8 @@ Notes: --*/ #include"cmd_context.h" -#include"strategic_solver.h" +#include"combined_solver.h" +#include"tactic2solver.h" #include"qfbv_tactic.h" #include"qflia_tactic.h" #include"qfnia_tactic.h" @@ -36,57 +37,76 @@ Notes: #include"horn_tactic.h" #include"smt_solver.h" -MK_SIMPLE_TACTIC_FACTORY(qfuf_fct, mk_qfuf_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfidl_fct, mk_qfidl_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfauflia_fct, mk_qfauflia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(auflia_fct, mk_auflia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(auflira_fct, mk_auflira_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(aufnira_fct, mk_aufnira_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(ufnia_fct, mk_ufnia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(uflra_fct, mk_uflra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(lra_fct, mk_lra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfbv_fct, mk_qfbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(default_fct, mk_default_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfaufbv_fct, mk_qfaufbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qflra_fct, mk_qflra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qflia_fct, mk_qflia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfufbv_fct, mk_qfufbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfnia_fct, mk_qfnia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfnra_fct, mk_qfnra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qffpa_fct, mk_qffpa_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(ufbv_fct, mk_ufbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(horn_fct, mk_horn_tactic(m, p)); - -static void init(strategic_solver * s) { - s->set_default_tactic(alloc(default_fct)); - s->set_tactic_for(symbol("QF_UF"), alloc(qfuf_fct)); - s->set_tactic_for(symbol("QF_BV"), alloc(qfbv_fct)); - s->set_tactic_for(symbol("QF_IDL"), alloc(qfidl_fct)); - s->set_tactic_for(symbol("QF_LIA"), alloc(qflia_fct)); - s->set_tactic_for(symbol("QF_LRA"), alloc(qflra_fct)); - s->set_tactic_for(symbol("QF_NIA"), alloc(qfnia_fct)); - s->set_tactic_for(symbol("QF_NRA"), alloc(qfnra_fct)); - s->set_tactic_for(symbol("QF_AUFLIA"), alloc(qfauflia_fct)); - s->set_tactic_for(symbol("QF_AUFBV"), alloc(qfaufbv_fct)); - s->set_tactic_for(symbol("QF_ABV"), alloc(qfaufbv_fct)); - s->set_tactic_for(symbol("QF_UFBV"), alloc(qfufbv_fct)); - s->set_tactic_for(symbol("AUFLIA"), alloc(auflia_fct)); - s->set_tactic_for(symbol("AUFLIRA"), alloc(auflira_fct)); - s->set_tactic_for(symbol("AUFNIRA"), alloc(aufnira_fct)); - s->set_tactic_for(symbol("UFNIA"), alloc(ufnia_fct)); - s->set_tactic_for(symbol("UFLRA"), alloc(uflra_fct)); - s->set_tactic_for(symbol("LRA"), alloc(lra_fct)); - s->set_tactic_for(symbol("UFBV"), alloc(ufbv_fct)); - s->set_tactic_for(symbol("BV"), alloc(ufbv_fct)); - s->set_tactic_for(symbol("QF_FPA"), alloc(qffpa_fct)); - s->set_tactic_for(symbol("QF_FPABV"), alloc(qffpa_fct)); - s->set_tactic_for(symbol("HORN"), alloc(horn_fct)); +tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) { + if (logic=="QF_UF") + return mk_qfufbv_tactic(m, p); + else if (logic=="QF_BV") + return mk_qfbv_tactic(m, p); + else if (logic=="QF_IDL") + return mk_qfidl_tactic(m, p); + else if (logic=="QF_LIA") + return mk_qflia_tactic(m, p); + else if (logic=="QF_LRA") + return mk_qflra_tactic(m, p); + else if (logic=="QF_NIA") + return mk_qfnia_tactic(m, p); + else if (logic=="QF_NRA") + return mk_qfnra_tactic(m, p); + else if (logic=="QF_AUFLIA") + return mk_qfauflia_tactic(m, p); + else if (logic=="QF_AUFBV") + return mk_qfaufbv_tactic(m, p); + else if (logic=="QF_ABV") + return mk_qfaufbv_tactic(m, p); + else if (logic=="QF_UFBV") + return mk_qfufbv_tactic(m, p); + else if (logic=="AUFLIA") + return mk_auflia_tactic(m, p); + else if (logic=="AUFLIRA") + return mk_auflira_tactic(m, p); + else if (logic=="AUFNIRA") + return mk_aufnira_tactic(m, p); + else if (logic=="UFNIA") + return mk_ufnia_tactic(m, p); + else if (logic=="UFLRA") + return mk_uflra_tactic(m, p); + else if (logic=="LRA") + return mk_lra_tactic(m, p); + else if (logic=="UFBV") + return mk_ufbv_tactic(m, p); + else if (logic=="BV") + return mk_ufbv_tactic(m, p); + else if (logic=="QF_FPA") + return mk_qffpa_tactic(m, p); + else if (logic=="QF_FPABV") + return mk_qffpa_tactic(m, p); + else if (logic=="HORN") + return mk_horn_tactic(m, p); + else + return mk_default_tactic(m, p); } -solver * mk_smt_strategic_solver(bool force_tactic) { - strategic_solver * s = alloc(strategic_solver); - s->force_tactic(force_tactic); - s->set_inc_solver(mk_smt_solver()); - init(s); - return s; +class smt_strategic_solver_factory : public solver_factory { + symbol const & m_logic; +public: + smt_strategic_solver_factory(symbol const & logic):m_logic(logic) {} + + virtual ~smt_strategic_solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + symbol l; + if (m_logic != symbol::null) + l = m_logic; + else + l = logic; + tactic * t = mk_tactic_for_logic(m, p, logic); + return mk_combined_solver(mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, l), + mk_smt_solver(m, p, l), + p); + } +}; + +solver_factory * mk_smt_strategic_solver_factory(symbol const & logic) { + return alloc(smt_strategic_solver_factory, logic); } + diff --git a/src/tactic/portfolio/smt_strategic_solver.h b/src/tactic/portfolio/smt_strategic_solver.h index 060721e09..1d132532a 100644 --- a/src/tactic/portfolio/smt_strategic_solver.h +++ b/src/tactic/portfolio/smt_strategic_solver.h @@ -20,8 +20,8 @@ Notes: #ifndef _SMT_STRATEGIC_SOLVER_H_ #define _SMT_STRATEGIC_SOLVER_H_ -class solver; -// Create a strategic solver for the Z3 API -solver * mk_smt_strategic_solver(bool force_tactic=false); +class solver_factory; + +solver_factory * mk_smt_strategic_solver_factory(symbol const & logic = symbol::null); #endif From 528f34802220d93d95761b9c1466915b402c6343 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 11 Dec 2012 17:51:49 -0800 Subject: [PATCH 59/60] Fixed bug Signed-off-by: Leonardo de Moura --- src/tactic/portfolio/smt_strategic_solver.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index 3d83d8815..4813cbe1a 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -87,7 +87,7 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const } class smt_strategic_solver_factory : public solver_factory { - symbol const & m_logic; + symbol m_logic; public: smt_strategic_solver_factory(symbol const & logic):m_logic(logic) {} @@ -99,7 +99,7 @@ public: l = m_logic; else l = logic; - tactic * t = mk_tactic_for_logic(m, p, logic); + tactic * t = mk_tactic_for_logic(m, p, l); return mk_combined_solver(mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, l), mk_smt_solver(m, p, l), p); From 13dda76ddb4be2453254333e7033fdcf634c17d6 Mon Sep 17 00:00:00 2001 From: Leonardo de Moura Date: Tue, 11 Dec 2012 18:00:09 -0800 Subject: [PATCH 60/60] Removed dead code Signed-off-by: Leonardo de Moura --- src/solver/strategic_solver.cpp | 535 -------------------------------- src/solver/strategic_solver.h | 154 --------- 2 files changed, 689 deletions(-) delete mode 100644 src/solver/strategic_solver.cpp delete mode 100644 src/solver/strategic_solver.h diff --git a/src/solver/strategic_solver.cpp b/src/solver/strategic_solver.cpp deleted file mode 100644 index fa7458ea3..000000000 --- a/src/solver/strategic_solver.cpp +++ /dev/null @@ -1,535 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - strategic_solver.h - -Abstract: - - Strategies -> Solver - -Author: - - Leonardo (leonardo) 2011-05-19 - -Notes: - ---*/ -#if 0 -#include"strategic_solver.h" -#include"scoped_timer.h" -#include"ast_smt2_pp.h" - -// minimum verbosity level for portfolio verbose messages -#define PS_VB_LVL 15 - - -strategic_solver::ctx::ctx(ast_manager & m): - m_assertions(m), - m_assertion_names(m) { - } - -strategic_solver::strategic_solver(): - m_manager(0), - m_force_tactic(false), - m_inc_mode(false), - m_check_sat_executed(false), - m_inc_solver(0), - m_inc_solver_timeout(UINT_MAX), - m_inc_unknown_behavior(IUB_USE_TACTIC_IF_QF), - m_default_fct(0), - m_curr_tactic(0), - m_proof(0), - m_core(0), - m_callback(0) { - m_use_inc_solver_results = false; - DEBUG_CODE(m_num_scopes = 0;); - m_produce_proofs = false; - m_produce_models = false; - m_produce_unsat_cores = false; - m_auto_config = true; -} - -strategic_solver::~strategic_solver() { - SASSERT(!m_curr_tactic); - dictionary::iterator it = m_logic2fct.begin(); - dictionary::iterator end = m_logic2fct.end(); - for (; it != end; ++it) { - dealloc(it->m_value); - } - if (m_proof) - m().dec_ref(m_proof); - if (m_core) - m().dec_ref(m_core); -} - -bool strategic_solver::has_quantifiers() const { - unsigned sz = get_num_assertions(); - for (unsigned i = 0; i < sz; i++) { - if (::has_quantifiers(get_assertion(i))) - return true; - } - return false; -} - -/** - \brief Return true if a tactic should be used when the incremental solver returns unknown. -*/ -bool strategic_solver::use_tactic_when_undef() const { - switch (m_inc_unknown_behavior) { - case IUB_RETURN_UNDEF: return false; - case IUB_USE_TACTIC_IF_QF: return !has_quantifiers(); - case IUB_USE_TACTIC: return true; - default: - UNREACHABLE(); - return false; - } -} - -void strategic_solver::set_inc_solver(solver * s) { - SASSERT(m_inc_solver == 0); - SASSERT(m_num_scopes == 0); - m_inc_solver = s; - if (m_callback) - m_inc_solver->set_progress_callback(m_callback); -} - -void strategic_solver::updt_params(params_ref const & p) { - if (m_inc_solver) - m_inc_solver->updt_params(p); - m_params = p; - m_auto_config = p.get_bool("auto_config", true); -} - -void strategic_solver::collect_param_descrs(param_descrs & r) { - if (m_inc_solver) - m_inc_solver->collect_param_descrs(r); -} - -/** - \brief Set a timeout for each check_sat query that is processed by the inc_solver. - timeout == UINT_MAX means infinite - After the timeout a strategy is used. -*/ -void strategic_solver::set_inc_solver_timeout(unsigned timeout) { - m_inc_solver_timeout = timeout; -} - -/** - \brief Set the default tactic factory. - It is used if there is no tactic for a given logic. -*/ -void strategic_solver::set_default_tactic(tactic_factory * fct) { - m_default_fct = fct; -} - -/** - \brief Set a tactic factory for a given logic. -*/ -void strategic_solver::set_tactic_for(symbol const & logic, tactic_factory * fct) { - tactic_factory * old_fct; - if (m_logic2fct.find(logic, old_fct)) { - dealloc(old_fct); - } - m_logic2fct.insert(logic, fct); -} - -void strategic_solver::init(ast_manager & m, symbol const & logic) { - m_manager = &m; - m_logic = logic; - if (m_inc_mode) { - SASSERT(m_inc_solver); - m_inc_solver->init(m, logic); - } - m_ctx = alloc(ctx, m); - TRACE("strategic_solver", tout << "strategic_solver was initialized.\n";); -} - -unsigned strategic_solver::get_num_assertions() const { - if (m_ctx == 0) - return 0; - return m_ctx->m_assertions.size(); -} - -expr * strategic_solver::get_assertion(unsigned idx) const { - SASSERT(m_ctx); - return m_ctx->m_assertions.get(idx); -} - -expr * strategic_solver::get_assertion_name(unsigned idx) const { - SASSERT(m_ctx); - SASSERT(m_produce_unsat_cores); - return m_ctx->m_assertion_names.get(idx); -} - -void strategic_solver::set_produce_proofs(bool f) { - m_produce_proofs = f; - // do not need to propagate to inc_solver since flag cannot be changed after initialization -} - -void strategic_solver::set_produce_models(bool f) { - m_produce_models = f; - if (m_inc_solver) - m_inc_solver->set_produce_models(f); -} - -void strategic_solver::set_produce_unsat_cores(bool f) { - m_produce_unsat_cores = f; - // do not need to propagate to inc_solver since flag cannot be changed after initialization -} - -// delayed inc solver initialization -void strategic_solver::init_inc_solver() { - if (m_inc_mode) - return; // solver was already initialized - if (!m_inc_solver) - return; // inc solver was not installed - m_inc_mode = true; - m_inc_solver->set_produce_proofs(m_produce_proofs); - m_inc_solver->set_produce_models(m_produce_models); - m_inc_solver->set_produce_unsat_cores(m_produce_unsat_cores); - m_inc_solver->init(m(), m_logic); - unsigned sz = get_num_assertions(); - if (m_produce_unsat_cores) { - SASSERT(m_ctx->m_assertions.size() == m_ctx->m_assertion_names.size()); - for (unsigned i = 0; i < sz; i++) { - m_inc_solver->assert_expr(get_assertion(i), get_assertion_name(i)); - } - } - else { - for (unsigned i = 0; i < sz; i++) { - m_inc_solver->assert_expr(get_assertion(i)); - } - } -} - -void strategic_solver::collect_statistics(statistics & st) const { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->collect_statistics(st); - } - else { - if (m_curr_tactic) - m_curr_tactic->collect_statistics(st); // m_curr_tactic is still being executed. - else - st.copy(m_stats); - } -} - -void strategic_solver::reset() { - m_ctx = 0; - m_logic = symbol::null; - m_inc_mode = false; - m_check_sat_executed = false; - if (m_inc_solver) - m_inc_solver->reset(); - SASSERT(!m_curr_tactic); - m_use_inc_solver_results = false; - reset_results(); -} - -void strategic_solver::reset_results() { - m_use_inc_solver_results = false; - m_model = 0; - if (m_proof) { - m().dec_ref(m_proof); - m_proof = 0; - } - if (m_core) { - m().dec_ref(m_core); - m_core = 0; - } - m_reason_unknown.clear(); - m_stats.reset(); -} - -void strategic_solver::assert_expr(expr * t) { - if (m_check_sat_executed && !m_inc_mode) { - // a check sat was already executed --> switch to incremental mode - init_inc_solver(); - SASSERT(m_inc_solver == 0 || m_inc_mode); - } - if (m_inc_mode) { - SASSERT(m_inc_solver); - m_inc_solver->assert_expr(t); - } - SASSERT(m_ctx); - m_ctx->m_assertions.push_back(t); - if (m_produce_unsat_cores) - m_ctx->m_assertion_names.push_back(0); -} - -void strategic_solver::assert_expr(expr * t, expr * a) { - if (m_check_sat_executed && !m_inc_mode) { - // a check sat was already executed --> switch to incremental mode - init_inc_solver(); - SASSERT(m_inc_solver == 0 || m_inc_mode); - } - if (m_inc_mode) { - SASSERT(m_inc_solver); - m_inc_solver->assert_expr(t, a); - } - SASSERT(m_ctx); - m_ctx->m_assertions.push_back(t); - if (m_produce_unsat_cores) - m_ctx->m_assertion_names.push_back(a); -} - -void strategic_solver::push() { - DEBUG_CODE(m_num_scopes++;); - init_inc_solver(); - if (m_inc_solver) - m_inc_solver->push(); - m_ctx->m_scopes.push_back(m_ctx->m_assertions.size()); -} - -void strategic_solver::pop(unsigned n) { - DEBUG_CODE({ - SASSERT(n <= m_num_scopes); - m_num_scopes -= n; - }); - init_inc_solver(); - if (m_inc_solver) - m_inc_solver->pop(n); - - SASSERT(m_ctx); - unsigned new_lvl = m_ctx->m_scopes.size() - n; - unsigned old_sz = m_ctx->m_scopes[new_lvl]; - m_ctx->m_assertions.shrink(old_sz); - if (m_produce_unsat_cores) - m_ctx->m_assertion_names.shrink(old_sz); - m_ctx->m_scopes.shrink(new_lvl); -} - -unsigned strategic_solver::get_scope_level() const { - if (m_ctx == 0) - return 0; - return m_ctx->m_scopes.size(); -} - -struct aux_timeout_eh : public event_handler { - solver * m_solver; - volatile bool m_canceled; - aux_timeout_eh(solver * s):m_solver(s), m_canceled(false) {} - virtual void operator()() { - m_solver->cancel(); - m_canceled = true; - } -}; - -struct strategic_solver::mk_tactic { - strategic_solver * m_solver; - - mk_tactic(strategic_solver * s, tactic_factory * f, params_ref const & p):m_solver(s) { - ast_manager & m = s->m(); - tactic * tct = (*f)(m, p); - tct->set_logic(s->m_logic); - if (s->m_callback) - tct->set_progress_callback(s->m_callback); - #pragma omp critical (strategic_solver) - { - s->m_curr_tactic = tct; - } - } - - ~mk_tactic() { - #pragma omp critical (strategic_solver) - { - m_solver->m_curr_tactic = 0; - } - } -}; - -tactic_factory * strategic_solver::get_tactic_factory() const { - tactic_factory * f = 0; - if (m_logic2fct.find(m_logic, f)) - return f; - return m_default_fct.get(); -} - -lbool strategic_solver::check_sat_with_assumptions(unsigned num_assumptions, expr * const * assumptions) { - if (!m_inc_solver) { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "incremental solver was not installed, returning unknown...\n";); - m_use_inc_solver_results = false; - m_reason_unknown = "incomplete"; - return l_undef; - } - init_inc_solver(); - m_use_inc_solver_results = true; - TRACE("strategic_solver", tout << "invoking inc_solver with " << num_assumptions << " assumptions\n";); - return m_inc_solver->check_sat(num_assumptions, assumptions); -} - -lbool strategic_solver::check_sat(unsigned num_assumptions, expr * const * assumptions) { - TRACE("strategic_solver", tout << "assumptions at strategic_solver:\n"; - for (unsigned i = 0; i < num_assumptions; i++) { - tout << mk_ismt2_pp(assumptions[i], m()) << "\n"; - } - tout << "m_produce_unsat_cores: " << m_produce_unsat_cores << ", m_inc_mode: " << m_inc_mode << "\n";); - reset_results(); - m_check_sat_executed = true; - if (num_assumptions > 0 || // assumptions were provided - (!m_auto_config && !m_force_tactic) // auto config and force_tactic are turned off - ) { - // must use incremental solver - return check_sat_with_assumptions(num_assumptions, assumptions); - } - - tactic_factory * factory = get_tactic_factory(); - if (factory == 0) - init_inc_solver(); // try to switch to incremental solver - - if (m_inc_mode) { - SASSERT(m_inc_solver); - unsigned timeout = m_inc_solver_timeout; - if (factory == 0) - timeout = UINT_MAX; // there is no tactic available - if (timeout == UINT_MAX) { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "using incremental solver (without a timeout).\n";); - m_use_inc_solver_results = true; - lbool r = m_inc_solver->check_sat(0, 0); - if (r != l_undef || factory == 0 || !use_tactic_when_undef()) { - m_use_inc_solver_results = true; - return r; - } - } - else { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "using incremental solver (with timeout).\n";); - SASSERT(factory != 0); - aux_timeout_eh eh(m_inc_solver.get()); - lbool r; - { - scoped_timer timer(m_inc_solver_timeout, &eh); - r = m_inc_solver->check_sat(0, 0); - } - if ((r != l_undef || !use_tactic_when_undef()) && !eh.m_canceled) { - m_use_inc_solver_results = true; - return r; - } - } - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "incremental solver failed, trying tactic.\n";); - } - - m_use_inc_solver_results = false; - - if (factory == 0) { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "there is no tactic available for the current logic.\n";); - m_reason_unknown = "incomplete"; - return l_undef; - } - - goal_ref g = alloc(goal, m(), m_produce_proofs, m_produce_models, m_produce_unsat_cores); - unsigned sz = get_num_assertions(); - if (m_produce_unsat_cores) { - SASSERT(m_ctx->m_assertions.size() == m_ctx->m_assertion_names.size()); - for (unsigned i = 0; i < sz; i++) - g->assert_expr(get_assertion(i), get_assertion_name(i)); - } - else { - for (unsigned i = 0; i < sz; i++) - g->assert_expr(get_assertion(i)); - } - expr_dependency_ref core(m()); - - TRACE("strategic_solver", tout << "using goal...\n"; g->display_with_dependencies(tout);); - - mk_tactic tct_maker(this, factory, m_params); - SASSERT(m_curr_tactic); - - proof_ref pr(m()); - lbool r = ::check_sat(*(m_curr_tactic.get()), g, m_model, pr, core, m_reason_unknown); - m_curr_tactic->collect_statistics(m_stats); - if (pr) { - m_proof = pr; - m().inc_ref(m_proof); - } - if (core) { - m_core = core; - m().inc_ref(m_core); - } - return r; -} - -void strategic_solver::set_cancel(bool f) { - if (m_inc_solver) - m_inc_solver->set_cancel(f); - #pragma omp critical (strategic_solver) - { - if (m_curr_tactic) - m_curr_tactic->set_cancel(f); - } -} - -void strategic_solver::get_unsat_core(ptr_vector & r) { - TRACE("strategic_solver", tout << "get_unsat_core, m_use_inc_solver_results: " << m_use_inc_solver_results << "\n";); - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->get_unsat_core(r); - } - else { - m().linearize(m_core, r); - } -} - -void strategic_solver::get_model(model_ref & m) { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->get_model(m); - } - else { - m = m_model; - } -} - -proof * strategic_solver::get_proof() { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - return m_inc_solver->get_proof(); - } - else { - return m_proof; - } -} - -std::string strategic_solver::reason_unknown() const { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - return m_inc_solver->reason_unknown(); - } - return m_reason_unknown; -} - -void strategic_solver::get_labels(svector & r) { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->get_labels(r); - } -} - -void strategic_solver::set_progress_callback(progress_callback * callback) { - m_callback = callback; - if (m_inc_solver) - m_inc_solver->set_progress_callback(callback); -} - -void strategic_solver::display(std::ostream & out) const { - if (m_manager) { - unsigned num = get_num_assertions(); - out << "(solver"; - for (unsigned i = 0; i < num; i++) { - out << "\n " << mk_ismt2_pp(get_assertion(i), m(), 2); - } - out << ")"; - } - else { - out << "(solver)"; - } -} - -#endif - - - - - diff --git a/src/solver/strategic_solver.h b/src/solver/strategic_solver.h deleted file mode 100644 index 0bae8b254..000000000 --- a/src/solver/strategic_solver.h +++ /dev/null @@ -1,154 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - strategic_solver.h - -Abstract: - - Strategies -> Solver - -Author: - - Leonardo (leonardo) 2011-05-19 - -Notes: - ---*/ -#ifndef _STRATEGIC_SOLVER_H_ -#define _STRATEGIC_SOLVER_H_ - -#include"solver.h" -#include"tactic.h" - -class progress_callback; - -/** - \brief Implementation of the solver API that supports: - - a different tactic for each logic - - a general purpose tactic - - a default incremental solver - - The strategic solver has two modes: - - non-incremental - - incremental - In non-incremental mode, tactics are used. - In incremental model, the incremental (general purpose) solver is used. - - A timeout for the incremental solver can be specified. - If the timeout is reached, then the strategic_solver tries to solve the problem using tactics. - - The strategic_solver switches to incremental when: - - push is used - - assertions are peformed after a check_sat - It goes back to non_incremental mode when: - - reset is invoked. -*/ -class strategic_solver : public solver { -public: - // Behavior when the incremental solver returns unknown. - enum inc_unknown_behavior { - IUB_RETURN_UNDEF, // just return unknown - IUB_USE_TACTIC_IF_QF, // invoke tactic if problem is quantifier free - IUB_USE_TACTIC // invoke tactic - }; - -private: - ast_manager * m_manager; - params_ref m_params; - symbol m_logic; - bool m_force_tactic; // use tactics even when auto_config = false - bool m_inc_mode; - bool m_check_sat_executed; - scoped_ptr m_inc_solver_factory; - ref m_inc_solver; - unsigned m_inc_solver_timeout; - inc_unknown_behavior m_inc_unknown_behavior; - scoped_ptr m_default_fct; - dictionary m_logic2fct; - - ref m_curr_tactic; - - bool m_use_inc_solver_results; - model_ref m_model; - proof * m_proof; - expr_dependency * m_core; - std::string m_reason_unknown; - statistics m_stats; - - struct ctx { - expr_ref_vector m_assertions; - expr_ref_vector m_assertion_names; - unsigned_vector m_scopes; - ctx(ast_manager & m); - }; - scoped_ptr m_ctx; - -#ifdef Z3DEBUG - unsigned m_num_scopes; -#endif - - bool m_produce_proofs; - bool m_produce_models; - bool m_produce_unsat_cores; - - bool m_auto_config; - - progress_callback * m_callback; - - void reset_results(); - void init_inc_solver(); - tactic_factory * get_tactic_factory() const; - lbool check_sat_with_assumptions(unsigned num_assumptions, expr * const * assumptions); - - struct mk_tactic; - - bool has_quantifiers() const; - bool use_tactic_when_undef() const; - -public: - strategic_solver(ast_manager & m, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic); - ~strategic_solver(); - - ast_manager & m() const { SASSERT(m_manager); return *m_manager; } - - void set_inc_solver_factory(solver_factory * s); - void set_inc_solver_timeout(unsigned timeout); - void set_default_tactic(tactic_factory * fct); - void set_tactic_for(symbol const & logic, tactic_factory * fct); - void set_inc_unknown_behavior(inc_unknown_behavior b) { m_inc_unknown_behavior = b; } - void force_tactic(bool f) { m_force_tactic = f; } - - virtual void updt_params(params_ref const & p); - virtual void collect_param_descrs(param_descrs & r); - - virtual void set_produce_proofs(bool f); - virtual void set_produce_models(bool f); - virtual void set_produce_unsat_cores(bool f); - - unsigned get_num_assertions() const; - expr * get_assertion(unsigned idx) const; - expr * get_assertion_name(unsigned idx) const; - - virtual void display(std::ostream & out) const; - - virtual void init(ast_manager & m, symbol const & logic); - virtual void collect_statistics(statistics & st) const; - virtual void reset(); - virtual void assert_expr(expr * t); - virtual void assert_expr(expr * t, expr * a); - virtual void push(); - virtual void pop(unsigned n); - virtual unsigned get_scope_level() const; - virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions); - virtual void get_unsat_core(ptr_vector & r); - virtual void get_model(model_ref & m); - virtual proof * get_proof(); - virtual std::string reason_unknown() const; - virtual void get_labels(svector & r); - virtual void set_cancel(bool f); - virtual void set_progress_callback(progress_callback * callback); -}; - -#endif