mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-26 09:24:36 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into polysat
This commit is contained in:
		
						commit
						cd50f2ea88
					
				
					 378 changed files with 13563 additions and 7320 deletions
				
			
		
							
								
								
									
										2
									
								
								.github/workflows/docker-image.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/docker-image.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -41,7 +41,7 @@ jobs: | |||
|             type=edge | ||||
|             type=sha,prefix=ubuntu-20.04-bare-z3-sha- | ||||
|       - name: Build and push Bare Z3 Docker Image | ||||
|         uses: docker/build-push-action@v5.0.0 | ||||
|         uses: docker/build-push-action@v5.1.0 | ||||
|         with:   | ||||
|           context: . | ||||
|           push: true | ||||
|  |  | |||
							
								
								
									
										4
									
								
								.github/workflows/wasm-release.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/wasm-release.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -24,7 +24,7 @@ jobs: | |||
|         uses: actions/checkout@v4 | ||||
| 
 | ||||
|       - name: Setup node | ||||
|         uses: actions/setup-node@v3 | ||||
|         uses: actions/setup-node@v4 | ||||
|         with: | ||||
|           node-version: "lts/*" | ||||
|           registry-url: "https://registry.npmjs.org" | ||||
|  | @ -36,7 +36,7 @@ jobs: | |||
|           cp ../../../LICENSE.txt . | ||||
| 
 | ||||
|       - name: Setup emscripten | ||||
|         uses: mymindstorm/setup-emsdk@v12 | ||||
|         uses: mymindstorm/setup-emsdk@v13 | ||||
|         with: | ||||
|           no-install: true | ||||
|           version: ${{env.EM_VERSION}} | ||||
|  |  | |||
							
								
								
									
										4
									
								
								.github/workflows/wasm.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/wasm.yml
									
										
									
									
										vendored
									
									
								
							|  | @ -24,12 +24,12 @@ jobs: | |||
|         uses: actions/checkout@v4 | ||||
| 
 | ||||
|       - name: Setup node | ||||
|         uses: actions/setup-node@v3 | ||||
|         uses: actions/setup-node@v4 | ||||
|         with: | ||||
|           node-version: "lts/*" | ||||
| 
 | ||||
|       - name: Setup emscripten | ||||
|         uses: mymindstorm/setup-emsdk@v12 | ||||
|         uses: mymindstorm/setup-emsdk@v13 | ||||
|         with: | ||||
|           no-install: true | ||||
|           version: ${{env.EM_VERSION}} | ||||
|  |  | |||
|  | @ -1,8 +1,8 @@ | |||
| # Enforce some CMake policies | ||||
| cmake_minimum_required(VERSION 3.4) | ||||
| cmake_minimum_required(VERSION 3.16) | ||||
| 
 | ||||
| set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cxx_compiler_flags_overrides.cmake") | ||||
| project(Z3 VERSION 4.12.3.0 LANGUAGES CXX C) | ||||
| project(Z3 VERSION 4.12.5.0 LANGUAGES CXX C) | ||||
| 
 | ||||
| ################################################################################ | ||||
| # Project version | ||||
|  | @ -41,19 +41,22 @@ list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/modules") | |||
| ################################################################################ | ||||
| include(${PROJECT_SOURCE_DIR}/cmake/git_utils.cmake) | ||||
| macro(disable_git_describe) | ||||
|   message(WARNING "Disabling Z3_INCLUDE_GIT_DESCRIBE") | ||||
|   set(Z3_INCLUDE_GIT_DESCRIBE OFF CACHE BOOL "Include git describe output in version output" FORCE) | ||||
|   if(Z3_INCLUDE_GIT_DESCRIBE) | ||||
|     message(WARNING "Disabling Z3_INCLUDE_GIT_DESCRIBE") | ||||
|     set(Z3_INCLUDE_GIT_DESCRIBE OFF CACHE BOOL "Include git describe output in version output" FORCE) | ||||
|   endif() | ||||
| endmacro() | ||||
| macro(disable_git_hash) | ||||
|   message(WARNING "Disabling Z3_INCLUDE_GIT_HASH") | ||||
|   set(Z3_INCLUDE_GIT_HASH OFF CACHE BOOL "Include git hash in version output" FORCE) | ||||
|   unset(Z3GITHASH) # Used in configure_file() | ||||
|   if(Z3_INCLUDE_GIT_HASH) | ||||
|     message(WARNING "Disabling Z3_INCLUDE_GIT_HASH") | ||||
|     set(Z3_INCLUDE_GIT_HASH OFF CACHE BOOL "Include git hash in version output" FORCE) | ||||
|   endif() | ||||
| endmacro() | ||||
| option(Z3_INCLUDE_GIT_HASH "Include git hash in version output" ON) | ||||
| option(Z3_INCLUDE_GIT_DESCRIBE "Include git describe output in version output" ON) | ||||
| 
 | ||||
| set(GIT_DIR "${PROJECT_SOURCE_DIR}/.git") | ||||
| if (EXISTS "${GIT_DIR}") | ||||
| if ((Z3_INCLUDE_GIT_HASH OR Z3_INCLUDE_GIT_HASH) AND EXISTS "${GIT_DIR}") | ||||
|   # Try to make CMake configure depend on the current git HEAD so that | ||||
|   # a re-configure is triggered when the HEAD changes. | ||||
|   add_git_dir_dependency("${GIT_DIR}" ADD_GIT_DEP_SUCCESS) | ||||
|  | @ -63,13 +66,13 @@ if (EXISTS "${GIT_DIR}") | |||
|       if (NOT Z3GITHASH) | ||||
|         message(WARNING "Failed to get Git hash") | ||||
|         disable_git_hash() | ||||
|       else() | ||||
|         message(STATUS "Using Git hash in version output: ${Z3GITHASH}") | ||||
|         # This mimics the behaviour of the old build system. | ||||
|         set(Z3_FULL_VERSION_STR "${Z3_FULL_VERSION_STR} ${Z3GITHASH}") | ||||
|       endif() | ||||
|       message(STATUS "Using Git hash in version output: ${Z3GITHASH}") | ||||
|       # This mimics the behaviour of the old build system. | ||||
|       set(Z3_FULL_VERSION_STR "${Z3_FULL_VERSION_STR} ${Z3GITHASH}") | ||||
|     else() | ||||
|       message(STATUS "Not using Git hash in version output") | ||||
|       unset(Z3GITHASH) # Used in configure_file() | ||||
|     endif() | ||||
|     if (Z3_INCLUDE_GIT_DESCRIBE) | ||||
|       get_git_head_describe("${GIT_DIR}" Z3_GIT_DESCRIPTION) | ||||
|  | @ -93,6 +96,9 @@ else() | |||
|   disable_git_describe() | ||||
|   disable_git_hash() | ||||
| endif() | ||||
| if(NOT Z3_INCLUDE_GIT_HASH) | ||||
|   unset(Z3GITHASH) # Used in configure_file() | ||||
| endif() | ||||
| 
 | ||||
| ################################################################################ | ||||
| # Useful CMake functions/Macros | ||||
|  | @ -153,8 +159,8 @@ list(APPEND Z3_COMPONENT_CXX_DEFINES $<$<CONFIG:RelWithDebInfo>:_EXTERNAL_RELEAS | |||
| ################################################################################ | ||||
| # Find Python | ||||
| ################################################################################ | ||||
| find_package(PythonInterp 3 REQUIRED) | ||||
| message(STATUS "PYTHON_EXECUTABLE: ${PYTHON_EXECUTABLE}") | ||||
| find_package(Python3 REQUIRED COMPONENTS Interpreter) | ||||
| message(STATUS "Python3_EXECUTABLE: ${Python3_EXECUTABLE}") | ||||
| 
 | ||||
| ################################################################################ | ||||
| # Target architecture detection | ||||
|  |  | |||
|  | @ -277,7 +277,7 @@ The following useful options can be passed to CMake whilst configuring. | |||
| * ``CMAKE_INSTALL_PYTHON_PKG_DIR`` - STRING. The path to install the z3 python bindings. This can be relative (to ``CMAKE_INSTALL_PREFIX``) or absolute. | ||||
| * ``CMAKE_INSTALL_Z3_CMAKE_PACKAGE_DIR`` - STRING. The path to install CMake package files (e.g. ``/usr/lib/cmake/z3``). | ||||
| * ``CMAKE_INSTALL_API_BINDINGS_DOC`` - STRING. The path to install documentation for API bindings. | ||||
| * ``PYTHON_EXECUTABLE`` - STRING. The python executable to use during the build. | ||||
| * ``Python3_EXECUTABLE`` - STRING. The python executable to use during the build. | ||||
| * ``Z3_ENABLE_TRACING_FOR_NON_DEBUG`` - BOOL. If set to ``TRUE`` enable tracing in non-debug builds, if set to ``FALSE`` disable tracing in non-debug builds. Note in debug builds tracing is always enabled. | ||||
| * ``Z3_BUILD_LIBZ3_SHARED`` - BOOL. If set to ``TRUE`` build libz3 as a shared library otherwise build as a static library. | ||||
| * ``Z3_ENABLE_EXAMPLE_TARGETS`` - BOOL. If set to ``TRUE`` add the build targets for building the API examples. | ||||
|  | @ -303,7 +303,7 @@ The following useful options can be passed to CMake whilst configuring. | |||
| * ``Z3_ENABLE_CFI`` - BOOL. If set to ``TRUE`` will enable Control Flow Integrity security checks. This is only supported by MSVC and Clang and will | ||||
|     fail on other compilers. This requires Z3_LINK_TIME_OPTIMIZATION to also be enabled. | ||||
| * ``Z3_API_LOG_SYNC`` - BOOL. If set to ``TRUE`` will enable experimental API log sync feature. | ||||
| * ``WARNINGS_AS_ERRORS`` - STRING. If set to ``TRUE`` compiler warnings will be treated as errors. If set to ``False`` compiler warnings will not be treated as errors. | ||||
| * ``WARNINGS_AS_ERRORS`` - STRING. If set to ``ON`` compiler warnings will be treated as errors. If set to ``OFF`` compiler warnings will not be treated as errors. | ||||
|     If set to ``SERIOUS_ONLY`` a subset of compiler warnings will be treated as errors. | ||||
| * ``Z3_C_EXAMPLES_FORCE_CXX_LINKER`` - BOOL. If set to ``TRUE`` the C API examples will request that the C++ linker is used rather than the C linker. | ||||
| * ``Z3_BUILD_EXECUTABLE`` - BOOL. If set to ``TRUE`` build the z3 executable. Defaults to ``TRUE`` unless z3 is being built as a submodule in which case it defaults to ``FALSE``. | ||||
|  |  | |||
|  | @ -230,6 +230,7 @@ to Z3's C API. For more information, see [MachineArithmetic/README.md](https://g | |||
| * [.NET API](https://z3prover.github.io/api/html/namespace_microsoft_1_1_z3.html) | ||||
| * [Java API](https://z3prover.github.io/api/html/namespacecom_1_1microsoft_1_1z3.html) | ||||
| * [Python API](https://z3prover.github.io/api/html/namespacez3py.html) (also available in [pydoc format](https://z3prover.github.io/api/html/z3.html)) | ||||
| * [Rust](https://github.com/prove-rs/z3.rs) | ||||
| * C | ||||
| * OCaml | ||||
| * [Julia](https://github.com/ahumenberger/Z3.jl) | ||||
|  |  | |||
|  | @ -10,9 +10,34 @@ Version 4.next | |||
|     - native word level bit-vector solving. | ||||
|   - introduction of simple induction lemmas to handle a limited repertoire of induction proofs. | ||||
| 
 | ||||
| Version 4.12.3 | ||||
| Version 4.12.5 | ||||
| ============== | ||||
| 
 | ||||
| Version 4.12.4 | ||||
| ============== | ||||
| - Re-release fixing a few issues with 4.12: | ||||
|   - Python dependency on importlib.resources vs importlib_resources break automatic pypi installations. Supposedly fixed by conditioning dependency on Python 3.9 where the feature is built-in. | ||||
|   - Missing release of arm64 for Ubuntu. | ||||
|   - Futile attempt to streamline adding readme.md file as part of Nuget distribution. Nuget.org now requires a readme file. I was able to integrate the readme with the cmake build, but the cross-platform repackage in scripts/mk_nuget_task.py does not ingest a similar readme file with the CI pipelines. | ||||
| 
 | ||||
| Version 4.12.3 | ||||
| ============== | ||||
| - Alpha support for polymorphism. | ||||
|   - SMTLIB3-ish, C, Python | ||||
|   It adds the new command `(declare-type-var A)` that declares a symbol (in this case `A`) globally as a polymorphic type variable. | ||||
|   The C API contains a new function `Z3_mk_type_variable` and a new enumeration case `Z3_TYPE_VAR` as a kind associated with sorts. | ||||
|   All occurrences of `A` are treated as type variables. A function declaration whose signature uses `A` is treated as a shorthand | ||||
|   for declarations of all functions that use instances of `A`. | ||||
|   Assertions that use type variables are shorthands for assertions covering all instantiations. | ||||
| - Various (ongoing) performance fixes and improvements to smt.arith.solver=6 | ||||
| - A working version of solver.proof.trim=true option. Proofs logs created when using sat.smt=true may be trimmed by running z3 | ||||
|   on the generated proof log using the option solver.proof.trim=true.  | ||||
| - Optimizations LIA and NIA (linear integer arithmetic and non-linear integer (and real) arithmetic reasoning). | ||||
|   smt.arith.solver=6 is the default for most use cases. It trails smt.arith.solver=2 in some scenarios and the gap has been either removed or reduced. | ||||
|   smt.arith.solver=6 is complete for integrations of non-linear real arithmetic and theories, smt.arith.solver=2 is not.  | ||||
| - qel: Light quantifier elimination based on term graphs (egraphs), and corresponding Model Based Projection for arrays and ADTs. Used by Spacer and QSAT. | ||||
| - added real-closed fields features to C API, exposed more RCF over OCaml API | ||||
| - fixes to FP | ||||
| 
 | ||||
| Version 4.12.2 | ||||
| ============== | ||||
|  |  | |||
|  | @ -116,7 +116,7 @@ macro(z3_add_component component_name) | |||
|     set(_full_output_file_path "${CMAKE_CURRENT_BINARY_DIR}/${_output_file}") | ||||
|     message(STATUS "Adding rule to generate \"${_output_file}\"") | ||||
|     add_custom_command(OUTPUT "${_output_file}" | ||||
|       COMMAND "${PYTHON_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/scripts/pyg2hpp.py" "${_full_pyg_file_path}" "${CMAKE_CURRENT_BINARY_DIR}" | ||||
|       COMMAND "${Python3_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/scripts/pyg2hpp.py" "${_full_pyg_file_path}" "${CMAKE_CURRENT_BINARY_DIR}" | ||||
|       MAIN_DEPENDENCY "${_full_pyg_file_path}" | ||||
|       DEPENDS "${PROJECT_SOURCE_DIR}/scripts/pyg2hpp.py" | ||||
|               ${Z3_GENERATED_FILE_EXTRA_DEPENDENCIES} | ||||
|  | @ -275,7 +275,7 @@ macro(z3_add_install_tactic_rule) | |||
|   string(REPLACE ";" "\n" _tactic_header_files "${_tactic_header_files}") | ||||
|   file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/install_tactic.deps" ${_tactic_header_files}) | ||||
|   add_custom_command(OUTPUT "install_tactic.cpp" | ||||
|     COMMAND "${PYTHON_EXECUTABLE}" | ||||
|     COMMAND "${Python3_EXECUTABLE}" | ||||
|     "${PROJECT_SOURCE_DIR}/scripts/mk_install_tactic_cpp.py" | ||||
|     "${CMAKE_CURRENT_BINARY_DIR}" | ||||
|     "${CMAKE_CURRENT_BINARY_DIR}/install_tactic.deps" | ||||
|  | @ -313,7 +313,7 @@ macro(z3_add_memory_initializer_rule) | |||
|   endforeach() | ||||
| 
 | ||||
|   add_custom_command(OUTPUT "mem_initializer.cpp" | ||||
|     COMMAND "${PYTHON_EXECUTABLE}" | ||||
|     COMMAND "${Python3_EXECUTABLE}" | ||||
|     "${PROJECT_SOURCE_DIR}/scripts/mk_mem_initializer_cpp.py" | ||||
|     "${CMAKE_CURRENT_BINARY_DIR}" | ||||
|     ${_mem_init_finalize_headers} | ||||
|  | @ -349,7 +349,7 @@ macro(z3_add_gparams_register_modules_rule) | |||
|   unset(_component_register_module_header_files) | ||||
| 
 | ||||
|   add_custom_command(OUTPUT "gparams_register_modules.cpp" | ||||
|     COMMAND "${PYTHON_EXECUTABLE}" | ||||
|     COMMAND "${Python3_EXECUTABLE}" | ||||
|     "${PROJECT_SOURCE_DIR}/scripts/mk_gparams_register_modules_cpp.py" | ||||
|     "${CMAKE_CURRENT_BINARY_DIR}" | ||||
|     ${_register_module_header_files} | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ endif() | |||
| 
 | ||||
| add_custom_target(api_docs ${ALWAYS_BUILD_DOCS_ARG} | ||||
|   COMMAND | ||||
|   "${PYTHON_EXECUTABLE}" "${MK_API_DOC_SCRIPT}" | ||||
|   "${Python3_EXECUTABLE}" "${MK_API_DOC_SCRIPT}" | ||||
|   --build "${PROJECT_BINARY_DIR}" | ||||
|   --doxygen-executable "${DOXYGEN_EXECUTABLE}" | ||||
|   --output-dir "${DOC_DEST_DIR}" | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| (*  | ||||
| (* | ||||
|    Copyright (C) 2012 Microsoft Corporation | ||||
|    Author: CM Wintersteiger (cwinter) 2012-12-17 | ||||
| *) | ||||
|  | @ -19,7 +19,6 @@ open Z3.Arithmetic.Integer | |||
| open Z3.Arithmetic.Real | ||||
| open Z3.BitVector | ||||
| 
 | ||||
| 
 | ||||
| exception TestFailedException of string | ||||
| 
 | ||||
| (** | ||||
|  | @ -31,14 +30,14 @@ let  model_converter_test ( ctx : context ) = | |||
|   let yr = (Expr.mk_const ctx (Symbol.mk_string ctx "y") (Real.mk_sort ctx)) in | ||||
|   let g4 = (mk_goal ctx true false false ) in | ||||
|   (Goal.add g4 [ (mk_gt ctx xr (Real.mk_numeral_nd ctx 10 1)) ]) ; | ||||
|   (Goal.add g4 [ (mk_eq ctx  | ||||
|   (Goal.add g4 [ (mk_eq ctx | ||||
| 			 yr | ||||
| 			 (Arithmetic.mk_add ctx [ xr; (Real.mk_numeral_nd ctx 1 1)  ])) ]) ; | ||||
|   (Goal.add g4 [ (mk_gt ctx yr (Real.mk_numeral_nd ctx 1 1)) ]) ; | ||||
|   ( | ||||
|     let  ar = (Tactic.apply (mk_tactic ctx "simplify") g4 None) in | ||||
|     if ((get_num_subgoals ar) == 1 &&  | ||||
| 	   ((is_decided_sat (get_subgoal ar 0)) ||   | ||||
|     if ((get_num_subgoals ar) == 1 && | ||||
| 	   ((is_decided_sat (get_subgoal ar 0)) || | ||||
| 	       (is_decided_unsat (get_subgoal ar 0)))) then | ||||
|       raise (TestFailedException "") | ||||
|     else | ||||
|  | @ -46,8 +45,8 @@ let  model_converter_test ( ctx : context ) = | |||
|   ); | ||||
|   ( | ||||
|     let ar = (Tactic.apply (and_then ctx (mk_tactic ctx ("simplify")) (mk_tactic ctx "solve-eqs") []) g4 None) in | ||||
|     if ((get_num_subgoals ar) == 1 &&  | ||||
| 	   ((is_decided_sat (get_subgoal ar 0)) ||   | ||||
|     if ((get_num_subgoals ar) == 1 && | ||||
| 	   ((is_decided_sat (get_subgoal ar 0)) || | ||||
| 	       (is_decided_unsat (get_subgoal ar 0)))) then | ||||
|       raise (TestFailedException "") | ||||
|     else | ||||
|  | @ -57,15 +56,15 @@ let  model_converter_test ( ctx : context ) = | |||
|     let f e = (Solver.add solver [ e ]) in | ||||
|     ignore (List.map f (get_formulas (get_subgoal ar 0))) ; | ||||
|     let q = (check solver []) in | ||||
|     if q != SATISFIABLE then  | ||||
|     if q != SATISFIABLE then | ||||
|       raise (TestFailedException "") | ||||
|     else | ||||
|       let m = (get_model solver) in     | ||||
|       match m with  | ||||
|       let m = (get_model solver) in | ||||
|       match m with | ||||
| 	| None -> raise (TestFailedException "") | ||||
| 	| Some (m) ->  | ||||
| 	| Some (m) -> | ||||
| 	  Printf.printf "Solver says: %s\n" (string_of_status q) ; | ||||
| 	  Printf.printf "Model: \n%s\n" (Model.to_string m)  | ||||
| 	  Printf.printf "Model: \n%s\n" (Model.to_string m) | ||||
|   ) | ||||
| 
 | ||||
| (** | ||||
|  | @ -79,7 +78,7 @@ let basic_tests ( ctx : context ) = | |||
|   let bs = (Boolean.mk_sort ctx) in | ||||
|   let domain = [ bs; bs ] in | ||||
|   let f = (FuncDecl.mk_func_decl ctx fname domain bs) in | ||||
|   let fapp = (mk_app ctx f  | ||||
|   let fapp = (mk_app ctx f | ||||
| 		[ (Expr.mk_const ctx x bs); (Expr.mk_const ctx y bs) ]) in | ||||
|   let fargs2 = [ (mk_fresh_const ctx "cp" bs) ] in | ||||
|   let domain2 = [ bs ] in | ||||
|  | @ -100,8 +99,8 @@ let basic_tests ( ctx : context ) = | |||
|   ); | ||||
|   ( | ||||
|     let ar = (Tactic.apply (mk_tactic ctx "simplify") g None) in | ||||
|     if ((get_num_subgoals ar) == 1 &&  | ||||
| 	   ((is_decided_sat (get_subgoal ar 0)) ||   | ||||
|     if ((get_num_subgoals ar) == 1 && | ||||
| 	   ((is_decided_sat (get_subgoal ar 0)) || | ||||
| 	       (is_decided_unsat (get_subgoal ar 0)))) then | ||||
|       raise (TestFailedException "") | ||||
|     else | ||||
|  | @ -109,28 +108,28 @@ let basic_tests ( ctx : context ) = | |||
|   ); | ||||
|   ( | ||||
|     let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in | ||||
|     if ((get_num_subgoals ar) == 1 &&  | ||||
|     if ((get_num_subgoals ar) == 1 && | ||||
| 	   (not (is_decided_sat (get_subgoal ar 0)))) then | ||||
|       raise (TestFailedException "") | ||||
|     else | ||||
|       Printf.printf "Test passed.\n" | ||||
|   ); | ||||
|   (Goal.add g [ (mk_eq ctx  | ||||
|   (Goal.add g [ (mk_eq ctx | ||||
| 			(mk_numeral_int ctx 1 (BitVector.mk_sort ctx 32)) | ||||
| 			(mk_numeral_int ctx 2 (BitVector.mk_sort ctx 32))) ] ) | ||||
|   ; | ||||
|   ( | ||||
|     let ar = (Tactic.apply (mk_tactic ctx "smt") g None) in | ||||
|     if ((get_num_subgoals ar) == 1 &&  | ||||
|     if ((get_num_subgoals ar) == 1 && | ||||
| 	   (not (is_decided_unsat (get_subgoal ar 0)))) then | ||||
|       raise (TestFailedException "") | ||||
|     else  | ||||
|     else | ||||
|       Printf.printf "Test passed.\n" | ||||
|   ); | ||||
|   ( | ||||
|     let g2 = (mk_goal ctx true true false) in | ||||
|     let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in | ||||
|     if ((get_num_subgoals ar) == 1 &&  | ||||
|     if ((get_num_subgoals ar) == 1 && | ||||
| 	   (not (is_decided_sat (get_subgoal ar 0)))) then | ||||
|       raise (TestFailedException "") | ||||
|     else | ||||
|  | @ -140,10 +139,10 @@ let basic_tests ( ctx : context ) = | |||
|     let g2 = (mk_goal ctx true true false) in | ||||
|     (Goal.add g2 [ (Boolean.mk_false ctx) ]) ; | ||||
|     let ar = (Tactic.apply (mk_tactic ctx "smt") g2 None) in | ||||
|     if ((get_num_subgoals ar) == 1 &&  | ||||
|     if ((get_num_subgoals ar) == 1 && | ||||
| 	   (not (is_decided_unsat (get_subgoal ar 0)))) then | ||||
|       raise (TestFailedException "") | ||||
|     else  | ||||
|     else | ||||
|       Printf.printf "Test passed.\n" | ||||
|   ); | ||||
|   ( | ||||
|  | @ -155,10 +154,10 @@ let basic_tests ( ctx : context ) = | |||
|     let constr = (mk_eq ctx xc yc) in | ||||
|     (Goal.add g3 [ constr ] ) ; | ||||
|     let ar = (Tactic.apply (mk_tactic ctx "smt") g3 None) in | ||||
|     if ((get_num_subgoals ar) == 1 &&  | ||||
|     if ((get_num_subgoals ar) == 1 && | ||||
| 	   (not (is_decided_unsat (get_subgoal ar 0)))) then | ||||
|       raise (TestFailedException "") | ||||
|     else  | ||||
|     else | ||||
|       Printf.printf "Test passed.\n" | ||||
|   ) ; | ||||
|   model_converter_test ctx ; | ||||
|  | @ -169,12 +168,12 @@ let basic_tests ( ctx : context ) = | |||
|   Printf.printf "Numerator: %s Denominator: %s\n" (Real.numeral_to_string inum) (Real.numeral_to_string iden) ; | ||||
|   if ((Real.numeral_to_string inum) <> "42" || (Real.numeral_to_string iden) <> "43") then | ||||
|     raise (TestFailedException "") | ||||
|   else  | ||||
|   else | ||||
|     Printf.printf "Test passed.\n" | ||||
|   ; | ||||
|   if ((to_decimal_string rn 3) <> "0.976?") then | ||||
|     raise (TestFailedException "") | ||||
|   else  | ||||
|   else | ||||
|     Printf.printf "Test passed.\n" | ||||
|   ; | ||||
|   if (to_decimal_string (Real.mk_numeral_s ctx "-1231231232/234234333") 5 <> "-5.25640?") then | ||||
|  | @ -193,7 +192,7 @@ let basic_tests ( ctx : context ) = | |||
|     raise (TestFailedException "check") | ||||
|   ) | ||||
|   with Z3.Error(_) -> ( | ||||
|     Printf.printf "Exception caught, OK.\n"  | ||||
|     Printf.printf "Exception caught, OK.\n" | ||||
|   ) | ||||
| 
 | ||||
| (** | ||||
|  | @ -212,22 +211,22 @@ let  quantifier_example1 ( ctx : context ) = | |||
|   let xs = [ (Integer.mk_const ctx (List.nth names 0)); | ||||
| 	     (Integer.mk_const ctx (List.nth names 1)); | ||||
| 	     (Integer.mk_const ctx (List.nth names 2)) ] in | ||||
|    | ||||
|   let body_vars = (Boolean.mk_and ctx  | ||||
| 		     [ (mk_eq ctx  | ||||
| 			  (Arithmetic.mk_add ctx [ (List.nth vars 0) ; (Integer.mk_numeral_i ctx 1)])  | ||||
| 
 | ||||
|   let body_vars = (Boolean.mk_and ctx | ||||
| 		     [ (mk_eq ctx | ||||
| 			  (Arithmetic.mk_add ctx [ (List.nth vars 0) ; (Integer.mk_numeral_i ctx 1)]) | ||||
| 			  (Integer.mk_numeral_i ctx 2)) ; | ||||
| 		       (mk_eq ctx  | ||||
| 		       (mk_eq ctx | ||||
| 			  (Arithmetic.mk_add ctx [ (List.nth vars 1); (Integer.mk_numeral_i ctx 2)]) | ||||
| 			  (Arithmetic.mk_add ctx [ (List.nth vars 2); (Integer.mk_numeral_i ctx 3)])) ]) in | ||||
|   let body_const = (Boolean.mk_and ctx | ||||
| 		      [ (mk_eq ctx  | ||||
| 			   (Arithmetic.mk_add ctx [ (List.nth xs 0); (Integer.mk_numeral_i ctx 1)])  | ||||
| 		      [ (mk_eq ctx | ||||
| 			   (Arithmetic.mk_add ctx [ (List.nth xs 0); (Integer.mk_numeral_i ctx 1)]) | ||||
| 			   (Integer.mk_numeral_i ctx 2)) ; | ||||
| 			(mk_eq ctx  | ||||
| 			(mk_eq ctx | ||||
| 			   (Arithmetic.mk_add ctx [ (List.nth xs 1); (Integer.mk_numeral_i ctx 2)]) | ||||
| 			   (Arithmetic.mk_add ctx [ (List.nth xs 2); (Integer.mk_numeral_i ctx 3)])) ]) in | ||||
|    | ||||
| 
 | ||||
|   let x = (Quantifier.mk_forall ctx types names body_vars (Some 1) [] [] (Some (Symbol.mk_string ctx "Q1")) (Some (Symbol.mk_string ctx "skid1"))) in | ||||
|   Printf.printf "Quantifier X: %s\n" (Quantifier.to_string x) ; | ||||
|   let y = (Quantifier.mk_forall_const ctx xs body_const (Some 1) [] [] (Some (Symbol.mk_string ctx "Q2")) (Some (Symbol.mk_string ctx "skid2"))) in | ||||
|  | @ -242,8 +241,8 @@ let  quantifier_example1 ( ctx : context ) = | |||
| 
 | ||||
| open Z3.FloatingPoint | ||||
| 
 | ||||
| (**  | ||||
| 	A basic example of floating point arithmetic  | ||||
| (** | ||||
| 	A basic example of floating point arithmetic | ||||
| **) | ||||
| let fpa_example ( ctx : context ) = | ||||
|   Printf.printf "FPAExample\n" ; | ||||
|  | @ -271,7 +270,7 @@ let fpa_example ( ctx : context ) = | |||
| 				   (Boolean.mk_not ctx (mk_is_nan ctx y)) ; | ||||
| 				   (Boolean.mk_not ctx (mk_is_infinite ctx y)) ] in | ||||
|   let args3 = [ c3 ; (Boolean.mk_and ctx and_args) ] in | ||||
|   let c4 = (Boolean.mk_and ctx args3) in   | ||||
|   let c4 = (Boolean.mk_and ctx args3) in | ||||
|   (Printf.printf "c4: %s\n" (Expr.to_string c4)) ; | ||||
|   ( | ||||
|     let solver = (mk_solver ctx None) in | ||||
|  | @ -293,7 +292,7 @@ let fpa_example ( ctx : context ) = | |||
|   let c2 = (mk_to_fp_bv ctx | ||||
| 			  (mk_numeral_string ctx "4619567317775286272" (BitVector.mk_sort ctx 64)) | ||||
| 			  (mk_sort ctx 11 53)) in | ||||
|   let c3 = (mk_to_fp_int_real ctx  | ||||
|   let c3 = (mk_to_fp_int_real ctx | ||||
| 			  (RoundingMode.mk_rtz ctx) | ||||
|                           (mk_numeral_string ctx "2" (Integer.mk_sort ctx)) | ||||
| 			  (mk_numeral_string ctx "1.75" (Real.mk_sort ctx)) | ||||
|  | @ -304,7 +303,7 @@ let fpa_example ( ctx : context ) = | |||
|   let args3 = [ (mk_eq ctx c1 c2) ; | ||||
| 				(mk_eq ctx c1 c3) ; | ||||
| 				(mk_eq ctx c1 c4) ] in | ||||
|   let c5 = (Boolean.mk_and ctx args3) in   | ||||
|   let c5 = (Boolean.mk_and ctx args3) in | ||||
|   (Printf.printf "c5: %s\n" (Expr.to_string c5)) ; | ||||
|   ( | ||||
|     let solver = (mk_solver ctx None) in | ||||
|  | @ -313,9 +312,70 @@ let fpa_example ( ctx : context ) = | |||
| 	  raise (TestFailedException "") | ||||
|     else | ||||
| 	  Printf.printf "Test passed.\n" | ||||
|   )  | ||||
|   ) | ||||
| 
 | ||||
| let _ =  | ||||
| (** | ||||
| 	A basic example of RCF usage | ||||
| **) | ||||
| let rcf_example ( ctx : context ) = | ||||
|   Printf.printf "RCFExample\n" ; | ||||
|   let pi = RCF.mk_pi ctx in | ||||
|   let e = RCF.mk_e ctx in | ||||
|   let inf0 = RCF.mk_infinitesimal ctx in | ||||
|   let inf1 = RCF.mk_infinitesimal ctx in | ||||
|   let r = RCF.mk_rational ctx "42.001" in | ||||
|   let pi_div_e = RCF.div ctx pi e in | ||||
|   let pi_div_r = RCF.div ctx pi r in | ||||
|   (Printf.printf "e: %s,  pi: %s, e==pi: %b, e < pi: %b\n" | ||||
|     (RCF.num_to_string ctx e true false) | ||||
|     (RCF.num_to_string ctx pi true false) | ||||
|     (RCF.eq ctx e pi) | ||||
|     (RCF.lt ctx e pi)) ; | ||||
|   Printf.printf "pi_div_e: %s.\n" (RCF.num_to_string ctx pi_div_e true false); | ||||
|   Printf.printf "pi_div_r: %s.\n" (RCF.num_to_string ctx pi_div_r true false); | ||||
|   Printf.printf "inf0: %s.\n" (RCF.num_to_string ctx inf0 true false); | ||||
|   Printf.printf "(RCF.is_rational ctx pi): %b.\n" (RCF.is_rational ctx pi); | ||||
|   Printf.printf "(RCF.is_algebraic ctx pi): %b.\n" (RCF.is_algebraic ctx pi); | ||||
|   Printf.printf "(RCF.is_transcendental ctx pi): %b.\n" (RCF.is_transcendental ctx pi); | ||||
|   Printf.printf "(RCF.is_rational ctx r): %b.\n" (RCF.is_rational ctx r); | ||||
|   Printf.printf "(RCF.is_algebraic ctx r): %b.\n" (RCF.is_algebraic ctx r); | ||||
|   Printf.printf "(RCF.is_transcendental ctx r): %b.\n" (RCF.is_transcendental ctx r); | ||||
|   Printf.printf "(RCF.is_infinitesimal ctx inf0): %b.\n" (RCF.is_infinitesimal ctx inf0); | ||||
|   Printf.printf "(RCF.extension_index ctx inf0): %d.\n" (RCF.extension_index ctx inf0); | ||||
|   Printf.printf "(RCF.extension_index ctx inf1): %d.\n" (RCF.extension_index ctx inf1); | ||||
|   let poly:RCF.rcf_num list = [ e; pi; inf0 ] in | ||||
|   let rs:RCF.root list = RCF.roots ctx poly in | ||||
|   let print_root (x:RCF.root) = | ||||
|     begin | ||||
|     Printf.printf "root: %s\n%!" (RCF.num_to_string ctx x.obj true false); | ||||
|     if RCF.is_algebraic ctx x.obj then ( | ||||
|       (match x.interval with | ||||
|       | Some ivl -> Printf.printf "  interval: (%b, %b, %s, %b, %b, %s)\n" | ||||
|                                   ivl.lower_is_inf | ||||
|                                   ivl.lower_is_open | ||||
|                                   (RCF.num_to_string ctx ivl.lower true false) | ||||
|                                   ivl.upper_is_inf | ||||
|                                   ivl.upper_is_open | ||||
|                                   (RCF.num_to_string ctx ivl.upper true false); | ||||
|       | None -> ()); | ||||
|       Printf.printf "  polynomial coefficients:"; | ||||
|       List.iter (fun c -> Printf.printf " %s" (RCF.num_to_string ctx c false false)) x.polynomial; | ||||
|       Printf.printf "\n"; | ||||
|       Printf.printf "  sign conditions:"; | ||||
|       List.iter | ||||
|         (fun (poly, sign) -> | ||||
|           List.iter (fun p -> Printf.printf " %s" (RCF.num_to_string ctx p true false)) poly; | ||||
|           Printf.printf " %s" (if sign > 0 then "> 0" else if sign < 0 then "< 0" else "= 0")) | ||||
|         x.sign_conditions; | ||||
|       Printf.printf "\n") | ||||
|     end | ||||
|   in | ||||
|   List.iter print_root rs; | ||||
|   RCF.del_roots ctx rs; | ||||
|   RCF.del_list ctx [pi; e; inf0; inf1; r; pi_div_e; pi_div_r]; | ||||
|   Printf.printf "Test passed.\n" | ||||
| 
 | ||||
| let _ = | ||||
|   try ( | ||||
|     if not (Log.open_ "z3.log") then | ||||
|       raise (TestFailedException "Log couldn't be opened.") | ||||
|  | @ -340,6 +400,7 @@ let _ = | |||
| 	basic_tests ctx ; | ||||
| 	quantifier_example1 ctx ; | ||||
| 	fpa_example ctx ; | ||||
|   rcf_example ctx ; | ||||
| 	Printf.printf "Disposing...\n"; | ||||
| 	Gc.full_major () | ||||
|       ); | ||||
|  | @ -348,5 +409,6 @@ let _ = | |||
|   ) with Error(msg) -> ( | ||||
|     Printf.printf "Z3 EXCEPTION: %s\n" msg ; | ||||
|     exit 1 | ||||
|   )     | ||||
|   ) | ||||
| ;; | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										27
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										27
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							|  | @ -1,27 +0,0 @@ | |||
| { | ||||
|   "requires": true, | ||||
|   "lockfileVersion": 1, | ||||
|   "dependencies": { | ||||
|     "async-mutex": { | ||||
|       "version": "0.3.2", | ||||
|       "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.3.2.tgz", | ||||
|       "integrity": "sha512-HuTK7E7MT7jZEh1P9GtRW9+aTWiDWWi9InbZ5hjxrnRa39KS4BW04+xLBhYNS2aXhHUIKZSw3gj4Pn1pj+qGAA==", | ||||
|       "requires": { | ||||
|         "tslib": "^2.3.1" | ||||
|       } | ||||
|     }, | ||||
|     "tslib": { | ||||
|       "version": "2.4.0", | ||||
|       "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", | ||||
|       "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" | ||||
|     }, | ||||
|     "z3-solver": { | ||||
|       "version": "4.9.0", | ||||
|       "resolved": "https://registry.npmjs.org/z3-solver/-/z3-solver-4.9.0.tgz", | ||||
|       "integrity": "sha512-clSV0uyHsfrO84pSbHxoqvmd5HgSG4CoSJG2f8U65hBVylbV6p/0svctQWee9W2fWo0IsxHYRjxz2Z85GT0LAA==", | ||||
|       "requires": { | ||||
|         "async-mutex": "^0.3.2" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -24,14 +24,16 @@ def mk_dir(d): | |||
| os_info = {  'ubuntu-latest' : ('so', 'linux-x64'), | ||||
|              'ubuntu-18' : ('so', 'linux-x64'), | ||||
|              'ubuntu-20' : ('so', 'linux-x64'), | ||||
|              'glibc' : ('so', 'linux-x64'), | ||||
|              #'glibc-2.35' : ('so', 'linux-x64'), | ||||
|              'x64-glibc-2.35' : ('so', 'linux-x64'), | ||||
|              'x64-win' : ('dll', 'win-x64'), | ||||
|              'x86-win' : ('dll', 'win-x86'), | ||||
|              'x64-osx' : ('dylib', 'osx-x64'), | ||||
|              'arm64-osx' : ('dylib', 'osx-arm64'), | ||||
|              'debian' : ('so', 'linux-x64') } | ||||
| 
 | ||||
| # Nuget not supported for ARM | ||||
| #'arm-glibc-2.35' : ('so', 'linux-arm64'), | ||||
| #'arm64-osx' : ('dylib', 'osx-arm64'), | ||||
| 
 | ||||
|          | ||||
| 
 | ||||
| def classify_package(f, arch): | ||||
|  | @ -87,6 +89,11 @@ def mk_icon(source_root): | |||
|     mk_dir("out/content") | ||||
|     shutil.copy(f"{source_root}/resources/icon.jpg", "out/content/icon.jpg") | ||||
| 
 | ||||
| def mk_readme(source_root): | ||||
|     mk_dir("out/content") | ||||
|     shutil.copy(f"{source_root}/src/api/dotnet/README.md", "out/README.md") | ||||
| 
 | ||||
| 
 | ||||
|      | ||||
| def create_nuget_spec(version, repo, branch, commit, symbols, arch): | ||||
|     arch = f".{arch}" if arch == "x86" else "" | ||||
|  | @ -142,6 +149,7 @@ class Env: | |||
|         unpack(self.packages, self.symbols, self.arch) | ||||
|         mk_targets(self.source_root) | ||||
|         mk_icon(self.source_root) | ||||
| #       mk_readme(self.source_root) | ||||
|         create_nuget_spec(self.version, self.repo, self.branch, self.commit, self.symbols, self.arch) | ||||
|          | ||||
| def main(): | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
| from mk_util import * | ||||
| 
 | ||||
| def init_version(): | ||||
|     set_version(4, 12, 3, 0) # express a default build version or pick up ci build version | ||||
|     set_version(4, 12, 5, 0) # express a default build version or pick up ci build version | ||||
|      | ||||
| # Z3 Project definition | ||||
| def init_project_def(): | ||||
|  |  | |||
|  | @ -1736,6 +1736,7 @@ class DotNetDLLComponent(Component): | |||
|     <GeneratePackageOnBuild>true</GeneratePackageOnBuild> | ||||
|     <Authors>Microsoft</Authors> | ||||
|     <Company>Microsoft</Company> | ||||
|     <PackageReadmeFile>README.md</PackageReadmeFile> | ||||
|     <EnableDefaultCompileItems>false</EnableDefaultCompileItems> | ||||
|     <Description>Z3 is a satisfiability modulo theories solver from Microsoft Research.</Description> | ||||
|     <Copyright>Copyright Microsoft Corporation. All rights reserved.</Copyright> | ||||
|  | @ -1745,9 +1746,10 @@ class DotNetDLLComponent(Component): | |||
| 
 | ||||
|   <ItemGroup> | ||||
|     <Compile Include="..\%s\*.cs;*.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" /> | ||||
|     <None Include="..\%s\README.md" Pack="true" PackagePath="/"/> | ||||
|   </ItemGroup> | ||||
| 
 | ||||
| </Project>""" % (version, key, self.to_src_dir) | ||||
| </Project>""" % (version, key, self.to_src_dir, self.to_src_dir) | ||||
| 
 | ||||
|         mk_dir(os.path.join(BUILD_DIR, 'dotnet')) | ||||
|         csproj = os.path.join('dotnet', 'z3.csproj') | ||||
|  | @ -2519,19 +2521,19 @@ def mk_config(): | |||
|                 'SLINK_FLAGS=/nologo /LDd\n' % static_opt) | ||||
|             if VS_X64: | ||||
|                 config.write( | ||||
|                     'CXXFLAGS=/c %s /W3 /WX- /Od /Oy- /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /Gm- /RTC1 %s %s\n' % (CXXFLAGS, extra_opt, static_opt)) | ||||
|                     'CXXFLAGS=/c %s /Zi /W3 /WX- /Od /Oy- /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /Gm- /RTC1 %s %s\n' % (CXXFLAGS, extra_opt, static_opt)) | ||||
|                 config.write( | ||||
|                     'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' | ||||
|                     'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (link_extra_opt, maybe_disable_dynamic_base, link_extra_opt)) | ||||
|                     'LINK_EXTRA_FLAGS=/link /PROFILE /DEBUG:full /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' | ||||
|                     'SLINK_EXTRA_FLAGS=/link /PROFILE /DEBUG:full /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (link_extra_opt, maybe_disable_dynamic_base, link_extra_opt)) | ||||
|             elif VS_ARM: | ||||
|                 print("ARM on VS is unsupported") | ||||
|                 exit(1) | ||||
|             else: | ||||
|                 config.write( | ||||
|                     'CXXFLAGS=/c %s /W3 /WX- /Od /Oy- /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /Gm- /RTC1 /arch:SSE2 %s %s\n' % (CXXFLAGS, extra_opt, static_opt)) | ||||
|                     'CXXFLAGS=/c %s /Zi /W3 /WX- /Od /Oy- /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /Gm- /RTC1 /arch:SSE2 %s %s\n' % (CXXFLAGS, extra_opt, static_opt)) | ||||
|                 config.write( | ||||
|                     'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' | ||||
|                     'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (link_extra_opt, maybe_disable_dynamic_base, link_extra_opt)) | ||||
|                     'LINK_EXTRA_FLAGS=/link /PROFILE /DEBUG:full /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' | ||||
|                     'SLINK_EXTRA_FLAGS=/link /PROFILE /DEBUG:full /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (link_extra_opt, maybe_disable_dynamic_base, link_extra_opt)) | ||||
|         else: | ||||
|             # Windows Release mode | ||||
|             LTCG=' /LTCG' if SLOW_OPTIMIZE else '' | ||||
|  | @ -2544,19 +2546,19 @@ def mk_config(): | |||
|                 extra_opt = '%s /D _TRACE ' % extra_opt | ||||
|             if VS_X64: | ||||
|                 config.write( | ||||
|                     'CXXFLAGS=/c%s %s /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D NDEBUG /D _LIB /D UNICODE /Gm- /GF /Gy /TP %s %s\n' % (GL, CXXFLAGS, extra_opt, static_opt)) | ||||
|                     'CXXFLAGS=/c%s %s /Zi /W3 /WX- /O2 /D _EXTERNAL_RELEASE /D NDEBUG /D _LIB /D UNICODE /Gm- /GF /Gy /TP %s %s\n' % (GL, CXXFLAGS, extra_opt, static_opt)) | ||||
|                 config.write( | ||||
|                     'LINK_EXTRA_FLAGS=/link%s /profile /MACHINE:X64 /SUBSYSTEM:CONSOLE /STACK:8388608 %s\n' | ||||
|                     'SLINK_EXTRA_FLAGS=/link%s /profile /MACHINE:X64 /SUBSYSTEM:WINDOWS /STACK:8388608 %s\n' % (LTCG, link_extra_opt, LTCG, link_extra_opt)) | ||||
|                     'LINK_EXTRA_FLAGS=/link%s /PROFILE /DEBUG:full /profile /MACHINE:X64 /SUBSYSTEM:CONSOLE /STACK:8388608 %s\n' | ||||
|                     'SLINK_EXTRA_FLAGS=/link%s /PROFILE /DEBUG:full /profile /MACHINE:X64 /SUBSYSTEM:WINDOWS /STACK:8388608 %s\n' % (LTCG, link_extra_opt, LTCG, link_extra_opt)) | ||||
|             elif VS_ARM: | ||||
|                 print("ARM on VS is unsupported") | ||||
|                 exit(1) | ||||
|             else: | ||||
|                 config.write( | ||||
|                     'CXXFLAGS=/c%s %s /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D NDEBUG /D _CONSOLE /D ASYNC_COMMANDS /Gm- /arch:SSE2 %s %s\n' % (GL, CXXFLAGS, extra_opt, static_opt)) | ||||
|                     'CXXFLAGS=/c%s %s /Zi /WX- /O2 /Oy- /D _EXTERNAL_RELEASE /D NDEBUG /D _CONSOLE /D ASYNC_COMMANDS /Gm- /arch:SSE2 %s %s\n' % (GL, CXXFLAGS, extra_opt, static_opt)) | ||||
|                 config.write( | ||||
|                     'LINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' | ||||
|                     'SLINK_EXTRA_FLAGS=/link%s /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (LTCG, link_extra_opt, LTCG, maybe_disable_dynamic_base, link_extra_opt)) | ||||
|                     'LINK_EXTRA_FLAGS=/link%s /PROFILE /DEBUG:full /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT %s\n' | ||||
|                     'SLINK_EXTRA_FLAGS=/link%s /PROFILE /DEBUG:full /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 %s %s\n' % (LTCG, link_extra_opt, LTCG, maybe_disable_dynamic_base, link_extra_opt)) | ||||
| 
 | ||||
|         config.write('CFLAGS=$(CXXFLAGS)\n') | ||||
| 
 | ||||
|  | @ -2664,7 +2666,7 @@ def mk_config(): | |||
|             LDFLAGS = '%s -static-libgcc -static-libstdc++' % LDFLAGS | ||||
|         if sysname == 'Linux' and machine.startswith('armv7') or machine.startswith('armv8'): | ||||
|             CXXFLAGS = '%s -fpic' % CXXFLAGS | ||||
|         if IS_OSX and IS_ARCH_ARM64: | ||||
|         if IS_ARCH_ARM64 and IS_OSX: | ||||
|             print("Setting arm64") | ||||
|             CXXFLAGS = '%s -arch arm64' % CXXFLAGS | ||||
|             LDFLAGS = '%s -arch arm64' % LDFLAGS | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| variables: | ||||
|   Major: '4' | ||||
|   Minor: '12' | ||||
|   Patch: '3' | ||||
|   Patch: '5' | ||||
|   AssemblyVersion: $(Major).$(Minor).$(Patch).$(Build.BuildId) | ||||
|   NightlyVersion: $(AssemblyVersion)-$(Build.DefinitionName) | ||||
| 
 | ||||
|  | @ -63,11 +63,29 @@ stages: | |||
|         artifactName: 'Ubuntu' | ||||
|         targetPath: $(Build.ArtifactStagingDirectory) | ||||
| 
 | ||||
|   - job: UbuntuArm64 | ||||
|     displayName: "Ubuntu ARM64 build" | ||||
|     pool: | ||||
|       vmImage: "ubuntu-latest" | ||||
|     steps: | ||||
|     - script: sudo apt update | ||||
|     - script: sudo apt install gcc-arm-none-eabi -y | ||||
|     - script: sudo apt install gcc-arm-linux-gnueabihf -y | ||||
|     - script: sudo apt install gcc-aarch64-linux-gnu -y | ||||
|     - script: sudo apt install g++-aarch64-linux-gnu -y | ||||
|     - script: CXX=aarch64-linux-gnu-g++ CC=aarch64-linux-gnu-gcc python scripts/mk_unix_dist.py --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk --arch=arm64 | ||||
|     - script: cp dist/*.zip $(Build.ArtifactStagingDirectory)/. | ||||
|     - task: PublishPipelineArtifact@0 | ||||
|       inputs: | ||||
|         artifactName: 'UbuntuArm64' | ||||
|         targetPath: $(Build.ArtifactStagingDirectory) | ||||
| 
 | ||||
|   - job: UbuntuDoc | ||||
|     displayName: "Ubuntu Doc build" | ||||
|     pool: | ||||
|       vmImage: "ubuntu-latest" | ||||
|     steps: | ||||
|     - script: pip3 install importlib-resources | ||||
|     - script: sudo apt-get install ocaml opam libgmp-dev | ||||
|     - script: opam init -y | ||||
|     - script: eval `opam config env`; opam install zarith ocamlfind -y | ||||
|  | @ -86,8 +104,8 @@ stages: | |||
|         set -e | ||||
|         eval `opam config env`  | ||||
|         cd doc | ||||
|         python mk_api_doc.py --mld --z3py-package-path=../build/python/z3 | ||||
|         python mk_params_doc.py  | ||||
|         python3 mk_api_doc.py --mld --z3py-package-path=../build/python/z3 | ||||
|         python3 mk_params_doc.py  | ||||
|         mkdir api/html/ml | ||||
|         ocamldoc -html -d api/html/ml -sort -hide Z3 -I $( ocamlfind query zarith ) -I ../build/api/ml ../build/api/ml/z3enums.mli ../build/api/ml/z3.mli | ||||
|         cd .. | ||||
|  | @ -238,6 +256,16 @@ stages: | |||
|       inputs: | ||||
|         artifact: 'Ubuntu' | ||||
|         path: $(Agent.TempDirectory)\package | ||||
|     - task: DownloadPipelineArtifact@2 | ||||
|       displayName: 'Download Ubuntu 20.04 Build' | ||||
|       inputs: | ||||
|         artifact: 'Ubuntu-20.04' | ||||
|         path: $(Agent.TempDirectory)\package | ||||
|     - task: DownloadPipelineArtifact@2 | ||||
|       displayName: 'Download Ubuntu ARM64 Build' | ||||
|       inputs: | ||||
|         artifact: 'UbuntuArm64' | ||||
|         path: $(Agent.TempDirectory)\package | ||||
|     - task: DownloadPipelineArtifact@2 | ||||
|       displayName: 'Download macOS Build' | ||||
|       inputs: | ||||
|  | @ -521,6 +549,11 @@ stages: | |||
|       inputs: | ||||
|         artifactName: 'MacArm64' | ||||
|         targetPath: tmp | ||||
|     - task: DownloadPipelineArtifact@2 | ||||
|       displayName: "Download Ubuntu Arm64" | ||||
|       inputs: | ||||
|         artifactName: 'UbuntuArm64' | ||||
|         targetPath: tmp | ||||
|     - task: DownloadPipelineArtifact@2 | ||||
|       displayName: "Download Ubuntu" | ||||
|       inputs: | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ | |||
| trigger: none | ||||
| 
 | ||||
| variables: | ||||
|   ReleaseVersion: '4.12.3' | ||||
|   ReleaseVersion: '4.12.5' | ||||
| 
 | ||||
| stages: | ||||
| 
 | ||||
|  | @ -114,11 +114,26 @@ stages: | |||
|         artifactName: 'UbuntuBuild20' | ||||
|         targetPath: $(Build.ArtifactStagingDirectory) | ||||
| 
 | ||||
|   - job: UbuntuArm64 | ||||
|     displayName: "Ubuntu ARM64 build" | ||||
|     pool: | ||||
|       vmImage: "ubuntu-latest" | ||||
|     steps: | ||||
|     - script: python scripts/mk_unix_dist.py --dotnet-key=$(Build.SourcesDirectory)/resources/z3.snk --arch=arm64 | ||||
|     - script: git clone https://github.com/z3prover/z3test z3test | ||||
|     - script: python z3test/scripts/test_benchmarks.py build-dist/z3 z3test/regressions/smt2     | ||||
|     - script: cp dist/*.zip $(Build.ArtifactStagingDirectory)/. | ||||
|     - task: PublishPipelineArtifact@0 | ||||
|       inputs: | ||||
|         artifactName: 'UbuntuArm64' | ||||
|         targetPath: $(Build.ArtifactStagingDirectory) | ||||
| 
 | ||||
|   - job: UbuntuDoc | ||||
|     displayName: "Ubuntu Doc build" | ||||
|     pool: | ||||
|       vmImage: "ubuntu-latest" | ||||
|     steps: | ||||
|     - script: pip3 install importlib-resources | ||||
|     - script: sudo apt-get install ocaml opam libgmp-dev | ||||
|     - script: opam init -y | ||||
|     - script: eval `opam config env`; opam install zarith ocamlfind -y | ||||
|  | @ -137,8 +152,8 @@ stages: | |||
|         set -e | ||||
|         eval `opam config env`  | ||||
|         cd doc | ||||
|         python mk_api_doc.py --mld --z3py-package-path=../build/python/z3 | ||||
|         python mk_params_doc.py  | ||||
|         python3 mk_api_doc.py --mld --z3py-package-path=../build/python/z3 | ||||
|         python3 mk_params_doc.py  | ||||
|         mkdir api/html/ml | ||||
|         ocamldoc -html -d api/html/ml -sort -hide Z3 -I $( ocamlfind query zarith ) -I ../build/api/ml ../build/api/ml/z3enums.mli ../build/api/ml/z3.mli | ||||
|         cd .. | ||||
|  | @ -225,6 +240,11 @@ stages: | |||
|       inputs: | ||||
|         artifact: 'UbuntuBuild20' | ||||
|         path: $(Agent.TempDirectory)\package | ||||
|     - task: DownloadPipelineArtifact@2 | ||||
|       displayName: 'Download Ubuntu ARM64 Build' | ||||
|       inputs: | ||||
|         artifact: 'UbuntuArm64' | ||||
|         path: $(Agent.TempDirectory)\package	 | ||||
|     - task: DownloadPipelineArtifact@2 | ||||
|       displayName: 'Download macOS Build' | ||||
|       inputs: | ||||
|  | @ -480,6 +500,11 @@ stages: | |||
|       inputs: | ||||
|         artifact: 'UbuntuBuild' | ||||
|         path: $(Agent.TempDirectory) | ||||
|     - task: DownloadPipelineArtifact@2 | ||||
|       displayName: "Download Ubuntu Arm64" | ||||
|       inputs: | ||||
|         artifactName: 'UbuntuArm64' | ||||
|         path: $(Agent.TempDirectory) | ||||
|     - task: DownloadPipelineArtifact@2 | ||||
|       displayName: "Download Doc" | ||||
|       inputs: | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ steps: | |||
|     cd build | ||||
|     mkdir -p examples/java | ||||
|     cp ../examples/java/JavaExample.java examples/java/ | ||||
|     javac examples/java/Javaexamplejava -classpath com.microsoft.z3.jar | ||||
|     javac examples/java/JavaExample.java -classpath com.microsoft.z3.jar | ||||
|     export LD_LIBRARY_PATH=$(pwd):${LD_LIBRARY_PATH} | ||||
|     java -cp .:examples/java:com.microsoft.z3.jar JavaExample | ||||
|     cd .. | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| #  - !/usr/bin/env python | ||||
| #!/usr/bin/env python | ||||
| ############################################ | ||||
| # Copyright (c) 2012 Microsoft Corporation | ||||
| # | ||||
|  | @ -426,9 +426,10 @@ def mk_dotnet(dotnet): | |||
|     dotnet.write('    {\n\n') | ||||
| 
 | ||||
|     for name, ret, sig in Closures: | ||||
|         sig = sig.replace("unsigned const*","uint[]") | ||||
|         sig = sig.replace("void*","voidp").replace("unsigned","uint") | ||||
|         sig = sig.replace("Z3_ast*","ref IntPtr").replace("uint*","ref uint").replace("Z3_lbool*","ref int") | ||||
|         ret = ret.replace("void*","voidp").replace("unsigned","uint") | ||||
|         ret = ret.replace("void*","voidp").replace("unsigned","uint")         | ||||
|         if "*" in sig or "*" in ret: | ||||
|             continue | ||||
|         dotnet.write('        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]\n') | ||||
|  | @ -1826,17 +1827,28 @@ def write_core_py_preamble(core_py): | |||
|   core_py.write( | ||||
| """ | ||||
| # Automatically generated file | ||||
| import atexit | ||||
| import sys, os | ||||
| import contextlib | ||||
| import ctypes | ||||
| import pkg_resources | ||||
| if sys.version_info >= (3, 9): | ||||
|     import importlib.resources as importlib_resources | ||||
| else: | ||||
|     import importlib_resources | ||||
| from .z3types import * | ||||
| from .z3consts import * | ||||
| 
 | ||||
| _file_manager = contextlib.ExitStack() | ||||
| atexit.register(_file_manager.close) | ||||
| _ext = 'dll' if sys.platform in ('win32', 'cygwin') else 'dylib' if sys.platform == 'darwin' else 'so' | ||||
| _lib = None | ||||
| _z3_lib_resource = importlib_resources.files('z3').joinpath('lib') | ||||
| _z3_lib_resource_path = _file_manager.enter_context( | ||||
|     importlib_resources.as_file(_z3_lib_resource) | ||||
| ) | ||||
| _default_dirs = ['.', | ||||
|                  os.path.dirname(os.path.abspath(__file__)), | ||||
|                  pkg_resources.resource_filename('z3', 'lib'), | ||||
|                  _z3_lib_resource_path, | ||||
|                  os.path.join(sys.prefix, 'lib'), | ||||
|                  None] | ||||
| _all_dirs = [] | ||||
|  | @ -1886,10 +1898,10 @@ if _lib is None: | |||
|   print("  - to the custom Z3_LIB_DIRS Python-builtin before importing the z3 module, e.g. via") | ||||
|   if sys.version < '3': | ||||
|     print("    import __builtin__") | ||||
|     print("    __builtin__.Z3_LIB_DIRS = [ '/path/to/libz3.%s' ] " % _ext) | ||||
|     print("    __builtin__.Z3_LIB_DIRS = [ '/path/to/z3/lib/dir' ] # directory containing libz3.%s" % _ext) | ||||
|   else: | ||||
|     print("    import builtins") | ||||
|     print("    builtins.Z3_LIB_DIRS = [ '/path/to/libz3.%s' ] " % _ext) | ||||
|     print("    builtins.Z3_LIB_DIRS = [ '/path/to/z3/lib/dir' ] # directory containing libz3.%s" % _ext) | ||||
|   print(_failures) | ||||
|   raise Z3Exception("libz3.%s not found." % _ext) | ||||
| 
 | ||||
|  | @ -1919,7 +1931,7 @@ _error_handler_type  = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_uint) | |||
| _lib.Z3_set_error_handler.restype  = None | ||||
| _lib.Z3_set_error_handler.argtypes = [ContextObj, _error_handler_type] | ||||
| 
 | ||||
| Z3_on_clause_eh = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) | ||||
| Z3_on_clause_eh = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint, ctypes.POINTER(ctypes.c_uint), ctypes.c_void_p) | ||||
| Z3_push_eh  = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p) | ||||
| Z3_pop_eh   = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint) | ||||
| Z3_fresh_eh = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p) | ||||
|  |  | |||
|  | @ -220,7 +220,7 @@ if (MSVC) | |||
|   set(dll_module_exports_file "${CMAKE_CURRENT_BINARY_DIR}/api_dll.def") | ||||
|   add_custom_command(OUTPUT "${dll_module_exports_file}" | ||||
|     COMMAND | ||||
|       "${PYTHON_EXECUTABLE}" | ||||
|       "${Python3_EXECUTABLE}" | ||||
|       "${PROJECT_SOURCE_DIR}/scripts/mk_def_file.py" | ||||
|       "${dll_module_exports_file}" | ||||
|       "libz3" | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ | |||
| 
 | ||||
| #include "ast/bv_decl_plugin.h" | ||||
| #include "ast/array_decl_plugin.h" | ||||
| #include "ast/ast_ll_pp.h" | ||||
| 
 | ||||
| class ackr_helper { | ||||
| public: | ||||
|  | @ -40,10 +41,8 @@ public: | |||
|     inline bool is_uninterp_fn(app const * a) const { | ||||
|         if (is_uninterp(a)) | ||||
|             return true; | ||||
|         else { | ||||
|             decl_plugin * p = m_bvutil.get_manager().get_plugin(a->get_family_id()); | ||||
|             return p->is_considered_uninterpreted(a->get_decl()); | ||||
|         } | ||||
|         decl_plugin * p = m_bvutil.get_manager().get_plugin(a->get_family_id()); | ||||
|         return p->is_considered_uninterpreted(a->get_decl());         | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|  | @ -64,9 +63,8 @@ public: | |||
|             } | ||||
|         } | ||||
|         else { | ||||
|             for (expr* arg : *a) { | ||||
|             for (expr* arg : *a)  | ||||
|                 non_select.mark(arg, true); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -112,7 +110,8 @@ public: | |||
|     } | ||||
| 
 | ||||
|     void insert(fun2terms_map& f2t, sel2terms_map& s2t, app* a) { | ||||
|         if (a->get_num_args() == 0) return; | ||||
|         if (a->get_num_args() == 0) | ||||
|             return; | ||||
|         ast_manager& m = m_bvutil.get_manager(); | ||||
|         app_set* ts = nullptr; | ||||
|         bool is_const_args = true; | ||||
|  | @ -129,21 +128,18 @@ public: | |||
|                 ts = alloc(app_set); | ||||
|                 f2t.insert(fd, ts); | ||||
|             } | ||||
|             is_const_args = m.is_value(a->get_arg(0)); | ||||
|             is_const_args = m.is_unique_value(a->get_arg(0)); | ||||
|         } | ||||
|         else { | ||||
|         else  | ||||
|             return; | ||||
|         } | ||||
|         for (unsigned i = 1; is_const_args && i < a->get_num_args(); ++i) { | ||||
|             is_const_args &= m.is_value(a->get_arg(i)); | ||||
|         } | ||||
|          | ||||
|         if (is_const_args) { | ||||
|         for (unsigned i = 1; is_const_args && i < a->get_num_args(); ++i)  | ||||
|             is_const_args &= m.is_unique_value(a->get_arg(i)); | ||||
|          | ||||
|         if (is_const_args)  | ||||
|             ts->const_args.insert(a); | ||||
|         } | ||||
|         else { | ||||
|         else  | ||||
|             ts->var_args.insert(a); | ||||
|         } | ||||
|     } | ||||
|      | ||||
| private: | ||||
|  |  | |||
|  | @ -22,6 +22,8 @@ | |||
| #include "ackermannization/ackr_info.h" | ||||
| #include "ast/for_each_expr.h" | ||||
| #include "ast/ast_util.h" | ||||
| #include "ast/ast_pp.h" | ||||
| #include "ast/ast_ll_pp.h" | ||||
| #include "model/model_smt2_pp.h" | ||||
| 
 | ||||
| lackr::lackr(ast_manager& m, const params_ref& p, lackr_stats& st, | ||||
|  | @ -142,10 +144,10 @@ bool lackr::ackr(app * const t1, app * const t2) { | |||
| // Introduce the ackermann lemma for each pair of terms.
 | ||||
| //
 | ||||
| void lackr::eager_enc() { | ||||
|     TRACE("ackermannize", tout << "#funs: " << m_fun2terms.size() << "#sels: " << m_sel2terms.size() << std::endl;); | ||||
|     for (auto const& kv : m_fun2terms) { | ||||
|     TRACE("ackermannize", tout << "#funs: " << m_fun2terms.size() << " #sels: " << m_sel2terms.size() << std::endl;); | ||||
|     for (auto const& [k,v] : m_fun2terms) { | ||||
|         checkpoint(); | ||||
|         ackr(kv.get_value()); | ||||
|         ackr(v); | ||||
|     } | ||||
|     for (auto const& kv : m_sel2terms) { | ||||
|         checkpoint(); | ||||
|  | @ -172,14 +174,13 @@ void lackr::ackr(app_set const* ts) { | |||
| } | ||||
| 
 | ||||
| void lackr::abstract_fun(fun2terms_map const& apps) { | ||||
|     for (auto const& kv : apps) { | ||||
|         func_decl* fd = kv.m_key; | ||||
|         for (app * t : kv.m_value->var_args) { | ||||
|     for (auto const& [fd, v] : apps) { | ||||
|         for (app * t : v->var_args) { | ||||
|             app * fc = m.mk_fresh_const(fd->get_name(), t->get_sort()); | ||||
|             SASSERT(t->get_decl() == fd); | ||||
|             m_info->set_abstr(t, fc); | ||||
|         } | ||||
|         for (app * t : kv.m_value->const_args) { | ||||
|         for (app * t : v->const_args) { | ||||
|             app * fc = m.mk_fresh_const(fd->get_name(), t->get_sort()); | ||||
|             SASSERT(t->get_decl() == fd); | ||||
|             m_info->set_abstr(t, fc); | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ foreach (gen_file ${generated_files}) | |||
| endforeach() | ||||
| 
 | ||||
| add_custom_command(OUTPUT ${generated_files} | ||||
|   COMMAND "${PYTHON_EXECUTABLE}" | ||||
|   COMMAND "${Python3_EXECUTABLE}" | ||||
|   "${PROJECT_SOURCE_DIR}/scripts/update_api.py" | ||||
|   ${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN} | ||||
|   "--api_output_dir" | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ Revision History: | |||
| #include "ast/ast_ll_pp.h" | ||||
| #include "ast/ast_smt_pp.h" | ||||
| #include "ast/ast_smt2_pp.h" | ||||
| #include "ast/polymorphism_util.h" | ||||
| #include "ast/rewriter/th_rewriter.h" | ||||
| #include "ast/rewriter/var_subst.h" | ||||
| #include "ast/rewriter/expr_safe_replace.h" | ||||
|  | @ -88,6 +89,16 @@ extern "C" { | |||
|         Z3_CATCH_RETURN(nullptr); | ||||
|     } | ||||
| 
 | ||||
|     Z3_sort Z3_API Z3_mk_type_variable(Z3_context c, Z3_symbol name) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_mk_type_variable(c, name); | ||||
|         RESET_ERROR_CODE(); | ||||
|         sort* ty = mk_c(c)->m().mk_type_var(to_symbol(name)); | ||||
|         mk_c(c)->save_ast_trail(ty); | ||||
|         RETURN_Z3(of_sort(ty)); | ||||
|         Z3_CATCH_RETURN(nullptr); | ||||
|     } | ||||
| 
 | ||||
|     bool Z3_API Z3_is_eq_ast(Z3_context c, Z3_ast s1, Z3_ast s2) { | ||||
|         RESET_ERROR_CODE(); | ||||
|         return s1 == s2; | ||||
|  | @ -180,7 +191,20 @@ extern "C" { | |||
|             arg_list.push_back(to_expr(args[i])); | ||||
|         } | ||||
|         func_decl* _d = reinterpret_cast<func_decl*>(d); | ||||
|         app* a = mk_c(c)->m().mk_app(_d, num_args, arg_list.data()); | ||||
|         ast_manager& m = mk_c(c)->m(); | ||||
|         if (_d->is_polymorphic()) { | ||||
|             polymorphism::util u(m); | ||||
|             polymorphism::substitution sub(m); | ||||
|             ptr_buffer<sort> domain; | ||||
|             for (unsigned i = 0; i < num_args; ++i) { | ||||
|                 if (!sub.match(_d->get_domain(i), arg_list[i]->get_sort()))  | ||||
|                     SET_ERROR_CODE(Z3_INVALID_ARG, "failed to match argument of polymorphic function"); | ||||
|                 domain.push_back(arg_list[i]->get_sort()); | ||||
|             } | ||||
|             sort_ref range = sub(_d->get_range()); | ||||
|             _d = m.instantiate_polymorphic(_d, num_args, domain.data(), range); | ||||
|         } | ||||
|         app* a = m.mk_app(_d, num_args, arg_list.data()); | ||||
|         mk_c(c)->save_ast_trail(a); | ||||
|         check_sorts(c, a); | ||||
|         RETURN_Z3(of_ast(a)); | ||||
|  | @ -728,6 +752,9 @@ extern "C" { | |||
|         else if (fid == mk_c(c)->get_char_fid() && k == CHAR_SORT) { | ||||
|             return Z3_CHAR_SORT; | ||||
|         } | ||||
|         else if (fid == poly_family_id) { | ||||
|             return Z3_TYPE_VAR; | ||||
|         } | ||||
|         else { | ||||
|             return Z3_UNKNOWN_SORT; | ||||
|         } | ||||
|  |  | |||
|  | @ -227,6 +227,9 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \ | |||
|     Z3_ast Z3_API Z3_mk_bvadd_no_underflow(Z3_context c, Z3_ast t1, Z3_ast t2) { | ||||
|         Z3_TRY; | ||||
|         RESET_ERROR_CODE(); | ||||
|         // l1 := t1 <s 0
 | ||||
|         // l2 := t2 <s 0
 | ||||
|         // l1 & l2 => t1 + t2 <s 0
 | ||||
|         Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1)); | ||||
|         Z3_inc_ref(c, zero); | ||||
|         Z3_ast r = Z3_mk_bvadd(c, t1, t2); | ||||
|  | @ -255,6 +258,10 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \ | |||
|     Z3_ast Z3_API Z3_mk_bvsub_no_overflow(Z3_context c, Z3_ast t1, Z3_ast t2) { | ||||
|         Z3_TRY; | ||||
|         RESET_ERROR_CODE(); | ||||
|         // x := t2 = min_int
 | ||||
|         // y := t1 <s 0
 | ||||
|         // z := no_overflow(t1 + -t2)
 | ||||
|         // if x y z
 | ||||
|         Z3_ast minus_t2 = Z3_mk_bvneg(c, t2); | ||||
|         Z3_inc_ref(c, minus_t2); | ||||
|         Z3_sort s = Z3_get_sort(c, t2); | ||||
|  | @ -284,6 +291,9 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \ | |||
|         Z3_TRY; | ||||
|         RESET_ERROR_CODE(); | ||||
|         if (is_signed) { | ||||
|             // x := 0 <s -t2
 | ||||
|             // y := no_underflow(x + -t2)
 | ||||
|             // x => y
 | ||||
|             Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1)); | ||||
|             Z3_inc_ref(c, zero); | ||||
|             Z3_ast minus_t2 = Z3_mk_bvneg(c, t2); | ||||
|  |  | |||
|  | @ -78,6 +78,11 @@ namespace api { | |||
|             m().dec_ref(a); | ||||
|     } | ||||
| 
 | ||||
|     // flush_objects can only be called in the main thread.
 | ||||
|     // This ensures that the calls to m().dec_ref() and dealloc(o)
 | ||||
|     // only happens in the main thread.
 | ||||
|     // Calls to dec_ref are allowed in other threads when m_concurrent_dec_ref is
 | ||||
|     // set to true.
 | ||||
|     void context::flush_objects() { | ||||
| #ifndef SINGLE_THREAD | ||||
|         if (!m_concurrent_dec_ref) | ||||
|  | @ -157,6 +162,9 @@ namespace api { | |||
|         flush_objects(); | ||||
|         for (auto& kv : m_allocated_objects) { | ||||
|             api::object* val = kv.m_value; | ||||
| #ifdef SINGLE_THREAD | ||||
| # define m_concurrent_dec_ref false | ||||
| #endif | ||||
|             DEBUG_CODE(if (!m_concurrent_dec_ref) warning_msg("Uncollected memory: %d: %s", kv.m_key, typeid(*val).name());); | ||||
|             dealloc(val); | ||||
|         } | ||||
|  |  | |||
|  | @ -241,6 +241,20 @@ extern "C" { | |||
|         Z3_CATCH_RETURN(nullptr); | ||||
|     } | ||||
| 
 | ||||
|     unsigned Z3_API Z3_constructor_num_fields(Z3_context c, Z3_constructor constr) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_constructor_num_fields(c, constr); | ||||
|         RESET_ERROR_CODE(); | ||||
|         mk_c(c)->reset_last_result(); | ||||
|         if (!constr) { | ||||
|             SET_ERROR_CODE(Z3_INVALID_ARG, nullptr); | ||||
|             return 0; | ||||
|         } | ||||
|         constructor* c = reinterpret_cast<constructor*>(constr); | ||||
|         return c->m_field_names.size(); | ||||
|         Z3_CATCH_RETURN(0); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void Z3_API Z3_query_constructor(Z3_context c, | ||||
|                                      Z3_constructor constr, | ||||
|  |  | |||
|  | @ -29,13 +29,12 @@ bool is_numeral_sort(Z3_context c, Z3_sort ty) { | |||
|     if (!ty) return false; | ||||
|     sort * _ty = to_sort(ty); | ||||
|     family_id fid  = _ty->get_family_id(); | ||||
|     if (fid != mk_c(c)->get_arith_fid() && | ||||
|         fid != mk_c(c)->get_bv_fid() && | ||||
|         fid != mk_c(c)->get_datalog_fid() && | ||||
|         fid != mk_c(c)->get_fpa_fid()) { | ||||
|         return false; | ||||
|     } | ||||
|     return true; | ||||
|     return  | ||||
|         fid == mk_c(c)->get_arith_fid() || | ||||
|         fid == mk_c(c)->get_bv_fid() || | ||||
|         fid == mk_c(c)->get_datalog_fid() || | ||||
|         fid == mk_c(c)->get_fpa_fid(); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| static bool check_numeral_sort(Z3_context c, Z3_sort ty) { | ||||
|  | @ -152,7 +151,7 @@ extern "C" { | |||
|             mk_c(c)->bvutil().is_numeral(e) || | ||||
|             mk_c(c)->fpautil().is_numeral(e) || | ||||
|             mk_c(c)->fpautil().is_rm_numeral(e) || | ||||
|             mk_c(c)->datalog_util().is_numeral_ext(e); | ||||
|             mk_c(c)->datalog_util().is_numeral(e); | ||||
|         Z3_CATCH_RETURN(false); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -383,6 +383,36 @@ extern "C" { | |||
|         Z3_CATCH_RETURN(0); | ||||
|     } | ||||
| 
 | ||||
|     Z3_symbol Z3_API Z3_get_quantifier_skolem_id(Z3_context c, Z3_ast a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_get_quantifier_skolem_id(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         ast * _a = to_ast(a); | ||||
|         if (_a->get_kind() == AST_QUANTIFIER) { | ||||
|             return of_symbol(to_quantifier(_a)->get_skid()); | ||||
|         } | ||||
|         else { | ||||
|             SET_ERROR_CODE(Z3_SORT_ERROR, nullptr); | ||||
|             return of_symbol(symbol::null); | ||||
|         } | ||||
|         Z3_CATCH_RETURN(of_symbol(symbol::null)); | ||||
|     } | ||||
| 
 | ||||
|     Z3_symbol Z3_API Z3_get_quantifier_id(Z3_context c, Z3_ast a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_get_quantifier_skolem_id(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         ast * _a = to_ast(a); | ||||
|         if (_a->get_kind() == AST_QUANTIFIER) { | ||||
|             return of_symbol(to_quantifier(_a)->get_qid()); | ||||
|         } | ||||
|         else { | ||||
|             SET_ERROR_CODE(Z3_SORT_ERROR, nullptr); | ||||
|             return of_symbol(symbol::null); | ||||
|         } | ||||
|         Z3_CATCH_RETURN(of_symbol(symbol::null)); | ||||
|     } | ||||
| 
 | ||||
|     unsigned Z3_API Z3_get_quantifier_num_patterns(Z3_context c, Z3_ast a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_get_quantifier_num_patterns(c, a); | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ Author: | |||
|     Leonardo de Moura (leonardo) 2012-01-05 | ||||
| 
 | ||||
| Notes: | ||||
|      | ||||
| 
 | ||||
| --*/ | ||||
| #include "api/z3.h" | ||||
| #include "api/api_log_macros.h" | ||||
|  | @ -32,12 +32,12 @@ static void reset_rcf_cancel(Z3_context c) { | |||
|     // no-op
 | ||||
| } | ||||
| 
 | ||||
| static Z3_rcf_num from_rcnumeral(rcnumeral a) {  | ||||
|     return reinterpret_cast<Z3_rcf_num>(a.data());  | ||||
| static Z3_rcf_num from_rcnumeral(rcnumeral a) { | ||||
|     return reinterpret_cast<Z3_rcf_num>(a.data()); | ||||
| } | ||||
| 
 | ||||
| static rcnumeral to_rcnumeral(Z3_rcf_num a) {  | ||||
|     return rcnumeral::mk(a);  | ||||
| static rcnumeral to_rcnumeral(Z3_rcf_num a) { | ||||
|     return rcnumeral::mk(a); | ||||
| } | ||||
| 
 | ||||
| extern "C" { | ||||
|  | @ -179,7 +179,7 @@ extern "C" { | |||
|         RETURN_Z3(from_rcnumeral(r)); | ||||
|         Z3_CATCH_RETURN(nullptr); | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     Z3_rcf_num Z3_API Z3_rcf_neg(Z3_context c, Z3_rcf_num a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_neg(c, a); | ||||
|  | @ -302,4 +302,139 @@ extern "C" { | |||
|         Z3_CATCH; | ||||
|     } | ||||
| 
 | ||||
|     bool Z3_API Z3_rcf_is_rational(Z3_context c, Z3_rcf_num a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_is_rational(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return rcfm(c).is_rational(to_rcnumeral(a)); | ||||
|         Z3_CATCH_RETURN(false); | ||||
|     } | ||||
| 
 | ||||
|     bool Z3_API Z3_rcf_is_algebraic(Z3_context c, Z3_rcf_num a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_is_algebraic(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return rcfm(c).is_algebraic(to_rcnumeral(a)); | ||||
|         Z3_CATCH_RETURN(false); | ||||
|     } | ||||
| 
 | ||||
|     bool Z3_API Z3_rcf_is_infinitesimal(Z3_context c, Z3_rcf_num a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_is_infinitesimal(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return rcfm(c).is_infinitesimal(to_rcnumeral(a)); | ||||
|         Z3_CATCH_RETURN(false); | ||||
|     } | ||||
| 
 | ||||
|     bool Z3_API Z3_rcf_is_transcendental(Z3_context c, Z3_rcf_num a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_is_transcendental(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return rcfm(c).is_transcendental(to_rcnumeral(a)); | ||||
|         Z3_CATCH_RETURN(false); | ||||
|     } | ||||
| 
 | ||||
|     unsigned Z3_API Z3_rcf_extension_index(Z3_context c, Z3_rcf_num a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_extension_index(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return rcfm(c).extension_index(to_rcnumeral(a)); | ||||
|         Z3_CATCH_RETURN(false); | ||||
|     } | ||||
| 
 | ||||
|     Z3_symbol Z3_API Z3_rcf_transcendental_name(Z3_context c, Z3_rcf_num a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_transcendental_name(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return of_symbol(rcfm(c).transcendental_name(to_rcnumeral(a))); | ||||
|         Z3_CATCH_RETURN(of_symbol(symbol::null)); | ||||
|     } | ||||
| 
 | ||||
|     Z3_symbol Z3_API Z3_rcf_infinitesimal_name(Z3_context c, Z3_rcf_num a) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_infinitesimal_name(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return of_symbol(rcfm(c).infinitesimal_name(to_rcnumeral(a))); | ||||
|         Z3_CATCH_RETURN(of_symbol(symbol::null)); | ||||
|     } | ||||
| 
 | ||||
|     unsigned Z3_API Z3_rcf_num_coefficients(Z3_context c, Z3_rcf_num a) | ||||
|     { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_num_coefficients(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return rcfm(c).num_coefficients(to_rcnumeral(a)); | ||||
|         Z3_CATCH_RETURN(0); | ||||
|     } | ||||
| 
 | ||||
|     Z3_rcf_num Z3_API Z3_rcf_coefficient(Z3_context c, Z3_rcf_num a, unsigned i) | ||||
|     { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_coefficient(c, a, i); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return from_rcnumeral(rcfm(c).get_coefficient(to_rcnumeral(a), i)); | ||||
|         Z3_CATCH_RETURN(nullptr); | ||||
|     } | ||||
| 
 | ||||
|     int Z3_API Z3_rcf_interval(Z3_context c, Z3_rcf_num a, int * lower_is_inf, int * lower_is_open, Z3_rcf_num * lower, int * upper_is_inf, int * upper_is_open, Z3_rcf_num * upper) { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_interval(c, a, lower_is_inf, lower_is_open, lower, upper_is_inf, upper_is_open, upper); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         rcnumeral r_lower, r_upper; | ||||
|         bool r = rcfm(c).get_interval(to_rcnumeral(a), *lower_is_inf, *lower_is_open, r_lower, *upper_is_inf, *upper_is_open, r_upper); | ||||
|         *lower = from_rcnumeral(r_lower); | ||||
|         *upper = from_rcnumeral(r_upper); | ||||
|         return r; | ||||
|         Z3_CATCH_RETURN(0); | ||||
|     } | ||||
| 
 | ||||
|     unsigned Z3_API Z3_rcf_num_sign_conditions(Z3_context c, Z3_rcf_num a) | ||||
|     { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_num_sign_conditions(c, a); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return rcfm(c).num_sign_conditions(to_rcnumeral(a)); | ||||
|         Z3_CATCH_RETURN(0); | ||||
|     } | ||||
| 
 | ||||
|     int Z3_API Z3_rcf_sign_condition_sign(Z3_context c, Z3_rcf_num a, unsigned i) | ||||
|     { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_sign_condition_sign(c, a, i); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return rcfm(c).get_sign_condition_sign(to_rcnumeral(a), i); | ||||
|         Z3_CATCH_RETURN(0); | ||||
|     } | ||||
| 
 | ||||
|     unsigned Z3_API Z3_rcf_num_sign_condition_coefficients(Z3_context c, Z3_rcf_num a, unsigned i) | ||||
|     { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_num_sign_condition_coefficients(c, a, i); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return rcfm(c).num_sign_condition_coefficients(to_rcnumeral(a), i); | ||||
|         Z3_CATCH_RETURN(0); | ||||
|     } | ||||
| 
 | ||||
|     Z3_rcf_num Z3_API Z3_rcf_sign_condition_coefficient(Z3_context c, Z3_rcf_num a, unsigned i, unsigned j) | ||||
|     { | ||||
|         Z3_TRY; | ||||
|         LOG_Z3_rcf_sign_condition_coefficient(c, a, i, j); | ||||
|         RESET_ERROR_CODE(); | ||||
|         reset_rcf_cancel(c); | ||||
|         return from_rcnumeral(rcfm(c).get_sign_condition_coefficient(to_rcnumeral(a), i, j)); | ||||
|         Z3_CATCH_RETURN(nullptr); | ||||
|     } | ||||
| }; | ||||
|  |  | |||
|  | @ -984,14 +984,14 @@ extern "C" { | |||
|         Z3_TRY; | ||||
|         RESET_ERROR_CODE(); | ||||
|         init_solver(c, s);      | ||||
|         user_propagator::on_clause_eh_t _on_clause = [=](void* user_ctx, expr* proof, unsigned n, expr* const* _literals) { | ||||
|         user_propagator::on_clause_eh_t _on_clause = [=](void* user_ctx, expr* proof, unsigned nd, unsigned const* deps, unsigned n, expr* const* _literals) { | ||||
|             Z3_ast_vector_ref * literals = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m()); | ||||
|             mk_c(c)->save_object(literals); | ||||
|             expr_ref pr(proof, mk_c(c)->m()); | ||||
|             scoped_ast_vector _sc(literals); | ||||
|             for (unsigned i = 0; i < n; ++i) | ||||
|                 literals->m_ast_vector.push_back(_literals[i]); | ||||
|             on_clause_eh(user_ctx, of_expr(pr.get()), of_ast_vector(literals)); | ||||
|             on_clause_eh(user_ctx, of_expr(pr.get()), nd, deps, of_ast_vector(literals)); | ||||
|         }; | ||||
|         to_solver_ref(s)->register_on_clause(user_context, _on_clause); | ||||
|         auto& solver = *to_solver(s); | ||||
|  |  | |||
|  | @ -368,7 +368,7 @@ namespace z3 { | |||
|         func_decl recfun(char const * name, sort const & d1, sort const & d2, sort const & range); | ||||
| 
 | ||||
|         /**
 | ||||
|          * \brief add function definition body to declaration decl. decl needs to be declared using context::<recfun>. | ||||
|          * \brief add function definition body to declaration decl. decl needs to be declared using context::recfun. | ||||
|          * @param decl | ||||
|          * @param args | ||||
|          * @param body | ||||
|  | @ -4214,17 +4214,20 @@ namespace z3 { | |||
|         return expr(ctx(), r); | ||||
|     } | ||||
| 
 | ||||
|     typedef std::function<void(expr const& proof, expr_vector const& clause)> on_clause_eh_t; | ||||
|     typedef std::function<void(expr const& proof, std::vector<unsigned> const& deps, expr_vector const& clause)> on_clause_eh_t; | ||||
| 
 | ||||
|     class on_clause { | ||||
|         context& c; | ||||
|         on_clause_eh_t m_on_clause; | ||||
| 
 | ||||
|         static void _on_clause_eh(void* _ctx, Z3_ast _proof, Z3_ast_vector _literals) { | ||||
|         static void _on_clause_eh(void* _ctx, Z3_ast _proof, unsigned n, unsigned const* dep, Z3_ast_vector _literals) { | ||||
|             on_clause* ctx = static_cast<on_clause*>(_ctx); | ||||
|             expr_vector lits(ctx->c, _literals); | ||||
|             expr proof(ctx->c, _proof); | ||||
|             ctx->m_on_clause(proof, lits); | ||||
|             std::vector<unsigned> deps; | ||||
|             for (unsigned i = 0; i < n; ++i) | ||||
|                 deps.push_back(dep[i]); | ||||
|             ctx->m_on_clause(proof, deps, lits); | ||||
|         } | ||||
|     public: | ||||
|         on_clause(solver& s, on_clause_eh_t& on_clause_eh): c(s.ctx()) { | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ set(VER_TWEAK "${Z3_VERSION_TWEAK}") | |||
| # Generate Native.cs | ||||
| set(Z3_DOTNET_NATIVE_FILE "${CMAKE_CURRENT_BINARY_DIR}/Native.cs") | ||||
| add_custom_command(OUTPUT "${Z3_DOTNET_NATIVE_FILE}" | ||||
|   COMMAND "${PYTHON_EXECUTABLE}" | ||||
|   COMMAND "${Python3_EXECUTABLE}" | ||||
|     "${PROJECT_SOURCE_DIR}/scripts/update_api.py" | ||||
|     ${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN} | ||||
|     "--dotnet-output-dir" | ||||
|  | @ -25,7 +25,7 @@ add_custom_command(OUTPUT "${Z3_DOTNET_NATIVE_FILE}" | |||
| # Generate Enumerations.cs | ||||
| set(Z3_DOTNET_CONST_FILE "${CMAKE_CURRENT_BINARY_DIR}/Enumerations.cs") | ||||
| add_custom_command(OUTPUT "${Z3_DOTNET_CONST_FILE}" | ||||
|   COMMAND "${PYTHON_EXECUTABLE}" | ||||
|   COMMAND "${Python3_EXECUTABLE}" | ||||
|     "${PROJECT_SOURCE_DIR}/scripts/mk_consts_files.py" | ||||
|     ${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN} | ||||
|     "--dotnet-output-dir" | ||||
|  |  | |||
|  | @ -91,7 +91,13 @@ namespace Microsoft.Z3 | |||
|         /// </summary> | ||||
|         ~Constructor() | ||||
|         { | ||||
|             Native.Z3_del_constructor(Context.nCtx, NativeObject); | ||||
| 	    if (Context.nCtx != IntPtr.Zero) { | ||||
|                lock (Context)  | ||||
| 	       {  | ||||
|                    if (Context.nCtx != IntPtr.Zero)  | ||||
|                        Native.Z3_del_constructor(Context.nCtx, NativeObject); | ||||
|                } | ||||
|             } | ||||
|         }         | ||||
| 
 | ||||
|         #region Internal | ||||
|  |  | |||
|  | @ -7,6 +7,8 @@ | |||
|     <AssemblyName>Microsoft.Z3</AssemblyName> | ||||
|     <RootNamespace>Microsoft.Z3</RootNamespace> | ||||
| 
 | ||||
|     <PackageReadmeFile>README.md</PackageReadmeFile> | ||||
| 
 | ||||
|     <Title>Z3 .NET Interface</Title> | ||||
|     <AssemblyTitle>Z3 .NET Interface</AssemblyTitle> | ||||
| 
 | ||||
|  | @ -15,8 +17,8 @@ | |||
|     <Description>Z3 is a satisfiability modulo theories solver from Microsoft Research.</Description> | ||||
|     <AssemblyDescription>.NET Interface to the Z3 Theorem Prover</AssemblyDescription> | ||||
| 
 | ||||
|     <Copyright>Copyright (C) 2006-2019 Microsoft Corporation</Copyright> | ||||
|     <AssemblyCopyright>Copyright (C) 2006-2019 Microsoft Corporation</AssemblyCopyright> | ||||
|     <Copyright>Copyright (C) 2006- Microsoft Corporation</Copyright> | ||||
|     <AssemblyCopyright>Copyright (C) 2006- Microsoft Corporation</AssemblyCopyright> | ||||
| 
 | ||||
|     <Company>Microsoft Corporation</Company> | ||||
|     <AssemblyCompany>Microsoft Corporation</AssemblyCompany> | ||||
|  | @ -65,6 +67,11 @@ | |||
| ${Z3_DOTNET_COMPILE_ITEMS} | ||||
|   </ItemGroup> | ||||
| 
 | ||||
|   <!-- Readme --> | ||||
|   <ItemGroup> | ||||
|   <None Include="${CMAKE_CURRENT_LIST_DIR}/README.md" Pack="true" PackagePath="\"/> | ||||
|   </ItemGroup> | ||||
| 
 | ||||
|   <!-- Legacy .NET framework native library helper routines  --> | ||||
|   <ItemGroup> | ||||
|     <Content Include="${CMAKE_CURRENT_LIST_DIR}/Microsoft.Z3.props"> | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ namespace Microsoft.Z3 | |||
|     using Z3_context = System.IntPtr; | ||||
|     using Z3_solver = System.IntPtr; | ||||
|     using voidp = System.IntPtr; | ||||
|     using uintp = System.IntPtr; | ||||
|     using Z3_ast = System.IntPtr; | ||||
|     using Z3_ast_vector = System.IntPtr; | ||||
| 
 | ||||
|  | @ -60,7 +61,7 @@ namespace Microsoft.Z3 | |||
| 
 | ||||
|         Native.Z3_on_clause_eh on_clause_eh; | ||||
| 
 | ||||
| 	static void _on_clause(voidp ctx, Z3_ast _proof_hint, Z3_ast_vector _clause)  | ||||
| 	static void _on_clause(voidp ctx, Z3_ast _proof_hint, uint n, uint[] deps, Z3_ast_vector _clause)  | ||||
|         { | ||||
|              var onc = (OnClause)GCHandle.FromIntPtr(ctx).Target; | ||||
|              using var proof_hint = Expr.Create(onc.ctx, _proof_hint); | ||||
|  |  | |||
|  | @ -220,7 +220,7 @@ namespace Microsoft.Z3 | |||
|         /// <summary> | ||||
|         /// Check satisfiability of asserted constraints. | ||||
|         /// Produce a model that (when the objectives are bounded and  | ||||
|         /// don't use strict inequalities) meets the objectives. | ||||
|         /// don't use strict inequalities) is optimal. | ||||
|         /// </summary> | ||||
|         /// | ||||
|         public Status Check(params Expr[] assumptions) | ||||
|  |  | |||
							
								
								
									
										3
									
								
								src/api/dotnet/README.md
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/api/dotnet/README.md
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| # Z3 Nuget Package | ||||
| 
 | ||||
| For more information see [the Z3 github page](https://github.com/z3prover/z3.git) | ||||
|  | @ -16,7 +16,7 @@ set(Z3_JAVA_PACKAGE_NAME "com.microsoft.z3") | |||
| set(Z3_JAVA_NATIVE_JAVA "${CMAKE_CURRENT_BINARY_DIR}/Native.java") | ||||
| set(Z3_JAVA_NATIVE_CPP "${CMAKE_CURRENT_BINARY_DIR}/Native.cpp") | ||||
| add_custom_command(OUTPUT "${Z3_JAVA_NATIVE_JAVA}" "${Z3_JAVA_NATIVE_CPP}" | ||||
|   COMMAND "${PYTHON_EXECUTABLE}" | ||||
|   COMMAND "${Python3_EXECUTABLE}" | ||||
|     "${PROJECT_SOURCE_DIR}/scripts/update_api.py" | ||||
|     ${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN} | ||||
|     "--java-input-dir" | ||||
|  | @ -74,7 +74,7 @@ foreach (enum_file ${Z3_JAVA_ENUMERATION_PACKAGE_FILES}) | |||
|   ) | ||||
| endforeach() | ||||
| add_custom_command(OUTPUT ${Z3_JAVA_ENUMERATION_PACKAGE_FILES_FULL_PATH} | ||||
|   COMMAND "${PYTHON_EXECUTABLE}" | ||||
|   COMMAND "${Python3_EXECUTABLE}" | ||||
|     "${PROJECT_SOURCE_DIR}/scripts/mk_consts_files.py" | ||||
|     ${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN} | ||||
|     "--java-output-dir" | ||||
|  |  | |||
|  | @ -193,7 +193,7 @@ public class Optimize extends Z3Object { | |||
|     /** | ||||
|      * Check satisfiability of asserted constraints. | ||||
|      * Produce a model that (when the objectives are bounded and  | ||||
|      * don't use strict inequalities) meets the objectives. | ||||
|      * don't use strict inequalities) is optimal. | ||||
|      **/ | ||||
|     public Status Check(Expr<BoolSort>... assumptions) | ||||
|     { | ||||
|  |  | |||
							
								
								
									
										164
									
								
								src/api/js/package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										164
									
								
								src/api/js/package-lock.json
									
										
									
										generated
									
									
									
								
							|  | @ -1,7 +1,8 @@ | |||
| { | ||||
|   "name": "z3-solver", | ||||
|   "requires": true, | ||||
|   "version": "0.1.0", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
|     "@ampproject/remapping": { | ||||
|       "version": "2.2.0", | ||||
|  | @ -109,25 +110,6 @@ | |||
|       "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "@babel/helper-function-name": { | ||||
|       "version": "7.19.0", | ||||
|       "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", | ||||
|       "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "@babel/template": "^7.18.10", | ||||
|         "@babel/types": "^7.19.0" | ||||
|       } | ||||
|     }, | ||||
|     "@babel/helper-hoist-variables": { | ||||
|       "version": "7.18.6", | ||||
|       "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", | ||||
|       "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "@babel/types": "^7.18.6" | ||||
|       } | ||||
|     }, | ||||
|     "@babel/helper-module-imports": { | ||||
|       "version": "7.18.6", | ||||
|       "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", | ||||
|  | @ -361,21 +343,141 @@ | |||
|       } | ||||
|     }, | ||||
|     "@babel/traverse": { | ||||
|       "version": "7.19.4", | ||||
|       "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.4.tgz", | ||||
|       "integrity": "sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g==", | ||||
|       "version": "7.23.2", | ||||
|       "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", | ||||
|       "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "@babel/code-frame": "^7.18.6", | ||||
|         "@babel/generator": "^7.19.4", | ||||
|         "@babel/helper-environment-visitor": "^7.18.9", | ||||
|         "@babel/helper-function-name": "^7.19.0", | ||||
|         "@babel/helper-hoist-variables": "^7.18.6", | ||||
|         "@babel/helper-split-export-declaration": "^7.18.6", | ||||
|         "@babel/parser": "^7.19.4", | ||||
|         "@babel/types": "^7.19.4", | ||||
|         "@babel/code-frame": "^7.22.13", | ||||
|         "@babel/generator": "^7.23.0", | ||||
|         "@babel/helper-environment-visitor": "^7.22.20", | ||||
|         "@babel/helper-function-name": "^7.23.0", | ||||
|         "@babel/helper-hoist-variables": "^7.22.5", | ||||
|         "@babel/helper-split-export-declaration": "^7.22.6", | ||||
|         "@babel/parser": "^7.23.0", | ||||
|         "@babel/types": "^7.23.0", | ||||
|         "debug": "^4.1.0", | ||||
|         "globals": "^11.1.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "@babel/code-frame": { | ||||
|           "version": "7.22.13", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", | ||||
|           "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "@babel/highlight": "^7.22.13", | ||||
|             "chalk": "^2.4.2" | ||||
|           } | ||||
|         }, | ||||
|         "@babel/generator": { | ||||
|           "version": "7.23.0", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", | ||||
|           "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "@babel/types": "^7.23.0", | ||||
|             "@jridgewell/gen-mapping": "^0.3.2", | ||||
|             "@jridgewell/trace-mapping": "^0.3.17", | ||||
|             "jsesc": "^2.5.1" | ||||
|           } | ||||
|         }, | ||||
|         "@babel/helper-environment-visitor": { | ||||
|           "version": "7.22.20", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", | ||||
|           "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", | ||||
|           "dev": true | ||||
|         }, | ||||
|         "@babel/helper-function-name": { | ||||
|           "version": "7.23.0", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", | ||||
|           "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "@babel/template": "^7.22.15", | ||||
|             "@babel/types": "^7.23.0" | ||||
|           } | ||||
|         }, | ||||
|         "@babel/helper-hoist-variables": { | ||||
|           "version": "7.22.5", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", | ||||
|           "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "@babel/types": "^7.22.5" | ||||
|           } | ||||
|         }, | ||||
|         "@babel/helper-split-export-declaration": { | ||||
|           "version": "7.22.6", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", | ||||
|           "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "@babel/types": "^7.22.5" | ||||
|           } | ||||
|         }, | ||||
|         "@babel/helper-string-parser": { | ||||
|           "version": "7.22.5", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", | ||||
|           "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", | ||||
|           "dev": true | ||||
|         }, | ||||
|         "@babel/helper-validator-identifier": { | ||||
|           "version": "7.22.20", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", | ||||
|           "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", | ||||
|           "dev": true | ||||
|         }, | ||||
|         "@babel/highlight": { | ||||
|           "version": "7.22.20", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", | ||||
|           "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "@babel/helper-validator-identifier": "^7.22.20", | ||||
|             "chalk": "^2.4.2", | ||||
|             "js-tokens": "^4.0.0" | ||||
|           } | ||||
|         }, | ||||
|         "@babel/parser": { | ||||
|           "version": "7.23.0", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", | ||||
|           "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", | ||||
|           "dev": true | ||||
|         }, | ||||
|         "@babel/template": { | ||||
|           "version": "7.22.15", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", | ||||
|           "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "@babel/code-frame": "^7.22.13", | ||||
|             "@babel/parser": "^7.22.15", | ||||
|             "@babel/types": "^7.22.15" | ||||
|           } | ||||
|         }, | ||||
|         "@babel/types": { | ||||
|           "version": "7.23.0", | ||||
|           "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", | ||||
|           "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "@babel/helper-string-parser": "^7.22.5", | ||||
|             "@babel/helper-validator-identifier": "^7.22.20", | ||||
|             "to-fast-properties": "^2.0.0" | ||||
|           } | ||||
|         }, | ||||
|         "@jridgewell/gen-mapping": { | ||||
|           "version": "0.3.3", | ||||
|           "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", | ||||
|           "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "@jridgewell/set-array": "^1.0.1", | ||||
|             "@jridgewell/sourcemap-codec": "^1.4.10", | ||||
|             "@jridgewell/trace-mapping": "^0.3.9" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "@babel/types": { | ||||
|  |  | |||
|  | @ -69,7 +69,7 @@ const fns = JSON.stringify(exportedFuncs()); | |||
| const methods = '["ccall","FS","allocate","UTF8ToString","intArrayFromString","ALLOC_NORMAL"]'; | ||||
| const libz3a = path.normalize('../../../build/libz3.a'); | ||||
| spawnSync( | ||||
|   `emcc build/async-fns.cc ${libz3a} --std=c++20 --pre-js src/low-level/async-wrapper.js -g2 -pthread -fexceptions -s WASM_BIGINT -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=0 -s PTHREAD_POOL_SIZE_STRICT=0 -s MODULARIZE=1 -s 'EXPORT_NAME="initZ3"' -s EXPORTED_RUNTIME_METHODS=${methods} -s EXPORTED_FUNCTIONS=${fns} -s DISABLE_EXCEPTION_CATCHING=0 -s SAFE_HEAP=0 -s DEMANGLE_SUPPORT=1 -s TOTAL_MEMORY=1GB -I z3/src/api/ -o build/z3-built.js`, | ||||
|   `emcc build/async-fns.cc ${libz3a} --std=c++20 --pre-js src/low-level/async-wrapper.js -g2 -pthread -fexceptions -s WASM_BIGINT -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=0 -s PTHREAD_POOL_SIZE_STRICT=0 -s MODULARIZE=1 -s 'EXPORT_NAME="initZ3"' -s EXPORTED_RUNTIME_METHODS=${methods} -s EXPORTED_FUNCTIONS=${fns} -s DISABLE_EXCEPTION_CATCHING=0 -s SAFE_HEAP=0 -s DEMANGLE_SUPPORT=1 -s TOTAL_MEMORY=1GB -s TOTAL_STACK=20MB -I z3/src/api/ -o build/z3-built.js`, | ||||
| ); | ||||
| 
 | ||||
| fs.rmSync(ccWrapperPath); | ||||
|  |  | |||
							
								
								
									
										171
									
								
								src/api/ml/z3.ml
									
										
									
									
									
								
							
							
						
						
									
										171
									
								
								src/api/ml/z3.ml
									
										
									
									
									
								
							|  | @ -26,7 +26,7 @@ struct | |||
|   let (major, minor, build, revision) = Z3native.get_version () | ||||
| 
 | ||||
|   let full_version : string = Z3native.get_full_version() | ||||
|                                                               | ||||
| 
 | ||||
|   let to_string = | ||||
|     string_of_int major ^ "." ^ | ||||
|     string_of_int minor ^ "." ^ | ||||
|  | @ -45,12 +45,12 @@ let mk_list f n = | |||
| 
 | ||||
| let check_int32 v = v = Int32.to_int (Int32.of_int v) | ||||
| 
 | ||||
| let mk_int_expr ctx v ty =  | ||||
| let mk_int_expr ctx v ty = | ||||
|    if not (check_int32 v) then | ||||
|       Z3native.mk_numeral ctx (string_of_int v) ty | ||||
|    else | ||||
|       Z3native.mk_int ctx v ty | ||||
|      | ||||
| 
 | ||||
| let mk_context (settings:(string * string) list) = | ||||
|   let cfg = Z3native.mk_config () in | ||||
|   let f e = Z3native.set_param_value cfg (fst e) (snd e) in | ||||
|  | @ -62,6 +62,9 @@ let mk_context (settings:(string * string) list) = | |||
|   Z3native.enable_concurrent_dec_ref res; | ||||
|   res | ||||
| 
 | ||||
| let interrupt (ctx:context) = | ||||
|     Z3native.interrupt ctx | ||||
| 
 | ||||
| module Symbol = | ||||
| struct | ||||
|   type symbol = Z3native.symbol | ||||
|  | @ -721,7 +724,7 @@ struct | |||
|   let mk_exists = _internal_mk_quantifier ~universal:false | ||||
|   let mk_exists_const = _internal_mk_quantifier_const ~universal:false | ||||
|   let mk_lambda_const ctx bound body = Z3native.mk_lambda_const ctx (List.length bound) bound body | ||||
|   let mk_lambda ctx bound body =  | ||||
|   let mk_lambda ctx bound body = | ||||
|       let names = List.map (fun (x,_) -> x) bound in | ||||
|       let sorts = List.map (fun (_,y) -> y) bound in | ||||
|       Z3native.mk_lambda ctx (List.length bound) sorts names body | ||||
|  | @ -855,15 +858,6 @@ struct | |||
|   module Constructor = | ||||
|   struct | ||||
|     type constructor = Z3native.constructor | ||||
| 
 | ||||
|     module FieldNumTable = Hashtbl.Make(struct | ||||
|         type t = AST.ast | ||||
|         let equal x y = AST.compare x y = 0 | ||||
|         let hash = AST.hash | ||||
|       end) | ||||
| 
 | ||||
|     let _field_nums = FieldNumTable.create 0 | ||||
| 
 | ||||
|     let create (ctx:context) (name:Symbol.symbol) (recognizer:Symbol.symbol) (field_names:Symbol.symbol list) (sorts:Sort.sort option list) (sort_refs:int list) = | ||||
|       let n = List.length field_names in | ||||
|       if n <> List.length sorts then | ||||
|  | @ -879,10 +873,9 @@ struct | |||
|             (let f x = match x with None -> Z3native.mk_null_ast ctx | Some s -> s in | ||||
|              List.map f sorts) | ||||
|             sort_refs in | ||||
|         FieldNumTable.add _field_nums no n; | ||||
|         no | ||||
| 
 | ||||
|     let get_num_fields (x:constructor) = FieldNumTable.find _field_nums x | ||||
|     let get_num_fields (x:constructor) = Z3native.constructor_num_fields (gc x) x | ||||
| 
 | ||||
|     let get_constructor_decl (x:constructor) = | ||||
|       let (a, _, _) = (Z3native.query_constructor (gc x) x (get_num_fields x)) in | ||||
|  | @ -917,10 +910,10 @@ struct | |||
| 
 | ||||
|   let mk_sort_s (ctx:context) (name:string) (constructors:Constructor.constructor list) = | ||||
|     mk_sort ctx (Symbol.mk_string ctx name) constructors | ||||
|      | ||||
| 
 | ||||
|   let mk_sort_ref (ctx: context) (name:Symbol.symbol) = | ||||
|     Z3native.mk_datatype_sort ctx name | ||||
|      | ||||
| 
 | ||||
|   let mk_sort_ref_s (ctx: context) (name: string) = | ||||
|     mk_sort_ref ctx (Symbol.mk_string ctx name) | ||||
| 
 | ||||
|  | @ -1249,7 +1242,7 @@ end | |||
| module Seq = | ||||
| struct | ||||
|   let mk_seq_sort  = Z3native.mk_seq_sort | ||||
|   let is_seq_sort = Z3native.is_seq_sort  | ||||
|   let is_seq_sort = Z3native.is_seq_sort | ||||
|   let mk_re_sort = Z3native.mk_re_sort | ||||
|   let is_re_sort = Z3native.is_re_sort | ||||
|   let mk_string_sort = Z3native.mk_string_sort | ||||
|  | @ -1264,7 +1257,7 @@ struct | |||
|   let mk_seq_concat ctx args = Z3native.mk_seq_concat ctx (List.length args) args | ||||
|   let mk_seq_prefix = Z3native.mk_seq_prefix | ||||
|   let mk_seq_suffix = Z3native.mk_seq_suffix | ||||
|   let mk_seq_contains = Z3native.mk_seq_contains  | ||||
|   let mk_seq_contains = Z3native.mk_seq_contains | ||||
|   let mk_seq_extract = Z3native.mk_seq_extract | ||||
|   let mk_seq_replace = Z3native.mk_seq_replace | ||||
|   let mk_seq_at = Z3native.mk_seq_at | ||||
|  | @ -1509,13 +1502,15 @@ struct | |||
|     in | ||||
|     Z3native.apply_result_inc_ref (gc x) arn; | ||||
|     let sg = Z3native.apply_result_get_num_subgoals (gc x) arn in | ||||
|     let res = if sg = 0 then | ||||
|         raise (Error "No subgoals") | ||||
|       else | ||||
|         Z3native.apply_result_get_subgoal (gc x) arn 0 in | ||||
|     Z3native.apply_result_dec_ref (gc x) arn; | ||||
|     Z3native.tactic_dec_ref (gc x) tn; | ||||
|     res | ||||
|     if sg = 0 then ( | ||||
|       Z3native.apply_result_dec_ref (gc x) arn; | ||||
|       Z3native.tactic_dec_ref (gc x) tn; | ||||
|       raise (Error "No subgoals")) | ||||
|     else | ||||
|       let res:goal = Z3native.apply_result_get_subgoal (gc x) arn 0 in | ||||
|       Z3native.apply_result_dec_ref (gc x) arn; | ||||
|       Z3native.tactic_dec_ref (gc x) tn; | ||||
|       res | ||||
| 
 | ||||
|   let mk_goal = Z3native.mk_goal | ||||
| 
 | ||||
|  | @ -1889,9 +1884,9 @@ struct | |||
|     | _ -> UNKNOWN | ||||
| 
 | ||||
|   let get_model x = | ||||
|     try  | ||||
|     try | ||||
|        let q = Z3native.solver_get_model (gc x) x in | ||||
|        if Z3native.is_null_model q then None else Some q  | ||||
|        if Z3native.is_null_model q then None else Some q | ||||
|     with | _ -> None | ||||
| 
 | ||||
|   let get_proof x = | ||||
|  | @ -1916,6 +1911,9 @@ struct | |||
|   let add_simplifier = Z3native.solver_add_simplifier | ||||
|   let translate x = Z3native.solver_translate (gc x) x | ||||
|   let to_string x = Z3native.solver_to_string (gc x) x | ||||
| 
 | ||||
|   let interrupt (ctx:context) (s:solver) = | ||||
|     Z3native.solver_interrupt ctx s | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
|  | @ -2077,6 +2075,123 @@ struct | |||
| end | ||||
| 
 | ||||
| 
 | ||||
| module RCF = | ||||
| struct | ||||
|   type rcf_num = Z3native.rcf_num | ||||
| 
 | ||||
|   let del (ctx:context) (a:rcf_num) = Z3native.rcf_del ctx a | ||||
|   let del_list (ctx:context) (ns:rcf_num list) = List.iter (fun a -> Z3native.rcf_del ctx a) ns | ||||
|   let mk_rational (ctx:context) (v:string) = Z3native.rcf_mk_rational ctx v | ||||
|   let mk_small_int (ctx:context) (v:int) = Z3native.rcf_mk_small_int ctx v | ||||
| 
 | ||||
|   let mk_pi (ctx:context) = Z3native.rcf_mk_pi ctx | ||||
|   let mk_e (ctx:context) = Z3native.rcf_mk_e ctx | ||||
|   let mk_infinitesimal (ctx:context) = Z3native.rcf_mk_infinitesimal ctx | ||||
| 
 | ||||
|   let mk_roots (ctx:context) (a:rcf_num list) = | ||||
|     let n, r = Z3native.rcf_mk_roots ctx (List.length a) a in | ||||
|     List.init n (fun x -> List.nth r x) | ||||
| 
 | ||||
|   let add (ctx:context) (a:rcf_num) (b:rcf_num) = Z3native.rcf_add ctx a b | ||||
|   let sub (ctx:context) (a:rcf_num) (b:rcf_num) = Z3native.rcf_sub ctx a b | ||||
|   let mul (ctx:context) (a:rcf_num) (b:rcf_num) = Z3native.rcf_mul ctx a b | ||||
|   let div (ctx:context) (a:rcf_num) (b:rcf_num) = Z3native.rcf_div ctx a b | ||||
| 
 | ||||
|   let neg (ctx:context) (a:rcf_num) = Z3native.rcf_neg ctx a | ||||
|   let inv (ctx:context) (a:rcf_num) = Z3native.rcf_neg ctx a | ||||
| 
 | ||||
|   let power (ctx:context) (a:rcf_num) (k:int) = Z3native.rcf_power ctx a k | ||||
| 
 | ||||
|   let lt (ctx:context) (a:rcf_num) (b:rcf_num) = Z3native.rcf_lt ctx a b | ||||
|   let gt (ctx:context) (a:rcf_num) (b:rcf_num) = Z3native.rcf_gt ctx a b | ||||
|   let le (ctx:context) (a:rcf_num) (b:rcf_num) = Z3native.rcf_le ctx a b | ||||
|   let ge (ctx:context) (a:rcf_num) (b:rcf_num) = Z3native.rcf_ge ctx a b | ||||
|   let eq (ctx:context) (a:rcf_num) (b:rcf_num) = Z3native.rcf_eq ctx a b | ||||
|   let neq (ctx:context) (a:rcf_num) (b:rcf_num) = Z3native.rcf_neq ctx a b | ||||
| 
 | ||||
|   let num_to_string (ctx:context) (a:rcf_num) (compact:bool) (html:bool) = Z3native.rcf_num_to_string ctx a compact html | ||||
|   let num_to_decimal_string (ctx:context) (a:rcf_num) (prec:int) = Z3native.rcf_num_to_decimal_string ctx a prec | ||||
|   let get_numerator_denominator (ctx:context) (a:rcf_num) = Z3native.rcf_get_numerator_denominator ctx a | ||||
| 
 | ||||
|   let is_rational (ctx:context) (a:rcf_num) = Z3native.rcf_is_rational ctx a | ||||
|   let is_algebraic (ctx:context) (a:rcf_num) = Z3native.rcf_is_algebraic ctx a | ||||
|   let is_infinitesimal (ctx:context) (a:rcf_num) = Z3native.rcf_is_infinitesimal ctx a | ||||
|   let is_transcendental (ctx:context) (a:rcf_num) = Z3native.rcf_is_transcendental ctx a | ||||
| 
 | ||||
|   let extension_index (ctx:context) (a:rcf_num) =  Z3native.rcf_extension_index ctx a | ||||
|   let transcendental_name (ctx:context) (a:rcf_num) = Z3native.rcf_transcendental_name ctx a | ||||
|   let infinitesimal_name (ctx:context) (a:rcf_num) = Z3native.rcf_infinitesimal_name ctx a | ||||
| 
 | ||||
|   let num_coefficients (ctx:context) (a:rcf_num) = Z3native.rcf_num_coefficients ctx a | ||||
|   let get_coefficient (ctx:context) (a:rcf_num) (i:int) = Z3native.rcf_coefficient ctx a i | ||||
| 
 | ||||
|   let coefficients (ctx:context) (a:rcf_num) = | ||||
|     List.init (num_coefficients ctx a) (fun i -> Z3native.rcf_coefficient ctx a i) | ||||
| 
 | ||||
|   type interval = { | ||||
|       lower_is_inf : bool; | ||||
|       lower_is_open : bool; | ||||
|       lower : rcf_num; | ||||
|       upper_is_inf : bool; | ||||
|       upper_is_open : bool; | ||||
|       upper : rcf_num; | ||||
|   } | ||||
| 
 | ||||
|   let root_interval (ctx:context) (a:rcf_num) = | ||||
|     let ok, linf, lopen, l, uinf, uopen, u = Z3native.rcf_interval ctx a in | ||||
|     let i:interval = { | ||||
|       lower_is_inf = linf != 0; | ||||
|       lower_is_open = lopen != 0; | ||||
|       lower = l; | ||||
|       upper_is_inf = uinf != 0; | ||||
|       upper_is_open = uopen != 0; | ||||
|       upper = u } in | ||||
|     if ok != 0 then Some i else None | ||||
| 
 | ||||
|   let sign_condition_sign (ctx:context) (a:rcf_num) (i:int) = Z3native.rcf_sign_condition_sign ctx a i | ||||
| 
 | ||||
|   let sign_condition_coefficient (ctx:context) (a:rcf_num) (i:int) (j:int) = Z3native.rcf_sign_condition_coefficient ctx a i j | ||||
| 
 | ||||
|   let num_sign_condition_coefficients (ctx:context) (a:rcf_num) (i:int) = Z3native.rcf_num_sign_condition_coefficients ctx a i | ||||
| 
 | ||||
|   let sign_condition_coefficients (ctx:context) (a:rcf_num) (i:int) = | ||||
|     let n = Z3native.rcf_num_sign_condition_coefficients ctx a i in | ||||
|     List.init n (fun j -> Z3native.rcf_sign_condition_coefficient ctx a i j) | ||||
| 
 | ||||
|   let sign_conditions (ctx:context) (a:rcf_num) = | ||||
|     let n = Z3native.rcf_num_sign_conditions ctx a in | ||||
|     List.init n (fun i -> | ||||
|       (let nc = Z3native.rcf_num_sign_condition_coefficients ctx a i in | ||||
|        List.init nc (fun j -> Z3native.rcf_sign_condition_coefficient ctx a i j)), | ||||
|       Z3native.rcf_sign_condition_sign ctx a i) | ||||
| 
 | ||||
|   type root = { | ||||
|     obj : rcf_num; | ||||
|     polynomial : rcf_num list; | ||||
|     interval : interval option; | ||||
|     sign_conditions : (rcf_num list * int) list; | ||||
|   } | ||||
| 
 | ||||
|   let roots (ctx:context) (a:rcf_num list) = | ||||
|       let rs = mk_roots ctx a in | ||||
|       List.map | ||||
|         (fun r -> { | ||||
|           obj = r; | ||||
|           polynomial = coefficients ctx r; | ||||
|           interval = root_interval ctx r; | ||||
|           sign_conditions = sign_conditions ctx r}) | ||||
|         rs | ||||
| 
 | ||||
|   let del_root (ctx:context) (r:root) = | ||||
|     del ctx r.obj; | ||||
|     List.iter (fun n -> del ctx n) r.polynomial; | ||||
|     List.iter (fun (ns, _) -> del_list ctx ns) r.sign_conditions | ||||
| 
 | ||||
|   let del_roots (ctx:context) (rs:root list) = | ||||
|     List.iter (fun r -> del_root ctx r) rs | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| let set_global_param = Z3native.global_param_set | ||||
| 
 | ||||
| let get_global_param id = | ||||
|  |  | |||
|  | @ -48,6 +48,12 @@ type context | |||
| *) | ||||
| val mk_context : (string * string) list -> context | ||||
| 
 | ||||
| (** Interrupt the execution of a Z3 procedure. | ||||
| 
 | ||||
|     This procedure can be used to interrupt: solvers, simplifiers and tactics. | ||||
|     Note: Tactic.interrupt is an alias for this. *) | ||||
| val interrupt: context -> unit | ||||
| 
 | ||||
| (** Interaction logging for Z3 | ||||
|     Interaction logs are used to record calls into the API into a text file. | ||||
|     The text file can be replayed using z3. It has to be the same version of z3 | ||||
|  | @ -1068,13 +1074,13 @@ sig | |||
|       if the corresponding sort reference is 0, then the value in sort_refs should be an index | ||||
|       referring to one of the recursive datatypes that is declared. *) | ||||
|   val mk_constructor_s : context -> string -> Symbol.symbol -> Symbol.symbol list -> Sort.sort option list -> int list -> Constructor.constructor | ||||
|    | ||||
| 
 | ||||
|   (* Create a forward reference to a recursive datatype being declared. | ||||
|      The forward reference can be used in a nested occurrence: the range of an array | ||||
|      or as element sort of a sequence. The forward reference should only be used when | ||||
|      used in an accessor for a recursive datatype that gets declared. *) | ||||
|   val mk_sort_ref : context -> Symbol.symbol -> Sort.sort | ||||
|    | ||||
| 
 | ||||
|   (* [mk_sort_ref_s ctx s] is [mk_sort_ref ctx (Symbol.mk_string ctx s)] *) | ||||
|   val mk_sort_ref_s : context -> string -> Sort.sort | ||||
| 
 | ||||
|  | @ -1653,8 +1659,8 @@ sig | |||
| 
 | ||||
|       - The \c ceiling of [t1/t2] if \c t2 is different from zero, and [t1*t2 < 0]. | ||||
| 
 | ||||
|       If [t2] is zero, then the result is is not uniquely specified.  | ||||
|       It can be set to any value that satisfies the constraints  | ||||
|       If [t2] is zero, then the result is is not uniquely specified. | ||||
|       It can be set to any value that satisfies the constraints | ||||
|       where signed division is used. | ||||
|       The arguments must have the same bit-vector sort. *) | ||||
|   val mk_sdiv : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
|  | @ -1662,8 +1668,8 @@ sig | |||
|   (** Unsigned remainder. | ||||
| 
 | ||||
|       It is defined as [t1 - (t1 /u t2) * t2], where [/u] represents unsigned division. | ||||
|       If [t2] is zero, then the result is not uniquely specified.  | ||||
|       It can be set to any value that satisfies the constraints  | ||||
|       If [t2] is zero, then the result is not uniquely specified. | ||||
|       It can be set to any value that satisfies the constraints | ||||
|       where unsigned remainder is used. | ||||
|       The arguments must have the same bit-vector sort. *) | ||||
|   val mk_urem : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
|  | @ -1673,16 +1679,16 @@ sig | |||
|       It is defined as [t1 - (t1 /s t2) * t2], where [/s] represents signed division. | ||||
|       The most significant bit (sign) of the result is equal to the most significant bit of \c t1. | ||||
| 
 | ||||
|       If [t2] is zero, then the result is not uniquely specified.  | ||||
|       It can be set to any value that satisfies the constraints  | ||||
|       If [t2] is zero, then the result is not uniquely specified. | ||||
|       It can be set to any value that satisfies the constraints | ||||
|       where signed remainder is used. | ||||
|       The arguments must have the same bit-vector sort. *) | ||||
|   val mk_srem : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** Two's complement signed remainder (sign follows divisor). | ||||
| 
 | ||||
|       If [t2] is zero, then the result is not uniquely specified.  | ||||
|       It can be set to any value that satisfies the constraints  | ||||
|       If [t2] is zero, then the result is not uniquely specified. | ||||
|       It can be set to any value that satisfies the constraints | ||||
|       where two's complement signed remainder is used. | ||||
|       The arguments must have the same bit-vector sort. *) | ||||
|   val mk_smod : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
|  | @ -1864,7 +1870,7 @@ sig | |||
| end | ||||
| 
 | ||||
| (** Sequences, Strings and Regular Expressions **) | ||||
| module Seq :  | ||||
| module Seq : | ||||
| sig | ||||
|   (** create a sequence sort *) | ||||
|   val mk_seq_sort : context -> Sort.sort -> Sort.sort | ||||
|  | @ -1872,9 +1878,9 @@ sig | |||
|   (** test if sort is a sequence sort *) | ||||
|   val is_seq_sort : context -> Sort.sort -> bool | ||||
| 
 | ||||
|   (** create regular expression sorts over sequences of the argument sort *)    | ||||
|   (** create regular expression sorts over sequences of the argument sort *) | ||||
|   val mk_re_sort : context -> Sort.sort -> Sort.sort | ||||
|    | ||||
| 
 | ||||
|   (** test if sort is a regular expression sort *) | ||||
|   val is_re_sort : context -> Sort.sort -> bool | ||||
| 
 | ||||
|  | @ -1885,7 +1891,7 @@ sig | |||
|   val mk_char_sort : context -> Sort.sort | ||||
| 
 | ||||
|   (** test if sort is a string sort (a sequence of 8-bit bit-vectors) *) | ||||
|   val is_string_sort : context -> Sort.sort -> bool  | ||||
|   val is_string_sort : context -> Sort.sort -> bool | ||||
| 
 | ||||
|   (** test if sort is a char sort *) | ||||
|   val is_char_sort : context -> Sort.sort -> bool | ||||
|  | @ -1894,51 +1900,51 @@ sig | |||
|   val mk_string : context -> string -> Expr.expr | ||||
| 
 | ||||
|   (** test if expression is a string *) | ||||
|   val is_string : context -> Expr.expr -> bool  | ||||
|   val is_string : context -> Expr.expr -> bool | ||||
| 
 | ||||
|   (** retrieve string from string Expr.expr *) | ||||
|   val get_string : context -> Expr.expr -> string  | ||||
|   val get_string : context -> Expr.expr -> string | ||||
| 
 | ||||
|   (** the empty sequence over base sort *) | ||||
|   val mk_seq_empty : context -> Sort.sort -> Expr.expr  | ||||
|   val mk_seq_empty : context -> Sort.sort -> Expr.expr | ||||
| 
 | ||||
|   (** a unit sequence *) | ||||
|   val mk_seq_unit : context -> Expr.expr -> Expr.expr  | ||||
|   val mk_seq_unit : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** sequence concatenation *) | ||||
|   val mk_seq_concat : context -> Expr.expr list -> Expr.expr  | ||||
|   val mk_seq_concat : context -> Expr.expr list -> Expr.expr | ||||
| 
 | ||||
|   (** predicate if the first argument is a prefix of the second *) | ||||
|   val mk_seq_prefix : context -> Expr.expr -> Expr.expr -> Expr.expr   | ||||
|   val mk_seq_prefix : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** predicate if the first argument is a suffix of the second *) | ||||
|   val mk_seq_suffix : context -> Expr.expr -> Expr.expr -> Expr.expr   | ||||
|   val mk_seq_suffix : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** predicate if the first argument contains the second *) | ||||
|   val mk_seq_contains : context -> Expr.expr -> Expr.expr -> Expr.expr   | ||||
|   val mk_seq_contains : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** extract sub-sequence starting at index given by second argument and of length provided by third argument *) | ||||
|   val mk_seq_extract : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr   | ||||
|   val mk_seq_extract : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** replace first occurrence of second argument by third *) | ||||
|   val mk_seq_replace : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr   | ||||
|   val mk_seq_replace : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** a unit sequence at index provided by second argument *) | ||||
|   val mk_seq_at : context -> Expr.expr -> Expr.expr -> Expr.expr  | ||||
|   val mk_seq_at : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** length of a sequence *) | ||||
|   val mk_seq_length : context -> Expr.expr -> Expr.expr   | ||||
|    | ||||
|   (** [mk_seq_nth ctx s index] retrieves from [s] the element at position [index].  | ||||
|   val mk_seq_length : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** [mk_seq_nth ctx s index] retrieves from [s] the element at position [index]. | ||||
|       The function is under-specified if the index is out of bounds. *) | ||||
|   val mk_seq_nth : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** index of the first occurrence of the second argument in the first *) | ||||
|   val mk_seq_index : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr  | ||||
|   val mk_seq_index : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** [mk_seq_last_index ctx s substr] occurence of [substr] in the sequence [s] *) | ||||
|   val mk_seq_last_index : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
|    | ||||
| 
 | ||||
|   (** retrieve integer expression encoded in string *) | ||||
|   val mk_str_to_int : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|  | @ -1950,7 +1956,7 @@ sig | |||
|   val mk_str_lt : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** convert an integer expression to a string *) | ||||
|   val mk_int_to_str : context -> Expr.expr -> Expr.expr  | ||||
|   val mk_int_to_str : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** [mk_string_to_code ctx s] convert a unit length string [s] to integer code *) | ||||
|   val mk_string_to_code : context -> Expr.expr -> Expr.expr | ||||
|  | @ -1965,43 +1971,43 @@ sig | |||
|   val mk_sbv_to_str : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** create regular expression that accepts the argument sequence *) | ||||
|   val mk_seq_to_re : context -> Expr.expr -> Expr.expr  | ||||
|   val mk_seq_to_re : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** regular expression membership predicate *) | ||||
|   val mk_seq_in_re : context -> Expr.expr -> Expr.expr -> Expr.expr  | ||||
|   val mk_seq_in_re : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** regular expression plus *) | ||||
|   val mk_re_plus : context -> Expr.expr -> Expr.expr  | ||||
|   val mk_re_plus : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** regular expression star *) | ||||
|   val mk_re_star : context -> Expr.expr -> Expr.expr  | ||||
|   val mk_re_star : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** optional regular expression *) | ||||
|   val mk_re_option : context -> Expr.expr -> Expr.expr  | ||||
|   val mk_re_option : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** union of regular expressions *) | ||||
|   val mk_re_union : context -> Expr.expr list -> Expr.expr  | ||||
|   val mk_re_union : context -> Expr.expr list -> Expr.expr | ||||
| 
 | ||||
|   (** concatenation of regular expressions *) | ||||
|   val mk_re_concat : context -> Expr.expr list -> Expr.expr  | ||||
|    | ||||
|   val mk_re_concat : context -> Expr.expr list -> Expr.expr | ||||
| 
 | ||||
|   (** regular expression for the range between two characters *) | ||||
|   val mk_re_range : context -> Expr.expr -> Expr.expr -> Expr.expr  | ||||
|   val mk_re_range : context -> Expr.expr -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** bounded loop regular expression *) | ||||
|   val mk_re_loop : context -> Expr.expr -> int -> int -> Expr.expr  | ||||
|    | ||||
|   val mk_re_loop : context -> Expr.expr -> int -> int -> Expr.expr | ||||
| 
 | ||||
|   (** intersection of regular expressions *) | ||||
|   val mk_re_intersect : context -> Expr.expr list -> Expr.expr | ||||
| 
 | ||||
|   (** the regular expression complement *) | ||||
|   val mk_re_complement : context -> Expr.expr -> Expr.expr  | ||||
|   val mk_re_complement : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|   (** the regular expression that accepts no sequences *) | ||||
|   val mk_re_empty : context -> Sort.sort -> Expr.expr  | ||||
|   val mk_re_empty : context -> Sort.sort -> Expr.expr | ||||
| 
 | ||||
|   (** the regular expression that accepts all sequences *) | ||||
|   val mk_re_full : context -> Sort.sort -> Expr.expr  | ||||
|   val mk_re_full : context -> Sort.sort -> Expr.expr | ||||
| 
 | ||||
|   (** [mk_char ctx i] converts an integer to a character *) | ||||
|   val mk_char : context -> int -> Expr.expr | ||||
|  | @ -2339,7 +2345,7 @@ sig | |||
|   (** Retrieves the sign of a floating-point literal. *) | ||||
|   val get_numeral_sign : context -> Expr.expr -> bool * int | ||||
| 
 | ||||
|   (** Return the sign of a floating-point numeral as a bit-vector expression.  | ||||
|   (** Return the sign of a floating-point numeral as a bit-vector expression. | ||||
|       Remark: NaN's do not have a bit-vector sign, so they are invalid arguments. *) | ||||
|   val get_numeral_sign_bv : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|  | @ -2349,11 +2355,11 @@ sig | |||
|   (** Return the exponent value of a floating-point numeral as a signed integer *) | ||||
|   val get_numeral_exponent_int : context -> Expr.expr -> bool -> bool * int64 | ||||
| 
 | ||||
|   (** Return the exponent of a floating-point numeral as a bit-vector expression.  | ||||
|   (** Return the exponent of a floating-point numeral as a bit-vector expression. | ||||
|       Remark: NaN's do not have a bit-vector exponent, so they are invalid arguments. *) | ||||
|   val get_numeral_exponent_bv : context -> Expr.expr -> bool -> Expr.expr | ||||
| 
 | ||||
|   (** Return the significand value of a floating-point numeral as a bit-vector expression.  | ||||
|   (** Return the significand value of a floating-point numeral as a bit-vector expression. | ||||
|       Remark: NaN's do not have a bit-vector significand, so they are invalid arguments. *) | ||||
|   val get_numeral_significand_bv : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|  | @ -2386,7 +2392,7 @@ sig | |||
| 
 | ||||
|   (** Indicates whether a floating-point numeral is negative. *) | ||||
|   val is_numeral_negative : context -> Expr.expr -> bool | ||||
|     | ||||
| 
 | ||||
|   (** Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. *) | ||||
|   val mk_to_ieee_bv : context -> Expr.expr -> Expr.expr | ||||
| 
 | ||||
|  | @ -3260,7 +3266,7 @@ sig | |||
| 
 | ||||
|   (** Assert multiple constraints (cs) into the solver, and track them (in the | ||||
|       unsat) core using the Boolean constants in ps. | ||||
|       | ||||
| 
 | ||||
|       This API is an alternative to {!check} with 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 {!assert_and_track} and the Boolean literals | ||||
|  | @ -3269,10 +3275,10 @@ sig | |||
| 
 | ||||
|   (** Assert a constraint (c) into the solver, and track it (in the unsat) core | ||||
|       using the Boolean constant p. | ||||
|        | ||||
|       This API is an alternative to {!check} with 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 {!assert_and_track} and the Boolean literals  | ||||
| 
 | ||||
|       This API is an alternative to {!check} with 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 {!assert_and_track} and the Boolean literals | ||||
|       provided using {!check} with assumptions. *) | ||||
|   val assert_and_track : solver -> Expr.expr -> Expr.expr -> unit | ||||
| 
 | ||||
|  | @ -3342,6 +3348,15 @@ sig | |||
| 
 | ||||
|   (** A string representation of the solver. *) | ||||
|   val to_string : solver -> string | ||||
| 
 | ||||
|   (** Solver local interrupt. | ||||
| 
 | ||||
|       Normally you should use Z3_interrupt to cancel solvers because only | ||||
|       one solver is enabled concurrently per context. | ||||
|       However, per GitHub issue #1006, there are use cases where | ||||
|       it is more convenient to cancel a specific solver. Solvers | ||||
|       that are not selected for interrupts are left alone.*) | ||||
|   val interrupt: context -> solver -> unit | ||||
| end | ||||
| 
 | ||||
| (** Fixedpoint solving *) | ||||
|  | @ -3466,7 +3481,7 @@ sig | |||
|   (** Add minimization objective. *) | ||||
|   val minimize : optimize -> Expr.expr -> handle | ||||
| 
 | ||||
|   (** Checks whether the assertions in the context are satisfiable and solves objectives. *) | ||||
|   (** Check consistency and produce optimal values. *) | ||||
|   val check : optimize -> Solver.status | ||||
| 
 | ||||
|   (** Retrieve model from satisfiable context *) | ||||
|  | @ -3496,23 +3511,23 @@ sig | |||
|   val get_statistics : optimize -> Statistics.statistics | ||||
| 
 | ||||
|   (** Parse an SMT-LIB2 file with assertions, soft constraints and optimization | ||||
|       objectives. Add the parsed constraints and objectives to the optimization  | ||||
|       objectives. Add the parsed constraints and objectives to the optimization | ||||
|       context. *) | ||||
|   val from_file : optimize -> string -> unit | ||||
| 
 | ||||
|   (** Parse an SMT-LIB2 string with assertions, soft constraints and optimization  | ||||
|       objectives. Add the parsed constraints and objectives to the optimization  | ||||
|   (** Parse an SMT-LIB2 string with assertions, soft constraints and optimization | ||||
|       objectives. Add the parsed constraints and objectives to the optimization | ||||
|       context. *) | ||||
|   val from_string : optimize -> string -> unit | ||||
|                                              | ||||
|   (** Return the set of asserted formulas on the optimization context. *)  | ||||
| 
 | ||||
|   (** Return the set of asserted formulas on the optimization context. *) | ||||
|   val get_assertions : optimize -> Expr.expr list | ||||
| 
 | ||||
|   (** Return objectives on the optimization context. If the objective function  | ||||
|       is a max-sat objective it is returned as a Pseudo-Boolean (minimization)  | ||||
|       sum of the form (+ (if f1 w1 0) (if f2 w2 0) ...). If the objective  | ||||
|       function is entered as a maximization objective, then return the  | ||||
|       corresponding minimization objective. In this way the resulting  | ||||
|   (** Return objectives on the optimization context. If the objective function | ||||
|       is a max-sat objective it is returned as a Pseudo-Boolean (minimization) | ||||
|       sum of the form (+ (if f1 w1 0) (if f2 w2 0) ...). If the objective | ||||
|       function is entered as a maximization objective, then return the | ||||
|       corresponding minimization objective. In this way the resulting | ||||
|       objective function is always returned as a minimization objective. *) | ||||
|   val get_objectives : optimize -> Expr.expr list | ||||
| end | ||||
|  | @ -3535,6 +3550,151 @@ sig | |||
|   val parse_smtlib2_file : context -> string -> Symbol.symbol list -> Sort.sort list -> Symbol.symbol list -> FuncDecl.func_decl list -> AST.ASTVector.ast_vector | ||||
| end | ||||
| 
 | ||||
| (** Real closed field *) | ||||
| module RCF : | ||||
| sig | ||||
|   type rcf_num | ||||
| 
 | ||||
|   (** Delete a RCF numeral created using the RCF API. *) | ||||
|   val del : context -> rcf_num -> unit | ||||
| 
 | ||||
|   (** Delete RCF numerals created using the RCF API. *) | ||||
|   val del_list : context -> rcf_num list -> unit | ||||
| 
 | ||||
|   (** Return a RCF rational using the given string. *) | ||||
|   val mk_rational : context -> string -> rcf_num | ||||
| 
 | ||||
|   (** Return a RCF small integer. *) | ||||
|   val mk_small_int : context -> int -> rcf_num | ||||
| 
 | ||||
|   (** Return Pi *) | ||||
|   val mk_pi : context -> rcf_num | ||||
| 
 | ||||
|   (** Return e (Euler's constant) *) | ||||
|   val mk_e : context -> rcf_num | ||||
| 
 | ||||
|   (** Return a new infinitesimal that is smaller than all elements in the Z3 field. *) | ||||
|   val mk_infinitesimal : context -> rcf_num | ||||
| 
 | ||||
|   (** Extract the roots of a polynomial. Precondition: The input polynomial is not the zero polynomial. *) | ||||
|   val mk_roots : context -> rcf_num list -> rcf_num list | ||||
| 
 | ||||
|   (** Addition *) | ||||
|   val add : context -> rcf_num -> rcf_num -> rcf_num | ||||
| 
 | ||||
|   (** Subtraction *) | ||||
|   val sub : context -> rcf_num -> rcf_num -> rcf_num | ||||
| 
 | ||||
|   (** Multiplication *) | ||||
|   val mul : context -> rcf_num -> rcf_num -> rcf_num | ||||
| 
 | ||||
|   (** Division *) | ||||
|   val div : context -> rcf_num -> rcf_num -> rcf_num | ||||
| 
 | ||||
|   (** Negation *) | ||||
|   val neg : context -> rcf_num -> rcf_num | ||||
| 
 | ||||
|   (** Multiplicative Inverse *) | ||||
|   val inv : context -> rcf_num -> rcf_num | ||||
| 
 | ||||
|   (** Power *) | ||||
|   val power : context -> rcf_num -> int -> rcf_num | ||||
| 
 | ||||
|   (** less-than *) | ||||
|   val lt : context -> rcf_num -> rcf_num -> bool | ||||
| 
 | ||||
|   (** greater-than *) | ||||
|   val gt : context -> rcf_num -> rcf_num -> bool | ||||
| 
 | ||||
|   (** less-than or equal *) | ||||
|   val le : context -> rcf_num -> rcf_num -> bool | ||||
| 
 | ||||
|   (** greater-than or equal *) | ||||
|   val ge : context -> rcf_num -> rcf_num -> bool | ||||
| 
 | ||||
|   (** equality *) | ||||
|   val eq : context -> rcf_num -> rcf_num -> bool | ||||
| 
 | ||||
|   (** not equal *) | ||||
|   val neq : context -> rcf_num -> rcf_num -> bool | ||||
| 
 | ||||
|   (** Convert the RCF numeral into a string. *) | ||||
|   val num_to_string : context -> rcf_num -> bool -> bool -> string | ||||
| 
 | ||||
|   (** Convert the RCF numeral into a string in decimal notation. *) | ||||
|   val num_to_decimal_string : context -> rcf_num -> int -> string | ||||
| 
 | ||||
|   (** Extract the "numerator" and "denominator" of the given RCF numeral. | ||||
|       We have that \ccode{a = n/d}, moreover \c n and \c d are not represented using rational functions. *) | ||||
|   val get_numerator_denominator : context -> rcf_num -> (rcf_num * rcf_num) | ||||
| 
 | ||||
|   (** Return \c true if \c a represents a rational number. *) | ||||
|   val is_rational : context -> rcf_num -> bool | ||||
| 
 | ||||
|   (** Return \c true if \c a represents an algebraic number. *) | ||||
|   val is_algebraic : context -> rcf_num -> bool | ||||
| 
 | ||||
|   (** Return \c true if \c a represents an infinitesimal. *) | ||||
|   val is_infinitesimal : context -> rcf_num -> bool | ||||
| 
 | ||||
|   (** Return \c true if \c a represents a transcendental number. *) | ||||
|   val is_transcendental : context -> rcf_num -> bool | ||||
| 
 | ||||
|   (** Return the index of a field extension. *) | ||||
|   val extension_index : context -> rcf_num -> int | ||||
| 
 | ||||
|   (** Return the name of a transcendental. *) | ||||
|   val transcendental_name : context -> rcf_num -> Symbol.symbol | ||||
| 
 | ||||
|   (** Return the name of an infinitesimal. *) | ||||
|   val infinitesimal_name : context -> rcf_num -> Symbol.symbol | ||||
| 
 | ||||
|   (** Return the number of coefficients in an algebraic number. *) | ||||
|   val num_coefficients : context -> rcf_num -> int | ||||
| 
 | ||||
|   (** Extract a coefficient from an algebraic number. *) | ||||
|   val get_coefficient : context -> rcf_num -> int -> rcf_num | ||||
| 
 | ||||
|   (** Extract the coefficients from an algebraic number. *) | ||||
|   val coefficients : context -> rcf_num -> rcf_num list | ||||
| 
 | ||||
|   (** Extract the sign of a sign condition from an algebraic number. *) | ||||
|   val sign_condition_sign : context -> rcf_num -> int -> int | ||||
| 
 | ||||
|   (** Return the size of a sign condition polynomial. *) | ||||
|   val num_sign_condition_coefficients : context -> rcf_num -> int -> int | ||||
| 
 | ||||
|   (** Extract a sign condition polynomial coefficient from an algebraic number. *) | ||||
|   val sign_condition_coefficient : context -> rcf_num -> int -> int -> rcf_num | ||||
| 
 | ||||
|   (** Extract sign conditions from an algebraic number. *) | ||||
|   val sign_conditions : context -> rcf_num -> (rcf_num list * int) list | ||||
| 
 | ||||
|   (** Extract the interval from an algebraic number. *) | ||||
|   type interval = { | ||||
|     lower_is_inf : bool; | ||||
|     lower_is_open : bool; | ||||
|     lower : rcf_num; | ||||
|     upper_is_inf : bool; | ||||
|     upper_is_open : bool; | ||||
|     upper : rcf_num; | ||||
|   } | ||||
| 
 | ||||
|   val root_interval : context -> rcf_num -> interval option | ||||
| 
 | ||||
|   type root = { | ||||
|     obj : rcf_num; | ||||
|     polynomial : rcf_num list; | ||||
|     interval : interval option; | ||||
|     sign_conditions : (rcf_num list * int) list; | ||||
|   } | ||||
| 
 | ||||
|   val roots : context -> rcf_num list -> root list | ||||
| 
 | ||||
|   val del_root : context -> root -> unit | ||||
| 
 | ||||
|   val del_roots : context -> root list -> unit | ||||
| end | ||||
| 
 | ||||
| (** Set a global (or module) parameter, which is shared by all Z3 contexts. | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,6 +2,12 @@ | |||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #ifndef __STDC_NO_ATOMICS__ | ||||
| #include <stdatomic.h> | ||||
| #else | ||||
| #define _Atomic(T) T | ||||
| #endif | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | @ -118,7 +124,7 @@ int compare_pointers(void* pt1, void* pt2) { | |||
|    blocks that get copied. */ | ||||
| typedef struct { | ||||
|   Z3_context ctx; | ||||
|   unsigned long obj_count; | ||||
|   _Atomic(unsigned long) obj_count; | ||||
| } Z3_context_plus_data; | ||||
| 
 | ||||
| /* A context is wrapped to an OCaml value by storing a pointer | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ endforeach() | |||
| 
 | ||||
| # Generate z3core.py | ||||
| add_custom_command(OUTPUT "${z3py_bindings_build_dest}/z3/z3core.py" | ||||
|   COMMAND "${PYTHON_EXECUTABLE}" | ||||
|   COMMAND "${Python3_EXECUTABLE}" | ||||
|     "${PROJECT_SOURCE_DIR}/scripts/update_api.py" | ||||
|     ${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN} | ||||
|     "--z3py-output-dir" | ||||
|  | @ -49,7 +49,7 @@ list(APPEND build_z3_python_bindings_target_depends "${z3py_bindings_build_dest} | |||
| 
 | ||||
| # Generate z3consts.py | ||||
| add_custom_command(OUTPUT "${z3py_bindings_build_dest}/z3/z3consts.py" | ||||
|   COMMAND "${PYTHON_EXECUTABLE}" | ||||
|   COMMAND "${Python3_EXECUTABLE}" | ||||
|     "${PROJECT_SOURCE_DIR}/scripts/mk_consts_files.py" | ||||
|     ${Z3_FULL_PATH_API_HEADER_FILES_TO_SCAN} | ||||
|     "--z3py-output-dir" | ||||
|  | @ -96,7 +96,7 @@ if (Z3_INSTALL_PYTHON_BINDINGS) | |||
|   if (NOT DEFINED CMAKE_INSTALL_PYTHON_PKG_DIR) | ||||
|     message(STATUS "CMAKE_INSTALL_PYTHON_PKG_DIR not set. Trying to guess") | ||||
|     execute_process( | ||||
|       COMMAND "${PYTHON_EXECUTABLE}" "-c" | ||||
|       COMMAND "${Python3_EXECUTABLE}" "-c" | ||||
|         "import sysconfig; print(sysconfig.get_path('purelib'))" | ||||
|       RESULT_VARIABLE exit_code | ||||
|       OUTPUT_VARIABLE CMAKE_INSTALL_PYTHON_PKG_DIR | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ from setuptools.command.bdist_egg import bdist_egg as _bdist_egg | |||
| 
 | ||||
| build_env = dict(os.environ) | ||||
| build_env['PYTHON'] = sys.executable | ||||
| build_env['CXXFLAGS'] = build_env.get('CXXFLAGS', '') + " -std=c++11" | ||||
| build_env['CXXFLAGS'] = build_env.get('CXXFLAGS', '') + " -std=c++17" | ||||
| 
 | ||||
| # determine where we're building and where sources are | ||||
| ROOT_DIR = os.path.abspath(os.path.dirname(__file__)) | ||||
|  |  | |||
|  | @ -683,6 +683,8 @@ def _to_sort_ref(s, ctx): | |||
|         return SeqSortRef(s, ctx) | ||||
|     elif k == Z3_CHAR_SORT: | ||||
|         return CharSortRef(s, ctx) | ||||
|     elif k == Z3_TYPE_VAR: | ||||
|         return TypeVarRef(s, ctx) | ||||
|     return SortRef(s, ctx) | ||||
| 
 | ||||
| 
 | ||||
|  | @ -708,6 +710,26 @@ def DeclareSort(name, ctx=None): | |||
|     ctx = _get_ctx(ctx) | ||||
|     return SortRef(Z3_mk_uninterpreted_sort(ctx.ref(), to_symbol(name, ctx)), ctx) | ||||
| 
 | ||||
| class TypeVarRef(SortRef): | ||||
|     """Type variable reference""" | ||||
| 
 | ||||
|     def subsort(self, other): | ||||
|         return True | ||||
|      | ||||
|     def cast(self, val): | ||||
|         return val | ||||
|      | ||||
| 
 | ||||
| def DeclareTypeVar(name, ctx=None): | ||||
|     """Create a new type variable named `name`. | ||||
| 
 | ||||
|     If `ctx=None`, then the new sort is declared in the global Z3Py context. | ||||
| 
 | ||||
|     """ | ||||
|     ctx = _get_ctx(ctx) | ||||
|     return TypeVarRef(Z3_mk_type_variable(ctx.ref(), to_symbol(name, ctx)), ctx) | ||||
| 
 | ||||
| 
 | ||||
| ######################################### | ||||
| # | ||||
| # Function Declarations | ||||
|  | @ -1549,6 +1571,14 @@ class BoolRef(ExprRef): | |||
|     def sort(self): | ||||
|         return BoolSortRef(Z3_get_sort(self.ctx_ref(), self.as_ast()), self.ctx) | ||||
| 
 | ||||
|     def __add__(self, other): | ||||
|         if isinstance(other, BoolRef): | ||||
|             other = If(other, 1, 0) | ||||
|         return If(self, 1, 0) + other | ||||
| 
 | ||||
|     def __radd__(self, other): | ||||
|         return self + other | ||||
|   | ||||
|     def __rmul__(self, other): | ||||
|         return self * other | ||||
| 
 | ||||
|  | @ -1562,6 +1592,20 @@ class BoolRef(ExprRef): | |||
|         if isinstance(other, BoolRef): | ||||
|             other = If(other, 1, 0) | ||||
|         return If(self, other, 0) | ||||
|          | ||||
|     def __and__(self, other): | ||||
|         return And(self, other) | ||||
|      | ||||
|     def __or__(self, other): | ||||
|         return Or(self, other) | ||||
| 
 | ||||
|     def __xor__(self, other): | ||||
|         return Xor(self, other) | ||||
|      | ||||
|     def __invert__(self): | ||||
|         return Not(self) | ||||
|      | ||||
|      | ||||
| 
 | ||||
|      | ||||
| def is_bool(a): | ||||
|  | @ -2059,6 +2103,16 @@ class QuantifierRef(BoolRef): | |||
|         """ | ||||
|         return int(Z3_get_quantifier_weight(self.ctx_ref(), self.ast)) | ||||
| 
 | ||||
|     def skolem_id(self): | ||||
|         """Return the skolem id of `self`. | ||||
|         """ | ||||
|         return _symbol2py(self.ctx, Z3_get_quantifier_skolem_id(self.ctx_ref(), self.ast)) | ||||
| 
 | ||||
|     def qid(self): | ||||
|         """Return the quantifier id of `self`. | ||||
|         """ | ||||
|         return _symbol2py(self.ctx, Z3_get_quantifier_id(self.ctx_ref(), self.ast)) | ||||
| 
 | ||||
|     def num_patterns(self): | ||||
|         """Return the number of patterns (i.e., quantifier instantiation hints) in `self`. | ||||
| 
 | ||||
|  | @ -6909,6 +6963,13 @@ class Solver(Z3PPObject): | |||
|         if self.solver is not None and self.ctx.ref() is not None and Z3_solver_dec_ref is not None: | ||||
|             Z3_solver_dec_ref(self.ctx.ref(), self.solver) | ||||
| 
 | ||||
|     def __enter__(self): | ||||
|         self.push() | ||||
|         return self | ||||
| 
 | ||||
|     def __exit__(self, *exc_info): | ||||
|         self.pop() | ||||
| 
 | ||||
|     def set(self, *args, **keys): | ||||
|         """Set a configuration option. | ||||
|         The method `help()` return a string containing all available options. | ||||
|  | @ -7993,7 +8054,7 @@ class Optimize(Z3PPObject): | |||
|         Z3_optimize_pop(self.ctx.ref(), self.optimize) | ||||
| 
 | ||||
|     def check(self, *assumptions): | ||||
|         """Check satisfiability while optimizing objective functions.""" | ||||
|         """Check consistency and produce optimal values.""" | ||||
|         assumptions = _get_args(assumptions) | ||||
|         num = len(assumptions) | ||||
|         _assumptions = (Ast * num)() | ||||
|  | @ -11416,11 +11477,12 @@ def to_AstVectorObj(ptr,): | |||
| # for UserPropagator we use a global dictionary, which isn't great code. | ||||
| 
 | ||||
| _my_hacky_class = None | ||||
| def on_clause_eh(ctx, p, clause): | ||||
| def on_clause_eh(ctx, p, n, dep, clause): | ||||
|     onc = _my_hacky_class | ||||
|     p = _to_expr_ref(to_Ast(p), onc.ctx) | ||||
|     clause = AstVector(to_AstVectorObj(clause), onc.ctx) | ||||
|     onc.on_clause(p, clause) | ||||
|     deps = [dep[i] for i in range(n)] | ||||
|     onc.on_clause(p, deps, clause) | ||||
|      | ||||
| _on_clause_eh = Z3_on_clause_eh(on_clause_eh) | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,7 +20,6 @@ Notes: | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdbool.h> | ||||
| #include <stdint.h> | ||||
| #include "z3_macros.h" | ||||
|  |  | |||
|  | @ -5,7 +5,6 @@ | |||
| #pragma once | ||||
| 
 | ||||
| DEFINE_TYPE(Z3_symbol); | ||||
| DEFINE_TYPE(Z3_literals); | ||||
| DEFINE_TYPE(Z3_config); | ||||
| DEFINE_TYPE(Z3_context); | ||||
| DEFINE_TYPE(Z3_sort); | ||||
|  | @ -151,6 +150,7 @@ typedef enum | |||
|     Z3_SEQ_SORT, | ||||
|     Z3_RE_SORT, | ||||
|     Z3_CHAR_SORT, | ||||
|     Z3_TYPE_VAR, | ||||
|     Z3_UNKNOWN_SORT = 1000 | ||||
| } Z3_sort_kind; | ||||
| 
 | ||||
|  | @ -1397,7 +1397,6 @@ typedef enum | |||
|   def_Type('FUNC_DECL',        'Z3_func_decl',        'FuncDecl') | ||||
|   def_Type('PATTERN',          'Z3_pattern',          'Pattern') | ||||
|   def_Type('MODEL',            'Z3_model',            'ModelObj') | ||||
|   def_Type('LITERALS',         'Z3_literals',         'Literals') | ||||
|   def_Type('CONSTRUCTOR',      'Z3_constructor',      'Constructor') | ||||
|   def_Type('CONSTRUCTOR_LIST', 'Z3_constructor_list', 'ConstructorList') | ||||
|   def_Type('SOLVER',           'Z3_solver',           'SolverObj') | ||||
|  | @ -1436,7 +1435,7 @@ Z3_DECLARE_CLOSURE(Z3_eq_eh,      void, (void* ctx, Z3_solver_callback cb, Z3_as | |||
| Z3_DECLARE_CLOSURE(Z3_final_eh,   void, (void* ctx, Z3_solver_callback cb)); | ||||
| Z3_DECLARE_CLOSURE(Z3_created_eh, void, (void* ctx, Z3_solver_callback cb, Z3_ast t)); | ||||
| Z3_DECLARE_CLOSURE(Z3_decide_eh,  void, (void* ctx, Z3_solver_callback cb, Z3_ast t, unsigned idx, bool phase)); | ||||
| Z3_DECLARE_CLOSURE(Z3_on_clause_eh, void, (void* ctx, Z3_ast proof_hint, Z3_ast_vector literals)); | ||||
| Z3_DECLARE_CLOSURE(Z3_on_clause_eh, void, (void* ctx, Z3_ast proof_hint, unsigned n, unsigned const* deps, Z3_ast_vector literals)); | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -1883,6 +1882,17 @@ extern "C" { | |||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_uninterpreted_sort(Z3_context c, Z3_symbol s); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Create a type variable. | ||||
| 
 | ||||
|        Functions using type variables can be applied to instantiations that match the signature  | ||||
|        of the function. Assertions using type variables correspond to assertions over all possible | ||||
|        instantiations. | ||||
| 
 | ||||
|        def_API('Z3_mk_type_variable', SORT, (_in(CONTEXT), _in(SYMBOL))) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_type_variable(Z3_context c, Z3_symbol s); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Create the Boolean type. | ||||
| 
 | ||||
|  | @ -2072,6 +2082,16 @@ extern "C" { | |||
|                                             unsigned sort_refs[] | ||||
|                                             ); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Retrieve the number of fields of a constructor | ||||
| 
 | ||||
|        \param c logical context. | ||||
|        \param constr constructor. | ||||
| 
 | ||||
|        def_API('Z3_constructor_num_fields', UINT, (_in(CONTEXT), _in(CONSTRUCTOR))) | ||||
|     */ | ||||
|     unsigned Z3_API Z3_constructor_num_fields(Z3_context c, Z3_constructor constr); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Reclaim memory allocated to constructor. | ||||
| 
 | ||||
|  | @ -5186,6 +5206,24 @@ extern "C" { | |||
|     */ | ||||
|     unsigned Z3_API Z3_get_quantifier_weight(Z3_context c, Z3_ast a); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Obtain skolem id of quantifier. | ||||
| 
 | ||||
|        \pre Z3_get_ast_kind(a) == Z3_QUANTIFIER_AST | ||||
| 
 | ||||
|        def_API('Z3_get_quantifier_skolem_id', SYMBOL, (_in(CONTEXT), _in(AST))) | ||||
|     */ | ||||
|     Z3_symbol Z3_API Z3_get_quantifier_skolem_id(Z3_context c, Z3_ast a); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Obtain id of quantifier. | ||||
| 
 | ||||
|        \pre Z3_get_ast_kind(a) == Z3_QUANTIFIER_AST | ||||
| 
 | ||||
|        def_API('Z3_get_quantifier_id', SYMBOL, (_in(CONTEXT), _in(AST))) | ||||
|     */ | ||||
|     Z3_symbol Z3_API Z3_get_quantifier_id(Z3_context c, Z3_ast a); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Return number of patterns used in quantifier. | ||||
| 
 | ||||
|  | @ -5584,14 +5622,14 @@ extern "C" { | |||
|     void Z3_API Z3_add_const_interp(Z3_context c, Z3_model m, Z3_func_decl f, Z3_ast a); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Increment the reference counter of the given Z3_func_interp object. | ||||
|        \brief Increment the reference counter of the given \c Z3_func_interp object. | ||||
| 
 | ||||
|        def_API('Z3_func_interp_inc_ref', VOID, (_in(CONTEXT), _in(FUNC_INTERP))) | ||||
|     */ | ||||
|     void Z3_API Z3_func_interp_inc_ref(Z3_context c, Z3_func_interp f); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Decrement the reference counter of the given Z3_func_interp object. | ||||
|        \brief Decrement the reference counter of the given \c Z3_func_interp object. | ||||
| 
 | ||||
|        def_API('Z3_func_interp_dec_ref', VOID, (_in(CONTEXT), _in(FUNC_INTERP))) | ||||
|     */ | ||||
|  |  | |||
							
								
								
									
										256
									
								
								src/api/z3_fpa.h
									
										
									
									
									
								
							
							
						
						
									
										256
									
								
								src/api/z3_fpa.h
									
										
									
									
									
								
							|  | @ -32,6 +32,12 @@ extern "C" { | |||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_round_nearest_ties_to_away or Z3_mk_fpa_rna | ||||
|         \sa Z3_mk_fpa_round_nearest_ties_to_even or Z3_mk_fpa_rne | ||||
|         \sa Z3_mk_fpa_round_toward_negative or Z3_mk_fpa_rtn | ||||
|         \sa Z3_mk_fpa_round_toward_positive or Z3_mk_fpa_rtp | ||||
|         \sa Z3_mk_fpa_round_toward_zero or Z3_mk_fpa_rtz | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_rounding_mode_sort', SORT, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_fpa_rounding_mode_sort(Z3_context c); | ||||
|  | @ -39,8 +45,16 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_rne. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_rounding_mode_sort | ||||
|         \sa Z3_mk_fpa_round_nearest_ties_to_away | ||||
|         \sa Z3_mk_fpa_round_toward_negative | ||||
|         \sa Z3_mk_fpa_round_toward_positive | ||||
|         \sa Z3_mk_fpa_round_toward_zero | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_round_nearest_ties_to_even', AST, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_even(Z3_context c); | ||||
|  | @ -48,8 +62,16 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_round_nearest_ties_to_even. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_rounding_mode_sort | ||||
|         \sa Z3_mk_fpa_rna | ||||
|         \sa Z3_mk_fpa_rtn | ||||
|         \sa Z3_mk_fpa_rtp | ||||
|         \sa Z3_mk_fpa_rtz | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_rne', AST, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_rne(Z3_context c); | ||||
|  | @ -57,8 +79,16 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_rna. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_rounding_mode_sort | ||||
|         \sa Z3_mk_fpa_round_nearest_ties_to_even | ||||
|         \sa Z3_mk_fpa_round_toward_negative | ||||
|         \sa Z3_mk_fpa_round_toward_positive | ||||
|         \sa Z3_mk_fpa_round_toward_zero | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_round_nearest_ties_to_away', AST, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_round_nearest_ties_to_away(Z3_context c); | ||||
|  | @ -66,8 +96,16 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_round_nearest_ties_to_away. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_rounding_mode_sort | ||||
|         \sa Z3_mk_fpa_rne | ||||
|         \sa Z3_mk_fpa_rtn | ||||
|         \sa Z3_mk_fpa_rtp | ||||
|         \sa Z3_mk_fpa_rtz | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_rna', AST, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_rna(Z3_context c); | ||||
|  | @ -75,8 +113,16 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_rtp. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_rounding_mode_sort | ||||
|         \sa Z3_mk_fpa_round_nearest_ties_to_away | ||||
|         \sa Z3_mk_fpa_round_nearest_ties_to_even | ||||
|         \sa Z3_mk_fpa_round_toward_negative | ||||
|         \sa Z3_mk_fpa_round_toward_zero | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_round_toward_positive', AST, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_round_toward_positive(Z3_context c); | ||||
|  | @ -84,8 +130,16 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_round_toward_positive. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_rounding_mode_sort | ||||
|         \sa Z3_mk_fpa_rna | ||||
|         \sa Z3_mk_fpa_rne | ||||
|         \sa Z3_mk_fpa_rtn | ||||
|         \sa Z3_mk_fpa_rtz | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_rtp', AST, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_rtp(Z3_context c); | ||||
|  | @ -93,8 +147,16 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_rtn. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_rounding_mode_sort | ||||
|         \sa Z3_mk_fpa_round_nearest_ties_to_away | ||||
|         \sa Z3_mk_fpa_round_nearest_ties_to_even | ||||
|         \sa Z3_mk_fpa_round_toward_positive | ||||
|         \sa Z3_mk_fpa_round_toward_zero | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_round_toward_negative', AST, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_round_toward_negative(Z3_context c); | ||||
|  | @ -102,8 +164,16 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_round_toward_negative. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_rounding_mode_sort | ||||
|         \sa Z3_mk_fpa_rna | ||||
|         \sa Z3_mk_fpa_rne | ||||
|         \sa Z3_mk_fpa_rtp | ||||
|         \sa Z3_mk_fpa_rtz | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_rtn', AST, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_rtn(Z3_context c); | ||||
|  | @ -111,8 +181,16 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_rtz. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_rounding_mode_sort | ||||
|         \sa Z3_mk_fpa_round_nearest_ties_to_away | ||||
|         \sa Z3_mk_fpa_round_nearest_ties_to_even | ||||
|         \sa Z3_mk_fpa_round_toward_negative | ||||
|         \sa Z3_mk_fpa_round_toward_positive | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_round_toward_zero', AST, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_round_toward_zero(Z3_context c); | ||||
|  | @ -120,8 +198,16 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_round_toward_zero. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_rounding_mode_sort | ||||
|         \sa Z3_mk_fpa_rna | ||||
|         \sa Z3_mk_fpa_rne | ||||
|         \sa Z3_mk_fpa_rtn | ||||
|         \sa Z3_mk_fpa_rtp | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_rtz', AST, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_rtz(Z3_context c); | ||||
|  | @ -135,6 +221,11 @@ extern "C" { | |||
| 
 | ||||
|         \remark \c ebits must be larger than 1 and \c sbits must be larger than 2. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_sort_half or Z3_mk_fpa_sort_16 | ||||
|         \sa Z3_mk_fpa_sort_single or Z3_mk_fpa_sort_32 | ||||
|         \sa Z3_mk_fpa_sort_double or Z3_mk_fpa_sort_64 | ||||
|         \sa Z3_mk_fpa_sort_quadruple or Z3_mk_fpa_sort_128 | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_sort', SORT, (_in(CONTEXT), _in(UINT), _in(UINT))) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_fpa_sort(Z3_context c, unsigned ebits, unsigned sbits); | ||||
|  | @ -142,8 +233,15 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create the half-precision (16-bit) FloatingPoint sort. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_sort_16. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_sort | ||||
|         \sa Z3_mk_fpa_sort_single | ||||
|         \sa Z3_mk_fpa_sort_double | ||||
|         \sa Z3_mk_fpa_sort_quadruple | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_sort_half', SORT, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_fpa_sort_half(Z3_context c); | ||||
|  | @ -151,8 +249,15 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create the half-precision (16-bit) FloatingPoint sort. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_sort_half. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_sort | ||||
|         \sa Z3_mk_fpa_sort_32 | ||||
|         \sa Z3_mk_fpa_sort_64 | ||||
|         \sa Z3_mk_fpa_sort_128 | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_sort_16', SORT, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_fpa_sort_16(Z3_context c); | ||||
|  | @ -160,8 +265,15 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create the single-precision (32-bit) FloatingPoint sort. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_sort_32. | ||||
| 
 | ||||
|         \param c logical context. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_sort | ||||
|         \sa Z3_mk_fpa_sort_half | ||||
|         \sa Z3_mk_fpa_sort_double | ||||
|         \sa Z3_mk_fpa_sort_quadruple | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_sort_single', SORT, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_fpa_sort_single(Z3_context c); | ||||
|  | @ -169,8 +281,15 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create the single-precision (32-bit) FloatingPoint sort. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_sort_single. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_sort | ||||
|         \sa Z3_mk_fpa_sort_16 | ||||
|         \sa Z3_mk_fpa_sort_64 | ||||
|         \sa Z3_mk_fpa_sort_128 | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_sort_32', SORT, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_fpa_sort_32(Z3_context c); | ||||
|  | @ -178,8 +297,15 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create the double-precision (64-bit) FloatingPoint sort. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_sort_64. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_sort | ||||
|         \sa Z3_mk_fpa_sort_half | ||||
|         \sa Z3_mk_fpa_sort_single | ||||
|         \sa Z3_mk_fpa_sort_quadruple | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_sort_double', SORT, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_fpa_sort_double(Z3_context c); | ||||
|  | @ -187,8 +313,15 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create the double-precision (64-bit) FloatingPoint sort. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_sort_double. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_sort | ||||
|         \sa Z3_mk_fpa_sort_16 | ||||
|         \sa Z3_mk_fpa_sort_32 | ||||
|         \sa Z3_mk_fpa_sort_128 | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_sort_64', SORT, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_fpa_sort_64(Z3_context c); | ||||
|  | @ -196,8 +329,15 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create the quadruple-precision (128-bit) FloatingPoint sort. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_sort_128. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_sort | ||||
|         \sa Z3_mk_fpa_sort_half | ||||
|         \sa Z3_mk_fpa_sort_single | ||||
|         \sa Z3_mk_fpa_sort_double | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_sort_quadruple', SORT, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_fpa_sort_quadruple(Z3_context c); | ||||
|  | @ -205,8 +345,15 @@ extern "C" { | |||
|     /**
 | ||||
|         \brief Create the quadruple-precision (128-bit) FloatingPoint sort. | ||||
| 
 | ||||
|         This is the same as #Z3_mk_fpa_sort_quadruple. | ||||
| 
 | ||||
|         \param c logical context | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_sort | ||||
|         \sa Z3_mk_fpa_sort_16 | ||||
|         \sa Z3_mk_fpa_sort_32 | ||||
|         \sa Z3_mk_fpa_sort_64 | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_sort_128', SORT, (_in(CONTEXT),)) | ||||
|     */ | ||||
|     Z3_sort Z3_API Z3_mk_fpa_sort_128(Z3_context c); | ||||
|  | @ -218,6 +365,7 @@ extern "C" { | |||
|         \param s target sort | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_inf | ||||
|         \sa Z3_mk_fpa_is_nan | ||||
|         \sa Z3_mk_fpa_zero | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_nan', AST, (_in(CONTEXT),_in(SORT))) | ||||
|  | @ -233,6 +381,7 @@ extern "C" { | |||
| 
 | ||||
|         When \c negative is \c true, -oo will be generated instead of +oo. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_is_infinite | ||||
|         \sa Z3_mk_fpa_nan | ||||
|         \sa Z3_mk_fpa_zero | ||||
| 
 | ||||
|  | @ -250,6 +399,7 @@ extern "C" { | |||
|         When \c negative is \c true, -zero will be generated instead of +zero. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_inf | ||||
|         \sa Z3_mk_fpa_is_zero | ||||
|         \sa Z3_mk_fpa_nan | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_zero', AST, (_in(CONTEXT),_in(SORT),_in(BOOL))) | ||||
|  | @ -397,6 +547,10 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param t term of FloatingPoint sort | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_is_negative | ||||
|         \sa Z3_mk_fpa_is_positive | ||||
|         \sa Z3_mk_fpa_neg | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_abs', AST, (_in(CONTEXT),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_abs(Z3_context c, Z3_ast t); | ||||
|  | @ -407,6 +561,10 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param t term of FloatingPoint sort | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_abs | ||||
|         \sa Z3_mk_fpa_is_negative | ||||
|         \sa Z3_mk_fpa_is_positive | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_neg', AST, (_in(CONTEXT),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_neg(Z3_context c, Z3_ast t); | ||||
|  | @ -533,6 +691,8 @@ extern "C" { | |||
| 
 | ||||
|         \c t1, \c t2 must have the same FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_max | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_min', AST, (_in(CONTEXT),_in(AST),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_min(Z3_context c, Z3_ast t1, Z3_ast t2); | ||||
|  | @ -546,6 +706,8 @@ extern "C" { | |||
| 
 | ||||
|         \c t1, \c t2 must have the same FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_min | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_max', AST, (_in(CONTEXT),_in(AST),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_max(Z3_context c, Z3_ast t1, Z3_ast t2); | ||||
|  | @ -559,6 +721,11 @@ extern "C" { | |||
| 
 | ||||
|         \c t1 and \c t2 must have the same FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_eq | ||||
|         \sa Z3_mk_fpa_geq | ||||
|         \sa Z3_mk_fpa_gt | ||||
|         \sa Z3_mk_fpa_lt | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_leq', AST, (_in(CONTEXT),_in(AST),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_leq(Z3_context c, Z3_ast t1, Z3_ast t2); | ||||
|  | @ -572,6 +739,11 @@ extern "C" { | |||
| 
 | ||||
|         \c t1 and \c t2 must have the same FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_eq | ||||
|         \sa Z3_mk_fpa_geq | ||||
|         \sa Z3_mk_fpa_gt | ||||
|         \sa Z3_mk_fpa_leq | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_lt', AST, (_in(CONTEXT),_in(AST),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_lt(Z3_context c, Z3_ast t1, Z3_ast t2); | ||||
|  | @ -585,6 +757,11 @@ extern "C" { | |||
| 
 | ||||
|         \c t1 and \c t2 must have the same FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_eq | ||||
|         \sa Z3_mk_fpa_gt | ||||
|         \sa Z3_mk_fpa_leq | ||||
|         \sa Z3_mk_fpa_lt | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_geq', AST, (_in(CONTEXT),_in(AST),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_geq(Z3_context c, Z3_ast t1, Z3_ast t2); | ||||
|  | @ -598,6 +775,11 @@ extern "C" { | |||
| 
 | ||||
|         \c t1 and \c t2 must have the same FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_eq | ||||
|         \sa Z3_mk_fpa_geq | ||||
|         \sa Z3_mk_fpa_leq | ||||
|         \sa Z3_mk_fpa_lt | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_gt', AST, (_in(CONTEXT),_in(AST),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_gt(Z3_context c, Z3_ast t1, Z3_ast t2); | ||||
|  | @ -613,6 +795,11 @@ extern "C" { | |||
| 
 | ||||
|         \c t1 and \c t2 must have the same FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_geq | ||||
|         \sa Z3_mk_fpa_gt | ||||
|         \sa Z3_mk_fpa_leq | ||||
|         \sa Z3_mk_fpa_lt | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_eq', AST, (_in(CONTEXT),_in(AST),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_eq(Z3_context c, Z3_ast t1, Z3_ast t2); | ||||
|  | @ -625,6 +812,11 @@ extern "C" { | |||
| 
 | ||||
|         \c t must have FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_is_infinite | ||||
|         \sa Z3_mk_fpa_is_nan | ||||
|         \sa Z3_mk_fpa_is_subnormal | ||||
|         \sa Z3_mk_fpa_is_zero | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_is_normal', AST, (_in(CONTEXT),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_is_normal(Z3_context c, Z3_ast t); | ||||
|  | @ -637,6 +829,11 @@ extern "C" { | |||
| 
 | ||||
|         \c t must have FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_is_infinite | ||||
|         \sa Z3_mk_fpa_is_nan | ||||
|         \sa Z3_mk_fpa_is_normal | ||||
|         \sa Z3_mk_fpa_is_zero | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_is_subnormal', AST, (_in(CONTEXT),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_is_subnormal(Z3_context c, Z3_ast t); | ||||
|  | @ -649,6 +846,12 @@ extern "C" { | |||
| 
 | ||||
|         \c t must have FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_is_infinite | ||||
|         \sa Z3_mk_fpa_is_nan | ||||
|         \sa Z3_mk_fpa_is_normal | ||||
|         \sa Z3_mk_fpa_is_subnormal | ||||
|         \sa Z3_mk_fpa_zero | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_is_zero', AST, (_in(CONTEXT),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_is_zero(Z3_context c, Z3_ast t); | ||||
|  | @ -661,6 +864,12 @@ extern "C" { | |||
| 
 | ||||
|         \c t must have FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_inf | ||||
|         \sa Z3_mk_fpa_is_nan | ||||
|         \sa Z3_mk_fpa_is_normal | ||||
|         \sa Z3_mk_fpa_is_subnormal | ||||
|         \sa Z3_mk_fpa_is_zero | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_is_infinite', AST, (_in(CONTEXT),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_is_infinite(Z3_context c, Z3_ast t); | ||||
|  | @ -673,6 +882,12 @@ extern "C" { | |||
| 
 | ||||
|         \c t must have FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_is_infinite | ||||
|         \sa Z3_mk_fpa_is_normal | ||||
|         \sa Z3_mk_fpa_is_subnormal | ||||
|         \sa Z3_mk_fpa_is_zero | ||||
|         \sa Z3_mk_fpa_nan | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_is_nan', AST, (_in(CONTEXT),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_is_nan(Z3_context c, Z3_ast t); | ||||
|  | @ -685,6 +900,10 @@ extern "C" { | |||
| 
 | ||||
|         \c t must have FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_abs | ||||
|         \sa Z3_mk_fpa_is_positive | ||||
|         \sa Z3_mk_fpa_neg | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_is_negative', AST, (_in(CONTEXT),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_is_negative(Z3_context c, Z3_ast t); | ||||
|  | @ -697,6 +916,10 @@ extern "C" { | |||
| 
 | ||||
|         \c t must have FloatingPoint sort. | ||||
| 
 | ||||
|         \sa Z3_mk_fpa_abs | ||||
|         \sa Z3_mk_fpa_is_negative | ||||
|         \sa Z3_mk_fpa_neg | ||||
| 
 | ||||
|         def_API('Z3_mk_fpa_is_positive', AST, (_in(CONTEXT),_in(AST))) | ||||
|     */ | ||||
|     Z3_ast Z3_API Z3_mk_fpa_is_positive(Z3_context c, Z3_ast t); | ||||
|  | @ -848,6 +1071,8 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param s FloatingPoint sort | ||||
| 
 | ||||
|         \sa Z3_fpa_get_sbits | ||||
| 
 | ||||
|         def_API('Z3_fpa_get_ebits', UINT, (_in(CONTEXT),_in(SORT))) | ||||
|     */ | ||||
|     unsigned Z3_API Z3_fpa_get_ebits(Z3_context c, Z3_sort s); | ||||
|  | @ -858,6 +1083,8 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param s FloatingPoint sort | ||||
| 
 | ||||
|         \sa Z3_fpa_get_ebits | ||||
| 
 | ||||
|         def_API('Z3_fpa_get_sbits', UINT, (_in(CONTEXT),_in(SORT))) | ||||
|     */ | ||||
|     unsigned Z3_API Z3_fpa_get_sbits(Z3_context c, Z3_sort s); | ||||
|  | @ -868,6 +1095,11 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param t a floating-point numeral | ||||
| 
 | ||||
|         \sa Z3_fpa_is_numeral_inf | ||||
|         \sa Z3_fpa_is_numeral_normal | ||||
|         \sa Z3_fpa_is_numeral_subnormal | ||||
|         \sa Z3_fpa_is_numeral_zero | ||||
| 
 | ||||
|         def_API('Z3_fpa_is_numeral_nan', BOOL, (_in(CONTEXT), _in(AST))) | ||||
|     */ | ||||
|     bool Z3_API Z3_fpa_is_numeral_nan(Z3_context c, Z3_ast t); | ||||
|  | @ -878,6 +1110,11 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param t a floating-point numeral | ||||
| 
 | ||||
|         \sa Z3_fpa_is_numeral_nan | ||||
|         \sa Z3_fpa_is_numeral_normal | ||||
|         \sa Z3_fpa_is_numeral_subnormal | ||||
|         \sa Z3_fpa_is_numeral_zero | ||||
| 
 | ||||
|         def_API('Z3_fpa_is_numeral_inf', BOOL, (_in(CONTEXT), _in(AST))) | ||||
|     */ | ||||
|     bool Z3_API Z3_fpa_is_numeral_inf(Z3_context c, Z3_ast t); | ||||
|  | @ -888,6 +1125,11 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param t a floating-point numeral | ||||
| 
 | ||||
|         \sa Z3_fpa_is_numeral_inf | ||||
|         \sa Z3_fpa_is_numeral_nan | ||||
|         \sa Z3_fpa_is_numeral_normal | ||||
|         \sa Z3_fpa_is_numeral_subnormal | ||||
| 
 | ||||
|         def_API('Z3_fpa_is_numeral_zero', BOOL, (_in(CONTEXT), _in(AST))) | ||||
|     */ | ||||
|     bool Z3_API Z3_fpa_is_numeral_zero(Z3_context c, Z3_ast t); | ||||
|  | @ -898,6 +1140,11 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param t a floating-point numeral | ||||
| 
 | ||||
|         \sa Z3_fpa_is_numeral_inf | ||||
|         \sa Z3_fpa_is_numeral_nan | ||||
|         \sa Z3_fpa_is_numeral_subnormal | ||||
|         \sa Z3_fpa_is_numeral_zero | ||||
| 
 | ||||
|         def_API('Z3_fpa_is_numeral_normal', BOOL, (_in(CONTEXT), _in(AST))) | ||||
|     */ | ||||
|     bool Z3_API Z3_fpa_is_numeral_normal(Z3_context c, Z3_ast t); | ||||
|  | @ -908,6 +1155,11 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param t a floating-point numeral | ||||
| 
 | ||||
|         \sa Z3_fpa_is_numeral_inf | ||||
|         \sa Z3_fpa_is_numeral_nan | ||||
|         \sa Z3_fpa_is_numeral_normal | ||||
|         \sa Z3_fpa_is_numeral_zero | ||||
| 
 | ||||
|         def_API('Z3_fpa_is_numeral_subnormal', BOOL, (_in(CONTEXT), _in(AST))) | ||||
|     */ | ||||
|     bool Z3_API Z3_fpa_is_numeral_subnormal(Z3_context c, Z3_ast t); | ||||
|  | @ -918,6 +1170,8 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param t a floating-point numeral | ||||
| 
 | ||||
|         \sa Z3_fpa_is_numeral_negative | ||||
| 
 | ||||
|         def_API('Z3_fpa_is_numeral_positive', BOOL, (_in(CONTEXT), _in(AST))) | ||||
|     */ | ||||
|     bool Z3_API Z3_fpa_is_numeral_positive(Z3_context c, Z3_ast t); | ||||
|  | @ -928,6 +1182,8 @@ extern "C" { | |||
|         \param c logical context | ||||
|         \param t a floating-point numeral | ||||
| 
 | ||||
|         \sa Z3_fpa_is_numeral_positive | ||||
| 
 | ||||
|         def_API('Z3_fpa_is_numeral_negative', BOOL, (_in(CONTEXT), _in(AST))) | ||||
|     */ | ||||
|     bool Z3_API Z3_fpa_is_numeral_negative(Z3_context c, Z3_ast t); | ||||
|  |  | |||
							
								
								
									
										120
									
								
								src/api/z3_rcf.h
									
										
									
									
									
								
							
							
						
						
									
										120
									
								
								src/api/z3_rcf.h
									
										
									
									
									
								
							|  | @ -193,8 +193,124 @@ extern "C" { | |||
|        We have that \ccode{a = n/d}, moreover \c n and \c d are not represented using rational functions. | ||||
| 
 | ||||
|        def_API('Z3_rcf_get_numerator_denominator', VOID, (_in(CONTEXT), _in(RCF_NUM), _out(RCF_NUM), _out(RCF_NUM))) | ||||
|     */ | ||||
|     void Z3_API Z3_rcf_get_numerator_denominator(Z3_context c, Z3_rcf_num a, Z3_rcf_num * n, Z3_rcf_num * d); | ||||
|    */ | ||||
|    void Z3_API Z3_rcf_get_numerator_denominator(Z3_context c, Z3_rcf_num a, Z3_rcf_num * n, Z3_rcf_num * d); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Return \c true if \c a represents a rational number. | ||||
| 
 | ||||
|        def_API('Z3_rcf_is_rational', BOOL, (_in(CONTEXT), _in(RCF_NUM))) | ||||
|    */ | ||||
|    bool Z3_API Z3_rcf_is_rational(Z3_context c, Z3_rcf_num a); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Return \c true if \c a represents an algebraic number. | ||||
| 
 | ||||
|        def_API('Z3_rcf_is_algebraic', BOOL, (_in(CONTEXT), _in(RCF_NUM))) | ||||
|    */ | ||||
|    bool Z3_API Z3_rcf_is_algebraic(Z3_context c, Z3_rcf_num a); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Return \c true if \c a represents an infinitesimal. | ||||
| 
 | ||||
|        def_API('Z3_rcf_is_infinitesimal', BOOL, (_in(CONTEXT), _in(RCF_NUM))) | ||||
|    */ | ||||
|    bool Z3_API Z3_rcf_is_infinitesimal(Z3_context c, Z3_rcf_num a); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Return \c true if \c a represents a transcendental number. | ||||
| 
 | ||||
|        def_API('Z3_rcf_is_transcendental', BOOL, (_in(CONTEXT), _in(RCF_NUM))) | ||||
|    */ | ||||
|    bool Z3_API Z3_rcf_is_transcendental(Z3_context c, Z3_rcf_num a); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Return the index of a field extension. | ||||
| 
 | ||||
|       def_API('Z3_rcf_extension_index', UINT, (_in(CONTEXT), _in(RCF_NUM))) | ||||
|    */ | ||||
|    unsigned Z3_API Z3_rcf_extension_index(Z3_context c, Z3_rcf_num a); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Return the name of a transcendental. | ||||
| 
 | ||||
|        \pre Z3_rcf_is_transcendtal(ctx, a); | ||||
| 
 | ||||
|        def_API('Z3_rcf_transcendental_name', SYMBOL, (_in(CONTEXT), _in(RCF_NUM))) | ||||
|    */ | ||||
|    Z3_symbol Z3_API Z3_rcf_transcendental_name(Z3_context c, Z3_rcf_num a); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Return the name of an infinitesimal. | ||||
| 
 | ||||
|        \pre Z3_rcf_is_infinitesimal(ctx, a); | ||||
| 
 | ||||
|        def_API('Z3_rcf_infinitesimal_name', SYMBOL, (_in(CONTEXT), _in(RCF_NUM))) | ||||
|    */ | ||||
|    Z3_symbol Z3_API Z3_rcf_infinitesimal_name(Z3_context c, Z3_rcf_num a); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Return the number of coefficients in an algebraic number. | ||||
| 
 | ||||
|        \pre Z3_rcf_is_algebraic(ctx, a); | ||||
| 
 | ||||
|        def_API('Z3_rcf_num_coefficients', UINT, (_in(CONTEXT), _in(RCF_NUM))) | ||||
|    */ | ||||
|    unsigned Z3_API Z3_rcf_num_coefficients(Z3_context c, Z3_rcf_num a); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Extract a coefficient from an algebraic number. | ||||
| 
 | ||||
|        \pre Z3_rcf_is_algebraic(ctx, a); | ||||
| 
 | ||||
|        def_API('Z3_rcf_coefficient', RCF_NUM, (_in(CONTEXT), _in(RCF_NUM), _in(UINT))) | ||||
|    */ | ||||
|    Z3_rcf_num Z3_API Z3_rcf_coefficient(Z3_context c, Z3_rcf_num a, unsigned i); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Extract an interval from an algebraic number. | ||||
| 
 | ||||
|        \pre Z3_rcf_is_algebraic(ctx, a); | ||||
| 
 | ||||
|        def_API('Z3_rcf_interval', INT, (_in(CONTEXT), _in(RCF_NUM), _out(INT), _out(INT), _out(RCF_NUM), _out(INT), _out(INT), _out(RCF_NUM))) | ||||
|    */ | ||||
|    int Z3_API Z3_rcf_interval(Z3_context c, Z3_rcf_num a, int * lower_is_inf, int * lower_is_open, Z3_rcf_num * lower, int * upper_is_inf, int * upper_is_open, Z3_rcf_num * upper); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Return the number of sign conditions of an algebraic number. | ||||
| 
 | ||||
|        \pre Z3_rcf_is_algebraic(ctx, a); | ||||
| 
 | ||||
|        def_API('Z3_rcf_num_sign_conditions', UINT, (_in(CONTEXT), _in(RCF_NUM))) | ||||
|    */ | ||||
|    unsigned Z3_API Z3_rcf_num_sign_conditions(Z3_context c, Z3_rcf_num a); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Extract the sign of a sign condition from an algebraic number. | ||||
| 
 | ||||
|        \pre Z3_rcf_is_algebraic(ctx, a); | ||||
| 
 | ||||
|        def_API('Z3_rcf_sign_condition_sign', INT, (_in(CONTEXT), _in(RCF_NUM), _in(UINT))) | ||||
|    */ | ||||
|    int Z3_API Z3_rcf_sign_condition_sign(Z3_context c, Z3_rcf_num a, unsigned i); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Return the number of sign condition polynomial coefficients of an algebraic number. | ||||
| 
 | ||||
|        \pre Z3_rcf_is_algebraic(ctx, a); | ||||
| 
 | ||||
|        def_API('Z3_rcf_num_sign_condition_coefficients', UINT, (_in(CONTEXT), _in(RCF_NUM), _in(UINT))) | ||||
|    */ | ||||
|    unsigned Z3_API Z3_rcf_num_sign_condition_coefficients(Z3_context c, Z3_rcf_num a, unsigned i); | ||||
| 
 | ||||
|    /**
 | ||||
|        \brief Extract the j-th polynomial coefficient of the i-th sign condition. | ||||
| 
 | ||||
|        \pre Z3_rcf_is_algebraic(ctx, a); | ||||
| 
 | ||||
|        def_API('Z3_rcf_sign_condition_coefficient', RCF_NUM, (_in(CONTEXT), _in(RCF_NUM), _in(UINT), _in(UINT))) | ||||
|    */ | ||||
|    Z3_rcf_num Z3_API Z3_rcf_sign_condition_coefficient(Z3_context c, Z3_rcf_num a, unsigned i, unsigned j); | ||||
| 
 | ||||
|     /**@}*/ | ||||
|     /**@}*/ | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ z3_add_component(ast | |||
|     act_cache.cpp | ||||
|     arith_decl_plugin.cpp | ||||
|     array_decl_plugin.cpp | ||||
|     array_peq.cpp | ||||
|     ast.cpp | ||||
|     ast_ll_pp.cpp | ||||
|     ast_lt.cpp | ||||
|  | @ -37,6 +38,8 @@ z3_add_component(ast | |||
|     num_occurs.cpp | ||||
|     occurs.cpp | ||||
|     pb_decl_plugin.cpp | ||||
|     polymorphism_inst.cpp | ||||
|     polymorphism_util.cpp | ||||
|     pp.cpp | ||||
|     quantifier_stat.cpp | ||||
|     recfun_decl_plugin.cpp | ||||
|  |  | |||
|  | @ -801,6 +801,29 @@ expr_ref arith_util::mk_add_simplify(unsigned sz, expr* const* args) { | |||
|     return result; | ||||
| } | ||||
| 
 | ||||
| bool arith_util::is_considered_partially_interpreted(func_decl* f, unsigned n, expr* const* args, func_decl_ref& f_out) { | ||||
|     if (is_decl_of(f, arith_family_id, OP_DIV) && n == 2 && !is_numeral(args[1])) { | ||||
|         f_out = mk_div0(); | ||||
|         return true; | ||||
|     } | ||||
|     if (is_decl_of(f, arith_family_id, OP_IDIV) && n == 2 && !is_numeral(args[1])) { | ||||
|         sort* rs[2] = { mk_int(), mk_int() }; | ||||
|         f_out = m_manager.mk_func_decl(arith_family_id, OP_IDIV0, 0, nullptr, 2, rs, mk_int()); | ||||
|         return true; | ||||
|     } | ||||
|     if (is_decl_of(f, arith_family_id, OP_MOD) && n == 2 && !is_numeral(args[1])) { | ||||
|         sort* rs[2] = { mk_int(), mk_int() }; | ||||
|         f_out = m_manager.mk_func_decl(arith_family_id, OP_MOD0, 0, nullptr, 2, rs, mk_int()); | ||||
|         return true; | ||||
|     } | ||||
|     if (is_decl_of(f, arith_family_id, OP_REM) && n == 2 && !is_numeral(args[1])) { | ||||
|         sort* rs[2] = { mk_int(), mk_int() }; | ||||
|         f_out = m_manager.mk_func_decl(arith_family_id, OP_MOD0, 0, nullptr, 2, rs, mk_int()); | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool arith_util::is_considered_uninterpreted(func_decl* f, unsigned n, expr* const* args, func_decl_ref& f_out) { | ||||
|     rational r; | ||||
|     if (is_decl_of(f, arith_family_id, OP_DIV) && n == 2 && is_numeral(args[1], r) && r.is_zero()) { | ||||
|  |  | |||
|  | @ -517,6 +517,8 @@ public: | |||
| 
 | ||||
|     bool is_considered_uninterpreted(func_decl* f, unsigned n, expr* const* args, func_decl_ref& f_out); | ||||
| 
 | ||||
|     bool is_considered_partially_interpreted(func_decl* f, unsigned n, expr* const* args, func_decl_ref& f_out); | ||||
| 
 | ||||
|     bool is_underspecified(expr* e) const; | ||||
| 
 | ||||
|     bool is_bounded(expr* e) const; | ||||
|  |  | |||
|  | @ -633,6 +633,12 @@ bool array_decl_plugin::is_value(app * _e) const { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| bool array_decl_plugin::is_unique_value(app* _e) const { | ||||
|     array_util u(*m_manager); | ||||
|     expr* e = _e; | ||||
|     return u.is_const(e, e) && m_manager->is_unique_value(e); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| func_decl * array_recognizers::get_as_array_func_decl(expr * n) const {  | ||||
|     SASSERT(is_as_array(n));  | ||||
|  |  | |||
|  | @ -137,6 +137,8 @@ class array_decl_plugin : public decl_plugin { | |||
| 
 | ||||
|     bool is_value(app * e) const override; | ||||
| 
 | ||||
|     bool is_unique_value(app* e) const override; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| class array_recognizers { | ||||
|  | @ -184,6 +186,21 @@ public: | |||
| 
 | ||||
|     bool is_store_ext(expr* e, expr_ref& a, expr_ref_vector& args, expr_ref& value); | ||||
| 
 | ||||
| 
 | ||||
|     bool is_select1(expr* n) const { return is_select(n) && to_app(n)->get_num_args() == 2; } | ||||
|      | ||||
|     bool is_select1(expr* n, expr*& a, expr*& i) const { | ||||
|         return is_select1(n) && (a = to_app(n)->get_arg(0), i = to_app(n)->get_arg(1), true); | ||||
|     } | ||||
| 
 | ||||
|     bool is_store1(expr* n) const { return is_store(n) && to_app(n)->get_num_args() == 3; } | ||||
|      | ||||
|     bool is_store1(expr* n, expr*& a, expr*& i, expr*& v) const { | ||||
|         app* _n; | ||||
|         return is_store1(n) && (_n = to_app(n), a = _n->get_arg(0), i = _n->get_arg(1), v = _n->get_arg(2), true); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     MATCH_BINARY(is_subset); | ||||
| }; | ||||
| 
 | ||||
|  | @ -211,6 +228,11 @@ public: | |||
|         return mk_store(args.size(), args.data()); | ||||
|     } | ||||
| 
 | ||||
|     app * mk_select(expr* a, expr* i) const { | ||||
|         expr* args[2] = { a, i }; | ||||
|         return mk_select(2, args); | ||||
|     } | ||||
| 
 | ||||
|     app * mk_select(unsigned num_args, expr * const * args) const { | ||||
|         return m_manager.mk_app(m_fid, OP_SELECT, 0, nullptr, num_args, args); | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										107
									
								
								src/ast/array_peq.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								src/ast/array_peq.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,107 @@ | |||
| /*++
 | ||||
| Copyright (c) 2023 Microsoft Corporation | ||||
| 
 | ||||
| Module Name: | ||||
| 
 | ||||
|     array_peq.cpp | ||||
| 
 | ||||
| Abstract: | ||||
| 
 | ||||
|   Partial equality for arrays | ||||
| 
 | ||||
| Author: | ||||
| 
 | ||||
|     Nikolaj Bjorner (nbjorner) 2015-06-13 | ||||
|     Hari Govind V K | ||||
| 
 | ||||
| Revision History: | ||||
| 
 | ||||
| --*/ | ||||
| #include "ast/array_peq.h" | ||||
| 
 | ||||
| #define PARTIAL_EQ "!partial_eq" | ||||
| bool is_partial_eq(const func_decl *f) { | ||||
|     SASSERT(f); | ||||
|     return f->get_name() == PARTIAL_EQ; | ||||
| } | ||||
| 
 | ||||
| bool is_partial_eq(const app *a) { | ||||
|     SASSERT(a); | ||||
|     return is_partial_eq(a->get_decl()); | ||||
| } | ||||
| 
 | ||||
| app_ref mk_peq(expr *e0, expr *e1, vector<expr_ref_vector> const &indices, | ||||
|                ast_manager &m) { | ||||
|     peq p(e0, e1, indices, m); | ||||
|     return p.mk_peq(); | ||||
| } | ||||
| 
 | ||||
| app_ref peq::mk_eq(app_ref_vector &aux_consts, bool stores_on_rhs) { | ||||
|     if (!m_eq) { | ||||
|         expr_ref lhs(m_lhs, m), rhs(m_rhs, m); | ||||
|         if (!stores_on_rhs) { std::swap(lhs, rhs); } | ||||
|         // lhs = (...(store (store rhs i0 v0) i1 v1)...)
 | ||||
|         sort *val_sort = get_array_range(lhs->get_sort()); | ||||
|         for (expr_ref_vector const &diff : m_diff_indices) { | ||||
|             ptr_vector<expr> store_args; | ||||
|             store_args.push_back(rhs); | ||||
|             store_args.append(diff.size(), diff.data()); | ||||
|             app_ref val(m.mk_fresh_const("diff", val_sort), m); | ||||
|             store_args.push_back(val); | ||||
|             aux_consts.push_back(val); | ||||
|             rhs = m_arr_u.mk_store(store_args); | ||||
|         } | ||||
|         m_eq = m.mk_eq(lhs, rhs); | ||||
|     } | ||||
|     return m_eq; | ||||
| } | ||||
| 
 | ||||
| app_ref peq::mk_peq() { | ||||
|     if (!m_peq) { | ||||
|         ptr_vector<expr> args; | ||||
|         args.push_back(m_lhs); | ||||
|         args.push_back(m_rhs); | ||||
|         for (auto const &v : m_diff_indices) { | ||||
|             args.append(v.size(), v.data()); | ||||
|         } | ||||
|         m_peq = m.mk_app(m_decl, args.size(), args.data()); | ||||
|     } | ||||
|     return m_peq; | ||||
| } | ||||
| 
 | ||||
| peq::peq(expr *lhs, expr *rhs, vector<expr_ref_vector> const &diff_indices, | ||||
|          ast_manager &m) | ||||
|     : m(m), m_lhs(lhs, m), m_rhs(rhs, m), m_diff_indices(diff_indices), | ||||
|       m_decl(m), m_peq(m), m_eq(m), m_arr_u(m) { | ||||
|     SASSERT(m_arr_u.is_array(lhs)); | ||||
|     SASSERT(m_arr_u.is_array(rhs)); | ||||
|     SASSERT(lhs->get_sort() == rhs->get_sort()); | ||||
|     ptr_vector<sort> sorts; | ||||
|     sorts.push_back(m_lhs->get_sort()); | ||||
|     sorts.push_back(m_rhs->get_sort()); | ||||
| 
 | ||||
|     for (auto const &v : diff_indices) { | ||||
|         SASSERT(v.size() == get_array_arity(m_lhs->get_sort())); | ||||
|         for (expr *e : v) sorts.push_back(e->get_sort()); | ||||
|     } | ||||
|     m_decl = m.mk_func_decl(symbol(PARTIAL_EQ), sorts.size(), sorts.data(), | ||||
|                             m.mk_bool_sort()); | ||||
| } | ||||
| 
 | ||||
| peq::peq(app *p, ast_manager &m) | ||||
|     : m(m), m_lhs(p->get_arg(0), m), m_rhs(p->get_arg(1), m), | ||||
|       m_decl(p->get_decl(), m), m_peq(p, m), m_eq(m), m_arr_u(m), | ||||
|       m_name(symbol(PARTIAL_EQ)) { | ||||
|     SASSERT(is_partial_eq(p)); | ||||
| 
 | ||||
|     SASSERT(m_arr_u.is_array(m_lhs)); | ||||
|     SASSERT(m_arr_u.is_array(m_rhs)); | ||||
|     SASSERT(m_lhs->get_sort() == m_rhs->get_sort()); | ||||
|     unsigned arity = get_array_arity(m_lhs->get_sort()); | ||||
|     for (unsigned i = 2; i < p->get_num_args(); i += arity) { | ||||
|         SASSERT(arity + i <= p->get_num_args()); | ||||
|         expr_ref_vector vec(m); | ||||
|         vec.append(arity, p->get_args() + i); | ||||
|         m_diff_indices.push_back(std::move(vec)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										91
									
								
								src/ast/array_peq.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/ast/array_peq.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | |||
| /*++
 | ||||
| Copyright (c) 2023 Microsoft Corporation | ||||
| 
 | ||||
| Module Name: | ||||
| 
 | ||||
|     array_peq.h | ||||
| 
 | ||||
| Abstract: | ||||
| 
 | ||||
|   Partial equality for arrays | ||||
| 
 | ||||
| Author: | ||||
| 
 | ||||
|     Nikolaj Bjorner (nbjorner) 2015-06-13 | ||||
|     Hari Govind V K | ||||
| 
 | ||||
| Revision History: | ||||
| 
 | ||||
| --*/ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "ast/array_decl_plugin.h" | ||||
| #include "ast/ast.h" | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief utility class for partial equalities | ||||
|  * | ||||
|  * A partial equality (a ==I b), for two arrays a, b and a finite set of indices | ||||
|  * I holds iff (forall i :: i \not\in I => a[i] == b[i]). In other words, peq is | ||||
|  * a restricted form of the extensionality axiom | ||||
|  * | ||||
|  * Using this class, we denote (a =I b) as f(a,b,i0,i1,...), | ||||
|  * where f is an uninterpreted predicate with the name PARTIAL_EQ and | ||||
|  * I = {i0,i1,...} | ||||
|  */ | ||||
| 
 | ||||
| class peq { | ||||
|     ast_manager &m; | ||||
|     expr_ref m_lhs; | ||||
|     expr_ref m_rhs; | ||||
|     vector<expr_ref_vector> m_diff_indices; | ||||
|     func_decl_ref m_decl; // the partial equality declaration
 | ||||
|     app_ref m_peq;        // partial equality application
 | ||||
|     app_ref m_eq;         // equivalent std equality using def. of partial eq
 | ||||
|     array_util m_arr_u; | ||||
|     symbol m_name; | ||||
| 
 | ||||
|   public: | ||||
|     peq(app *p, ast_manager &m); | ||||
| 
 | ||||
|     peq(expr *lhs, expr *rhs, vector<expr_ref_vector> const &diff_indices, | ||||
|         ast_manager &m); | ||||
| 
 | ||||
|     expr_ref lhs() { return m_lhs; } | ||||
| 
 | ||||
|     expr_ref rhs() { return m_rhs; } | ||||
| 
 | ||||
|     void get_diff_indices(vector<expr_ref_vector> &result) { | ||||
|         result.append(m_diff_indices); | ||||
|     } | ||||
| 
 | ||||
|     /** Convert peq into a peq expression */ | ||||
|     app_ref mk_peq(); | ||||
| 
 | ||||
|     /** Convert peq into an equality
 | ||||
| 
 | ||||
|         For peq of the form (a =I b) returns (a = b[i0 := v0, i1 := v1, ...]) | ||||
|         where i0, i1 \in I, and v0, v1 are fresh skolem constants | ||||
| 
 | ||||
|         Skolems are returned in aux_consts | ||||
| 
 | ||||
|         The left and right hand arguments are reversed when stores_on_rhs is | ||||
|        false | ||||
|      */ | ||||
|     app_ref mk_eq(app_ref_vector &aux_consts, bool stores_on_rhs = true); | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * mk (e0 ==indices e1) | ||||
|  * | ||||
|  * result has stores if either e0 or e1 or an index term has stores | ||||
|  */ | ||||
| app_ref mk_peq(expr *e0, expr *e1, vector<expr_ref_vector> const &indices, | ||||
|                ast_manager &m); | ||||
| 
 | ||||
| bool is_partial_eq(const func_decl *f); | ||||
| 
 | ||||
| bool is_partial_eq(const app *a); | ||||
| 
 | ||||
| inline bool is_peq(const func_decl *f) { return is_partial_eq(f); } | ||||
| inline bool is_peq(const app *a) { return is_partial_eq(a); } | ||||
							
								
								
									
										168
									
								
								src/ast/ast.cpp
									
										
									
									
									
								
							
							
						
						
									
										168
									
								
								src/ast/ast.cpp
									
										
									
									
									
								
							|  | @ -202,8 +202,7 @@ unsigned decl_info::hash() const { | |||
| 
 | ||||
| bool decl_info::operator==(decl_info const & info) const { | ||||
|     return m_family_id == info.m_family_id && m_kind == info.m_kind && | ||||
|         m_parameters.size() == info.m_parameters.size() &&  | ||||
|         compare_arrays<parameter>(m_parameters.begin(), info.m_parameters.begin(), m_parameters.size()); | ||||
|            m_parameters == info.m_parameters; | ||||
| } | ||||
| 
 | ||||
| std::ostream & operator<<(std::ostream & out, decl_info const & info) { | ||||
|  | @ -255,7 +254,8 @@ func_decl_info::func_decl_info(family_id family_id, decl_kind k, unsigned num_pa | |||
|     m_injective(false), | ||||
|     m_idempotent(false), | ||||
|     m_skolem(false), | ||||
|     m_lambda(false) { | ||||
|     m_lambda(false), | ||||
|     m_polymorphic(false) { | ||||
| } | ||||
| 
 | ||||
| bool func_decl_info::operator==(func_decl_info const & info) const { | ||||
|  | @ -283,6 +283,7 @@ std::ostream & operator<<(std::ostream & out, func_decl_info const & info) { | |||
|     if (info.is_idempotent()) out << " :idempotent "; | ||||
|     if (info.is_skolem()) out << " :skolem "; | ||||
|     if (info.is_lambda()) out << " :lambda "; | ||||
|     if (info.is_polymorphic()) out << " :polymorphic "; | ||||
|     return out; | ||||
| } | ||||
| 
 | ||||
|  | @ -447,7 +448,7 @@ bool compare_nodes(ast const * n1, ast const * n2) { | |||
|         if (to_sort(n1)->get_info() != nullptr && !(*to_sort(n1)->get_info() == *to_sort(n2)->get_info())) { | ||||
|             return false; | ||||
|         } | ||||
|         return to_sort(n1)->get_name()  == to_sort(n2)->get_name(); | ||||
|         return to_sort(n1)->get_name() == to_sort(n2)->get_name(); | ||||
|     case AST_FUNC_DECL: | ||||
|         if ((to_func_decl(n1)->get_info() == nullptr) != (to_func_decl(n2)->get_info() == nullptr)) { | ||||
|             return false; | ||||
|  | @ -477,15 +478,15 @@ bool compare_nodes(ast const * n1, ast const * n2) { | |||
|         return | ||||
|             q1->get_kind()         == q2->get_kind() && | ||||
|             q1->get_num_decls()    == q2->get_num_decls() && | ||||
|             q1->get_expr()         == q2->get_expr() && | ||||
|             q1->get_weight()       == q2->get_weight() && | ||||
|             q1->get_num_patterns() == q2->get_num_patterns() && | ||||
|             compare_arrays(q1->get_decl_sorts(), | ||||
|                            q2->get_decl_sorts(), | ||||
|                            q1->get_num_decls()) && | ||||
|             compare_arrays(q1->get_decl_names(), | ||||
|                            q2->get_decl_names(), | ||||
|                            q1->get_num_decls()) && | ||||
|             q1->get_expr()         == q2->get_expr() && | ||||
|             q1->get_weight()       == q2->get_weight() && | ||||
|             q1->get_num_patterns() == q2->get_num_patterns() && | ||||
|             ((q1->get_qid().is_numerical() && q2->get_qid().is_numerical()) || | ||||
|              (q1->get_qid() == q2->get_qid())) &&  | ||||
|             compare_arrays(q1->get_patterns(), | ||||
|  | @ -540,22 +541,6 @@ inline unsigned ast_array_hash(T * const * array, unsigned size, unsigned init_v | |||
|     } } | ||||
| } | ||||
| 
 | ||||
| unsigned get_asts_hash(unsigned sz, ast * const* ns, unsigned init) { | ||||
|     return ast_array_hash<ast>(ns, sz, init); | ||||
| } | ||||
| unsigned get_apps_hash(unsigned sz, app * const* ns, unsigned init) { | ||||
|     return ast_array_hash<app>(ns, sz, init); | ||||
| } | ||||
| unsigned get_exprs_hash(unsigned sz, expr * const* ns, unsigned init) { | ||||
|     return ast_array_hash<expr>(ns, sz, init); | ||||
| } | ||||
| unsigned get_sorts_hash(unsigned sz, sort * const* ns, unsigned init) { | ||||
|     return ast_array_hash<sort>(ns, sz, init); | ||||
| } | ||||
| unsigned get_decl_hash(unsigned sz, func_decl* const* ns, unsigned init) { | ||||
|     return ast_array_hash<func_decl>(ns, sz, init); | ||||
| } | ||||
| 
 | ||||
| unsigned get_node_hash(ast const * n) { | ||||
|     unsigned a, b, c; | ||||
| 
 | ||||
|  | @ -1309,10 +1294,7 @@ ast_manager::ast_manager(proof_gen_mode m, char const * trace_file, bool is_form | |||
|     m_expr_array_manager(*this, m_alloc), | ||||
|     m_expr_dependency_manager(*this, m_alloc), | ||||
|     m_expr_dependency_array_manager(*this, m_alloc), | ||||
|     m_proof_mode(m), | ||||
|     m_trace_stream(nullptr), | ||||
|     m_trace_stream_owner(false), | ||||
|     m_lambda_def(":lambda-def") { | ||||
|     m_proof_mode(m) { | ||||
| 
 | ||||
|     if (trace_file) { | ||||
|         m_trace_stream       = alloc(std::fstream, trace_file, std::ios_base::out); | ||||
|  | @ -1333,9 +1315,7 @@ ast_manager::ast_manager(proof_gen_mode m, std::fstream * trace_stream, bool is_ | |||
|     m_expr_dependency_manager(*this, m_alloc), | ||||
|     m_expr_dependency_array_manager(*this, m_alloc), | ||||
|     m_proof_mode(m), | ||||
|     m_trace_stream(trace_stream), | ||||
|     m_trace_stream_owner(false), | ||||
|     m_lambda_def(":lambda-def") { | ||||
|     m_trace_stream(trace_stream) { | ||||
| 
 | ||||
|     if (!is_format_manager) | ||||
|         m_format_manager = alloc(ast_manager, PGM_DISABLED, trace_stream, true); | ||||
|  | @ -1350,9 +1330,7 @@ ast_manager::ast_manager(ast_manager const & src, bool disable_proofs): | |||
|     m_expr_dependency_manager(*this, m_alloc), | ||||
|     m_expr_dependency_array_manager(*this, m_alloc), | ||||
|     m_proof_mode(disable_proofs ? PGM_DISABLED : src.m_proof_mode), | ||||
|     m_trace_stream(src.m_trace_stream), | ||||
|     m_trace_stream_owner(false), | ||||
|     m_lambda_def(":lambda-def") { | ||||
|     m_trace_stream(src.m_trace_stream) { | ||||
|     SASSERT(!src.is_format_manager()); | ||||
|     m_format_manager = alloc(ast_manager, PGM_DISABLED, m_trace_stream, true); | ||||
|     init(); | ||||
|  | @ -1880,6 +1858,8 @@ void ast_manager::delete_node(ast * n) { | |||
|             break; | ||||
|         case AST_FUNC_DECL: { | ||||
|             func_decl* f = to_func_decl(n); | ||||
|             if (f->is_polymorphic()) | ||||
|                 m_poly_roots.erase(f); | ||||
|             if (f->m_info != nullptr) { | ||||
|                 func_decl_info * info = f->get_info(); | ||||
|                 if (info->is_lambda()) { | ||||
|  | @ -2020,10 +2000,6 @@ sort * ast_manager::mk_uninterpreted_sort(symbol const & name, unsigned num_para | |||
|     return plugin->mk_sort(kind, num_parameters, parameters); | ||||
| } | ||||
| 
 | ||||
| sort * ast_manager::mk_type_var(symbol const& name) { | ||||
|     sort_info si(poly_family_id, 0); | ||||
|     return mk_sort(name, &si); | ||||
| } | ||||
| 
 | ||||
| func_decl * ast_manager::mk_func_decl(symbol const & name, unsigned arity, sort * const * domain, sort * range, | ||||
|                                       bool assoc, bool comm, bool inj) { | ||||
|  | @ -2035,13 +2011,30 @@ func_decl * ast_manager::mk_func_decl(symbol const & name, unsigned arity, sort | |||
| } | ||||
| 
 | ||||
| func_decl * ast_manager::mk_func_decl(symbol const & name, unsigned arity, sort * const * domain, sort * range, func_decl_info * info) { | ||||
|     SASSERT(arity == 1 || info == 0 || !info->is_injective()); | ||||
|     SASSERT(arity == 2 || info == 0 || !info->is_associative()); | ||||
|     SASSERT(arity == 2 || info == 0 || !info->is_commutative()); | ||||
|     SASSERT(arity == 1 || !info || !info->is_injective()); | ||||
|     SASSERT(arity == 2 || !info || !info->is_associative()); | ||||
|     SASSERT(arity == 2 || !info || !info->is_commutative()); | ||||
|     unsigned sz               = func_decl::get_obj_size(arity); | ||||
|     void * mem                = allocate_node(sz); | ||||
|     func_decl * new_node = new (mem) func_decl(name, arity, domain, range, info); | ||||
|     return register_node(new_node); | ||||
| 
 | ||||
|     // determine if function is a polymorphic root object.
 | ||||
|     // instances of polymorphic functions are automatically tagged as polymorphic and
 | ||||
|     // inserted into the m_poly_roots table.
 | ||||
|     bool is_polymorphic_root = false; | ||||
|     func_decl_info info0; | ||||
|     if (has_type_var(arity, domain, range)) { | ||||
|         if (!info) | ||||
|             info = &info0; | ||||
|         if (!info->is_polymorphic()) { | ||||
|             info->set_polymorphic(true); | ||||
|             is_polymorphic_root = true; | ||||
|         } | ||||
|     } | ||||
|     func_decl* new_node = new (mem) func_decl(name, arity, domain, range, info); | ||||
|     new_node = register_node(new_node); | ||||
|     if (is_polymorphic_root)  | ||||
|         m_poly_roots.insert(new_node, new_node); | ||||
|     return new_node; | ||||
| } | ||||
| 
 | ||||
| void ast_manager::check_sort(func_decl const * decl, unsigned num_args, expr * const * args) const { | ||||
|  | @ -2306,9 +2299,10 @@ func_decl * ast_manager::mk_fresh_func_decl(symbol const & prefix, symbol const | |||
|     func_decl_info info(null_family_id, null_decl_kind); | ||||
|     info.m_skolem = skolem; | ||||
|     SASSERT(skolem == info.is_skolem()); | ||||
|     func_decl_info* infop = skolem ? &info : nullptr; | ||||
|     func_decl * d; | ||||
|     if (prefix == symbol::null && suffix == symbol::null) { | ||||
|         d = mk_func_decl(symbol(m_fresh_id), arity, domain, range, &info); | ||||
|         d = mk_func_decl(symbol(m_fresh_id), arity, domain, range, infop); | ||||
|     } | ||||
|     else { | ||||
|         string_buffer<64> buffer; | ||||
|  | @ -2320,10 +2314,10 @@ func_decl * ast_manager::mk_fresh_func_decl(symbol const & prefix, symbol const | |||
|         if (suffix != symbol::null) | ||||
|             buffer << suffix << "!"; | ||||
|         buffer << m_fresh_id; | ||||
|         d = mk_func_decl(symbol(buffer.c_str()), arity, domain, range, &info); | ||||
|         d = mk_func_decl(symbol(buffer.c_str()), arity, domain, range, infop); | ||||
|     } | ||||
|     m_fresh_id++; | ||||
|     SASSERT(d->get_info()); | ||||
|     SASSERT(!skolem || d->get_info()); | ||||
|     SASSERT(skolem == d->is_skolem()); | ||||
|     return d; | ||||
| } | ||||
|  | @ -2725,6 +2719,49 @@ bool ast_manager::is_fully_interp(sort * s) const { | |||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // -----------------------------------------
 | ||||
| // Polymorphism
 | ||||
| // -----------------------------------------
 | ||||
| sort * ast_manager::mk_type_var(symbol const& name) { | ||||
|     m_has_type_vars = true; | ||||
|     sort_info si(poly_family_id, 0); | ||||
|     return mk_sort(name, &si); | ||||
| } | ||||
| 
 | ||||
| bool ast_manager::has_type_var(sort* s) const { | ||||
|     if (is_type_var(s)) | ||||
|         return true; | ||||
|     for (parameter const& p : s->parameters())  | ||||
|         if (p.is_ast() && is_sort(p.get_ast()) && has_type_var(to_sort(p.get_ast()))) | ||||
|             return true;    | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool ast_manager::has_type_var(func_decl* f) const { | ||||
|     return has_type_var(f->get_arity(), f->get_domain(), f->get_range()); | ||||
| } | ||||
| 
 | ||||
| bool ast_manager::has_type_var(unsigned n, sort* const* domain, sort* range) const { | ||||
|     if (!has_type_vars()) | ||||
|         return false; | ||||
|     for (unsigned i = n; i-- > 0; ) | ||||
|         if (has_type_var(domain[i])) | ||||
|             return true; | ||||
|     return has_type_var(range);     | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * \brief create an instantiation of polymorphic function f. | ||||
|  */ | ||||
| 
 | ||||
| func_decl* ast_manager::instantiate_polymorphic(func_decl* f, unsigned arity, sort * const* domain, sort * range) { | ||||
|     SASSERT(f->is_polymorphic()); | ||||
|     func_decl* g = mk_func_decl(f->get_name(), arity, domain, range, f->get_info()); | ||||
|     m_poly_roots.insert(g, f); | ||||
|     // SASSERT(g->is_polymorphic());
 | ||||
|     return g; | ||||
| } | ||||
| 
 | ||||
| // -----------------------------------
 | ||||
| //
 | ||||
| // Proof generation
 | ||||
|  | @ -2847,29 +2884,40 @@ proof * ast_manager::mk_transitivity(proof * p1, proof * p2) { | |||
|     SASSERT(has_fact(p2)); | ||||
|     SASSERT(is_app(get_fact(p1))); | ||||
|     SASSERT(is_app(get_fact(p2))); | ||||
|     SASSERT(to_app(get_fact(p1))->get_num_args() == 2); | ||||
|     SASSERT(to_app(get_fact(p2))->get_num_args() == 2); | ||||
|     CTRACE("mk_transitivity", to_app(get_fact(p1))->get_decl() != to_app(get_fact(p2))->get_decl(), | ||||
|            tout << mk_pp(get_fact(p1), *this) << "\n\n" << mk_pp(get_fact(p2), *this) << "\n"; | ||||
|            tout << mk_pp(to_app(get_fact(p1))->get_decl(), *this) << "\n"; | ||||
|            tout << mk_pp(to_app(get_fact(p2))->get_decl(), *this) << "\n";); | ||||
|     SASSERT(to_app(get_fact(p1))->get_decl() == to_app(get_fact(p2))->get_decl() || | ||||
|             ( (is_eq(get_fact(p1)) || is_oeq(get_fact(p1))) && | ||||
|               (is_eq(get_fact(p2)) || is_oeq(get_fact(p2))))); | ||||
|     CTRACE("mk_transitivity", to_app(get_fact(p1))->get_arg(1) != to_app(get_fact(p2))->get_arg(0), | ||||
|            tout << mk_pp(get_fact(p1), *this) << "\n\n" << mk_pp(get_fact(p2), *this) << "\n"; | ||||
|     app* fact1 = to_app(get_fact(p1)); | ||||
|     app* fact2 = to_app(get_fact(p2)); | ||||
|     SASSERT(fact1->get_num_args() == 2); | ||||
|     SASSERT(fact2->get_num_args() == 2); | ||||
|     CTRACE("mk_transitivity", fact1->get_decl() != fact2->get_decl(), | ||||
|            tout << mk_pp(fact1, *this) << "\n\n" << mk_pp(fact2, *this) << "\n"; | ||||
|            tout << mk_pp(fact1->get_decl(), *this) << "\n"; | ||||
|            tout << mk_pp(fact2->get_decl(), *this) << "\n";); | ||||
|     SASSERT(fact1->get_decl() == fact2->get_decl() || | ||||
|             ( (is_eq(fact1) || is_oeq(fact1)) && | ||||
|               (is_eq(fact2) || is_oeq(fact2)))); | ||||
|     CTRACE("mk_transitivity", fact1->get_arg(1) != fact2->get_arg(0), | ||||
|            tout << mk_pp(fact1, *this) << "\n\n" << mk_pp(fact2, *this) << "\n"; | ||||
|            tout << p1->get_id() << ": " << mk_bounded_pp(p1, *this, 5) << "\n\n"; | ||||
|            tout << p2->get_id() << ": " << mk_bounded_pp(p2, *this, 5) << "\n\n"; | ||||
|     ); | ||||
|     SASSERT(to_app(get_fact(p1))->get_arg(1) == to_app(get_fact(p2))->get_arg(0)); | ||||
|     if (is_reflexivity(p1)) | ||||
|         return p2; | ||||
|     if (is_reflexivity(p2)) | ||||
|         return p1; | ||||
|     // local fixup to admit inline simplifications of not(not(e)) to e
 | ||||
|     expr* e; | ||||
|     if (is_not(fact1->get_arg(1), e) && is_not(e, e) && e == fact2->get_arg(0)) | ||||
|         p1 = mk_transitivity(p1, mk_rewrite(fact1->get_arg(1), fact2->get_arg(0))); | ||||
|     else if (is_not(fact2->get_arg(0), e) && is_not(e, e) && e == fact1->get_arg(1)) | ||||
|         p1 = mk_transitivity(p1, mk_rewrite(fact1->get_arg(1), fact2->get_arg(0))); | ||||
|     else {                                             | ||||
|         SASSERT(fact1->get_arg(1) == fact2->get_arg(0)); | ||||
|     } | ||||
|     // OEQ is compatible with EQ for transitivity.
 | ||||
|     func_decl* f = to_app(get_fact(p1))->get_decl(); | ||||
|     if (is_oeq(get_fact(p2))) f = to_app(get_fact(p2))->get_decl(); | ||||
|     return  mk_app(basic_family_id, PR_TRANSITIVITY, p1, p2, mk_app(f, to_app(get_fact(p1))->get_arg(0), to_app(get_fact(p2))->get_arg(1))); | ||||
|     func_decl* f = fact1->get_decl(); | ||||
|     if (is_oeq(fact2)) | ||||
|         f = fact2->get_decl(); | ||||
|     return  mk_app(basic_family_id, PR_TRANSITIVITY, p1, p2, mk_app(f, fact1->get_arg(0), fact2->get_arg(1))); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -400,6 +400,7 @@ struct func_decl_info : public decl_info { | |||
|     bool m_idempotent:1; | ||||
|     bool m_skolem:1; | ||||
|     bool m_lambda:1; | ||||
|     bool m_polymorphic:1; | ||||
| 
 | ||||
|     func_decl_info(family_id family_id = null_family_id, decl_kind k = null_decl_kind, unsigned num_parameters = 0, parameter const * parameters = nullptr); | ||||
| 
 | ||||
|  | @ -414,6 +415,7 @@ struct func_decl_info : public decl_info { | |||
|     bool is_idempotent() const { return m_idempotent; } | ||||
|     bool is_skolem() const { return m_skolem; } | ||||
|     bool is_lambda() const { return m_lambda; } | ||||
|     bool is_polymorphic() const { return m_polymorphic; } | ||||
| 
 | ||||
|     void set_associative(bool flag = true) { m_left_assoc = flag; m_right_assoc = flag; } | ||||
|     void set_left_associative(bool flag = true) { m_left_assoc = flag; } | ||||
|  | @ -426,6 +428,7 @@ struct func_decl_info : public decl_info { | |||
|     void set_idempotent(bool flag = true) { m_idempotent = flag; } | ||||
|     void set_skolem(bool flag = true) { m_skolem = flag; } | ||||
|     void set_lambda(bool flag = true) { m_lambda = flag; } | ||||
|     void set_polymorphic(bool flag = true) { m_polymorphic = flag; } | ||||
| 
 | ||||
|     bool operator==(func_decl_info const & info) const; | ||||
| 
 | ||||
|  | @ -655,6 +658,7 @@ public: | |||
|     bool is_skolem() const { return get_info() != nullptr && get_info()->is_skolem(); } | ||||
|     bool is_lambda() const { return get_info() != nullptr && get_info()->is_lambda(); } | ||||
|     bool is_idempotent() const { return get_info() != nullptr && get_info()->is_idempotent(); } | ||||
|     bool is_polymorphic() const { return get_info() != nullptr && get_info()->is_polymorphic(); } | ||||
|     unsigned get_arity() const { return m_arity; } | ||||
|     sort * get_domain(unsigned idx) const { SASSERT(idx < get_arity()); return m_domain[idx]; } | ||||
|     sort * const * get_domain() const { return m_domain; } | ||||
|  | @ -966,11 +970,6 @@ inline quantifier const * to_quantifier(ast const * n) { SASSERT(is_quantifier(n | |||
| unsigned get_node_hash(ast const * n); | ||||
| bool compare_nodes(ast const * n1, ast const * n2); | ||||
| unsigned get_node_size(ast const * n); | ||||
| unsigned get_asts_hash(unsigned sz, ast * const* ns, unsigned init); | ||||
| unsigned get_apps_hash(unsigned sz, app * const* ns, unsigned init); | ||||
| unsigned get_exprs_hash(unsigned sz, expr * const* ns, unsigned init); | ||||
| unsigned get_sorts_hash(unsigned sz, sort * const* ns, unsigned init); | ||||
| unsigned get_decl_hash(unsigned sz, func_decl* const* ns, unsigned init); | ||||
| 
 | ||||
| // This is the internal comparison functor for hash-consing AST nodes.
 | ||||
| struct ast_eq_proc { | ||||
|  | @ -1511,13 +1510,15 @@ protected: | |||
|     unsigned                  m_fresh_id; | ||||
|     bool                      m_debug_ref_count; | ||||
|     u_map<unsigned>           m_debug_free_indices; | ||||
|     std::fstream*             m_trace_stream; | ||||
|     bool                      m_trace_stream_owner; | ||||
|     std::fstream*             m_trace_stream = nullptr; | ||||
|     bool                      m_trace_stream_owner = false; | ||||
|     bool                      m_has_type_vars = false; | ||||
| #ifdef Z3DEBUG | ||||
|     bool slow_not_contains(ast const * n); | ||||
| #endif | ||||
|     ast_manager *             m_format_manager; // hack for isolating format objects in a different manager.
 | ||||
|     symbol                    m_lambda_def; | ||||
|     symbol                    m_lambda_def = symbol(":lambda-def"); | ||||
|     obj_map<func_decl, func_decl*> m_poly_roots; | ||||
| 
 | ||||
|     void init(); | ||||
| 
 | ||||
|  | @ -1734,12 +1735,27 @@ public: | |||
| 
 | ||||
|     bool is_uninterp(sort const * s) const { return s->get_family_id() == null_family_id || s->get_family_id() == user_sort_family_id; } | ||||
| 
 | ||||
|     bool is_type_var(sort const* s) const { return s->get_family_id() == poly_family_id; } | ||||
| 
 | ||||
|     bool has_type_vars() const { return m_has_type_vars; } | ||||
| 
 | ||||
|     func_decl* poly_root(func_decl* f) const { SASSERT(f->is_polymorphic()); return m_poly_roots[f]; } | ||||
| 
 | ||||
| 
 | ||||
|     func_decl* instantiate_polymorphic(func_decl* f, unsigned arity, sort * const* domain, sort * range); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief A sort is "fully" interpreted if it is interpreted, | ||||
|        and doesn't depend on other uninterpreted sorts. | ||||
|     */ | ||||
|     bool is_fully_interp(sort * s) const; | ||||
| 
 | ||||
|     bool has_type_var(sort* s) const; | ||||
| 
 | ||||
|     bool has_type_var(func_decl* f) const; | ||||
| 
 | ||||
|     bool has_type_var(unsigned n, sort* const* domain, sort* range) const; | ||||
| 
 | ||||
|     func_decl * mk_func_decl(family_id fid, decl_kind k, unsigned num_parameters, parameter const * parameters, | ||||
|                              unsigned arity, sort * const * domain, sort * range = nullptr); | ||||
| 
 | ||||
|  |  | |||
|  | @ -65,6 +65,13 @@ void ast_translation::collect_decl_extra_children(decl * d) { | |||
| } | ||||
| 
 | ||||
| void ast_translation::push_frame(ast * n) { | ||||
|     // ensure poly roots are pushed first.
 | ||||
|     if (m_from_manager.has_type_vars() && n->get_kind() == AST_FUNC_DECL && to_func_decl(n)->is_polymorphic()) { | ||||
|         func_decl* g = m_from_manager.poly_root(to_func_decl(n)); | ||||
|         if (n != g && m_cache.contains(g)) { | ||||
|             m_frame_stack.push_back(frame(n, 0, m_extra_children_stack.size(), m_result_stack.size())); | ||||
|         } | ||||
|     } | ||||
|     m_frame_stack.push_back(frame(n, 0, m_extra_children_stack.size(), m_result_stack.size())); | ||||
|     switch (n->get_kind()) { | ||||
|     case AST_SORT: | ||||
|  | @ -153,6 +160,10 @@ void ast_translation::mk_func_decl(func_decl * f, frame & fr) { | |||
|                                           new_domain, | ||||
|                                           new_range); | ||||
|     } | ||||
|     else if (f->is_polymorphic() && m_from_manager.poly_root(f) != f) { | ||||
|         func_decl* fr = to_func_decl(m_cache[m_from_manager.poly_root(f)]); | ||||
|         new_f = m_to_manager.instantiate_polymorphic(fr, f->get_arity(), new_domain, new_range); | ||||
|     } | ||||
|     else { | ||||
|         buffer<parameter> ps; | ||||
|         copy_params(f, fr.m_rpos, ps); | ||||
|  |  | |||
|  | @ -24,7 +24,8 @@ Notes: | |||
|  * Add or overwrite value in model. | ||||
|  */ | ||||
| void model_converter::display_add(std::ostream& out, smt2_pp_environment& env, ast_manager& m, func_decl* f, expr* e) { | ||||
|     VERIFY(e); | ||||
|     if (!e) | ||||
|         return; | ||||
|     VERIFY(f->get_range() == e->get_sort()); | ||||
|     ast_smt2_pp_rev(out, f, e, env, params_ref(), 0, "model-add") << "\n"; | ||||
| } | ||||
|  |  | |||
|  | @ -39,8 +39,10 @@ namespace euf { | |||
|         } | ||||
|         m_expr2enode.setx(f->get_id(), n, nullptr); | ||||
|         push_node(n); | ||||
|         for (unsigned i = 0; i < num_args; ++i)  | ||||
|             set_cgc_enabled(args[i], true);                              | ||||
|         for (unsigned i = 0; i < num_args; ++i) { | ||||
|             set_cgc_enabled(args[i], true);       | ||||
|             args[i]->get_root()->set_is_shared(l_undef); | ||||
|         }                        | ||||
|         return n; | ||||
|     } | ||||
| 
 | ||||
|  | @ -70,7 +72,7 @@ namespace euf { | |||
|     } | ||||
| 
 | ||||
|     enode_bool_pair egraph::insert_table(enode* p) { | ||||
|         TRACE("euf", tout << bpp(p) << "\n"); | ||||
|         TRACE("euf", tout << "insert_table " << bpp(p) << "\n"); | ||||
|         //SASSERT(!m_table.contains_ptr(p));
 | ||||
|         auto rc = m_table.insert(p); | ||||
|         p->m_cg = rc.first; | ||||
|  | @ -82,9 +84,14 @@ namespace euf { | |||
|     } | ||||
| 
 | ||||
|     void egraph::reinsert_equality(enode* p) { | ||||
|         SASSERT(p->is_equality()); | ||||
|         SASSERT(p->is_equality());         | ||||
|         if (p->value() != l_true && p->get_arg(0)->get_root() == p->get_arg(1)->get_root())  | ||||
|             add_literal(p, nullptr); | ||||
|             queue_literal(p, nullptr); | ||||
|     } | ||||
| 
 | ||||
|     void egraph::queue_literal(enode* p, enode* ante) {         | ||||
|         if (m_on_propagate_literal) | ||||
|             m_to_merge.push_back(to_merge(p, ante)); | ||||
|     } | ||||
| 
 | ||||
|     void egraph::force_push() { | ||||
|  | @ -128,9 +135,8 @@ namespace euf { | |||
|         if (n2 == n)  | ||||
|             update_children(n);         | ||||
|         else  | ||||
|             push_merge(n, n2, justification::congruence(comm, 0)); | ||||
|         // merge(n, n2, justification::congruence(comm, m_congruence_timestamp++));
 | ||||
|              | ||||
|             push_merge(n, n2, comm); | ||||
|      | ||||
|         return n; | ||||
|     } | ||||
| 
 | ||||
|  | @ -145,18 +151,9 @@ namespace euf { | |||
|             memory::deallocate(m_tmp_node); | ||||
|     } | ||||
| 
 | ||||
|     void egraph::add_plugins() { | ||||
|         if (!m_plugins.empty()) | ||||
|             return; | ||||
| 
 | ||||
|         auto insert = [&](plugin* p) { | ||||
|             m_plugins.reserve(p->get_id() + 1); | ||||
|             m_plugins.set(p->get_id(), p); | ||||
|         }; | ||||
| 
 | ||||
|         insert(alloc(bv_plugin, *this)); | ||||
|         insert(alloc(arith_plugin, *this)); | ||||
|         insert(alloc(specrel_plugin, *this)); | ||||
|     void egraph::add_plugin(plugin* p) { | ||||
|         m_plugins.reserve(p->get_id() + 1); | ||||
|         m_plugins.set(p->get_id(), p);        | ||||
|     } | ||||
| 
 | ||||
|     void egraph::propagate_plugins() { | ||||
|  | @ -188,25 +185,21 @@ namespace euf { | |||
|     } | ||||
| 
 | ||||
|     void egraph::add_literal(enode* n, enode* ante) { | ||||
|         TRACE("euf", tout << "propagate " << bpp(n) << " " << bpp(ante) << "\n"); | ||||
|         if (!m_on_propagate_literal) | ||||
|             return; | ||||
|         if (!ante) ++m_stats.m_num_eqs; else ++m_stats.m_num_lits; | ||||
|         if (!ante) | ||||
|             m_on_propagate_literal(n, ante); | ||||
|         else if (m.is_true(ante->get_expr()) || m.is_false(ante->get_expr())) { | ||||
|             for (enode* k : enode_class(n)) { | ||||
|                 if (k != ante) { | ||||
|                     //verbose_stream() << "eq: " << k->value() << " " <<ante->value() << "\n";
 | ||||
|                     m_on_propagate_literal(k, ante); | ||||
|                 } | ||||
|             } | ||||
|             for (enode* k : enode_class(n))  | ||||
|                 if (k != ante)  | ||||
|                     m_on_propagate_literal(k, ante);            | ||||
|         } | ||||
|         else { | ||||
|             for (enode* k : enode_class(n)) { | ||||
|                 if (k->value() != ante->value()) { | ||||
|                     //verbose_stream() << "eq: " << k->value() << " " <<ante->value() << "\n";
 | ||||
|                     m_on_propagate_literal(k, ante); | ||||
|                 } | ||||
|                 if (k->value() != ante->value())  | ||||
|                     m_on_propagate_literal(k, ante);                 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | @ -516,6 +509,7 @@ namespace euf { | |||
|             c->m_root = r2; | ||||
|         std::swap(r1->m_next, r2->m_next); | ||||
|         r2->inc_class_size(r1->class_size());    | ||||
|         r2->set_is_shared(l_undef); | ||||
|         merge_th_eq(r1, r2, j); | ||||
|         reinsert_parents(r1, r2); | ||||
|         if (j.is_congruence() && (m.is_false(r2->get_expr()) || m.is_true(r2->get_expr()))) | ||||
|  | @ -532,6 +526,7 @@ namespace euf { | |||
| 
 | ||||
|     void egraph::remove_parents(enode* r) { | ||||
|         TRACE("euf", tout << bpp(r) << "\n"); | ||||
|         SASSERT(all_of(enode_parents(r), [&](enode* p) { return !p->is_marked1(); })); | ||||
|         for (enode* p : enode_parents(r)) { | ||||
|             if (p->is_marked1()) | ||||
|                 continue; | ||||
|  | @ -558,7 +553,7 @@ namespace euf { | |||
|             if (p->cgc_enabled()) { | ||||
|                 auto [p_other, comm] = insert_table(p); | ||||
|                 SASSERT(m_table.contains_ptr(p) == (p_other == p)); | ||||
|                 TRACE("euf", tout << "other " << bpp(p_other) << "\n";); | ||||
|                 CTRACE("euf", p_other != p, tout << "reinsert " << bpp(p) << " == " << bpp(p_other) << " " << p->value() << " " << p_other->value() << "\n"); | ||||
|                 if (p_other != p)  | ||||
|                     m_to_merge.push_back(to_merge(p_other, p, comm));                 | ||||
|                 else | ||||
|  | @ -594,6 +589,7 @@ namespace euf { | |||
|         enode* r2 = r1->get_root(); | ||||
|         TRACE("euf", tout << "undo-eq old-root: " << bpp(r1) << " current-root " << bpp(r2) << " node: " << bpp(n1) << "\n";); | ||||
|         r2->dec_class_size(r1->class_size()); | ||||
|         r2->set_is_shared(l_undef); | ||||
|         std::swap(r1->m_next, r2->m_next); | ||||
|         auto begin = r2->begin_parents() + r2_num_parents, end = r2->end_parents(); | ||||
|         for (auto it = begin; it != end; ++it) { | ||||
|  | @ -615,18 +611,29 @@ namespace euf { | |||
|         unmerge_justification(n1); | ||||
|     } | ||||
| 
 | ||||
|     bool egraph::propagate() {         | ||||
| 
 | ||||
|     bool egraph::propagate() { | ||||
|         force_push(); | ||||
|         propagate_plugins(); | ||||
|         for (unsigned i = 0; i < m_to_merge.size() && m.limit().inc() && !inconsistent(); ++i) { | ||||
|             auto const& w = m_to_merge[i]; | ||||
|             if (w.j.is_congruence()) | ||||
|                 merge(w.a, w.b, justification::congruence(w.j.is_commutative(), m_congruence_timestamp++)); | ||||
|             else | ||||
|                 merge(w.a, w.b, w.j); | ||||
|              | ||||
|             if (i + 1 == m_to_merge.size()) | ||||
|                 propagate_plugins(); | ||||
|         unsigned i = 0; | ||||
|         bool change = true; | ||||
|         while (change) { | ||||
|             change = false; | ||||
|             propagate_plugins(); | ||||
|             for (; i < m_to_merge.size() && m.limit().inc() && !inconsistent(); ++i) { | ||||
|                 auto const& w = m_to_merge[i]; | ||||
|                 switch (w.t) { | ||||
|                 case to_merge_plain: | ||||
|                 case to_merge_comm: | ||||
|                     merge(w.a, w.b, justification::congruence(w.commutativity(), m_congruence_timestamp++)); | ||||
|                     break; | ||||
|                 case to_justified: | ||||
|                     merge(w.a, w.b, w.j); | ||||
|                     break; | ||||
|                 case to_add_literal: | ||||
|                     add_literal(w.a, w.b); | ||||
|                     break; | ||||
|                 }                 | ||||
|             } | ||||
|         } | ||||
|         m_to_merge.reset(); | ||||
|         return  | ||||
|  | @ -642,7 +649,7 @@ namespace euf { | |||
|         m_updates.push_back(update_record(false, update_record::inconsistent())); | ||||
|         m_n1 = n1; | ||||
|         m_n2 = n2; | ||||
|         TRACE("euf", tout << "conflict " << bpp(n1) << " " << bpp(n2) << " " << j << "\n"); | ||||
|         TRACE("euf", tout << "conflict " << bpp(n1) << " " << bpp(n2) << " " << j << " " << n1->get_root()->value() << " " << n2->get_root()->value() << "\n"); | ||||
|         m_justification = j; | ||||
|     } | ||||
| 
 | ||||
|  | @ -920,7 +927,7 @@ namespace euf { | |||
|         for (enode* n : m_nodes) | ||||
|             max_args = std::max(max_args, n->num_args()); | ||||
|         for (enode* n : m_nodes)  | ||||
|             display(out, max_args, n);    | ||||
|             display(out, max_args, n);           | ||||
|         for (auto* p : m_plugins) | ||||
|             if (p) | ||||
|                 p->display(out); | ||||
|  |  | |||
|  | @ -88,11 +88,15 @@ namespace euf { | |||
| 
 | ||||
|         typedef ptr_vector<trail> trail_stack; | ||||
| 
 | ||||
|         enum to_merge_t { to_merge_plain, to_merge_comm, to_justified, to_add_literal }; | ||||
|         struct to_merge { | ||||
|             enode* a, * b; | ||||
|             to_merge_t t; | ||||
|             justification j; | ||||
|             to_merge(enode* a, enode* b, bool c) : a(a), b(b), j(justification::congruence(c, 0)) {} | ||||
|             to_merge(enode* a, enode* b, justification j) : a(a), b(b), j(j) {} | ||||
|             bool commutativity() const { return t == to_merge_comm; } | ||||
|             to_merge(enode* a, enode* b, bool c) : a(a), b(b), t(c ? to_merge_comm : to_merge_plain) {} | ||||
|             to_merge(enode* a, enode* b, justification j): a(a), b(b), t(to_justified), j(j) {} | ||||
|             to_merge(enode* p, enode* ante): a(p), b(ante), t(to_add_literal) {} | ||||
|         }; | ||||
| 
 | ||||
|         struct stats { | ||||
|  | @ -215,6 +219,7 @@ namespace euf { | |||
|         // plugin related methods
 | ||||
|         void push_plugin_undo(unsigned th_id) { m_updates.push_back(update_record(th_id, update_record::plugin_undo())); } | ||||
|         void push_merge(enode* a, enode* b, justification j) { m_to_merge.push_back({ a, b, j }); } | ||||
|         void push_merge(enode* a, enode* b, bool comm) { m_to_merge.push_back({ a, b, comm }); } | ||||
|         void propagate_plugins(); | ||||
| 
 | ||||
|         void add_th_eq(theory_id id, theory_var v1, theory_var v2, enode* c, enode* r); | ||||
|  | @ -222,6 +227,7 @@ namespace euf { | |||
|         void add_th_diseqs(theory_id id, theory_var v1, enode* r); | ||||
|         bool th_propagates_diseqs(theory_id id) const; | ||||
|         void add_literal(enode* n, enode* ante); | ||||
|         void queue_literal(enode* n, enode* ante); | ||||
|         void undo_eq(enode* r1, enode* n1, unsigned r2_num_parents); | ||||
|         void undo_add_th_var(enode* n, theory_id id); | ||||
|         enode* mk_enode(expr* f, unsigned generation, unsigned num_args, enode * const* args); | ||||
|  | @ -256,8 +262,10 @@ namespace euf { | |||
|     public: | ||||
|         egraph(ast_manager& m); | ||||
|         ~egraph(); | ||||
|         void add_plugins(); | ||||
| 
 | ||||
|         void add_plugin(plugin* p); | ||||
|         plugin* get_plugin(family_id fid) const { return m_plugins.get(fid, nullptr); } | ||||
| 
 | ||||
|         enode* find(expr* f) const { return m_expr2enode.get(f->get_id(), nullptr); } | ||||
|         enode* find(expr* f, unsigned n, enode* const* args); | ||||
|         enode* mk(expr* f, unsigned generation, unsigned n, enode *const* args); | ||||
|  | @ -284,6 +292,7 @@ namespace euf { | |||
|            of new equalities. | ||||
|         */ | ||||
|         bool propagate(); | ||||
|         bool can_propagate() const { return !m_to_merge.empty(); } | ||||
|         bool inconsistent() const { return m_inconsistent; } | ||||
| 
 | ||||
|         /**
 | ||||
|  |  | |||
|  | @ -52,6 +52,7 @@ namespace euf { | |||
|         bool          m_merge_tf_enabled = false; | ||||
|         bool          m_is_equality = false;    // Does the expression represent an equality
 | ||||
|         bool          m_is_relevant = false; | ||||
|         lbool         m_is_shared = l_undef; | ||||
|         lbool         m_value = l_undef;        // Assignment by SAT solver for Boolean node
 | ||||
|         sat::bool_var m_bool_var = sat::null_bool_var;    // SAT solver variable associated with Boolean node
 | ||||
|         unsigned      m_class_size = 1;         // Size of the equivalence class if the enode is the root.
 | ||||
|  | @ -96,6 +97,7 @@ namespace euf { | |||
|             for (unsigned i = 0; i < num_args; ++i) { | ||||
|                 SASSERT(to_app(f)->get_arg(i) == args[i]->get_expr()); | ||||
|                 n->m_args[i] = args[i]; | ||||
|                 n->m_args[i]->get_root()->set_is_shared(l_undef); | ||||
|             } | ||||
|             return n; | ||||
|         } | ||||
|  | @ -181,6 +183,9 @@ namespace euf { | |||
|         void unmark3() { m_mark3 = false; } | ||||
|         bool is_marked3() { return m_mark3; } | ||||
| 
 | ||||
|         lbool is_shared() const { return m_is_shared; } | ||||
|         void set_is_shared(lbool s) { m_is_shared = s; } | ||||
| 
 | ||||
|         template<bool m> void mark1_targets() { | ||||
|             enode* n = this; | ||||
|             while (n) { | ||||
|  |  | |||
|  | @ -237,6 +237,8 @@ namespace euf { | |||
|             UNTAG(table*, t)->erase(n); | ||||
|             break; | ||||
|         } | ||||
|         CTRACE("euf", contains_ptr(n), display(tout)); | ||||
|         SASSERT(!contains_ptr(n)); | ||||
|     } | ||||
| 
 | ||||
|     bool etable::contains(enode* n) const { | ||||
|  |  | |||
|  | @ -109,9 +109,9 @@ bool has_skolem_functions(expr * n) { | |||
| 
 | ||||
| subterms::subterms(expr_ref_vector const& es, bool include_bound, ptr_vector<expr>* esp, expr_mark* vp): m_include_bound(include_bound), m_es(es), m_esp(esp), m_vp(vp) {} | ||||
| subterms::subterms(expr_ref const& e, bool include_bound, ptr_vector<expr>* esp, expr_mark* vp) : m_include_bound(include_bound), m_es(e.m()), m_esp(esp), m_vp(vp) { if (e) m_es.push_back(e); } | ||||
| subterms::iterator subterms::begin() { return iterator(* this, m_esp, m_vp, true); } | ||||
| subterms::iterator subterms::end() { return iterator(*this, nullptr, nullptr, false); } | ||||
| subterms::iterator::iterator(subterms& f, ptr_vector<expr>* esp, expr_mark* vp, bool start): m_include_bound(f.m_include_bound), m_esp(esp), m_visitedp(vp) { | ||||
| subterms::iterator subterms::begin() const { return iterator(* this, m_esp, m_vp, true); } | ||||
| subterms::iterator subterms::end() const { return iterator(*this, nullptr, nullptr, false); } | ||||
| subterms::iterator::iterator(subterms const& f, ptr_vector<expr>* esp, expr_mark* vp, bool start): m_include_bound(f.m_include_bound), m_esp(esp), m_visitedp(vp) { | ||||
|     if (!esp) | ||||
|         m_esp = &m_es; | ||||
|     else | ||||
|  |  | |||
|  | @ -186,7 +186,7 @@ public: | |||
|         expr_mark         m_visited;    | ||||
|         expr_mark*        m_visitedp = nullptr; | ||||
|     public: | ||||
|         iterator(subterms& f, ptr_vector<expr>* esp, expr_mark* vp, bool start); | ||||
|         iterator(subterms const& f, ptr_vector<expr>* esp, expr_mark* vp, bool start); | ||||
|         expr* operator*(); | ||||
|         iterator operator++(int); | ||||
|         iterator& operator++(); | ||||
|  | @ -198,8 +198,8 @@ public: | |||
|     static subterms ground(expr_ref const& e, ptr_vector<expr>* esp = nullptr, expr_mark* vp = nullptr) { return subterms(e, false, esp, vp); } | ||||
|     static subterms all(expr_ref_vector const& e, ptr_vector<expr>* esp = nullptr, expr_mark* vp = nullptr) { return subterms(e, true, esp, vp); } | ||||
|     static subterms ground(expr_ref_vector const& e, ptr_vector<expr>* esp = nullptr, expr_mark* vp = nullptr) { return subterms(e, false, esp, vp); } | ||||
|     iterator begin(); | ||||
|     iterator end(); | ||||
|     iterator begin() const; | ||||
|     iterator end() const; | ||||
| }; | ||||
| 
 | ||||
| class subterms_postorder { | ||||
|  |  | |||
|  | @ -324,7 +324,7 @@ func_interp * bv2fpa_converter::convert_func_interp(model_core * mc, func_decl * | |||
|             expr_ref else_value(m.mk_app(to_bv_i, dom.size(), dom.data()), m); | ||||
|             result->set_else(else_value); | ||||
|         } | ||||
|         else if (m_fpa_util.is_to_real(f)) {            | ||||
|         else if (m_fpa_util.is_to_real(f)) { | ||||
|             SASSERT(dom.size() == 1); | ||||
|             func_decl_ref to_real_i(m.mk_func_decl(fid, OP_FPA_TO_REAL_I, 0, nullptr, dom.size(), dom.data()), m); | ||||
|             expr_ref else_value(m.mk_app(to_real_i, dom.size(), dom.data()), m); | ||||
|  | @ -508,7 +508,7 @@ void bv2fpa_converter::convert_uf2bvuf(model_core * mc, model_core * target_mode | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     TRACE("bv2fpa", tout << "Target model: " << *target_model; ); | ||||
|     TRACE("bv2fpa", tout << "Target model: " << *target_model << std::endl; ); | ||||
| } | ||||
| 
 | ||||
| void bv2fpa_converter::display(std::ostream & out) { | ||||
|  |  | |||
|  | @ -147,36 +147,11 @@ void fpa2bv_converter::mk_distinct(func_decl * f, unsigned num, expr * const * a | |||
| 
 | ||||
| void fpa2bv_converter::mk_numeral(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { | ||||
|     SASSERT(num == 0); | ||||
|     sort* s = f->get_range(); | ||||
|     if (f->get_num_parameters() == 1) { | ||||
|         SASSERT(f->get_parameter(0).is_external()); | ||||
|         unsigned p_id = f->get_parameter(0).get_ext_id(); | ||||
|         mpf const& v = m_plugin->get_value(p_id); | ||||
|         mk_numeral(s, v, result); | ||||
|         return; | ||||
|     } | ||||
|     scoped_mpf v(m_mpf_manager);    | ||||
|     unsigned ebits = m_util.get_ebits(s), sbits = m_util.get_sbits(s); | ||||
|     switch (f->get_decl_kind()) { | ||||
|     case OP_FPA_PLUS_INF: | ||||
|         m_util.fm().mk_pinf(ebits, sbits, v); | ||||
|         break; | ||||
|     case OP_FPA_MINUS_INF: | ||||
|         m_util.fm().mk_ninf(ebits, sbits, v); | ||||
|         break; | ||||
|     case OP_FPA_NAN:         | ||||
|         m_util.fm().mk_nan(ebits, sbits, v); | ||||
|         break; | ||||
|     case OP_FPA_PLUS_ZERO: | ||||
|         m_util.fm().mk_pzero(ebits, sbits, v); | ||||
|         break; | ||||
|     case OP_FPA_MINUS_ZERO: | ||||
|         m_util.fm().mk_nzero(ebits, sbits, v); | ||||
|         break; | ||||
|     default: | ||||
|         UNREACHABLE(); | ||||
|     } | ||||
|     mk_numeral(s, v, result); | ||||
|     scoped_mpf v(m_mpf_manager); | ||||
|     expr_ref a(m); | ||||
|     a = m.mk_app(f, num, args); | ||||
|     m_util.is_numeral(a, v); | ||||
|     mk_numeral(f->get_range(), v, result); | ||||
| } | ||||
| 
 | ||||
| void fpa2bv_converter::mk_numeral(sort * s, mpf const & v, expr_ref & result) { | ||||
|  | @ -941,8 +916,8 @@ void fpa2bv_converter::mk_div(sort * s, expr_ref & rm, expr_ref & x, expr_ref & | |||
|     dbg_decouple("fpa2bv_div_y_is_pos", y_is_pos); | ||||
|     dbg_decouple("fpa2bv_div_y_is_inf", y_is_inf); | ||||
| 
 | ||||
|     expr_ref c1(m), c2(m), c3(m), c4(m), c5(m), c6(m), c7(m); | ||||
|     expr_ref v1(m), v2(m), v3(m), v4(m), v5(m), v6(m), v7(m), v8(m); | ||||
|     expr_ref c1(m), c2(m), c3(m), c4(m), c5(m), c6(m), c7(m), c8(m); | ||||
|     expr_ref v1(m), v2(m), v3(m), v4(m), v5(m), v6(m), v7(m), v8(m), v9(m); | ||||
| 
 | ||||
|     // (x is NaN) || (y is NaN) -> NaN
 | ||||
|     m_simp.mk_or(x_is_nan, y_is_nan, c1); | ||||
|  | @ -998,6 +973,9 @@ void fpa2bv_converter::mk_div(sort * s, expr_ref & rm, expr_ref & x, expr_ref & | |||
|     a_sig_ext = m_bv_util.mk_concat(a_sig, m_bv_util.mk_numeral(0, sbits + extra_bits)); | ||||
|     b_sig_ext = m_bv_util.mk_zero_extend(sbits + extra_bits, b_sig); | ||||
| 
 | ||||
|     dbg_decouple("fpa2bv_div_a_sig_ext", a_sig_ext); | ||||
|     dbg_decouple("fpa2bv_div_b_sig_ext", b_sig_ext); | ||||
| 
 | ||||
|     expr_ref a_exp_ext(m), b_exp_ext(m); | ||||
|     a_exp_ext = m_bv_util.mk_sign_extend(2, a_exp); | ||||
|     b_exp_ext = m_bv_util.mk_sign_extend(2, b_exp); | ||||
|  | @ -1017,14 +995,21 @@ void fpa2bv_converter::mk_div(sort * s, expr_ref & rm, expr_ref & x, expr_ref & | |||
|     expr_ref quotient(m); | ||||
|     // b_sig_ext can't be 0 here, so it's safe to use OP_BUDIV_I
 | ||||
|     quotient = m.mk_app(m_bv_util.get_fid(), OP_BUDIV_I, a_sig_ext, b_sig_ext); | ||||
| 
 | ||||
|     dbg_decouple("fpa2bv_div_quotient", quotient); | ||||
| 
 | ||||
|     SASSERT(m_bv_util.get_bv_size(quotient) == (sbits + sbits + extra_bits)); | ||||
| 
 | ||||
|     expr_ref sticky(m); | ||||
|     expr_ref sticky(m), upper(m), upper_reduced(m), too_large(m); | ||||
|     sticky = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, m_bv_util.mk_extract(extra_bits-2, 0, quotient)); | ||||
|     res_sig = m_bv_util.mk_concat(m_bv_util.mk_extract(extra_bits+sbits+1, extra_bits-1, quotient), sticky); | ||||
|     upper = m_bv_util.mk_extract(sbits + sbits + extra_bits-1, extra_bits+sbits+2, quotient); | ||||
|     upper_reduced = m.mk_app(m_bv_util.get_fid(), OP_BREDOR, upper.get()); | ||||
|     too_large = m.mk_eq(upper_reduced, m_bv_util.mk_numeral(1, 1)); | ||||
|     c8 = too_large; | ||||
|     mk_ite(signs_xor, ninf, pinf, v8); | ||||
|     dbg_decouple("fpa2bv_div_res_sig_p4", res_sig); | ||||
|     dbg_decouple("fpa2bv_div_upper", upper); | ||||
|     dbg_decouple("fpa2bv_div_too_large", too_large); | ||||
| 
 | ||||
|     SASSERT(m_bv_util.get_bv_size(res_sig) == (sbits + 4)); | ||||
| 
 | ||||
|  | @ -1042,10 +1027,14 @@ void fpa2bv_converter::mk_div(sort * s, expr_ref & rm, expr_ref & x, expr_ref & | |||
|     m_simp.mk_ite(shift_cond, res_sig, res_sig_shifted, res_sig); | ||||
|     m_simp.mk_ite(shift_cond, res_exp, res_exp_shifted, res_exp); | ||||
| 
 | ||||
|     round(s, rm, res_sgn, res_sig, res_exp, v8); | ||||
|     dbg_decouple("fpa2bv_div_res_sig", res_sig); | ||||
|     dbg_decouple("fpa2bv_div_res_exp", res_exp); | ||||
| 
 | ||||
|     round(s, rm, res_sgn, res_sig, res_exp, v9); | ||||
| 
 | ||||
|     // And finally, we tie them together.
 | ||||
|     mk_ite(c7, v7, v8, result); | ||||
|     mk_ite(c8, v8, v9, result); | ||||
|     mk_ite(c7, v7, result, result); | ||||
|     mk_ite(c6, v6, result, result); | ||||
|     mk_ite(c5, v5, result, result); | ||||
|     mk_ite(c4, v4, result, result); | ||||
|  | @ -2809,8 +2798,46 @@ void fpa2bv_converter::mk_to_fp_real(func_decl * f, sort * s, expr * rm, expr * | |||
| 
 | ||||
|         expr * e = m.mk_eq(m_util.mk_to_real(result), x); | ||||
|         m_extra_assertions.push_back(e); | ||||
|         // x = 0 -> result = 0+
 | ||||
|         m_extra_assertions.push_back(m.mk_implies(m.mk_eq(x, zero), m.mk_eq(result, m_util.mk_pzero(result->get_sort())))); | ||||
| 
 | ||||
|         expr_ref r_is_nan(m); | ||||
|         mk_is_nan(result, r_is_nan); | ||||
|         m_extra_assertions.push_back(m.mk_not(r_is_nan)); | ||||
| 
 | ||||
|         rational min_real, max_real; | ||||
|         const mpz& max_exp_z = m_mpf_manager.m_powers2.m1(ebits-1); | ||||
|         SASSERT(m_mpz_manager.is_uint(max_exp_z)); | ||||
|         unsigned max_exp = m_mpz_manager.get_uint(max_exp_z); | ||||
|         rational max_sig = m_mpf_manager.m_powers2.m1(sbits) / m_mpf_manager.m_powers2(sbits-1); | ||||
|         max_real = max_sig * rational(m_mpf_manager.m_powers2(max_exp)); | ||||
|         TRACE("fpa2bv_to_real", tout << "max exp: " << max_exp << " max real: " << max_real << std::endl;); | ||||
| 
 | ||||
|         expr_ref r_is_pinf(m), r_is_ninf(m); | ||||
|         mk_is_pinf(result, r_is_pinf); | ||||
|         mk_is_ninf(result, r_is_ninf); | ||||
| 
 | ||||
|         expr_ref e_max_real(m), e_max_real_neg(m); | ||||
|         e_max_real = m_arith_util.mk_numeral(max_real, false); | ||||
|         e_max_real_neg = m_arith_util.mk_numeral(-max_real, false); | ||||
| 
 | ||||
|         expr_ref rm_nta(m), rm_nte(m), rm_tp(m), rm_tn(m), rm_tz(m); | ||||
|         mk_is_rm(bv_rm, BV_RM_TIES_TO_AWAY, rm_nta); | ||||
|         mk_is_rm(bv_rm, BV_RM_TIES_TO_EVEN, rm_nte); | ||||
|         mk_is_rm(bv_rm, BV_RM_TO_POSITIVE, rm_tp); | ||||
|         mk_is_rm(bv_rm, BV_RM_TO_NEGATIVE, rm_tn); | ||||
|         mk_is_rm(bv_rm, BV_RM_TO_ZERO, rm_tz); | ||||
| 
 | ||||
|         expr_ref implies_gt_max_real(m), implies_lt_min_real(m); | ||||
|         implies_gt_max_real = m.mk_implies(r_is_pinf, m.mk_and(rm_tp, m_arith_util.mk_gt(x, e_max_real))); | ||||
|         implies_lt_min_real = m.mk_implies(r_is_ninf, m.mk_and(rm_tn, m_arith_util.mk_lt(x, e_max_real_neg))); | ||||
| 
 | ||||
|         m_extra_assertions.push_back(implies_gt_max_real); | ||||
|         m_extra_assertions.push_back(implies_lt_min_real); | ||||
| 
 | ||||
|         // x = 0 -> result = +0/-0
 | ||||
|         expr_ref pzero(m), nzero(m); | ||||
|         mk_pzero(result->get_sort(), pzero); | ||||
|         mk_nzero(result->get_sort(), nzero); | ||||
|         m_extra_assertions.push_back(m.mk_implies(m.mk_eq(x, zero), m.mk_or(m.mk_eq(result, pzero), m.mk_eq(result, nzero)))); | ||||
|     } | ||||
| 
 | ||||
|     SASSERT(is_well_sorted(m, result)); | ||||
|  | @ -2854,19 +2881,13 @@ void fpa2bv_converter::mk_to_fp_real_int(func_decl * f, unsigned num, expr * con | |||
|         m_mpf_manager.set(tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, e.to_mpq().numerator(), q.to_mpq()); | ||||
|         m_mpf_manager.set(tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, e.to_mpq().numerator(), q.to_mpq()); | ||||
| 
 | ||||
|         app_ref a_nte(m), a_nta(m), a_tp(m), a_tn(m), a_tz(m); | ||||
|         a_nte = m_plugin->mk_numeral(nte); | ||||
|         a_nta = m_plugin->mk_numeral(nta); | ||||
|         a_tp = m_plugin->mk_numeral(tp); | ||||
|         a_tn = m_plugin->mk_numeral(tn); | ||||
|         a_tz = m_plugin->mk_numeral(tz); | ||||
| 
 | ||||
|         expr_ref bv_nte(m), bv_nta(m), bv_tp(m), bv_tn(m), bv_tz(m); | ||||
|         mk_numeral(a_nte->get_decl(), 0, nullptr, bv_nte); | ||||
|         mk_numeral(a_nta->get_decl(), 0, nullptr, bv_nta); | ||||
|         mk_numeral(a_tp->get_decl(), 0, nullptr, bv_tp); | ||||
|         mk_numeral(a_tn->get_decl(), 0, nullptr, bv_tn); | ||||
|         mk_numeral(a_tz->get_decl(), 0, nullptr, bv_tz); | ||||
|         sort *s = f->get_range(); | ||||
|         mk_numeral(s, nte, bv_nte); | ||||
|         mk_numeral(s, nta, bv_nta); | ||||
|         mk_numeral(s, tp, bv_tp); | ||||
|         mk_numeral(s, tn, bv_tn); | ||||
|         mk_numeral(s, tz, bv_tz); | ||||
| 
 | ||||
|         expr_ref c1(m), c2(m), c3(m), c4(m); | ||||
|         c1 = m.mk_eq(bv_rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)); | ||||
|  | @ -3003,27 +3024,34 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const | |||
|     unsigned bv_sz = m_bv_util.get_bv_size(x); | ||||
|     SASSERT(m_bv_util.get_bv_size(rm) == 3); | ||||
| 
 | ||||
|     expr_ref rm_is_to_neg(m); | ||||
|     mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg); | ||||
| 
 | ||||
|     expr_ref bv1_1(m), bv0_sz(m); | ||||
|     bv1_1 = m_bv_util.mk_numeral(1, 1); | ||||
|     bv0_sz = m_bv_util.mk_numeral(0, bv_sz); | ||||
| 
 | ||||
|     expr_ref is_zero(m), pzero(m); | ||||
|     expr_ref is_zero(m), pzero(m), nzero(m); | ||||
|     is_zero = m.mk_eq(x, bv0_sz); | ||||
|     mk_pzero(f, pzero); | ||||
|     mk_nzero(f, nzero); | ||||
| 
 | ||||
|     // Special case: x == 0 -> p/n zero
 | ||||
|     // Special case: x == 0 -> +zero
 | ||||
|     expr_ref c1(m), v1(m); | ||||
|     c1 = is_zero; | ||||
|     v1 = pzero; | ||||
|     v1 = pzero; // No -zero (IEEE754)
 | ||||
| 
 | ||||
|     // Special case: x != 0
 | ||||
|     expr_ref is_neg_bit(m), exp_too_large(m), sig_4(m), exp_2(m); | ||||
|     expr_ref sign_bit(m), exp_too_large(m), sig_4(m), exp_2(m), rest(m); | ||||
|     expr_ref is_neg(m), x_abs(m), neg_x(m); | ||||
|     is_neg_bit = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, x); | ||||
|     is_neg = m.mk_eq(is_neg_bit, bv1_1); | ||||
|     neg_x = m_bv_util.mk_bv_neg(x); // overflow problem?
 | ||||
|     sign_bit = m_bv_util.mk_extract(bv_sz - 1, bv_sz - 1, x); | ||||
|     rest = m_bv_util.mk_extract(bv_sz - 2, 0, x); | ||||
|     dbg_decouple("fpa2bv_to_fp_signed_rest", rest); | ||||
|     is_neg = m.mk_eq(sign_bit, bv1_1); | ||||
|     neg_x = m_bv_util.mk_bv_neg(x); // overflow ok, x_abs is now unsigned.
 | ||||
|     x_abs = m.mk_ite(is_neg, neg_x, x); | ||||
|     dbg_decouple("fpa2bv_to_fp_signed_is_neg", is_neg); | ||||
|     dbg_decouple("fpa2bv_to_fp_signed_x_abs", x_abs); | ||||
|     // x_abs has an extra bit in the front.
 | ||||
|     // x_abs is [bv_sz-1, bv_sz-2] . [bv_sz-3 ... 0] * 2^(bv_sz-2)
 | ||||
|     // bv_sz-2 is the "1.0" bit for the rounder.
 | ||||
|  | @ -3075,7 +3103,7 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const | |||
| 
 | ||||
|     TRACE("fpa2bv_to_fp_signed", tout << "exp worst case sz: " << exp_worst_case_sz << std::endl;); | ||||
| 
 | ||||
|     if (exp_sz < exp_worst_case_sz) { | ||||
|     if (exp_sz <= exp_worst_case_sz) { | ||||
|         // exp_sz < exp_worst_case_sz and exp >= 0.
 | ||||
|         // Take the maximum legal exponent; this
 | ||||
|         // allows us to keep the most precision.
 | ||||
|  | @ -3093,7 +3121,7 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const | |||
|     dbg_decouple("fpa2bv_to_fp_signed_exp_too_large", exp_too_large); | ||||
| 
 | ||||
|     expr_ref sgn(m), sig(m), exp(m); | ||||
|     sgn = is_neg_bit; | ||||
|     sgn = sign_bit; | ||||
|     sig = sig_4; | ||||
|     exp = exp_2; | ||||
| 
 | ||||
|  | @ -3132,6 +3160,9 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con | |||
|     rm = to_app(args[0])->get_arg(0); | ||||
|     x = args[1]; | ||||
| 
 | ||||
|     expr_ref rm_is_to_neg(m); | ||||
|     mk_is_rm(rm, BV_RM_TO_NEGATIVE, rm_is_to_neg); | ||||
| 
 | ||||
|     dbg_decouple("fpa2bv_to_fp_unsigned_x", x); | ||||
| 
 | ||||
|     unsigned ebits = m_util.get_ebits(f->get_range()); | ||||
|  | @ -3143,14 +3174,15 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con | |||
|     bv0_1 = m_bv_util.mk_numeral(0, 1); | ||||
|     bv0_sz = m_bv_util.mk_numeral(0, bv_sz); | ||||
| 
 | ||||
|     expr_ref is_zero(m), pzero(m); | ||||
|     expr_ref is_zero(m), pzero(m), nzero(m); | ||||
|     is_zero = m.mk_eq(x, bv0_sz); | ||||
|     mk_pzero(f, pzero); | ||||
|     mk_nzero(f, nzero); | ||||
| 
 | ||||
|     // Special case: x == 0 -> p/n zero
 | ||||
|     // Special case: x == 0 -> +zero
 | ||||
|     expr_ref c1(m), v1(m); | ||||
|     c1 = is_zero; | ||||
|     v1 = pzero; | ||||
|     v1 = pzero; // No -zero (IEEE754)
 | ||||
| 
 | ||||
|     // Special case: x != 0
 | ||||
|     expr_ref exp_too_large(m), sig_4(m), exp_2(m); | ||||
|  | @ -3194,7 +3226,7 @@ void fpa2bv_converter::mk_to_fp_unsigned(func_decl * f, unsigned num, expr * con | |||
|     unsigned exp_sz = ebits + 2; // (+2 for rounder)
 | ||||
|     exp_2 = m_bv_util.mk_extract(exp_sz - 1, 0, s_exp); | ||||
|     // the remaining bits are 0 if ebits is large enough.
 | ||||
|     exp_too_large = m.mk_false(); // This is always in range.
 | ||||
|     exp_too_large = m.mk_false(); | ||||
| 
 | ||||
|                                   // The exponent is at most bv_sz, i.e., we need ld(bv_sz)+1 ebits.
 | ||||
|                                   // exp < bv_sz (+sign bit which is [0])
 | ||||
|  |  | |||
|  | @ -208,6 +208,7 @@ protected: | |||
| 
 | ||||
| private: | ||||
|     void mk_nan(sort * s, expr_ref & result); | ||||
| 
 | ||||
|     void mk_nzero(sort * s, expr_ref & result); | ||||
|     void mk_pzero(sort * s, expr_ref & result); | ||||
|     void mk_zero(sort * s, expr_ref & sgn, expr_ref & result); | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ Revision History: | |||
| --*/ | ||||
| #include "ast/normal_forms/elim_term_ite.h" | ||||
| #include "ast/ast_smt2_pp.h" | ||||
| #include "ast/rewriter/rewriter_def.h" | ||||
| 
 | ||||
| br_status elim_term_ite_cfg::reduce_app(func_decl* f, unsigned n, expr * const* args, expr_ref& result, proof_ref& result_pr) { | ||||
|     if (!m.is_term_ite(f)) { | ||||
|  | @ -38,3 +39,4 @@ br_status elim_term_ite_cfg::reduce_app(func_decl* f, unsigned n, expr * const* | |||
|     return BR_DONE; | ||||
| } | ||||
| 
 | ||||
| template class rewriter_tpl<elim_term_ite_cfg>; | ||||
|  |  | |||
|  | @ -28,6 +28,7 @@ Notes: | |||
| #include "ast/rewriter/var_subst.h" | ||||
| #include "ast/normal_forms/name_exprs.h" | ||||
| #include "ast/ast_smt2_pp.h" | ||||
| #include "ast/ast_pp.h" | ||||
| #include <array> | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -149,7 +150,7 @@ class skolemizer { | |||
|         p = nullptr; | ||||
|         if (m_proofs_enabled) { | ||||
|             if (q->get_kind() == forall_k)  | ||||
|                 p = m.mk_skolemization(mk_not(m, q), m.mk_not(r)); | ||||
|                 p = m.mk_skolemization(mk_not(m, q), mk_not(m, r)); | ||||
|             else | ||||
|                 p = m.mk_skolemization(q, r); | ||||
|         } | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ Revision History: | |||
| #include "ast/occurs.h" | ||||
| 
 | ||||
| #include "ast/for_each_expr.h" | ||||
| #include "ast/for_each_ast.h" | ||||
| 
 | ||||
| // -----------------------------------
 | ||||
| //
 | ||||
|  | @ -49,6 +50,15 @@ namespace { | |||
|         void operator()(quantifier const * n) { } | ||||
|     }; | ||||
| 
 | ||||
| 
 | ||||
|     struct sort_proc { | ||||
|         sort* m_s; | ||||
|         sort_proc(sort* s) :m_s(s) {} | ||||
|         void operator()(sort const* s2) { if (m_s == s2) throw found(); } | ||||
|         void operator()(ast*) {} | ||||
|     }; | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| // Return true if n1 occurs in n2
 | ||||
|  | @ -74,6 +84,17 @@ bool occurs(func_decl * d, expr * n) { | |||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool occurs(sort* s1, sort* s2) { | ||||
|     sort_proc p(s1); | ||||
|     try { | ||||
|         for_each_ast(p, s2, true); | ||||
|     } | ||||
|     catch (const found&) { | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| void mark_occurs(ptr_vector<expr>& to_check, expr* v, expr_mark& occ) { | ||||
|     expr_fast_mark2 visited; | ||||
|     occ.mark(v, true); | ||||
|  | @ -116,4 +137,4 @@ void mark_occurs(ptr_vector<expr>& to_check, expr* v, expr_mark& occ) { | |||
|             to_check.pop_back(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -31,6 +31,11 @@ bool occurs(expr * n1, expr * n2); | |||
| */ | ||||
| bool occurs(func_decl * d, expr * n); | ||||
| 
 | ||||
| /**
 | ||||
| * \brief Return true if s1 occurs in s2 | ||||
| */ | ||||
| bool occurs(sort* s1, sort* s2); | ||||
| 
 | ||||
| /**
 | ||||
| * \brief Mark sub-expressions of to_check by whether v occurs in these. | ||||
| */ | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/database.h") | |||
| endif() | ||||
| 
 | ||||
| add_custom_command(OUTPUT "database.h" | ||||
|   COMMAND "${PYTHON_EXECUTABLE}" | ||||
|   COMMAND "${Python3_EXECUTABLE}" | ||||
|           "${PROJECT_SOURCE_DIR}/scripts/mk_pat_db.py" | ||||
|           "${CMAKE_CURRENT_SOURCE_DIR}/database.smt2" | ||||
|           "${CMAKE_CURRENT_BINARY_DIR}/database.h" | ||||
|  |  | |||
|  | @ -624,9 +624,11 @@ bool pattern_inference_cfg::reduce_quantifier( | |||
|     proof_ref & result_pr) { | ||||
| 
 | ||||
|     TRACE("pattern_inference", tout << "processing:\n" << mk_pp(q, m) << "\n";); | ||||
|     if (!is_forall(q)) { | ||||
|     if (!m_params.m_pi_enabled) | ||||
|         return false; | ||||
| 
 | ||||
|     if (!is_forall(q))  | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     int weight = q->get_weight(); | ||||
| 
 | ||||
|  | @ -653,9 +655,8 @@ bool pattern_inference_cfg::reduce_quantifier( | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (q->get_num_patterns() > 0) { | ||||
|     if (q->get_num_patterns() > 0)  | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     if (m_params.m_pi_nopat_weight >= 0) | ||||
|         weight = m_params.m_pi_nopat_weight; | ||||
|  |  | |||
							
								
								
									
										139
									
								
								src/ast/polymorphism_inst.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/ast/polymorphism_inst.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,139 @@ | |||
| /*++
 | ||||
| Copyright (c) 2023 Microsoft Corporation | ||||
| 
 | ||||
| Module Name: | ||||
| 
 | ||||
|     polymorphism_inst.cpp | ||||
| 
 | ||||
| Abstract: | ||||
| 
 | ||||
|     Utilities for instantiating polymorphic assertions. | ||||
| 
 | ||||
| Author: | ||||
| 
 | ||||
|     Nikolaj Bjorner (nbjorner) 2023-7-8 | ||||
| 
 | ||||
| 
 | ||||
| --*/ | ||||
| #include "ast/polymorphism_inst.h" | ||||
| #include "ast/ast_pp.h" | ||||
| 
 | ||||
| namespace polymorphism { | ||||
|      | ||||
|     void inst::add(expr* e) { | ||||
|         if (!m.has_type_vars()) | ||||
|             return; | ||||
| 
 | ||||
|         if (m_from_instantiation.contains(e)) | ||||
|             return; | ||||
| 
 | ||||
|         instances inst; | ||||
|         u.collect_poly_instances(e, inst.m_poly_fns); | ||||
|         if (inst.m_poly_fns.empty()) | ||||
|             return; | ||||
|         if (m_instances.contains(e)) | ||||
|             return; | ||||
|          | ||||
|         add_instantiations(e, inst.m_poly_fns); | ||||
| 
 | ||||
|         if (!u.has_type_vars(e)) | ||||
|             return; | ||||
|          | ||||
|         // insert e into the occurs list for polymorphic roots
 | ||||
|         ast_mark seen; | ||||
|         for (auto* f : inst.m_poly_fns) { | ||||
|             f = m.poly_root(f); | ||||
|             if (seen.is_marked(f)) | ||||
|                 continue; | ||||
|             seen.mark(f, true); | ||||
|             if (!m_occurs.contains(f)) { | ||||
|                 m_occurs.insert(f, ptr_vector<expr>()); | ||||
|                 t.push(insert_map(m_occurs, f)); | ||||
|             } | ||||
|             auto& es = m_occurs.find(f); | ||||
|             es.push_back(e); | ||||
|             t.push(remove_back(m_occurs, f)); | ||||
|         } | ||||
|         m_assertions.push_back(e); | ||||
|         t.push(push_back_vector(m_assertions)); | ||||
|         u.collect_type_vars(e, inst.m_tvs); | ||||
|         inst.m_subst = alloc(substitutions); | ||||
|         inst.m_subst->insert(alloc(substitution, m)); | ||||
|         m_instances.insert(e, inst);             | ||||
|         t.push(new_obj_trail(inst.m_subst)); | ||||
|         t.push(insert_map(m_instances, e));         | ||||
|     } | ||||
| 
 | ||||
|     void inst::collect_instantiations(expr* e) { | ||||
|         ptr_vector<func_decl> instances; | ||||
|         u.collect_poly_instances(e, instances); | ||||
|         add_instantiations(e, instances); | ||||
|     } | ||||
| 
 | ||||
|     void inst::add_instantiations(expr* e, ptr_vector<func_decl> const& instances) { | ||||
|         for (auto* f : instances) { | ||||
|             if (m_in_decl_queue.is_marked(f)) | ||||
|                 continue; | ||||
|             m_in_decl_queue.mark(f, true); | ||||
|             m_decl_queue.push_back(f); | ||||
|             t.push(add_decl_queue(*this)); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     void inst::instantiate(vector<instantiation>& instances) { | ||||
|         unsigned num_decls = m_decl_queue.size(); | ||||
|         if (m_assertions_qhead < m_assertions.size()) { | ||||
|             t.push(value_trail(m_assertions_qhead)); | ||||
|             for (; m_assertions_qhead < m_assertions.size(); ++m_assertions_qhead) { | ||||
|                 expr* e = m_assertions.get(m_assertions_qhead); | ||||
|                 for (unsigned i = 0; i < num_decls; ++i) | ||||
|                     instantiate(m_decl_queue.get(i), e, instances); | ||||
|             } | ||||
|         }        | ||||
|         if (m_decl_qhead < num_decls) { | ||||
|             t.push(value_trail(m_decl_qhead)); | ||||
|             for (; m_decl_qhead < num_decls; ++m_decl_qhead) { | ||||
|                 func_decl* p = m_decl_queue.get(m_decl_qhead); | ||||
|                 for (expr* e : m_occurs[m.poly_root(p)]) | ||||
|                     instantiate(p, e, instances); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void inst::instantiate(func_decl* f1, expr* e, vector<instantiation>& instances) { | ||||
|         auto const& [tv, fns, substs] = m_instances[e]; | ||||
|                  | ||||
|         for (auto* f2 : fns) { | ||||
|             substitution sub1(m), new_sub(m); | ||||
|             if (!u.unify(f1, f2, sub1)) | ||||
|                 continue; | ||||
|             if (substs->contains(&sub1)) | ||||
|                 continue; | ||||
|             substitutions new_substs; | ||||
|             for (auto* sub2 : *substs) { | ||||
|                 if (!u.unify(sub1, *sub2, new_sub)) | ||||
|                     continue; | ||||
|                 if (substs->contains(&new_sub)) | ||||
|                     continue; | ||||
|                 if (new_substs.contains(&new_sub)) | ||||
|                     continue; | ||||
|                 expr_ref e_inst = new_sub(e); | ||||
|                 if (!m_from_instantiation.contains(e_inst)) { | ||||
|                     collect_instantiations(e_inst); | ||||
|                     auto* new_sub1 = alloc(substitution, new_sub); | ||||
|                     instances.push_back(instantiation(e, e_inst, new_sub1)); | ||||
|                     new_substs.insert(new_sub1); | ||||
|                     m_from_instantiation.insert(e_inst); | ||||
|                     m.inc_ref(e_inst); | ||||
|                     t.push(insert_ref_map(m, m_from_instantiation, e_inst)); | ||||
|                 } | ||||
|             } | ||||
|             for (auto* sub2 : new_substs) { | ||||
|                 SASSERT(!substs->contains(sub2)); | ||||
|                 substs->insert(sub2); | ||||
|                 t.push(new_obj_trail(sub2)); | ||||
|                 t.push(insert_map(*substs, sub2)); | ||||
|             } | ||||
|         }         | ||||
|     } | ||||
| } | ||||
							
								
								
									
										91
									
								
								src/ast/polymorphism_inst.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/ast/polymorphism_inst.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,91 @@ | |||
| /*++
 | ||||
| Copyright (c) 2023 Microsoft Corporation | ||||
| 
 | ||||
| Module Name: | ||||
| 
 | ||||
|     polymorphism_inst.h | ||||
| 
 | ||||
| Abstract: | ||||
| 
 | ||||
|     Utilities for instantiating polymorphic assertions. | ||||
| 
 | ||||
| Author: | ||||
| 
 | ||||
|     Nikolaj Bjorner (nbjorner) 2023-7-8 | ||||
| 
 | ||||
| 
 | ||||
| --*/ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "util/trail.h" | ||||
| #include "ast/ast.h" | ||||
| #include "ast/polymorphism_util.h" | ||||
| 
 | ||||
| namespace polymorphism { | ||||
|      | ||||
|     struct instantiation { | ||||
|         expr* orig; | ||||
|         expr_ref inst; | ||||
|         substitution* sub; | ||||
|         instantiation(expr* orig, expr_ref& inst, substitution* s): | ||||
|             orig(orig), inst(inst), sub(s) {} | ||||
|     }; | ||||
|      | ||||
|     class inst { | ||||
|         ast_manager& m; | ||||
|         trail_stack& t; | ||||
|         util u; | ||||
|          | ||||
|         struct instances { | ||||
|             ptr_vector<sort>               m_tvs; | ||||
|             ptr_vector<func_decl>          m_poly_fns; | ||||
|             substitutions*                 m_subst = nullptr; | ||||
|         }; | ||||
|          | ||||
|         func_decl_ref_vector m_poly_roots; | ||||
|         obj_map<func_decl, ptr_vector<expr>> m_occurs; | ||||
|         obj_map<expr, instances>      m_instances; | ||||
|         func_decl_ref_vector          m_decl_queue; | ||||
|         unsigned                      m_decl_qhead = 0; | ||||
|         ast_mark                      m_in_decl_queue; | ||||
|         expr_ref_vector               m_assertions; | ||||
|         unsigned                      m_assertions_qhead = 0; | ||||
|         obj_hashtable<expr>           m_from_instantiation; | ||||
|                  | ||||
|         struct add_decl_queue : public trail { | ||||
|             inst& i; | ||||
|             add_decl_queue(inst& i): i(i) {} | ||||
|             void undo() override { | ||||
|                 i.m_in_decl_queue.mark(i.m_decl_queue.back(), false); | ||||
|                 i.m_decl_queue.pop_back(); | ||||
|             }; | ||||
|         }; | ||||
| 
 | ||||
|         struct remove_back : public trail { | ||||
|             obj_map<func_decl, ptr_vector<expr>>& occ; | ||||
|             func_decl* f; | ||||
|             remove_back(obj_map<func_decl, ptr_vector<expr>>& occ, func_decl* f): | ||||
|                 occ(occ), f(f) {} | ||||
|             void undo() override { | ||||
|                 occ.find(f).pop_back(); | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         void instantiate(func_decl* p, expr* e, vector<instantiation>& instances); | ||||
| 
 | ||||
|         void collect_instantiations(expr* e); | ||||
| 
 | ||||
|         void add_instantiations(expr* e, ptr_vector<func_decl> const& insts); | ||||
| 
 | ||||
|     public: | ||||
|         inst(ast_manager& m, trail_stack& t): | ||||
|             m(m), t(t), u(m), m_poly_roots(m), m_decl_queue(m), m_assertions(m) {} | ||||
|          | ||||
|         void add(expr* e); | ||||
|          | ||||
|         void instantiate(vector<instantiation>& instances); | ||||
| 
 | ||||
|         bool pending() const { return m_decl_qhead < m_decl_queue.size() || m_assertions_qhead < m_assertions.size(); } | ||||
|          | ||||
|     }; | ||||
| } | ||||
							
								
								
									
										353
									
								
								src/ast/polymorphism_util.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								src/ast/polymorphism_util.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,353 @@ | |||
| /*++
 | ||||
| Copyright (c) 2023 Microsoft Corporation | ||||
| 
 | ||||
| Module Name: | ||||
| 
 | ||||
|     polymorphism_util.cpp | ||||
| 
 | ||||
| Abstract: | ||||
| 
 | ||||
|     Utilities for supporting polymorphic type signatures. | ||||
| 
 | ||||
| Author: | ||||
| 
 | ||||
|     Nikolaj Bjorner (nbjorner) 2023-7-8 | ||||
| 
 | ||||
| --*/ | ||||
| 
 | ||||
| #include "ast/polymorphism_util.h" | ||||
| #include "ast/for_each_ast.h" | ||||
| #include "ast/occurs.h" | ||||
| #include "ast/ast_pp.h" | ||||
| 
 | ||||
| namespace polymorphism { | ||||
| 
 | ||||
|     sort_ref_vector substitution::operator()(sort_ref_vector const& s) { | ||||
|         sort_ref_vector r(m); | ||||
|         for (auto* srt : s) | ||||
|             r.push_back((*this)(srt)); | ||||
|         return r; | ||||
|     } | ||||
|      | ||||
|     sort_ref substitution::operator()(sort* s) { | ||||
|         if (!m.has_type_var(s)) | ||||
|             return sort_ref(s, m); | ||||
|         if (s->is_type_var()) { | ||||
|             if (m_sub.find(s, s)) | ||||
|                 return (*this)(s); | ||||
|             return sort_ref(s, m); | ||||
|         } | ||||
|         unsigned n = s->get_num_parameters(); | ||||
|         vector<parameter> ps; | ||||
|         for (unsigned i = 0; i < n; ++i) { | ||||
|             auto p = s->get_parameter(i); | ||||
|             if (p.is_ast() && is_sort(p.get_ast())) { | ||||
|                 sort_ref s = (*this)(to_sort(p.get_ast())); | ||||
|                 ps.push_back(parameter(s.get())); | ||||
|             } | ||||
|             else | ||||
|                 ps.push_back(p); | ||||
|         } | ||||
|         sort_info si(s->get_family_id(), s->get_decl_kind(), n, ps.data(), s->private_parameters()); | ||||
|         return sort_ref(m.mk_sort(s->get_name(), si), m); | ||||
|     } | ||||
|      | ||||
|     expr_ref substitution::operator()(expr* e) { | ||||
|         ptr_vector<expr> todo; | ||||
|         expr_ref_vector result(m); | ||||
|         todo.push_back(e); | ||||
|         auto in_cache = [&](expr* a) { | ||||
|             return result.size() > a->get_id() && result.get(a->get_id()); | ||||
|         }; | ||||
|         ptr_buffer<expr> args; | ||||
|         sort_ref_buffer domain(m); | ||||
|         while (!todo.empty()) { | ||||
|             expr* a = todo.back(); | ||||
|             if (in_cache(a)) { | ||||
|                 todo.pop_back(); | ||||
|                 continue; | ||||
|             } | ||||
|             if (is_var(a)) { | ||||
|                 if (m.has_type_var(a->get_sort()))  | ||||
|                     result.setx(a->get_id(), m.mk_var(to_var(a)->get_idx(), (*this)(a->get_sort())));                 | ||||
|                 else | ||||
|                     result.setx(a->get_id(), a);                 | ||||
|                 todo.pop_back(); | ||||
|             } | ||||
|             else if (is_quantifier(a)) { | ||||
|                 quantifier* q = to_quantifier(a); | ||||
|                 bool pending = false; | ||||
|                 if (!in_cache(q->get_expr())) { | ||||
|                     todo.push_back(q->get_expr()); | ||||
|                     pending = true; | ||||
|                 } | ||||
|                 ptr_buffer<expr> patterns, no_patterns; | ||||
|                 unsigned np = q->get_num_patterns(); | ||||
|                 for (unsigned i = 0; i < np; ++i) { | ||||
|                     if (!in_cache(q->get_pattern(i))) { | ||||
|                         todo.push_back(q->get_pattern(i)); | ||||
|                         pending = true; | ||||
|                     } | ||||
|                     else | ||||
|                         patterns.push_back(result.get(q->get_pattern(i)->get_id())); | ||||
|                 } | ||||
|                 np = q->get_num_no_patterns(); | ||||
|                 for (unsigned i = 0; i < np; ++i) { | ||||
|                     if (!in_cache(q->get_no_pattern(i))) { | ||||
|                         todo.push_back(q->get_no_pattern(i)); | ||||
|                         pending = true; | ||||
|                     } | ||||
|                     else | ||||
|                         no_patterns.push_back(result.get(q->get_no_pattern(i)->get_id())); | ||||
|                 } | ||||
|                 if (pending) | ||||
|                     continue; | ||||
|                 todo.pop_back(); | ||||
|                 domain.reset(); | ||||
|                 for (unsigned i = 0; i < q->get_num_decls(); ++i) | ||||
|                     domain.push_back((*this)(q->get_decl_sort(i))); | ||||
|                 quantifier* q2 =  | ||||
|                     m.mk_quantifier(q->get_kind(), q->get_num_decls(), domain.data(), q->get_decl_names(), result.get(q->get_expr()->get_id()), | ||||
|                     q->get_weight(), | ||||
|                     q->get_qid(), q->get_skid(),  | ||||
|                     q->get_num_patterns(), patterns.data(), q->get_num_no_patterns(), no_patterns.data() | ||||
|                     ); | ||||
|                 result.setx(q->get_id(), q2); | ||||
|             } | ||||
|             else if (is_app(a)) { | ||||
|                 args.reset(); | ||||
|                 unsigned n = todo.size(); | ||||
|                 for (expr* arg : *to_app(a)) { | ||||
|                     if (!in_cache(arg)) | ||||
|                         todo.push_back(arg); | ||||
|                     else | ||||
|                         args.push_back(result.get(arg->get_id())); | ||||
|                 } | ||||
|                 if (n < todo.size()) | ||||
|                     continue; | ||||
|                 func_decl* f = to_app(a)->get_decl(); | ||||
|                 if (f->is_polymorphic()) { | ||||
|                     domain.reset(); | ||||
|                     for (unsigned i = 0; i < f->get_arity(); ++i) | ||||
|                         domain.push_back((*this)(f->get_domain(i))); | ||||
|                     sort_ref range = (*this)(f->get_range()); | ||||
|                     f = m.instantiate_polymorphic(f, f->get_arity(), domain.data(), range); | ||||
|                 } | ||||
|                 result.setx(a->get_id(), m.mk_app(f, args)); | ||||
|                 todo.pop_back(); | ||||
|             } | ||||
|         } | ||||
|         return expr_ref(result.get(e->get_id()), m); | ||||
|     } | ||||
|      | ||||
|     bool substitution::unify(sort* s1, sort* s2) { | ||||
|         if (s1 == s2) | ||||
|             return true; | ||||
|         if (s1->is_type_var() && m_sub.find(s1, s1)) | ||||
|             return unify(s1, s2); | ||||
|         if (s2->is_type_var() && m_sub.find(s2, s2)) | ||||
|             return unify(s1, s2); | ||||
|         if (s2->is_type_var() && !s1->is_type_var()) | ||||
|             std::swap(s1, s2); | ||||
|         if (s1->is_type_var()) { | ||||
|             auto s22 = (*this)(s2); | ||||
|             if (occurs(s1, s22)) | ||||
|                 return false;     | ||||
|             m_trail.push_back(s22); | ||||
|             m_trail.push_back(s1); | ||||
|             m_sub.insert(s1, s22); | ||||
|             return true; | ||||
|         } | ||||
|         if (s1->get_family_id() != s2->get_family_id()) | ||||
|             return false; | ||||
|         if (s1->get_decl_kind() != s2->get_decl_kind()) | ||||
|             return false; | ||||
|         if (s1->get_name() != s2->get_name()) | ||||
|             return false; | ||||
|         if (s1->get_num_parameters() != s2->get_num_parameters()) | ||||
|             return false; | ||||
|         for (unsigned i = s1->get_num_parameters(); i-- > 0;) { | ||||
|             auto p1 = s1->get_parameter(i); | ||||
|             auto p2 = s2->get_parameter(i); | ||||
|             if (p1.is_ast() && is_sort(p1.get_ast())) { | ||||
|                 if (!p2.is_ast()) | ||||
|                     return false; | ||||
|                 if (!is_sort(p2.get_ast())) | ||||
|                     return false; | ||||
|                 if (!unify(to_sort(p1.get_ast()), to_sort(p2.get_ast()))) | ||||
|                     return false; | ||||
|                 continue; | ||||
|             } | ||||
|             if (p1 != p2) | ||||
|                 return false; | ||||
|         } | ||||
|         return true; | ||||
|     }     | ||||
| 
 | ||||
|     bool substitution::match(sort* s1, sort* s2) { | ||||
|         if (s1 == s2) | ||||
|             return true; | ||||
|         if (s1->is_type_var() && m_sub.find(s1, s1)) | ||||
|             return match(s1, s2); | ||||
|         if (s1->is_type_var()) { | ||||
|             m_trail.push_back(s2); | ||||
|             m_trail.push_back(s1); | ||||
|             m_sub.insert(s1, s2); | ||||
|             return true; | ||||
|         } | ||||
|         if (s1->get_family_id() != s2->get_family_id()) | ||||
|             return false; | ||||
|         if (s1->get_decl_kind() != s2->get_decl_kind()) | ||||
|             return false; | ||||
|         if (s1->get_name() != s2->get_name()) | ||||
|             return false; | ||||
|         if (s1->get_num_parameters() != s2->get_num_parameters()) | ||||
|             return false; | ||||
|         for (unsigned i = s1->get_num_parameters(); i-- > 0;) { | ||||
|             auto p1 = s1->get_parameter(i); | ||||
|             auto p2 = s2->get_parameter(i); | ||||
|             if (p1.is_ast() && is_sort(p1.get_ast())) { | ||||
|                 if (!p2.is_ast()) | ||||
|                     return false; | ||||
|                 if (!is_sort(p2.get_ast())) | ||||
|                     return false; | ||||
|                 if (!match(to_sort(p1.get_ast()), to_sort(p2.get_ast()))) | ||||
|                     return false; | ||||
|                 continue; | ||||
|             } | ||||
|             if (p1 != p2) | ||||
|                 return false; | ||||
|         } | ||||
|         return true; | ||||
|     }      | ||||
| 
 | ||||
|     // util        
 | ||||
|     bool util::unify(sort* s1, sort* s2, substitution& sub) { | ||||
|         return sub.unify(s1, s2); | ||||
|     } | ||||
|          | ||||
|     bool util::unify(func_decl* f1, func_decl* f2, substitution& sub) { | ||||
|         if (f1 == f2) | ||||
|             return true; | ||||
|         if (!f1->is_polymorphic() || !f2->is_polymorphic()) | ||||
|             return false; | ||||
|         if (m.poly_root(f1) != m.poly_root(f2)) | ||||
|             return false; | ||||
|         for (unsigned i = f1->get_arity(); i-- > 0; ) | ||||
|             if (!sub.unify(fresh(f1->get_domain(i)), f2->get_domain(i))) | ||||
|                 return false; | ||||
|         return sub.unify(fresh(f1->get_range()), f2->get_range()); | ||||
|     } | ||||
|          | ||||
|     bool util::unify(substitution const& s1, substitution const& s2, | ||||
|                      substitution& sub) { | ||||
|         sort* v2; | ||||
|         for (auto const& [k, v] : s1) | ||||
|             sub.insert(k, v); | ||||
|         for (auto const& [k, v] : s2) { | ||||
|             if (sub.find(k, v2)) { | ||||
|                 if (!sub.unify(sub(v), v2)) | ||||
|                     return false; | ||||
|             } | ||||
|             else | ||||
|                 sub.insert(k, sub(v)); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     bool util::match(substitution& sub, sort* s1, sort* s_ground) { | ||||
|         return sub.match(s1, s_ground); | ||||
|     } | ||||
|       | ||||
|     /**
 | ||||
|     * Create fresh variables, but with caching.  | ||||
|     * So "fresh" variables are not truly fresh globally. | ||||
|     * This can block some unifications and therefore block some instantiations of | ||||
|     * polymorphic assertions. A different caching scheme could be created to | ||||
|     * ensure that fresh variables are introduced at the right time, or use other | ||||
|     * tricks such as creating variable/offset pairs to distinguish name spaces without  | ||||
|     * incurring costs. | ||||
|     */ | ||||
|     sort_ref util::fresh(sort* s) { | ||||
|         sort* s1; | ||||
|         if (m_fresh.find(s, s1)) | ||||
|             return sort_ref(s1, m); | ||||
| 
 | ||||
|         if (m.is_type_var(s)) { | ||||
|             s1 = m.mk_type_var(symbol("fresh!" + std::to_string(m_counter))); | ||||
|             m_trail.push_back(s1); | ||||
|             m_trail.push_back(s); | ||||
|             m_fresh.insert(s, s1); | ||||
|             return sort_ref(s1, m); | ||||
|         } | ||||
|         vector<parameter> params; | ||||
|         for (unsigned i = 0; i < s->get_num_parameters(); ++i) { | ||||
|             parameter p = s->get_parameter(i); | ||||
|             if (p.is_ast() && is_sort(p.get_ast())) { | ||||
|                 sort_ref fs = fresh(to_sort(p.get_ast())); | ||||
|                 params.push_back(parameter(fs.get())); | ||||
|             } | ||||
|             else | ||||
|                 params.push_back(p); | ||||
|         } | ||||
|         sort_info info(s->get_family_id(), s->get_decl_kind(), params.size(), params.data(), s->private_parameters()); | ||||
|         s1 = m.mk_sort(s->get_name(), info); | ||||
|         m_trail.push_back(s1); | ||||
|         m_trail.push_back(s); | ||||
|         m_fresh.insert(s, s1); | ||||
|         return sort_ref(s1, m); | ||||
|     } | ||||
|          | ||||
|     sort_ref_vector util::fresh(unsigned n, sort* const* s) { | ||||
|         sort_ref_vector r(m); | ||||
|         for (unsigned i = 0; i < n; ++i) | ||||
|             r.push_back(fresh(s[i])); | ||||
|         return r; | ||||
|     } | ||||
|       | ||||
|     void util::collect_poly_instances(expr* e, ptr_vector<func_decl>& instances) { | ||||
|         struct proc { | ||||
|             ast_manager& m; | ||||
|             ptr_vector<func_decl>& instances; | ||||
|             proc(ast_manager& m, ptr_vector<func_decl>& instances) : m(m), instances(instances) {} | ||||
|             void operator()(func_decl* f) { | ||||
|                 if (f->is_polymorphic() && !m.is_eq(f) && !is_decl_of(f, pattern_family_id, OP_PATTERN)) | ||||
|                     instances.push_back(f); | ||||
|             } | ||||
|             void operator()(ast* a) {} | ||||
|         }; | ||||
|         proc proc(m, instances); | ||||
|         for_each_ast(proc, e, false);         | ||||
|     } | ||||
|          | ||||
|     bool util::has_type_vars(expr* e) { | ||||
|         struct proc { | ||||
|             ast_manager& m; | ||||
|             bool found = false; | ||||
|             proc(ast_manager& m) : m(m) {} | ||||
|             void operator()(sort* f) { | ||||
|                 if (m.has_type_var(f)) | ||||
|                     found = true; | ||||
|             } | ||||
|             void operator()(ast* a) {} | ||||
|         }; | ||||
|         proc proc(m); | ||||
|         for_each_ast(proc, e, false); | ||||
|         return proc.found; | ||||
|     } | ||||
|      | ||||
|     void util::collect_type_vars(expr* e, ptr_vector<sort>& tvs) { | ||||
|         struct proc { | ||||
|             ast_manager& m; | ||||
|             ptr_vector<sort>& tvs; | ||||
|             proc(ast_manager& m, ptr_vector<sort>& tvs) : m(m), tvs(tvs) {} | ||||
|             void operator()(sort* s) { | ||||
|                 if (m.is_type_var(s)) | ||||
|                     tvs.push_back(s); | ||||
|             } | ||||
|             void operator()(ast* a) {} | ||||
|         }; | ||||
|         proc proc(m, tvs); | ||||
|         for_each_ast(proc, e, true); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										112
									
								
								src/ast/polymorphism_util.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/ast/polymorphism_util.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| /*++
 | ||||
| Copyright (c) 2023 Microsoft Corporation | ||||
| 
 | ||||
| Module Name: | ||||
| 
 | ||||
|     polymorphism_util.h | ||||
| 
 | ||||
| Abstract: | ||||
| 
 | ||||
|     Utilities for supporting polymorphic type signatures. | ||||
| 
 | ||||
| Author: | ||||
| 
 | ||||
|     Nikolaj Bjorner (nbjorner) 2023-7-8 | ||||
| 
 | ||||
| --*/ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "ast/ast.h" | ||||
| #include "util/hashtable.h" | ||||
| 
 | ||||
| namespace polymorphism { | ||||
| 
 | ||||
|     class substitution { | ||||
|         ast_manager& m; | ||||
|         obj_map<sort, sort*> m_sub; | ||||
|         sort_ref_vector m_trail; | ||||
|     public: | ||||
|         substitution(ast_manager& m): m(m), m_trail(m) {} | ||||
|      | ||||
|         sort_ref_vector operator()(sort_ref_vector const& s); | ||||
|          | ||||
|         sort_ref operator()(sort* s); | ||||
| 
 | ||||
|         expr_ref operator()(expr* e); | ||||
|          | ||||
|         bool unify(sort* s1, sort* s2);        | ||||
| 
 | ||||
|         bool match(sort* s1, sort* s_ground); | ||||
| 
 | ||||
|         obj_map<sort, sort*>::iterator begin() const { return m_sub.begin(); } | ||||
|         obj_map<sort, sort*>::iterator end() const { return m_sub.end(); } | ||||
| 
 | ||||
|         void insert(sort* v, sort* t) { m_trail.push_back(v).push_back(t); m_sub.insert(v, t); } | ||||
| 
 | ||||
|         bool find(sort* v, sort*& t) const { return m_sub.find(v, t); } | ||||
| 
 | ||||
|         unsigned size() const { return m_sub.size(); } | ||||
| 
 | ||||
|         /**
 | ||||
|         * weak equality: strong equality considers applying substitutions recursively in range | ||||
|         * because substitutions may be in triangular form. | ||||
|         */ | ||||
|         struct eq { | ||||
|             bool operator()(substitution const* s1, substitution const* s2) const { | ||||
|                 if (s1->size() != s2->size()) | ||||
|                     return false; | ||||
|                 sort* v2; | ||||
|                 for (auto const& [k, v] : *s1) { | ||||
|                     if (!s2->find(k, v2)) | ||||
|                         return false; | ||||
|                     if (v != v2) | ||||
|                         return false; | ||||
|                 } | ||||
|                 return true; | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         struct hash { | ||||
|             unsigned operator()(substitution const* s) const { | ||||
|                 unsigned hash = 0xfabc1234 + s->size(); | ||||
|                 for (auto const& [k, v] : *s)  | ||||
|                     hash ^= k->hash() + 2 * v->hash();                 | ||||
|                 return hash; | ||||
|             } | ||||
|         }; | ||||
|     }; | ||||
| 
 | ||||
|     typedef hashtable<substitution*, substitution::hash, substitution::eq> substitutions; | ||||
|      | ||||
|     class util { | ||||
|         ast_manager&         m; | ||||
|         sort_ref_vector      m_trail; | ||||
|         obj_map<sort, sort*> m_fresh; | ||||
|         unsigned             m_counter = 0; | ||||
| 
 | ||||
|         sort_ref fresh(sort* s); | ||||
| 
 | ||||
|         sort_ref_vector fresh(unsigned n, sort* const* s); | ||||
|          | ||||
|     public: | ||||
|         util(ast_manager& m): m(m), m_trail(m) {} | ||||
|          | ||||
|         bool unify(sort* s1, sort* s2, substitution& sub); | ||||
|          | ||||
|         bool unify(func_decl* f1, func_decl* f2, substitution& sub); | ||||
|          | ||||
|         bool unify(substitution const& s1, substitution const& s2, | ||||
|                    substitution& sub); | ||||
| 
 | ||||
|         bool match(substitution& sub, sort* s1, sort* s_ground); | ||||
|                          | ||||
|         // collect instantiations of polymorphic functions
 | ||||
|         void collect_poly_instances(expr* e, ptr_vector<func_decl>& instances); | ||||
|          | ||||
|         // test if expression contains polymorphic variable.
 | ||||
|         bool has_type_vars(expr* e); | ||||
| 
 | ||||
|         void collect_type_vars(expr* e, ptr_vector<sort>& tvs); | ||||
|          | ||||
|     }; | ||||
| } | ||||
|  | @ -23,7 +23,6 @@ z3_add_component(rewriter | |||
|     factor_rewriter.cpp | ||||
|     fpa_rewriter.cpp | ||||
|     func_decl_replace.cpp | ||||
|     hoist_rewriter.cpp | ||||
|     inj_axiom.cpp | ||||
|     label_rewriter.cpp | ||||
|     macro_replacer.cpp | ||||
|  |  | |||
|  | @ -551,25 +551,10 @@ br_status arith_rewriter::mk_le_ge_eq_core(expr * arg1, expr * arg2, op_kind kin | |||
| } | ||||
| 
 | ||||
|     if (m_anum_simp) { | ||||
|         if (is_numeral(arg1, a1) && m_util.is_irrational_algebraic_numeral(arg2)) { | ||||
|             anum_manager & am = m_util.am(); | ||||
|             scoped_anum v1(am); | ||||
|             am.set(v1, a1.to_mpq()); | ||||
|             anum const & v2 = m_util.to_irrational_algebraic_numeral(arg2); | ||||
|             ANUM_LE_GE_EQ(); | ||||
|         } | ||||
|         if (m_util.is_irrational_algebraic_numeral(arg1) && is_numeral(arg2, a2)) { | ||||
|             anum_manager & am = m_util.am(); | ||||
|             anum const & v1 = m_util.to_irrational_algebraic_numeral(arg1); | ||||
|             scoped_anum v2(am); | ||||
|             am.set(v2, a2.to_mpq()); | ||||
|             ANUM_LE_GE_EQ(); | ||||
|         } | ||||
|         if (m_util.is_irrational_algebraic_numeral(arg1) && m_util.is_irrational_algebraic_numeral(arg2)) { | ||||
|             anum_manager & am = m_util.am(); | ||||
|             anum const & v1 = m_util.to_irrational_algebraic_numeral(arg1); | ||||
|             anum const & v2 = m_util.to_irrational_algebraic_numeral(arg2); | ||||
|             ANUM_LE_GE_EQ(); | ||||
|         auto& am = m_util.am(); | ||||
|         scoped_anum v1(am), v2(am); | ||||
|         if (is_algebraic_numeral(arg1, v1) && is_algebraic_numeral(arg2, v2)) { | ||||
|             ANUM_LE_GE_EQ();             | ||||
|         } | ||||
|     } | ||||
|     br_status st1 = is_separated(arg1, arg2, kind, result); | ||||
|  | @ -669,6 +654,7 @@ br_status arith_rewriter::mk_le_ge_eq_core(expr * arg1, expr * arg2, op_kind kin | |||
|     return BR_FAILED; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| br_status arith_rewriter::mk_le_core(expr * arg1, expr * arg2, expr_ref & result) { | ||||
|     return mk_le_ge_eq_core(arg1, arg2, LE, result); | ||||
| } | ||||
|  | @ -744,18 +730,26 @@ bool arith_rewriter::mk_eq_mod(expr* arg1, expr* arg2, expr_ref& result) { | |||
|         if (g == 1) { | ||||
|             expr_ref nb(m_util.mk_numeral(b, true), m); | ||||
|             result = m.mk_eq(m_util.mk_mod(u, y), | ||||
|                                m_util.mk_mod(m_util.mk_mul(nb, arg2), y)); | ||||
|                              m_util.mk_mod(m_util.mk_mul(nb, arg2), y)); | ||||
|             return true;             | ||||
|         } | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| expr_ref arith_rewriter::neg_monomial(expr* e) const { | ||||
| expr_ref arith_rewriter::neg_monomial(expr* e) { | ||||
|     expr_ref_vector args(m); | ||||
|     rational a1; | ||||
|     if (m_util.is_numeral(e, a1))  | ||||
|         args.push_back(m_util.mk_numeral(-a1, e->get_sort())); | ||||
|     else if (m_util.is_irrational_algebraic_numeral(e)) { | ||||
|         auto& n = m_util.to_irrational_algebraic_numeral(e); | ||||
|         auto& am = m_util.am(); | ||||
|         scoped_anum new_n(am); | ||||
|         am.set(new_n, n); | ||||
|         am.neg(new_n); | ||||
|         args.push_back(m_util.mk_numeral(am, new_n, m_util.is_int(e))); | ||||
|     } | ||||
|     else if (is_app(e) && m_util.is_mul(e)) { | ||||
|         if (is_numeral(to_app(e)->get_arg(0), a1)) { | ||||
|             if (!a1.is_minus_one()) { | ||||
|  | @ -780,7 +774,7 @@ expr_ref arith_rewriter::neg_monomial(expr* e) const { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| bool arith_rewriter::is_neg_poly(expr* t, expr_ref& neg) const { | ||||
| bool arith_rewriter::is_neg_poly(expr* t, expr_ref& neg) { | ||||
|     rational r; | ||||
|     if (m_util.is_mul(t) && is_numeral(to_app(t)->get_arg(0), r) && r.is_neg()) { | ||||
|         neg = neg_monomial(t); | ||||
|  | @ -824,6 +818,36 @@ bool arith_rewriter::is_anum_simp_target(unsigned num_args, expr * const * args) | |||
|     return false; | ||||
| } | ||||
| 
 | ||||
| bool arith_rewriter::is_algebraic_numeral(expr* n, scoped_anum& a) { | ||||
|     auto& am = m_util.am(); | ||||
|     expr* x, *y; | ||||
|     rational r; | ||||
|     if (m_util.is_mul(n, x, y)) { | ||||
|         scoped_anum ax(am), ay(am); | ||||
|         if (is_algebraic_numeral(x, ax) && is_algebraic_numeral(y, ay)) { | ||||
|             am.mul(ax, ay, a); | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|     else if (m_util.is_add(n, x, y)) { | ||||
|         scoped_anum ax(am), ay(am); | ||||
|         if (is_algebraic_numeral(x, ax) && is_algebraic_numeral(y, ay)) { | ||||
|             am.add(ax, ay, a); | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|     else if (m_util.is_numeral(n, r)) { | ||||
|         am.set(a, r.to_mpq()); | ||||
|         return true; | ||||
|     }     | ||||
|     else if (m_util.is_irrational_algebraic_numeral(n)) { | ||||
|         am.set(a, m_util.to_irrational_algebraic_numeral(n)); | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| br_status arith_rewriter::mk_add_core(unsigned num_args, expr * const * args, expr_ref & result) { | ||||
|     if (is_anum_simp_target(num_args, args)) { | ||||
|         expr_ref_buffer new_args(m); | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ Notes: | |||
| #include "ast/rewriter/poly_rewriter.h" | ||||
| #include "ast/arith_decl_plugin.h" | ||||
| #include "ast/seq_decl_plugin.h" | ||||
| #include "math/polynomial/algebraic_numbers.h" | ||||
| 
 | ||||
| class arith_rewriter_core { | ||||
| protected: | ||||
|  | @ -80,6 +81,7 @@ class arith_rewriter : public poly_rewriter<arith_rewriter_core> { | |||
|     void updt_local_params(params_ref const & p); | ||||
| 
 | ||||
|     bool is_anum_simp_target(unsigned num_args, expr * const * args); | ||||
|     bool is_algebraic_numeral(expr* n, scoped_anum& a); | ||||
| 
 | ||||
|     br_status mk_div_irrat_rat(expr * arg1, expr * arg2, expr_ref & result); | ||||
|     br_status mk_div_rat_irrat(expr * arg1, expr * arg2, expr_ref & result); | ||||
|  | @ -97,8 +99,8 @@ class arith_rewriter : public poly_rewriter<arith_rewriter_core> { | |||
|     bool is_2_pi_integer_offset(expr * t, expr * & m); | ||||
|     bool is_pi_integer(expr * t); | ||||
|     bool is_pi_integer_offset(expr * t, expr * & m); | ||||
|     bool is_neg_poly(expr* e, expr_ref& neg) const; | ||||
|     expr_ref neg_monomial(expr * e) const; | ||||
|     bool is_neg_poly(expr* e, expr_ref& neg); | ||||
|     expr_ref neg_monomial(expr * e); | ||||
|     expr * mk_sin_value(rational const & k); | ||||
|     app * mk_sqrt(rational const & k); | ||||
|     bool divides(expr* d, expr* n, expr_ref& result); | ||||
|  |  | |||
|  | @ -24,6 +24,7 @@ Notes: | |||
| #include "ast/rewriter/var_subst.h" | ||||
| #include "params/array_rewriter_params.hpp" | ||||
| #include "util/util.h" | ||||
| #include "ast/array_peq.h" | ||||
| 
 | ||||
| void array_rewriter::updt_params(params_ref const & _p) { | ||||
|     array_rewriter_params p(_p); | ||||
|  | @ -40,8 +41,48 @@ void array_rewriter::get_param_descrs(param_descrs & r) { | |||
| } | ||||
| 
 | ||||
| br_status array_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { | ||||
|     br_status st = BR_FAILED; | ||||
| 
 | ||||
|     // BEGIN: rewrite rules for PEQs
 | ||||
|     if (is_partial_eq(f)) { | ||||
|         SASSERT(num_args >= 2); | ||||
|         expr *e0, *e1; | ||||
|         e0 = args[0]; | ||||
|         e1 = args[1]; | ||||
| 
 | ||||
|         expr_ref a(m()), val(m()); | ||||
|         expr_ref_vector vindex(m()); | ||||
| 
 | ||||
|         if (e0 == e1) { | ||||
|             // t peq t --> true
 | ||||
|             result = m().mk_true(); | ||||
|             st = BR_DONE; | ||||
|         } | ||||
|         else if (m_util.is_store_ext(e0, a, vindex, val)) { | ||||
|             if (num_args == 2 && a == e1) { | ||||
|                 // (a[i := x] peq_{\emptyset} a) ---> a[i] == x
 | ||||
|                 mk_select(vindex.size(), vindex.data(), result); | ||||
|                 result = m().mk_eq(result, val); | ||||
|                 st = BR_REWRITE_FULL; | ||||
|             } | ||||
|             else if (a == e1 && vindex.size() == num_args + 2) { | ||||
|                 // a [i: = x] peq_{i} a -- > true
 | ||||
|                 bool all_eq = true; | ||||
|                 for (unsigned i = 0, sz = vindex.size(); all_eq && i < sz; | ||||
|                      ++i) { | ||||
|                     all_eq &= vindex.get(i) == args[2+i]; | ||||
|                 } | ||||
|                 if (all_eq) { | ||||
|                     result = m().mk_true(); | ||||
|                     st = BR_DONE; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return st; | ||||
|     } | ||||
|     // END: rewrite rules for PEQs
 | ||||
| 
 | ||||
|     SASSERT(f->get_family_id() == get_fid()); | ||||
|     br_status st; | ||||
|     switch (f->get_decl_kind()) { | ||||
|     case OP_SELECT: | ||||
|         st = mk_select_core(num_args, args, result); | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ Notes: | |||
| #include "ast/rewriter/bit_blaster/bit_blaster_tpl_def.h" | ||||
| #include "ast/rewriter/rewriter_def.h" | ||||
| #include "ast/rewriter/bool_rewriter.h" | ||||
| #include "ast/rewriter/th_rewriter.h" | ||||
| #include "util/ref_util.h" | ||||
| #include "ast/ast_smt2_pp.h" | ||||
| 
 | ||||
|  | @ -549,10 +550,19 @@ MK_PARAMETRIC_UNARY_REDUCE(reduce_sign_extend, mk_sign_extend); | |||
|             case OP_INT2BV: | ||||
|             case OP_BV2INT: | ||||
|                 return BR_FAILED; | ||||
|             default: | ||||
|             default:                 | ||||
|                 TRACE("bit_blaster", tout << "non-supported operator: " << f->get_name() << "\n"; | ||||
|                       for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << std::endl;); | ||||
|                 { | ||||
|                     expr_ref r(m().mk_app(f, num, args), m()); | ||||
|                     result = r; | ||||
|                     th_rewriter rw(m()); | ||||
|                     rw(result); | ||||
|                     if (!is_app(result) || to_app(result)->get_decl() != f) | ||||
|                         return BR_REWRITE_FULL;                     | ||||
|                 } | ||||
|                 throw_unsupported(f); | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
|  | @ -34,7 +34,6 @@ void bool_rewriter::updt_params(params_ref const & _p) { | |||
|     m_blast_distinct       = p.blast_distinct(); | ||||
|     m_blast_distinct_threshold = p.blast_distinct_threshold(); | ||||
|     m_ite_extra_rules      = p.ite_extra_rules(); | ||||
|     m_hoist.set_elim_and(m_elim_and); | ||||
| } | ||||
| 
 | ||||
| void bool_rewriter::get_param_descrs(param_descrs & r) { | ||||
|  | @ -270,28 +269,6 @@ br_status bool_rewriter::mk_nflat_or_core(unsigned num_args, expr * const * args | |||
|                 return BR_DONE; | ||||
|         } | ||||
| 
 | ||||
| #if 1 | ||||
|         br_status st; | ||||
|         expr_ref r(m()); | ||||
|         st = m_hoist.mk_or(buffer.size(), buffer.data(), r); | ||||
|         if (st != BR_FAILED) { | ||||
|             m_counts1.reserve(m().get_num_asts() + 1); | ||||
|             m_counts2.reserve(m().get_num_asts() + 1); | ||||
|             get_num_internal_exprs(m_counts1, m_todo1, r); | ||||
|             for (unsigned i = 0; i < num_args; ++i) | ||||
|                 get_num_internal_exprs(m_counts2, m_todo2, args[i]); | ||||
|             unsigned count1 = count_internal_nodes(m_counts1, m_todo1); | ||||
|             unsigned count2 = count_internal_nodes(m_counts2, m_todo2); | ||||
|             if (count1 > count2) | ||||
|                 st = BR_FAILED; | ||||
|         } | ||||
|         if (st != BR_FAILED) | ||||
|             result = r; | ||||
|         if (st == BR_DONE) | ||||
|             return BR_REWRITE1; | ||||
|         if (st != BR_FAILED) | ||||
|             return st; | ||||
| #endif | ||||
|         if (s) { | ||||
|             if (m_sort_disjunctions) { | ||||
|                 ast_lt lt; | ||||
|  |  | |||
|  | @ -20,7 +20,6 @@ Notes: | |||
| 
 | ||||
| #include "ast/ast.h" | ||||
| #include "ast/rewriter/rewriter.h" | ||||
| #include "ast/rewriter/hoist_rewriter.h" | ||||
| #include "util/params.h" | ||||
| 
 | ||||
| /**
 | ||||
|  | @ -51,7 +50,6 @@ Notes: | |||
| */ | ||||
| class bool_rewriter { | ||||
|     ast_manager &  m_manager; | ||||
|     hoist_rewriter m_hoist; | ||||
|     bool           m_flat_and_or = false; | ||||
|     bool           m_sort_disjunctions = true; | ||||
|     bool           m_local_ctx = false; | ||||
|  | @ -84,7 +82,7 @@ class bool_rewriter { | |||
|     void push_new_arg(expr* arg, expr_ref_vector& new_args, expr_fast_mark1& neg_lits, expr_fast_mark2& pos_lits); | ||||
| 
 | ||||
| public: | ||||
|     bool_rewriter(ast_manager & m, params_ref const & p = params_ref()):m_manager(m), m_hoist(m), m_local_ctx_cost(0) {  | ||||
|     bool_rewriter(ast_manager & m, params_ref const & p = params_ref()):m_manager(m), m_local_ctx_cost(0) {  | ||||
|         updt_params(p);  | ||||
|     } | ||||
|     ast_manager & m() const { return m_manager; } | ||||
|  |  | |||
|  | @ -217,7 +217,7 @@ br_status bv_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * cons | |||
|     case OP_BUSUB_OVFL: | ||||
|         return mk_bvusub_underflow(num_args, args, result); | ||||
|     case OP_BSSUB_OVFL: | ||||
|         return mk_bvssub_overflow(num_args, args, result); | ||||
|         return mk_bvssub_under_overflow(num_args, args, result); | ||||
|     default: | ||||
|         return BR_FAILED; | ||||
|     } | ||||
|  | @ -3085,19 +3085,29 @@ br_status bv_rewriter::mk_bvusub_underflow(unsigned num, expr * const * args, ex | |||
|     return status; | ||||
| } | ||||
| 
 | ||||
| br_status bv_rewriter::mk_bvssub_overflow(unsigned num, expr * const * args, expr_ref & result) { | ||||
| //
 | ||||
| // no_overflow    := if t2 = min_int then t1 <s 0 else no_overflow(t1 + -t2)
 | ||||
| // no_underflow   := 0 <s -t2 => no_underflow(t1 + -t2)
 | ||||
| // over_underflow := 0 <s -t2 & under_overflow+(t1 + -t2) || t2 = min_int & t1 >=s 0 || t2 != min_int & under_overflow+(t1 + -t2)
 | ||||
| //                := if t2 == min_int then t1 >=s 0 else under_overflow+(t1 + -t2)
 | ||||
| // because when 0 <s min_int = false
 | ||||
| // 
 | ||||
| br_status bv_rewriter::mk_bvssub_under_overflow(unsigned num, expr * const * args, expr_ref & result) { | ||||
|     SASSERT(num == 2); | ||||
|     SASSERT(get_bv_size(args[0]) == get_bv_size(args[1])); | ||||
|     auto sz = get_bv_size(args[0]); | ||||
|     auto minSigned = mk_numeral(rational::power_of_two(sz-1), sz); | ||||
|     expr_ref bvsaddo {m}; | ||||
|     expr * args2[2] = { args[0], m_util.mk_bv_neg(args[1]) }; | ||||
|     auto bvsaddo_stat = mk_bvsadd_overflow(2, args2, bvsaddo); | ||||
|     auto bvsaddo_stat = mk_bvsadd_over_underflow(2, args2, bvsaddo); | ||||
|     SASSERT(bvsaddo_stat != BR_FAILED); (void)bvsaddo_stat; | ||||
|     auto first_arg_ge_zero = m_util.mk_sle(mk_zero(sz), args[0]); | ||||
|     result = m.mk_ite(m.mk_eq(args[1], minSigned), first_arg_ge_zero, bvsaddo); | ||||
|     return BR_REWRITE_FULL; | ||||
| } | ||||
| 
 | ||||
| //br_status bv_rewriter::mk_bvssub_overflow(unsigned num, expr * const * args, expr_ref & result) {
 | ||||
| //}
 | ||||
| br_status bv_rewriter::mk_bvsdiv_overflow(unsigned num, expr * const * args, expr_ref & result) { | ||||
|     SASSERT(num == 2); | ||||
|     SASSERT(get_bv_size(args[0]) == get_bv_size(args[1])); | ||||
|  |  | |||
|  | @ -153,7 +153,8 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> { | |||
|     br_status mk_bvsadd_over_underflow(unsigned num, expr * const * args, expr_ref & result); | ||||
| 
 | ||||
|     br_status mk_bvusub_underflow(unsigned num, expr * const * args, expr_ref & result); | ||||
|     br_status mk_bvssub_overflow(unsigned num, expr * const * args, expr_ref & result); | ||||
|     // br_status mk_bvssub_overflow(unsigned num, expr * const * args, expr_ref & result);
 | ||||
|     br_status mk_bvssub_under_overflow(unsigned num, expr * const * args, expr_ref & result); | ||||
| 
 | ||||
|     bool is_minus_one_times_t(expr * arg); | ||||
|     void mk_t1_add_t2_eq_c(expr * t1, expr * t2, expr * c, expr_ref & result); | ||||
|  |  | |||
|  | @ -21,7 +21,8 @@ Notes: | |||
| br_status datatype_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { | ||||
|     SASSERT(f->get_family_id() == get_fid()); | ||||
|     switch(f->get_decl_kind()) { | ||||
|     case OP_DT_CONSTRUCTOR: return BR_FAILED; | ||||
|     case OP_DT_CONSTRUCTOR: | ||||
|         return BR_FAILED; | ||||
|     case OP_DT_RECOGNISER: | ||||
|         SASSERT(num_args == 1); | ||||
|         result = m_util.mk_is(m_util.get_recognizer_constructor(f), args[0]); | ||||
|  |  | |||
|  | @ -17,8 +17,6 @@ Revision History: | |||
| 
 | ||||
| --*/ | ||||
| 
 | ||||
| #ifndef ELIM_BOUNDS_H_ | ||||
| #define ELIM_BOUNDS_H_ | ||||
| 
 | ||||
| #include "ast/used_vars.h" | ||||
| #include "util/obj_hashtable.h" | ||||
|  | @ -201,4 +199,3 @@ bool elim_bounds_cfg::reduce_quantifier(quantifier * q, | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| #endif /* ELIM_BOUNDS_H_ */ | ||||
|  |  | |||
|  | @ -1,248 +0,0 @@ | |||
| /*++
 | ||||
| Copyright (c) 2019 Microsoft Corporation | ||||
| 
 | ||||
| Module Name: | ||||
| 
 | ||||
|     hoist_rewriter.cpp | ||||
| 
 | ||||
| Abstract: | ||||
| 
 | ||||
|     Hoist predicates over disjunctions | ||||
| 
 | ||||
| Author: | ||||
| 
 | ||||
|     Nikolaj Bjorner (nbjorner) 2019-2-4 | ||||
| 
 | ||||
| --*/ | ||||
| 
 | ||||
| 
 | ||||
| #include "ast/rewriter/hoist_rewriter.h" | ||||
| #include "ast/rewriter/bool_rewriter.h" | ||||
| #include "ast/ast_util.h" | ||||
| #include "ast/ast_pp.h" | ||||
| #include "ast/ast_ll_pp.h" | ||||
| 
 | ||||
| hoist_rewriter::hoist_rewriter(ast_manager & m, params_ref const & p): | ||||
|     m(m), m_args1(m), m_args2(m), m_refs(m), m_subst(m) {  | ||||
|     updt_params(p);  | ||||
| } | ||||
| 
 | ||||
| expr_ref hoist_rewriter::mk_and(expr_ref_vector const& args) { | ||||
|     if (m_elim_and) { | ||||
|         expr_ref_vector negs(m); | ||||
|         for (expr* a : args) | ||||
|             if (m.is_false(a)) | ||||
|                 return expr_ref(m.mk_false(), m); | ||||
|             else if (m.is_true(a)) | ||||
|                 continue; | ||||
|             else | ||||
|                 negs.push_back(::mk_not(m, a)); | ||||
|         return ::mk_not(mk_or(negs)); | ||||
|     } | ||||
|     else | ||||
|         return ::mk_and(args); | ||||
| } | ||||
| 
 | ||||
| expr_ref hoist_rewriter::mk_or(expr_ref_vector const& args) { | ||||
|     return ::mk_or(args); | ||||
| } | ||||
| 
 | ||||
| br_status hoist_rewriter::mk_or(unsigned num_args, expr * const * es, expr_ref & result) { | ||||
|     if (num_args < 2)  | ||||
|         return BR_FAILED; | ||||
| 
 | ||||
|     for (unsigned i = 0; i < num_args; ++i)  | ||||
|         if (!is_and(es[i], nullptr))  | ||||
|             return BR_FAILED; | ||||
| 
 | ||||
|     bool turn = false; | ||||
|     m_preds1.reset();  | ||||
|     m_preds2.reset(); | ||||
|     m_uf1.reset();  | ||||
|     m_uf2.reset(); | ||||
|     m_expr2var.reset(); | ||||
|     m_var2expr.reset(); | ||||
|     basic_union_find* uf[2] = { &m_uf1, &m_uf2 }; | ||||
|     obj_hashtable<expr>* preds[2] = { &m_preds1, &m_preds2 }; | ||||
|     expr_ref_vector* args[2] = { &m_args1, &m_args2 }; | ||||
|     VERIFY(is_and(es[0], args[turn])); | ||||
|     expr* e1, *e2; | ||||
|     for (expr* e : *(args[turn])) { | ||||
|         if (m.is_eq(e, e1, e2))              | ||||
|             (*uf)[turn].merge(mk_var(e1), mk_var(e2)); | ||||
|         else  | ||||
|             (*preds)[turn].insert(e); | ||||
|     } | ||||
|     unsigned round = 0; | ||||
|     for (unsigned j = 1; j < num_args; ++j) { | ||||
|         ++round; | ||||
|         m_es.reset(); | ||||
|         m_mark.reset(); | ||||
| 
 | ||||
|         bool last = turn; | ||||
|         turn = !turn; | ||||
|         (*preds)[turn].reset(); | ||||
|         reset(m_uf0); | ||||
|         VERIFY(is_and(es[j], args[turn])); | ||||
| 
 | ||||
|         for (expr* e : *args[turn]) { | ||||
|             if (m.is_eq(e, e1, e2)) { | ||||
|                 m_es.push_back(e1);                 | ||||
|                 m_uf0.merge(mk_var(e1), mk_var(e2)); | ||||
|             }     | ||||
|             else if ((*preds)[last].contains(e))  | ||||
|                 (*preds)[turn].insert(e); | ||||
|         } | ||||
| 
 | ||||
|         if ((*preds)[turn].empty() && m_es.empty())  | ||||
|             return BR_FAILED; | ||||
| 
 | ||||
|         m_eqs.reset(); | ||||
|         for (expr* e : m_es) { | ||||
|             if (m_mark.is_marked(e))  | ||||
|                 continue; | ||||
|             unsigned u = mk_var(e); | ||||
|             unsigned v = u; | ||||
|             m_roots.reset(); | ||||
|             do { | ||||
|                 m_mark.mark(e); | ||||
|                 unsigned r = (*uf)[last].find(v); | ||||
|                 if (m_roots.find(r, e2))  | ||||
|                     m_eqs.push_back({e, e2}); | ||||
|                 else  | ||||
|                     m_roots.insert(r, e); | ||||
|                 v = m_uf0.next(v); | ||||
|                 e = mk_expr(v); | ||||
|             } | ||||
|             while (u != v); | ||||
|         } | ||||
|         reset((*uf)[turn]); | ||||
|         for (auto const& [e1, e2] : m_eqs)  | ||||
|             (*uf)[turn].merge(mk_var(e1), mk_var(e2)); | ||||
|         if ((*preds)[turn].empty() && m_eqs.empty())  | ||||
|             return BR_FAILED; | ||||
|     } | ||||
|     if (m_eqs.empty()) { | ||||
|         result = hoist_predicates((*preds)[turn], num_args, es); | ||||
|         return BR_DONE; | ||||
|     } | ||||
|     // p & eqs & (or fmls)
 | ||||
|     expr_ref_vector fmls(m); | ||||
|     m_subst.reset(); | ||||
|     for (expr * p : (*preds)[turn]) { | ||||
|         expr* q = nullptr; | ||||
|         if (m.is_not(p, q))  | ||||
|             m_subst.insert(q, m.mk_false()); | ||||
|         else  | ||||
|             m_subst.insert(p, m.mk_true()); | ||||
|         fmls.push_back(p); | ||||
|     } | ||||
|     for (auto& p : m_eqs) { | ||||
|         if (m.is_value(p.first)) | ||||
|             std::swap(p.first, p.second); | ||||
|         m_subst.insert(p.first, p.second); | ||||
|         fmls.push_back(m.mk_eq(p.first, p.second)); | ||||
|     }     | ||||
|     expr_ref ors(::mk_or(m, num_args, es), m); | ||||
|     m_subst(ors); | ||||
|     fmls.push_back(ors); | ||||
|     result = mk_and(fmls); | ||||
|     TRACE("hoist", tout << ors << " => " << result << "\n";); | ||||
|     return BR_DONE; | ||||
| } | ||||
| 
 | ||||
| unsigned hoist_rewriter::mk_var(expr* e) { | ||||
|     unsigned v = 0; | ||||
|     if (m_expr2var.find(e, v))  | ||||
|         return v; | ||||
|     m_uf1.mk_var(); | ||||
|     v = m_uf2.mk_var(); | ||||
|     SASSERT(v == m_var2expr.size()); | ||||
|     m_expr2var.insert(e, v); | ||||
|     m_var2expr.push_back(e); | ||||
|     return v; | ||||
| } | ||||
| 
 | ||||
| expr_ref hoist_rewriter::hoist_predicates(obj_hashtable<expr> const& preds, unsigned num_args, expr* const* es) { | ||||
|     expr_ref_vector args(m), args1(m), fmls(m); | ||||
|     for (unsigned i = 0; i < num_args; ++i) { | ||||
|         VERIFY(is_and(es[i], &args1)); | ||||
|         fmls.reset(); | ||||
|         for (expr* e : args1)  | ||||
|             if (!preds.contains(e)) | ||||
|                 fmls.push_back(e); | ||||
|         args.push_back(mk_and(fmls)); | ||||
|     } | ||||
|     fmls.reset(); | ||||
|     fmls.push_back(mk_or(args)); | ||||
|     for (auto* p : preds)  | ||||
|         fmls.push_back(p); | ||||
|     return mk_and(fmls); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| br_status hoist_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result) { | ||||
|     switch (f->get_decl_kind()) { | ||||
|     case OP_OR:         | ||||
|         return mk_or(num_args, args, result); | ||||
|     default: | ||||
|         return BR_FAILED; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool hoist_rewriter::is_and(expr * e, expr_ref_vector* args) { | ||||
| #if 0 | ||||
|     if (!args)  | ||||
|         return m.is_and(e) || (m.is_not(e, e) && m.is_or(e)); | ||||
|     expr_fast_mark1 visited; | ||||
|     args->reset(); | ||||
|     args->push_back(e); | ||||
|     m_refs.reset(); | ||||
|     for (unsigned i = 0; i < args->size(); ++i) { | ||||
|         e = args->get(i); | ||||
|         if (visited.is_marked(e))  | ||||
|             goto drop; | ||||
|         m_refs.push_back(e); | ||||
|         visited.mark(e, true); | ||||
|         if (m.is_and(e))  | ||||
|             args->append(to_app(e)->get_num_args(), to_app(e)->get_args()); | ||||
|         else if (m.is_not(e, e) && m.is_or(e))  | ||||
|             for (expr* arg : *to_app(e))  | ||||
|                 args->push_back(::mk_not(m, arg)); | ||||
|         else  | ||||
|             continue; | ||||
|     drop: | ||||
|         (*args)[i] = args->back(); | ||||
|         args->pop_back(); | ||||
|         --i; | ||||
|     } | ||||
|     return args->size() > 1; | ||||
| #else | ||||
|     if (m.is_and(e)) { | ||||
|         if (args) { | ||||
|             args->reset(); | ||||
|             args->append(to_app(e)->get_num_args(), to_app(e)->get_args()); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|     if (m.is_not(e, e) && m.is_or(e)) { | ||||
|         if (args) { | ||||
|             args->reset(); | ||||
|             for (expr* arg : *to_app(e))  | ||||
|                 args->push_back(::mk_not(m, arg)); | ||||
|             TRACE("hoist", tout << args << " " <<  * args << "\n"); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
| #endif | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void hoist_rewriter::reset(basic_union_find& uf) { | ||||
|     uf.reset(); | ||||
|     for (expr* e : m_var2expr) { | ||||
|         (void)e; | ||||
|         uf.mk_var(); | ||||
|     } | ||||
| } | ||||
|  | @ -1,87 +0,0 @@ | |||
| /*++
 | ||||
| Copyright (c) 2019 Microsoft Corporation | ||||
| 
 | ||||
| Module Name: | ||||
| 
 | ||||
|     hoist_rewriter.h | ||||
| 
 | ||||
| Abstract: | ||||
| 
 | ||||
|     Hoist predicates over disjunctions | ||||
| 
 | ||||
| Author: | ||||
| 
 | ||||
|     Nikolaj Bjorner (nbjorner) 2019-2-4 | ||||
| 
 | ||||
| Notes: | ||||
| 
 | ||||
| --*/ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "ast/ast.h" | ||||
| #include "ast/rewriter/rewriter.h" | ||||
| #include "ast/rewriter/expr_safe_replace.h" | ||||
| #include "util/params.h" | ||||
| #include "util/union_find.h" | ||||
| #include "util/obj_hashtable.h" | ||||
| 
 | ||||
| class bool_rewriter; | ||||
| 
 | ||||
| class hoist_rewriter { | ||||
|     ast_manager &                   m; | ||||
|     expr_ref_vector                 m_args1, m_args2, m_refs; | ||||
|     obj_hashtable<expr>             m_preds1, m_preds2; | ||||
|     basic_union_find                m_uf1, m_uf2, m_uf0; | ||||
|     ptr_vector<expr>                m_es; | ||||
|     svector<std::pair<expr*,expr*>> m_eqs; | ||||
|     u_map<expr*>                    m_roots; | ||||
|     expr_safe_replace               m_subst; | ||||
|     obj_map<expr, unsigned>         m_expr2var; | ||||
|     ptr_vector<expr>                m_var2expr; | ||||
|     expr_mark                       m_mark; | ||||
|     bool                            m_elim_and = false; | ||||
| 
 | ||||
|     bool is_and(expr* e, expr_ref_vector* args); | ||||
|     expr_ref mk_and(expr_ref_vector const& args); | ||||
|     expr_ref mk_or(expr_ref_vector const& args); | ||||
| 
 | ||||
|     bool is_var(expr* e) { return m_expr2var.contains(e); } | ||||
|     expr* mk_expr(unsigned v) { return m_var2expr[v]; } | ||||
|     unsigned mk_var(expr* e); | ||||
| 
 | ||||
|     void reset(basic_union_find& uf); | ||||
| 
 | ||||
|     expr_ref hoist_predicates(obj_hashtable<expr> const& p, unsigned num_args, expr* const* args); | ||||
| 
 | ||||
| 
 | ||||
| public: | ||||
|     hoist_rewriter(ast_manager & m, params_ref const & p = params_ref()); | ||||
|     family_id get_fid() const { return m.get_basic_family_id(); } | ||||
|     bool is_eq(expr * t) const { return m.is_eq(t); }        | ||||
|     void updt_params(params_ref const & p) {} | ||||
|     static void get_param_descrs(param_descrs & r) {} | ||||
|     br_status mk_app_core(func_decl * f, unsigned num_args, expr * const * args, expr_ref & result);     | ||||
|     br_status mk_or(unsigned num_args, expr * const * args, expr_ref & result);     | ||||
|     void set_elim_and(bool b) { m_elim_and = b; } | ||||
| }; | ||||
| 
 | ||||
| struct hoist_rewriter_cfg : public default_rewriter_cfg { | ||||
|     hoist_rewriter m_r; | ||||
|     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) { | ||||
|         result_pr = nullptr; | ||||
|         if (f->get_family_id() != m_r.get_fid()) | ||||
|             return BR_FAILED; | ||||
|         return m_r.mk_app_core(f, num, args, result); | ||||
|     } | ||||
|     hoist_rewriter_cfg(ast_manager & m, params_ref const & p):m_r(m, p) {} | ||||
| }; | ||||
| 
 | ||||
| class hoist_rewriter_star : public rewriter_tpl<hoist_rewriter_cfg> { | ||||
|     hoist_rewriter_cfg m_cfg; | ||||
| public: | ||||
|     hoist_rewriter_star(ast_manager & m, params_ref const & p = params_ref()): | ||||
|         rewriter_tpl<hoist_rewriter_cfg>(m, false, m_cfg), | ||||
|         m_cfg(m, p) {} | ||||
| }; | ||||
| 
 | ||||
|  | @ -17,6 +17,8 @@ Notes: | |||
| 
 | ||||
| --*/ | ||||
| #include "ast/rewriter/rewriter_def.h" | ||||
| #include "ast/rewriter/push_app_ite.h" | ||||
| #include "ast/rewriter/elim_bounds.h" | ||||
| #include "ast/ast_ll_pp.h" | ||||
| #include "ast/ast_pp.h" | ||||
| #include "ast/ast_smt2_pp.h" | ||||
|  | @ -417,3 +419,6 @@ void inv_var_shifter::process_var(var * v) { | |||
| } | ||||
|      | ||||
| template class rewriter_tpl<beta_reducer_cfg>; | ||||
| template class rewriter_tpl<ng_push_app_ite_cfg>; | ||||
| template class rewriter_tpl<push_app_ite_cfg>; | ||||
| template class rewriter_tpl<elim_bounds_cfg>; | ||||
|  |  | |||
|  | @ -33,6 +33,18 @@ enum br_status { | |||
|     BR_FAILED                  // no builtin rewrite is available
 | ||||
| }; | ||||
| 
 | ||||
| inline std::ostream& operator<<(std::ostream& out, br_status st) { | ||||
|     switch (st) { | ||||
|     case BR_REWRITE1: return out << "rewrite1"; | ||||
|     case BR_REWRITE2: return out << "rewrite2"; | ||||
|     case BR_REWRITE3: return out << "rewrite3"; | ||||
|     case BR_REWRITE_FULL: return out << "rewrite_full"; | ||||
|     case BR_DONE: return out << "done"; | ||||
|     case BR_FAILED: return out << "failed"; | ||||
|     default: return out << "unknown"; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #define RW_UNBOUNDED_DEPTH 3 | ||||
| inline br_status unsigned2br_status(unsigned u) { | ||||
|     br_status r = u >= RW_UNBOUNDED_DEPTH ? BR_REWRITE_FULL : static_cast<br_status>(u); | ||||
|  |  | |||
|  | @ -538,6 +538,7 @@ namespace seq { | |||
|         expr_ref t_eq_empty = mk_eq_empty(t); | ||||
|         expr_ref xsy        = mk_concat(x, s, y); | ||||
| 
 | ||||
|         //        add_clause(~mk_eq(t, s), i_eq_0);
 | ||||
|         add_clause(cnt, i_eq_m1); | ||||
|         add_clause(~t_eq_empty, s_eq_empty, i_eq_m1); | ||||
|         add_clause(~s_eq_empty, mk_eq(i, mk_len(t))); | ||||
|  |  | |||
|  | @ -828,6 +828,7 @@ br_status seq_rewriter::mk_seq_concat(expr* a, expr* b, expr_ref& result) { | |||
| 
 | ||||
| br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) { | ||||
|     zstring b; | ||||
|     rational r; | ||||
|     m_es.reset(); | ||||
|     str().get_concat(a, m_es); | ||||
|     unsigned len = 0; | ||||
|  | @ -867,6 +868,16 @@ br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) { | |||
|         result = str().mk_length(z); | ||||
|         return BR_REWRITE1; | ||||
|     }  | ||||
|     // len(extract(x, 0, z)) = min(z, len(x))
 | ||||
|     if (str().is_extract(a, x, y, z) &&  | ||||
|         m_autil.is_numeral(y, r) && r.is_zero() && | ||||
|         m_autil.is_numeral(z, r) && r >= 0) { | ||||
|         expr* len_x = str().mk_length(x); | ||||
|         result = m().mk_ite(m_autil.mk_le(len_x, z), len_x, z); | ||||
|         // expr* zero = m_autil.mk_int(0);
 | ||||
|         // result = m().mk_ite(m_autil.mk_le(z, zero), zero, result);
 | ||||
|         return BR_REWRITE_FULL; | ||||
|     } | ||||
| #if 0 | ||||
|     expr* s = nullptr, *offset = nullptr, *length = nullptr; | ||||
|     if (str().is_extract(a, s, offset, length)) { | ||||
|  | @ -1209,6 +1220,11 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu | |||
|     constantPos &= pos.is_unsigned(); | ||||
|     constantLen &= len.is_unsigned(); | ||||
| 
 | ||||
|     if (constantPos && constantLen && len == 1) { | ||||
|         result = str().mk_at(a, b); | ||||
|         return BR_REWRITE1; | ||||
|     } | ||||
| 
 | ||||
|     if (constantPos && constantLen && constantBase) { | ||||
|         unsigned _pos = pos.get_unsigned(); | ||||
|         unsigned _len = len.get_unsigned(); | ||||
|  | @ -1245,6 +1261,15 @@ br_status seq_rewriter::mk_seq_extract(expr* a, expr* b, expr* c, expr_ref& resu | |||
|         result = str().mk_substr(a1, m_autil.mk_add(b1, b), m_autil.mk_sub(c1, b)); | ||||
|         return BR_REWRITE3; | ||||
|     } | ||||
|     rational r1, r2; | ||||
|     if (str().is_extract(a, a1, b1, c1) && | ||||
|         m_autil.is_numeral(b1, r1) && r1.is_unsigned() && | ||||
|         m_autil.is_numeral(c1, r2) && r2.is_unsigned() && | ||||
|         constantPos && constantLen && | ||||
|         r1 == 0 && r2 >= pos + len) {         | ||||
|         result = str().mk_substr(a1, b, c); | ||||
|         return BR_REWRITE1;             | ||||
|     } | ||||
| 
 | ||||
|     if (str().is_extract(a, a1, b1, c1) &&  | ||||
|         is_prefix(a1, b1, c1) && is_prefix(a, b, c)) { | ||||
|  | @ -1539,9 +1564,17 @@ bool seq_rewriter::reduce_by_char(expr_ref& r, expr* ch, unsigned depth) { | |||
|  */ | ||||
| br_status seq_rewriter::mk_seq_at(expr* a, expr* b, expr_ref& result) { | ||||
|     zstring c; | ||||
|     rational r; | ||||
|     rational r, offset_r, len_r; | ||||
|     expr* offset, *a1, *len; | ||||
|     expr_ref_vector lens(m()); | ||||
|     sort* sort_a = a->get_sort(); | ||||
|     if (str().is_extract(a, a1, offset, len) &&  | ||||
|         m_autil.is_numeral(offset, offset_r) && offset_r.is_zero() &&  | ||||
|         m_autil.is_numeral(len, len_r) && m_autil.is_numeral(b, r) &&  | ||||
|         r < len_r) { | ||||
|         result = str().mk_at(a1, b); | ||||
|         return BR_REWRITE1; | ||||
|     } | ||||
|     if (!get_lengths(b, lens, r)) { | ||||
|         return BR_FAILED; | ||||
|     } | ||||
|  | @ -1716,6 +1749,10 @@ br_status seq_rewriter::mk_seq_last_index(expr* a, expr* b, expr_ref& result) { | |||
|         result = m_autil.mk_numeral(rational(idx), true); | ||||
|         return BR_DONE; | ||||
|     } | ||||
|     if (a == b) { | ||||
|         result = m_autil.mk_int(0); | ||||
|         return BR_DONE; | ||||
|     } | ||||
|     return BR_FAILED; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ Notes: | |||
| #include "ast/ast_util.h" | ||||
| #include "ast/well_sorted.h" | ||||
| #include "ast/for_each_expr.h" | ||||
| #include "ast/array_peq.h" | ||||
| 
 | ||||
| namespace { | ||||
| struct th_rewriter_cfg : public default_rewriter_cfg { | ||||
|  | @ -75,6 +76,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg { | |||
|     bool                m_ignore_patterns_on_ground_qbody = true; | ||||
|     bool                m_rewrite_patterns = true; | ||||
|     bool                m_enable_der = true; | ||||
|     bool                m_nested_der = false; | ||||
| 
 | ||||
| 
 | ||||
|     ast_manager & m() const { return m_b_rw.m(); } | ||||
|  | @ -91,6 +93,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg { | |||
|         m_ignore_patterns_on_ground_qbody = p.ignore_patterns_on_ground_qbody(); | ||||
|         m_rewrite_patterns = p.rewrite_patterns(); | ||||
|         m_enable_der     = p.enable_der(); | ||||
|         m_nested_der     = _p.get_bool("nested_der", false); | ||||
|     } | ||||
| 
 | ||||
|     void updt_params(params_ref const & p) { | ||||
|  | @ -644,6 +647,10 @@ struct th_rewriter_cfg : public default_rewriter_cfg { | |||
|             else | ||||
|                 st = pull_ite(result); | ||||
|         } | ||||
|         if (st == BR_FAILED && f->get_family_id() == null_family_id && is_partial_eq(f)) { | ||||
|             st = m_ar_rw.mk_app_core(f,  num, args, result); | ||||
|         } | ||||
| 
 | ||||
|         CTRACE("th_rewriter_step", st != BR_FAILED, | ||||
|                tout << f->get_name() << "\n"; | ||||
|                for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << "\n"; | ||||
|  | @ -838,8 +845,11 @@ struct th_rewriter_cfg : public default_rewriter_cfg { | |||
|             result = r; | ||||
|         } | ||||
| 
 | ||||
|         if (der_change) { | ||||
|         if (der_change && !m_nested_der) { | ||||
|             th_rewriter rw(m()); | ||||
|             params_ref p; | ||||
|             p.set_bool("nested_der", true); | ||||
|             rw.updt_params(p); | ||||
|             rw(result, r, p2); | ||||
|             if (m().proofs_enabled() && result.get() != r.get())  | ||||
|                 result_pr = m().mk_transitivity(result_pr, p2); | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ class bound_simplifier : public dependent_expr_simplifier { | |||
|     unsynch_mpq_manager     nm; | ||||
|     small_object_allocator  m_alloc; | ||||
|     bound_propagator        bp; | ||||
|     u_dependency_manager    m_dep_manager; | ||||
|     dep_intervals           m_interval; | ||||
|     ptr_vector<expr>        m_var2expr; | ||||
|     unsigned_vector         m_expr2var; | ||||
|  | @ -105,7 +106,7 @@ public: | |||
|         a(m), | ||||
|         m_rewriter(m), | ||||
|         bp(nm, m_alloc, p), | ||||
|         m_interval(m.limit()), | ||||
|         m_interval(m_dep_manager, m.limit()), | ||||
|         m_trail(m), | ||||
|         m_num_buffer(nm) { | ||||
|         updt_params(p); | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue