diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 7ac026673..694a6d635 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -9,6 +9,8 @@ Version 4.3.2 - Added support for FreeBSD. Z3 can be compiled on FreeBSD using g++. +- Added support for Python 3.x. + - Reverted to `(set-option :global-decls false)` as the default. In Z3 4.3.0 and Z3 4.3.1, this option was set to true. Thanks to Julien Henry for reporting this problem. @@ -26,6 +28,29 @@ Version 4.3.2 - Fixed crash reported at http://z3.codeplex.com/workitem/10 +- Removed auxiliary constants created by the nnf tactic from Z3 models. + +- Fixed problem in the pretty printer. It was not introducing quotes for attribute names such as |foo:10|. + +- Fixed bug when using assumptions (Thanks to Philippe Suter and Etienne Kneuss) + Consider the following example: + (assert F) + (check-sat a) + (check-sat) + If 'F' is unstatisfiable independently of the assumption 'a', and + the inconsistenty can be detected by just performing propagation, + Then, version <= 4.3.1 may return + unsat + sat + instead of + unsat + unsat + We say may because 'F' may have other unsatisfiable cores. + +- Fixed bug reported at http://stackoverflow.com/questions/13923316/unprintable-solver-model + +- Fixed timers on Linux and FreeBSD. + Version 4.3.1 ============= diff --git a/examples/c++/example.cpp b/examples/c++/example.cpp index ab6e67ab9..9e92d99ab 100644 --- a/examples/c++/example.cpp +++ b/examples/c++/example.cpp @@ -812,6 +812,68 @@ void tst_visit() { visit(f); } +void incremental_example1() { + std::cout << "incremental example1\n"; + context c; + expr x = c.int_const("x"); + solver s(c); + s.add(x > 0); + std::cout << s.check() << "\n"; + // We can add more formulas to the solver + s.add(x < 0); + // and, invoke s.check() again... + std::cout << s.check() << "\n"; +} + +void incremental_example2() { + // In this example, we show how push() and pop() can be used + // to remove formulas added to the solver. + std::cout << "incremental example2\n"; + context c; + expr x = c.int_const("x"); + solver s(c); + s.add(x > 0); + std::cout << s.check() << "\n"; + // push() creates a backtracking point (aka a snapshot). + s.push(); + // We can add more formulas to the solver + s.add(x < 0); + // and, invoke s.check() again... + std::cout << s.check() << "\n"; + // pop() will remove all formulas added between this pop() and the matching push() + s.pop(); + // The context is satisfiable again + std::cout << s.check() << "\n"; + // and contains only x > 0 + std::cout << s << "\n"; +} + +void incremental_example3() { + // In this example, we show how to use assumptions to "remove" + // formulas added to a solver. Actually, we disable them. + std::cout << "incremental example3\n"; + context c; + expr x = c.int_const("x"); + solver s(c); + s.add(x > 0); + std::cout << s.check() << "\n"; + // Now, suppose we want to add x < 0 to the solver, but we also want + // to be able to disable it later. + // To do that, we create an auxiliary Boolean variable + expr b = c.bool_const("b"); + // and, assert (b implies x < 0) + s.add(implies(b, x < 0)); + // Now, we check whether s is satisfiable under the assumption "b" is true. + expr_vector a1(c); + a1.push_back(b); + std::cout << s.check(a1) << "\n"; + // To "disable" (x > 0), we may just ask with the assumption "not b" or not provide any assumption. + std::cout << s.check() << "\n"; + expr_vector a2(c); + a2.push_back(!b); + std::cout << s.check(a2) << "\n"; +} + int main() { try { demorgan(); std::cout << "\n"; @@ -842,6 +904,9 @@ int main() { tactic_example9(); std::cout << "\n"; tactic_qe(); std::cout << "\n"; tst_visit(); std::cout << "\n"; + incremental_example1(); std::cout << "\n"; + incremental_example2(); std::cout << "\n"; + incremental_example3(); std::cout << "\n"; std::cout << "done\n"; } catch (exception & ex) { diff --git a/examples/python/example.py b/examples/python/example.py index a8a764a4d..879c17c43 100644 --- a/examples/python/example.py +++ b/examples/python/example.py @@ -4,5 +4,5 @@ x = Real('x') y = Real('y') s = Solver() s.add(x + y > 5, x > 1, y > 1) -print s.check() -print s.model() +print(s.check()) +print(s.model()) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 381f92def..268a6d27b 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -7,11 +7,6 @@ # Author: Leonardo de Moura (leonardo) ############################################ import sys - -if sys.version >= "3": - print "ERROR: python 2.x required." - exit(1) - import os import glob import re @@ -75,6 +70,8 @@ VER_BUILD=None VER_REVISION=None PREFIX='/usr' GMP=False +VS_PAR=False +VS_PAR_NUM=8 def is_windows(): return IS_WINDOWS @@ -132,8 +129,7 @@ def exec_cmd(cmd): first = True for e in cmd: if first: - # Allow spaces in the executable name - first = False + first = False new_cmd.append(e) else: if e != "": @@ -164,7 +160,7 @@ def exec_compiler_cmd(cmd): def test_cxx_compiler(cc): if is_verbose(): - print "Testing %s..." % cc + print("Testing %s..." % cc) t = TempFile('tst.cpp') t.add('#include\nint main() { return 0; }\n') t.commit() @@ -172,7 +168,7 @@ def test_cxx_compiler(cc): def test_c_compiler(cc): if is_verbose(): - print "Testing %s..." % cc + print("Testing %s..." % cc) t = TempFile('tst.c') t.add('#include\nint main() { return 0; }\n') t.commit() @@ -180,7 +176,7 @@ def test_c_compiler(cc): def test_gmp(cc): if is_verbose(): - print "Testing GMP..." + print("Testing GMP...") t = TempFile('tstgmp.cpp') t.add('#include\nint main() { mpz_t t; mpz_init(t); mpz_clear(t); return 0; }\n') t.commit() @@ -188,7 +184,7 @@ def test_gmp(cc): def test_openmp(cc): if is_verbose(): - print "Testing OpenMP..." + print("Testing OpenMP...") t = TempFile('tstomp.cpp') t.add('#include\nint main() { return omp_in_parallel() ? 1 : 0; }\n') t.commit() @@ -199,12 +195,12 @@ def check_java(): t.add('public class Hello { public static void main(String[] args) { System.out.println("Hello, World"); }}\n') t.commit() if is_verbose(): - print "Testing %s..." % JAVAC + print("Testing %s..." % JAVAC) r = exec_cmd([JAVAC, 'Hello.java']) if r != 0: raise MKException('Failed testing Java compiler. Set environment variable JAVAC with the path to the Java compiler') if is_verbose(): - print "Testing %s..." % JAVA + print("Testing %s..." % JAVA) r = exec_cmd([JAVA, 'Hello']) rmf('Hello.class') if r != 0: @@ -222,11 +218,11 @@ def find_java_home(): global JAVA_HOME if JAVA_HOME != None: if is_verbose(): - print "Checking jni.h..." + print("Checking jni.h...") if os.path.exists(os.path.join(JAVA_HOME, 'include', 'jni.h')): return if is_verbose(): - print "Finding JAVA_HOME..." + print("Finding JAVA_HOME...") t = TempFile('output') null = open(os.devnull, 'wb') try: @@ -240,17 +236,17 @@ def find_java_home(): m = open_pat.match(line) if m: # Remove last 3 directives from m.group(1) - print m.group(1) + print(m.group(1)) tmp = m.group(1).split(os.sep) path = string.join(tmp[:len(tmp) - 3], os.sep) if is_verbose(): - print "Checking jni.h..." + print("Checking jni.h...") jni_dir = find_jni_h(path) if not jni_dir: raise MKException("Failed to detect jni.h at '%s'.Possible solution: set JAVA_HOME with the path to JDK." % os.path.join(path, 'include')) JAVA_HOME = os.path.split(jni_dir)[0] if is_verbose(): - print 'JAVA_HOME=%s' % JAVA_HOME + print('JAVA_HOME=%s' % JAVA_HOME) return raise MKException('Failed to find JAVA_HOME') @@ -259,7 +255,7 @@ def is64(): def check_ar(): if is_verbose(): - print "Testing ar..." + print("Testing ar...") if which('ar')== None: raise MKException('ar (archive tool) was not found') @@ -320,7 +316,7 @@ def dos2unix(fname): fout.close() shutil.move(fname_new, fname) if is_verbose(): - print "dos2unix '%s'" % fname + print("dos2unix '%s'" % fname) def dos2unix_tree_core(pattern, dir, files): for filename in files: @@ -337,7 +333,7 @@ def check_eol(): # Linux/OSX/BSD check if the end-of-line is cr/lf if is_cr_lf('LICENSE.txt'): if is_verbose(): - print "Fixing end of line..." + print("Fixing end of line...") dos2unix_tree() if os.name == 'nt': @@ -353,53 +349,55 @@ elif os.name == 'posix': IS_LINUX=True def display_help(exit_code): - print "mk_make.py: Z3 Makefile generator\n" - print "This script generates the Makefile for the Z3 theorem prover." - print "It must be executed from the Z3 root directory." - print "\nOptions:" - print " -h, --help display this message." - print " -s, --silent do not print verbose messages." + print("mk_make.py: Z3 Makefile generator\n") + print("This script generates the Makefile for the Z3 theorem prover.") + print("It must be executed from the Z3 root directory.") + print("\nOptions:") + print(" -h, --help display this message.") + print(" -s, --silent do not print verbose messages.") if not IS_WINDOWS: - print " -p , --prefix= installation prefix (default: %s)." % PREFIX - print " -y , --pydir= installation prefix for Z3 python bindings (default: %s)." % PYTHON_PACKAGE_DIR - print " -b , --build= subdirectory where Z3 will be built (default: build)." - print " -d, --debug compile Z3 in debug mode." - print " -t, --trace enable tracing in release mode." + print(" -p , --prefix= installation prefix (default: %s)." % PREFIX) + print(" -y , --pydir= installation prefix for Z3 python bindings (default: %s)." % PYTHON_PACKAGE_DIR) + else: + print(" --parallel=num use cl option /MP with 'num' parallel processes") + print(" -b , --build= subdirectory where Z3 will be built (default: build).") + print(" -d, --debug compile Z3 in debug mode.") + print(" -t, --trace enable tracing in release mode.") if IS_WINDOWS: - print " -x, --x64 create 64 binary when using Visual Studio." - print " -m, --makefiles generate only makefiles." + print(" -x, --x64 create 64 binary when using Visual Studio.") + print(" -m, --makefiles generate only makefiles.") if IS_WINDOWS: - print " -v, --vsproj generate Visual Studio Project Files." + print(" -v, --vsproj generate Visual Studio Project Files.") if IS_WINDOWS: - print " -n, --nodotnet do not generate Microsoft.Z3.dll make rules." - print " -j, --java generate Java bindinds." - print " --staticlib build Z3 static library." + print(" -n, --nodotnet do not generate Microsoft.Z3.dll make rules.") + print(" -j, --java generate Java bindinds.") + print(" --staticlib build Z3 static library.") if not IS_WINDOWS: - print " -g, --gmp use GMP." - print "" - print "Some influential environment variables:" + print(" -g, --gmp use GMP.") + print("") + print("Some influential environment variables:") if not IS_WINDOWS: - print " CXX C++ compiler" - print " CC C compiler" - print " LDFLAGS Linker flags, e.g., -L if you have libraries in a non-standard directory" - print " CPPFLAGS Preprocessor flags, e.g., -I if you have header files in a non-standard directory" - print " CXXFLAGS C++ compiler flags" - print " JAVA Java virtual machine (only relevant if -j or --java option is provided)" - print " JAVAC Java compiler (only relevant if -j or --java option is provided)" - print " JAVA_HOME JDK installation directory (only relevant if -j or --java option is provided)" + print(" CXX C++ compiler") + print(" CC C compiler") + print(" LDFLAGS Linker flags, e.g., -L if you have libraries in a non-standard directory") + print(" CPPFLAGS Preprocessor flags, e.g., -I if you have header files in a non-standard directory") + print(" CXXFLAGS C++ compiler flags") + print(" JAVA Java virtual machine (only relevant if -j or --java option is provided)") + print(" JAVAC Java compiler (only relevant if -j or --java option is provided)") + print(" JAVA_HOME JDK installation directory (only relevant if -j or --java option is provided)") exit(exit_code) # Parse configuration option for mk_make script def parse_options(): - global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE + global VERBOSE, DEBUG_MODE, IS_WINDOWS, VS_X64, ONLY_MAKEFILES, SHOW_CPPS, VS_PROJ, TRACE, VS_PAR, VS_PAR_NUM global DOTNET_ENABLED, JAVA_ENABLED, STATIC_LIB, PREFIX, GMP, PYTHON_PACKAGE_DIR try: options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:dsxhmcvtnp:gjy:', ['build=', 'debug', 'silent', 'x64', 'help', 'makefiles', 'showcpp', 'vsproj', - 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'java', 'pydir=']) + 'trace', 'nodotnet', 'staticlib', 'prefix=', 'gmp', 'java', 'pydir=', 'parallel=']) except: - print "ERROR: Invalid command line option" + print("ERROR: Invalid command line option") display_help(1) for opt, arg in options: @@ -429,8 +427,11 @@ def parse_options(): DOTNET_ENABLED = False elif opt in ('--staticlib'): STATIC_LIB = True - elif opt in ('-p', '--prefix'): + elif not IS_WINDOWS and opt in ('-p', '--prefix'): PREFIX = arg + elif IS_WINDOWS and opt == '--parallel': + VS_PAR = True + VS_PAR_NUM = int(arg) elif opt in ('-y', '--pydir'): PYTHON_PACKAGE_DIR = arg mk_dir(PYTHON_PACKAGE_DIR) @@ -439,7 +440,7 @@ def parse_options(): elif opt in ('-j', '--java'): JAVA_ENABLED = True else: - print "ERROR: Invalid command line option '%s'" % opt + print("ERROR: Invalid command line option '%s'" % opt) display_help(1) # Return a list containing a file names included using '#include' in @@ -490,7 +491,7 @@ def set_z3py_dir(p): raise MKException("Python bindings directory '%s' does not exist" % full) Z3PY_SRC_DIR = full if VERBOSE: - print "Python bindinds directory was detected." + print("Python bindinds directory was detected.") _UNIQ_ID = 0 @@ -656,8 +657,32 @@ class Component: out.write(' -I%s' % get_component(dep).to_src_dir) out.write('\n') mk_dir(os.path.join(BUILD_DIR, self.build_dir)) - for cppfile in get_cpp_files(self.src_dir): - self.add_cpp_rules(out, include_defs, cppfile) + if VS_PAR and IS_WINDOWS: + cppfiles = get_cpp_files(self.src_dir) + dependencies = set() + for cppfile in cppfiles: + dependencies.add(os.path.join(self.to_src_dir, cppfile)) + self.add_rule_for_each_include(out, cppfile) + includes = extract_c_includes(os.path.join(self.src_dir, cppfile)) + for include in includes: + owner = self.find_file(include, cppfile) + dependencies.add('%s.node' % os.path.join(owner.build_dir, include)) + for cppfile in cppfiles: + out.write('%s$(OBJ_EXT) ' % os.path.join(self.build_dir, os.path.splitext(cppfile)[0])) + out.write(': ') + for dep in dependencies: + out.write(dep) + out.write(' ') + out.write('\n') + out.write('\t@$(CXX) $(CXXFLAGS) /MP%s $(%s)' % (VS_PAR_NUM, include_defs)) + for cppfile in cppfiles: + out.write(' ') + out.write(os.path.join(self.to_src_dir, cppfile)) + out.write('\n') + out.write('\tmove *.obj %s\n' % self.build_dir) + else: + for cppfile in get_cpp_files(self.src_dir): + self.add_cpp_rules(out, include_defs, cppfile) # Return true if the component should be included in the all: rule def main_component(self): @@ -750,7 +775,7 @@ def comp_components(c1, c2): # Sort components based on (reverse) definition time def sort_components(cnames): - return sorted(cnames, cmp=comp_components) + return sorted(cnames, key=lambda c: get_component(c).id, reverse=True) class ExeComponent(Component): def __init__(self, name, exe_name, path, deps, install): @@ -933,10 +958,8 @@ class DLLComponent(Component): mk_dir(os.path.join(dist_path, 'bin')) shutil.copy('%s.dll' % os.path.join(build_path, self.dll_name), '%s.dll' % os.path.join(dist_path, 'bin', self.dll_name)) - if self.static: - mk_dir(os.path.join(dist_path, 'bin')) - shutil.copy('%s.lib' % os.path.join(build_path, self.dll_name), - '%s.lib' % os.path.join(dist_path, 'bin', self.dll_name)) + shutil.copy('%s.lib' % os.path.join(build_path, self.dll_name), + '%s.lib' % os.path.join(dist_path, 'bin', self.dll_name)) class DotNetDLLComponent(Component): def __init__(self, name, dll_name, path, deps, assembly_info_dir): @@ -1042,6 +1065,11 @@ class JavaDLLComponent(Component): def main_component(self): return is_java_enabled() + def mk_win_dist(self, build_path, dist_path): + if JAVA_ENABLED: + mk_dir(os.path.join(dist_path, 'bin')) + shutil.copy('%s.jar' % os.path.join(build_path, self.package_name), + '%s.jar' % os.path.join(dist_path, 'bin', self.package_name)) class ExampleComponent(Component): def __init__(self, name, path): @@ -1162,7 +1190,7 @@ class PythonExampleComponent(ExampleComponent): for py in filter(lambda f: f.endswith('.py'), os.listdir(full)): shutil.copyfile(os.path.join(full, py), os.path.join(BUILD_DIR, py)) if is_verbose(): - print "Copied Z3Py example '%s' to '%s'" % (py, BUILD_DIR) + print("Copied Z3Py example '%s' to '%s'" % (py, BUILD_DIR)) out.write('_ex_%s: \n\n' % self.name) @@ -1174,7 +1202,7 @@ def reg_component(name, c): _ComponentNames.add(name) _Name2Component[name] = c if VERBOSE: - print "New component: '%s'" % name + print("New component: '%s'" % name) def add_lib(name, deps=[], path=None, includes2install=[]): c = LibComponent(name, path, deps, includes2install) @@ -1250,12 +1278,12 @@ def mk_config(): 'SLINK_FLAGS=/nologo /LDd\n') if not VS_X64: config.write( - 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' + 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze- /arch:SSE2\n' 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X86 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') else: config.write( - 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n' + 'CXXFLAGS=/c /Zi /nologo /openmp /W3 /WX- /Od /Oy- /D WIN32 /D _AMD64_ /D _DEBUG /D Z3DEBUG /D _CONSOLE /D _TRACE /D _WINDOWS /Gm- /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /analyze-\n' 'LINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:CONSOLE /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE /NXCOMPAT\n' 'SLINK_EXTRA_FLAGS=/link /DEBUG /MACHINE:X64 /SUBSYSTEM:WINDOWS /INCREMENTAL:NO /STACK:8388608 /OPT:REF /OPT:ICF /TLBID:1 /DYNAMICBASE:NO\n') else: @@ -1281,11 +1309,11 @@ def mk_config(): # End of Windows VS config.mk if is_verbose(): - print '64-bit: %s' % is64() + print('64-bit: %s' % is64()) if is_java_enabled(): - print 'Java Home: %s' % JAVA_HOME - print 'Java Compiler: %s' % JAVAC - print 'Java VM: %s' % JAVA + print('Java Home: %s' % JAVA_HOME) + print('Java Compiler: %s' % JAVAC) + print('Java VM: %s' % JAVA) else: global CXX, CC, GMP, CPPFLAGS, CXXFLAGS, LDFLAGS ARITH = "internal" @@ -1367,17 +1395,17 @@ def mk_config(): config.write('SLINK_EXTRA_FLAGS=%s\n' % SLIBEXTRAFLAGS) config.write('SLINK_OUT_FLAG=-o \n') if is_verbose(): - print 'Host platform: %s' % sysname - print 'C++ Compiler: %s' % CXX - print 'C Compiler : %s' % CC - print 'Arithmetic: %s' % ARITH - print 'OpenMP: %s' % HAS_OMP - print 'Prefix: %s' % PREFIX - print '64-bit: %s' % is64() + print('Host platform: %s' % sysname) + print('C++ Compiler: %s' % CXX) + print('C Compiler : %s' % CC) + print('Arithmetic: %s' % ARITH) + print('OpenMP: %s' % HAS_OMP) + print('Prefix: %s' % PREFIX) + print('64-bit: %s' % is64()) if is_java_enabled(): - print 'Java Home: %s' % JAVA_HOME - print 'Java Compiler: %s' % JAVAC - print 'Java VM: %s' % JAVA + print('Java Home: %s' % JAVA_HOME) + print('Java Compiler: %s' % JAVAC) + print('Java VM: %s' % JAVA) def mk_install(out): out.write('install:\n') @@ -1403,7 +1431,7 @@ def mk_makefile(): mk_dir(BUILD_DIR) mk_config() if VERBOSE: - print "Writing %s" % os.path.join(BUILD_DIR, 'Makefile') + print("Writing %s" % os.path.join(BUILD_DIR, 'Makefile')) out = open(os.path.join(BUILD_DIR, 'Makefile'), 'w') out.write('# Automatically generated file.\n') out.write('include config.mk\n') @@ -1431,24 +1459,24 @@ def mk_makefile(): mk_uninstall(out) # Finalize if VERBOSE: - print "Makefile was successfully generated." + print("Makefile was successfully generated.") if not IS_WINDOWS: - print " python packages dir:", PYTHON_PACKAGE_DIR + print(" python packages dir: %s" % PYTHON_PACKAGE_DIR) if DEBUG_MODE: - print " compilation mode: Debug" + print(" compilation mode: Debug") else: - print " compilation mode: Release" + print(" compilation mode: Release") if IS_WINDOWS: if VS_X64: - print " platform: x64\n" - print "To build Z3, open a [Visual Studio x64 Command Prompt], then" + print(" platform: x64\n") + print("To build Z3, open a [Visual Studio x64 Command Prompt], then") else: - print " platform: x86" - print "To build Z3, open a [Visual Studio Command Prompt], then" - print "type 'cd %s && nmake'\n" % os.path.join(os.getcwd(), BUILD_DIR) - print 'Remark: to open a Visual Studio Command Prompt, go to: "Start > All Programs > Visual Studio > Visual Studio Tools"' + print(" platform: x86") + print("To build Z3, open a [Visual Studio Command Prompt], then") + print("type 'cd %s && nmake'\n" % os.path.join(os.getcwd(), BUILD_DIR)) + print('Remark: to open a Visual Studio Command Prompt, go to: "Start > All Programs > Visual Studio > Visual Studio Tools"') else: - print "Type 'cd %s; make' to build Z3" % BUILD_DIR + print("Type 'cd %s; make' to build Z3" % BUILD_DIR) # Generate automatically generated source code def mk_auto_src(): @@ -1543,7 +1571,7 @@ def def_module_params(module_name, export, params, class_name=None, description= out.write('};\n') out.write('#endif\n') if is_verbose(): - print "Generated '%s'" % hpp + print("Generated '%s'" % hpp) def max_memory_param(): return ('max_memory', UINT, UINT_MAX, 'maximum amount of memory in megabytes') @@ -1557,6 +1585,10 @@ PYG_GLOBALS = { 'UINT' : UINT, 'BOOL' : BOOL, 'DOUBLE' : DOUBLE, 'STRING' : STRI 'max_steps_param' : max_steps_param, 'def_module_params' : def_module_params } +def _execfile(file, globals=globals(), locals=locals()): + with open(file, "r") as fh: + exec(fh.read()+"\n", globals, locals) + # Execute python auxiliary scripts that generate extra code for Z3. def exec_pyg_scripts(): global CURR_PYG @@ -1565,7 +1597,7 @@ def exec_pyg_scripts(): if f.endswith('.pyg'): script = os.path.join(root, f) CURR_PYG = script - execfile(script, PYG_GLOBALS) + _execfile(script, PYG_GLOBALS) # TODO: delete after src/ast/pattern/expr_pattern_match # database.smt ==> database.h @@ -1578,7 +1610,7 @@ def mk_pat_db(): fout.write('"%s\\n"\n' % line.strip('\n')) fout.write(';\n') if VERBOSE: - print "Generated '%s'" % os.path.join(c.src_dir, 'database.h') + print("Generated '%s'" % os.path.join(c.src_dir, 'database.h')) # Update version numbers def update_version(): @@ -1603,7 +1635,7 @@ def mk_version_dot_h(major, minor, build, revision): fout.write('#define Z3_BUILD_NUMBER %s\n' % build) fout.write('#define Z3_REVISION_NUMBER %s\n' % revision) if VERBOSE: - print "Generated '%s'" % os.path.join(c.src_dir, 'version.h') + print("Generated '%s'" % os.path.join(c.src_dir, 'version.h')) # Update version number in AssemblyInfo.cs files def update_all_assembly_infos(major, minor, build, revision): @@ -1652,13 +1684,13 @@ def update_assembly_info_version(assemblyinfo, major, minor, build, revision, is else: fout.write(line) # if VERBOSE: - # print "%s version numbers updated at '%s'" % (num_updates, assemblyinfo) + # print("%s version numbers updated at '%s'" % (num_updates, assemblyinfo)) assert num_updates == 2, "unexpected number of version number updates" fin.close() fout.close() shutil.move(tmp, assemblyinfo) if VERBOSE: - print "Updated '%s'" % assemblyinfo + print("Updated '%s'" % assemblyinfo) ADD_TACTIC_DATA=[] ADD_PROBE_DATA=[] @@ -1700,7 +1732,7 @@ def mk_install_tactic_cpp(cnames, path): added_include = True fout.write('#include"%s"\n' % h_file) try: - exec line.strip('\n ') in globals() + exec(line.strip('\n '), globals()) except: raise MKException("Failed processing ADD_TACTIC command at '%s'\n%s" % (fullname, line)) if probe_pat.match(line): @@ -1708,7 +1740,7 @@ def mk_install_tactic_cpp(cnames, path): added_include = True fout.write('#include"%s"\n' % h_file) try: - exec line.strip('\n ') in globals() + exec(line.strip('\n '), globals()) except: raise MKException("Failed processing ADD_PROBE command at '%s'\n%s" % (fullname, line)) # First pass will just generate the tactic factories @@ -1727,7 +1759,7 @@ def mk_install_tactic_cpp(cnames, path): fout.write(' ADD_PROBE("%s", "%s", %s);\n' % data) fout.write('}\n') if VERBOSE: - print "Generated '%s'" % fullname + print("Generated '%s'" % fullname) def mk_all_install_tactic_cpps(): if not ONLY_MAKEFILES: @@ -1790,7 +1822,7 @@ def mk_mem_initializer_cpp(cnames, path): fout.write('\n') fout.write('}\n') if VERBOSE: - print "Generated '%s'" % fullname + print("Generated '%s'" % fullname) def mk_all_mem_initializer_cpps(): if not ONLY_MAKEFILES: @@ -1847,7 +1879,7 @@ def mk_gparams_register_modules(cnames, path): fout.write('gparams::register_module_descr("%s", "%s");\n' % (mod, descr)) fout.write('}\n') if VERBOSE: - print "Generated '%s'" % fullname + print("Generated '%s'" % fullname) def mk_all_gparams_register_modules(): if not ONLY_MAKEFILES: @@ -1880,7 +1912,7 @@ def mk_def_file(c): i = i + 1 num = num + 1 if VERBOSE: - print "Generated '%s'" % defname + print("Generated '%s'" % defname) def mk_def_files(): if not ONLY_MAKEFILES: @@ -1900,7 +1932,7 @@ def cp_z3pyc_to_build(): shutil.copyfile(os.path.join(Z3PY_SRC_DIR, pyc), os.path.join(BUILD_DIR, pyc)) os.remove(os.path.join(Z3PY_SRC_DIR, pyc)) if is_verbose(): - print "Generated '%s'" % pyc + print("Generated '%s'" % pyc) def mk_bindings(api_files): if not ONLY_MAKEFILES: @@ -1911,12 +1943,12 @@ def mk_bindings(api_files): for api_file in api_files: api_file_path = api.find_file(api_file, api.name) new_api_files.append(os.path.join(api_file_path.src_dir, api_file)) - g = {} + g = globals() g["API_FILES"] = new_api_files if is_java_enabled(): check_java() mk_z3consts_java(api_files) - execfile(os.path.join('scripts', 'update_api.py'), g) # HACK + _execfile(os.path.join('scripts', 'update_api.py'), g) # HACK cp_z3pyc_to_build() # Extract enumeration types from API files, and add python definitions. @@ -1980,7 +2012,8 @@ def mk_z3consts_py(api_files): if m: name = words[1] z3consts.write('# enum %s\n' % name) - for k, i in decls.iteritems(): + for k in decls: + i = decls[k] z3consts.write('%s = %s\n' % (k, i)) z3consts.write('\n') mode = SEARCHING @@ -1994,7 +2027,7 @@ def mk_z3consts_py(api_files): idx = idx + 1 linenum = linenum + 1 if VERBOSE: - print "Generated '%s'" % os.path.join(Z3PY_SRC_DIR, 'z3consts.py') + print("Generated '%s'" % os.path.join(Z3PY_SRC_DIR, 'z3consts.py')) # Extract enumeration types from z3_api.h, and add .Net definitions @@ -2064,7 +2097,8 @@ def mk_z3consts_dotnet(api_files): z3consts.write(' /// %s\n' % name) z3consts.write(' public enum %s {\n' % name) z3consts.write - for k, i in decls.iteritems(): + for k in decls: + i = decls[k] z3consts.write(' %s = %s,\n' % (k, i)) z3consts.write(' }\n\n') mode = SEARCHING @@ -2079,7 +2113,7 @@ def mk_z3consts_dotnet(api_files): linenum = linenum + 1 z3consts.write('}\n'); if VERBOSE: - print "Generated '%s'" % os.path.join(dotnet.src_dir, 'Enumerations.cs') + print("Generated '%s'" % os.path.join(dotnet.src_dir, 'Enumerations.cs')) # Extract enumeration types from z3_api.h, and add Java definitions @@ -2153,7 +2187,8 @@ def mk_z3consts_java(api_files): efile.write('public enum %s {\n' % name) efile.write first = True - for k, i in decls.iteritems(): + for k in decls: + i = decls[k] if first: first = False else: @@ -2184,7 +2219,7 @@ def mk_z3consts_java(api_files): idx = idx + 1 linenum = linenum + 1 if VERBOSE: - print "Generated '%s'" % ('%s' % gendir) + print("Generated '%s'" % ('%s' % gendir)) def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id @@ -2271,7 +2306,7 @@ def mk_vs_proj(name, components): f.write(' \n') f.write('\n') if is_verbose(): - print "Generated '%s'" % proj_name + print("Generated '%s'" % proj_name) def mk_win_dist(build_path, dist_path): for c in get_components(): diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index 57ae66b03..dd50a3977 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -16,13 +16,15 @@ import subprocess import zipfile from mk_exception import * from mk_project import * +import mk_util BUILD_DIR='build-dist' -BUILD_X64_DIR='build-dist/x64' -BUILD_X86_DIR='build-dist/x86' +BUILD_X64_DIR=os.path.join('build-dist', 'x64') +BUILD_X86_DIR=os.path.join('build-dist', 'x86') VERBOSE=True DIST_DIR='dist' FORCE_MK=False +JAVA_ENABLED=True def set_verbose(flag): global VERBOSE @@ -38,8 +40,8 @@ def mk_dir(d): def set_build_dir(path): global BUILD_DIR BUILD_DIR = path - BUILD_X86_DIR = '%s/x86' % path - BUILD_X64_DIR = '%s/x64' % path + BUILD_X86_DIR = os.path.join(path, 'x86') + BUILD_X64_DIR = os.path.join(path, 'x64') mk_dir(BUILD_X86_DIR) mk_dir(BUILD_X64_DIR) @@ -52,16 +54,18 @@ def display_help(): print " -s, --silent do not print verbose messages." print " -b , --build= subdirectory where x86 and x64 Z3 versions will be built (default: build-dist)." print " -f, --force force script to regenerate Makefiles." + print " --nojava do not include Java bindings in the binary distribution files." exit(0) # Parse configuration option for mk_make script def parse_options(): - global FORCE_MK + global FORCE_MK, JAVA_ENABLED path = BUILD_DIR options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:hsf', ['build=', 'help', 'silent', - 'force' + 'force', + 'nojava' ]) for opt, arg in options: if opt in ('-b', '--build'): @@ -74,18 +78,22 @@ def parse_options(): display_help() elif opt in ('-f', '--force'): FORCE_MK = True + elif opt == '--nojava': + JAVA_ENABLED = False else: raise MKException("Invalid command line option '%s'" % opt) set_build_dir(path) # Check whether build directory already exists or not def check_build_dir(path): - return os.path.exists(path) and os.path.exists('%s/Makefile' % path) + return os.path.exists(path) and os.path.exists(os.path.join(path, 'Makefile')) # Create a build directory using mk_make.py def mk_build_dir(path, x64): if not check_build_dir(path) or FORCE_MK: - opts = ["python", "scripts/mk_make.py", "-b", path] + opts = ["python", os.path.join('scripts', 'mk_make.py'), "-b", path] + if JAVA_ENABLED: + opts.append('--java') if x64: opts.append('-x') if subprocess.call(opts) != 0: @@ -147,8 +155,12 @@ def mk_dist_dir_core(x64): else: platform = "x86" build_path = BUILD_X86_DIR - dist_path = '%s/z3-%s.%s.%s-%s' % (DIST_DIR, major, minor, build, platform) + dist_path = os.path.join(DIST_DIR, 'z3-%s.%s.%s-%s' % (major, minor, build, platform)) mk_dir(dist_path) + if JAVA_ENABLED: + # HACK: Propagate JAVA_ENABLED flag to mk_util + # TODO: fix this hack + mk_util.JAVA_ENABLED = JAVA_ENABLED mk_win_dist(build_path, dist_path) if is_verbose(): print "Generated %s distribution folder at '%s'" % (platform, dist_path) @@ -225,7 +237,7 @@ def cp_vs_runtime_core(x64): path = '%sredist\\%s' % (vcdir, platform) VS_RUNTIME_FILES = [] os.path.walk(path, cp_vs_runtime_visitor, '*.dll') - bin_dist_path = '%s/%s/bin' % (DIST_DIR, get_dist_path(x64)) + bin_dist_path = os.path.join(DIST_DIR, get_dist_path(x64), 'bin') for f in VS_RUNTIME_FILES: shutil.copy(f, bin_dist_path) if is_verbose(): @@ -236,8 +248,8 @@ def cp_vs_runtime(): cp_vs_runtime_core(False) def cp_license(): - shutil.copy("LICENSE.txt", "%s/%s" % (DIST_DIR, get_dist_path(True))) - shutil.copy("LICENSE.txt", "%s/%s" % (DIST_DIR, get_dist_path(False))) + shutil.copy("LICENSE.txt", os.path.join(DIST_DIR, get_dist_path(True))) + shutil.copy("LICENSE.txt", os.path.join(DIST_DIR, get_dist_path(False))) # Entry point def main(): diff --git a/scripts/trackall.sh b/scripts/trackall.sh new file mode 100755 index 000000000..d8351af24 --- /dev/null +++ b/scripts/trackall.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# Script for "cloning" (and tracking) all branches at codeplex. +# On Windows, this script must be executed in the "git Bash" console. +for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do + git branch --track ${branch##*/} $branch +done +git fetch --all +git pull --all diff --git a/scripts/update_api.py b/scripts/update_api.py index a636a1a02..08dd012e3 100644 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -84,6 +84,19 @@ def lib(): raise Z3Exception("init(Z3_LIBRARY_PATH) must be invoked before using Z3-python") return _lib +def _to_ascii(s): + if isinstance(s, str): + return s.encode('ascii') + else: + return s + +if sys.version < '3': + def _to_pystr(s): + return s +else: + def _to_pystr(s): + return s.decode('utf-8') + def init(PATH): global _lib _lib = ctypes.CDLL(PATH) @@ -146,20 +159,22 @@ next_type_id = FIRST_OBJ_ID def def_Type(var, c_type, py_type): global next_type_id - exec ('%s = %s' % (var, next_type_id)) in globals() + exec('%s = %s' % (var, next_type_id), globals()) Type2Str[next_type_id] = c_type Type2PyStr[next_type_id] = py_type next_type_id = next_type_id + 1 def def_Types(): - pat1 = re.compile(" *def_Type.*") + import re + pat1 = re.compile(" *def_Type\(\'(.*)\',[^\']*\'(.*)\',[^\']*\'(.*)\'\)[ \t]*") for api_file in API_FILES: api = open(api_file, 'r') for line in api: m = pat1.match(line) if m: - eval(line) - for k, v in Type2Str.iteritems(): + def_Type(m.group(1), m.group(2), m.group(3)) + for k in Type2Str: + v = Type2Str[k] if is_obj(k): Type2Dotnet[k] = v @@ -258,7 +273,7 @@ def param2java(p): elif param_type(p) == STRING: return "StringPtr" else: - print "ERROR: unreachable code" + print("ERROR: unreachable code") assert(False) exit(1) if k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY: @@ -313,6 +328,17 @@ def display_args(num): core_py.write(", ") core_py.write("a%s" % i) +def display_args_to_z3(params): + i = 0 + for p in params: + if i > 0: + core_py.write(", ") + if param_type(p) == STRING: + core_py.write("_to_ascii(a%s)" % i) + else: + core_py.write("a%s" % i) + i = i + 1 + def mk_py_wrappers(): core_py.write("\n") for sig in _API2PY: @@ -327,13 +353,15 @@ def mk_py_wrappers(): core_py.write(" r = lib().%s(" % name) else: core_py.write(" lib().%s(" % name) - display_args(num) + display_args_to_z3(params) core_py.write(")\n") if len(params) > 0 and param_type(params[0]) == CONTEXT: core_py.write(" err = lib().Z3_get_error_code(a0)\n") core_py.write(" if err != Z3_OK:\n") core_py.write(" raise Z3Exception(lib().Z3_get_error_msg_ex(a0, err))\n") - if result != VOID: + if result == STRING: + core_py.write(" return _to_pystr(r)\n") + elif result != VOID: core_py.write(" return r\n") core_py.write("\n") @@ -356,7 +384,8 @@ def mk_dotnet(): dotnet.write('#pragma warning disable 1591\n\n'); dotnet.write('namespace Microsoft.Z3\n') dotnet.write('{\n') - for k, v in Type2Str.iteritems(): + for k in Type2Str: + v = Type2Str[k] if is_obj(k): dotnet.write(' using %s = System.IntPtr;\n' % v) dotnet.write('\n'); @@ -579,7 +608,7 @@ def mk_java(): java_wrapper.write(' } \n\n') java_wrapper.write('#define RELEASELONGAELEMS(OLD,NEW) \\\n') java_wrapper.write(' delete [] NEW; \n\n') - java_wrapper.write('#define GETLONGAREGION(T,OLD,Z,SZ,NEW) \\\n') + java_wrapper.write('#define GETLONGAREGION(T,OLD,Z,SZ,NEW) \\\n') java_wrapper.write(' { \\\n') java_wrapper.write(' jlong * temp = new jlong[SZ]; \\\n') java_wrapper.write(' jenv->GetLongArrayRegion(OLD,Z,(jsize)SZ,(jlong*)temp); \\\n') @@ -702,7 +731,7 @@ def mk_java(): java_wrapper.write('}\n') java_wrapper.write('#endif\n') if is_verbose(): - print "Generated '%s'" % java_nativef + print("Generated '%s'" % java_nativef) def mk_log_header(file, name, params): file.write("void log_%s(" % name) @@ -710,7 +739,7 @@ def mk_log_header(file, name, params): for p in params: if i > 0: file.write(", "); - file.write("%s a%s" % (param2str(p), i)) + file.write("%s a%s" % (param2str(p), i)) i = i + 1 file.write(")"); @@ -981,8 +1010,8 @@ exe_c.close() core_py.close() if is_verbose(): - print "Generated '%s'" % os.path.join(api_dir, 'api_log_macros.h') - print "Generated '%s'" % os.path.join(api_dir, 'api_log_macros.cpp') - print "Generated '%s'" % os.path.join(api_dir, 'api_commands.cpp') - print "Generated '%s'" % os.path.join(get_z3py_dir(), 'z3core.py') - print "Generated '%s'" % os.path.join(dotnet_dir, 'Native.cs') + print("Generated '%s'" % os.path.join(api_dir, 'api_log_macros.h')) + print("Generated '%s'" % os.path.join(api_dir, 'api_log_macros.cpp')) + print("Generated '%s'" % os.path.join(api_dir, 'api_commands.cpp')) + print("Generated '%s'" % os.path.join(get_z3py_dir(), 'z3core.py')) + print("Generated '%s'" % os.path.join(dotnet_dir, 'Native.cs')) diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp index 7dc8d1a12..9ebc771f0 100644 --- a/src/api/api_context.cpp +++ b/src/api/api_context.cpp @@ -106,11 +106,11 @@ namespace api { m_error_handler = &default_error_handler; m_basic_fid = m().get_basic_family_id(); - m_arith_fid = m().get_family_id("arith"); - m_bv_fid = m().get_family_id("bv"); - m_array_fid = m().get_family_id("array"); - m_dt_fid = m().get_family_id("datatype"); - m_datalog_fid = m().get_family_id("datalog_relation"); + m_arith_fid = m().mk_family_id("arith"); + m_bv_fid = m().mk_family_id("bv"); + m_array_fid = m().mk_family_id("array"); + m_dt_fid = m().mk_family_id("datatype"); + m_datalog_fid = m().mk_family_id("datalog_relation"); m_dt_plugin = static_cast(m().get_plugin(m_dt_fid)); if (!m_user_ref_count) { diff --git a/src/api/api_datalog.h b/src/api/api_datalog.h index 1dc0a9cbd..51dbb72ec 100644 --- a/src/api/api_datalog.h +++ b/src/api/api_datalog.h @@ -55,6 +55,7 @@ namespace api { std::string get_last_status(); std::string to_string(unsigned num_queries, expr*const* queries); void cancel() { m_context.cancel(); } + void reset_cancel() { m_context.reset_cancel(); } unsigned get_num_levels(func_decl* pred); expr_ref get_cover_delta(int level, func_decl* pred); diff --git a/src/api/api_parsers.cpp b/src/api/api_parsers.cpp index 69ca1fc81..8f6eb1125 100644 --- a/src/api/api_parsers.cpp +++ b/src/api/api_parsers.cpp @@ -252,42 +252,6 @@ extern "C" { // --------------- // Support for SMTLIB2 - class z3_context_solver : public solver_na2as { - api::context & m_ctx; - smt::kernel & ctx() const { return m_ctx.get_smt_kernel(); } - public: - virtual ~z3_context_solver() {} - z3_context_solver(api::context& c) : m_ctx(c) {} - virtual void init_core(ast_manager & m, symbol const & logic) {} - virtual void collect_statistics(statistics & st) const {} - virtual void reset_core() { ctx().reset(); } - virtual void assert_expr(expr * t) { ctx().assert_expr(t); } - virtual void push_core() { ctx().push(); } - virtual void pop_core(unsigned n) { ctx().pop(n); } - virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) { - return ctx().check(num_assumptions, assumptions); - } - virtual void get_unsat_core(ptr_vector & r) { - unsigned sz = ctx().get_unsat_core_size(); - for (unsigned i = 0; i < sz; i++) - r.push_back(ctx().get_unsat_core_expr(i)); - } - virtual void get_model(model_ref & m) { ctx().get_model(m); } - virtual proof * get_proof() { return ctx().get_proof(); } - virtual std::string reason_unknown() const { return ctx().last_failure_as_string(); } - virtual void get_labels(svector & r) { - buffer tmp; - ctx().get_relevant_labels(0, tmp); - r.append(tmp.size(), tmp.c_ptr()); - } - - // These are controlled by the main API - virtual void set_cancel(bool f) { } - void cancel() { set_cancel(true); } - void reset_cancel() { set_cancel(false); } - virtual void set_progress_callback(progress_callback * callback) {} - }; - Z3_ast parse_smtlib2_stream(bool exec, Z3_context c, std::istream& is, unsigned num_sorts, Z3_symbol const sort_names[], @@ -298,9 +262,6 @@ extern "C" { Z3_TRY; cmd_context ctx(false, &(mk_c(c)->m())); ctx.set_ignore_check(true); - if (exec) { - ctx.set_solver(alloc(z3_context_solver, *mk_c(c))); - } for (unsigned i = 0; i < num_decls; ++i) { ctx.insert(to_symbol(decl_names[i]), to_func_decl(decls[i])); } @@ -353,39 +314,4 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } - - Z3_ast Z3_API Z3_exec_smtlib2_string(Z3_context c, Z3_string str, - unsigned num_sorts, - Z3_symbol sort_names[], - Z3_sort sorts[], - unsigned num_decls, - Z3_symbol decl_names[], - Z3_func_decl decls[]) { - Z3_TRY; - cmd_context ctx(false, &(mk_c(c)->m())); - std::string s(str); - std::istringstream is(s); - // No logging for this one, since it private. - return parse_smtlib2_stream(true, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - Z3_CATCH_RETURN(0); - } - - Z3_ast Z3_API Z3_exec_smtlib2_file(Z3_context c, Z3_string file_name, - unsigned num_sorts, - Z3_symbol sort_names[], - Z3_sort sorts[], - unsigned num_decls, - Z3_symbol decl_names[], - Z3_func_decl decls[]) { - Z3_TRY; - std::ifstream is(file_name); - if (!is) { - SET_ERROR_CODE(Z3_PARSER_ERROR); - return 0; - } - // No logging for this one, since it private. - return parse_smtlib2_stream(true, c, is, num_sorts, sort_names, sorts, num_decls, decl_names, decls); - Z3_CATCH_RETURN(0); - } - }; diff --git a/src/api/api_solver.cpp b/src/api/api_solver.cpp index 89bfd9519..9ace149af 100644 --- a/src/api/api_solver.cpp +++ b/src/api/api_solver.cpp @@ -30,19 +30,20 @@ Revision History: #include"scoped_timer.h" #include"smt_strategic_solver.h" #include"smt_solver.h" +#include"smt_implied_equalities.h" extern "C" { static void init_solver_core(Z3_context c, Z3_solver _s) { - ast_manager & m = mk_c(c)->m(); Z3_solver_ref * s = to_solver(_s); - mk_c(c)->params().init_solver_params(mk_c(c)->m(), *(s->m_solver), s->m_params); - s->m_solver->init(m, s->m_logic); - s->m_initialized = true; + bool proofs_enabled, models_enabled, unsat_core_enabled; + params_ref p = s->m_params; + mk_c(c)->params().get_solver_params(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled); + s->m_solver = (*(s->m_solver_factory))(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled, s->m_logic); } static void init_solver(Z3_context c, Z3_solver s) { - if (!to_solver(s)->m_initialized) + if (to_solver(s)->m_solver.get() == 0) init_solver_core(c, s); } @@ -50,8 +51,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_simple_solver(c); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref); - s->m_solver = mk_smt_solver(); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_smt_solver_factory()); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -62,8 +62,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_solver(c); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref); - s->m_solver = mk_smt_strategic_solver(); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_smt_strategic_solver_factory()); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -74,8 +73,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_solver_for_logic(c, logic); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref, to_symbol(logic)); - s->m_solver = mk_smt_strategic_solver(true /* force solver to use tactics even when auto_config is disabled */); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_smt_strategic_solver_factory(to_symbol(logic))); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -86,8 +84,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_solver_from_tactic(c, t); RESET_ERROR_CODE(); - Z3_solver_ref * s = alloc(Z3_solver_ref); - s->m_solver = alloc(tactic2solver, to_tactic_ref(t)); + Z3_solver_ref * s = alloc(Z3_solver_ref, mk_tactic2solver_factory(to_tactic_ref(t))); mk_c(c)->save_object(s); Z3_solver r = of_solver(s); RETURN_Z3(r); @@ -100,7 +97,12 @@ extern "C" { RESET_ERROR_CODE(); std::ostringstream buffer; param_descrs descrs; + bool initialized = to_solver(s)->m_solver.get() != 0; + if (!initialized) + init_solver(c, s); to_solver_ref(s)->collect_param_descrs(descrs); + if (!initialized) + to_solver(s)->m_solver = 0; descrs.display(buffer); return mk_c(c)->mk_external_string(buffer.str()); Z3_CATCH_RETURN(""); @@ -112,7 +114,12 @@ extern "C" { RESET_ERROR_CODE(); Z3_param_descrs_ref * d = alloc(Z3_param_descrs_ref); mk_c(c)->save_object(d); + bool initialized = to_solver(s)->m_solver.get() != 0; + if (!initialized) + init_solver(c, s); to_solver_ref(s)->collect_param_descrs(d->m_descrs); + if (!initialized) + to_solver(s)->m_solver = 0; Z3_param_descrs r = of_param_descrs(d); RETURN_Z3(r); Z3_CATCH_RETURN(0); @@ -122,7 +129,7 @@ extern "C" { Z3_TRY; LOG_Z3_solver_set_params(c, s, p); RESET_ERROR_CODE(); - if (to_solver(s)->m_initialized) { + if (to_solver(s)->m_solver) { bool old_model = to_solver(s)->m_params.get_bool("model", true); bool new_model = to_param_ref(p).get_bool("model", true); if (old_model != new_model) @@ -176,8 +183,7 @@ extern "C" { Z3_TRY; LOG_Z3_solver_reset(c, s); RESET_ERROR_CODE(); - to_solver_ref(s)->reset(); - to_solver(s)->m_initialized = false; + to_solver(s)->m_solver = 0; Z3_CATCH; } @@ -352,4 +358,22 @@ extern "C" { return mk_c(c)->mk_external_string(buffer.str()); Z3_CATCH_RETURN(""); } + + + Z3_lbool Z3_API Z3_get_implied_equalities(Z3_context c, + Z3_solver s, + unsigned num_terms, + Z3_ast const terms[], + unsigned class_ids[]) { + Z3_TRY; + LOG_Z3_get_implied_equalities(c, s, num_terms, terms, class_ids); + ast_manager& m = mk_c(c)->m(); + RESET_ERROR_CODE(); + CHECK_SEARCHING(c); + init_solver(c, s); + lbool result = smt::implied_equalities(m, *to_solver_ref(s), num_terms, to_exprs(terms), class_ids); + return static_cast(result); + Z3_CATCH_RETURN(Z3_L_UNDEF); + } + }; diff --git a/src/api/api_solver.h b/src/api/api_solver.h index 1569ef0da..f11c9bfd8 100644 --- a/src/api/api_solver.h +++ b/src/api/api_solver.h @@ -22,17 +22,16 @@ Revision History: #include"solver.h" struct Z3_solver_ref : public api::object { - solver * m_solver; - params_ref m_params; - bool m_initialized; - symbol m_logic; - Z3_solver_ref():m_solver(0), m_initialized(false), m_logic(symbol::null) {} - Z3_solver_ref(symbol const & logic):m_solver(0), m_initialized(false), m_logic(logic) {} - virtual ~Z3_solver_ref() { dealloc(m_solver); } + scoped_ptr m_solver_factory; + ref m_solver; + params_ref m_params; + symbol m_logic; + Z3_solver_ref(solver_factory * f):m_solver_factory(f), m_solver(0), m_logic(symbol::null) {} + virtual ~Z3_solver_ref() {} }; inline Z3_solver_ref * to_solver(Z3_solver s) { return reinterpret_cast(s); } inline Z3_solver of_solver(Z3_solver_ref * s) { return reinterpret_cast(s); } -inline solver * to_solver_ref(Z3_solver s) { return to_solver(s)->m_solver; } +inline solver * to_solver_ref(Z3_solver s) { return to_solver(s)->m_solver.get(); } #endif diff --git a/src/api/api_solver_old.cpp b/src/api/api_solver_old.cpp index cd4b797e3..c89f89873 100644 --- a/src/api/api_solver_old.cpp +++ b/src/api/api_solver_old.cpp @@ -22,7 +22,6 @@ Revision History: #include"api_log_macros.h" #include"api_context.h" #include"api_model.h" -#include"smt_implied_equalities.h" #include"cancel_eh.h" extern "C" { @@ -112,19 +111,6 @@ extern "C" { Z3_CATCH_RETURN(Z3_L_UNDEF); } - Z3_lbool Z3_API Z3_get_implied_equalities(Z3_context c, - unsigned num_terms, - Z3_ast const terms[], - unsigned class_ids[]) { - Z3_TRY; - LOG_Z3_get_implied_equalities(c, num_terms, terms, class_ids); - RESET_ERROR_CODE(); - CHECK_SEARCHING(c); - lbool result = smt::implied_equalities(mk_c(c)->get_smt_kernel(), num_terms, to_exprs(terms), class_ids); - return static_cast(result); - Z3_CATCH_RETURN(Z3_L_UNDEF); - } - Z3_lbool Z3_API Z3_check_assumptions(Z3_context c, unsigned num_assumptions, Z3_ast const assumptions[], diff --git a/src/api/ml/Makefile.build b/src/api/ml/Makefile.build index 27c798bbf..0a737e356 100644 --- a/src/api/ml/Makefile.build +++ b/src/api/ml/Makefile.build @@ -13,7 +13,7 @@ XCDBG=-g $(CFLAGS) XCOPT=-ccopt -Ox -ccopt -Oy- $(CFLAGS) # ole32 is needed by camlidl (COM support) XLIB=-cclib ole32.lib -AR=lib /nologo /LIBPATH:../../build ../../z3.lib /out: +AR=lib /nologo /LIBPATH:../../build ../../libz3.lib /out: O=obj A=lib else diff --git a/src/api/ml/README-linux b/src/api/ml/README-linux index a726c0c94..5ee20bb27 100644 --- a/src/api/ml/README-linux +++ b/src/api/ml/README-linux @@ -1,22 +1,22 @@ -The OCaml API for Z3 was tested using OCaml 3.12.1. -You also need CamlIDL to be able to generate the OCaml API. - -- To download OCaml: - http://caml.inria.fr/ocaml/ - -- To download CamlIDL: - http://forge.ocamlcore.org/projects/camlidl/ - -- To build the OCaml API for Z3: - ./build-lib.sh - -Remark: The OCaml and C compiler tool chains must be configured in your environment. - -Remark: Building the OCaml API copies some pathnames into files, -so the OCaml API must be recompiled if the Z3 library files are moved. - -See ../examples/ocaml/build-test.sh for an example of how to compile and link with Z3. - -Acknowledgements: -The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg. -Many thanks to them! +The OCaml API for Z3 was tested using OCaml 3.12.1. +You also need CamlIDL to be able to generate the OCaml API. + +- To download OCaml: + http://caml.inria.fr/ocaml/ + +- To download CamlIDL: + http://forge.ocamlcore.org/projects/camlidl/ + +- To build the OCaml API for Z3: + ./build-lib.sh + +Remark: The OCaml and C compiler tool chains must be configured in your environment. + +Remark: Building the OCaml API copies some pathnames into files, +so the OCaml API must be recompiled if the Z3 library files are moved. + +See ../examples/ocaml/build-test.sh for an example of how to compile and link with Z3. + +Acknowledgements: +The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg. +Many thanks to them! diff --git a/src/api/ml/README-osx b/src/api/ml/README-osx index a726c0c94..5ee20bb27 100644 --- a/src/api/ml/README-osx +++ b/src/api/ml/README-osx @@ -1,22 +1,22 @@ -The OCaml API for Z3 was tested using OCaml 3.12.1. -You also need CamlIDL to be able to generate the OCaml API. - -- To download OCaml: - http://caml.inria.fr/ocaml/ - -- To download CamlIDL: - http://forge.ocamlcore.org/projects/camlidl/ - -- To build the OCaml API for Z3: - ./build-lib.sh - -Remark: The OCaml and C compiler tool chains must be configured in your environment. - -Remark: Building the OCaml API copies some pathnames into files, -so the OCaml API must be recompiled if the Z3 library files are moved. - -See ../examples/ocaml/build-test.sh for an example of how to compile and link with Z3. - -Acknowledgements: -The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg. -Many thanks to them! +The OCaml API for Z3 was tested using OCaml 3.12.1. +You also need CamlIDL to be able to generate the OCaml API. + +- To download OCaml: + http://caml.inria.fr/ocaml/ + +- To download CamlIDL: + http://forge.ocamlcore.org/projects/camlidl/ + +- To build the OCaml API for Z3: + ./build-lib.sh + +Remark: The OCaml and C compiler tool chains must be configured in your environment. + +Remark: Building the OCaml API copies some pathnames into files, +so the OCaml API must be recompiled if the Z3 library files are moved. + +See ../examples/ocaml/build-test.sh for an example of how to compile and link with Z3. + +Acknowledgements: +The OCaml interface for Z3 was written by Josh Berdine and Jakob Lichtenberg. +Many thanks to them! diff --git a/src/api/ml/README-test-linux b/src/api/ml/README-test-linux index 34900883d..fc15fb2a2 100644 --- a/src/api/ml/README-test-linux +++ b/src/api/ml/README-test-linux @@ -1,17 +1,17 @@ -This directory contains scripts to build the test application using -OCaml. You also need CamlIDL to be able to generate the OCaml API. - -- To download OCaml: - http://caml.inria.fr/ocaml/ - -- To download CamlIDL: - http://forge.ocamlcore.org/projects/camlidl/ - -- One must build the OCaml library before compiling the example. - Go to directory ../ocaml - -- Use 'build-test.sh' to build the test application using the OCaml compiler. - -Remark: The OCaml and C compiler tool chains must be configured in your environment. - -- Use 'exec.sh' to execute test_mlapi. The script sets LD_LIBRARY_PATH, and invokes test_mlapi. +This directory contains scripts to build the test application using +OCaml. You also need CamlIDL to be able to generate the OCaml API. + +- To download OCaml: + http://caml.inria.fr/ocaml/ + +- To download CamlIDL: + http://forge.ocamlcore.org/projects/camlidl/ + +- One must build the OCaml library before compiling the example. + Go to directory ../ocaml + +- Use 'build-test.sh' to build the test application using the OCaml compiler. + +Remark: The OCaml and C compiler tool chains must be configured in your environment. + +- Use 'exec.sh' to execute test_mlapi. The script sets LD_LIBRARY_PATH, and invokes test_mlapi. diff --git a/src/api/ml/README-test-osx b/src/api/ml/README-test-osx index bfc6b115e..3a20d1f1d 100644 --- a/src/api/ml/README-test-osx +++ b/src/api/ml/README-test-osx @@ -1,17 +1,17 @@ -This directory contains scripts to build the test application using -OCaml. You also need CamlIDL to be able to generate the OCaml API. - -- To download OCaml: - http://caml.inria.fr/ocaml/ - -- To download CamlIDL: - http://forge.ocamlcore.org/projects/camlidl/ - -- One must build the OCaml library before compiling the example. - Go to directory ../ocaml - -- Use 'build-test.sh' to build the test application using the OCaml compiler. - -Remark: The OCaml and C compiler tool chains must be configured in your environment. - -- Use 'exec.sh' to execute test_mlapi. The script sets DYLD_LIBRARY_PATH, and invokes test_mlapi. +This directory contains scripts to build the test application using +OCaml. You also need CamlIDL to be able to generate the OCaml API. + +- To download OCaml: + http://caml.inria.fr/ocaml/ + +- To download CamlIDL: + http://forge.ocamlcore.org/projects/camlidl/ + +- One must build the OCaml library before compiling the example. + Go to directory ../ocaml + +- Use 'build-test.sh' to build the test application using the OCaml compiler. + +Remark: The OCaml and C compiler tool chains must be configured in your environment. + +- Use 'exec.sh' to execute test_mlapi. The script sets DYLD_LIBRARY_PATH, and invokes test_mlapi. diff --git a/src/api/ml/exec.sh b/src/api/ml/exec.sh index a1d3c8e49..573ec6ddf 100644 --- a/src/api/ml/exec.sh +++ b/src/api/ml/exec.sh @@ -1,4 +1,4 @@ -#!/bin/sh -export LD_LIBRARY_PATH=../../lib:$LD_LIBRARY_PATH # for linux -export DYLD_LIBRARY_PATH=../../lib:$DYLD_LIBRARY_PATH # for osx -./test_mlapi +#!/bin/sh +export LD_LIBRARY_PATH=../../lib:$LD_LIBRARY_PATH # for linux +export DYLD_LIBRARY_PATH=../../lib:$DYLD_LIBRARY_PATH # for osx +./test_mlapi diff --git a/src/api/ml/z3.ml b/src/api/ml/z3.ml index 7498a0d46..abedaeef8 100644 --- a/src/api/ml/z3.ml +++ b/src/api/ml/z3.ml @@ -229,16 +229,6 @@ and param_kind = | PK_OTHER | PK_INVALID -and search_failure = - | NO_FAILURE - | UNKNOWN - | TIMEOUT - | MEMOUT_WATERMARK - | CANCELED - | NUM_CONFLICTS - | THEORY - | QUANTIFIERS - and ast_print_mode = | PRINT_SMTLIB_FULL | PRINT_LOW_LEVEL @@ -1596,6 +1586,9 @@ external stats_get_uint_value : context -> stats -> int -> int external stats_get_double_value : context -> stats -> int -> float = "camlidl_z3_Z3_stats_get_double_value" +external get_implied_equalities : context -> solver -> ast array -> lbool * int array + = "camlidl_z3_Z3_get_implied_equalities" + (* Internal auxiliary functions: *) @@ -3027,9 +3020,6 @@ external check : context -> lbool external check_assumptions : context -> ast array -> int -> ast array -> lbool * model * ast * int * ast array = "camlidl_z3V3_Z3_check_assumptions" -external get_implied_equalities : context -> ast array -> lbool * int array - = "camlidl_z3V3_Z3_get_implied_equalities" - external del_model : context -> model -> unit = "camlidl_z3V3_Z3_del_model" diff --git a/src/api/ml/z3.mli b/src/api/ml/z3.mli index 905716035..cf3c3d6c2 100644 --- a/src/api/ml/z3.mli +++ b/src/api/ml/z3.mli @@ -229,16 +229,6 @@ and param_kind = | PK_OTHER | PK_INVALID -and search_failure = - | NO_FAILURE - | UNKNOWN - | TIMEOUT - | MEMOUT_WATERMARK - | CANCELED - | NUM_CONFLICTS - | THEORY - | QUANTIFIERS - and ast_print_mode = | PRINT_SMTLIB_FULL | PRINT_LOW_LEVEL @@ -1013,37 +1003,22 @@ and goal_prec = - PK_INVALID invalid parameter. *) (** - {!search_failure} - The different kinds of search failure types. - - - NO_FAILURE: The last search was successful - - UNKNOWN: Undocumented failure reason - - TIMEOUT: Timeout - - MEMOUT_WATERMAK: Search hit a memory high-watermak limit - - CANCELED: External cancel flag was set - - NUM_CONFLICTS: Maximum number of conflicts was reached - - THEORY: Theory is incomplete - - QUANTIFIERS: Logical context contains universal quantifiers -*) -(** - {!ast_print_mode} + {!ast_print_mode} Z3 pretty printing modes (See {!set_ast_print_mode}). - - - PRINT_SMTLIB_FULL: Print AST nodes in SMTLIB verbose format. - - PRINT_LOW_LEVEL: Print AST nodes using a low-level format. + - PRINT_SMTLIB_FULL: Print AST nodes in SMTLIB verbose format. + - PRINT_LOW_LEVEL: Print AST nodes using a low-level format. - PRINT_SMTLIB_COMPLIANT: Print AST nodes in SMTLIB 1.x compliant format. - PRINT_SMTLIB2_COMPLIANT: Print AST nodes in SMTLIB 2.x compliant format. *) (** - {!error_code} - Z3 error codes - - - OK: No error. - - SORT_ERROR: User tried to build an invalid (type incorrect) AST. - - IOB: Index out of bounds. - - INVALID_ARG: Invalid argument was provided. - - PARSER_ERROR: An error occurred when parsing a string or file. - - NO_PARSER: Parser output is not available, that is, user didn't invoke {!parse_smtlib_string} or {!parse_smtlib_file}. + {!error_code} + Z3 error codes + - OK: No error. + - SORT_ERROR: User tried to build an invalid (type incorrect) AST. + - IOB: Index out of bounds. + - INVALID_ARG: Invalid argument was provided. + - PARSER_ERROR: An error occurred when parsing a string or file. + - NO_PARSER: Parser output is not available, that is, user didn't invoke {!parse_smtlib_string} or {!parse_smtlib_file}. - INVALID_PATTERN: Invalid pattern was used to build a quantifier. - MEMOUT_FAIL: A memory allocation failure was encountered. - FILE_ACCESS_ERRROR: A file could not be accessed. @@ -1054,17 +1029,16 @@ and goal_prec = *) (** Definitions for update_api.py - - def_Type('CONFIG', 'config', 'Config') - def_Type('CONTEXT', 'context', 'ContextObj') - def_Type('AST', 'ast', 'Ast') - def_Type('APP', 'app', 'Ast') - def_Type('SORT', 'sort', 'Sort') - def_Type('FUNC_DECL', 'func_decl', 'FuncDecl') - def_Type('PATTERN', 'pattern', 'Pattern') - def_Type('MODEL', 'model', 'Model') - def_Type('LITERALS', 'literals', 'Literals') - def_Type('CONSTRUCTOR', 'constructor', 'Constructor') + def_Type('CONFIG', 'config', 'Config') + def_Type('CONTEXT', 'context', 'ContextObj') + def_Type('AST', 'ast', 'Ast') + def_Type('APP', 'app', 'Ast') + def_Type('SORT', 'sort', 'Sort') + def_Type('FUNC_DECL', 'func_decl', 'FuncDecl') + def_Type('PATTERN', 'pattern', 'Pattern') + def_Type('MODEL', 'model', 'Model') + def_Type('LITERALS', 'literals', 'Literals') + def_Type('CONSTRUCTOR', 'constructor', 'Constructor') def_Type('CONSTRUCTOR_LIST', 'constructor_list', 'ConstructorList') def_Type('THEORY', 'theory', 'ctypes.c_void_p') def_Type('THEORY_DATA', 'theory_data', 'ctypes.c_void_p') @@ -6050,6 +6024,30 @@ external stats_get_uint_value : context -> stats -> int -> int external stats_get_double_value : context -> stats -> int -> float = "camlidl_z3_Z3_stats_get_double_value" +(** + {2 {L Deprecated Constraints API}} +*) +(** + Summary: Retrieve congruence class representatives for terms. + The function can be used for relying on Z3 to identify equal terms under the current + set of assumptions. The array of terms and array of class identifiers should have + the same length. The class identifiers are numerals that are assigned to the same + value for their corresponding terms if the current context forces the terms to be + equal. You cannot deduce that terms corresponding to different numerals must be all different, + (especially when using non-convex theories). + All implied equalities are returned by this call. + This means that two terms map to the same class identifier if and only if + the current context implies that they are equal. + A side-effect of the function is a satisfiability check on the assertions on the solver that is passed in. + The function return L_FALSE if the current assertions are not satisfiable. + - {b See also}: {!check_and_get_model} + - {b See also}: {!check} + @deprecated To be moved outside of API. + def_API('get_implied_equalities', UINT, (_in(CONTEXT), _in(SOLVER), _in(UINT), _in_array(2, AST), _out_array(2, UINT))) +*) +external get_implied_equalities : context -> solver -> ast array -> lbool * int array + = "camlidl_z3_Z3_get_implied_equalities" + (** {2 {L Legacy V3 API}} @@ -10595,32 +10593,6 @@ external check : context -> lbool external check_assumptions : context -> ast array -> int -> ast array -> lbool * model * ast * int * ast array = "camlidl_z3V3_Z3_check_assumptions" -(** - Summary: Retrieve congruence class representatives for terms. - - The function can be used for relying on Z3 to identify equal terms under the current - set of assumptions. The array of terms and array of class identifiers should have - the same length. The class identifiers are numerals that are assigned to the same - value for their corresponding terms if the current context forces the terms to be - equal. You cannot deduce that terms corresponding to different numerals must be all different, - (especially when using non-convex theories). - All implied equalities are returned by this call. - This means that two terms map to the same class identifier if and only if - the current context implies that they are equal. - - A side-effect of the function is a satisfiability check. - The function return L_FALSE if the current assertions are not satisfiable. - - - {b See also}: {!check_and_get_model} - - {b See also}: {!check} - - @deprecated Subsumed by solver API - - def_API('get_implied_equalities', UINT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _out_array(1, UINT))) -*) -external get_implied_equalities : context -> ast array -> lbool * int array - = "camlidl_z3V3_Z3_get_implied_equalities" - (** Summary: Delete a model object. diff --git a/src/api/ml/z3_stubs.c b/src/api/ml/z3_stubs.c index dcc434196..6286e94c7 100644 --- a/src/api/ml/z3_stubs.c +++ b/src/api/ml/z3_stubs.c @@ -605,30 +605,7 @@ value _v1; return _v1; } -int camlidl_transl_table_z3_enum_8[8] = { - Z3_NO_FAILURE, - Z3_UNKNOWN, - Z3_TIMEOUT, - Z3_MEMOUT_WATERMARK, - Z3_CANCELED, - Z3_NUM_CONFLICTS, - Z3_THEORY, - Z3_QUANTIFIERS, -}; - -void camlidl_ml2c_z3_Z3_search_failure(value _v1, Z3_search_failure * _c2, camlidl_ctx _ctx) -{ - (*_c2) = camlidl_transl_table_z3_enum_8[Int_val(_v1)]; -} - -value camlidl_c2ml_z3_Z3_search_failure(Z3_search_failure * _c2, camlidl_ctx _ctx) -{ -value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_8, 8, "typedef Z3_search_failure: bad enum value"); - return _v1; -} - -int camlidl_transl_table_z3_enum_9[4] = { +int camlidl_transl_table_z3_enum_8[4] = { Z3_PRINT_SMTLIB_FULL, Z3_PRINT_LOW_LEVEL, Z3_PRINT_SMTLIB_COMPLIANT, @@ -637,7 +614,7 @@ int camlidl_transl_table_z3_enum_9[4] = { void camlidl_ml2c_z3_Z3_ast_print_mode(value _v1, Z3_ast_print_mode * _c2, camlidl_ctx _ctx) { - (*_c2) = camlidl_transl_table_z3_enum_9[Int_val(_v1)]; + (*_c2) = camlidl_transl_table_z3_enum_8[Int_val(_v1)]; } value camlidl_c2ml_z3_Z3_ast_print_mode(Z3_ast_print_mode * _c2, camlidl_ctx _ctx) @@ -653,7 +630,7 @@ value _v1; return _v1; } -int camlidl_transl_table_z3_enum_10[13] = { +int camlidl_transl_table_z3_enum_9[13] = { Z3_OK, Z3_SORT_ERROR, Z3_IOB, @@ -671,13 +648,13 @@ int camlidl_transl_table_z3_enum_10[13] = { void camlidl_ml2c_z3_Z3_error_code(value _v1, Z3_error_code * _c2, camlidl_ctx _ctx) { - (*_c2) = camlidl_transl_table_z3_enum_10[Int_val(_v1)]; + (*_c2) = camlidl_transl_table_z3_enum_9[Int_val(_v1)]; } value camlidl_c2ml_z3_Z3_error_code(Z3_error_code * _c2, camlidl_ctx _ctx) { value _v1; - _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_10, 13, "typedef Z3_error_code: bad enum value"); + _v1 = camlidl_find_enum((*_c2), camlidl_transl_table_z3_enum_9, 13, "typedef Z3_error_code: bad enum value"); return _v1; } @@ -707,7 +684,7 @@ void check_error_code (Z3_context c) void* error_handler_static = NULL; -int camlidl_transl_table_z3_enum_11[4] = { +int camlidl_transl_table_z3_enum_10[4] = { Z3_GOAL_PRECISE, Z3_GOAL_UNDER, Z3_GOAL_OVER, @@ -716,7 +693,7 @@ int camlidl_transl_table_z3_enum_11[4] = { void camlidl_ml2c_z3_Z3_goal_prec(value _v1, Z3_goal_prec * _c2, camlidl_ctx _ctx) { - (*_c2) = camlidl_transl_table_z3_enum_11[Int_val(_v1)]; + (*_c2) = camlidl_transl_table_z3_enum_10[Int_val(_v1)]; } value camlidl_c2ml_z3_Z3_goal_prec(Z3_goal_prec * _c2, camlidl_ctx _ctx) @@ -11072,7 +11049,56 @@ check_error_code(c); return _vres; } -void caml_z3_error_handler(Z3_context c, Z3_error_code e) { static char buffer[128]; char * msg = Z3_get_error_msg_ex(c, e); if (strlen(msg) > 100) { failwith("Z3: error message is too big to fit in buffer"); } else { sprintf(buffer, "Z3: %s", msg); failwith(buffer); } } +value camlidl_z3_Z3_get_implied_equalities( + value _v_c, + value _v_s, + value _v_terms) +{ + Z3_context c; /*in*/ + Z3_solver s; /*in*/ + unsigned int num_terms; /*in*/ + Z3_ast const *terms; /*in*/ + unsigned int *class_ids; /*out*/ + Z3_lbool _res; + struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; + camlidl_ctx _ctx = &_ctxs; + mlsize_t _c1; + mlsize_t _c2; + value _v3; + mlsize_t _c4; + value _v5; + value _vresult; + value _vres[2] = { 0, 0, }; + + camlidl_ml2c_z3_Z3_context(_v_c, &c, _ctx); + camlidl_ml2c_z3_Z3_solver(_v_s, &s, _ctx); + _c1 = Wosize_val(_v_terms); + terms = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); + for (_c2 = 0; _c2 < _c1; _c2++) { + _v3 = Field(_v_terms, _c2); + camlidl_ml2c_z3_Z3_ast(_v3, &terms[_c2], _ctx); + } + num_terms = _c1; + class_ids = camlidl_malloc(num_terms * sizeof(unsigned int ), _ctx); + _res = Z3_get_implied_equalities(c, s, num_terms, terms, class_ids); + Begin_roots_block(_vres, 2) + _vres[0] = camlidl_c2ml_z3_Z3_lbool(&_res, _ctx); + _vres[1] = camlidl_alloc(num_terms, 0); + for (_c4 = 0; _c4 < num_terms; _c4++) { + _v5 = Val_int(class_ids[_c4]); + modify(&Field(_vres[1], _c4), _v5); + } + _vresult = camlidl_alloc_small(2, 0); + Field(_vresult, 0) = _vres[0]; + Field(_vresult, 1) = _vres[1]; + End_roots() + camlidl_free(_ctx); + /* begin user-supplied deallocation sequence */ +check_error_code(c); + /* end user-supplied deallocation sequence */ + return _vresult; +} + void camlidl_ml2c_z3V3_Z3_symbol(value _v1, Z3_symbol * _c2, camlidl_ctx _ctx) { *_c2 = *((Z3_symbol *) Bp_val(_v1)); @@ -18250,50 +18276,6 @@ value camlidl_z3V3_Z3_check_assumptions( return _vresult; } -value camlidl_z3V3_Z3_get_implied_equalities( - value _v_c, - value _v_terms) -{ - Z3_context c; /*in*/ - unsigned int num_terms; /*in*/ - Z3_ast const *terms; /*in*/ - unsigned int *class_ids; /*out*/ - Z3_lbool _res; - struct camlidl_ctx_struct _ctxs = { CAMLIDL_TRANSIENT, NULL }; - camlidl_ctx _ctx = &_ctxs; - mlsize_t _c1; - mlsize_t _c2; - value _v3; - mlsize_t _c4; - value _v5; - value _vresult; - value _vres[2] = { 0, 0, }; - - camlidl_ml2c_z3V3_Z3_context(_v_c, &c, _ctx); - _c1 = Wosize_val(_v_terms); - terms = camlidl_malloc(_c1 * sizeof(Z3_ast const ), _ctx); - for (_c2 = 0; _c2 < _c1; _c2++) { - _v3 = Field(_v_terms, _c2); - camlidl_ml2c_z3V3_Z3_ast(_v3, &terms[_c2], _ctx); - } - num_terms = _c1; - class_ids = camlidl_malloc(num_terms * sizeof(unsigned int ), _ctx); - _res = Z3_get_implied_equalities(c, num_terms, terms, class_ids); - Begin_roots_block(_vres, 2) - _vres[0] = camlidl_c2ml_z3V3_Z3_lbool(&_res, _ctx); - _vres[1] = camlidl_alloc(num_terms, 0); - for (_c4 = 0; _c4 < num_terms; _c4++) { - _v5 = Val_int(class_ids[_c4]); - modify(&Field(_vres[1], _c4), _v5); - } - _vresult = camlidl_alloc_small(2, 0); - Field(_vresult, 0) = _vres[0]; - Field(_vresult, 1) = _vres[1]; - End_roots() - camlidl_free(_ctx); - return _vresult; -} - value camlidl_z3V3_Z3_del_model( value _v_c, value _v_m) diff --git a/src/api/python/z3.py b/src/api/python/z3.py index 924ac0ea5..9b1d5f1f0 100644 --- a/src/api/python/z3.py +++ b/src/api/python/z3.py @@ -37,15 +37,23 @@ Z3 exceptions: ... # the expression x + y is type incorrect ... n = x + y ... except Z3Exception as ex: -... print "failed:", ex +... print("failed: %s" % ex) failed: 'sort mismatch' """ from z3core import * from z3types import * from z3consts import * from z3printer import * +import sys import io +if sys.version < '3': + def _is_int(v): + return isinstance(v, int) or isinstance(v, long) +else: + def _is_int(v): + return isinstance(v, int) + def enable_trace(msg): Z3_enable_trace(msg) @@ -102,12 +110,12 @@ _error_handler_fptr = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.c_uint) # list of arguments. def _get_args(args): try: - if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)): - return args[0] - else: - return args + if len(args) == 1 and (isinstance(args[0], tuple) or isinstance(args[0], list)): + return args[0] + else: + return args except: # len is not necessarily defined when args is not a sequence (use reflection?) - return args + return args def _Z3python_error_handler_core(c, e): # Do nothing error handler, just avoid exit(0) @@ -140,7 +148,8 @@ class Context: if __debug__: _z3_assert(len(args) % 2 == 0, "Argument list must have an even number of elements.") conf = Z3_mk_config() - for key, value in kws.iteritems(): + for key in kws: + value = kws[key] Z3_set_param_value(conf, str(key).upper(), _to_param_value(value)) prev = None for a in args: @@ -209,10 +218,12 @@ def set_param(*args, **kws): if __debug__: _z3_assert(len(args) % 2 == 0, "Argument list must have an even number of elements.") new_kws = {} - for k, v in kws.iteritems(): + for k in kws: + v = kws[k] if not set_pp_option(k, v): new_kws[k] = v - for key, value in new_kws.iteritems(): + for key in new_kws: + value = new_kws[key] Z3_global_param_set(str(key).upper(), _to_param_value(value)) prev = None for a in args: @@ -240,7 +251,7 @@ def get_param(name): """ ptr = (ctypes.c_char_p * 1)() if Z3_global_param_get(str(name), ptr): - r = str(ptr[0]) + r = z3core._to_pystr(ptr[0]) return r raise Z3Exception("failed to retrieve value for '%s'" % name) @@ -899,11 +910,22 @@ def _coerce_exprs(a, b, ctx=None): b = s.cast(b) return (a, b) +def _reduce(f, l, a): + r = a + for e in l: + r = f(r, e) + return r + def _coerce_expr_list(alist, ctx=None): - if filter(is_expr, alist) == []: - alist = map(lambda a: _py2expr(a, ctx), alist) - s = reduce(_coerce_expr_merge, alist, None) - return map(lambda a: s.cast(a), alist) + has_expr = False + for a in alist: + if is_expr(a): + has_expr = True + break + if not has_expr: + alist = [ _py2expr(a, ctx) for a in alist ] + s = _reduce(_coerce_expr_merge, alist, None) + return [ s.cast(a) for a in alist ] def is_expr(a): """Return `True` if `a` is a Z3 expression. @@ -1518,7 +1540,7 @@ def MultiPattern(*args): """ if __debug__: _z3_assert(len(args) > 0, "At least one argument expected") - _z3_assert(all(map(is_expr, args)), "Z3 expressions expected") + _z3_assert(all([ is_expr(a) for a in args ]), "Z3 expressions expected") ctx = args[0].ctx args, sz = _to_ast_array(args) return PatternRef(Z3_mk_pattern(ctx.ref(), sz, args), ctx) @@ -1695,9 +1717,9 @@ def is_quantifier(a): def _mk_quantifier(is_forall, vs, body, weight=1, qid="", skid="", patterns=[], no_patterns=[]): if __debug__: _z3_assert(is_bool(body), "Z3 expression expected") - _z3_assert(is_const(vs) or (len(vs) > 0 and all(map(is_const, vs))), "Invalid bounded variable(s)") - _z3_assert(all(map(lambda a: is_pattern(a) or is_expr(a), patterns)), "Z3 patterns expected") - _z3_assert(all(map(is_expr, no_patterns)), "no patterns are Z3 expressions") + _z3_assert(is_const(vs) or (len(vs) > 0 and all([ is_const(v) for v in vs])), "Invalid bounded variable(s)") + _z3_assert(all([is_pattern(a) or is_expr(a) for a in patterns]), "Z3 patterns expected") + _z3_assert(all([is_expr(p) for p in no_patterns]), "no patterns are Z3 expressions") ctx = body.ctx if is_app(vs): vs = [vs] @@ -1706,7 +1728,7 @@ def _mk_quantifier(is_forall, vs, body, weight=1, qid="", skid="", patterns=[], for i in range(num_vars): ## TODO: Check if is constant _vs[i] = vs[i].as_ast() - patterns = map(_to_pattern, patterns) + patterns = [ _to_pattern(p) for p in patterns ] num_pats = len(patterns) _pats = (Pattern * num_pats)() for i in range(num_pats): @@ -2008,7 +2030,7 @@ class ArithRef(ExprRef): def __truediv__(self, other): """Create the Z3 expression `other/self`.""" - self.__div__(other) + return self.__div__(other) def __rdiv__(self, other): """Create the Z3 expression `other/self`. @@ -2029,7 +2051,7 @@ class ArithRef(ExprRef): def __rtruediv__(self, other): """Create the Z3 expression `other/self`.""" - self.__rdiv__(other) + return self.__rdiv__(other) def __mod__(self, other): """Create the Z3 expression `other%self`. @@ -2413,11 +2435,11 @@ class IntNumRef(ArithRef): >>> v + 1 1 + 1 >>> v.as_long() + 1 - 2L + 2 """ if __debug__: _z3_assert(self.is_int(), "Integer value expected") - return long(self.as_string()) + return int(self.as_string()) def as_string(self): """Return a Z3 integer numeral as a Python string. @@ -2464,8 +2486,8 @@ class RatNumRef(ArithRef): 10000000000 >>> v + 1 10000000000 + 1 - >>> v.numerator_as_long() + 1 - 10000000001L + >>> v.numerator_as_long() + 1 == 10000000001 + True """ return self.numerator().as_long() @@ -2476,7 +2498,7 @@ class RatNumRef(ArithRef): >>> v 1/3 >>> v.denominator_as_long() - 3L + 3 """ return self.denominator().as_long() @@ -2529,7 +2551,7 @@ class AlgebraicNumRef(ArithRef): def _py2expr(a, ctx=None): if isinstance(a, bool): return BoolVal(a, ctx) - if isinstance(a, int) or isinstance(a, long): + if _is_int(a): return IntVal(a, ctx) if isinstance(a, float): return RealVal(a, ctx) @@ -2576,9 +2598,7 @@ def _to_int_str(val): return "1" else: return "0" - elif isinstance(val, int): - return str(val) - elif isinstance(val, long): + elif _is_int(val): return str(val) elif isinstance(val, str): return val @@ -2625,8 +2645,8 @@ def RatVal(a, b, ctx=None): Real """ if __debug__: - _z3_assert(isinstance(a, int) or isinstance(a, str) or isinstance(a, long), "First argument cannot be converted into an integer") - _z3_assert(isinstance(b, int) or isinstance(b, str) or isinstance(a, long), "Second argument cannot be converted into an integer") + _z3_assert(_is_int(a) or isinstance(a, str), "First argument cannot be converted into an integer") + _z3_assert(_is_int(b) or isinstance(b, str), "Second argument cannot be converted into an integer") return simplify(RealVal(a, ctx)/RealVal(b, ctx)) def Q(a, b, ctx=None): @@ -3078,7 +3098,7 @@ class BitVecRef(ExprRef): def __truediv__(self, other): """Create the Z3 expression (signed) division `self / other`.""" - self.__div__(other) + return self.__div__(other) def __rdiv__(self, other): """Create the Z3 expression (signed) division `other / self`. @@ -3098,7 +3118,7 @@ class BitVecRef(ExprRef): def __rtruediv__(self, other): """Create the Z3 expression (signed) division `other / self`.""" - self.__rdiv__(other) + return self.__rdiv__(other) def __mod__(self, other): """Create the Z3 expression (signed) mod `self % other`. @@ -3218,9 +3238,9 @@ class BitVecRef(ExprRef): >>> BitVecVal(4, 3) 4 >>> BitVecVal(4, 3).as_signed_long() - -4L + -4 >>> simplify(BitVecVal(4, 3) >> 1).as_signed_long() - -2L + -2 >>> simplify(BitVecVal(4, 3) >> 1) 6 >>> simplify(LShR(BitVecVal(4, 3), 1)) @@ -3284,32 +3304,32 @@ class BitVecNumRef(BitVecRef): >>> v = BitVecVal(0xbadc0de, 32) >>> v 195936478 - >>> print "0x%.8x" % v.as_long() + >>> print("0x%.8x" % v.as_long()) 0x0badc0de """ - return long(self.as_string()) + return int(self.as_string()) def as_signed_long(self): """Return a Z3 bit-vector numeral as a Python long (bignum) numeral. The most significant bit is assumed to be the sign. >>> BitVecVal(4, 3).as_signed_long() - -4L + -4 >>> BitVecVal(7, 3).as_signed_long() - -1L + -1 >>> BitVecVal(3, 3).as_signed_long() - 3L - >>> BitVecVal(2L**32 - 1, 32).as_signed_long() - -1L - >>> BitVecVal(2L**64 - 1, 64).as_signed_long() - -1L + 3 + >>> BitVecVal(2**32 - 1, 32).as_signed_long() + -1 + >>> BitVecVal(2**64 - 1, 64).as_signed_long() + -1 """ - sz = long(self.size()) + sz = self.size() val = self.as_long() - if val >= 2L**(sz - 1): - val = val - 2L**sz - if val < -2L**(sz - 1): - val = val + 2L**sz - return val + if val >= 2**(sz - 1): + val = val - 2**sz + if val < -2**(sz - 1): + val = val + 2**sz + return int(val) def as_string(self): return Z3_get_numeral_string(self.ctx_ref(), self.as_ast()) @@ -3379,7 +3399,7 @@ def BitVecVal(val, bv, ctx=None): >>> v = BitVecVal(10, 32) >>> v 10 - >>> print "0x%.8x" % v.as_long() + >>> print("0x%.8x" % v.as_long()) 0x0000000a """ if is_bv_sort(bv): @@ -3440,12 +3460,12 @@ def Concat(*args): Concat(Concat(1, 1 + 1), 1) >>> simplify(Concat(v, v+1, v)) 289 - >>> print "%.3x" % simplify(Concat(v, v+1, v)).as_long() + >>> print("%.3x" % simplify(Concat(v, v+1, v)).as_long()) 121 """ args = _get_args(args) if __debug__: - _z3_assert(all(map(is_bv, args)), "All arguments must be Z3 bit-vector expressions.") + _z3_assert(all([is_bv(a) for a in args]), "All arguments must be Z3 bit-vector expressions.") _z3_assert(len(args) >= 2, "At least two arguments expected.") ctx = args[0].ctx r = args[0] @@ -3615,9 +3635,9 @@ def LShR(a, b): >>> BitVecVal(4, 3) 4 >>> BitVecVal(4, 3).as_signed_long() - -4L + -4 >>> simplify(BitVecVal(4, 3) >> 1).as_signed_long() - -2L + -2 >>> simplify(BitVecVal(4, 3) >> 1) 6 >>> simplify(LShR(BitVecVal(4, 3), 1)) @@ -3682,7 +3702,7 @@ def SignExt(n, a): 254 >>> v.size() 8 - >>> print "%.x" % v.as_long() + >>> print("%.x" % v.as_long()) fe """ if __debug__: @@ -3727,12 +3747,12 @@ def RepeatBitVec(n, a): >>> n.size() 32 >>> v0 = BitVecVal(10, 4) - >>> print "%.x" % v0.as_long() + >>> print("%.x" % v0.as_long()) a >>> v = simplify(RepeatBitVec(4, v0)) >>> v.size() 16 - >>> print "%.x" % v.as_long() + >>> print("%.x" % v.as_long()) aaaa """ if __debug__: @@ -4006,7 +4026,7 @@ def Map(f, *args): if __debug__: _z3_assert(len(args) > 0, "At least one Z3 array expression expected") _z3_assert(is_func_decl(f), "First argument must be a Z3 function declaration") - _z3_assert(all(map(is_array, args)), "Z3 array expected expected") + _z3_assert(all([is_array(a) for a in args]), "Z3 array expected expected") _z3_assert(len(args) == f.arity(), "Number of arguments mismatch") _args, sz = _to_ast_array(args) ctx = f.ctx @@ -4100,7 +4120,7 @@ class Datatype: if __debug__: _z3_assert(isinstance(name, str), "String expected") _z3_assert(isinstance(rec_name, str), "String expected") - _z3_assert(all(map(_valid_accessor, args)), "Valid list of accessors expected. An accessor is a pair of the form (String, Datatype|Sort)") + _z3_assert(all([_valid_accessor(a) for a in args]), "Valid list of accessors expected. An accessor is a pair of the form (String, Datatype|Sort)") self.constructors.append((name, rec_name, args)) def declare(self, name, *args): @@ -4187,9 +4207,9 @@ def CreateDatatypes(*ds): ds = _get_args(ds) if __debug__: _z3_assert(len(ds) > 0, "At least one Datatype must be specified") - _z3_assert(all(map(lambda d: isinstance(d, Datatype), ds)), "Arguments must be Datatypes") - _z3_assert(all(map(lambda d: d.ctx == ds[0].ctx, ds)), "Context mismatch") - _z3_assert(all(map(lambda d: d.constructors != [], ds)), "Non-empty Datatypes expected") + _z3_assert(all([isinstance(d, Datatype) for d in ds]), "Arguments must be Datatypes") + _z3_assert(all([d.ctx == ds[0].ctx for d in ds]), "Context mismatch") + _z3_assert(all([d.constructors != [] for d in ds]), "Non-empty Datatypes expected") ctx = ds[0].ctx num = len(ds) names = (Symbol * num)() @@ -4355,7 +4375,7 @@ def EnumSort(name, values, ctx=None): """ if __debug__: _z3_assert(isinstance(name, str), "Name must be a string") - _z3_assert(all(map(lambda v: isinstance(v, str), values)), "Eumeration sort values must be strings") + _z3_assert(all([isinstance(v, str) for v in values]), "Eumeration sort values must be strings") _z3_assert(len(values) > 0, "At least one value expected") ctx = _get_ctx(ctx) num = len(values) @@ -4369,7 +4389,7 @@ def EnumSort(name, values, ctx=None): V = [] for i in range(num): V.append(FuncDeclRef(_values[i], ctx)) - V = map(lambda a: a(), V) + V = [a() for a in V] return S, V ######################################### @@ -4432,7 +4452,8 @@ def args2params(arguments, keywords, ctx=None): else: r.set(prev, a) prev = None - for k, v in keywords.iteritems(): + for k in keywords: + v = keywords[k] r.set(k, v) return r @@ -4469,7 +4490,7 @@ class ParamDescrsRef: return Z3_param_descrs_get_kind(self.ctx.ref(), self.descr, to_symbol(n, self.ctx)) def __getitem__(self, arg): - if isinstance(arg, int) or isinstance(arg, long): + if _is_int(arg): return self.get_name(arg) else: return self.get_kind(arg) @@ -5057,7 +5078,7 @@ class FuncEntry: >>> try: ... e.arg_value(2) ... except IndexError: - ... print "index error" + ... print("index error") index error """ if idx >= self.num_args(): @@ -5122,7 +5143,10 @@ class FuncInterp(Z3PPObject): Z3_func_interp_dec_ref(self.ctx.ref(), self.f) def else_value(self): - """Return the `else` value for a function interpretation. + """ + Return the `else` value for a function interpretation. + Return None if Z3 did not specify the `else` value for + this object. >>> f = Function('f', IntSort(), IntSort()) >>> s = Solver() @@ -5135,7 +5159,11 @@ class FuncInterp(Z3PPObject): >>> m[f].else_value() 1 """ - return _to_expr_ref(Z3_func_interp_get_else(self.ctx.ref(), self.f), self.ctx) + r = Z3_func_interp_get_else(self.ctx.ref(), self.f) + if r: + return _to_expr_ref(r, self.ctx) + else: + return None def num_entries(self): """Return the number of entries/points in the function interpretation `self`. @@ -5428,7 +5456,7 @@ class ModelRef(Z3PPObject): 1 >>> m[f] [1 -> 0, else -> 0] - >>> for d in m: print "%s -> %s" % (d, m[d]) + >>> for d in m: print("%s -> %s" % (d, m[d])) x -> 1 f -> [1 -> 0, else -> 0] """ @@ -5499,16 +5527,16 @@ class Statistics: if in_html_mode(): out = io.StringIO() even = True - out.write(u'') + out.write(u('
')) for k, v in self: if even: - out.write(u'') + out.write(u('')) even = False else: - out.write(u'') + out.write(u('')) even = True - out.write(u'' % (k, v)) - out.write(u'
%s%s
') + out.write(u('%s%s' % (k, v))) + out.write(u('')) return out.getvalue() else: return Z3_stats_to_string(self.ctx.ref(), self.stats) @@ -5806,7 +5834,7 @@ class Solver(Z3PPObject): >>> s.assert_and_track(x > 0, 'p1') >>> s.assert_and_track(x != 1, 'p2') >>> s.assert_and_track(x < 0, p3) - >>> print s.check() + >>> print(s.check()) unsat >>> c = s.unsat_core() >>> len(c) @@ -5954,7 +5982,7 @@ class Solver(Z3PPObject): def help(self): """Display a string describing all available options.""" - print Z3_solver_get_help(self.ctx.ref(), self.solver) + print(Z3_solver_get_help(self.ctx.ref(), self.solver)) def param_descrs(self): """Return the parameter description set.""" @@ -6025,7 +6053,7 @@ class Fixedpoint(Z3PPObject): else: self.fixedpoint = fixedpoint Z3_fixedpoint_inc_ref(self.ctx.ref(), self.fixedpoint) - self.vars = [] + self.vars = [] def __del__(self): if self.fixedpoint != None: @@ -6039,8 +6067,8 @@ class Fixedpoint(Z3PPObject): def help(self): """Display a string describing all available options.""" - print Z3_fixedpoint_get_help(self.ctx.ref(), self.fixedpoint) - + print(Z3_fixedpoint_get_help(self.ctx.ref(), self.fixedpoint)) + def param_descrs(self): """Return the parameter description set.""" return ParamDescrsRef(Z3_fixedpoint_get_param_descrs(self.ctx.ref(), self.fixedpoint), self.ctx) @@ -6052,11 +6080,11 @@ class Fixedpoint(Z3PPObject): for arg in args: if isinstance(arg, Goal) or isinstance(arg, AstVector): for f in arg: - f = self.abstract(f) + f = self.abstract(f) Z3_fixedpoint_assert(self.ctx.ref(), self.fixedpoint, f.as_ast()) else: arg = s.cast(arg) - arg = self.abstract(arg) + arg = self.abstract(arg) Z3_fixedpoint_assert(self.ctx.ref(), self.fixedpoint, arg.as_ast()) def add(self, *args): @@ -6072,38 +6100,38 @@ class Fixedpoint(Z3PPObject): self.assert_exprs(*args) def add_rule(self, head, body = None, name = None): - """Assert rules defining recursive predicates to the fixedpoint solver. + """Assert rules defining recursive predicates to the fixedpoint solver. >>> a = Bool('a') - >>> b = Bool('b') + >>> b = Bool('b') >>> s = Fixedpoint() - >>> s.register_relation(a.decl()) - >>> s.register_relation(b.decl()) - >>> s.fact(a) + >>> s.register_relation(a.decl()) + >>> s.register_relation(b.decl()) + >>> s.fact(a) >>> s.rule(b, a) - >>> s.query(b) - sat - """ - if name == None: - name = "" + >>> s.query(b) + sat + """ + if name == None: + name = "" name = to_symbol(name, self.ctx) - if body == None: - head = self.abstract(head) - Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, head.as_ast(), name) - else: - body = _get_args(body) - f = self.abstract(Implies(And(body),head)) - Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) - + if body == None: + head = self.abstract(head) + Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, head.as_ast(), name) + else: + body = _get_args(body) + f = self.abstract(Implies(And(body),head)) + Z3_fixedpoint_add_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) + def rule(self, head, body = None, name = None): - """Assert rules defining recursive predicates to the fixedpoint solver. Alias for add_rule.""" - self.add_rule(head, body, name) - + """Assert rules defining recursive predicates to the fixedpoint solver. Alias for add_rule.""" + self.add_rule(head, body, name) + def fact(self, head, name = None): - """Assert facts defining recursive predicates to the fixedpoint solver. Alias for add_rule.""" - self.add_rule(head, None, name) + """Assert facts defining recursive predicates to the fixedpoint solver. Alias for add_rule.""" + self.add_rule(head, None, name) def query(self, *query): - """Query the fixedpoint engine whether formula is derivable. + """Query the fixedpoint engine whether formula is derivable. You can also pass an tuple or list of recursive predicates. """ query = _get_args(query) @@ -6134,17 +6162,17 @@ class Fixedpoint(Z3PPObject): def update_rule(self, head, body, name): """update rule""" - if name == None: - name = "" + if name == None: + name = "" name = to_symbol(name, self.ctx) body = _get_args(body) f = self.abstract(Implies(And(body),head)) - Z3_fixedpoint_update_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) + Z3_fixedpoint_update_rule(self.ctx.ref(), self.fixedpoint, f.as_ast(), name) - def get_answer(self): - """Retrieve answer from last query call.""" - r = Z3_fixedpoint_get_answer(self.ctx.ref(), self.fixedpoint) - return _to_expr_ref(r, self.ctx) + def get_answer(self): + """Retrieve answer from last query call.""" + r = Z3_fixedpoint_get_answer(self.ctx.ref(), self.fixedpoint) + return _to_expr_ref(r, self.ctx) def get_num_levels(self, predicate): """Retrieve number of levels used for predicate in PDR engine""" @@ -6160,40 +6188,40 @@ class Fixedpoint(Z3PPObject): Z3_fixedpoint_add_cover(self.ctx.ref(), self.fixedpoint, level, predicate.ast, property.ast) def register_relation(self, *relations): - """Register relation as recursive""" - relations = _get_args(relations) - for f in relations: - Z3_fixedpoint_register_relation(self.ctx.ref(), self.fixedpoint, f.ast) + """Register relation as recursive""" + relations = _get_args(relations) + for f in relations: + Z3_fixedpoint_register_relation(self.ctx.ref(), self.fixedpoint, f.ast) def set_predicate_representation(self, f, *representations): - """Control how relation is represented""" - representations = _get_args(representations) - representations = map(to_symbol, representations) - sz = len(representations) - args = (Symbol * sz)() - for i in range(sz): - args[i] = representations[i] - Z3_fixedpoint_set_predicate_representation(self.ctx.ref(), self.fixedpoint, f.ast, sz, args) + """Control how relation is represented""" + representations = _get_args(representations) + representations = [to_symbol(s) for s in representations] + sz = len(representations) + args = (Symbol * sz)() + for i in range(sz): + args[i] = representations[i] + Z3_fixedpoint_set_predicate_representation(self.ctx.ref(), self.fixedpoint, f.ast, sz, args) def parse_string(self, s): - """Parse rules and queries from a string""" - return AstVector(Z3_fixedpoint_from_string(self.ctx.ref(), self.fixedpoint, s), self.ctx) - + """Parse rules and queries from a string""" + return AstVector(Z3_fixedpoint_from_string(self.ctx.ref(), self.fixedpoint, s), self.ctx) + def parse_file(self, f): - """Parse rules and queries from a file""" - return AstVector(Z3_fixedpoint_from_file(self.ctx.ref(), self.fixedpoint, f), self.ctx) + """Parse rules and queries from a file""" + return AstVector(Z3_fixedpoint_from_file(self.ctx.ref(), self.fixedpoint, f), self.ctx) def get_rules(self): - """retrieve rules that have been added to fixedpoint context""" - return AstVector(Z3_fixedpoint_get_rules(self.ctx.ref(), self.fixedpoint), self.ctx) + """retrieve rules that have been added to fixedpoint context""" + return AstVector(Z3_fixedpoint_get_rules(self.ctx.ref(), self.fixedpoint), self.ctx) def get_assertions(self): - """retrieve assertions that have been added to fixedpoint context""" - return AstVector(Z3_fixedpoint_get_assertions(self.ctx.ref(), self.fixedpoint), self.ctx) + """retrieve assertions that have been added to fixedpoint context""" + return AstVector(Z3_fixedpoint_get_assertions(self.ctx.ref(), self.fixedpoint), self.ctx) def __repr__(self): """Return a formatted string with all added rules and constraints.""" - return self.sexpr() + return self.sexpr() def sexpr(self): """Return a formatted string (in Lisp-like format) with all added constraints. We say the string is in s-expression format. @@ -6201,16 +6229,16 @@ class Fixedpoint(Z3PPObject): return Z3_fixedpoint_to_string(self.ctx.ref(), self.fixedpoint, 0, (Ast * 0)()) def to_string(self, queries): - """Return a formatted string (in Lisp-like format) with all added constraints. + """Return a formatted string (in Lisp-like format) with all added constraints. We say the string is in s-expression format. - Include also queries. + Include also queries. """ - args, len = _to_ast_array(queries) + args, len = _to_ast_array(queries) return Z3_fixedpoint_to_string(self.ctx.ref(), self.fixedpoint, len, args) def statistics(self): """Return statistics for the last `query()`. - """ + """ return Statistics(Z3_fixedpoint_get_statistics(self.ctx.ref(), self.fixedpoint), self.ctx) def reason_unknown(self): @@ -6219,21 +6247,21 @@ class Fixedpoint(Z3PPObject): return Z3_fixedpoint_get_reason_unknown(self.ctx.ref(), self.fixedpoint) def declare_var(self, *vars): - """Add variable or several variables. - The added variable or variables will be bound in the rules - and queries - """ - vars = _get_args(vars) - for v in vars: - self.vars += [v] - + """Add variable or several variables. + The added variable or variables will be bound in the rules + and queries + """ + vars = _get_args(vars) + for v in vars: + self.vars += [v] + def abstract(self, fml, is_forall=True): - if self.vars == []: - return fml - if is_forall: - return ForAll(self.vars, fml) - else: - return Exists(self.vars, fml) + if self.vars == []: + return fml + if is_forall: + return ForAll(self.vars, fml) + else: + return Exists(self.vars, fml) ######################################### # @@ -6425,7 +6453,7 @@ class Tactic: def help(self): """Display a string containing a description of the available options for the `self` tactic.""" - print Z3_tactic_get_help(self.ctx.ref(), self.tactic) + print(Z3_tactic_get_help(self.ctx.ref(), self.tactic)) def param_descrs(self): """Return the parameter description set.""" @@ -6521,7 +6549,7 @@ def ParOr(*ts, **ks): if __debug__: _z3_assert(len(ts) >= 2, "At least two arguments expected") ctx = _get_ctx(ks.get('ctx', None)) - ts = map(lambda t: _to_tactic(t, ctx), ts) + ts = [ _to_tactic(t, ctx) for t in ts ] sz = len(ts) _args = (TacticObj * sz)() for i in range(sz): @@ -6566,7 +6594,7 @@ def Repeat(t, max=4294967295, ctx=None): >>> c = And(Or(x == 0, x == 1), Or(y == 0, y == 1), x > y) >>> t = Repeat(OrElse(Tactic('split-clause'), Tactic('skip'))) >>> r = t(c) - >>> for subgoal in r: print subgoal + >>> for subgoal in r: print(subgoal) [x == 0, y == 0, x > y] [x == 0, y == 1, x > y] [x == 1, y == 0, x > y] @@ -6608,19 +6636,19 @@ def describe_tactics(): """Display a (tabular) description of all available tactics in Z3.""" if in_html_mode(): even = True - print '' + print('
') for t in tactics(): if even: - print '' + print('') even = False else: - print '' + print('') even = True - print '' % (t, insert_line_breaks(tactic_description(t), 40)) - print '
%s%s
' + print('%s%s' % (t, insert_line_breaks(tactic_description(t), 40))) + print('') else: for t in tactics(): - print '%s : %s' % (t, tactic_description(t)) + print('%s : %s' % (t, tactic_description(t))) class Probe: """Probes are used to inspect a goal (aka problem) and collect information that may be used to decide which solver and/or preprocessing step will be used.""" @@ -6631,7 +6659,7 @@ class Probe: self.probe = probe elif isinstance(probe, float): self.probe = Z3_probe_const(self.ctx.ref(), probe) - elif isinstance(probe, int) or isinstance(probe, long): + elif _is_int(probe): self.probe = Z3_probe_const(self.ctx.ref(), float(probe)) elif isinstance(probe, bool): if probe: @@ -6796,19 +6824,19 @@ def describe_probes(): """Display a (tabular) description of all available probes in Z3.""" if in_html_mode(): even = True - print '' + print('
') for p in probes(): if even: - print '' + print('') even = False else: - print '' + print('') even = True - print '' % (p, insert_line_breaks(probe_description(p), 40)) - print '
%s%s
' + print('%s%s' % (p, insert_line_breaks(probe_description(p), 40))) + print('') else: for p in probes(): - print '%s : %s' % (p, probe_description(p)) + print('%s : %s' % (p, probe_description(p))) def _probe_nary(f, args, ctx): if __debug__: @@ -6904,7 +6932,7 @@ def simplify(a, *arguments, **keywords): def help_simplify(): """Return a string describing all options available for Z3 `simplify` procedure.""" - print Z3_simplify_get_help(main_ctx().ref()) + print(Z3_simplify_get_help(main_ctx().ref())) def simplify_param_descrs(): """Return the set of parameter descriptions for Z3 `simplify` procedure.""" @@ -6927,7 +6955,7 @@ def substitute(t, *m): m = _get_args(m1) if __debug__: _z3_assert(is_expr(t), "Z3 expression expected") - _z3_assert(all(map(lambda p: isinstance(p, tuple) and is_expr(p[0]) and is_expr(p[1]) and p[0].sort().eq(p[1].sort()), m)), "Z3 invalid substitution, expression pairs expected.") + _z3_assert(all([isinstance(p, tuple) and is_expr(p[0]) and is_expr(p[1]) and p[0].sort().eq(p[1].sort()) for p in m]), "Z3 invalid substitution, expression pairs expected.") num = len(m) _from = (Ast * num)() _to = (Ast * num)() @@ -6949,7 +6977,7 @@ def substitute_vars(t, *m): """ if __debug__: _z3_assert(is_expr(t), "Z3 expression expected") - _z3_assert(all(map(is_expr, m)), "Z3 invalid substitution, list of expressions expected.") + _z3_assert(all([is_expr(n) for n in m]), "Z3 invalid substitution, list of expressions expected.") num = len(m) _to = (Ast * num)() for i in range(num): @@ -6976,7 +7004,7 @@ def Sum(*args): _z3_assert(ctx != None, "At least one of the arguments must be a Z3 expression") args = _coerce_expr_list(args, ctx) if is_bv(args[0]): - return reduce(lambda a, b: a + b, args, 0) + return _reduce(lambda a, b: a + b, args, 0) else: _args, sz = _to_ast_array(args) return ArithRef(Z3_mk_add(ctx.ref(), sz, _args), ctx) @@ -7001,7 +7029,7 @@ def Product(*args): _z3_assert(ctx != None, "At least one of the arguments must be a Z3 expression") args = _coerce_expr_list(args, ctx) if is_bv(args[0]): - return reduce(lambda a, b: a * b, args, 1) + return _reduce(lambda a, b: a * b, args, 1) else: _args, sz = _to_ast_array(args) return ArithRef(Z3_mk_mul(ctx.ref(), sz, _args), ctx) @@ -7021,18 +7049,18 @@ def solve(*args, **keywords): s.set(**keywords) s.add(*args) if keywords.get('show', False): - print s + print(s) r = s.check() if r == unsat: - print "no solution" + print("no solution") elif r == unknown: - print "failed to solve" + print("failed to solve") try: - print s.model() + print(s.model()) except Z3Exception: return else: - print s.model() + print(s.model()) def solve_using(s, *args, **keywords): """Solve the constraints `*args` using solver `s`. @@ -7047,21 +7075,21 @@ def solve_using(s, *args, **keywords): s.set(**keywords) s.add(*args) if keywords.get('show', False): - print "Problem:" - print s + print("Problem:") + print(s) r = s.check() if r == unsat: - print "no solution" + print("no solution") elif r == unknown: - print "failed to solve" + print("failed to solve") try: - print s.model() + print(s.model()) except Z3Exception: return else: if keywords.get('show', False): - print "Solution:" - print s.model() + print("Solution:") + print(s.model()) def prove(claim, **keywords): """Try to prove the given claim. @@ -7079,16 +7107,16 @@ def prove(claim, **keywords): s.set(**keywords) s.add(Not(claim)) if keywords.get('show', False): - print s + print(s) r = s.check() if r == unsat: - print "proved" + print("proved") elif r == unknown: - print "failed to prove" - print s.model() + print("failed to prove") + print(s.model()) else: - print "counterexample" - print s.model() + print("counterexample") + print(s.model()) def _solve_html(*args, **keywords): """Version of funcion `solve` used in RiSE4Fun.""" @@ -7096,21 +7124,21 @@ def _solve_html(*args, **keywords): s.set(**keywords) s.add(*args) if keywords.get('show', False): - print "Problem:" - print s + print("Problem:") + print(s) r = s.check() if r == unsat: - print "no solution" + print("no solution") elif r == unknown: - print "failed to solve" + print("failed to solve") try: - print s.model() + print(s.model()) except Z3Exception: return else: if keywords.get('show', False): - print "Solution:" - print s.model() + print("Solution:") + print(s.model()) def _solve_using_html(s, *args, **keywords): """Version of funcion `solve_using` used in RiSE4Fun.""" @@ -7119,21 +7147,21 @@ def _solve_using_html(s, *args, **keywords): s.set(**keywords) s.add(*args) if keywords.get('show', False): - print "Problem:" - print s + print("Problem:") + print(s) r = s.check() if r == unsat: - print "no solution" + print("no solution") elif r == unknown: - print "failed to solve" + print("failed to solve") try: - print s.model() + print(s.model()) except Z3Exception: return else: if keywords.get('show', False): - print "Solution:" - print s.model() + print("Solution:") + print(s.model()) def _prove_html(claim, **keywords): """Version of funcion `prove` used in RiSE4Fun.""" @@ -7143,23 +7171,24 @@ def _prove_html(claim, **keywords): s.set(**keywords) s.add(Not(claim)) if keywords.get('show', False): - print s + print(s) r = s.check() if r == unsat: - print "proved" + print("proved") elif r == unknown: - print "failed to prove" - print s.model() + print("failed to prove") + print(s.model()) else: - print "counterexample" - print s.model() + print("counterexample") + print(s.model()) def _dict2sarray(sorts, ctx): sz = len(sorts) _names = (Symbol * sz)() _sorts = (Sort * sz) () i = 0 - for k, v in sorts.iteritems(): + for k in sorts: + v = sorts[k] if __debug__: _z3_assert(isinstance(k, str), "String expected") _z3_assert(is_sort(v), "Z3 sort expected") @@ -7173,7 +7202,8 @@ def _dict2darray(decls, ctx): _names = (Symbol * sz)() _decls = (FuncDecl * sz) () i = 0 - for k, v in decls.iteritems(): + for k in decls: + v = decls[k] if __debug__: _z3_assert(isinstance(k, str), "String expected") _z3_assert(is_func_decl(v) or is_const(v), "Z3 declaration or constant expected") diff --git a/src/api/python/z3printer.py b/src/api/python/z3printer.py index 920de1a3b..d3dc43d3e 100644 --- a/src/api/python/z3printer.py +++ b/src/api/python/z3printer.py @@ -74,6 +74,15 @@ def _is_add(k): def _is_sub(k): return k == Z3_OP_SUB or k == Z3_OP_BSUB +import sys +if sys.version < '3': + import codecs + def u(x): + return codecs.unicode_escape_decode(x)[0] +else: + def u(x): + return x + _z3_infix_compact = [ Z3_OP_MUL, Z3_OP_BMUL, Z3_OP_POWER, Z3_OP_DIV, Z3_OP_IDIV, Z3_OP_MOD, Z3_OP_BSDIV, Z3_OP_BSMOD ] _ellipses = '...' @@ -161,15 +170,19 @@ def _get_precedence(k): return _z3_precedence.get(k, 100000) _z3_html_op_to_str = {} -for _k, _v in _z3_op_to_str.iteritems(): +for _k in _z3_op_to_str: + _v = _z3_op_to_str[_k] _z3_html_op_to_str[_k] = _v -for _k, _v in _z3_pre_html_op_to_str.iteritems(): +for _k in _z3_pre_html_op_to_str: + _v = _z3_pre_html_op_to_str[_k] _z3_html_op_to_str[_k] = _v _z3_html_precedence = {} -for _k, _v in _z3_precedence.iteritems(): +for _k in _z3_precedence: + _v = _z3_precedence[_k] _z3_html_precedence[_k] = _v -for _k, _v in _z3_pre_html_precedence.iteritems(): +for _k in _z3_pre_html_precedence: + _v = _z3_pre_html_precedence[_k] _z3_html_precedence[_k] = _v _html_infix_map = {} @@ -237,7 +250,7 @@ class FormatObject: class NAryFormatObject(FormatObject): def __init__(self, fs): - assert all(map(lambda a: isinstance(a, FormatObject), fs)) + assert all([isinstance(a, FormatObject) for a in fs]) self.children = fs def children(self): return self.children @@ -246,7 +259,7 @@ class ComposeFormatObject(NAryFormatObject): def is_compose(sef): return True def as_tuple(self): - return ('compose', map(lambda a: a.as_tuple(), self.children)) + return ('compose', [ a.as_tuple() for a in self.children ]) def space_upto_nl(self): r = 0 for child in self.children: @@ -256,13 +269,13 @@ class ComposeFormatObject(NAryFormatObject): return (r, True) return (r, False) def flat(self): - return compose(map(lambda a: a.flat(), self.children)) + return compose([a.flat() for a in self.children ]) class ChoiceFormatObject(NAryFormatObject): def is_choice(sef): return True def as_tuple(self): - return ('choice', map(lambda a: a.as_tuple(), self.children)) + return ('choice', [ a.as_tuple() for a in self.children ]) def space_upto_nl(self): return self.children[0].space_upto_nl() def flat(self): @@ -388,11 +401,11 @@ class PP: if not self.bounded or self.pos <= self.max_width: sz = _len(f) if self.bounded and self.pos + sz > self.max_width: - self.out.write(_ellipses) + self.out.write(u(_ellipses)) else: self.pos = self.pos + sz self.ribbon_pos = self.ribbon_pos + sz - self.out.write(unicode(f.string)) + self.out.write(u(f.string)) def pp_compose(self, f, indent): for c in f.children: @@ -410,11 +423,11 @@ class PP: self.ribbon_pos = 0 self.line = self.line + 1 if self.line < self.max_lines: - self.out.write(unicode('\n')) + self.out.write(u('\n')) for i in range(indent): - self.out.write(unicode(' ')) + self.out.write(u(' ')) else: - self.out.write(unicode('\n...')) + self.out.write(u('\n...')) raise StopPPException() def pp(self, f, indent): @@ -791,7 +804,11 @@ class Formatter: r.append(self.pp_ellipses()) break if sz <= self.max_args: - else_pp = self.pp_expr(f.else_value(), 0, []) + else_val = f.else_value() + if else_val == None: + else_pp = to_format('#unspecified') + else: + else_pp = self.pp_expr(else_val, 0, []) r.append(group(seq((to_format('else'), else_pp), self.pp_arrow()))) return seq3(r, '[', ']') @@ -953,23 +970,23 @@ def in_html_mode(): def pp(a): if _support_pp(a): - print obj_to_string(a) + print(obj_to_string(a)) else: - print a + print(a) def print_matrix(m): z3._z3_assert(isinstance(m, list) or isinstance(m, tuple), "matrix expected") if not in_html_mode(): - print obj_to_string(m) + print(obj_to_string(m)) else: - print '' + print('
') for r in m: z3._z3_assert(isinstance(r, list) or isinstance(r, tuple), "matrix expected") - print '' + print('') for c in r: - print '' % c - print '' - print '
%s
' + print('%s' % c) + print('') + print('') def insert_line_breaks(s, width): """Break s in lines of size width (approx)""" @@ -980,9 +997,9 @@ def insert_line_breaks(s, width): w = 0 for i in range(sz): if w > width and s[i] == ' ': - new_str.write(u'
') + new_str.write(u('
')) w = 0 else: - new_str.write(unicode(s[i])) + new_str.write(u(s[i])) w = w + 1 return new_str.getvalue() diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 49d59e125..98bde7bcf 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -1080,6 +1080,7 @@ typedef enum { Z3_PK_INVALID } Z3_param_kind; +#ifdef CorML3 /** \mlonly {!search_failure} \endmlonly \conly \brief The different kinds of search failure types. @@ -1103,6 +1104,7 @@ typedef enum { Z3_THEORY, Z3_QUANTIFIERS } Z3_search_failure; +#endif /** \mlonly {!ast_print_mode} \endmlonly \conly \brief @@ -6922,12 +6924,15 @@ END_MLAPI_EXCLUDE ); /*@}*/ - +#endif + + /** @name Deprecated Constraints API */ /*@{*/ +#ifdef CorML3 /** \brief Set the SMTLIB logic to be used in the given logical context. It is incorrect to invoke this function after invoking @@ -7109,7 +7114,9 @@ END_MLAPI_EXCLUDE __out Z3_model * m, __out Z3_ast* proof, __inout unsigned* core_size, __inout_ecount(num_assumptions) Z3_ast core[] ); +#endif +#ifdef CorML4 /** \brief Retrieve congruence class representatives for terms. @@ -7123,23 +7130,26 @@ END_MLAPI_EXCLUDE This means that two terms map to the same class identifier if and only if the current context implies that they are equal. - A side-effect of the function is a satisfiability check. + A side-effect of the function is a satisfiability check on the assertions on the solver that is passed in. The function return Z3_L_FALSE if the current assertions are not satisfiable. \sa Z3_check_and_get_model \sa Z3_check - \deprecated Subsumed by Z3_solver API + \deprecated To be moved outside of API. - def_API('Z3_get_implied_equalities', UINT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _out_array(1, UINT))) + def_API('Z3_get_implied_equalities', UINT, (_in(CONTEXT), _in(SOLVER), _in(UINT), _in_array(2, AST), _out_array(2, UINT))) */ Z3_lbool Z3_API Z3_get_implied_equalities( __in Z3_context c, + __in Z3_solver s, __in unsigned num_terms, __in_ecount(num_terms) Z3_ast const terms[], __out_ecount(num_terms) unsigned class_ids[] ); +#endif +#ifdef CorML3 /** \brief Delete a model object. diff --git a/src/api/z3_private.h b/src/api/z3_private.h index 17075a6c6..91becd158 100644 --- a/src/api/z3_private.h +++ b/src/api/z3_private.h @@ -36,38 +36,6 @@ extern "C" { Z3_bool Z3_API Z3_get_numeral_rational(__in Z3_context c, __in Z3_ast a, rational& r); - /** - \brief \mlh exec_smtlib2_string c str \endmlh - Parse the given string using the SMT-LIB2 parser and execute its commands. - - It returns a formula comprising of the conjunction of assertions in the scope - (up to push/pop) at the end of the string. - The returned formula is also asserted to the logical context on return. - */ - Z3_ast Z3_API Z3_exec_smtlib2_string(__in Z3_context c, - __in Z3_string str, - __in unsigned num_sorts, - __in_ecount(num_sorts) Z3_symbol sort_names[], - __in_ecount(num_sorts) Z3_sort sorts[], - __in unsigned num_decls, - __in_ecount(num_decls) Z3_symbol decl_names[], - __in_ecount(num_decls) Z3_func_decl decls[] - ); - - /** - \brief Similar to #Z3_exec_smtlib2_string, but reads the commands from a file. - */ - Z3_ast Z3_API Z3_exec_smtlib2_file(__in Z3_context c, - __in Z3_string file_name, - __in unsigned num_sorts, - __in_ecount(num_sorts) Z3_symbol sort_names[], - __in_ecount(num_sorts) Z3_sort sorts[], - __in unsigned num_decls, - __in_ecount(num_decls) Z3_symbol decl_names[], - __in_ecount(num_decls) Z3_func_decl decls[] - ); - - #ifndef CAMLIDL #ifdef __cplusplus }; diff --git a/src/ast/arith_decl_plugin.cpp b/src/ast/arith_decl_plugin.cpp index a89cc18d0..f2dccf065 100644 --- a/src/ast/arith_decl_plugin.cpp +++ b/src/ast/arith_decl_plugin.cpp @@ -573,18 +573,7 @@ expr * arith_decl_plugin::get_some_value(sort * s) { return mk_numeral(rational(0), s == m_int_decl); } -arith_util::arith_util(ast_manager & m): - m_manager(m), - m_afid(m.get_family_id("arith")), - m_plugin(0) { -} - -void arith_util::init_plugin() { - SASSERT(m_plugin == 0); - m_plugin = static_cast(m_manager.get_plugin(m_afid)); -} - -bool arith_util::is_numeral(expr const * n, rational & val, bool & is_int) const { +bool arith_recognizers::is_numeral(expr const * n, rational & val, bool & is_int) const { if (!is_app_of(n, m_afid, OP_NUM)) return false; func_decl * decl = to_app(n)->get_decl(); @@ -593,6 +582,17 @@ bool arith_util::is_numeral(expr const * n, rational & val, bool & is_int) const return true; } +arith_util::arith_util(ast_manager & m): + arith_recognizers(m.mk_family_id("arith")), + m_manager(m), + m_plugin(0) { +} + +void arith_util::init_plugin() { + SASSERT(m_plugin == 0); + m_plugin = static_cast(m_manager.get_plugin(m_afid)); +} + bool arith_util::is_irrational_algebraic_numeral(expr const * n, algebraic_numbers::anum & val) { if (!is_app_of(n, m_afid, OP_IRRATIONAL_ALGEBRAIC_NUM)) return false; diff --git a/src/ast/arith_decl_plugin.h b/src/ast/arith_decl_plugin.h index c39768d4c..e63e866c3 100644 --- a/src/ast/arith_decl_plugin.h +++ b/src/ast/arith_decl_plugin.h @@ -187,36 +187,24 @@ public: virtual void set_cancel(bool f); }; -class arith_util { - ast_manager & m_manager; +/** + \brief Procedures for recognizing arithmetic expressions. + We don't need access to ast_manager, and operations can be simultaneously + executed in different threads. +*/ +class arith_recognizers { +protected: family_id m_afid; - arith_decl_plugin * m_plugin; - - void init_plugin(); - - arith_decl_plugin & plugin() const { - if (!m_plugin) const_cast(this)->init_plugin(); - SASSERT(m_plugin != 0); - return *m_plugin; - } - public: - arith_util(ast_manager & m); + arith_recognizers(family_id id):m_afid(id) {} - ast_manager & get_manager() const { return m_manager; } family_id get_family_id() const { return m_afid; } - algebraic_numbers::manager & am() { - return plugin().am(); - } - bool is_arith_expr(expr const * n) const { return is_app(n) && to_app(n)->get_family_id() == m_afid; } + bool is_irrational_algebraic_numeral(expr const * n) const { return is_app_of(n, m_afid, OP_IRRATIONAL_ALGEBRAIC_NUM); } bool is_numeral(expr const * n, rational & val, bool & is_int) const; bool is_numeral(expr const * n, rational & val) const { bool is_int; return is_numeral(n, val, is_int); } bool is_numeral(expr const * n) const { return is_app_of(n, m_afid, OP_NUM); } - bool is_irrational_algebraic_numeral(expr const * n) const { return is_app_of(n, m_afid, OP_IRRATIONAL_ALGEBRAIC_NUM); } - bool is_irrational_algebraic_numeral(expr const * n, algebraic_numbers::anum & val); - algebraic_numbers::anum const & to_irrational_algebraic_numeral(expr const * n); bool is_zero(expr const * n) const { rational val; return is_numeral(n, val) && val.is_zero(); } bool is_minus_one(expr * n) const { rational tmp; return is_numeral(n, tmp) && tmp.is_minus_one(); } // return true if \c n is a term of the form (* -1 r) @@ -227,6 +215,7 @@ public: } return false; } + bool is_le(expr const * n) const { return is_app_of(n, m_afid, OP_LE); } bool is_ge(expr const * n) const { return is_app_of(n, m_afid, OP_GE); } bool is_lt(expr const * n) const { return is_app_of(n, m_afid, OP_LT); } @@ -245,14 +234,13 @@ public: bool is_power(expr const * n) const { return is_app_of(n, m_afid, OP_POWER); } bool is_int(sort const * s) const { return is_sort_of(s, m_afid, INT_SORT); } - bool is_int(expr const * n) const { return is_int(m_manager.get_sort(n)); } + bool is_int(expr const * n) const { return is_int(get_sort(n)); } bool is_real(sort const * s) const { return is_sort_of(s, m_afid, REAL_SORT); } - bool is_real(expr const * n) const { return is_real(m_manager.get_sort(n)); } + bool is_real(expr const * n) const { return is_real(get_sort(n)); } bool is_int_real(sort const * s) const { return s->get_family_id() == m_afid; } - bool is_int_real(expr const * n) const { return is_int_real(m_manager.get_sort(n)); } + bool is_int_real(expr const * n) const { return is_int_real(get_sort(n)); } MATCH_UNARY(is_uminus); - MATCH_BINARY(is_sub); MATCH_BINARY(is_add); MATCH_BINARY(is_mul); @@ -265,6 +253,34 @@ public: MATCH_BINARY(is_div); MATCH_BINARY(is_idiv); + bool is_pi(expr * arg) { return is_app_of(arg, m_afid, OP_PI); } + bool is_e(expr * arg) { return is_app_of(arg, m_afid, OP_E); } +}; + +class arith_util : public arith_recognizers { + ast_manager & m_manager; + arith_decl_plugin * m_plugin; + + void init_plugin(); + + arith_decl_plugin & plugin() const { + if (!m_plugin) const_cast(this)->init_plugin(); + SASSERT(m_plugin != 0); + return *m_plugin; + } + +public: + arith_util(ast_manager & m); + + ast_manager & get_manager() const { return m_manager; } + + algebraic_numbers::manager & am() { + return plugin().am(); + } + + bool is_irrational_algebraic_numeral(expr const * n) const { return is_app_of(n, m_afid, OP_IRRATIONAL_ALGEBRAIC_NUM); } + bool is_irrational_algebraic_numeral(expr const * n, algebraic_numbers::anum & val); + algebraic_numbers::anum const & to_irrational_algebraic_numeral(expr const * n); sort * mk_int() { return m_manager.mk_sort(m_afid, INT_SORT); } sort * mk_real() { return m_manager.mk_sort(m_afid, REAL_SORT); } @@ -320,9 +336,6 @@ public: app * mk_acosh(expr * arg) { return m_manager.mk_app(m_afid, OP_ACOSH, arg); } app * mk_atanh(expr * arg) { return m_manager.mk_app(m_afid, OP_ATANH, arg); } - bool is_pi(expr * arg) { return is_app_of(arg, m_afid, OP_PI); } - bool is_e(expr * arg) { return is_app_of(arg, m_afid, OP_E); } - app * mk_pi() { return plugin().mk_pi(); } app * mk_e() { return plugin().mk_e(); } diff --git a/src/ast/array_decl_plugin.cpp b/src/ast/array_decl_plugin.cpp index 23d5145ea..857cec105 100644 --- a/src/ast/array_decl_plugin.cpp +++ b/src/ast/array_decl_plugin.cpp @@ -542,6 +542,16 @@ bool array_decl_plugin::is_fully_interp(sort const * s) const { return m_manager->is_fully_interp(get_array_range(s)); } +func_decl * array_recognizers::get_as_array_func_decl(app * n) const { + SASSERT(is_as_array(n)); + return to_func_decl(n->get_decl()->get_parameter(0).get_ast()); +} + +array_util::array_util(ast_manager& m): + array_recognizers(m.mk_family_id("array")), + m_manager(m) { +} + bool array_util::is_as_array_tree(expr * n) { ptr_buffer todo; todo.push_back(n); diff --git a/src/ast/array_decl_plugin.h b/src/ast/array_decl_plugin.h index 68c473560..2184b0088 100644 --- a/src/ast/array_decl_plugin.h +++ b/src/ast/array_decl_plugin.h @@ -129,27 +129,34 @@ class array_decl_plugin : public decl_plugin { virtual bool is_fully_interp(sort const * s) const; }; -class array_util { - ast_manager & m_manager; - family_id m_fid; +class array_recognizers { +protected: + family_id m_fid; public: - array_util(ast_manager& m): m_manager(m), m_fid(m.get_family_id("array")) {} - ast_manager & get_manager() const { return m_manager; } + array_recognizers(family_id fid):m_fid(fid) {} family_id get_family_id() const { return m_fid; } bool is_array(sort* s) const { return is_sort_of(s, m_fid, ARRAY_SORT);} - bool is_array(expr* n) const { return is_array(m_manager.get_sort(n)); } + bool is_array(expr* n) const { return is_array(get_sort(n)); } bool is_select(expr* n) const { return is_app_of(n, m_fid, OP_SELECT); } bool is_store(expr* n) const { return is_app_of(n, m_fid, OP_STORE); } bool is_const(expr* n) const { return is_app_of(n, m_fid, OP_CONST_ARRAY); } bool is_map(expr* n) const { return is_app_of(n, m_fid, OP_ARRAY_MAP); } bool is_as_array(expr * n) const { return is_app_of(n, m_fid, OP_AS_ARRAY); } - bool is_as_array_tree(expr * n); bool is_select(func_decl* f) const { return is_decl_of(f, m_fid, OP_SELECT); } bool is_store(func_decl* f) const { return is_decl_of(f, m_fid, OP_STORE); } bool is_const(func_decl* f) const { return is_decl_of(f, m_fid, OP_CONST_ARRAY); } bool is_map(func_decl* f) const { return is_decl_of(f, m_fid, OP_ARRAY_MAP); } bool is_as_array(func_decl* f) const { return is_decl_of(f, m_fid, OP_AS_ARRAY); } - func_decl * get_as_array_func_decl(app * n) const { SASSERT(is_as_array(n)); return to_func_decl(n->get_decl()->get_parameter(0).get_ast()); } + func_decl * get_as_array_func_decl(app * n) const; +}; + +class array_util : public array_recognizers { + ast_manager & m_manager; +public: + array_util(ast_manager& m); + ast_manager & get_manager() const { return m_manager; } + + bool is_as_array_tree(expr * n); app * mk_store(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_fid, OP_STORE, 0, 0, num_args, args); diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 3fb422a2e..486aa9646 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -137,7 +137,7 @@ void display_parameters(std::ostream & out, unsigned n, parameter const * p) { // // ----------------------------------- -family_id family_manager::get_family_id(symbol const & s) { +family_id family_manager::mk_family_id(symbol const & s) { family_id r; if (m_families.find(s, r)) { return r; @@ -149,7 +149,15 @@ family_id family_manager::get_family_id(symbol const & s) { return r; } -bool family_manager::has_family(symbol const & s) { +family_id family_manager::get_family_id(symbol const & s) const { + family_id r; + if (m_families.find(s, r)) + return r; + else + return null_family_id; +} + +bool family_manager::has_family(symbol const & s) const { return m_families.contains(s); } @@ -374,6 +382,31 @@ quantifier::quantifier(bool forall, unsigned num_decls, sort * const * decl_sort memcpy(const_cast(get_no_patterns()), no_patterns, sizeof(expr *) * num_no_patterns); } +// ----------------------------------- +// +// Auxiliary functions +// +// ----------------------------------- + +sort * get_sort(expr const * n) { + while (true) { + switch(n->get_kind()) { + case AST_APP: + return to_app(n)->get_decl()->get_range(); + case AST_VAR: + return to_var(n)->get_sort(); + case AST_QUANTIFIER: + // The sort of the quantifier is the sort of the nested expression. + // This code assumes the given expression is well-sorted. + n = to_quantifier(n)->get_expr(); + break; + default: + UNREACHABLE(); + return 0; + } + } +} + // ----------------------------------- // // AST hash-consing @@ -1048,6 +1081,16 @@ expr * basic_decl_plugin::get_some_value(sort * s) { return 0; } +bool basic_recognizers::is_ite(expr const * n, expr * & t1, expr * & t2, expr * & t3) const { + if (is_ite(n)) { + t1 = to_app(n)->get_arg(0); + t2 = to_app(n)->get_arg(1); + t3 = to_app(n)->get_arg(2); + return true; + } + return false; +} + // ----------------------------------- // // label_decl_plugin @@ -1262,12 +1305,12 @@ void ast_manager::init() { m_expr_id_gen.reset(0); m_decl_id_gen.reset(c_first_decl_id); m_some_value_proc = 0; - m_basic_family_id = get_family_id("basic"); - m_label_family_id = get_family_id("label"); - m_pattern_family_id = get_family_id("pattern"); - m_model_value_family_id = get_family_id("model-value"); - m_user_sort_family_id = get_family_id("user-sort"); - m_arith_family_id = get_family_id("arith"); + m_basic_family_id = mk_family_id("basic"); + m_label_family_id = mk_family_id("label"); + m_pattern_family_id = mk_family_id("pattern"); + m_model_value_family_id = mk_family_id("model-value"); + m_user_sort_family_id = mk_family_id("user-sort"); + m_arith_family_id = mk_family_id("arith"); basic_decl_plugin * plugin = alloc(basic_decl_plugin); register_plugin(m_basic_family_id, plugin); m_bool_sort = plugin->mk_bool_sort(); @@ -1400,7 +1443,7 @@ void ast_manager::copy_families_plugins(ast_manager const & from) { << ", target has_family: " << m_family_manager.has_family(fid) << "\n"; if (m_family_manager.has_family(fid)) tout << get_family_id(fid_name) << "\n";); if (!m_family_manager.has_family(fid)) { - family_id new_fid = get_family_id(fid_name); + family_id new_fid = mk_family_id(fid_name); TRACE("copy_families_plugins", tout << "new target fid created: " << new_fid << " fid_name: " << fid_name << "\n";); } TRACE("copy_families_plugins", tout << "target fid: " << get_family_id(fid_name) << "\n";); @@ -1437,7 +1480,7 @@ void ast_manager::set_next_expr_id(unsigned id) { unsigned ast_manager::get_node_size(ast const * n) { return ::get_node_size(n); } void ast_manager::register_plugin(symbol const & s, decl_plugin * plugin) { - family_id id = m_family_manager.get_family_id(s); + family_id id = m_family_manager.mk_family_id(s); SASSERT(is_format_manager() || s != symbol("format")); register_plugin(id, plugin); } @@ -1495,20 +1538,6 @@ void ast_manager::register_plugin(family_id id, decl_plugin * plugin) { plugin->set_manager(this, id); } -sort * ast_manager::get_sort(expr const * n) const { - switch(n->get_kind()) { - case AST_APP: - return to_app(n)->get_decl()->get_range(); - case AST_VAR: - return to_var(n)->get_sort(); - case AST_QUANTIFIER: - return m_bool_sort; - default: - UNREACHABLE(); - return 0; - } -} - bool ast_manager::is_bool(expr const * n) const { return get_sort(n) == m_bool_sort; } diff --git a/src/ast/ast.h b/src/ast/ast.h index e9da41377..3f03b86b9 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -188,10 +188,20 @@ class family_manager { svector m_names; public: family_manager():m_next_id(0) {} + + /** + \brief Return the family_id for s, a new id is created if !has_family(s) + + If has_family(s), then this method is equivalent to get_family_id(s) + */ + family_id mk_family_id(symbol const & s); + + /** + \brief Return the family_id for s, return null_family_id if s was not registered in the manager. + */ + family_id get_family_id(symbol const & s) const; - family_id get_family_id(symbol const & s); - - bool has_family(symbol const & s); + bool has_family(symbol const & s) const; void get_dom(svector& dom) const { m_families.get_dom(dom); } @@ -1287,6 +1297,55 @@ inline bool has_labels(expr const * n) { else return false; } +sort * get_sort(expr const * n); + +class basic_recognizers { + family_id m_fid; +public: + basic_recognizers(family_id fid):m_fid(fid) {} + bool is_bool(sort const * s) const { return is_sort_of(s, m_fid, BOOL_SORT); } + bool is_bool(expr const * n) const { return is_bool(get_sort(n)); } + bool is_or(expr const * n) const { return is_app_of(n, m_fid, OP_OR); } + bool is_implies(expr const * n) const { return is_app_of(n, m_fid, OP_IMPLIES); } + bool is_and(expr const * n) const { return is_app_of(n, m_fid, OP_AND); } + bool is_not(expr const * n) const { return is_app_of(n, m_fid, OP_NOT); } + bool is_eq(expr const * n) const { return is_app_of(n, m_fid, OP_EQ); } + bool is_oeq(expr const * n) const { return is_app_of(n, m_fid, OP_OEQ); } + bool is_distinct(expr const * n) const { return is_app_of(n, m_fid, OP_DISTINCT); } + bool is_iff(expr const * n) const { return is_app_of(n, m_fid, OP_IFF); } + bool is_xor(expr const * n) const { return is_app_of(n, m_fid, OP_XOR); } + bool is_ite(expr const * n) const { return is_app_of(n, m_fid, OP_ITE); } + bool is_term_ite(expr const * n) const { return is_ite(n) && !is_bool(n); } + bool is_true(expr const * n) const { return is_app_of(n, m_fid, OP_TRUE); } + bool is_false(expr const * n) const { return is_app_of(n, m_fid, OP_FALSE); } + bool is_complement_core(expr const * n1, expr const * n2) const { + return (is_true(n1) && is_false(n2)) || (is_not(n1) && to_app(n1)->get_arg(0) == n2); + } + bool is_complement(expr const * n1, expr const * n2) const { return is_complement_core(n1, n2) || is_complement_core(n2, n1); } + bool is_or(func_decl const * d) const { return is_decl_of(d, m_fid, OP_OR); } + bool is_implies(func_decl const * d) const { return is_decl_of(d, m_fid, OP_IMPLIES); } + bool is_and(func_decl const * d) const { return is_decl_of(d, m_fid, OP_AND); } + bool is_not(func_decl const * d) const { return is_decl_of(d, m_fid, OP_NOT); } + bool is_eq(func_decl const * d) const { return is_decl_of(d, m_fid, OP_EQ); } + bool is_iff(func_decl const * d) const { return is_decl_of(d, m_fid, OP_IFF); } + bool is_xor(func_decl const * d) const { return is_decl_of(d, m_fid, OP_XOR); } + bool is_ite(func_decl const * d) const { return is_decl_of(d, m_fid, OP_ITE); } + bool is_term_ite(func_decl const * d) const { return is_ite(d) && !is_bool(d->get_range()); } + bool is_distinct(func_decl const * d) const { return is_decl_of(d, m_fid, OP_DISTINCT); } + + MATCH_UNARY(is_not); + MATCH_BINARY(is_eq); + MATCH_BINARY(is_iff); + MATCH_BINARY(is_implies); + MATCH_BINARY(is_and); + MATCH_BINARY(is_or); + MATCH_BINARY(is_xor); + MATCH_TERNARY(is_and); + MATCH_TERNARY(is_or); + + bool is_ite(expr const * n, expr * & t1, expr * & t2, expr * & t3) const; +}; + // ----------------------------------- // // Get Some Value functor @@ -1404,6 +1463,8 @@ public: // propagate cancellation signal to decl_plugins void set_cancel(bool f); + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } bool has_trace_stream() const { return m_trace_stream != 0; } std::ostream & trace_stream() { SASSERT(has_trace_stream()); return *m_trace_stream; } @@ -1432,8 +1493,10 @@ public: small_object_allocator & get_allocator() { return m_alloc; } - family_id get_family_id(symbol const & s) const { return const_cast(this)->m_family_manager.get_family_id(s); } - + family_id mk_family_id(symbol const & s) { return m_family_manager.mk_family_id(s); } + family_id mk_family_id(char const * s) { return mk_family_id(symbol(s)); } + + family_id get_family_id(symbol const & s) const { return m_family_manager.get_family_id(s); } family_id get_family_id(char const * s) const { return get_family_id(symbol(s)); } symbol const & get_family_name(family_id fid) const { return m_family_manager.get_name(fid); } @@ -1456,7 +1519,7 @@ public: bool has_plugin(family_id fid) const { return get_plugin(fid) != 0; } - bool has_plugin(symbol const & s) const { return has_plugin(get_family_id(s)); } + bool has_plugin(symbol const & s) const { return m_family_manager.has_family(s) && has_plugin(m_family_manager.get_family_id(s)); } void get_dom(svector & dom) const { m_family_manager.get_dom(dom); } @@ -1546,7 +1609,7 @@ protected: } public: - sort * get_sort(expr const * n) const; + sort * get_sort(expr const * n) const { return ::get_sort(n); } void check_sort(func_decl const * decl, unsigned num_args, expr * const * args) const; void check_sorts_core(ast const * n) const; bool check_sorts(ast const * n) const; diff --git a/src/ast/ast_smt2_pp.cpp b/src/ast/ast_smt2_pp.cpp index afe301ddf..1ad2b8222 100644 --- a/src/ast/ast_smt2_pp.cpp +++ b/src/ast/ast_smt2_pp.cpp @@ -501,7 +501,12 @@ class smt2_printer { } format * pp_simple_attribute(char const * attr, symbol const & s) { - return mk_compose(m(), mk_string(m(), attr), mk_string(m(), s.str().c_str())); + std::string str; + if (is_smt2_quoted_symbol(s)) + str = mk_smt2_quoted_symbol(s); + else + str = s.str(); + return mk_compose(m(), mk_string(m(), attr), mk_string(m(), str.c_str())); } format * pp_labels(bool is_pos, buffer const & names, format * f) { @@ -851,7 +856,7 @@ class smt2_printer { buf.push_back(pp_simple_attribute(":weight ", q->get_weight())); } if (q->get_skid() != symbol::null) { - buf.push_back(pp_simple_attribute(":skid ", q->get_skid())); + buf.push_back(pp_simple_attribute(":skolemid ", q->get_skid())); } if (q->get_qid() != symbol::null) { #if 0 diff --git a/src/ast/ast_smt_pp.cpp b/src/ast/ast_smt_pp.cpp index 78a1caf68..66b467b92 100644 --- a/src/ast/ast_smt_pp.cpp +++ b/src/ast/ast_smt_pp.cpp @@ -795,11 +795,11 @@ public: m_simplify_implies(simplify_implies) { m_basic_fid = m.get_basic_family_id(); - m_label_fid = m.get_family_id("label"); - m_bv_fid = m.get_family_id("bv"); - m_arith_fid = m.get_family_id("arith"); - m_array_fid = m.get_family_id("array"); - m_dt_fid = m.get_family_id("datatype"); + m_label_fid = m.mk_family_id("label"); + m_bv_fid = m.mk_family_id("bv"); + m_arith_fid = m.mk_family_id("arith"); + m_array_fid = m.mk_family_id("array"); + m_dt_fid = m.mk_family_id("datatype"); } void operator()(expr* n) { @@ -1009,7 +1009,7 @@ ast_smt_pp::ast_smt_pp(ast_manager& m): m_status("unknown"), m_category(), m_logic(), - m_dt_fid(m.get_family_id("datatype")), + m_dt_fid(m.mk_family_id("datatype")), m_is_declared(&m_is_declared_default), m_simplify_implies(true) {} diff --git a/src/ast/bv_decl_plugin.cpp b/src/ast/bv_decl_plugin.cpp index fd15ca681..9c5bccbc6 100644 --- a/src/ast/bv_decl_plugin.cpp +++ b/src/ast/bv_decl_plugin.cpp @@ -41,26 +41,6 @@ bv_decl_plugin::bv_decl_plugin(): m_int_sort(0) { } -void bv_decl_plugin::mk_table_upto(unsigned n) { - if (m_powers.empty()) { - m_powers.push_back(rational(1)); - } - unsigned sz = m_powers.size(); - rational curr = m_powers[sz - 1]; - rational two(2); - for (unsigned i = sz; i <= n; i++) { - curr *= two; - m_powers.push_back(curr); - } -} - -rational bv_decl_plugin::power_of_two(unsigned n) const { - if (n >= m_powers.size()) { - const_cast(this)->mk_table_upto(n + 1); - } - return m_powers[n]; -} - void bv_decl_plugin::set_manager(ast_manager * m, family_id id) { decl_plugin::set_manager(m, id); @@ -79,7 +59,7 @@ void bv_decl_plugin::set_manager(ast_manager * m, family_id id) { m_xor3 = m_manager->mk_func_decl(symbol("xor3"), 3, d, b, func_decl_info(m_family_id, OP_XOR3)); m_manager->inc_ref(m_xor3); - m_int_sort = m_manager->mk_sort(m_manager->get_family_id("arith"), INT_SORT); + m_int_sort = m_manager->mk_sort(m_manager->mk_family_id("arith"), INT_SORT); SASSERT(m_int_sort != 0); // arith_decl_plugin must be installed before bv_decl_plugin. m_manager->inc_ref(m_int_sort); } @@ -169,7 +149,7 @@ void bv_decl_plugin::mk_bv_sort(unsigned bv_size) { sz = sort_size::mk_very_big(); } else { - sz = sort_size(power_of_two(bv_size)); + sz = sort_size(rational::power_of_two(bv_size)); } m_bv_sorts[bv_size] = m_manager->mk_sort(symbol("bv"), sort_info(m_family_id, BV_SORT, sz, 1, &p)); m_manager->inc_ref(m_bv_sorts[bv_size]); @@ -436,7 +416,7 @@ func_decl * bv_decl_plugin::mk_num_decl(unsigned num_parameters, parameter const // This cannot be enforced now, since some Z3 modules try to generate these invalid numerals. // After SMT-COMP, I should find all offending modules. // For now, I will just simplify the numeral here. - parameter p0(mod(parameters[0].get_rational(), power_of_two(bv_size))); + parameter p0(mod(parameters[0].get_rational(), rational::power_of_two(bv_size))); parameter ps[2] = { p0, parameters[1] }; sort * bv = get_bv_sort(bv_size); return m_manager->mk_const_decl(m_bv_sym, bv, func_decl_info(m_family_id, OP_BV_NUM, num_parameters, ps)); @@ -621,7 +601,7 @@ void bv_decl_plugin::get_offset_term(app * a, expr * & t, rational & offset) con offset = decl->get_parameter(0).get_rational(); sz = decl->get_parameter(1).get_int(); t = a->get_arg(1); - offset = mod(offset, power_of_two(sz)); + offset = mod(offset, rational::power_of_two(sz)); } else { t = a; @@ -729,37 +709,104 @@ expr * bv_decl_plugin::get_some_value(sort * s) { return m_manager->mk_app(m_family_id, OP_BV_NUM, 2, p, 0, 0); } -bv_util::bv_util(ast_manager & m): - m_manager(m) { - SASSERT(m.has_plugin(symbol("bv"))); - m_plugin = static_cast(m.get_plugin(m.get_family_id("bv"))); -} - -rational bv_util::norm(rational const & val, unsigned bv_size, bool is_signed) const { - rational r = mod(val, power_of_two(bv_size)); +rational bv_recognizers::norm(rational const & val, unsigned bv_size, bool is_signed) const { + rational r = mod(val, rational::power_of_two(bv_size)); SASSERT(!r.is_neg()); if (is_signed) { - if (r >= power_of_two(bv_size - 1)) { - r -= power_of_two(bv_size); + if (r >= rational::power_of_two(bv_size - 1)) { + r -= rational::power_of_two(bv_size); } - if (r < -power_of_two(bv_size - 1)) { - r += power_of_two(bv_size); + if (r < -rational::power_of_two(bv_size - 1)) { + r += rational::power_of_two(bv_size); } } return r; } -bool bv_util::has_sign_bit(rational const & n, unsigned bv_size) const { +bool bv_recognizers::has_sign_bit(rational const & n, unsigned bv_size) const { SASSERT(bv_size > 0); rational m = norm(n, bv_size, false); - rational p = power_of_two(bv_size - 1); + rational p = rational::power_of_two(bv_size - 1); return m >= p; } -bool bv_util::is_bv_sort(sort const * s) const { +bool bv_recognizers::is_bv_sort(sort const * s) const { return (s->get_family_id() == get_fid() && s->get_decl_kind() == BV_SORT && s->get_num_parameters() == 1); } +bool bv_recognizers::is_numeral(expr const * n, rational & val, unsigned & bv_size) const { + if (!is_app_of(n, get_fid(), OP_BV_NUM)) { + return false; + } + func_decl * decl = to_app(n)->get_decl(); + val = decl->get_parameter(0).get_rational(); + bv_size = decl->get_parameter(1).get_int(); + return true; +} + +bool bv_recognizers::is_allone(expr const * e) const { + rational r; + unsigned bv_size; + if (!is_numeral(e, r, bv_size)) { + return false; + } + bool result = (r == rational::power_of_two(bv_size) - rational(1)); + TRACE("is_allone", tout << r << " " << result << "\n";); + return result; +} + +bool bv_recognizers::is_zero(expr const * n) const { + if (!is_app_of(n, get_fid(), OP_BV_NUM)) { + return false; + } + func_decl * decl = to_app(n)->get_decl(); + return decl->get_parameter(0).get_rational().is_zero(); +} + +bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) { + if (!is_extract(e)) return false; + low = get_extract_low(e); + high = get_extract_high(e); + b = to_app(e)->get_arg(0); + return true; +} + +bool bv_recognizers::is_bv2int(expr const* e, expr*& r) { + if (!is_bv2int(e)) return false; + r = to_app(e)->get_arg(0); + return true; +} + +bool bv_recognizers::mult_inverse(rational const & n, unsigned bv_size, rational & result) { + if (n.is_one()) { + result = n; + return true; + } + + if (!mod(n, rational(2)).is_one()) { + return false; + } + + rational g; + rational x; + rational y; + g = gcd(n, rational::power_of_two(bv_size), x, y); + if (x.is_neg()) { + x = mod(x, rational::power_of_two(bv_size)); + } + SASSERT(x.is_pos()); + SASSERT(mod(x * n, rational::power_of_two(bv_size)).is_one()); + result = x; + return true; +} + +bv_util::bv_util(ast_manager & m): + bv_recognizers(m.mk_family_id(symbol("bv"))), + m_manager(m) { + SASSERT(m.has_plugin(symbol("bv"))); + m_plugin = static_cast(m.get_plugin(m.mk_family_id("bv"))); +} + app * bv_util::mk_numeral(rational const & val, sort* s) { if (!is_bv_sort(s)) { return 0; @@ -774,67 +821,13 @@ app * bv_util::mk_numeral(rational const & val, unsigned bv_size) { return m_manager.mk_app(get_fid(), OP_BV_NUM, 2, p, 0, 0); } -bool bv_util::is_numeral(expr const * n, rational & val, unsigned & bv_size) const { - if (!is_app_of(n, get_fid(), OP_BV_NUM)) { - return false; - } - func_decl * decl = to_app(n)->get_decl(); - val = decl->get_parameter(0).get_rational(); - bv_size = decl->get_parameter(1).get_int(); - return true; -} - - -bool bv_util::is_allone(expr const * e) const { - rational r; - unsigned bv_size; - if (!is_numeral(e, r, bv_size)) { - return false; - } - bool result = (r == power_of_two(bv_size) - rational(1)); - TRACE("is_allone", tout << r << " " << result << "\n";); - return result; -} - -bool bv_util::is_zero(expr const * n) const { - if (!is_app_of(n, get_fid(), OP_BV_NUM)) { - return false; - } - func_decl * decl = to_app(n)->get_decl(); - return decl->get_parameter(0).get_rational().is_zero(); -} - sort * bv_util::mk_sort(unsigned bv_size) { parameter p[1] = { parameter(bv_size) }; return m_manager.mk_sort(get_fid(), BV_SORT, 1, p); } - -bool bv_util::mult_inverse(rational const & n, unsigned bv_size, rational & result) { - if (n.is_one()) { - result = n; - return true; - } - - if (!mod(n, rational(2)).is_one()) { - return false; - } - - rational g; - rational x; - rational y; - g = gcd(n, power_of_two(bv_size), x, y); - if (x.is_neg()) { - x = mod(x, power_of_two(bv_size)); - } - SASSERT(x.is_pos()); - SASSERT(mod(x * n, power_of_two(bv_size)).is_one()); - result = x; - return true; -} - app * bv_util::mk_bv2int(expr* e) { - sort* s = m_manager.mk_sort(m_manager.get_family_id("arith"), INT_SORT); + sort* s = m_manager.mk_sort(m_manager.mk_family_id("arith"), INT_SORT); parameter p(s); return m_manager.mk_app(get_fid(), OP_BV2INT, 1, &p, 1, &e); } diff --git a/src/ast/bv_decl_plugin.h b/src/ast/bv_decl_plugin.h index 34f2baf6b..8ea90f844 100644 --- a/src/ast/bv_decl_plugin.h +++ b/src/ast/bv_decl_plugin.h @@ -127,9 +127,6 @@ inline func_decl * get_div0_decl(ast_manager & m, func_decl * decl) { class bv_decl_plugin : public decl_plugin { protected: - vector m_powers; - void mk_table_upto(unsigned n); - symbol m_bv_sym; symbol m_concat_sym; symbol m_sign_extend_sym; @@ -245,8 +242,6 @@ protected: public: bv_decl_plugin(); - rational power_of_two(unsigned n) const; - virtual ~bv_decl_plugin() {} virtual void finalize(); @@ -273,7 +268,70 @@ public: virtual expr * get_some_value(sort * s); }; -class bv_util { +class bv_recognizers { + family_id m_afid; +public: + bv_recognizers(family_id fid):m_afid(fid) {} + + family_id get_fid() const { return m_afid; } + family_id get_family_id() const { return get_fid(); } + + bool is_numeral(expr const * n, rational & val, unsigned & bv_size) const; + bool is_numeral(expr const * n) const { return is_app_of(n, get_fid(), OP_BV_NUM); } + bool is_allone(expr const * e) const; + bool is_zero(expr const * e) const; + bool is_bv_sort(sort const * s) const; + bool is_bv(expr const* e) const { return is_bv_sort(get_sort(e)); } + + bool is_concat(expr const * e) const { return is_app_of(e, get_fid(), OP_CONCAT); } + bool is_extract(func_decl const * f) const { return is_decl_of(f, get_fid(), OP_EXTRACT); } + bool is_extract(expr const * e) const { return is_app_of(e, get_fid(), OP_EXTRACT); } + unsigned get_extract_high(func_decl const * f) const { return f->get_parameter(0).get_int(); } + unsigned get_extract_low(func_decl const * f) const { return f->get_parameter(1).get_int(); } + unsigned get_extract_high(expr const * n) { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); } + unsigned get_extract_low(expr const * n) { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); } + bool is_extract(expr const * e, unsigned & low, unsigned & high, expr * & b); + bool is_bv2int(expr const * e, expr * & r); + bool is_bv_add(expr const * e) const { return is_app_of(e, get_fid(), OP_BADD); } + bool is_bv_sub(expr const * e) const { return is_app_of(e, get_fid(), OP_BSUB); } + bool is_bv_mul(expr const * e) const { return is_app_of(e, get_fid(), OP_BMUL); } + bool is_bv_neg(expr const * e) const { return is_app_of(e, get_fid(), OP_BNEG); } + bool is_bv_sdiv(expr const * e) const { return is_app_of(e, get_fid(), OP_BSDIV); } + bool is_bv_udiv(expr const * e) const { return is_app_of(e, get_fid(), OP_BUDIV); } + bool is_bv_srem(expr const * e) const { return is_app_of(e, get_fid(), OP_BSREM); } + bool is_bv_urem(expr const * e) const { return is_app_of(e, get_fid(), OP_BUREM); } + bool is_bv_smod(expr const * e) const { return is_app_of(e, get_fid(), OP_BSMOD); } + bool is_bv_and(expr const * e) const { return is_app_of(e, get_fid(), OP_BAND); } + bool is_bv_or(expr const * e) const { return is_app_of(e, get_fid(), OP_BOR); } + bool is_bv_xor(expr const * e) const { return is_app_of(e, get_fid(), OP_BXOR); } + bool is_bv_nand(expr const * e) const { return is_app_of(e, get_fid(), OP_BNAND); } + bool is_bv_nor(expr const * e) const { return is_app_of(e, get_fid(), OP_BNOR); } + bool is_bv_not(expr const * e) const { return is_app_of(e, get_fid(), OP_BNOT); } + bool is_bv_ule(expr const * e) const { return is_app_of(e, get_fid(), OP_ULEQ); } + bool is_bv_sle(expr const * e) const { return is_app_of(e, get_fid(), OP_SLEQ); } + bool is_bit2bool(expr const * e) const { return is_app_of(e, get_fid(), OP_BIT2BOOL); } + bool is_bv2int(expr const* e) const { return is_app_of(e, get_fid(), OP_BV2INT); } + bool is_int2bv(expr const* e) const { return is_app_of(e, get_fid(), OP_INT2BV); } + bool is_mkbv(expr const * e) const { return is_app_of(e, get_fid(), OP_MKBV); } + bool is_bv_ashr(expr const * e) const { return is_app_of(e, get_fid(), OP_BASHR); } + bool is_bv_lshr(expr const * e) const { return is_app_of(e, get_fid(), OP_BLSHR); } + bool is_bv_shl(expr const * e) const { return is_app_of(e, get_fid(), OP_BSHL); } + bool is_sign_ext(expr const * e) const { return is_app_of(e, get_fid(), OP_SIGN_EXT); } + + MATCH_BINARY(is_bv_add); + MATCH_BINARY(is_bv_mul); + MATCH_BINARY(is_bv_sle); + MATCH_BINARY(is_bv_ule); + MATCH_BINARY(is_bv_shl); + + rational norm(rational const & val, unsigned bv_size, bool is_signed) const ; + rational norm(rational const & val, unsigned bv_size) const { return norm(val, bv_size, false); } + bool has_sign_bit(rational const & n, unsigned bv_size) const; + bool mult_inverse(rational const & n, unsigned bv_size, rational & result); + +}; + +class bv_util : public bv_recognizers { ast_manager & m_manager; bv_decl_plugin * m_plugin; @@ -282,29 +340,10 @@ public: ast_manager & get_manager() const { return m_manager; } - family_id get_fid() const { return m_plugin->get_family_id(); } - - family_id get_family_id() const { return get_fid(); } - - rational power_of_two(unsigned n) const { return m_plugin->power_of_two(n); } - - rational norm(rational const & val, unsigned bv_size, bool is_signed) const ; - rational norm(rational const & val, unsigned bv_size) const { return norm(val, bv_size, false); } - bool has_sign_bit(rational const & n, unsigned bv_size) const; app * mk_numeral(rational const & val, sort* s); app * mk_numeral(rational const & val, unsigned bv_size); app * mk_numeral(uint64 u, unsigned bv_size) { return mk_numeral(rational(u, rational::ui64()), bv_size); } sort * mk_sort(unsigned bv_size); - bool is_numeral(expr const * n, rational & val, unsigned & bv_size) const; - bool is_numeral(expr const * n) const { - return is_app_of(n, get_fid(), OP_BV_NUM); - } - bool is_allone(expr const * e) const; - bool is_zero(expr const * e) const; - bool is_bv_sort(sort const * s) const; - bool is_bv(expr const* e) const { - return is_bv_sort(m_manager.get_sort(e)); - } unsigned get_bv_size(sort const * s) const { SASSERT(is_bv_sort(s)); @@ -348,59 +387,6 @@ public: app * mk_bvumul_no_ovfl(expr* m, expr* n) { return m_manager.mk_app(get_fid(), OP_BUMUL_NO_OVFL, n, m); } app * mk_bv(unsigned n, expr* const* es) { return m_manager.mk_app(get_fid(), OP_MKBV, n, es); } - - bool is_concat(expr const * e) const { return is_app_of(e, get_fid(), OP_CONCAT); } - bool is_extract(func_decl const * f) const { return is_decl_of(f, get_fid(), OP_EXTRACT); } - bool is_extract(expr const * e) const { return is_app_of(e, get_fid(), OP_EXTRACT); } - unsigned get_extract_high(func_decl const * f) const { return f->get_parameter(0).get_int(); } - unsigned get_extract_low(func_decl const * f) const { return f->get_parameter(1).get_int(); } - unsigned get_extract_high(expr const * n) { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); } - unsigned get_extract_low(expr const * n) { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); } - bool is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) { - if (!is_extract(e)) return false; - low = get_extract_low(e); - high = get_extract_high(e); - b = to_app(e)->get_arg(0); - return true; - } - bool is_bv2int(expr const* e, expr*& r) { - if (!is_bv2int(e)) return false; - r = to_app(e)->get_arg(0); - return true; - } - bool is_bv_add(expr const * e) const { return is_app_of(e, get_fid(), OP_BADD); } - bool is_bv_sub(expr const * e) const { return is_app_of(e, get_fid(), OP_BSUB); } - bool is_bv_mul(expr const * e) const { return is_app_of(e, get_fid(), OP_BMUL); } - bool is_bv_neg(expr const * e) const { return is_app_of(e, get_fid(), OP_BNEG); } - bool is_bv_sdiv(expr const * e) const { return is_app_of(e, get_fid(), OP_BSDIV); } - bool is_bv_udiv(expr const * e) const { return is_app_of(e, get_fid(), OP_BUDIV); } - bool is_bv_srem(expr const * e) const { return is_app_of(e, get_fid(), OP_BSREM); } - bool is_bv_urem(expr const * e) const { return is_app_of(e, get_fid(), OP_BUREM); } - bool is_bv_smod(expr const * e) const { return is_app_of(e, get_fid(), OP_BSMOD); } - bool is_bv_and(expr const * e) const { return is_app_of(e, get_fid(), OP_BAND); } - bool is_bv_or(expr const * e) const { return is_app_of(e, get_fid(), OP_BOR); } - bool is_bv_xor(expr const * e) const { return is_app_of(e, get_fid(), OP_BXOR); } - bool is_bv_nand(expr const * e) const { return is_app_of(e, get_fid(), OP_BNAND); } - bool is_bv_nor(expr const * e) const { return is_app_of(e, get_fid(), OP_BNOR); } - bool is_bv_not(expr const * e) const { return is_app_of(e, get_fid(), OP_BNOT); } - bool is_bv_ule(expr const * e) const { return is_app_of(e, get_fid(), OP_ULEQ); } - bool is_bv_sle(expr const * e) const { return is_app_of(e, get_fid(), OP_SLEQ); } - bool is_bit2bool(expr const * e) const { return is_app_of(e, get_fid(), OP_BIT2BOOL); } - bool is_bv2int(expr const* e) const { return is_app_of(e, get_fid(), OP_BV2INT); } - bool is_int2bv(expr const* e) const { return is_app_of(e, get_fid(), OP_INT2BV); } - bool is_mkbv(expr const * e) const { return is_app_of(e, get_fid(), OP_MKBV); } - bool is_bv_ashr(expr const * e) const { return is_app_of(e, get_fid(), OP_BASHR); } - bool is_bv_lshr(expr const * e) const { return is_app_of(e, get_fid(), OP_BLSHR); } - bool is_bv_shl(expr const * e) const { return is_app_of(e, get_fid(), OP_BSHL); } - bool is_sign_ext(expr const * e) const { return is_app_of(e, get_fid(), OP_SIGN_EXT); } - - MATCH_BINARY(is_bv_add); - MATCH_BINARY(is_bv_mul); - MATCH_BINARY(is_bv_sle); - MATCH_BINARY(is_bv_ule); - MATCH_BINARY(is_bv_shl); - - bool mult_inverse(rational const & n, unsigned bv_size, rational & result); }; #endif /* _BV_DECL_PLUGIN_H_ */ diff --git a/src/ast/datatype_decl_plugin.cpp b/src/ast/datatype_decl_plugin.cpp index 5cf841b49..0714af28b 100644 --- a/src/ast/datatype_decl_plugin.cpp +++ b/src/ast/datatype_decl_plugin.cpp @@ -673,7 +673,7 @@ bool datatype_decl_plugin::is_value(app * e) const { datatype_util::datatype_util(ast_manager & m): m_manager(m), - m_family_id(m.get_family_id("datatype")), + m_family_id(m.mk_family_id("datatype")), m_asts(m) { } diff --git a/src/ast/decl_collector.cpp b/src/ast/decl_collector.cpp index a83bf6b99..b663a9df3 100644 --- a/src/ast/decl_collector.cpp +++ b/src/ast/decl_collector.cpp @@ -45,7 +45,7 @@ decl_collector::decl_collector(ast_manager & m, bool preds): m_manager(m), m_sep_preds(preds) { m_basic_fid = m_manager.get_basic_family_id(); - m_dt_fid = m_manager.get_family_id("datatype"); + m_dt_fid = m_manager.mk_family_id("datatype"); } void decl_collector::visit(ast* n) { diff --git a/src/ast/dl_decl_plugin.cpp b/src/ast/dl_decl_plugin.cpp index 5b73f944a..8ac19c11c 100644 --- a/src/ast/dl_decl_plugin.cpp +++ b/src/ast/dl_decl_plugin.cpp @@ -629,7 +629,7 @@ namespace datalog { m(m), m_arith(m), m_bv(m), - m_fid(m.get_family_id(symbol("datalog_relation"))) + m_fid(m.mk_family_id(symbol("datalog_relation"))) {} // create a constant belonging to a given finite domain. diff --git a/src/ast/float_decl_plugin.cpp b/src/ast/float_decl_plugin.cpp index dbe7d5232..7f6d7f764 100644 --- a/src/ast/float_decl_plugin.cpp +++ b/src/ast/float_decl_plugin.cpp @@ -31,7 +31,7 @@ float_decl_plugin::float_decl_plugin(): void float_decl_plugin::set_manager(ast_manager * m, family_id id) { decl_plugin::set_manager(m, id); - family_id aid = m_manager->get_family_id("arith"); + family_id aid = m_manager->mk_family_id("arith"); m_real_sort = m_manager->mk_sort(aid, REAL_SORT); SASSERT(m_real_sort != 0); // arith_decl_plugin must be installed before float_decl_plugin. m_manager->inc_ref(m_real_sort); @@ -42,7 +42,7 @@ void float_decl_plugin::set_manager(ast_manager * m, family_id id) { if (m_manager->has_plugin(symbol("bv"))) { // bv plugin is optional, so m_bv_plugin may be 0 - m_bv_fid = m_manager->get_family_id("bv"); + m_bv_fid = m_manager->mk_family_id("bv"); m_bv_plugin = static_cast(m_manager->get_plugin(m_bv_fid)); } } @@ -512,7 +512,7 @@ bool float_decl_plugin::is_value(app * e) const { float_util::float_util(ast_manager & m): m_manager(m), - m_fid(m.get_family_id("float")), + m_fid(m.mk_family_id("float")), m_a_util(m) { m_plugin = static_cast(m.get_plugin(m_fid)); } diff --git a/src/ast/format.cpp b/src/ast/format.cpp index 68ba5ea9a..1a36ca8ae 100644 --- a/src/ast/format.cpp +++ b/src/ast/format.cpp @@ -103,7 +103,7 @@ namespace format_ns { symbol f("format"); if (!fm(m).has_plugin(f)) fm(m).register_plugin(f, alloc(format_decl_plugin)); - return fm(m).get_family_id(f); + return fm(m).mk_family_id(f); } static family_id fid(ast_manager & m) { diff --git a/src/ast/macros/macro_util.cpp b/src/ast/macros/macro_util.cpp index 4e457d270..cc710a82e 100644 --- a/src/ast/macros/macro_util.cpp +++ b/src/ast/macros/macro_util.cpp @@ -41,7 +41,7 @@ macro_util::macro_util(ast_manager & m, simplifier & s): arith_simplifier_plugin * macro_util::get_arith_simp() const { if (m_arith_simp == 0) { - const_cast(this)->m_arith_simp = static_cast(m_simplifier.get_plugin(m_manager.get_family_id("arith"))); + const_cast(this)->m_arith_simp = static_cast(m_simplifier.get_plugin(m_manager.mk_family_id("arith"))); } SASSERT(m_arith_simp != 0); return m_arith_simp; @@ -49,7 +49,7 @@ arith_simplifier_plugin * macro_util::get_arith_simp() const { bv_simplifier_plugin * macro_util::get_bv_simp() const { if (m_bv_simp == 0) { - const_cast(this)->m_bv_simp = static_cast(m_simplifier.get_plugin(m_manager.get_family_id("bv"))); + const_cast(this)->m_bv_simp = static_cast(m_simplifier.get_plugin(m_manager.mk_family_id("bv"))); } SASSERT(m_bv_simp != 0); return m_bv_simp; diff --git a/src/ast/normal_forms/defined_names.cpp b/src/ast/normal_forms/defined_names.cpp index dab0ca0d8..16e9098fc 100644 --- a/src/ast/normal_forms/defined_names.cpp +++ b/src/ast/normal_forms/defined_names.cpp @@ -17,11 +17,67 @@ Revision History: --*/ #include"defined_names.h" +#include"obj_hashtable.h" #include"used_vars.h" #include"var_subst.h" #include"ast_smt2_pp.h" #include"ast_pp.h" +struct defined_names::impl { + typedef obj_map expr2name; + typedef obj_map expr2proof; + ast_manager & m_manager; + symbol m_z3name; + + /** + \brief Mapping from expressions to their names. A name is an application. + If the expression does not have free variables, then the name is just a constant. + */ + expr2name m_expr2name; + /** + \brief Mapping from expressions to the apply-def proof. + That is, for each expression e, m_expr2proof[e] is the + proof e and m_expr2name[2] are observ. equivalent. + + This mapping is not used if proof production is disabled. + */ + expr2proof m_expr2proof; + + /** + \brief Domain of m_expr2name. It is used to keep the expressions + alive and for backtracking + */ + expr_ref_vector m_exprs; + expr_ref_vector m_names; //!< Range of m_expr2name. It is used to keep the names alive. + proof_ref_vector m_apply_proofs; //!< Range of m_expr2proof. It is used to keep the def-intro proofs alive. + + + unsigned_vector m_lims; //!< Backtracking support. + + impl(ast_manager & m, char const * prefix); + virtual ~impl(); + + app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer & var_names); + void cache_new_name(expr * e, app * name); + void cache_new_name_intro_proof(expr * e, proof * pr); + void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref & result); + void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref_buffer & result); + virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def); + bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr); + void push_scope(); + void pop_scope(unsigned num_scopes); + void reset(); + + unsigned get_num_names() const { return m_names.size(); } + func_decl * get_name_decl(unsigned i) const { return to_app(m_names.get(i))->get_decl(); } +}; + +struct defined_names::pos_impl : public defined_names::impl { + pos_impl(ast_manager & m, char const * fresh_prefix):impl(m, fresh_prefix) {} + virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def); +}; + + defined_names::impl::impl(ast_manager & m, char const * prefix): m_manager(m), m_exprs(m), @@ -222,5 +278,50 @@ void defined_names::impl::reset() { m_lims.reset(); } +defined_names::defined_names(ast_manager & m, char const * fresh_prefix) { + m_impl = alloc(impl, m, fresh_prefix); + m_pos_impl = alloc(pos_impl, m, fresh_prefix); +} + +defined_names::~defined_names() { + dealloc(m_impl); + dealloc(m_pos_impl); +} + +bool defined_names::mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) { + return m_impl->mk_name(e, new_def, new_def_pr, n, pr); +} + +bool defined_names::mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) { + return m_pos_impl->mk_name(e, new_def, new_def_pr, n, pr); +} + +void defined_names::push() { + m_impl->push_scope(); + m_pos_impl->push_scope(); +} + +void defined_names::pop(unsigned num_scopes) { + m_impl->pop_scope(num_scopes); + m_pos_impl->pop_scope(num_scopes); +} + +void defined_names::reset() { + m_impl->reset(); + m_pos_impl->reset(); +} + +unsigned defined_names::get_num_names() const { + return m_impl->get_num_names() + m_pos_impl->get_num_names(); +} + +func_decl * defined_names::get_name_decl(unsigned i) const { + SASSERT(i < get_num_names()); + unsigned n1 = m_impl->get_num_names(); + return i < n1 ? m_impl->get_name_decl(i) : m_pos_impl->get_name_decl(i - n1); +} + + + diff --git a/src/ast/normal_forms/defined_names.h b/src/ast/normal_forms/defined_names.h index c5e4a116f..0b9f04569 100644 --- a/src/ast/normal_forms/defined_names.h +++ b/src/ast/normal_forms/defined_names.h @@ -21,7 +21,6 @@ Revision History: #define _DEFINED_NAMES_H_ #include"ast.h" -#include"obj_hashtable.h" /** \brief Mapping from expressions to skolem functions that are used to name them. @@ -29,62 +28,13 @@ Revision History: The mapping supports backtracking using the methods #push_scope and #pop_scope. */ class defined_names { - - struct impl { - typedef obj_map expr2name; - typedef obj_map expr2proof; - ast_manager & m_manager; - symbol m_z3name; - - /** - \brief Mapping from expressions to their names. A name is an application. - If the expression does not have free variables, then the name is just a constant. - */ - expr2name m_expr2name; - /** - \brief Mapping from expressions to the apply-def proof. - That is, for each expression e, m_expr2proof[e] is the - proof e and m_expr2name[2] are observ. equivalent. - - This mapping is not used if proof production is disabled. - */ - expr2proof m_expr2proof; - - /** - \brief Domain of m_expr2name. It is used to keep the expressions - alive and for backtracking - */ - expr_ref_vector m_exprs; - expr_ref_vector m_names; //!< Range of m_expr2name. It is used to keep the names alive. - proof_ref_vector m_apply_proofs; //!< Range of m_expr2proof. It is used to keep the def-intro proofs alive. - - - unsigned_vector m_lims; //!< Backtracking support. - - impl(ast_manager & m, char const * prefix); - virtual ~impl(); - - app * gen_name(expr * e, sort_ref_buffer & var_sorts, buffer & var_names); - void cache_new_name(expr * e, app * name); - void cache_new_name_intro_proof(expr * e, proof * pr); - void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref & result); - void bound_vars(sort_ref_buffer const & sorts, buffer const & names, expr * def_conjunct, app * name, expr_ref_buffer & result); - virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def); - bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr); - void push_scope(); - void pop_scope(unsigned num_scopes); - void reset(); - }; - - struct pos_impl : public impl { - pos_impl(ast_manager & m, char const * fresh_prefix):impl(m, fresh_prefix) {} - virtual void mk_definition(expr * e, app * n, sort_ref_buffer & var_sorts, buffer const & var_names, expr_ref & new_def); - }; - - impl m_impl; - pos_impl m_pos_impl; + struct impl; + struct pos_impl; + impl * m_impl; + pos_impl * m_pos_impl; public: - defined_names(ast_manager & m, char const * fresh_prefix = "z3name"):m_impl(m, fresh_prefix), m_pos_impl(m, fresh_prefix) {} + defined_names(ast_manager & m, char const * fresh_prefix = "z3name"); + ~defined_names(); // ----------------------------------- // @@ -113,9 +63,7 @@ public: Remark: the definitions are closed with an universal quantifier if e contains free variables. */ - bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) { - return m_impl.mk_name(e, new_def, new_def_pr, n, pr); - } + bool mk_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr); /** \brief Create a name for a positive occurrence of the expression \c e. @@ -127,24 +75,14 @@ public: Remark: the definitions are closed with an universal quantifier if e contains free variables. */ - bool mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr) { - return m_pos_impl.mk_name(e, new_def, new_def_pr, n, pr); - } + bool mk_pos_name(expr * e, expr_ref & new_def, proof_ref & new_def_pr, app_ref & n, proof_ref & pr); - void push_scope() { - m_impl.push_scope(); - m_pos_impl.push_scope(); - } + void push(); + void pop(unsigned num_scopes); + void reset(); - void pop_scope(unsigned num_scopes) { - m_impl.pop_scope(num_scopes); - m_pos_impl.pop_scope(num_scopes); - } - - void reset() { - m_impl.reset(); - m_pos_impl.reset(); - } + unsigned get_num_names() const; + func_decl * get_name_decl(unsigned i) const; }; #endif /* _DEFINED_NAMES_H_ */ diff --git a/src/ast/pattern/pattern_inference.cpp b/src/ast/pattern/pattern_inference.cpp index 773b9a2f5..83362f5b3 100644 --- a/src/ast/pattern/pattern_inference.cpp +++ b/src/ast/pattern/pattern_inference.cpp @@ -91,7 +91,7 @@ pattern_inference::pattern_inference(ast_manager & m, pattern_inference_params & simplifier(m), m_params(params), m_bfid(m.get_basic_family_id()), - m_afid(m.get_family_id("arith")), + m_afid(m.mk_family_id("arith")), m_le(m), m_nested_arith_only(true), m_block_loop_patterns(params.m_pi_block_loop_patterns), diff --git a/src/ast/pattern/pattern_inference.h b/src/ast/pattern/pattern_inference.h index 1a179e794..97897835c 100644 --- a/src/ast/pattern/pattern_inference.h +++ b/src/ast/pattern/pattern_inference.h @@ -150,7 +150,7 @@ class pattern_inference : public simplifier { void save_candidate(expr * n, unsigned delta); void reset(); public: - collect(ast_manager & m, pattern_inference & o):m_manager(m), m_owner(o), m_afid(m.get_family_id("arith")) {} + collect(ast_manager & m, pattern_inference & o):m_manager(m), m_owner(o), m_afid(m.mk_family_id("arith")) {} void operator()(expr * n, unsigned num_bindings); }; diff --git a/src/ast/proof_checker/proof_checker.cpp b/src/ast/proof_checker/proof_checker.cpp index 240504048..85e0cc791 100644 --- a/src/ast/proof_checker/proof_checker.cpp +++ b/src/ast/proof_checker/proof_checker.cpp @@ -85,7 +85,7 @@ proof_checker::proof_checker(ast_manager& m) : m(m), m_todo(m), m_marked(), m_pi if (!m.has_plugin(fam_name)) { m.register_plugin(fam_name, alloc(hyp_decl_plugin)); } - m_hyp_fid = m.get_family_id(fam_name); + m_hyp_fid = m.mk_family_id(fam_name); // m_spc_fid = m.get_family_id("spc"); m_nil = m.mk_const(m_hyp_fid, OP_NIL); } diff --git a/src/ast/reg_decl_plugins.cpp b/src/ast/reg_decl_plugins.cpp index fd4d49789..ab1844e07 100644 --- a/src/ast/reg_decl_plugins.cpp +++ b/src/ast/reg_decl_plugins.cpp @@ -27,25 +27,25 @@ Revision History: #include"float_decl_plugin.h" void reg_decl_plugins(ast_manager & m) { - if (!m.get_plugin(m.get_family_id(symbol("arith")))) { + if (!m.get_plugin(m.mk_family_id(symbol("arith")))) { m.register_plugin(symbol("arith"), alloc(arith_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("bv")))) { + if (!m.get_plugin(m.mk_family_id(symbol("bv")))) { m.register_plugin(symbol("bv"), alloc(bv_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("array")))) { + if (!m.get_plugin(m.mk_family_id(symbol("array")))) { m.register_plugin(symbol("array"), alloc(array_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("datatype")))) { + if (!m.get_plugin(m.mk_family_id(symbol("datatype")))) { m.register_plugin(symbol("datatype"), alloc(datatype_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("datalog_relation")))) { + if (!m.get_plugin(m.mk_family_id(symbol("datalog_relation")))) { m.register_plugin(symbol("datalog_relation"), alloc(datalog::dl_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("seq")))) { + if (!m.get_plugin(m.mk_family_id(symbol("seq")))) { m.register_plugin(symbol("seq"), alloc(seq_decl_plugin)); } - if (!m.get_plugin(m.get_family_id(symbol("float")))) { + if (!m.get_plugin(m.mk_family_id(symbol("float")))) { m.register_plugin(symbol("float"), alloc(float_decl_plugin)); } } diff --git a/src/ast/rewriter/bit_blaster/bit_blaster.h b/src/ast/rewriter/bit_blaster/bit_blaster.h index 42444aebc..7b317c6cb 100644 --- a/src/ast/rewriter/bit_blaster/bit_blaster.h +++ b/src/ast/rewriter/bit_blaster/bit_blaster.h @@ -36,7 +36,7 @@ public: bit_blaster_cfg(bv_util & u, bit_blaster_params const & p, basic_simplifier_plugin & _s); ast_manager & m() const { return m_util.get_manager(); } - numeral power(unsigned n) const { return m_util.power_of_two(n); } + numeral power(unsigned n) const { return rational::power_of_two(n); } void mk_xor(expr * a, expr * b, expr_ref & r) { s.mk_xor(a, b, r); } void mk_xor3(expr * a, expr * b, expr * c, expr_ref & r); void mk_carry(expr * a, expr * b, expr * c, expr_ref & r); diff --git a/src/ast/rewriter/bit_blaster/bit_blaster_rewriter.cpp b/src/ast/rewriter/bit_blaster/bit_blaster_rewriter.cpp index 1fd83e91f..80d319377 100644 --- a/src/ast/rewriter/bit_blaster/bit_blaster_rewriter.cpp +++ b/src/ast/rewriter/bit_blaster/bit_blaster_rewriter.cpp @@ -32,7 +32,7 @@ struct blaster_cfg { blaster_cfg(bool_rewriter & r, bv_util & u):m_rewriter(r), m_util(u) {} ast_manager & m() const { return m_util.get_manager(); } - numeral power(unsigned n) const { return m_util.power_of_two(n); } + numeral power(unsigned n) const { return rational::power_of_two(n); } void mk_xor(expr * a, expr * b, expr_ref & r) { m_rewriter.mk_xor(a, b, r); } void mk_xor3(expr * a, expr * b, expr * c, expr_ref & r) { expr_ref tmp(m()); diff --git a/src/ast/rewriter/bool_rewriter.cpp b/src/ast/rewriter/bool_rewriter.cpp index b5f18a461..5b0c38616 100644 --- a/src/ast/rewriter/bool_rewriter.cpp +++ b/src/ast/rewriter/bool_rewriter.cpp @@ -27,6 +27,7 @@ void bool_rewriter::updt_params(params_ref const & _p) { m_local_ctx = p.local_ctx(); m_local_ctx_limit = p.local_ctx_limit(); m_blast_distinct = p.blast_distinct(); + m_blast_distinct_threshold = p.blast_distinct_threshold(); m_ite_extra_rules = p.ite_extra_rules(); } @@ -746,7 +747,7 @@ br_status bool_rewriter::mk_distinct_core(unsigned num_args, expr * const * args return BR_DONE; } - if (m_blast_distinct) { + if (m_blast_distinct && num_args < m_blast_distinct_threshold) { ptr_buffer new_diseqs; for (unsigned i = 0; i < num_args; i++) { for (unsigned j = i + 1; j < num_args; j++) diff --git a/src/ast/rewriter/bool_rewriter.h b/src/ast/rewriter/bool_rewriter.h index b1a177247..ef6dc2d38 100644 --- a/src/ast/rewriter/bool_rewriter.h +++ b/src/ast/rewriter/bool_rewriter.h @@ -55,6 +55,7 @@ class bool_rewriter { bool m_local_ctx; bool m_elim_and; bool m_blast_distinct; + unsigned m_blast_distinct_threshold; bool m_ite_extra_rules; unsigned m_local_ctx_limit; unsigned m_local_ctx_cost; diff --git a/src/ast/rewriter/bool_rewriter_params.pyg b/src/ast/rewriter/bool_rewriter_params.pyg index a5bcf6f5d..531bf4db9 100644 --- a/src/ast/rewriter/bool_rewriter_params.pyg +++ b/src/ast/rewriter/bool_rewriter_params.pyg @@ -6,4 +6,6 @@ def_module_params(module_name='rewriter', ("elim_and", BOOL, False, "conjunctions are rewritten using negation and disjunctions"), ("local_ctx", BOOL, False, "perform local (i.e., cheap) context simplifications"), ("local_ctx_limit", UINT, UINT_MAX, "limit for applying local context simplifier"), - ("blast_distinct", BOOL, False, "expand a distinct predicate into a quadratic number of disequalities"))) + ("blast_distinct", BOOL, False, "expand a distinct predicate into a quadratic number of disequalities"), + ("blast_distinct_threshold", UINT, UINT_MAX, "when blast_distinct is true, only distinct expressions with less than this number of arguments are blasted") + )) diff --git a/src/ast/rewriter/bv_rewriter.cpp b/src/ast/rewriter/bv_rewriter.cpp index 5fd562676..f8ff27337 100644 --- a/src/ast/rewriter/bv_rewriter.cpp +++ b/src/ast/rewriter/bv_rewriter.cpp @@ -283,12 +283,12 @@ br_status bv_rewriter::mk_leq_core(bool is_signed, expr * a, expr * b, expr_ref if (is_num1 || is_num2) { if (is_signed) { - lower = - m_util.power_of_two(sz - 1); - upper = m_util.power_of_two(sz - 1) - numeral(1); + lower = - rational::power_of_two(sz - 1); + upper = rational::power_of_two(sz - 1) - numeral(1); } else { lower = numeral(0); - upper = m_util.power_of_two(sz) - numeral(1); + upper = rational::power_of_two(sz) - numeral(1); } } @@ -387,14 +387,14 @@ br_status bv_rewriter::mk_extract(unsigned high, unsigned low, expr * arg, expr_ if (is_numeral(arg, v, sz)) { sz = high - low + 1; if (v.is_neg()) - mod(v, m_util.power_of_two(sz), v); + mod(v, rational::power_of_two(sz), v); if (v.is_uint64()) { uint64 u = v.get_uint64(); uint64 e = shift_right(u, low) & (shift_left(1ull, sz) - 1ull); result = mk_numeral(numeral(e, numeral::ui64()), sz); return BR_DONE; } - div(v, m_util.power_of_two(low), v); + div(v, rational::power_of_two(low), v); result = mk_numeral(v, sz); return BR_DONE; } @@ -519,7 +519,7 @@ br_status bv_rewriter::mk_bv_shl(expr * arg1, expr * arg2, expr_ref & result) { SASSERT(r2 < numeral(bv_size)); SASSERT(r2.is_unsigned()); - r1 = m_util.norm(r1 * m_util.power_of_two(r2.get_unsigned()), bv_size); + r1 = m_util.norm(r1 * rational::power_of_two(r2.get_unsigned()), bv_size); result = mk_numeral(r1, bv_size); return BR_DONE; } @@ -567,7 +567,7 @@ br_status bv_rewriter::mk_bv_lshr(expr * arg1, expr * arg2, expr_ref & result) { SASSERT(r2.is_unsigned()); unsigned sh = r2.get_unsigned(); - div(r1, m_util.power_of_two(sh), r1); + div(r1, rational::power_of_two(sh), r1); result = mk_numeral(r1, bv_size); return BR_DONE; } @@ -626,7 +626,7 @@ br_status bv_rewriter::mk_bv_ashr(expr * arg1, expr * arg2, expr_ref & result) { if (is_num1 && is_num2 && numeral(bv_size) <= r2) { if (m_util.has_sign_bit(r1, bv_size)) - result = mk_numeral(m_util.power_of_two(bv_size) - numeral(1), bv_size); + result = mk_numeral(rational::power_of_two(bv_size) - numeral(1), bv_size); else result = mk_numeral(0, bv_size); return BR_DONE; @@ -635,7 +635,7 @@ br_status bv_rewriter::mk_bv_ashr(expr * arg1, expr * arg2, expr_ref & result) { if (is_num1 && is_num2) { SASSERT(r2 < numeral(bv_size)); bool sign = m_util.has_sign_bit(r1, bv_size); - div(r1, m_util.power_of_two(r2.get_unsigned()), r1); + div(r1, rational::power_of_two(r2.get_unsigned()), r1); if (sign) { // pad ones. numeral p(1); @@ -697,7 +697,7 @@ br_status bv_rewriter::mk_bv_sdiv_core(expr * arg1, expr * arg2, bool hi_div0, e // The "hardware interpretation" for (bvsdiv x 0) is (ite (bvslt x #x0000) #x0001 #xffff) result = m().mk_ite(m().mk_app(get_fid(), OP_SLT, arg1, mk_numeral(0, bv_size)), mk_numeral(1, bv_size), - mk_numeral(m_util.power_of_two(bv_size) - numeral(1), bv_size)); + mk_numeral(rational::power_of_two(bv_size) - numeral(1), bv_size)); return BR_REWRITE2; } } @@ -746,7 +746,7 @@ br_status bv_rewriter::mk_bv_udiv_core(expr * arg1, expr * arg2, bool hi_div0, e } else { // The "hardware interpretation" for (bvudiv x 0) is #xffff - result = mk_numeral(m_util.power_of_two(bv_size) - numeral(1), bv_size); + result = mk_numeral(rational::power_of_two(bv_size) - numeral(1), bv_size); return BR_DONE; } @@ -845,7 +845,7 @@ bool bv_rewriter::is_minus_one_core(expr * arg) const { numeral r; unsigned bv_size; if (is_numeral(arg, r, bv_size)) { - return r == (m_util.power_of_two(bv_size) - numeral(1)); + return r == (rational::power_of_two(bv_size) - numeral(1)); } return false; } @@ -924,7 +924,7 @@ br_status bv_rewriter::mk_bv_urem_core(expr * arg1, expr * arg2, bool hi_div0, e if (is_x_minus_one(arg1, x) && x == arg2) { bv_size = get_bv_size(arg1); expr * x_minus_1 = arg1; - expr * minus_one = mk_numeral(m_util.power_of_two(bv_size) - numeral(1), bv_size); + expr * minus_one = mk_numeral(rational::power_of_two(bv_size) - numeral(1), bv_size); result = m().mk_ite(m().mk_eq(x, mk_numeral(0, bv_size)), m().mk_app(get_fid(), OP_BUREM0, minus_one), x_minus_1); @@ -1068,7 +1068,7 @@ br_status bv_rewriter::mk_concat(unsigned num_args, expr * const * args, expr_re if (i > 0) prev = new_args.back(); if (is_numeral(arg, v1, sz1) && prev != 0 && is_numeral(prev, v2, sz2)) { - v2 *= m_util.power_of_two(sz1); + v2 *= rational::power_of_two(sz1); v2 += v1; new_args.pop_back(); new_args.push_back(mk_numeral(v2, sz1+sz2)); @@ -1137,7 +1137,7 @@ br_status bv_rewriter::mk_sign_extend(unsigned n, expr * arg, expr_ref & result) if (is_numeral(arg, r, bv_size)) { unsigned result_bv_size = bv_size + n; r = m_util.norm(r, bv_size, true); - mod(r, m_util.power_of_two(result_bv_size), r); + mod(r, rational::power_of_two(result_bv_size), r); result = mk_numeral(r, result_bv_size); return BR_DONE; } @@ -1213,7 +1213,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re if (m_util.is_bv_not(arg)) { expr * atom = to_app(arg)->get_arg(0); if (pos_args.is_marked(atom)) { - result = mk_numeral(m_util.power_of_two(sz) - numeral(1), sz); + result = mk_numeral(rational::power_of_two(sz) - numeral(1), sz); return BR_DONE; } else if (neg_args.is_marked(atom)) { @@ -1229,7 +1229,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re continue; } else if (neg_args.is_marked(arg)) { - result = mk_numeral(m_util.power_of_two(sz) - numeral(1), sz); + result = mk_numeral(rational::power_of_two(sz) - numeral(1), sz); return BR_DONE; } pos_args.mark(arg, true); @@ -1237,7 +1237,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re } } - if (v1 == m_util.power_of_two(sz) - numeral(1)) { + if (v1 == rational::power_of_two(sz) - numeral(1)) { result = mk_numeral(v1, sz); return BR_DONE; } @@ -1294,7 +1294,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re } if (i != low) { unsigned num_sz = i - low; - exs.push_back(m_util.mk_numeral(m_util.power_of_two(num_sz) - numeral(1), num_sz)); + exs.push_back(m_util.mk_numeral(rational::power_of_two(num_sz) - numeral(1), num_sz)); low = i; } while (i < sz && mod(v1, two).is_zero()) { @@ -1385,7 +1385,7 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r else if (pos_args.is_marked(atom)) { pos_args.mark(atom, false); merged = true; - v1 = bitwise_xor(v1, m_util.power_of_two(sz) - numeral(1)); + v1 = bitwise_xor(v1, rational::power_of_two(sz) - numeral(1)); } else { neg_args.mark(atom, true); @@ -1399,7 +1399,7 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r else if (neg_args.is_marked(arg)) { neg_args.mark(arg, false); merged = true; - v1 = bitwise_xor(v1, m_util.power_of_two(sz) - numeral(1)); + v1 = bitwise_xor(v1, rational::power_of_two(sz) - numeral(1)); } else { pos_args.mark(arg, true); @@ -1455,7 +1455,7 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r return BR_REWRITE3; } - if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (m_util.power_of_two(sz) - numeral(1))))) + if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (rational::power_of_two(sz) - numeral(1))))) return BR_FAILED; ptr_buffer new_args; @@ -1611,7 +1611,7 @@ br_status bv_rewriter::mk_bv_redand(expr * arg, expr_ref & result) { numeral r; unsigned bv_size; if (is_numeral(arg, r, bv_size)) { - result = (r == m_util.power_of_two(bv_size) - numeral(1)) ? mk_numeral(1, 1) : mk_numeral(0, 1); + result = (r == rational::power_of_two(bv_size) - numeral(1)) ? mk_numeral(1, 1) : mk_numeral(0, 1); return BR_DONE; } return BR_FAILED; @@ -1707,7 +1707,7 @@ bool bv_rewriter::is_zero_bit(expr * x, unsigned idx) { if (is_numeral(x, val, bv_size)) { if (val.is_zero()) return true; - div(val, m_util.power_of_two(idx), val); + div(val, rational::power_of_two(idx), val); return (val % numeral(2)).is_zero(); } if (m_util.is_concat(x)) { diff --git a/src/ast/rewriter/float_rewriter.cpp b/src/ast/rewriter/float_rewriter.cpp index 9678af216..482e280e3 100644 --- a/src/ast/rewriter/float_rewriter.cpp +++ b/src/ast/rewriter/float_rewriter.cpp @@ -443,4 +443,4 @@ br_status float_rewriter::mk_eq_core(expr * arg1, expr * arg2, expr_ref & result br_status float_rewriter::mk_to_ieee_bv(expr * arg1, expr_ref & result) { return BR_FAILED; -} \ No newline at end of file +} diff --git a/src/ast/simplifier/bv_elim.cpp b/src/ast/simplifier/bv_elim.cpp index 3238d13e7..5c19a245e 100644 --- a/src/ast/simplifier/bv_elim.cpp +++ b/src/ast/simplifier/bv_elim.cpp @@ -15,7 +15,7 @@ void bv_elim::elim(quantifier* q, quantifier_ref& r) { expr_ref new_body(m_manager); expr* old_body = q->get_expr(); unsigned num_decls = q->get_num_decls(); - family_id bfid = m_manager.get_family_id("bv"); + family_id bfid = m_manager.mk_family_id("bv"); // // Traverse sequence of bound variables to eliminate diff --git a/src/ast/simplifier/bv_simplifier_plugin.cpp b/src/ast/simplifier/bv_simplifier_plugin.cpp index 2da1f3bab..3ef55baba 100644 --- a/src/ast/simplifier/bv_simplifier_plugin.cpp +++ b/src/ast/simplifier/bv_simplifier_plugin.cpp @@ -76,9 +76,9 @@ app * bv_simplifier_plugin::mk_numeral(numeral const & n) { } app * bv_simplifier_plugin::mk_numeral(numeral const& n, unsigned bv_size) { - numeral r = mod(n, m_util.power_of_two(bv_size)); + numeral r = mod(n, rational::power_of_two(bv_size)); SASSERT(!r.is_neg()); - SASSERT(r < m_util.power_of_two(bv_size)); + SASSERT(r < rational::power_of_two(bv_size)); return m_util.mk_numeral(r, bv_size); } @@ -225,7 +225,7 @@ inline uint64 bv_simplifier_plugin::to_uint64(const numeral & n, unsigned bv_siz SASSERT(bv_size <= 64); numeral tmp = n; if (tmp.is_neg()) { - tmp = mod(tmp, m_util.power_of_two(bv_size)); + tmp = mod(tmp, rational::power_of_two(bv_size)); } SASSERT(tmp.is_nonneg()); SASSERT(tmp.is_uint64()); @@ -235,7 +235,7 @@ inline uint64 bv_simplifier_plugin::to_uint64(const numeral & n, unsigned bv_siz #define MK_BV_OP(_oper_,_binop_) \ rational bv_simplifier_plugin::mk_bv_ ## _oper_(numeral const& a0, numeral const& b0, unsigned sz) { \ rational r(0), a(a0), b(b0); \ - numeral p64 = m_util.power_of_two(64); \ + numeral p64 = rational::power_of_two(64); \ numeral mul(1); \ while (sz > 0) { \ numeral a1 = a % p64; \ @@ -260,7 +260,7 @@ MK_BV_OP(xor,^) rational bv_simplifier_plugin::mk_bv_not(numeral const& a0, unsigned sz) { rational r(0), a(a0), mul(1); - numeral p64 = m_util.power_of_two(64); + numeral p64 = rational::power_of_two(64); while (sz > 0) { numeral a1 = a % p64; uint64 u = ~a1.get_uint64(); @@ -320,12 +320,12 @@ void bv_simplifier_plugin::mk_leq_core(bool is_signed, expr * arg1, expr * arg2, if (is_num1 || is_num2) { if (is_signed) { - lower = - m_util.power_of_two(bv_size - 1); - upper = m_util.power_of_two(bv_size - 1) - numeral(1); + lower = - rational::power_of_two(bv_size - 1); + upper = rational::power_of_two(bv_size - 1) - numeral(1); } else { lower = numeral(0); - upper = m_util.power_of_two(bv_size) - numeral(1); + upper = rational::power_of_two(bv_size) - numeral(1); } } @@ -509,7 +509,7 @@ bool bv_simplifier_plugin::try_mk_extract(unsigned high, unsigned low, expr * ar if (m_util.is_numeral(a, r, num_bits)) { if (r.is_neg()) { - r = mod(r, m_util.power_of_two(sz)); + r = mod(r, rational::power_of_two(sz)); } SASSERT(r.is_nonneg()); if (r.is_uint64()) { @@ -520,7 +520,7 @@ bool bv_simplifier_plugin::try_mk_extract(unsigned high, unsigned low, expr * ar result = mk_numeral(numeral(e, numeral::ui64()), sz); return true; } - result = mk_numeral(div(r, m_util.power_of_two(low)), sz); + result = mk_numeral(div(r, rational::power_of_two(low)), sz); return true; } // (extract[high:low] (extract[high2:low2] x)) == (extract[high+low2 : low+low2] x) @@ -902,7 +902,7 @@ void bv_simplifier_plugin::mk_concat(unsigned num_args, expr * const * args, exp --i; expr * arg = args[i]; if (is_numeral(arg, arg_val)) { - arg_val *= m_util.power_of_two(shift); + arg_val *= rational::power_of_two(shift); val += arg_val; shift += get_bv_size(arg); TRACE("bv_simplifier_plugin", @@ -1203,7 +1203,7 @@ bool bv_simplifier_plugin::is_minus_one_core(expr * arg) const { unsigned bv_size; if (m_util.is_numeral(arg, r, bv_size)) { numeral minus_one(-1); - minus_one = mod(minus_one, m_util.power_of_two(bv_size)); + minus_one = mod(minus_one, rational::power_of_two(bv_size)); return r == minus_one; } return false; @@ -1295,7 +1295,7 @@ void bv_simplifier_plugin::mk_sign_extend(unsigned n, expr * arg, expr_ref & res if (m_util.is_numeral(arg, r, bv_size)) { unsigned result_bv_size = bv_size + n; r = norm(r, bv_size, true); - r = mod(r, m_util.power_of_two(result_bv_size)); + r = mod(r, rational::power_of_two(result_bv_size)); result = mk_numeral(r, result_bv_size); TRACE("mk_sign_extend", tout << "n: " << n << "\n"; ast_ll_pp(tout, m_manager, arg); tout << "====>\n"; @@ -1373,7 +1373,7 @@ void bv_simplifier_plugin::mk_bv_shl(expr * arg1, expr * arg2, expr_ref & result else if (is_num1 && is_num2) { SASSERT(r2 < rational(bv_size)); SASSERT(r2.is_unsigned()); - result = mk_numeral(r1 * m_util.power_of_two(r2.get_unsigned()), bv_size); + result = mk_numeral(r1 * rational::power_of_two(r2.get_unsigned()), bv_size); } // @@ -1423,7 +1423,7 @@ void bv_simplifier_plugin::mk_bv_lshr(expr * arg1, expr * arg2, expr_ref & resul else if (is_num1 && is_num2) { SASSERT(r2.is_unsigned()); unsigned sh = r2.get_unsigned(); - r1 = div(r1, m_util.power_of_two(sh)); + r1 = div(r1, rational::power_of_two(sh)); result = mk_numeral(r1, bv_size); } // @@ -1804,8 +1804,8 @@ void bv_simplifier_plugin::mk_bv_rotate_left_core(unsigned shift, numeral r, uns result = mk_numeral(r, bv_size); } else { - rational r1 = div(r, m_util.power_of_two(bv_size - shift)); // shift right - rational r2 = (r * m_util.power_of_two(shift)) % m_util.power_of_two(bv_size); // shift left + rational r1 = div(r, rational::power_of_two(bv_size - shift)); // shift right + rational r2 = (r * rational::power_of_two(shift)) % rational::power_of_two(bv_size); // shift left result = mk_numeral(r1 + r2, bv_size); } } @@ -1831,8 +1831,8 @@ void bv_simplifier_plugin::mk_bv_rotate_right_core(unsigned shift, numeral r, un result = mk_numeral(r, bv_size); } else { - rational r1 = div(r, m_util.power_of_two(shift)); // shift right - rational r2 = (r * m_util.power_of_two(bv_size - shift)) % m_util.power_of_two(bv_size); // shift left + rational r1 = div(r, rational::power_of_two(shift)); // shift right + rational r2 = (r * rational::power_of_two(bv_size - shift)) % rational::power_of_two(bv_size); // shift left result = mk_numeral(r1 + r2, bv_size); } } @@ -1935,7 +1935,7 @@ void bv_simplifier_plugin::mk_bv_ashr(expr* arg1, expr* arg2, expr_ref& result) else if (is_num1 && is_num2) { SASSERT(r2 < rational(bv_size)); bool sign = has_sign_bit(r1, bv_size); - r1 = div(r1, m_util.power_of_two(r2.get_unsigned())); + r1 = div(r1, rational::power_of_two(r2.get_unsigned())); if (sign) { // pad ones. rational p(1); diff --git a/src/ast/simplifier/bv_simplifier_plugin.h b/src/ast/simplifier/bv_simplifier_plugin.h index 7f66566b6..36e773de0 100644 --- a/src/ast/simplifier/bv_simplifier_plugin.h +++ b/src/ast/simplifier/bv_simplifier_plugin.h @@ -172,7 +172,7 @@ public: app * mk_numeral(rational const & n, unsigned bv_size); app * mk_numeral(uint64 n, unsigned bv_size) { return mk_numeral(numeral(n, numeral::ui64()), bv_size); } app* mk_bv0(unsigned bv_size) { return m_util.mk_numeral(numeral(0), bv_size); } - rational mk_allone(unsigned bv_size) { return m_util.power_of_two(bv_size) - numeral(1); } + rational mk_allone(unsigned bv_size) { return rational::power_of_two(bv_size) - numeral(1); } bool is_minus_one_core(expr * arg) const; bool is_x_minus_one(expr * arg, expr * & x); void mk_int2bv(expr * arg, sort* range, expr_ref & result); diff --git a/src/ast/simplifier/simplifier_plugin.h b/src/ast/simplifier/simplifier_plugin.h index d95547a69..8e176ea6e 100644 --- a/src/ast/simplifier/simplifier_plugin.h +++ b/src/ast/simplifier/simplifier_plugin.h @@ -37,7 +37,7 @@ protected: void set_reduce_invoked() { m_reduce_invoked = true; } public: - simplifier_plugin(symbol const & fname, ast_manager & m):m_manager(m), m_fid(m.get_family_id(fname)), m_presimp(false), m_reduce_invoked(false) {} + simplifier_plugin(symbol const & fname, ast_manager & m):m_manager(m), m_fid(m.mk_family_id(fname)), m_presimp(false), m_reduce_invoked(false) {} bool reduce_invoked() const { return m_reduce_invoked; } diff --git a/src/ast/static_features.cpp b/src/ast/static_features.cpp index 234626365..f40eb2c75 100644 --- a/src/ast/static_features.cpp +++ b/src/ast/static_features.cpp @@ -23,8 +23,8 @@ static_features::static_features(ast_manager & m): m_manager(m), m_autil(m), m_bfid(m.get_basic_family_id()), - m_afid(m.get_family_id("arith")), - m_lfid(m.get_family_id("label")), + m_afid(m.mk_family_id("arith")), + m_lfid(m.mk_family_id("label")), m_label_sym("label"), m_pattern_sym("pattern"), m_expr_list_sym("expr-list") { diff --git a/src/cmd_context/basic_cmds.cpp b/src/cmd_context/basic_cmds.cpp index 8f65485ae..c1be7a69b 100644 --- a/src/cmd_context/basic_cmds.cpp +++ b/src/cmd_context/basic_cmds.cpp @@ -643,7 +643,7 @@ public: family_id get_array_fid(cmd_context & ctx) { if (m_array_fid == null_family_id) { - m_array_fid = ctx.m().get_family_id("array"); + m_array_fid = ctx.m().mk_family_id("array"); } return m_array_fid; } diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 828cc3a68..043dc45e6 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -343,6 +343,13 @@ cmd_context::~cmd_context() { m_check_sat_result = 0; } +void cmd_context::set_cancel(bool f) { + if (m_solver) + m_solver->set_cancel(f); + if (has_manager()) + m().set_cancel(f); +} + void cmd_context::global_params_updated() { m_params.updt_params(); if (m_solver) { @@ -582,8 +589,8 @@ void cmd_context::init_manager_core(bool new_manager) { // it prevents clashes with builtin types. insert(pm().mk_plist_decl()); } - if (m_solver) { - init_solver_options(m_solver.get()); + if (m_solver_factory) { + mk_solver(); } m_check_logic.set_logic(m(), m_logic); } @@ -1119,7 +1126,7 @@ void cmd_context::reset(bool finalize) { reset_func_decls(); restore_assertions(0); if (m_solver) - m_solver->reset(); + m_solver = 0; m_pp_env = 0; m_dt_eh = 0; if (m_manager) { @@ -1379,7 +1386,7 @@ void cmd_context::set_diagnostic_stream(char const * name) { struct contains_array_op_proc { struct found {}; family_id m_array_fid; - contains_array_op_proc(ast_manager & m):m_array_fid(m.get_family_id("array")) {} + contains_array_op_proc(ast_manager & m):m_array_fid(m.mk_family_id("array")) {} void operator()(var * n) {} void operator()(app * n) { if (n->get_family_id() != m_array_fid) @@ -1441,17 +1448,18 @@ void cmd_context::validate_model() { } } -void cmd_context::init_solver_options(solver * s) { +void cmd_context::mk_solver() { + bool proofs_enabled, models_enabled, unsat_core_enabled; params_ref p; - m_params.init_solver_params(m(), *m_solver, p); - m_solver->init(m(), m_logic); + m_params.get_solver_params(m(), p, proofs_enabled, models_enabled, unsat_core_enabled); + m_solver = (*m_solver_factory)(m(), p, proofs_enabled, models_enabled, unsat_core_enabled, m_logic); } -void cmd_context::set_solver(solver * s) { +void cmd_context::set_solver_factory(solver_factory * f) { + m_solver_factory = f; m_check_sat_result = 0; - m_solver = s; - if (has_manager() && s != 0) { - init_solver_options(s); + if (has_manager() && f != 0) { + mk_solver(); // assert formulas and create scopes in the new solver. unsigned lim = 0; svector::iterator it = m_scopes.begin(); diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 2edc87ca6..07b0cf456 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -185,6 +185,7 @@ protected: }; svector m_scopes; + scoped_ptr m_solver_factory; ref m_solver; ref m_check_sat_result; @@ -243,11 +244,14 @@ protected: void print_unsupported_msg() { regular_stream() << "unsupported" << std::endl; } void print_unsupported_info(symbol const& s) { if (s != symbol::null) diagnostic_stream() << "; " << s << std::endl;} - void init_solver_options(solver * s); + void mk_solver(); public: cmd_context(bool main_ctx = true, ast_manager * m = 0, symbol const & l = symbol::null); ~cmd_context(); + void set_cancel(bool f); + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } context_params & params() { return m_params; } void global_params_updated(); // this method should be invoked when global (and module) params are updated. void set_logic(symbol const & s); @@ -289,8 +293,7 @@ public: pdecl_manager & pm() const { if (!m_pmanager) const_cast(this)->init_manager(); return *m_pmanager; } sexpr_manager & sm() const { if (!m_sexpr_manager) const_cast(this)->m_sexpr_manager = alloc(sexpr_manager); return *m_sexpr_manager; } - void set_solver(solver * s); - solver * get_solver() const { return m_solver.get(); } + void set_solver_factory(solver_factory * s); void set_check_sat_result(check_sat_result * r) { m_check_sat_result = r; } check_sat_result * get_check_sat_result() const { return m_check_sat_result.get(); } check_sat_state cs_state() const; diff --git a/src/cmd_context/context_params.cpp b/src/cmd_context/context_params.cpp index 6d9222a37..2752967dd 100644 --- a/src/cmd_context/context_params.cpp +++ b/src/cmd_context/context_params.cpp @@ -131,11 +131,11 @@ params_ref context_params::merge_default_params(params_ref const & p) { } } -void context_params::init_solver_params(ast_manager & m, solver & s, params_ref const & p) { - s.set_produce_proofs(m.proofs_enabled() && m_proof); - s.set_produce_models(p.get_bool("model", m_model)); - s.set_produce_unsat_cores(p.get_bool("unsat_core", m_unsat_core)); - s.updt_params(merge_default_params(p)); +void context_params::get_solver_params(ast_manager const & m, params_ref & p, bool & proofs_enabled, bool & models_enabled, bool & unsat_core_enabled) { + proofs_enabled = m.proofs_enabled() && p.get_bool("proof", m_proof); + models_enabled = p.get_bool("model", m_model); + unsat_core_enabled = p.get_bool("unsat_core", m_unsat_core); + p = merge_default_params(p); } ast_manager * context_params::mk_ast_manager() { diff --git a/src/cmd_context/context_params.h b/src/cmd_context/context_params.h index dd60b9616..526b4f517 100644 --- a/src/cmd_context/context_params.h +++ b/src/cmd_context/context_params.h @@ -22,7 +22,6 @@ Notes: #include"params.h" class ast_manager; -class solver; class context_params { void set_bool(bool & opt, char const * param, char const * value); @@ -50,13 +49,9 @@ public: */ /** - \brief Goodie for updating the solver params - based on the configuration of the context_params object. - - This method is used when creating solvers from the - cmd_context and API. + \brief Goodies for extracting parameters for creating a solver object. */ - void init_solver_params(ast_manager & m, solver & s, params_ref const & p); + void get_solver_params(ast_manager const & m, params_ref & p, bool & proofs_enabled, bool & models_enabled, bool & unsat_core_enabled); /** \brief Include in p parameters derived from this context_params. diff --git a/src/cmd_context/pdecl.cpp b/src/cmd_context/pdecl.cpp index 6b55d4072..bafd76f0b 100644 --- a/src/cmd_context/pdecl.cpp +++ b/src/cmd_context/pdecl.cpp @@ -765,7 +765,7 @@ pdecl_manager::pdecl_manager(ast_manager & m): m_allocator(m.get_allocator()), m_new_dt_eh(0) { m_list = 0; - m_datatype_fid = m.get_family_id("datatype"); + m_datatype_fid = m.mk_family_id("datatype"); } pdecl_manager::~pdecl_manager() { diff --git a/src/math/polynomial/algebraic_numbers.cpp b/src/math/polynomial/algebraic_numbers.cpp index 90ad6ea9d..804a134e0 100644 --- a/src/math/polynomial/algebraic_numbers.cpp +++ b/src/math/polynomial/algebraic_numbers.cpp @@ -2796,72 +2796,58 @@ namespace algebraic_numbers { } void manager::del(numeral & a) { - set_cancel(false); return m_imp->del(a); } void manager::reset(numeral & a) { - set_cancel(false); return m_imp->reset(a); } bool manager::is_zero(numeral const & a) { - set_cancel(false); return m_imp->is_zero(const_cast(a)); } bool manager::is_pos(numeral const & a) { - set_cancel(false); return m_imp->is_pos(const_cast(a)); } bool manager::is_neg(numeral const & a) { - set_cancel(false); return m_imp->is_neg(const_cast(a)); } bool manager::is_rational(numeral const & a) { - set_cancel(false); return m_imp->is_rational(const_cast(a)); } bool manager::is_int(numeral const & a) { - set_cancel(false); return m_imp->is_int(const_cast(a)); } unsigned manager::degree(numeral const & a) { - set_cancel(false); return m_imp->degree(const_cast(a)); } void manager::to_rational(numeral const & a, mpq & r) { - set_cancel(false); return m_imp->to_rational(const_cast(a), r); } void manager::to_rational(numeral const & a, rational & r) { - set_cancel(false); return m_imp->to_rational(const_cast(a), r); } void manager::swap(numeral & a, numeral & b) { - set_cancel(false); return m_imp->swap(a, b); } void manager::int_lt(numeral const & a, numeral & b) { - set_cancel(false); m_imp->int_lt(const_cast(a), b); } void manager::int_gt(numeral const & a, numeral & b) { - set_cancel(false); m_imp->int_gt(const_cast(a), b); } void manager::select(numeral const & prev, numeral const & curr, numeral & result) { - set_cancel(false); m_imp->select(const_cast(prev), const_cast(curr), result); } @@ -2878,55 +2864,45 @@ namespace algebraic_numbers { } void manager::set(numeral & a, mpq const & n) { - set_cancel(false); m_imp->set(a, n); } void manager::set(numeral & a, numeral const & n) { - set_cancel(false); m_imp->set(a, n); } void manager::isolate_roots(polynomial_ref const & p, numeral_vector & roots) { - set_cancel(false); m_imp->isolate_roots(p, roots); } void manager::isolate_roots(polynomial_ref const & p, polynomial::var2anum const & x2v, numeral_vector & roots) { - set_cancel(false); m_imp->isolate_roots(p, x2v, roots); } void manager::isolate_roots(polynomial_ref const & p, polynomial::var2anum const & x2v, numeral_vector & roots, svector & signs) { - set_cancel(false); m_imp->isolate_roots(p, x2v, roots, signs); } void manager::mk_root(polynomial_ref const & p, unsigned i, numeral & r) { - set_cancel(false); m_imp->mk_root(p, i, r); } void manager::mk_root(sexpr const * p, unsigned i, numeral & r) { - set_cancel(false); m_imp->mk_root(p, i, r); } void manager::root(numeral const & a, unsigned k, numeral & b) { - set_cancel(false); m_imp->root(const_cast(a), k, b); } void manager::power(numeral const & a, unsigned k, numeral & b) { TRACE("anum_detail", display_root(tout, a); tout << "^" << k << "\n";); - set_cancel(false); m_imp->power(const_cast(a), k, b); TRACE("anum_detail", tout << "^ result: "; display_root(tout, b); tout << "\n";); } void manager::add(numeral const & a, numeral const & b, numeral & c) { TRACE("anum_detail", display_root(tout, a); tout << " + "; display_root(tout, b); tout << "\n";); - set_cancel(false); m_imp->add(const_cast(a), const_cast(b), c); TRACE("anum_detail", tout << "+ result: "; display_root(tout, c); tout << "\n";); } @@ -2939,45 +2915,37 @@ namespace algebraic_numbers { void manager::sub(numeral const & a, numeral const & b, numeral & c) { TRACE("anum_detail", display_root(tout, a); tout << " - "; display_root(tout, b); tout << "\n";); - set_cancel(false); m_imp->sub(const_cast(a), const_cast(b), c); TRACE("anum_detail", tout << "- result: "; display_root(tout, c); tout << "\n";); } void manager::mul(numeral const & a, numeral const & b, numeral & c) { TRACE("anum_detail", display_root(tout, a); tout << " * "; display_root(tout, b); tout << "\n";); - set_cancel(false); m_imp->mul(const_cast(a), const_cast(b), c); TRACE("anum_detail", tout << "* result: "; display_root(tout, c); tout << "\n";); } void manager::div(numeral const & a, numeral const & b, numeral & c) { - set_cancel(false); m_imp->div(const_cast(a), const_cast(b), c); } void manager::neg(numeral & a) { - set_cancel(false); m_imp->neg(a); } void manager::inv(numeral & a) { - set_cancel(false); m_imp->inv(a); } int manager::compare(numeral const & a, numeral const & b) { - set_cancel(false); return m_imp->compare(const_cast(a), const_cast(b)); } bool manager::eq(numeral const & a, numeral const & b) { - set_cancel(false); return m_imp->eq(const_cast(a), const_cast(b)); } bool manager::eq(numeral const & a, mpq const & b) { - set_cancel(false); return m_imp->eq(const_cast(a), b); } @@ -2988,12 +2956,10 @@ namespace algebraic_numbers { } bool manager::lt(numeral const & a, numeral const & b) { - set_cancel(false); return m_imp->lt(const_cast(a), const_cast(b)); } bool manager::lt(numeral const & a, mpq const & b) { - set_cancel(false); return m_imp->lt(const_cast(a), b); } @@ -3004,7 +2970,6 @@ namespace algebraic_numbers { } bool manager::gt(numeral const & a, mpq const & b) { - set_cancel(false); return m_imp->gt(const_cast(a), b); } @@ -3073,38 +3038,31 @@ namespace algebraic_numbers { } int manager::eval_sign_at(polynomial_ref const & p, polynomial::var2anum const & x2v) { - set_cancel(false); SASSERT(&(x2v.m()) == this); return m_imp->eval_sign_at(p, x2v); } void manager::display_interval(std::ostream & out, numeral const & a) const { - const_cast(this)->set_cancel(false); m_imp->display_interval(out, a); } void manager::display_decimal(std::ostream & out, numeral const & a, unsigned precision) const { - const_cast(this)->set_cancel(false); m_imp->display_decimal(out, a, precision); } void manager::display_root(std::ostream & out, numeral const & a) const { - const_cast(this)->set_cancel(false); m_imp->display_root(out, a); } void manager::display_mathematica(std::ostream & out, numeral const & a) const { - const_cast(this)->set_cancel(false); m_imp->display_mathematica(out, a); } void manager::display_root_smt2(std::ostream & out, numeral const & a) const { - const_cast(this)->set_cancel(false); m_imp->display_root_smt2(out, a); } void manager::reset_statistics() { - set_cancel(false); m_imp->reset_statistics(); } diff --git a/src/math/polynomial/algebraic_numbers.h b/src/math/polynomial/algebraic_numbers.h index a4669eae6..d11237b86 100644 --- a/src/math/polynomial/algebraic_numbers.h +++ b/src/math/polynomial/algebraic_numbers.h @@ -64,8 +64,8 @@ namespace algebraic_numbers { static void collect_param_descrs(param_descrs & r) { get_param_descrs(r); } void set_cancel(bool f); - void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } void updt_params(params_ref const & p); diff --git a/src/math/polynomial/polynomial.cpp b/src/math/polynomial/polynomial.cpp index 4e14c5661..f5d96e740 100644 --- a/src/math/polynomial/polynomial.cpp +++ b/src/math/polynomial/polynomial.cpp @@ -2368,7 +2368,6 @@ namespace polynomial { void checkpoint() { if (m_cancel) { - set_cancel(false); throw polynomial_exception("canceled"); } cooperate("polynomial"); diff --git a/src/math/polynomial/polynomial.h b/src/math/polynomial/polynomial.h index d17d2ac5a..e52dd4fee 100644 --- a/src/math/polynomial/polynomial.h +++ b/src/math/polynomial/polynomial.h @@ -220,6 +220,7 @@ namespace polynomial { void set_cancel(bool f); void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } /** \brief Abstract event handler. diff --git a/src/math/polynomial/polynomial_factorization.cpp b/src/math/polynomial/polynomial_factorization.cpp index e0f050411..220048a9a 100644 --- a/src/math/polynomial/polynomial_factorization.cpp +++ b/src/math/polynomial/polynomial_factorization.cpp @@ -16,7 +16,7 @@ Author: Notes: [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 46(8-10):1853–1859, 1967. + 46(8-10):1853-1859, 1967. [2] Donald Ervin Knuth. The Art of Computer Programming, volume 2: Seminumerical Algorithms. Addison Wesley, third edition, 1997. [3] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer Verlag, 1993. diff --git a/src/math/polynomial/polynomial_factorization.h b/src/math/polynomial/polynomial_factorization.h index 48b4efd98..f069121ba 100644 --- a/src/math/polynomial/polynomial_factorization.h +++ b/src/math/polynomial/polynomial_factorization.h @@ -16,7 +16,7 @@ Author: Notes: [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 46(8-10):1853–1859, 1967. + 46(8-10):1853-1859, 1967. [2] Donald Ervin Knuth. The Art of Computer Programming, volume 2: Seminumerical Algorithms. Addison Wesley, third edition, 1997. [3] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer Verlag, 1993. diff --git a/src/math/polynomial/upolynomial_factorization.cpp b/src/math/polynomial/upolynomial_factorization.cpp index a1e28e727..230d352f3 100644 --- a/src/math/polynomial/upolynomial_factorization.cpp +++ b/src/math/polynomial/upolynomial_factorization.cpp @@ -16,7 +16,7 @@ Author: Notes: [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 46(8-10):1853–1859, 1967. + 46(8-10):1853-1859, 1967. [2] Donald Ervin Knuth. The Art of Computer Programming, volume 2: Seminumerical Algorithms. Addison Wesley, third edition, 1997. [3] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer Verlag, 1993. diff --git a/src/math/polynomial/upolynomial_factorization.h b/src/math/polynomial/upolynomial_factorization.h index e687786da..327fffc9c 100644 --- a/src/math/polynomial/upolynomial_factorization.h +++ b/src/math/polynomial/upolynomial_factorization.h @@ -16,7 +16,7 @@ Author: Notes: [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 46(8-10):1853–1859, 1967. + 46(8-10):1853-1859, 1967. [2] Donald Ervin Knuth. The Art of Computer Programming, volume 2: Seminumerical Algorithms. Addison Wesley, third edition, 1997. [3] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer Verlag, 1993. diff --git a/src/math/polynomial/upolynomial_factorization_int.h b/src/math/polynomial/upolynomial_factorization_int.h index c076b2e6d..92d62301d 100644 --- a/src/math/polynomial/upolynomial_factorization_int.h +++ b/src/math/polynomial/upolynomial_factorization_int.h @@ -17,7 +17,7 @@ Author: Notes: [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 46(8-10):1853–1859, 1967. + 46(8-10):1853-1859, 1967. [2] Donald Ervin Knuth. The Art of Computer Programming, volume 2: Seminumerical Algorithms. Addison Wesley, third edition, 1997. [3] Henri Cohen. A Course in Computational Algebraic Number Theory. Springer Verlag, 1993. diff --git a/src/model/model_evaluator.cpp b/src/model/model_evaluator.cpp index beed0061e..dc4c20aa8 100644 --- a/src/model/model_evaluator.cpp +++ b/src/model/model_evaluator.cpp @@ -244,10 +244,10 @@ unsigned model_evaluator::get_num_steps() const { return m_imp->get_num_steps(); } -void model_evaluator::cancel() { +void model_evaluator::set_cancel(bool f) { #pragma omp critical (model_evaluator) { - m_imp->cancel(); + m_imp->set_cancel(f); } } diff --git a/src/model/model_evaluator.h b/src/model/model_evaluator.h index aad06739b..1a7469c6c 100644 --- a/src/model/model_evaluator.h +++ b/src/model/model_evaluator.h @@ -41,7 +41,9 @@ public: void operator()(expr * t, expr_ref & r); - void cancel(); + void set_cancel(bool f); + void cancel() { set_cancel(true); } + void reset_cancel() { set_cancel(false); } void cleanup(params_ref const & p = params_ref()); void reset(params_ref const & p = params_ref()); diff --git a/src/muz_qe/dl_bmc_engine.cpp b/src/muz_qe/dl_bmc_engine.cpp index b5ffa808a..c7e53e581 100644 --- a/src/muz_qe/dl_bmc_engine.cpp +++ b/src/muz_qe/dl_bmc_engine.cpp @@ -963,7 +963,7 @@ namespace datalog { sort_ref_vector new_sorts(m); - family_id dfid = m.get_family_id("datatype"); + family_id dfid = m.mk_family_id("datatype"); datatype_decl_plugin* dtp = static_cast(m.get_plugin(dfid)); VERIFY (dtp->mk_datatypes(dts.size(), dts.c_ptr(), new_sorts)); diff --git a/src/muz_qe/dl_cmds.cpp b/src/muz_qe/dl_cmds.cpp index bf9c24203..c88e7346e 100644 --- a/src/muz_qe/dl_cmds.cpp +++ b/src/muz_qe/dl_cmds.cpp @@ -75,7 +75,7 @@ struct dl_context { if (!m_decl_plugin) { symbol name("datalog_relation"); if (m.has_plugin(name)) { - m_decl_plugin = static_cast(m_cmd.m().get_plugin(m.get_family_id(name))); + m_decl_plugin = static_cast(m_cmd.m().get_plugin(m.mk_family_id(name))); } else { m_decl_plugin = alloc(datalog::dl_decl_plugin); diff --git a/src/muz_qe/dl_context.h b/src/muz_qe/dl_context.h index f84050e68..d3309beb5 100644 --- a/src/muz_qe/dl_context.h +++ b/src/muz_qe/dl_context.h @@ -349,6 +349,7 @@ namespace datalog { void cancel(); void cleanup(); + void reset_cancel() { cleanup(); } /** \brief check if query 'q' is satisfied under asserted rules and background. diff --git a/src/muz_qe/dl_mk_extract_quantifiers2.cpp b/src/muz_qe/dl_mk_extract_quantifiers2.cpp index 97976a6be..58255d2a1 100644 --- a/src/muz_qe/dl_mk_extract_quantifiers2.cpp +++ b/src/muz_qe/dl_mk_extract_quantifiers2.cpp @@ -332,7 +332,7 @@ namespace datalog { smt::quantifier_manager* qm = ctx.get_quantifier_manager(); qm->get_plugin()->set_instance_plugin(alloc(instance_plugin, *this)); #endif - lbool res = solver.check(); + solver.check(); for (unsigned i = 0; i < m_bindings.size(); ++i) { expr_ref_vector& binding = m_bindings[i]; diff --git a/src/muz_qe/dl_relation_manager.h b/src/muz_qe/dl_relation_manager.h index 270e06f12..ecba3d598 100644 --- a/src/muz_qe/dl_relation_manager.h +++ b/src/muz_qe/dl_relation_manager.h @@ -3,7 +3,7 @@ Copyright (c) 2006 Microsoft Corporation Module Name: - dl_remation_manager.h + dl_relation_manager.h Abstract: @@ -316,7 +316,7 @@ namespace datalog { oldTgt:=tgt.clone(); tgt:=tgt \union src if(tgt!=oldTgt) { - delta:=delta \union src //also “delta \union tgt” would work + delta:=delta \union src //also ?delta \union tgt? would work } } @@ -488,7 +488,7 @@ namespace datalog { oldTgt:=tgt.clone(); tgt:=tgt \union src if(tgt!=oldTgt) { - delta:=delta \union src //also “delta \union tgt” would work + delta:=delta \union src //also ?delta \union tgt? would work } } diff --git a/src/muz_qe/dl_rule.cpp b/src/muz_qe/dl_rule.cpp index bd7131fea..d34f8a67f 100644 --- a/src/muz_qe/dl_rule.cpp +++ b/src/muz_qe/dl_rule.cpp @@ -74,7 +74,7 @@ namespace datalog { class remove_label_cfg : public default_rewriter_cfg { family_id m_label_fid; public: - remove_label_cfg(ast_manager& m): m_label_fid(m.get_family_id("label")) {} + remove_label_cfg(ast_manager& m): m_label_fid(m.get_label_family_id()) {} virtual ~remove_label_cfg() {} br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, diff --git a/src/muz_qe/pdr_util.cpp b/src/muz_qe/pdr_util.cpp index fd08b1aad..1ea705e6e 100644 --- a/src/muz_qe/pdr_util.cpp +++ b/src/muz_qe/pdr_util.cpp @@ -1129,7 +1129,11 @@ namespace pdr { if (a.is_numeral(lhs) || a.is_numeral(rhs)) { return test_ineq(e); } - return test_term(lhs) && test_term(rhs); + return + test_term(lhs) && + test_term(rhs) && + !a.is_mul(lhs) && + !a.is_mul(rhs); } bool test_term(expr* e) const { diff --git a/src/muz_qe/proof_utils.cpp b/src/muz_qe/proof_utils.cpp index 75c9cbb15..e5a3ea437 100644 --- a/src/muz_qe/proof_utils.cpp +++ b/src/muz_qe/proof_utils.cpp @@ -312,9 +312,10 @@ public: }; void proof_utils::reduce_hypotheses(proof_ref& pr) { - class reduce_hypotheses reduce(pr.get_manager()); + ast_manager& m = pr.get_manager(); + class reduce_hypotheses reduce(m); reduce(pr); - SASSERT(is_closed(pr.get_manager(), pr)); + CTRACE("proof_utils", !is_closed(m, pr), tout << mk_pp(pr, m) << "\n";); } class proof_is_closed { @@ -449,7 +450,7 @@ static void permute_unit_resolution(expr_ref_vector& refs, obj_map parameter const* params = thLemma->get_decl()->get_parameters(); unsigned num_params = thLemma->get_decl()->get_num_parameters(); SASSERT(params[0].is_symbol()); - family_id tid = m.get_family_id(params[0].get_symbol()); + family_id tid = m.mk_family_id(params[0].get_symbol()); SASSERT(tid != null_family_id); prNew = m.mk_th_lemma(tid, m.get_fact(pr), premises.size(), premises.c_ptr(), num_params-1, params+1); diff --git a/src/muz_qe/qe_arith_plugin.cpp b/src/muz_qe/qe_arith_plugin.cpp index 69c036639..4e158229b 100644 --- a/src/muz_qe/qe_arith_plugin.cpp +++ b/src/muz_qe/qe_arith_plugin.cpp @@ -1512,7 +1512,7 @@ public: public: arith_plugin(i_solver_context& ctx, ast_manager& m, smt_params& p): - qe_solver_plugin(m, m.get_family_id("arith"), ctx), + qe_solver_plugin(m, m.mk_family_id("arith"), ctx), m_util(m, p, ctx), m_trail(m) {} @@ -2403,7 +2403,7 @@ public: bool m_produce_models; public: nlarith_plugin(i_solver_context& ctx, ast_manager& m, bool produce_models) : - qe_solver_plugin(m, m.get_family_id("arith"), ctx), + qe_solver_plugin(m, m.mk_family_id("arith"), ctx), m_rewriter(m), m_util(m), m_replacer(mk_default_expr_replacer(m)), diff --git a/src/muz_qe/qe_array_plugin.cpp b/src/muz_qe/qe_array_plugin.cpp index c013f93f4..106a42338 100644 --- a/src/muz_qe/qe_array_plugin.cpp +++ b/src/muz_qe/qe_array_plugin.cpp @@ -16,7 +16,7 @@ namespace qe { public: array_plugin(i_solver_context& ctx, ast_manager& m) : - qe_solver_plugin(m, m.get_family_id("array"), ctx), + qe_solver_plugin(m, m.mk_family_id("array"), ctx), m_replace(mk_default_expr_replacer(m)) { } diff --git a/src/muz_qe/qe_bv_plugin.cpp b/src/muz_qe/qe_bv_plugin.cpp index 8712061d6..cae567111 100644 --- a/src/muz_qe/qe_bv_plugin.cpp +++ b/src/muz_qe/qe_bv_plugin.cpp @@ -32,7 +32,7 @@ namespace qe { bv_util m_bv; public: bv_plugin(i_solver_context& ctx, ast_manager& m): - qe_solver_plugin(m, m.get_family_id("bv"), ctx), + qe_solver_plugin(m, m.mk_family_id("bv"), ctx), m_replace(mk_default_expr_replacer(m)), m_bv(m) {} diff --git a/src/muz_qe/qe_datatype_plugin.cpp b/src/muz_qe/qe_datatype_plugin.cpp index 3978a9ba4..0b51f26af 100644 --- a/src/muz_qe/qe_datatype_plugin.cpp +++ b/src/muz_qe/qe_datatype_plugin.cpp @@ -422,7 +422,7 @@ namespace qe { public: datatype_plugin(i_solver_context& ctx, ast_manager& m) : - qe_solver_plugin(m, m.get_family_id("datatype"), ctx), + qe_solver_plugin(m, m.mk_family_id("datatype"), ctx), m_datatype_util(m), m_replace(mk_default_expr_replacer(m)), m_trail(m) diff --git a/src/muz_qe/qe_dl_plugin.cpp b/src/muz_qe/qe_dl_plugin.cpp index 23f43759d..15e972e88 100644 --- a/src/muz_qe/qe_dl_plugin.cpp +++ b/src/muz_qe/qe_dl_plugin.cpp @@ -45,7 +45,7 @@ namespace qe { public: dl_plugin(i_solver_context& ctx, ast_manager& m) : - qe_solver_plugin(m, m.get_family_id("datalog_relation"), ctx), + qe_solver_plugin(m, m.mk_family_id("datalog_relation"), ctx), m_replace(mk_default_expr_replacer(m)), m_util(m), m_trail(m) diff --git a/src/muz_qe/qe_lite.cpp b/src/muz_qe/qe_lite.cpp index 8880a9ba5..df4a55475 100644 --- a/src/muz_qe/qe_lite.cpp +++ b/src/muz_qe/qe_lite.cpp @@ -35,7 +35,7 @@ Revision History: #include "dl_util.h" #include "for_each_expr.h" #include "expr_safe_replace.h" - +#include "cooperate.h" class is_variable_proc { public: @@ -91,6 +91,7 @@ namespace eq { expr_ref_vector m_subst_map; expr_ref_buffer m_new_args; th_rewriter m_rewriter; + volatile bool m_cancel; void der_sort_vars(ptr_vector & vars, ptr_vector & definitions, unsigned_vector & order) { order.reset(); @@ -530,6 +531,7 @@ namespace eq { // Find all definitions for (unsigned i = 0; i < num_args; i++) { + checkpoint(); if (is_var_def(is_exists, args[i], v, t)) { unsigned idx = v->get_idx(); if(m_map.get(idx, 0) == 0) { @@ -569,8 +571,14 @@ namespace eq { return false; } + void checkpoint() { + cooperate("der"); + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + } + public: - der(ast_manager & m): m(m), a(m), m_is_variable(0), m_subst(m), m_new_exprs(m), m_subst_map(m), m_new_args(m), m_rewriter(m) {} + der(ast_manager & m): m(m), a(m), m_is_variable(0), m_subst(m), m_new_exprs(m), m_subst_map(m), m_new_args(m), m_rewriter(m), m_cancel(false) {} void set_is_variable_proc(is_variable_proc& proc) { m_is_variable = &proc;} @@ -588,6 +596,7 @@ namespace eq { r = q; // Keep applying reduce_quantifier1 until r doesn't change anymore do { + checkpoint(); proof_ref curr_pr(m); q = to_quantifier(r); reduce_quantifier1(q, r, curr_pr); @@ -605,6 +614,12 @@ namespace eq { } ast_manager& get_manager() const { return m; } + + void set_cancel(bool f) { + m_rewriter.set_cancel(f); + m_cancel = f; + } + }; }; // namespace eq @@ -618,6 +633,7 @@ namespace ar { is_variable_proc* m_is_variable; ptr_vector m_todo; expr_mark m_visited; + volatile bool m_cancel; bool is_variable(expr * e) const { return (*m_is_variable)(e); @@ -723,13 +739,19 @@ namespace ar { return false; } + void checkpoint() { + cooperate("der"); + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + } public: - der(ast_manager& m): m(m), a(m), m_is_variable(0) {} + der(ast_manager& m): m(m), a(m), m_is_variable(0), m_cancel(false) {} void operator()(expr_ref_vector& fmls) { for (unsigned i = 0; i < fmls.size(); ++i) { + checkpoint(); solve_select(fmls, i, fmls[i].get()); solve_neq_select(fmls, i, fmls[i].get()); } @@ -738,6 +760,10 @@ namespace ar { void operator()(expr* e) {} void set_is_variable_proc(is_variable_proc& proc) { m_is_variable = &proc;} + + void set_cancel(bool f) { + m_cancel = f; + } }; }; // namespace ar @@ -866,7 +892,6 @@ namespace fm { unsigned m_fm_cutoff2; unsigned m_fm_extra; bool m_fm_occ; - unsigned long long m_max_memory; unsigned m_counter; bool m_inconsistent; expr_dependency_ref m_inconsistent_core; @@ -1243,7 +1268,7 @@ namespace fm { // // --------------------------- - fm(ast_manager & _m, params_ref const & p): + fm(ast_manager & _m): m(_m), m_allocator("fm-elim"), m_util(m), @@ -1251,7 +1276,6 @@ namespace fm { m_var2expr(m), m_new_fmls(m), m_inconsistent_core(m) { - updt_params(p); m_cancel = false; } @@ -1259,14 +1283,13 @@ namespace fm { reset_constraints(); } - void updt_params(params_ref const & p) { - m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX)); - m_fm_real_only = p.get_bool("fm_real_only", true); - m_fm_limit = p.get_uint("fm_limit", 5000000); - m_fm_cutoff1 = p.get_uint("fm_cutoff1", 8); - m_fm_cutoff2 = p.get_uint("fm_cutoff2", 256); - m_fm_extra = p.get_uint("fm_extra", 0); - m_fm_occ = p.get_bool("fm_occ", false); + void updt_params() { + m_fm_real_only = true; + m_fm_limit = 5000000; + m_fm_cutoff1 = 8; + m_fm_cutoff2 = 256; + m_fm_extra = 0; + m_fm_occ = false; } void set_cancel(bool f) { @@ -2010,11 +2033,9 @@ namespace fm { } void checkpoint() { - // cooperate("fm"); + cooperate("fm"); if (m_cancel) throw tactic_exception(TACTIC_CANCELED_MSG); - if (memory::get_allocation_size() > m_max_memory) - throw tactic_exception(TACTIC_MAX_MEMORY_MSG); } public: @@ -2083,11 +2104,56 @@ namespace fm { } // namespace fm class qe_lite::impl { +public: + struct elim_cfg : public default_rewriter_cfg { + impl& m_imp; + ast_manager& m; + public: + elim_cfg(impl& i): m_imp(i), m(i.m) {} + + bool reduce_quantifier(quantifier * q, + expr * new_body, + expr * const * new_patterns, + expr * const * new_no_patterns, + expr_ref & result, + proof_ref & result_pr) { + result = new_body; + if (is_forall(q)) { + result = m.mk_not(result); + } + uint_set indices; + for (unsigned i = 0; i < q->get_num_decls(); ++i) { + indices.insert(i); + } + m_imp(indices, true, result); + if (is_forall(q)) { + result = m.mk_not(result); + } + result = m.update_quantifier( + q, + q->get_num_patterns(), new_patterns, + q->get_num_no_patterns(), new_no_patterns, result); + m_imp.m_rewriter(result); + return true; + } + }; + + class elim_star : public rewriter_tpl { + elim_cfg m_cfg; + public: + elim_star(impl& i): + rewriter_tpl(i.m, false, m_cfg), + m_cfg(i) + {} + }; + +private: ast_manager& m; - params_ref m_params; eq::der m_der; fm::fm m_fm; ar::der m_array_der; + elim_star m_elim_star; + th_rewriter m_rewriter; bool has_unique_non_ground(expr_ref_vector const& fmls, unsigned& index) { index = fmls.size(); @@ -2106,7 +2172,13 @@ class qe_lite::impl { } public: - impl(ast_manager& m): m(m), m_der(m), m_fm(m, m_params), m_array_der(m) {} + impl(ast_manager& m): + m(m), + m_der(m), + m_fm(m), + m_array_der(m), + m_elim_star(*this), + m_rewriter(m) {} void operator()(app_ref_vector& vars, expr_ref& fml) { if (vars.empty()) { @@ -2145,14 +2217,12 @@ public: else { fml = tmp; } - } + } void operator()(expr_ref& fml, proof_ref& pr) { - // TODO apply der everywhere as a rewriting rule. - // TODO add cancel method. - if (is_quantifier(fml)) { - m_der(to_quantifier(fml), fml, pr); - } + expr_ref tmp(m); + m_elim_star(fml, tmp, pr); + fml = tmp; } void operator()(uint_set const& index_set, bool index_of_bound, expr_ref& fml) { @@ -2195,6 +2265,14 @@ public: TRACE("qe_lite", for (unsigned i = 0; i < fmls.size(); ++i) tout << mk_pp(fmls[i].get(), m) << "\n";); } + void set_cancel(bool f) { + m_der.set_cancel(f); + m_array_der.set_cancel(f); + m_fm.set_cancel(f); + m_elim_star.set_cancel(f); + m_rewriter.set_cancel(f); + } + }; qe_lite::qe_lite(ast_manager& m) { @@ -2209,6 +2287,10 @@ void qe_lite::operator()(app_ref_vector& vars, expr_ref& fml) { (*m_impl)(vars, fml); } +void qe_lite::set_cancel(bool f) { + m_impl->set_cancel(f); +} + void qe_lite::operator()(expr_ref& fml, proof_ref& pr) { (*m_impl)(fml, pr); } @@ -2220,3 +2302,130 @@ void qe_lite::operator()(uint_set const& index_set, bool index_of_bound, expr_re void qe_lite::operator()(uint_set const& index_set, bool index_of_bound, expr_ref_vector& fmls) { (*m_impl)(index_set, index_of_bound, fmls); } + +class qe_lite_tactic : public tactic { + + struct imp { + ast_manager& m; + qe_lite m_qe; + volatile bool m_cancel; + + imp(ast_manager& m, params_ref const& p): + m(m), + m_qe(m), + m_cancel(false) + {} + + void set_cancel(bool f) { + m_cancel = f; + m_qe.set_cancel(f); + } + + void checkpoint() { + if (m_cancel) + throw tactic_exception(TACTIC_CANCELED_MSG); + cooperate("qe-lite"); + } + + void operator()(goal_ref const & g, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + SASSERT(g->is_well_sorted()); + mc = 0; pc = 0; core = 0; + tactic_report report("qe-lite", *g); + proof_ref new_pr(m); + expr_ref new_f(m); + bool produce_proofs = g->proofs_enabled(); + + unsigned sz = g->size(); + for (unsigned i = 0; i < sz; i++) { + checkpoint(); + if (g->inconsistent()) + break; + expr * f = g->form(i); + if (!has_quantifiers(f)) + continue; + new_f = f; + m_qe(new_f, new_pr); + if (produce_proofs) { + new_pr = m.mk_modus_ponens(g->pr(i), new_pr); + } + g->update(i, new_f, new_pr, g->dep(i)); + } + g->inc_depth(); + result.push_back(g.get()); + TRACE("qe", g->display(tout);); + SASSERT(g->is_well_sorted()); + } + + }; + + params_ref m_params; + imp * m_imp; + +public: + qe_lite_tactic(ast_manager & m, params_ref const & p): + m_params(p) { + m_imp = alloc(imp, m, p); + } + + virtual tactic * translate(ast_manager & m) { + return alloc(qe_lite_tactic, m, m_params); + } + + virtual ~qe_lite_tactic() { + dealloc(m_imp); + } + + virtual void updt_params(params_ref const & p) { + m_params = p; + // m_imp->updt_params(p); + } + + + virtual void collect_param_descrs(param_descrs & r) { + // m_imp->collect_param_descrs(r); + } + + virtual void operator()(goal_ref const & in, + goal_ref_buffer & result, + model_converter_ref & mc, + proof_converter_ref & pc, + expr_dependency_ref & core) { + (*m_imp)(in, result, mc, pc, core); + } + + + virtual void collect_statistics(statistics & st) const { + // m_imp->collect_statistics(st); + } + + virtual void reset_statistics() { + // m_imp->reset_statistics(); + } + + + virtual void cleanup() { + ast_manager & m = m_imp->m; + imp * d = m_imp; + #pragma omp critical (tactic_cancel) + { + m_imp = 0; + } + dealloc(d); + d = alloc(imp, m, m_params); + #pragma omp critical (tactic_cancel) + { + m_imp = d; + } + } + +}; + +tactic * mk_qe_lite_tactic(ast_manager & m, params_ref const & p) { + return alloc(qe_lite_tactic, m, p); +} + +template class rewriter_tpl; diff --git a/src/muz_qe/qe_lite.h b/src/muz_qe/qe_lite.h index 3ffbf8fad..7d9239fa7 100644 --- a/src/muz_qe/qe_lite.h +++ b/src/muz_qe/qe_lite.h @@ -23,6 +23,9 @@ Revision History: #include "ast.h" #include "uint_set.h" +#include "params.h" + +class tactic; class qe_lite { class impl; @@ -56,6 +59,13 @@ public: \brief full rewriting based light-weight quantifier elimination round. */ void operator()(expr_ref& fml, proof_ref& pr); + + void set_cancel(bool f); }; +tactic * mk_qe_lite_tactic(ast_manager & m, params_ref const & p = params_ref()); +/* + ADD_TACTIC("qe-light", "apply light-weight quantifier elimination.", "mk_qe_lite_tactic(m, p)") +*/ + #endif diff --git a/src/nlsat/nlsat_explain.cpp b/src/nlsat/nlsat_explain.cpp index ca58b15af..460e07f58 100644 --- a/src/nlsat/nlsat_explain.cpp +++ b/src/nlsat/nlsat_explain.cpp @@ -981,6 +981,14 @@ namespace nlsat { bool atom_val = a->get_kind() == atom::EQ; bool lit_val = l.sign() ? !atom_val : atom_val; new_lit = lit_val ? true_literal : false_literal; + if (!info.m_lc_const) { + // We have essentially shown the current factor must be zero If the leading coefficient is not zero. + // Note that, if the current factor is zero, then the whole polynomial is zero. + // The atom is true if it is an equality, and false otherwise. + // The sign of the leading coefficient (info.m_lc) of info.m_eq doesn't matter. + // However, we have to store the fact it is not zero. + info.add_lc_diseq(); + } return; } else if (s == -1 && !is_even) { @@ -1341,3 +1349,32 @@ namespace nlsat { } }; + +#ifdef Z3DEBUG +void pp(nlsat::explain::imp & ex, unsigned num, nlsat::literal const * ls) { + ex.display(std::cout, num, ls); +} +void pp(nlsat::explain::imp & ex, nlsat::scoped_literal_vector & ls) { + ex.display(std::cout, ls); +} +void pp(nlsat::explain::imp & ex, polynomial_ref const & p) { + ex.display(std::cout, p); + std::cout << std::endl; +} +void pp(nlsat::explain::imp & ex, polynomial::polynomial * p) { + polynomial_ref _p(p, ex.m_pm); + ex.display(std::cout, _p); + std::cout << std::endl; +} +void pp(nlsat::explain::imp & ex, polynomial_ref_vector const & ps) { + ex.display(std::cout, ps); +} +void pp_var(nlsat::explain::imp & ex, nlsat::var x) { + ex.display(std::cout, x); + std::cout << std::endl; +} +void pp_lit(nlsat::explain::imp & ex, nlsat::literal l) { + ex.display(std::cout, l); + std::cout << std::endl; +} +#endif diff --git a/src/nlsat/nlsat_explain.h b/src/nlsat/nlsat_explain.h index 08f6201be..5ecb9d385 100644 --- a/src/nlsat/nlsat_explain.h +++ b/src/nlsat/nlsat_explain.h @@ -27,7 +27,9 @@ namespace nlsat { class evaluator; class explain { + public: struct imp; + private: imp * m_imp; public: explain(solver & s, assignment const & x2v, polynomial::cache & u, atom_vector const & atoms, atom_vector const & x2eq, diff --git a/src/parsers/smt/smtlib_solver.cpp b/src/parsers/smt/smtlib_solver.cpp index ef28216bf..7c8572ad8 100644 --- a/src/parsers/smt/smtlib_solver.cpp +++ b/src/parsers/smt/smtlib_solver.cpp @@ -86,7 +86,7 @@ namespace smtlib { benchmark.add_formula(m_ast_manager.mk_true()); } m_ctx = alloc(cmd_context, true, &m_ast_manager, benchmark.get_logic()); - m_ctx->set_solver(mk_smt_strategic_solver(false)); + m_ctx->set_solver_factory(mk_smt_strategic_solver_factory()); theory::expr_iterator fit = benchmark.begin_formulas(); theory::expr_iterator fend = benchmark.end_formulas(); for (; fit != fend; ++fit) diff --git a/src/parsers/smt/smtparser.cpp b/src/parsers/smt/smtparser.cpp index d3b2feeb7..c1ebd251b 100644 --- a/src/parsers/smt/smtparser.cpp +++ b/src/parsers/smt/smtparser.cpp @@ -483,13 +483,13 @@ public: class array_sort : public builtin_sort_builder { public: array_sort(ast_manager& m) : - builtin_sort_builder(m, m.get_family_id("array"), ARRAY_SORT) {} + builtin_sort_builder(m, m.mk_family_id("array"), ARRAY_SORT) {} }; class bv_sort : public builtin_sort_builder { public: bv_sort(ast_manager& m) : - builtin_sort_builder(m, m.get_family_id("bv"), BV_SORT) {} + builtin_sort_builder(m, m.mk_family_id("bv"), BV_SORT) {} }; class user_sort : public sort_builder { @@ -538,7 +538,7 @@ class smtparser : public parser { public: add_plugins(ast_manager& m) { #define REGISTER_PLUGIN(NAME, MK) { \ - family_id fid = m.get_family_id(symbol(NAME)); \ + family_id fid = m.mk_family_id(symbol(NAME)); \ if (!m.has_plugin(fid)) { \ m.register_plugin(fid, MK); \ } \ @@ -681,7 +681,7 @@ public: smtlib::symtable* table = m_benchmark.get_symtable(); symbol arith("arith"); - family_id afid = m_manager.get_family_id(arith); + family_id afid = m_manager.mk_family_id(arith); m_arith_fid = afid; add_builtin_type("Int", afid, INT_SORT); @@ -694,7 +694,7 @@ public: add_builtins(afid); symbol bv("bv"); - family_id bfid = m_manager.get_family_id(bv); + family_id bfid = m_manager.mk_family_id(bv); m_bv_fid = bfid; add_builtins(bfid); @@ -702,7 +702,7 @@ public: add_builtin_type("BitVec", bfid, BV_SORT); symbol array("array"); - afid = m_manager.get_family_id(array); + afid = m_manager.mk_family_id(array); m_array_fid = afid; add_builtins(afid); diff --git a/src/parsers/smt2/smt2parser.cpp b/src/parsers/smt2/smt2parser.cpp index c99c362bd..0698f4eaf 100644 --- a/src/parsers/smt2/smt2parser.cpp +++ b/src/parsers/smt2/smt2parser.cpp @@ -390,6 +390,7 @@ namespace smt2 { void check_float(char const * msg) { if (!curr_is_float()) throw parser_exception(msg); } void error(unsigned line, unsigned pos, char const * msg) { + m_ctx.reset_cancel(); if (use_vs_format()) { m_ctx.diagnostic_stream() << "Z3(" << line << ", " << pos << "): ERROR: " << msg; if (msg[strlen(msg)-1] != '\n') diff --git a/src/parsers/util/pattern_validation.h b/src/parsers/util/pattern_validation.h index d78502a8f..99024097e 100644 --- a/src/parsers/util/pattern_validation.h +++ b/src/parsers/util/pattern_validation.h @@ -32,11 +32,10 @@ class pattern_validator { public: pattern_validator(ast_manager const & m): m_bfid(m.get_basic_family_id()), - m_lfid(m.get_family_id("label")) { + m_lfid(m.get_label_family_id()) { } bool operator()(unsigned num_bindings, unsigned num_new_bindings, expr * n); - bool operator()(unsigned num_new_bindings, expr * n) { return operator()(UINT_MAX, num_new_bindings, n); } }; diff --git a/src/shell/smtlib_frontend.cpp b/src/shell/smtlib_frontend.cpp index 1551329c6..ef0b4ad6b 100644 --- a/src/shell/smtlib_frontend.cpp +++ b/src/shell/smtlib_frontend.cpp @@ -30,9 +30,6 @@ Revision History: #include"subpaving_cmds.h" #include"smt_strategic_solver.h" -#include"tactic2solver.h" -#include"qfnra_nlsat_tactic.h" - extern bool g_display_statistics; extern void display_config(); static clock_t g_start_time; @@ -98,8 +95,7 @@ unsigned read_smtlib2_commands(char const * file_name) { signal(SIGINT, on_ctrl_c); cmd_context ctx; - solver * s = mk_smt_strategic_solver(false); - ctx.set_solver(s); + ctx.set_solver_factory(mk_smt_strategic_solver_factory()); install_dl_cmds(ctx); install_dbg_cmds(ctx); diff --git a/src/smt/asserted_formulas.cpp b/src/smt/asserted_formulas.cpp index 6da2c15f5..3155d9c58 100644 --- a/src/smt/asserted_formulas.cpp +++ b/src/smt/asserted_formulas.cpp @@ -189,7 +189,7 @@ void asserted_formulas::push_scope() { s.m_asserted_formulas_lim = m_asserted_formulas.size(); SASSERT(inconsistent() || s.m_asserted_formulas_lim == m_asserted_qhead); s.m_inconsistent_old = m_inconsistent; - m_defined_names.push_scope(); + m_defined_names.push(); m_bv_sharing.push_scope(); commit(); } @@ -201,7 +201,7 @@ void asserted_formulas::pop_scope(unsigned num_scopes) { unsigned new_lvl = m_scopes.size() - num_scopes; scope & s = m_scopes[new_lvl]; m_inconsistent = s.m_inconsistent_old; - m_defined_names.pop_scope(num_scopes); + m_defined_names.pop(num_scopes); m_asserted_formulas.shrink(s.m_asserted_formulas_lim); if (m_manager.proofs_enabled()) m_asserted_formula_prs.shrink(s.m_asserted_formulas_lim); @@ -439,6 +439,8 @@ void asserted_formulas::nnf_cnf() { expr_ref r1(m_manager); proof_ref pr1(m_manager); CASSERT("well_sorted",is_well_sorted(m_manager, n)); + push_todo.reset(); + push_todo_prs.reset(); apply_nnf(n, push_todo, push_todo_prs, r1, pr1); CASSERT("well_sorted",is_well_sorted(m_manager, r1)); pr = m_manager.mk_modus_ponens(pr, pr1); @@ -855,3 +857,8 @@ void asserted_formulas::max_bv_sharing() { } +#ifdef Z3DEBUG +void pp(asserted_formulas & f) { + f.display(std::cout); +} +#endif diff --git a/src/smt/params/qi_params.h b/src/smt/params/qi_params.h index b0a21e75b..0cd817f22 100644 --- a/src/smt/params/qi_params.h +++ b/src/smt/params/qi_params.h @@ -52,8 +52,6 @@ struct qi_params { bool m_mbqi_trace; unsigned m_mbqi_force_template; - bool m_instgen; - qi_params(params_ref const & p = params_ref()): /* The "weight 0" performance bug @@ -99,8 +97,7 @@ struct qi_params { m_mbqi_max_cexs_incr(1), m_mbqi_max_iterations(1000), m_mbqi_trace(false), - m_mbqi_force_template(10), - m_instgen(false) { + m_mbqi_force_template(10) { updt_params(p); } diff --git a/src/smt/params/smt_params.cpp b/src/smt/params/smt_params.cpp index ec2fbc93c..519302c19 100644 --- a/src/smt/params/smt_params.cpp +++ b/src/smt/params/smt_params.cpp @@ -18,6 +18,7 @@ Revision History: --*/ #include"smt_params.h" #include"smt_params_helper.hpp" +#include"model_params.hpp" void smt_params::updt_local_params(params_ref const & _p) { smt_params_helper p(_p); @@ -33,6 +34,8 @@ void smt_params::updt_local_params(params_ref const & _p) { m_delay_units_threshold = p.delay_units_threshold(); m_preprocess = _p.get_bool("preprocess", true); // hidden parameter m_soft_timeout = p.soft_timeout(); + model_params mp(_p); + m_model_compact = mp.compact(); if (_p.get_bool("arith.greatest_error_pivot", false)) m_arith_pivot_strategy = ARITH_PIVOT_GREATEST_ERROR; else if (_p.get_bool("arith.least_error_pivot", false)) @@ -50,6 +53,4 @@ void smt_params::updt_params(params_ref const & p) { void smt_params::updt_params(context_params const & p) { m_auto_config = p.m_auto_config; m_model = p.m_model; - m_model_validate = p.m_model_validate; } - diff --git a/src/smt/params/smt_params.h b/src/smt/params/smt_params.h index 3d823cb51..256c5a646 100644 --- a/src/smt/params/smt_params.h +++ b/src/smt/params/smt_params.h @@ -177,7 +177,6 @@ struct smt_params : public preprocessor_params, // ----------------------------------- bool m_model; bool m_model_compact; - bool m_model_validate; bool m_model_on_timeout; bool m_model_on_final_check; @@ -264,7 +263,6 @@ struct smt_params : public preprocessor_params, m_abort_after_preproc(false), m_model(true), m_model_compact(false), - m_model_validate(false), m_model_on_timeout(false), m_model_on_final_check(false), m_progress_sampling_freq(0), diff --git a/src/smt/proto_model/array_factory.cpp b/src/smt/proto_model/array_factory.cpp index b91857e40..a929f6d9a 100644 --- a/src/smt/proto_model/array_factory.cpp +++ b/src/smt/proto_model/array_factory.cpp @@ -34,7 +34,7 @@ func_decl * mk_aux_decl_for_array_sort(ast_manager & m, sort * s) { } array_factory::array_factory(ast_manager & m, proto_model & md): - struct_factory(m, m.get_family_id("array"), md) { + struct_factory(m, m.mk_family_id("array"), md) { } /** diff --git a/src/smt/proto_model/datatype_factory.cpp b/src/smt/proto_model/datatype_factory.cpp index 0ea610869..5be802714 100644 --- a/src/smt/proto_model/datatype_factory.cpp +++ b/src/smt/proto_model/datatype_factory.cpp @@ -22,7 +22,7 @@ Revision History: #include"ast_ll_pp.h" datatype_factory::datatype_factory(ast_manager & m, proto_model & md): - struct_factory(m, m.get_family_id("datatype"), md), + struct_factory(m, m.mk_family_id("datatype"), md), m_util(m) { } diff --git a/src/smt/proto_model/numeral_factory.cpp b/src/smt/proto_model/numeral_factory.cpp index 9653322e3..a67b6c075 100644 --- a/src/smt/proto_model/numeral_factory.cpp +++ b/src/smt/proto_model/numeral_factory.cpp @@ -24,7 +24,7 @@ app * arith_factory::mk_value_core(rational const & val, sort * s) { } arith_factory::arith_factory(ast_manager & m): - numeral_factory(m, m.get_family_id("arith")), + numeral_factory(m, m.mk_family_id("arith")), m_util(m) { } @@ -36,7 +36,7 @@ app * arith_factory::mk_value(rational const & val, bool is_int) { } bv_factory::bv_factory(ast_manager & m): - numeral_factory(m, m.get_family_id("bv")), + numeral_factory(m, m.mk_family_id("bv")), m_util(m) { } diff --git a/src/smt/proto_model/proto_model.cpp b/src/smt/proto_model/proto_model.cpp index 92110bc1a..d7a06f14f 100644 --- a/src/smt/proto_model/proto_model.cpp +++ b/src/smt/proto_model/proto_model.cpp @@ -31,7 +31,7 @@ proto_model::proto_model(ast_manager & m, simplifier & s, params_ref const & p): model_core(m), m_asts(m), m_simplifier(s), - m_afid(m.get_family_id(symbol("array"))) { + m_afid(m.mk_family_id(symbol("array"))) { register_factory(alloc(basic_factory, m)); m_user_sort_factory = alloc(user_sort_factory, m); register_factory(m_user_sort_factory); diff --git a/src/smt/proto_model/value_factory.cpp b/src/smt/proto_model/value_factory.cpp index 0b2aded9e..93294d898 100644 --- a/src/smt/proto_model/value_factory.cpp +++ b/src/smt/proto_model/value_factory.cpp @@ -51,7 +51,7 @@ expr * basic_factory::get_fresh_value(sort * s) { } user_sort_factory::user_sort_factory(ast_manager & m): - simple_factory(m, m.get_family_id("user-sort")) { + simple_factory(m, m.mk_family_id("user-sort")) { } void user_sort_factory::freeze_universe(sort * s) { diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index a7623832f..02ee06985 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -2854,7 +2854,12 @@ namespace smt { m_bool_var2assumption.reset(); m_unsat_core.reset(); if (num_assumptions > 0) { - propagate(); // we must give a chance to the theories to propagate before we create a new scope... + // We must give a chance to the theories to propagate before we create a new scope... + propagate(); + // Internal backtracking scopes (created with push_scope()) must only be created when we are + // in a consistent context. + if (inconsistent()) + return; push_scope(); for (unsigned i = 0; i < num_assumptions; i++) { expr * curr_assumption = assumptions[i]; @@ -3987,3 +3992,8 @@ namespace smt { }; +#ifdef Z3DEBUG +void pp(smt::context & c) { + c.display(std::cout); +} +#endif diff --git a/src/smt/smt_implied_equalities.cpp b/src/smt/smt_implied_equalities.cpp index c6f28d4b2..70229ccab 100644 --- a/src/smt/smt_implied_equalities.cpp +++ b/src/smt/smt_implied_equalities.cpp @@ -21,23 +21,21 @@ Revision History: #include "smt_implied_equalities.h" #include "union_find.h" -#include "cmd_context.h" -#include "parametric_cmd.h" #include "ast_pp.h" -#include "arith_decl_plugin.h" -#include "datatype_decl_plugin.h" #include "array_decl_plugin.h" #include "uint_set.h" -#include "model_v2_pp.h" #include "smt_value_sort.h" - +#include "model_smt2_pp.h" +#include "stopwatch.h" +#include "model.h" +#include "solver.h" namespace smt { class get_implied_equalities_impl { ast_manager& m; - smt::kernel& m_solver; + solver& m_solver; union_find_default_ctx m_df; union_find m_uf; array_util m_array_util; @@ -98,7 +96,7 @@ namespace smt { ++m_stats_calls; m_solver.push(); m_solver.assert_expr(m.mk_not(m.mk_eq(s, t))); - bool is_eq = l_false == m_solver.check(); + bool is_eq = l_false == m_solver.check_sat(0,0); m_solver.pop(1); TRACE("get_implied_equalities", tout << mk_pp(t, m) << " = " << mk_pp(s, m) << " " << (is_eq?"eq":"unrelated") << "\n";); if (is_eq) { @@ -125,7 +123,7 @@ namespace smt { m_stats_timer.start(); m_solver.push(); m_solver.assert_expr(m.mk_not(m.mk_eq(s, t))); - bool is_eq = l_false == m_solver.check(); + bool is_eq = l_false == m_solver.check_sat(0,0); m_solver.pop(1); m_stats_timer.stop(); TRACE("get_implied_equalities", tout << mk_pp(t, m) << " = " << mk_pp(s, m) << " " << (is_eq?"eq":"unrelated") << "\n";); @@ -168,7 +166,7 @@ namespace smt { terms[i].term = m.mk_app(m_array_util.get_family_id(), OP_SELECT, 0, 0, args.size(), args.c_ptr()); } assert_relevant(terms); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); model_ref model1; m_solver.get_model(model1); SASSERT(model1.get()); @@ -218,7 +216,7 @@ namespace smt { expr* s = terms[vec[j]].term; m_solver.push(); m_solver.assert_expr(m.mk_not(m.mk_eq(t, s))); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); m_solver.pop(1); TRACE("get_implied_equalities", tout << mk_pp(t, m) << " = " << mk_pp(s, m) << " " << is_sat << "\n";); if (is_sat == l_false) { @@ -237,7 +235,7 @@ namespace smt { if (!non_values.empty()) { - TRACE("get_implied_equalities", model_v2_pp(tout, *model, true);); + TRACE("get_implied_equalities", model_smt2_pp(tout, m, *model, 0);); get_implied_equalities_filter_basic(non_values, terms); //get_implied_equalities_basic(terms); } @@ -321,7 +319,7 @@ namespace smt { public: - get_implied_equalities_impl(smt::kernel& s) : m(s.m()), m_solver(s), m_uf(m_df), m_array_util(m), m_stats_calls(0) {} + get_implied_equalities_impl(ast_manager& m, solver& s) : m(m), m_solver(s), m_uf(m_df), m_array_util(m), m_stats_calls(0) {} lbool operator()(unsigned num_terms, expr* const* terms, unsigned* class_ids) { params_ref p; @@ -338,7 +336,7 @@ namespace smt { m_solver.push(); assert_relevant(num_terms, terms); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); if (is_sat != l_false) { model_ref model; @@ -374,8 +372,8 @@ namespace smt { stopwatch get_implied_equalities_impl::s_timer; stopwatch get_implied_equalities_impl::s_stats_val_eq_timer; - lbool implied_equalities(smt::kernel& solver, unsigned num_terms, expr* const* terms, unsigned* class_ids) { - get_implied_equalities_impl gi(solver); + lbool implied_equalities(ast_manager& m, solver& solver, unsigned num_terms, expr* const* terms, unsigned* class_ids) { + get_implied_equalities_impl gi(m, solver); return gi(num_terms, terms, class_ids); } }; @@ -552,7 +550,7 @@ namespace smt { m_solver.assert_expr(m.mk_implies(eq_lit, eq)); } m_solver.assert_expr(m.mk_not(m.mk_and(eqs.size(), eqs.c_ptr()))); - lbool is_sat = m_solver.check(); + lbool is_sat = m_solver.check_sat(0,0); switch(is_sat) { case l_false: for (unsigned i = 0; i + 1 < terms.size(); ++i) { diff --git a/src/smt/smt_implied_equalities.h b/src/smt/smt_implied_equalities.h index 6fc002ff1..ec9b4bd21 100644 --- a/src/smt/smt_implied_equalities.h +++ b/src/smt/smt_implied_equalities.h @@ -23,13 +23,16 @@ Revision History: #ifndef __SMT_IMPLIED_EQUALITIES_H__ #define __SMT_IMPLIED_EQUALITIES_H__ -#include"smt_kernel.h" +#include"smt_solver.h" +#include"lbool.h" +#include"ast.h" namespace smt { lbool implied_equalities( - kernel & solver, + ast_manager & m, + solver & solver, unsigned num_terms, expr* const* terms, unsigned* class_ids); diff --git a/src/smt/smt_internalizer.cpp b/src/smt/smt_internalizer.cpp index b3f16a3ce..42e761b61 100644 --- a/src/smt/smt_internalizer.cpp +++ b/src/smt/smt_internalizer.cpp @@ -23,7 +23,6 @@ Revision History: #include"ast_smt2_pp.h" #include"smt_model_finder.h" #include"for_each_expr.h" -#include"theory_instgen.h" namespace smt { @@ -530,11 +529,6 @@ namespace smt { SASSERT(!b_internalized(q)); SASSERT(q->is_forall()); SASSERT(check_patterns(q)); - if (m_fparams.m_instgen) { - theory* th = m_theories.get_plugin(m_manager.get_family_id("inst_gen")); - static_cast(th)->internalize_quantifier(q); - return; - } bool_var v = mk_bool_var(q); unsigned generation = m_generation; unsigned _generation; diff --git a/src/smt/smt_kernel.cpp b/src/smt/smt_kernel.cpp index 779c68625..8ecd079bf 100644 --- a/src/smt/smt_kernel.cpp +++ b/src/smt/smt_kernel.cpp @@ -253,12 +253,10 @@ namespace smt { } lbool kernel::setup_and_check() { - set_cancel(false); return m_imp->setup_and_check(); } lbool kernel::check(unsigned num_assumptions, expr * const * assumptions) { - set_cancel(false); lbool r = m_imp->check(num_assumptions, assumptions); TRACE("smt_kernel", tout << "check result: " << r << "\n";); return r; diff --git a/src/smt/smt_model_finder.cpp b/src/smt/smt_model_finder.cpp index 619a7d60c..e69b7a1b6 100644 --- a/src/smt/smt_model_finder.cpp +++ b/src/smt/smt_model_finder.cpp @@ -454,8 +454,8 @@ namespace smt { m_model(0), m_eval_cache_range(m), m_new_constraints(0) { - m_asimp = static_cast(s.get_plugin(m.get_family_id("arith"))); - m_bvsimp = static_cast(s.get_plugin(m.get_family_id("bv"))); + m_asimp = static_cast(s.get_plugin(m.mk_family_id("arith"))); + m_bvsimp = static_cast(s.get_plugin(m.mk_family_id("bv"))); } ~auf_solver() { diff --git a/src/smt/smt_model_finder.h b/src/smt/smt_model_finder.h index 20d9ba6ef..b89603912 100644 --- a/src/smt/smt_model_finder.h +++ b/src/smt/smt_model_finder.h @@ -33,7 +33,7 @@ Abstract: Lugano, Switzerland, 2010. - Bugs, Moles and Skeletons: Symbolic Reasoning for Software - Development, Leonardo de Moura, Nikolaj Bjørner, IJCAR, + Development, Leonardo de Moura, Nikolaj Bjorner, IJCAR, Edinburgh, Scotland, 2010. Author: diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp index ac31eb1a9..96673e67e 100644 --- a/src/smt/smt_setup.cpp +++ b/src/smt/smt_setup.cpp @@ -28,7 +28,6 @@ Revision History: #include"theory_datatype.h" #include"theory_dummy.h" #include"theory_dl.h" -#include"theory_instgen.h" #include"theory_seq_empty.h" namespace smt { @@ -693,7 +692,7 @@ namespace smt { void setup::setup_arith() { switch(m_params.m_arith_mode) { case AS_NO_ARITH: - m_context.register_plugin(alloc(smt::theory_dummy, m_manager.get_family_id("arith"), "no arithmetic")); + m_context.register_plugin(alloc(smt::theory_dummy, m_manager.mk_family_id("arith"), "no arithmetic")); break; case AS_DIFF_LOGIC: if (m_params.m_arith_fixnum) { @@ -735,7 +734,7 @@ namespace smt { void setup::setup_bv() { switch(m_params.m_bv_mode) { case BS_NO_BV: - m_context.register_plugin(alloc(smt::theory_dummy, m_manager.get_family_id("bv"), "no bit-vector")); + m_context.register_plugin(alloc(smt::theory_dummy, m_manager.mk_family_id("bv"), "no bit-vector")); break; case BS_BLASTER: m_context.register_plugin(alloc(smt::theory_bv, m_manager, m_params, m_params)); @@ -746,7 +745,7 @@ namespace smt { void setup::setup_arrays() { switch(m_params.m_array_mode) { case AR_NO_ARRAY: - m_context.register_plugin(alloc(smt::theory_dummy, m_manager.get_family_id("array"), "no array")); + m_context.register_plugin(alloc(smt::theory_dummy, m_manager.mk_family_id("array"), "no array")); break; case AR_SIMPLE: m_context.register_plugin(alloc(smt::theory_array, m_manager, m_params)); @@ -772,11 +771,6 @@ namespace smt { void setup::setup_seq() { m_context.register_plugin(alloc(theory_seq_empty, m_manager)); } - void setup::setup_instgen() { - if (m_params.m_instgen) { - m_context.register_plugin(mk_theory_instgen(m_manager, m_params)); - } - } void setup::setup_unknown() { setup_arith(); @@ -784,7 +778,6 @@ namespace smt { setup_bv(); setup_datatypes(); setup_dl(); - setup_instgen(); setup_seq(); } diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp index e8c1c6698..1fbb58847 100644 --- a/src/smt/smt_solver.cpp +++ b/src/smt/smt_solver.cpp @@ -25,166 +25,114 @@ namespace smt { class solver : public solver_na2as { smt_params m_params; - smt::kernel * m_context; + smt::kernel m_context; progress_callback * m_callback; + symbol m_logic; public: - solver():m_context(0), m_callback(0) {} - + solver(ast_manager & m, params_ref const & p, symbol const & l): + solver_na2as(m), + m_params(p), + m_context(m, m_params) { + m_logic = l; + if (m_logic != symbol::null) + m_context.set_logic(m_logic); + } + virtual ~solver() { - if (m_context != 0) - dealloc(m_context); } virtual void updt_params(params_ref const & p) { m_params.updt_params(p); - if (m_context == 0) - return; - m_context->updt_params(p); + m_context.updt_params(p); } virtual void collect_param_descrs(param_descrs & r) { - if (m_context == 0) { - ast_manager m; - reg_decl_plugins(m); - smt::kernel s(m, m_params); - s.collect_param_descrs(r); - } - else { - m_context->collect_param_descrs(r); - } - } - - virtual void init_core(ast_manager & m, symbol const & logic) { - reset(); - // We can throw exceptions when creating a smt::kernel object - // So, we should create the smt::kernel outside of the criticial section - // block. OMP does not allow exceptions to cross critical section boundaries. - smt::kernel * new_kernel = alloc(smt::kernel, m, m_params); - #pragma omp critical (solver) - { - m_context = new_kernel; - if (m_callback) - m_context->set_progress_callback(m_callback); - } - if (logic != symbol::null) - m_context->set_logic(logic); + m_context.collect_param_descrs(r); } virtual void collect_statistics(statistics & st) const { - if (m_context == 0) { - return; - } - else { - m_context->collect_statistics(st); - } - } - - virtual void reset_core() { - if (m_context != 0) { - #pragma omp critical (solver) - { - dealloc(m_context); - m_context = 0; - } - } - } - - // An exception may be thrown when creating a smt::kernel. - // So, there is no guarantee that m_context != 0 when - // using smt_solver from the SMT 2.0 command line frontend. - void check_context() const { - if (m_context == 0) - throw default_exception("Z3 failed to create solver, check previous error messages"); + m_context.collect_statistics(st); } virtual void assert_expr(expr * t) { - check_context(); - m_context->assert_expr(t); + m_context.assert_expr(t); } virtual void push_core() { - check_context(); - m_context->push(); + m_context.push(); } virtual void pop_core(unsigned n) { - check_context(); - m_context->pop(n); + m_context.pop(n); } virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) { - check_context(); TRACE("solver_na2as", tout << "smt_solver::check_sat_core: " << num_assumptions << "\n";); - return m_context->check(num_assumptions, assumptions); + return m_context.check(num_assumptions, assumptions); } virtual void get_unsat_core(ptr_vector & r) { - check_context(); - unsigned sz = m_context->get_unsat_core_size(); + unsigned sz = m_context.get_unsat_core_size(); for (unsigned i = 0; i < sz; i++) - r.push_back(m_context->get_unsat_core_expr(i)); + r.push_back(m_context.get_unsat_core_expr(i)); } virtual void get_model(model_ref & m) { - check_context(); - m_context->get_model(m); + m_context.get_model(m); } virtual proof * get_proof() { - check_context(); - return m_context->get_proof(); + return m_context.get_proof(); } virtual std::string reason_unknown() const { - check_context(); - return m_context->last_failure_as_string(); + return m_context.last_failure_as_string(); } virtual void get_labels(svector & r) { - check_context(); buffer tmp; - m_context->get_relevant_labels(0, tmp); + m_context.get_relevant_labels(0, tmp); r.append(tmp.size(), tmp.c_ptr()); } virtual void set_cancel(bool f) { -#pragma omp critical (solver) - { - if (m_context) - m_context->set_cancel(f); - } + m_context.set_cancel(f); } virtual void set_progress_callback(progress_callback * callback) { m_callback = callback; - if (m_context) - m_context->set_progress_callback(callback); + m_context.set_progress_callback(callback); } virtual unsigned get_num_assertions() const { - if (m_context) - return m_context->size(); - else - return 0; + return m_context.size(); } virtual expr * get_assertion(unsigned idx) const { - SASSERT(m_context); SASSERT(idx < get_num_assertions()); - return m_context->get_formulas()[idx]; + return m_context.get_formulas()[idx]; } virtual void display(std::ostream & out) const { - if (m_context) - m_context->display(out); - else - out << "(solver)"; + m_context.display(out); } }; }; -solver * mk_smt_solver() { - return alloc(smt::solver); +solver * mk_smt_solver(ast_manager & m, params_ref const & p, symbol const & logic) { + return alloc(smt::solver, m, p, logic); } + +class smt_solver_factory : public solver_factory { +public: + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + return mk_smt_solver(m, p, logic); + } +}; + +solver_factory * mk_smt_solver_factory() { + return alloc(smt_solver_factory); +} + diff --git a/src/smt/smt_solver.h b/src/smt/smt_solver.h index e9af9aafa..81c9a1319 100644 --- a/src/smt/smt_solver.h +++ b/src/smt/smt_solver.h @@ -21,8 +21,13 @@ Notes: #ifndef _SMT_SOLVER_H_ #define _SMT_SOLVER_H_ -class solver; +#include"ast.h" +#include"params.h" -solver * mk_smt_solver(); +class solver; +class solver_factory; + +solver * mk_smt_solver(ast_manager & m, params_ref const & p, symbol const & logic); +solver_factory * mk_smt_solver_factory(); #endif diff --git a/src/smt/theory_arith_core.h b/src/smt/theory_arith_core.h index b774fb3d9..fafe73a79 100644 --- a/src/smt/theory_arith_core.h +++ b/src/smt/theory_arith_core.h @@ -1294,7 +1294,7 @@ namespace smt { template theory_arith::theory_arith(ast_manager & m, theory_arith_params & params): - theory(m.get_family_id("arith")), + theory(m.mk_family_id("arith")), m_params(params), m_util(m), m_arith_eq_solver(m), diff --git a/src/smt/theory_array_base.cpp b/src/smt/theory_array_base.cpp index ca6449d1d..c2c50567f 100644 --- a/src/smt/theory_array_base.cpp +++ b/src/smt/theory_array_base.cpp @@ -27,7 +27,7 @@ Revision History: namespace smt { theory_array_base::theory_array_base(ast_manager & m): - theory(m.get_family_id("array")), + theory(m.mk_family_id("array")), m_found_unsupported_op(false) { } diff --git a/src/smt/theory_bv.cpp b/src/smt/theory_bv.cpp index e425071d2..559ce155b 100644 --- a/src/smt/theory_bv.cpp +++ b/src/smt/theory_bv.cpp @@ -1239,7 +1239,7 @@ namespace smt { } theory_bv::theory_bv(ast_manager & m, theory_bv_params const & params, bit_blaster_params const & bb_params): - theory(m.get_family_id("bv")), + theory(m.mk_family_id("bv")), m_params(params), m_util(m), m_autil(m), diff --git a/src/smt/theory_datatype.cpp b/src/smt/theory_datatype.cpp index 65abfe238..8c6543eff 100644 --- a/src/smt/theory_datatype.cpp +++ b/src/smt/theory_datatype.cpp @@ -454,7 +454,7 @@ namespace smt { } theory_datatype::theory_datatype(ast_manager & m, theory_datatype_params & p): - theory(m.get_family_id("datatype")), + theory(m.mk_family_id("datatype")), m_params(p), m_util(m), m_find(*this), diff --git a/src/smt/theory_dense_diff_logic_def.h b/src/smt/theory_dense_diff_logic_def.h index 4d50bd8bf..21f1262ac 100644 --- a/src/smt/theory_dense_diff_logic_def.h +++ b/src/smt/theory_dense_diff_logic_def.h @@ -28,7 +28,7 @@ namespace smt { template theory_dense_diff_logic::theory_dense_diff_logic(ast_manager & m, theory_arith_params & p): - theory(m.get_family_id("arith")), + theory(m.mk_family_id("arith")), m_params(p), m_autil(m), m_arith_eq_adapter(*this, p, m_autil), diff --git a/src/smt/theory_diff_logic.h b/src/smt/theory_diff_logic.h index 264ab9b2d..4140f683c 100644 --- a/src/smt/theory_diff_logic.h +++ b/src/smt/theory_diff_logic.h @@ -306,7 +306,7 @@ namespace smt { public: theory_diff_logic(ast_manager& m, smt_params & params): - theory(m.get_family_id("arith")), + theory(m.mk_family_id("arith")), m_params(params), m_util(m), m_arith_eq_adapter(*this, params, m_util), diff --git a/src/smt/theory_dl.cpp b/src/smt/theory_dl.cpp index 402ab856c..758f78c2c 100644 --- a/src/smt/theory_dl.cpp +++ b/src/smt/theory_dl.cpp @@ -88,7 +88,7 @@ namespace smt { m_th.get_rep(s, r, v); app_ref rep_of(m_th.m()); rep_of = m_th.m().mk_app(r, m_node->get_owner()); - theory_id bv_id = m_th.m().get_family_id("bv"); + theory_id bv_id = m_th.m().mk_family_id("bv"); theory_bv* th_bv = dynamic_cast(ctx.get_theory(bv_id)); SASSERT(th_bv); rational val; @@ -106,7 +106,7 @@ namespace smt { public: theory_dl(ast_manager& m): - theory(m.get_family_id("datalog_relation")), + theory(m.mk_family_id("datalog_relation")), m_util(m), m_bv(m), m_trail(m) diff --git a/src/smt/theory_instgen.cpp b/src/smt/theory_instgen.cpp deleted file mode 100644 index 68e04aab0..000000000 --- a/src/smt/theory_instgen.cpp +++ /dev/null @@ -1,1494 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - theory_instgen.cpp - -Abstract: - - iProver style theory solver. - It provides an instantiation based engine - based on InstGen methods together with - unit propagation. - -Author: - - Krystof Hoder (t-khoder) - Nikolaj Bjorner (nbjorner) 2011-10-6 - -Revision History: - -Main data-structures: - -- Instantiation = Var -> Expr -- MatchingSet = Instantiation-set - operations: - - has_instance : Instantiation -> Bool - has_instance(i) = exists j in MatchingSet . j <= i -- UnificationIndex - operations: - - insert : Expr - - remove : Expr - - unify : Expr -> Expr-set - - set of inserted expressions that unify -- RootClauseMap : Expr -> Quantifier - where RootClauseMap(clause) = The quantifier that originated clause -- Occurs : Expr -> Quantifier-set - the set of quantifiers where non-ground literal occurs. -- LiteralMeanings : Literal -> Expr-set - - set of non-ground literals that were grounded to Literal -- InternalizedFoLits : Expr-set - - forall e in InternalizedFoLits . e \in LiteralMeanings(ground(e)) -- MatchingSets : Quantifier -> MatchingSet - - -Main operation: - - - insert all assigned literals into UnificationIndex - - for l' in LiteralMeanings(l) do: - for m',theta in UnificationIndex.unify(not l') do: - for q in Occurs(l') do: - for q' in Occurs(m') do: - instantiate q with theta - instantiate q' with theta - - instantiate q with theta: - -Discussion of plans: - -- Efficient unit propagation using the tables from dl_ - See addittional notes under unit propagation. - The idea is to perfrm unit propagation using the tables - provided in the dl_ module. This is similar to unit - propagation from the EPR solver and retains succinctness - features, but does not carry over the splitting component. - The efficient propagator is aimed at solving ground problems more efficiently, - for example - -- Reduce set of selected literals when clause already has on selected literal. - -- Subsumption module: - - simplify clause using already asserted clauses. - - check for variants. - -- Completeness for EPR with equality: - The relevant equality clause for EPR are C \/ x = y and C \/ a = x - Destructive E-resolution (DER) removes disequalities. - Two approaches: - 1. Rely on super-position/hyper-resolution of ordinary literals - in the clause. - 2. Instantiate based on congruence closure. - The instantiation based approach takes a clause of the form C \/ x = y, - where all other non-equality literals in C are assigned false by the - current assignment, and (the grounded version U = U' of) x = y is - assigned true. Take the equivalence classes of the type of x and - instantiate x, y using representatives for different equivalence - classes. The number of instantiations is potentially quadratic - in the number of terms. One reduction considers symmetries: - instantiate x by a smaller representative than y. -- Unit propagation: - - Why should unit-propagation matter: hunch: similar role as - theory propagation where conflicts are created close to root - of search tree. - - Add theory identifiers to literals so that assign_eh is invoked. - - Produce explanation objects for unit propagation. - - Unit propagation index. - - Idea only propagate known literals -- Exchange unit literals with super position engine for equalities. - iProver approach: perform unit super-position proof, get instances - by labeling equalities by clauses + substitution (set-labeling) - portfolio approach: exchange unit literals to super-position - (or hypotheses as suggested in more general setting). - ---*/ - -#include "theory_instgen.h" -#include "value_factory.h" -#include "smt_model_generator.h" -#include "smt_context.h" -#include "ast_smt2_pp.h" -#include "substitution.h" -#include "substitution_tree.h" -#include "uint_set.h" -#include "unifier.h" -#include "matcher.h" -#include "rewriter.h" -#include "rewriter_def.h" -#include "var_subst.h" - -#define PP mk_pp - -namespace smt { - - - // - // expression grounding for passing to the SMT solver - // - class grounder { - ast_manager& m; - vector > m_defaults; - expr_ref_vector m_ref_holder; - - class grounding_rewriter_cfg; - - void reserve(unsigned idx) { - if (m_defaults.size() <= idx) { - m_defaults.resize(idx+1); - } - } - - expr* mk_default(sort* s) { - return mk_default(0, s); - } - - expr* mk_default(unsigned i, sort* s) { - expr* d; - reserve(i); - if (!m_defaults[i].find(s, d)) { - d = m.mk_fresh_const("U",s); - m_defaults[i].insert(s, d); - m_ref_holder.push_back(d); - } - return d; - } - - class grounding_rewriter_cfg : public default_rewriter_cfg { - grounder& m_parent; - bool m_collapse; - public: - grounding_rewriter_cfg(grounder& parent, bool collapse) - : m_parent(parent), m_collapse(collapse) {} - - bool get_subst(expr * s, expr * & t, proof * & t_pr) { - SASSERT(is_app(s) || is_var(s)); - if (is_var(s)) { - var* v = to_var(s); - if (m_collapse) { - t = m_parent.mk_default(v->get_sort()); - } - else { - t = m_parent.mk_default(v->get_idx(), v->get_sort()); - } - } - return is_var(s); - } - }; - - void mk(expr * e, app_ref& res, bool collapse) { - if(is_ground(e)) { - res = to_app(e); - } - else { - while (is_quantifier(e)) { - e = to_quantifier(e)->get_expr(); - } - SASSERT(is_app(e)); - grounding_rewriter_cfg r_cfg(*this, collapse); - rewriter_tpl rwr(m, false, r_cfg); - expr_ref res_e(m); - rwr(e, res_e); - res = to_app(res_e); - } - SASSERT(is_ground(res.get())); - } - - public: - grounder(ast_manager& m): m(m), m_ref_holder(m) { - reserve(0); - } - - /** - create a grounding that recycles the same constant for - different variables of the same sort. - - This function can be called either with whole clauses (incl. quantifier), - or with literals one by one (without a quantifier) - */ - void operator()(expr * e, app_ref& res) { - mk(e, res, true); - } - - // - // create a grounding where different variables have different names - // - void mk_diff(expr * e, app_ref& res) { - mk(e, res, false); - } - }; - - // - // Class for first-order subsumption checking. - // if clause[renaming] is a superset of existing clause in context, then clause is subsumed. - // if context => clause then clause is subsumed. - // if context & clause => ~ lit then lit is subsumed from clause - // - // TBD: - // - check unit propagation - // - use internalizer functions directly. The assertions have already been pre-processed. - // - class clause_subsumption { - ast_manager& m; - grounder m_grounder; - smt_params m_params; - context m_ctx; - quantifier_ref_vector m_assumptions; - unsigned_vector m_limit; - public: - clause_subsumption(ast_manager& m, smt_params& p): - m(m), m_grounder(m), m_params(p), m_ctx(m,m_params), m_assumptions(m) { - m_params.m_instgen = false; - } - - void simplify(quantifier* new_clause, expr_ref& result, ptr_vector& assumptions) { -#if 1 - result = new_clause; - return; -#endif - - SASSERT(new_clause->is_forall()); - expr* body = new_clause->get_expr(); - app_ref ground_clause(m); - m_grounder.mk_diff(new_clause, ground_clause); - if (is_subsumed(ground_clause)) { - TRACE("theory_instgen", tout << "subsumed: " << PP(new_clause,m) << "\n";); - result = m.mk_true(); - return; - } - if (is_homomorphic_image(body)) { - result = m.mk_true(); - return; - } - // Assert the current clause. - m_ctx.internalize(ground_clause, true); - m_ctx.assign(m_ctx.get_literal(ground_clause), b_justification()); - TRACE("theory_instgen", tout << "Asserting: " << PP(ground_clause,m) << "\n";); - m_assumptions.push_back(new_clause); - SASSERT(m.is_or(body) == m.is_or(ground_clause)); - if (!m.is_or(body)) { - result = new_clause; - return; - } - SASSERT(to_app(body)->get_num_args() == ground_clause->get_num_args()); - ptr_vector lits; - for (unsigned i = 0; i < to_app(body)->get_num_args(); ++i) { - m_ctx.push(); - m_ctx.assign(m_ctx.get_literal(ground_clause->get_arg(i)), b_justification()); - lbool is_sat = m_ctx.check(); - m_ctx.pop(1); - if (is_sat != l_false) { - lits.push_back(to_app(body)->get_arg(i)); - } - else { - TRACE("theory_instgen", tout << "subsumed literal: " << PP(to_app(body)->get_arg(i),m) << "\n";); - } - } - if (lits.size() == ground_clause->get_num_args()) { - result = new_clause; - } - else { - SASSERT(!lits.empty()); - result = lits.size()==1?lits[0]:m.mk_or(lits.size(), lits.c_ptr()); - result = m.update_quantifier(new_clause, result); - TRACE("theory_instgen", tout << "simplified: " << PP(new_clause,m) << "\n"; - tout << PP(result.get(), m) << "\n"; - ); - //overapproximation of required assumptions - //( m_assumptions.size()-1 ... the -1 is not to make ourselves as an assumption) - assumptions.append(m_assumptions.size()-1, m_assumptions.c_ptr()); - } - } - - void push() { - m_ctx.push(); - m_limit.push_back(m_assumptions.size()); - } - - void pop(unsigned num_scopes) { - m_ctx.pop(num_scopes); - - unsigned last_idx = m_limit.size()-num_scopes; - unsigned restored_assumptions_size = m_limit[last_idx]; - m_limit.resize(last_idx); - m_assumptions.resize(restored_assumptions_size); - } - - private: - - bool is_subsumed(expr* ground_clause) { - m_ctx.push(); - m_ctx.internalize(ground_clause, true); - m_ctx.assign(~m_ctx.get_literal(ground_clause), b_justification()); - lbool is_sat = m_ctx.check(); - m_ctx.pop(1); - TRACE("theory_instgen", - tout << PP(ground_clause, m) << " " << - ((is_sat==l_false)?"unsat":"sat") << "\n";); - return (is_sat == l_false); - } - - bool is_homomorphic_image(expr* body) { - // TBD - return false; - } - - }; - - class fo_clause_internalizer; - class instantiator; - class theory_instgen_impl; - typedef expr_ref_vector inst; - - class instantiation_result { - quantifier_ref m_clause; - inst m_subst; - public: - instantiation_result(ast_manager& m) : m_clause(m), m_subst(m) {} - - void init(quantifier * q, const inst& subst) { - SASSERT(!m_clause); //we init each object at most once - SASSERT(m_subst.empty()); - SASSERT(q); - m_clause = q; - m_subst.append(subst); - } - quantifier * clause() const { return m_clause; } - const inst& subst() const { return m_subst; } - }; - - typedef vector instantiation_result_vector; - - // TBD: replace this by the substitution tree index. - // It should do the trick of identifying instances and generalizers. - // see matching_set2.. - // - class matching_set { - ast_manager& m; - vector m_inst; - - //used in the has_instance function - mutable substitution m_subst; - - public: - matching_set(ast_manager& m) : m(m), m_subst(m) {} - unsigned size() const { return m_inst.size(); } - inst const& operator[](unsigned i) const { return m_inst[i]; } - - void insert(inst const& inst) { - SASSERT(m_inst.empty() || m_inst.back().size() == inst.size()); - TRACE("theory_instgen_verbose", - for (unsigned i = 0; i < inst.size(); ++i) { - tout << PP(inst[i], m) << " "; - } - tout << "\n"; - ); - m_inst.push_back(inst); - } - void insert(unsigned sz, expr* const* exprs) { - insert(inst(m, sz, exprs)); - } - void pop_insert() { m_inst.pop_back(); } - - bool has_instance(inst const& inst) { - unsigned dont_care; - return has_instance(inst, dont_care); - } - - bool has_instance(inst const& new_inst, unsigned& index) { - for (unsigned i = 0; i < size(); ++i) { - if (has_instance(new_inst, m_inst[i])) { - index = i; - return true; - } - } - return false; - } - - class insert_inst : public trail { - matching_set& m_ms; - public: - insert_inst(matching_set& m): m_ms(m) {} - virtual void undo(smt::context& ctx) { m_ms.pop_insert(); } - }; - - static bool is_identity(const inst& subst) { - uint_set vars; - vars.reset(); - unsigned sz = subst.size(); - for(unsigned i=0; iget_idx(); - if(vars.contains(var_idx)) { - return false; - } - vars.insert(var_idx); - } - return true; - } - - private: - // check if old_instance is an instance of new_instance. - bool has_instance(inst const& new_instance, inst const& old_instance) const { - SASSERT(new_instance.size() == old_instance.size()); - unsigned sz = new_instance.size(); - m_subst.reset(); - m_subst.reserve_vars(sz); - m_subst.reserve_offsets(2); - matcher mtchr(m); - for(unsigned i = 0; i < sz; i++) { - TRACE("theory_instgen_verbose", tout << PP(new_instance[i], m) << " " << PP(old_instance[i], m) << "\n";); - if(!mtchr(new_instance[i], old_instance[i], m_subst)) { - return false; - } - } - return true; - } - }; - - - class matching_set2 { - class inst_visitor : public st_visitor { - bool m_found; - public: - inst_visitor(substitution& s): st_visitor(s), m_found(false) {} - virtual bool operator()(expr * e) { - m_found = true; - return false; - } - void reset() { m_found = false; } - bool found() const { return m_found; } - }; - - ast_manager& m; - substitution_tree m_st; - func_decl_ref m_f; - app_ref_vector m_trail; - substitution m_dummy; - inst_visitor m_visitor; - - public: - matching_set2(ast_manager& m) : m(m), m_st(m), m_f(m), m_trail(m), m_dummy(m), m_visitor(m_dummy) {} - - void insert(inst const& inst) { - if (!m_f.get()) { - ptr_buffer domain; - for (unsigned i = 0; i < inst.size(); ++i) { - domain.push_back(m.get_sort(inst[i])); - } - m_f = m.mk_func_decl(symbol("tuple"),inst.size(), domain.c_ptr(), m.mk_bool_sort()); - m_trail.push_back(m.mk_app(m_f, inst.size(), inst.c_ptr())); - m_st.insert(m_trail.back()); - } - } - void insert(unsigned sz, expr* const* exprs) { - insert(inst(m, sz, exprs)); - } - void pop_insert() { - m_st.erase(m_trail.back()); - m_trail.pop_back(); - } - - bool has_instance(inst const& inst) { - app_ref f(m); - f = m.mk_app(m_f, inst.size(), inst.c_ptr()); - m_visitor.reset(); - m_st.inst(f, m_visitor); - return m_visitor.found(); - } - - class insert_inst : public trail { - matching_set& m_ms; - public: - insert_inst(matching_set& m): m_ms(m) {} - virtual void undo(smt::context& ctx) { m_ms.pop_insert(); } - }; - - static bool is_identity(const inst& subst) { - uint_set vars; - vars.reset(); - unsigned sz = subst.size(); - for(unsigned i=0; iget_idx(); - if(vars.contains(var_idx)) { - return false; - } - vars.insert(var_idx); - } - return true; - } - }; - - - ///////////////////////// - // inst_gen_unif_index - // - - class inst_gen_unif_index { - ast_manager & m; - substitution_tree m_st; - unsigned m_num_vars; - app_ref_vector m_ref_holder; - unsigned_vector m_lim; - - class collecting_visitor : public st_visitor { - app_ref_vector& m_acc; - public: - collecting_visitor(app_ref_vector& acc, substitution& subst) - : st_visitor(subst), m_acc(acc) {} - virtual bool operator()(expr * e) { - SASSERT(is_app(e)); - m_acc.push_back(to_app(e)); - return true; - } - }; - - - class st_contains_visitor : public st_visitor { - expr* m_e; - bool m_found; - public: - st_contains_visitor(substitution& s, expr* e): st_visitor(s), m_e(e), m_found(false) {} - virtual bool operator()(expr* e) { - if (e == m_e) { - m_found = true; - return false; - } - return true; - } - bool found() const { return m_found; } - }; - - void debug_st(char const* cmd, app* l) { - expr_ref e(m); - ptr_vector sorts; - svector names; - get_free_vars(l, sorts); - for (unsigned i = 0; i < sorts.size(); ++i) { - if (!sorts[i]) { - sorts[i] = m.mk_bool_sort(); - } - names.push_back(symbol(i)); - } - sorts.reverse(); - if (!sorts.empty()) { - e = m.mk_forall(sorts.size(), sorts.c_ptr(), names.c_ptr(), l); - } - else { - e = l; - } - std::cout << ":" << cmd << " " << PP(e.get(),m) << "\n"; - } - - public: - inst_gen_unif_index(ast_manager & m) : - m(m), m_st(m), m_num_vars(0), m_ref_holder(m) {} - - void insert_literal(app * lit) { - // debug_st("st_insert", lit); - m_ref_holder.push_back(lit); - m_st.insert(lit); - } - - void get_unifications(app * lit, app_ref_vector& res) { - substitution subst(m); - subst.reserve_vars(m_num_vars); - subst.reserve_offsets(m_st.get_approx_num_regs()); - collecting_visitor visitor(res, subst); - // TRACE("theory_instgen", m_st.display(tout); ); - m_st.unify(lit, visitor); - } - void reserve_num_vars(unsigned num_vars) { - if (num_vars > m_num_vars) m_num_vars = num_vars; - } - - void push() { - m_lim.push_back(m_ref_holder.size()); - } - - void pop() { - unsigned sz = m_lim.back(); - m_ref_holder.resize(sz); - m_lim.pop_back(); - m_st.reset(); - } - - void pop_orig() { - unsigned sz = m_lim.back(); - while (m_ref_holder.size() > sz) { - debug_st("st_erase", m_ref_holder.back()); - m_st.erase(m_ref_holder.back()); - - substitution subst(m); - subst.reserve_vars(m_num_vars); - subst.reserve_offsets(m_st.get_approx_num_regs()); - st_contains_visitor cv(subst, m_ref_holder.back()); - m_st.unify(m_ref_holder.back(), cv); - if (cv.found()) { - m_st.display(std::cout); - m_st.erase(m_ref_holder.back()); - } - SASSERT(!cv.found()); - m_ref_holder.pop_back(); - } - m_lim.pop_back(); - } - - void display(std::ostream& out) { - m_st.display(out); - } - - bool empty() const{ - return m_st.empty(); - } - }; - - - /////////////////////////// - // fo_clause_internalizer - // - - class fo_clause_internalizer { - private: - typedef map, default_eq > literal_meaning_map; - typedef obj_map occurs; - typedef obj_map root_clause_map; //for any clause instance it gives us the clause from the original problem - - theory_instgen_impl& m_parent; - expr_ref_vector m_vars; - var_subst m_subst; - occurs m_occurs; - grounder m_grounder; - /** - For each clause which is a result of instantiation contains the - original problem clause from which it derives. - */ - root_clause_map m_root_clause_map; - - - /** - For each SMT literal contains a vector of first-order literals - that are represented by this literal. - */ - literal_meaning_map m_literal_meanings; - - /** - fo literals that have been internalized by this object. - Invariant: any app* fol in this set has a literal l such that - m_literal_meanings[l].contains(fol). - Particularly, l==get_context().get_literal(gnd_fol) where gnd_fol - is a grounded version of this literal - */ - obj_hashtable m_internalized_fo_lits; - - - ast_manager& m() const; - smt::context& get_context() const; - - class insert_occurs_trail : public trail { - occurs& m_occ; - quantifier_ref_vector* m_qs; - expr_ref m_lit; - public: - insert_occurs_trail(occurs& o, expr_ref& lit, quantifier* q): m_occ(o), m_qs(0), m_lit(lit) { - occurs::obj_map_entry* e = m_occ.insert_if_not_there2(lit,0); - m_qs = e->get_data().m_value; - if (!m_qs) { - m_qs = alloc(quantifier_ref_vector, lit.get_manager()); - e->get_data().m_value = m_qs; - } - m_qs->push_back(q); - } - - virtual void undo(smt::context& ctx) { - SASSERT(m_qs && !m_qs->empty()); - SASSERT(m_qs == m_occ.find_core(m_lit)->get_data().m_value); - m_qs->pop_back(); - if (m_qs->empty()) { - m_occ.remove(m_lit); - dealloc(m_qs); - } - } - }; - - class lit_meaning_trail : public trail { - literal_meaning_map& m_map; - app_ref_vector* m_apps; - smt::literal m_smtlit; - public: - - lit_meaning_trail(literal_meaning_map& map, ast_manager& m, smt::literal l, app* lit): - m_map(map), m_smtlit(l) { - literal_meaning_map::entry* e = map.insert_if_not_there2(l, 0); - m_apps = e->get_data().m_value; - if (!m_apps) { - m_apps = alloc(app_ref_vector, m); - e->get_data().m_value = m_apps; - } - m_apps->push_back(lit); - } - - virtual void undo(smt::context& ctx) { - SASSERT(m_apps && !m_apps->empty()); - SASSERT(m_apps == m_map.find_core(m_smtlit)->get_data().m_value); - m_apps->pop_back(); - if (m_apps->empty()) { - m_map.remove(m_smtlit); - dealloc(m_apps); - } - } - }; - - quantifier * get_root_clause(expr* clause) const { - quantifier * root; - if(!m_root_clause_map.find(clause, root)) { - SASSERT(is_forall(clause)); - root = to_quantifier(clause); - } - return root; - } - - void replace_by_root_clauses(ptr_vector& vect) const { - unsigned sz = vect.size(); - for(unsigned i=0; i(t)); - get_context().push_trail(insert_obj_trail(m_internalized_fo_lits, lit)); - get_context().push_trail(lit_meaning_trail(m_literal_meanings, m(), smt_lit, lit)); - TRACE("theory_instgen", tout << smt_lit << " "<< PP(grounded_lit, m()) << " |-> " << PP(lit, m()) << "\n";); - } - get_context().mark_as_relevant(smt_lit); - return smt_lit; - } - - void add_clause_to_smt(expr * clause, quantifier* root_clause, ptr_vector const& assumptions=ptr_vector()); - - void get_instance_clause(instantiation_result const& ir, expr_ref& res); - - /** - return false if nothing was done - - assumptions are instantiated clauses (to get a correct assumption for the SMT solver, we need - to convert the vector to root clauses). - */ - bool simplify_clause(quantifier * clause, expr_ref& result, ptr_vector& assumptions); - - public: - - fo_clause_internalizer(theory_instgen_impl& parent): - m_parent(parent), - m_vars(m()), - m_subst(m()), - m_grounder(m()) { - } - - ~fo_clause_internalizer() { - reset_dealloc_values(m_occurs); - } - - void get_literal_meanings(literal l, ptr_vector& fo_lits) { - app_ref_vector* lits = 0; - m_literal_meanings.find(l, lits); - if (lits) { - fo_lits.append(lits->size(), lits->c_ptr()); - } - } - - void add_initial_clause(quantifier* q) { - add_clause_to_smt(q, 0); - } - - quantifier_ref_vector* find_occurs(app * l) { - quantifier_ref_vector* result = 0; - m_occurs.find(l, result); - return result; - } - - void add_new_instance(instantiation_result const& ir) { - quantifier * root_clause = get_root_clause(ir.clause()); - expr_ref inst_clause(m()); - get_instance_clause(ir, inst_clause); - - ptr_vector assumptions; - if(is_quantifier(inst_clause.get())) { - quantifier * q_clause = to_quantifier(inst_clause.get()); - bool simplified = simplify_clause(q_clause, inst_clause, assumptions); - SASSERT(simplified || assumptions.empty()); - } - replace_by_root_clauses(assumptions); - - if(!m_root_clause_map.contains(inst_clause)) { - m_root_clause_map.insert(inst_clause, root_clause); - get_context().push_trail(insert_obj_map(m_root_clause_map, inst_clause)); - } - add_clause_to_smt(inst_clause, root_clause, assumptions); - } - }; - - - ///////////////// - // instantiator - // - - class instantiator { - private: - typedef quantifier clause_type; - typedef ptr_vector clause_vector; - typedef obj_map matching_sets; - - ast_manager& m; - theory_instgen_impl& m_parent; - fo_clause_internalizer& m_internalizer; - inst_gen_unif_index m_unif_index; - matching_sets m_matching; - unifier m_unifier; //used in the unify method, but we don't want to recreate over and over - - class var_rename_rewriter_cfg : public default_rewriter_cfg { - ast_manager& m; - u_map m_index_rename; - public: - var_rename_rewriter_cfg(ast_manager& m) : m(m) {} - - bool get_subst(expr * s, expr * & t, proof * & t_pr) { - if (is_var(s)) { - unsigned idx = to_var(s)->get_idx(); - unsigned new_idx = 0; - if (!m_index_rename.find(idx, new_idx)) { - new_idx = m_index_rename.size(); - m_index_rename.insert(idx, new_idx); - } - t = m.mk_var(new_idx, to_var(s)->get_sort()); - return true; - } - else { - return false; - } - } - }; - - static void extract_substitution(substitution& s, quantifier * q, unsigned subst_var_cnt, bool is_first_bank, expr_ref_vector& tgt) { - // unsigned var_increment = is_first_bank ? 0 : subst_var_cnt; - unsigned var_offset = is_first_bank ? 0 : 1; - - unsigned deltas[2] = {0, subst_var_cnt}; - ast_manager& m = s.get_manager(); - unsigned var_cnt = q->get_num_decls(); - var_rename_rewriter_cfg r_cfg(m); - rewriter_tpl rwr(m, false, r_cfg); - for(unsigned i=0; iget_decl_sort(i); - unsigned var_idx = var_cnt-1-i; - var_ref v(m.mk_var(var_idx, var_sort), m); - expr_ref tmp(m), subst_result(m); - s.apply(2, deltas, expr_offset(v.get(), var_offset), tmp); - rwr(tmp, subst_result); - tgt.push_back(subst_result); - } - } - - - // just to be sure there's not misunderstanding with the caller, we require the res to be empty:) - void get_literal_occurrences(app * lit, clause_vector& res) { - SASSERT(res.empty()); - quantifier_ref_vector * occurrences = m_internalizer.find_occurs(lit); - if(occurrences) { - res.append(occurrences->size(), occurrences->c_ptr()); - } - } - - /** - check substitution wrt dismatching constraints of clause - (variable offset is to deal with how variable banks are shifted on each - other in the substitution) - */ - bool is_allowed_instantiation(clause_type * clause, const inst& subst) { - matching_set * ms; - return !m_matching.find(clause, ms) || !ms->has_instance(subst); - } - - class new_ms : public trail { - matching_sets& m_ms; - matching_set* m_s; - quantifier* m_q; - public: - new_ms(matching_sets& m, matching_set* s, quantifier* q): m_ms(m), m_s(s), m_q(q) {} - virtual void undo(smt::context& ctx) { dealloc(m_s); m_ms.remove(m_q); } - }; - - // add instantiating substitution among the dismatching constraints - void record_instantiation(instantiation_result const& inst) { - quantifier * cl = inst.clause(); - matching_set * ms; - if(!m_matching.find(cl, ms)) { - ms = alloc(matching_set, m); - m_matching.insert(cl, ms); - get_context().push_trail(new_ms(m_matching, ms, cl)); - } - ms->insert(inst.subst()); - get_context().push_trail(matching_set::insert_inst(*ms)); - } - - void get_result_from_subst(clause_type * clause, const inst& subst, instantiation_result& res) { - res.init(clause, subst); - record_instantiation(res); - } - - void display_vector(expr_ref_vector const& v, std::ostream& out) { - for (unsigned i = 0; i < v.size(); ++i) { - out << PP(v[i], m) << " "; - } - out << "\n"; - } - - - void add_lit(literal lit) { - ptr_vector fo_lits; - m_internalizer.get_literal_meanings(lit, fo_lits); - expr_ref e(m); - get_context().literal2expr(lit, e); - if (is_ground(e.get())) { - fo_lits.push_back(to_app(e)); - } - for (unsigned i = 0; i < fo_lits.size(); ++i) { - app * fol = fo_lits[i]; - m_unif_index.insert_literal(fol); - } - } - - void mk_folit_neg(app * lit, app_ref& res) { - expr * arg; - if(m.is_not(lit, arg)) { - SASSERT(is_app(arg)); - res = to_app(arg); - } - else { - res = m.mk_not(lit); - } - } - - ast_manager& get_manager() const; - context& get_context() const; - - public: - instantiator(fo_clause_internalizer& internalizer, theory_instgen_impl& parent, ast_manager& m) : - m(m), - m_parent(parent), - m_internalizer(internalizer), - m_unif_index(m), - m_unifier(m) {} - - ~instantiator() { - reset_dealloc_values(m_matching); - } - - bool unif_is_empty() const { - return m_unif_index.empty(); - } - - void display(std::ostream& out) { - m_unif_index.display(out); - } - - void add_true_lit(literal lit) { - add_lit(lit); - } - - void push() { - m_unif_index.push(); - } - - void pop() { - m_unif_index.pop(); - } - - void reserve_num_vars(unsigned num_vars) { - m_unif_index.reserve_num_vars(num_vars); - } - - bool instantiate_clauses( - app * lit1, clause_type * clause1, - app * lit2, clause_type * clause2, - instantiation_result_vector& result); - - bool instantiate_clause( - app * lit1, clause_type * clause1, app * lit2, - instantiation_result_vector& result); - - void do_instantiating(literal lit, instantiation_result_vector& res) { - ptr_vector folits; - clause_vector folit_clauses; // clauses in which the first-order literal appears - app_ref_vector unifs(m); // unifying complementary literals - clause_vector comp_clauses; // clauses in which the unifying complementary literal appears - - m_internalizer.get_literal_meanings(lit, folits); - - while(!folits.empty()) { - app * folit = folits.back(); - - folits.pop_back(); - folit_clauses.reset(); - get_literal_occurrences(folit, folit_clauses); - SASSERT(!folit_clauses.empty()); //if we have a literal it should be in some clause (or not?) - - SASSERT(folit->get_ref_count() > 0); - app_ref complementary(m); - mk_folit_neg(folit, complementary); - m_unif_index.get_unifications(complementary, unifs); - - while(!unifs.empty()) { - app * comp_lit = unifs.back(); - unifs.pop_back(); - SASSERT(comp_lit->get_ref_count() > 0); - comp_clauses.reset(); - get_literal_occurrences(comp_lit, comp_clauses); - TRACE("theory_instgen", tout << "Literal " << lit << " meaning: " << PP(folit, m) << "\n"; - tout << "Unifies with: " << PP(comp_lit, m) << "\n";); - // - //if a literal is in the unification index (i.e. was assigned true sometime before), - //it should be in some clause or it is a ground literal. - - //iterate through all clauses that contain the query literal - // - clause_vector::const_iterator fc_end = folit_clauses.end(); - for(clause_vector::const_iterator fc_it = folit_clauses.begin(); fc_it!=fc_end; ++fc_it) { - - //iterate through all clauses that contain the complementary unifying literal - clause_vector::const_iterator end = comp_clauses.end(); - for(clause_vector::const_iterator it = comp_clauses.begin(); it!=end; ++it) { - - instantiate_clauses(folit, *fc_it, comp_lit, *it, res); - } - if (comp_clauses.empty()) { - instantiate_clause(folit, *fc_it, comp_lit, res); - } - } - } - complementary.reset(); - } - } - }; - - - /////////////////////////// - // theory_instgen_impl - // - - class theory_instgen_impl : public theory_instgen { - - friend class instantiator; - friend class fo_clause_internalizer; - - struct stats { - unsigned m_num_axioms; - unsigned m_num_subsumptions; - unsigned m_num_pruned; - stats() { memset(this, 0, sizeof(*this)); } - }; - - ast_manager& m_manager; - smt_params& m_params; - fo_clause_internalizer m_internalizer; - instantiator m_instantiator; - clause_subsumption m_subsumer; - stats m_stats; - - final_check_status instantiate_all_possible() { - // traverse instantiation queue and create initial instances. - - ast_manager& m = get_manager(); - context& ctx = get_context(); - instantiation_result_vector generated_clauses; - unsigned bv_cnt = ctx.get_num_bool_vars(); - - m_instantiator.push(); - - TRACE("theory_instgen", - tout << "Literals:\n"; - for (unsigned v = 0; v < bv_cnt; ++v) { - if (l_undef == ctx.get_assignment(v)) continue; - literal lit(v, ctx.get_assignment(v) == l_false); - expr_ref e(m); - ctx.literal2expr(lit, e); - tout << PP(e.get(),m) << "\n"; - } - ); - - SASSERT(m_instantiator.unif_is_empty()); - - for(unsigned bvi=0; bvi < bv_cnt; ++bvi) { - lbool asgn_val = ctx.get_assignment(bvi); - if(asgn_val==l_undef) { - continue; - } - literal lit(bvi, asgn_val==l_false); - m_instantiator.add_true_lit(lit); - m_instantiator.do_instantiating(lit, generated_clauses); - } - - bool change = !generated_clauses.empty(); - - while(!generated_clauses.empty()) { - m_internalizer.add_new_instance(generated_clauses.back()); - generated_clauses.pop_back(); - } - - m_instantiator.pop(); - - return change?FC_CONTINUE:FC_DONE; - } - - - public: - theory_instgen_impl(ast_manager& m, smt_params& p): - theory_instgen(m.get_family_id("inst_gen")), - m_manager(m), - m_params(p), - m_internalizer(*this), - m_instantiator(m_internalizer, *this, m), - m_subsumer(m, p) - {} - - ast_manager& m() { return m_manager; } - - virtual void internalize_quantifier(quantifier* q) { - TRACE("theory_instgen", tout << PP(q, m()) << "\n";); - context& ctx = get_context(); - if (!ctx.b_internalized(q)) { - bool_var v = ctx.mk_bool_var(q); - ctx.set_var_theory(v, get_id()); - m_instantiator.reserve_num_vars(q->get_num_decls()); - } - } - - virtual bool internalize_atom(app * atom, bool gate_ctx) { - UNREACHABLE(); - return false; - } - - virtual bool internalize_term(app * term) { - UNREACHABLE(); - return false; - } - - virtual void new_eq_eh(theory_var v1, theory_var v2) {} - - virtual void new_diseq_eh(theory_var v1, theory_var v2) {} - - virtual theory * mk_fresh(context * new_ctx) { - return alloc(theory_instgen_impl, get_manager(), m_params); - } - - virtual void assign_eh(bool_var v, bool is_true) { - context& ctx = get_context(); - expr* e = ctx.bool_var2expr(v); - if (is_quantifier(e)) { - if (is_true) { - m_internalizer.add_initial_clause(to_quantifier(e)); - } - else { - // TBD: handle existential force later. - } - } - } - - virtual final_check_status final_check_eh() { - TRACE("theory_instgen", tout << "Final check\n";); - return instantiate_all_possible(); - } - - virtual void init_model(smt::model_generator & m) { } - - virtual smt::model_value_proc * mk_value(smt::enode * n, smt::model_generator & m) { - UNREACHABLE(); - return 0; - } - - virtual void relevant_eh(app * n) { } - - virtual void push_scope_eh() { - m_subsumer.push(); - } - - virtual void pop_scope_eh(unsigned num_scopes) { - m_subsumer.pop(num_scopes); - } - - virtual void collect_statistics(::statistics & st) const { - st.update("inst axiom", m_stats.m_num_axioms); - st.update("inst subsump", m_stats.m_num_subsumptions); - } - - void inc_subsumptions() { - ++m_stats.m_num_subsumptions; - } - - void inc_axioms() { - ++m_stats.m_num_axioms; - } - - void inc_pruned() { - ++m_stats.m_num_pruned; - } - - }; - - theory_instgen* mk_theory_instgen(ast_manager& m, smt_params& p) { - return alloc(theory_instgen_impl, m, p); - } - - ast_manager& instantiator::get_manager() const { - return m_parent.m(); - } - - smt::context& instantiator::get_context() const { - return m_parent.get_context(); - } - - bool instantiator::instantiate_clauses( - app * lit1, clause_type * clause1, - app * lit2, clause_type * clause2, - instantiation_result_vector& result) { - TRACE("theory_instgen", tout << PP(lit1, m) << " " << PP(clause1, m) << "\n"; - tout << PP(lit2, m) << " " << PP(clause2, m) << "\n";); - substitution subst(m); - unsigned var_cnt = std::max(clause1->get_num_decls(), clause2->get_num_decls()); - subst.reserve(2, var_cnt); - //don't trust there offset values too much, it's just what i expect the substitution does:) - app_ref complementary(m); - mk_folit_neg(lit1, complementary); - TRUSTME(m_unifier(complementary, lit2, subst)); - - inst subst1(m); - extract_substitution(subst, clause1, var_cnt, true, subst1); - inst subst2(m); - extract_substitution(subst, clause2, var_cnt, false, subst2); - - bool s1_identity = matching_set::is_identity(subst1); - bool s2_identity = matching_set::is_identity(subst2); - - if((!s1_identity && !is_allowed_instantiation(clause1, subst1)) || - (!s2_identity && !is_allowed_instantiation(clause2, subst2))) { - TRACE("theory_instgen", - tout << "Pruned instantiation\n"; - tout << PP(clause1, m) << "\n"; - display_vector(subst1, tout); - tout << PP(clause2, m) << "\n"; - display_vector(subst2, tout); - ); - m_parent.inc_pruned(); - return false; - } - - // - // both substitutions cannot be identity as then the two complementary - // literals would correspond to the same SAT solver variable - // - SASSERT(!s1_identity || !s2_identity); - - if(!s1_identity) { - instantiation_result res1(m); - get_result_from_subst(clause1, subst1, res1); - result.push_back(res1); - } - - if(!s2_identity) { - instantiation_result res2(m); - get_result_from_subst(clause2, subst2, res2); - result.push_back(res2); - } - return true; - } - - // literal lit2 is ground. It is not associated with a clause. - // literal lit1 is associatd with a non-ground clause. - bool instantiator::instantiate_clause( - app * lit1, clause_type * clause1, app * lit2, - instantiation_result_vector& result) { - TRACE("theory_instgen", tout << PP(lit1, m) << " " << PP(clause1, m) << "\n"; - tout << PP(lit2, m) << "\n";); - if (!is_ground(lit2)) { - // TBD: remove. Debug code. - std::cout << PP(lit1, m) << " " << PP(clause1, m) << "\n"; - std::cout << PP(lit2, m) << "\n"; - m_unif_index.display(std::cout); - } - SASSERT(is_ground(lit2)); - substitution subst(m); - unsigned var_cnt = clause1->get_num_decls(); - subst.reserve(2, var_cnt); - app_ref complementary(m); - mk_folit_neg(lit1, complementary); - - TRUSTME(m_unifier(complementary, lit2, subst)); - - inst subst1(m); - extract_substitution(subst, clause1, var_cnt, true, subst1); - - if(matching_set::is_identity(subst1) || - !is_allowed_instantiation(clause1, subst1)) { - TRACE("theory_instgen", - tout << "Pruned instantiation\n"; - tout << PP(clause1, m) << "\n"; - display_vector(subst1, tout); - ); - m_parent.inc_pruned(); - return false; - } - - instantiation_result res1(m); - get_result_from_subst(clause1, subst1, res1); - result.push_back(res1); - return true; - } - - - //-------------------------- - // - // fo_clause_internalizer - // - //-------------------------- - - smt::context& fo_clause_internalizer::get_context() const { - return m_parent.get_context(); - } - - ast_manager& fo_clause_internalizer::m() const { - return m_parent.m(); - } - - bool fo_clause_internalizer::simplify_clause(quantifier * clause, expr_ref& result, ptr_vector& assumptions) { - m_parent.m_subsumer.simplify(clause, result, assumptions); - bool change = clause!=result.get(); - if (change) { - m_parent.inc_subsumptions(); - } - return change; - } - - void fo_clause_internalizer::get_instance_clause(instantiation_result const& ir, expr_ref& res) { - expr * orig_cl = ir.clause()->get_expr(); - SASSERT(is_app(orig_cl)); - - expr_ref res_inner(m()); //the clause after substitution, we might still need to quantify it - m_subst(orig_cl, ir.subst().size(), ir.subst().c_ptr(), res_inner); - SASSERT(is_app(res_inner.get())); - - if(is_ground(res_inner.get())) { - res = res_inner; - return; //we made it ground! - } - - ptr_vector free_var_sorts; - svector quant_names; - get_free_vars(res_inner.get(), free_var_sorts); - unsigned free_var_cnt = free_var_sorts.size(); - for(unsigned i=0; i const& assumptions) { - SASSERT(!root_clause || root_clause->is_forall()); - SASSERT(is_quantifier(clause) || root_clause); - context& ctx = get_context(); - buffer lits; - ptr_buffer todo; - - bool is_q_clause = is_quantifier(clause); - quantifier * q_clause = is_q_clause ? to_quantifier(clause) : 0; - if (!root_clause) root_clause = q_clause; - - lits.push_back(~get_root_clause_control_literal(root_clause)); - - for(unsigned i=0; iget_expr()):clause); - - while (!todo.empty()) { - expr* e = todo.back(); - todo.pop_back(); - if (m().is_or(e)) { - todo.append(to_app(e)->get_num_args(), to_app(e)->get_args()); - } - else if (is_app(e)) { - lits.push_back(ground_fo_literal(to_app(e), q_clause)); - } - else { - SASSERT(is_var(e) || is_quantifier(e)); - UNREACHABLE(); - //by skipping part of the disjunction we may get unsound - } - } - TRACE("theory_instgen", - tout << "Axiom: \n"; - for (unsigned i = 0; i < lits.size(); ++i) { - expr_ref e(m()); - get_context().literal2expr(lits[i], e); - tout << PP(e.get(), m()) << "\n"; - } - ); - m_parent.inc_axioms(); - ctx.mk_th_axiom(m_parent.get_id(), lits.size(), lits.c_ptr()); - } - - -}; diff --git a/src/smt/theory_instgen.h b/src/smt/theory_instgen.h deleted file mode 100644 index c32636e9b..000000000 --- a/src/smt/theory_instgen.h +++ /dev/null @@ -1,45 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - theory_instgen.h - -Abstract: - - InstGen (iProver) style theory solver. - It provides an instantiation based engine - based on InstGen methods together with - unit propagation. - - -Author: - - Krystof Hoder (t-khoder) - Nikolaj Bjorner (nbjorner) 2011-10-6 - -Revision History: - ---*/ -#ifndef _THEORY_INST_GEN_H_ -#define _THEORY_INST_GEN_H_ - -#include "smt_theory.h" -#include "smt_params.h" - -namespace smt { - - class theory_instgen : public theory { - public: - theory_instgen(family_id fid) : theory(fid) {} - virtual ~theory_instgen() {} - virtual void internalize_quantifier(quantifier* q) = 0; - virtual char const * get_name() const { return "instgen"; } - }; - - theory_instgen* mk_theory_instgen(ast_manager& m, smt_params& p); - -}; - -#endif /* _THEORY_INST_GEN_H_ */ - diff --git a/src/smt/theory_seq_empty.h b/src/smt/theory_seq_empty.h index ef3924603..d5468df28 100644 --- a/src/smt/theory_seq_empty.h +++ b/src/smt/theory_seq_empty.h @@ -32,7 +32,7 @@ namespace smt { virtual theory* mk_fresh(context*) { return alloc(theory_seq_empty, get_manager()); } virtual char const * get_name() const { return "seq-empty"; } public: - theory_seq_empty(ast_manager& m):theory(m.get_family_id("seq")), m_used(false) {} + theory_seq_empty(ast_manager& m):theory(m.mk_family_id("seq")), m_used(false) {} }; }; diff --git a/src/smt/user_plugin/user_smt_theory.cpp b/src/smt/user_plugin/user_smt_theory.cpp index ab4cc62c4..a2d1e4f37 100644 --- a/src/smt/user_plugin/user_smt_theory.cpp +++ b/src/smt/user_plugin/user_smt_theory.cpp @@ -646,7 +646,7 @@ namespace smt { context & ctx = _s.get_context(); // HACK symbol _name(name); ast_manager & m = ctx.get_manager(); - family_id fid = m.get_family_id(_name); + family_id fid = m.mk_family_id(_name); user_decl_plugin * dp = alloc(user_decl_plugin); m.register_plugin(fid, dp); simplifier & s = ctx.get_simplifier(); diff --git a/src/solver/combined_solver.cpp b/src/solver/combined_solver.cpp new file mode 100644 index 000000000..a98e5be49 --- /dev/null +++ b/src/solver/combined_solver.cpp @@ -0,0 +1,307 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + combined_solver.cpp + +Abstract: + + Implements the solver API by combining two solvers. + + This is a replacement for the strategic_solver class. + +Author: + + Leonardo (leonardo) 2012-12-11 + +Notes: + +--*/ +#include"solver.h" +#include"scoped_timer.h" +#include"combined_solver_params.hpp" +#define PS_VB_LVL 15 + +/** + \brief Implementation of the solver API that combines two given solvers. + + The combined solver has two modes: + - non-incremental + - incremental + In non-incremental mode, the first solver is used. + In incremental mode, the second one is used. + + A timeout for the second solver can be specified. + If the timeout is reached, then the first solver is executed. + + The object switches to incremental when: + - push is used + - assertions are peformed after a check_sat + - parameter ignore_solver1==false +*/ +class combined_solver : public solver { +public: + // Behavior when the incremental solver returns unknown. + enum inc_unknown_behavior { + IUB_RETURN_UNDEF, // just return unknown + IUB_USE_TACTIC_IF_QF, // invoke tactic if problem is quantifier free + IUB_USE_TACTIC // invoke tactic + }; + +private: + bool m_inc_mode; + bool m_check_sat_executed; + bool m_use_solver1_results; + ref m_solver1; + ref m_solver2; + // We delay sending assertions to solver 2 + // This is relevant for big benchmarks that are meant to be solved + // by a non-incremental solver. + bool m_solver2_initialized; + + bool m_ignore_solver1; + inc_unknown_behavior m_inc_unknown_behavior; + unsigned m_inc_timeout; + + void init_solver2_assertions() { + if (m_solver2_initialized) + return; + unsigned sz = m_solver1->get_num_assertions(); + for (unsigned i = 0; i < sz; i++) { + m_solver2->assert_expr(m_solver1->get_assertion(i)); + } + m_solver2_initialized = true; + } + + void switch_inc_mode() { + m_inc_mode = true; + init_solver2_assertions(); + } + + struct aux_timeout_eh : public event_handler { + solver * m_solver; + volatile bool m_canceled; + aux_timeout_eh(solver * s):m_solver(s), m_canceled(false) {} + virtual void operator()() { + m_solver->cancel(); + m_canceled = true; + } + }; + + void updt_local_params(params_ref const & _p) { + combined_solver_params p(_p); + m_inc_timeout = p.solver2_timeout(); + m_ignore_solver1 = p.ignore_solver1(); + m_inc_unknown_behavior = static_cast(p.solver2_unknown()); + } + + bool has_quantifiers() const { + unsigned sz = get_num_assertions(); + for (unsigned i = 0; i < sz; i++) { + if (::has_quantifiers(get_assertion(i))) + return true; + } + return false; + } + + bool use_solver1_when_undef() const { + switch (m_inc_unknown_behavior) { + case IUB_RETURN_UNDEF: return false; + case IUB_USE_TACTIC_IF_QF: return !has_quantifiers(); + case IUB_USE_TACTIC: return true; + default: + UNREACHABLE(); + return false; + } + } + +public: + combined_solver(solver * s1, solver * s2, params_ref const & p) { + m_solver1 = s1; + m_solver2 = s2; + updt_local_params(p); + m_solver2_initialized = false; + m_inc_mode = false; + m_check_sat_executed = false; + m_use_solver1_results = true; + } + + virtual void updt_params(params_ref const & p) { + m_solver1->updt_params(p); + m_solver2->updt_params(p); + updt_local_params(p); + } + + virtual void collect_param_descrs(param_descrs & r) { + m_solver1->collect_param_descrs(r); + m_solver2->collect_param_descrs(r); + combined_solver_params::collect_param_descrs(r); + } + + virtual void set_produce_models(bool f) { + m_solver1->set_produce_models(f); + m_solver2->set_produce_models(f); + } + + virtual void assert_expr(expr * t) { + if (m_check_sat_executed) + switch_inc_mode(); + m_solver1->assert_expr(t); + if (m_solver2_initialized) + m_solver2->assert_expr(t); + } + + virtual void assert_expr(expr * t, expr * a) { + if (m_check_sat_executed) + switch_inc_mode(); + m_solver1->assert_expr(t, a); + init_solver2_assertions(); + m_solver2->assert_expr(t, a); + } + + virtual void push() { + switch_inc_mode(); + m_solver1->push(); + m_solver2->push(); + } + + virtual void pop(unsigned n) { + switch_inc_mode(); + m_solver1->pop(n); + m_solver2->pop(n); + } + + virtual unsigned get_scope_level() const { + return m_solver1->get_scope_level(); + } + + virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) { + m_check_sat_executed = true; + + if (num_assumptions > 0 || // assumptions were provided + m_ignore_solver1) { + // must use incremental solver + switch_inc_mode(); + m_use_solver1_results = false; + return m_solver2->check_sat(num_assumptions, assumptions); + } + + if (m_inc_mode) { + if (m_inc_timeout == UINT_MAX) { + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (without a timeout)\")\n";); + lbool r = m_solver2->check_sat(0, 0); + if (r != l_undef || !use_solver1_when_undef()) { + m_use_solver1_results = false; + return r; + } + } + else { + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (with timeout)\")\n";); + aux_timeout_eh eh(m_solver2.get()); + lbool r; + { + scoped_timer timer(m_inc_timeout, &eh); + r = m_solver2->check_sat(0, 0); + } + if ((r != l_undef || !use_solver1_when_undef()) && !eh.m_canceled) { + m_use_solver1_results = false; + return r; + } + } + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"solver 2 failed, trying solver1\")\n";); + } + + IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 1\")\n";); + m_use_solver1_results = true; + return m_solver1->check_sat(0, 0); + } + + virtual void set_cancel(bool f) { + m_solver1->set_cancel(f); + m_solver2->set_cancel(f); + } + + virtual void set_progress_callback(progress_callback * callback) { + m_solver1->set_progress_callback(callback); + m_solver2->set_progress_callback(callback); + } + + virtual unsigned get_num_assertions() const { + return m_solver1->get_num_assertions(); + } + + virtual expr * get_assertion(unsigned idx) const { + return m_solver1->get_assertion(idx); + } + + virtual void display(std::ostream & out) const { + m_solver1->display(out); + } + + virtual void collect_statistics(statistics & st) const { + if (m_use_solver1_results) + m_solver1->collect_statistics(st); + else + m_solver2->collect_statistics(st); + } + + virtual void get_unsat_core(ptr_vector & r) { + if (m_use_solver1_results) + m_solver1->get_unsat_core(r); + else + m_solver2->get_unsat_core(r); + } + + virtual void get_model(model_ref & m) { + if (m_use_solver1_results) + m_solver1->get_model(m); + else + m_solver2->get_model(m); + } + + virtual proof * get_proof() { + if (m_use_solver1_results) + return m_solver1->get_proof(); + else + return m_solver2->get_proof(); + } + + virtual std::string reason_unknown() const { + if (m_use_solver1_results) + return m_solver1->reason_unknown(); + else + return m_solver2->reason_unknown(); + } + + virtual void get_labels(svector & r) { + if (m_use_solver1_results) + return m_solver1->get_labels(r); + else + return m_solver2->get_labels(r); + } + +}; + + +solver * mk_combined_solver(solver * s1, solver * s2, params_ref const & p) { + return alloc(combined_solver, s1, s2, p); +} + +class combined_solver_factory : public solver_factory { + scoped_ptr m_f1; + scoped_ptr m_f2; +public: + combined_solver_factory(solver_factory * f1, solver_factory * f2):m_f1(f1), m_f2(f2) {} + virtual ~combined_solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + return mk_combined_solver((*m_f1)(m, p, proofs_enabled, models_enabled, unsat_core_enabled, logic), + (*m_f2)(m, p, proofs_enabled, models_enabled, unsat_core_enabled, logic), + p); + } +}; + +solver_factory * mk_combined_solver_factory(solver_factory * f1, solver_factory * f2) { + return alloc(combined_solver_factory, f1, f2); +} diff --git a/src/solver/combined_solver.h b/src/solver/combined_solver.h new file mode 100644 index 000000000..2ccace7f0 --- /dev/null +++ b/src/solver/combined_solver.h @@ -0,0 +1,32 @@ +/*++ +Copyright (c) 2012 Microsoft Corporation + +Module Name: + + combined_solver.cpp + +Abstract: + + Implements the solver API by combining two solvers. + + This is a replacement for the strategic_solver class. + +Author: + + Leonardo (leonardo) 2012-12-11 + +Notes: + +--*/ +#ifndef _COMBINED_SOLVER_H_ +#define _COMBINED_SOLVER_H_ + +#include"params.h" + +class solver; +class solver_factory; + +solver * mk_combined_solver(solver * s1, solver * s2, params_ref const & p); +solver_factory * mk_combined_solver_factory(solver_factory * f1, solver_factory * f2); + +#endif diff --git a/src/solver/combined_solver_params.pyg b/src/solver/combined_solver_params.pyg new file mode 100644 index 000000000..7e1635c16 --- /dev/null +++ b/src/solver/combined_solver_params.pyg @@ -0,0 +1,9 @@ +def_module_params('combined_solver', + description='combines two solvers: non-incremental (solver1) and incremental (solver2)', + export=True, + params=(('solver2_timeout', UINT, UINT_MAX, "fallback to solver 1 after timeout even when in incremental model"), + ('ignore_solver1', BOOL, False, "if true, solver 2 is always used"), + ('solver2_unknown', UINT, 1, "what should be done when solver 2 returns unknown: 0 - just return unknown, 1 - execute solver 1 if quantifier free problem, 2 - execute solver 1") + )) + + diff --git a/src/solver/solver.h b/src/solver/solver.h index 5cd3da52b..e047bace1 100644 --- a/src/solver/solver.h +++ b/src/solver/solver.h @@ -23,6 +23,14 @@ Notes: #include"progress_callback.h" #include"params.h" +class solver; + +class solver_factory { +public: + virtual ~solver_factory() {} + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) = 0; +}; + /** \brief Abstract interface for making solvers available in the Z3 API and front-ends such as SMT 2.0 and (legacy) SMT 1.0. @@ -34,7 +42,6 @@ Notes: - statistics - results based on check_sat_result API - interruption (set_cancel) - - resets */ class solver : public check_sat_result { public: @@ -50,12 +57,6 @@ public: */ virtual void collect_param_descrs(param_descrs & r) {} - /** - \brief Enable/Disable proof production for this solver object. - - It is invoked before init(m, logic). - */ - virtual void set_produce_proofs(bool f) {} /** \brief Enable/Disable model generation for this solver object. @@ -63,23 +64,7 @@ public: The user may optionally invoke it after init(m, logic). */ virtual void set_produce_models(bool f) {} - /** - \brief Enable/Disable unsat core generation for this solver object. - - It is invoked before init(m, logic). - */ - virtual void set_produce_unsat_cores(bool f) {} - /** - \brief Initialize the solver object with the given ast_manager and logic. - */ - virtual void init(ast_manager & m, symbol const & logic) = 0; - - /** - \brief Reset the solver internal state. All assertions should be removed. - */ - virtual void reset() = 0; - /** \brief Add a new formula to the assertion stack. */ diff --git a/src/solver/solver_na2as.cpp b/src/solver/solver_na2as.cpp index e71a9873b..9889b5872 100644 --- a/src/solver/solver_na2as.cpp +++ b/src/solver/solver_na2as.cpp @@ -22,8 +22,8 @@ Notes: #include"solver_na2as.h" #include"ast_smt2_pp.h" -solver_na2as::solver_na2as() { - m_manager = 0; +solver_na2as::solver_na2as(ast_manager & m): + m_manager(m) { } solver_na2as::~solver_na2as() { @@ -35,23 +35,16 @@ void solver_na2as::assert_expr(expr * t, expr * a) { assert_expr(t); } else { - SASSERT(m_manager != 0); SASSERT(is_uninterp_const(a)); - SASSERT(m_manager->is_bool(a)); - TRACE("solver_na2as", tout << "asserting\n" << mk_ismt2_pp(t, *m_manager) << "\n" << mk_ismt2_pp(a, *m_manager) << "\n";); - m_manager->inc_ref(a); + SASSERT(m_manager.is_bool(a)); + TRACE("solver_na2as", tout << "asserting\n" << mk_ismt2_pp(t, m_manager) << "\n" << mk_ismt2_pp(a, m_manager) << "\n";); + m_manager.inc_ref(a); m_assumptions.push_back(a); - expr_ref new_t(*m_manager); - new_t = m_manager->mk_implies(a, t); + expr_ref new_t(m_manager); + new_t = m_manager.mk_implies(a, t); assert_expr(new_t); } } - -void solver_na2as::init(ast_manager & m, symbol const & logic) { - SASSERT(m_assumptions.empty()); - m_manager = &m; - init_core(m, logic); -} struct append_assumptions { ptr_vector & m_assumptions; @@ -89,9 +82,9 @@ void solver_na2as::pop(unsigned n) { } void solver_na2as::restore_assumptions(unsigned old_sz) { - SASSERT(old_sz == 0 || m_manager != 0); + SASSERT(old_sz == 0); for (unsigned i = old_sz; i < m_assumptions.size(); i++) { - m_manager->dec_ref(m_assumptions[i]); + m_manager.dec_ref(m_assumptions[i]); } m_assumptions.shrink(old_sz); } @@ -100,7 +93,3 @@ unsigned solver_na2as::get_scope_level() const { return m_scopes.size(); } -void solver_na2as::reset() { - reset_core(); - restore_assumptions(0); -} diff --git a/src/solver/solver_na2as.h b/src/solver/solver_na2as.h index eb12479fc..15750344a 100644 --- a/src/solver/solver_na2as.h +++ b/src/solver/solver_na2as.h @@ -25,30 +25,26 @@ Notes: #include"solver.h" class solver_na2as : public solver { - ast_manager * m_manager; + ast_manager & m_manager; ptr_vector m_assumptions; unsigned_vector m_scopes; void restore_assumptions(unsigned old_sz); public: - solver_na2as(); + solver_na2as(ast_manager & m); virtual ~solver_na2as(); virtual void assert_expr(expr * t, expr * a); virtual void assert_expr(expr * t) = 0; // Subclasses of solver_na2as should redefine the following *_core methods instead of these ones. - virtual void init(ast_manager & m, symbol const & logic); virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions); virtual void push(); virtual void pop(unsigned n); virtual unsigned get_scope_level() const; - virtual void reset(); protected: - virtual void init_core(ast_manager & m, symbol const & logic) = 0; virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions) = 0; virtual void push_core() = 0; virtual void pop_core(unsigned n) = 0; - virtual void reset_core() = 0; }; diff --git a/src/solver/strategic_solver.cpp b/src/solver/strategic_solver.cpp deleted file mode 100644 index 40d77066e..000000000 --- a/src/solver/strategic_solver.cpp +++ /dev/null @@ -1,533 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - strategic_solver.h - -Abstract: - - Strategies -> Solver - -Author: - - Leonardo (leonardo) 2011-05-19 - -Notes: - ---*/ -#include"strategic_solver.h" -#include"scoped_timer.h" -#include"ast_smt2_pp.h" - -// minimum verbosity level for portfolio verbose messages -#define PS_VB_LVL 15 - - -strategic_solver::ctx::ctx(ast_manager & m): - m_assertions(m), - m_assertion_names(m) { - } - -strategic_solver::strategic_solver(): - m_manager(0), - m_force_tactic(false), - m_inc_mode(false), - m_check_sat_executed(false), - m_inc_solver(0), - m_inc_solver_timeout(UINT_MAX), - m_inc_unknown_behavior(IUB_USE_TACTIC_IF_QF), - m_default_fct(0), - m_curr_tactic(0), - m_proof(0), - m_core(0), - m_callback(0) { - m_use_inc_solver_results = false; - DEBUG_CODE(m_num_scopes = 0;); - m_produce_proofs = false; - m_produce_models = false; - m_produce_unsat_cores = false; - m_auto_config = true; -} - -strategic_solver::~strategic_solver() { - SASSERT(!m_curr_tactic); - dictionary::iterator it = m_logic2fct.begin(); - dictionary::iterator end = m_logic2fct.end(); - for (; it != end; ++it) { - dealloc(it->m_value); - } - if (m_proof) - m().dec_ref(m_proof); - if (m_core) - m().dec_ref(m_core); -} - -bool strategic_solver::has_quantifiers() const { - unsigned sz = get_num_assertions(); - for (unsigned i = 0; i < sz; i++) { - if (::has_quantifiers(get_assertion(i))) - return true; - } - return false; -} - -/** - \brief Return true if a tactic should be used when the incremental solver returns unknown. -*/ -bool strategic_solver::use_tactic_when_undef() const { - switch (m_inc_unknown_behavior) { - case IUB_RETURN_UNDEF: return false; - case IUB_USE_TACTIC_IF_QF: return !has_quantifiers(); - case IUB_USE_TACTIC: return true; - default: - UNREACHABLE(); - return false; - } -} - -void strategic_solver::set_inc_solver(solver * s) { - SASSERT(m_inc_solver == 0); - SASSERT(m_num_scopes == 0); - m_inc_solver = s; - if (m_callback) - m_inc_solver->set_progress_callback(m_callback); -} - -void strategic_solver::updt_params(params_ref const & p) { - if (m_inc_solver) - m_inc_solver->updt_params(p); - m_params = p; - m_auto_config = p.get_bool("auto_config", true); -} - -void strategic_solver::collect_param_descrs(param_descrs & r) { - if (m_inc_solver) - m_inc_solver->collect_param_descrs(r); -} - -/** - \brief Set a timeout for each check_sat query that is processed by the inc_solver. - timeout == UINT_MAX means infinite - After the timeout a strategy is used. -*/ -void strategic_solver::set_inc_solver_timeout(unsigned timeout) { - m_inc_solver_timeout = timeout; -} - -/** - \brief Set the default tactic factory. - It is used if there is no tactic for a given logic. -*/ -void strategic_solver::set_default_tactic(tactic_factory * fct) { - m_default_fct = fct; -} - -/** - \brief Set a tactic factory for a given logic. -*/ -void strategic_solver::set_tactic_for(symbol const & logic, tactic_factory * fct) { - tactic_factory * old_fct; - if (m_logic2fct.find(logic, old_fct)) { - dealloc(old_fct); - } - m_logic2fct.insert(logic, fct); -} - -void strategic_solver::init(ast_manager & m, symbol const & logic) { - m_manager = &m; - m_logic = logic; - if (m_inc_mode) { - SASSERT(m_inc_solver); - m_inc_solver->init(m, logic); - } - m_ctx = alloc(ctx, m); - TRACE("strategic_solver", tout << "strategic_solver was initialized.\n";); -} - -unsigned strategic_solver::get_num_assertions() const { - if (m_ctx == 0) - return 0; - return m_ctx->m_assertions.size(); -} - -expr * strategic_solver::get_assertion(unsigned idx) const { - SASSERT(m_ctx); - return m_ctx->m_assertions.get(idx); -} - -expr * strategic_solver::get_assertion_name(unsigned idx) const { - SASSERT(m_ctx); - SASSERT(m_produce_unsat_cores); - return m_ctx->m_assertion_names.get(idx); -} - -void strategic_solver::set_produce_proofs(bool f) { - m_produce_proofs = f; - // do not need to propagate to inc_solver since flag cannot be changed after initialization -} - -void strategic_solver::set_produce_models(bool f) { - m_produce_models = f; - if (m_inc_solver) - m_inc_solver->set_produce_models(f); -} - -void strategic_solver::set_produce_unsat_cores(bool f) { - m_produce_unsat_cores = f; - // do not need to propagate to inc_solver since flag cannot be changed after initialization -} - -// delayed inc solver initialization -void strategic_solver::init_inc_solver() { - if (m_inc_mode) - return; // solver was already initialized - if (!m_inc_solver) - return; // inc solver was not installed - m_inc_mode = true; - m_inc_solver->set_produce_proofs(m_produce_proofs); - m_inc_solver->set_produce_models(m_produce_models); - m_inc_solver->set_produce_unsat_cores(m_produce_unsat_cores); - m_inc_solver->init(m(), m_logic); - unsigned sz = get_num_assertions(); - if (m_produce_unsat_cores) { - SASSERT(m_ctx->m_assertions.size() == m_ctx->m_assertion_names.size()); - for (unsigned i = 0; i < sz; i++) { - m_inc_solver->assert_expr(get_assertion(i), get_assertion_name(i)); - } - } - else { - for (unsigned i = 0; i < sz; i++) { - m_inc_solver->assert_expr(get_assertion(i)); - } - } -} - -void strategic_solver::collect_statistics(statistics & st) const { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->collect_statistics(st); - } - else { - if (m_curr_tactic) - m_curr_tactic->collect_statistics(st); // m_curr_tactic is still being executed. - else - st.copy(m_stats); - } -} - -void strategic_solver::reset() { - m_ctx = 0; - m_logic = symbol::null; - m_inc_mode = false; - m_check_sat_executed = false; - if (m_inc_solver) - m_inc_solver->reset(); - SASSERT(!m_curr_tactic); - m_use_inc_solver_results = false; - reset_results(); -} - -void strategic_solver::reset_results() { - m_use_inc_solver_results = false; - m_model = 0; - if (m_proof) { - m().dec_ref(m_proof); - m_proof = 0; - } - if (m_core) { - m().dec_ref(m_core); - m_core = 0; - } - m_reason_unknown.clear(); - m_stats.reset(); -} - -void strategic_solver::assert_expr(expr * t) { - if (m_check_sat_executed && !m_inc_mode) { - // a check sat was already executed --> switch to incremental mode - init_inc_solver(); - SASSERT(m_inc_solver == 0 || m_inc_mode); - } - if (m_inc_mode) { - SASSERT(m_inc_solver); - m_inc_solver->assert_expr(t); - } - SASSERT(m_ctx); - m_ctx->m_assertions.push_back(t); - if (m_produce_unsat_cores) - m_ctx->m_assertion_names.push_back(0); -} - -void strategic_solver::assert_expr(expr * t, expr * a) { - if (m_check_sat_executed && !m_inc_mode) { - // a check sat was already executed --> switch to incremental mode - init_inc_solver(); - SASSERT(m_inc_solver == 0 || m_inc_mode); - } - if (m_inc_mode) { - SASSERT(m_inc_solver); - m_inc_solver->assert_expr(t, a); - } - SASSERT(m_ctx); - m_ctx->m_assertions.push_back(t); - if (m_produce_unsat_cores) - m_ctx->m_assertion_names.push_back(a); -} - -void strategic_solver::push() { - DEBUG_CODE(m_num_scopes++;); - init_inc_solver(); - if (m_inc_solver) - m_inc_solver->push(); - m_ctx->m_scopes.push_back(m_ctx->m_assertions.size()); -} - -void strategic_solver::pop(unsigned n) { - DEBUG_CODE({ - SASSERT(n <= m_num_scopes); - m_num_scopes -= n; - }); - init_inc_solver(); - if (m_inc_solver) - m_inc_solver->pop(n); - - SASSERT(m_ctx); - unsigned new_lvl = m_ctx->m_scopes.size() - n; - unsigned old_sz = m_ctx->m_scopes[new_lvl]; - m_ctx->m_assertions.shrink(old_sz); - if (m_produce_unsat_cores) - m_ctx->m_assertion_names.shrink(old_sz); - m_ctx->m_scopes.shrink(new_lvl); -} - -unsigned strategic_solver::get_scope_level() const { - if (m_ctx == 0) - return 0; - return m_ctx->m_scopes.size(); -} - -struct aux_timeout_eh : public event_handler { - solver * m_solver; - volatile bool m_canceled; - aux_timeout_eh(solver * s):m_solver(s), m_canceled(false) {} - virtual void operator()() { - m_solver->cancel(); - m_canceled = true; - } -}; - -struct strategic_solver::mk_tactic { - strategic_solver * m_solver; - - mk_tactic(strategic_solver * s, tactic_factory * f, params_ref const & p):m_solver(s) { - ast_manager & m = s->m(); - tactic * tct = (*f)(m, p); - tct->set_logic(s->m_logic); - if (s->m_callback) - tct->set_progress_callback(s->m_callback); - #pragma omp critical (strategic_solver) - { - s->m_curr_tactic = tct; - } - } - - ~mk_tactic() { - #pragma omp critical (strategic_solver) - { - m_solver->m_curr_tactic = 0; - } - } -}; - -tactic_factory * strategic_solver::get_tactic_factory() const { - tactic_factory * f = 0; - if (m_logic2fct.find(m_logic, f)) - return f; - return m_default_fct.get(); -} - -lbool strategic_solver::check_sat_with_assumptions(unsigned num_assumptions, expr * const * assumptions) { - if (!m_inc_solver) { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "incremental solver was not installed, returning unknown...\n";); - m_use_inc_solver_results = false; - m_reason_unknown = "incomplete"; - return l_undef; - } - init_inc_solver(); - m_use_inc_solver_results = true; - TRACE("strategic_solver", tout << "invoking inc_solver with " << num_assumptions << " assumptions\n";); - return m_inc_solver->check_sat(num_assumptions, assumptions); -} - -lbool strategic_solver::check_sat(unsigned num_assumptions, expr * const * assumptions) { - TRACE("strategic_solver", tout << "assumptions at strategic_solver:\n"; - for (unsigned i = 0; i < num_assumptions; i++) { - tout << mk_ismt2_pp(assumptions[i], m()) << "\n"; - } - tout << "m_produce_unsat_cores: " << m_produce_unsat_cores << ", m_inc_mode: " << m_inc_mode << "\n";); - reset_results(); - m_check_sat_executed = true; - if (num_assumptions > 0 || // assumptions were provided - (!m_auto_config && !m_force_tactic) // auto config and force_tactic are turned off - ) { - // must use incremental solver - return check_sat_with_assumptions(num_assumptions, assumptions); - } - - tactic_factory * factory = get_tactic_factory(); - if (factory == 0) - init_inc_solver(); // try to switch to incremental solver - - if (m_inc_mode) { - SASSERT(m_inc_solver); - unsigned timeout = m_inc_solver_timeout; - if (factory == 0) - timeout = UINT_MAX; // there is no tactic available - if (timeout == UINT_MAX) { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "using incremental solver (without a timeout).\n";); - m_use_inc_solver_results = true; - lbool r = m_inc_solver->check_sat(0, 0); - if (r != l_undef || factory == 0 || !use_tactic_when_undef()) { - m_use_inc_solver_results = true; - return r; - } - } - else { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "using incremental solver (with timeout).\n";); - SASSERT(factory != 0); - aux_timeout_eh eh(m_inc_solver.get()); - lbool r; - { - scoped_timer timer(m_inc_solver_timeout, &eh); - r = m_inc_solver->check_sat(0, 0); - } - if ((r != l_undef || !use_tactic_when_undef()) && !eh.m_canceled) { - m_use_inc_solver_results = true; - return r; - } - } - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "incremental solver failed, trying tactic.\n";); - } - - m_use_inc_solver_results = false; - - if (factory == 0) { - IF_VERBOSE(PS_VB_LVL, verbose_stream() << "there is no tactic available for the current logic.\n";); - m_reason_unknown = "incomplete"; - return l_undef; - } - - goal_ref g = alloc(goal, m(), m_produce_proofs, m_produce_models, m_produce_unsat_cores); - unsigned sz = get_num_assertions(); - if (m_produce_unsat_cores) { - SASSERT(m_ctx->m_assertions.size() == m_ctx->m_assertion_names.size()); - for (unsigned i = 0; i < sz; i++) - g->assert_expr(get_assertion(i), get_assertion_name(i)); - } - else { - for (unsigned i = 0; i < sz; i++) - g->assert_expr(get_assertion(i)); - } - expr_dependency_ref core(m()); - - TRACE("strategic_solver", tout << "using goal...\n"; g->display_with_dependencies(tout);); - - mk_tactic tct_maker(this, factory, m_params); - SASSERT(m_curr_tactic); - - proof_ref pr(m()); - lbool r = ::check_sat(*(m_curr_tactic.get()), g, m_model, pr, core, m_reason_unknown); - m_curr_tactic->collect_statistics(m_stats); - if (pr) { - m_proof = pr; - m().inc_ref(m_proof); - } - if (core) { - m_core = core; - m().inc_ref(m_core); - } - return r; -} - -void strategic_solver::set_cancel(bool f) { - if (m_inc_solver) - m_inc_solver->set_cancel(f); - #pragma omp critical (strategic_solver) - { - if (m_curr_tactic) - m_curr_tactic->set_cancel(f); - } -} - -void strategic_solver::get_unsat_core(ptr_vector & r) { - TRACE("strategic_solver", tout << "get_unsat_core, m_use_inc_solver_results: " << m_use_inc_solver_results << "\n";); - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->get_unsat_core(r); - } - else { - m().linearize(m_core, r); - } -} - -void strategic_solver::get_model(model_ref & m) { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->get_model(m); - } - else { - m = m_model; - } -} - -proof * strategic_solver::get_proof() { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - return m_inc_solver->get_proof(); - } - else { - return m_proof; - } -} - -std::string strategic_solver::reason_unknown() const { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - return m_inc_solver->reason_unknown(); - } - return m_reason_unknown; -} - -void strategic_solver::get_labels(svector & r) { - if (m_use_inc_solver_results) { - SASSERT(m_inc_solver); - m_inc_solver->get_labels(r); - } -} - -void strategic_solver::set_progress_callback(progress_callback * callback) { - m_callback = callback; - if (m_inc_solver) - m_inc_solver->set_progress_callback(callback); -} - -void strategic_solver::display(std::ostream & out) const { - if (m_manager) { - unsigned num = get_num_assertions(); - out << "(solver"; - for (unsigned i = 0; i < num; i++) { - out << "\n " << mk_ismt2_pp(get_assertion(i), m(), 2); - } - out << ")"; - } - else { - out << "(solver)"; - } -} - - - - - - diff --git a/src/solver/strategic_solver.h b/src/solver/strategic_solver.h deleted file mode 100644 index 1883a88cd..000000000 --- a/src/solver/strategic_solver.h +++ /dev/null @@ -1,153 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - strategic_solver.h - -Abstract: - - Strategies -> Solver - -Author: - - Leonardo (leonardo) 2011-05-19 - -Notes: - ---*/ -#ifndef _STRATEGIC_SOLVER_H_ -#define _STRATEGIC_SOLVER_H_ - -#include"solver.h" -#include"tactic.h" - -class progress_callback; - -/** - \brief Implementation of the solver API that supports: - - a different tactic for each logic - - a general purpose tactic - - a default incremental solver - - The strategic solver has two modes: - - non-incremental - - incremental - In non-incremental mode, tactics are used. - In incremental model, the incremental (general purpose) solver is used. - - A timeout for the incremental solver can be specified. - If the timeout is reached, then the strategic_solver tries to solve the problem using tactics. - - The strategic_solver switches to incremental when: - - push is used - - assertions are peformed after a check_sat - It goes back to non_incremental mode when: - - reset is invoked. -*/ -class strategic_solver : public solver { -public: - // Behavior when the incremental solver returns unknown. - enum inc_unknown_behavior { - IUB_RETURN_UNDEF, // just return unknown - IUB_USE_TACTIC_IF_QF, // invoke tactic if problem is quantifier free - IUB_USE_TACTIC // invoke tactic - }; - -private: - ast_manager * m_manager; - params_ref m_params; - symbol m_logic; - bool m_force_tactic; // use tactics even when auto_config = false - bool m_inc_mode; - bool m_check_sat_executed; - scoped_ptr m_inc_solver; - unsigned m_inc_solver_timeout; - inc_unknown_behavior m_inc_unknown_behavior; - scoped_ptr m_default_fct; - dictionary m_logic2fct; - - ref m_curr_tactic; - - bool m_use_inc_solver_results; - model_ref m_model; - proof * m_proof; - expr_dependency * m_core; - std::string m_reason_unknown; - statistics m_stats; - - struct ctx { - expr_ref_vector m_assertions; - expr_ref_vector m_assertion_names; - unsigned_vector m_scopes; - ctx(ast_manager & m); - }; - scoped_ptr m_ctx; - -#ifdef Z3DEBUG - unsigned m_num_scopes; -#endif - - bool m_produce_proofs; - bool m_produce_models; - bool m_produce_unsat_cores; - - bool m_auto_config; - - progress_callback * m_callback; - - void reset_results(); - void init_inc_solver(); - tactic_factory * get_tactic_factory() const; - lbool check_sat_with_assumptions(unsigned num_assumptions, expr * const * assumptions); - - struct mk_tactic; - - bool has_quantifiers() const; - bool use_tactic_when_undef() const; - -public: - strategic_solver(); - ~strategic_solver(); - - ast_manager & m() const { SASSERT(m_manager); return *m_manager; } - - void set_inc_solver(solver * s); - void set_inc_solver_timeout(unsigned timeout); - void set_default_tactic(tactic_factory * fct); - void set_tactic_for(symbol const & logic, tactic_factory * fct); - void set_inc_unknown_behavior(inc_unknown_behavior b) { m_inc_unknown_behavior = b; } - void force_tactic(bool f) { m_force_tactic = f; } - - virtual void updt_params(params_ref const & p); - virtual void collect_param_descrs(param_descrs & r); - - virtual void set_produce_proofs(bool f); - virtual void set_produce_models(bool f); - virtual void set_produce_unsat_cores(bool f); - - unsigned get_num_assertions() const; - expr * get_assertion(unsigned idx) const; - expr * get_assertion_name(unsigned idx) const; - - virtual void display(std::ostream & out) const; - - virtual void init(ast_manager & m, symbol const & logic); - virtual void collect_statistics(statistics & st) const; - virtual void reset(); - virtual void assert_expr(expr * t); - virtual void assert_expr(expr * t, expr * a); - virtual void push(); - virtual void pop(unsigned n); - virtual unsigned get_scope_level() const; - virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions); - virtual void get_unsat_core(ptr_vector & r); - virtual void get_model(model_ref & m); - virtual proof * get_proof(); - virtual std::string reason_unknown() const; - virtual void get_labels(svector & r); - virtual void set_cancel(bool f); - virtual void set_progress_callback(progress_callback * callback); -}; - -#endif diff --git a/src/solver/tactic2solver.cpp b/src/solver/tactic2solver.cpp index e630f9c78..1268fbcea 100644 --- a/src/solver/tactic2solver.cpp +++ b/src/solver/tactic2solver.cpp @@ -19,96 +19,115 @@ Author: Notes: --*/ -#include"tactic2solver.h" +#include"solver_na2as.h" +#include"tactic.h" #include"ast_smt2_pp.h" -tactic2solver_core::ctx::ctx(ast_manager & m, symbol const & logic): - m_logic(logic), +/** + \brief Simulates the incremental solver interface using a tactic. + + Every query will be solved from scratch. So, this is not a good + option for applications trying to solve many easy queries that a + similar to each other. +*/ +class tactic2solver : public solver_na2as { + expr_ref_vector m_assertions; + unsigned_vector m_scopes; + ref m_result; + tactic_ref m_tactic; + symbol m_logic; + params_ref m_params; + bool m_produce_models; + bool m_produce_proofs; + bool m_produce_unsat_cores; +public: + tactic2solver(ast_manager & m, tactic * t, params_ref const & p, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic); + virtual ~tactic2solver(); + + virtual void updt_params(params_ref const & p); + virtual void collect_param_descrs(param_descrs & r); + + virtual void set_produce_models(bool f) { m_produce_models = f; } + + virtual void assert_expr(expr * t); + + virtual void push_core(); + virtual void pop_core(unsigned n); + virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions); + + virtual void set_cancel(bool f); + + virtual void collect_statistics(statistics & st) const; + virtual void get_unsat_core(ptr_vector & r); + virtual void get_model(model_ref & m); + virtual proof * get_proof(); + virtual std::string reason_unknown() const; + virtual void get_labels(svector & r) {} + + virtual void set_progress_callback(progress_callback * callback) {} + + virtual unsigned get_num_assertions() const; + virtual expr * get_assertion(unsigned idx) const; + + virtual void display(std::ostream & out) const; +}; + +tactic2solver::tactic2solver(ast_manager & m, tactic * t, params_ref const & p, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic): + solver_na2as(m), m_assertions(m) { + + m_tactic = t; + m_logic = logic; + m_params = p; + + m_produce_models = produce_models; + m_produce_proofs = produce_proofs; + m_produce_unsat_cores = produce_unsat_cores; } -tactic2solver_core::~tactic2solver_core() { +tactic2solver::~tactic2solver() { } -void tactic2solver_core::init_core(ast_manager & m, symbol const & logic) { - m_ctx = alloc(ctx, m, logic); -} - -void tactic2solver_core::updt_params(params_ref const & p) { +void tactic2solver::updt_params(params_ref const & p) { m_params = p; } -void tactic2solver_core::collect_param_descrs(param_descrs & r) { - if (m_ctx) { - if (!m_ctx->m_tactic) { - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = get_tactic(m_ctx->m(), m_params); - } - - if (m_ctx->m_tactic) { - m_ctx->m_tactic->collect_param_descrs(r); - } - - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = 0; - } - } - else { - m_ctx->m_tactic->collect_param_descrs(r); - } - } +void tactic2solver::collect_param_descrs(param_descrs & r) { + if (m_tactic.get()) + m_tactic->collect_param_descrs(r); } -void tactic2solver_core::reset_core() { - SASSERT(m_ctx); - m_ctx->m_assertions.reset(); - m_ctx->m_scopes.reset(); - m_ctx->m_result = 0; +void tactic2solver::assert_expr(expr * t) { + m_assertions.push_back(t); + m_result = 0; } -void tactic2solver_core::assert_expr(expr * t) { - SASSERT(m_ctx); - m_ctx->m_assertions.push_back(t); - m_ctx->m_result = 0; +void tactic2solver::push_core() { + m_scopes.push_back(m_assertions.size()); + m_result = 0; } -void tactic2solver_core::push_core() { - SASSERT(m_ctx); - m_ctx->m_scopes.push_back(m_ctx->m_assertions.size()); - m_ctx->m_result = 0; +void tactic2solver::pop_core(unsigned n) { + unsigned new_lvl = m_scopes.size() - n; + unsigned old_sz = m_scopes[new_lvl]; + m_assertions.shrink(old_sz); + m_scopes.shrink(new_lvl); + m_result = 0; } -void tactic2solver_core::pop_core(unsigned n) { - SASSERT(m_ctx); - unsigned new_lvl = m_ctx->m_scopes.size() - n; - unsigned old_sz = m_ctx->m_scopes[new_lvl]; - m_ctx->m_assertions.shrink(old_sz); - m_ctx->m_scopes.shrink(new_lvl); - m_ctx->m_result = 0; -} - -lbool tactic2solver_core::check_sat_core(unsigned num_assumptions, expr * const * assumptions) { - SASSERT(m_ctx); - ast_manager & m = m_ctx->m(); - params_ref p = m_params; - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = get_tactic(m, p); - if (m_ctx->m_tactic) { - m_ctx->m_result = alloc(simple_check_sat_result, m); - } - } - if (!m_ctx->m_tactic) - return l_undef; - tactic & t = *(m_ctx->m_tactic); - simple_check_sat_result & result = *(m_ctx->m_result); +lbool tactic2solver::check_sat_core(unsigned num_assumptions, expr * const * assumptions) { + if (m_tactic.get() == 0) + return l_false; + ast_manager & m = m_assertions.m(); + m_result = alloc(simple_check_sat_result, m); + m_tactic->cleanup(); + m_tactic->updt_params(m_params); + m_tactic->set_logic(m_logic); goal_ref g = alloc(goal, m, m_produce_proofs, m_produce_models, m_produce_unsat_cores); - t.set_logic(m_ctx->m_logic); - unsigned sz = m_ctx->m_assertions.size(); + + unsigned sz = m_assertions.size(); for (unsigned i = 0; i < sz; i++) { - g->assert_expr(m_ctx->m_assertions.get(i)); + g->assert_expr(m_assertions.get(i)); } for (unsigned i = 0; i < num_assumptions; i++) { g->assert_expr(assumptions[i], m.mk_asserted(assumptions[i]), m.mk_leaf(assumptions[i])); @@ -119,17 +138,17 @@ lbool tactic2solver_core::check_sat_core(unsigned num_assumptions, expr * const expr_dependency_ref core(m); std::string reason_unknown = "unknown"; try { - switch (::check_sat(t, g, md, pr, core, reason_unknown)) { + switch (::check_sat(*m_tactic, g, md, pr, core, reason_unknown)) { case l_true: - result.set_status(l_true); + m_result->set_status(l_true); break; case l_false: - result.set_status(l_false); + m_result->set_status(l_false); break; default: - result.set_status(l_undef); + m_result->set_status(l_undef); if (reason_unknown != "") - result.m_unknown = reason_unknown; + m_result->m_unknown = reason_unknown; break; } } @@ -137,112 +156,115 @@ lbool tactic2solver_core::check_sat_core(unsigned num_assumptions, expr * const throw ex; } catch (z3_exception & ex) { - TRACE("tactic2solver_core", tout << "exception: " << ex.msg() << "\n";); - result.set_status(l_undef); - result.m_unknown = ex.msg(); + TRACE("tactic2solver", tout << "exception: " << ex.msg() << "\n";); + m_result->set_status(l_undef); + m_result->m_unknown = ex.msg(); } - t.collect_statistics(result.m_stats); - result.m_model = md; - result.m_proof = pr; + m_tactic->collect_statistics(m_result->m_stats); + m_result->m_model = md; + m_result->m_proof = pr; if (m_produce_unsat_cores) { ptr_vector core_elems; m.linearize(core, core_elems); - result.m_core.append(core_elems.size(), core_elems.c_ptr()); + m_result->m_core.append(core_elems.size(), core_elems.c_ptr()); } - - #pragma omp critical (tactic2solver_core) - { - m_ctx->m_tactic = 0; - } - return result.status(); + m_tactic->cleanup(); + return m_result->status(); } -void tactic2solver_core::set_cancel(bool f) { - #pragma omp critical (tactic2solver_core) - { - if (m_ctx && m_ctx->m_tactic) - m_ctx->m_tactic->set_cancel(f); - } +void tactic2solver::set_cancel(bool f) { + if (m_tactic.get()) + m_tactic->set_cancel(f); } -void tactic2solver_core::collect_statistics(statistics & st) const { - if (m_ctx->m_result.get()) - m_ctx->m_result->collect_statistics(st); +void tactic2solver::collect_statistics(statistics & st) const { + if (m_result.get()) + m_result->collect_statistics(st); } -void tactic2solver_core::get_unsat_core(ptr_vector & r) { - if (m_ctx->m_result.get()) - m_ctx->m_result->get_unsat_core(r); +void tactic2solver::get_unsat_core(ptr_vector & r) { + if (m_result.get()) + m_result->get_unsat_core(r); } -void tactic2solver_core::get_model(model_ref & m) { - if (m_ctx->m_result.get()) - m_ctx->m_result->get_model(m); +void tactic2solver::get_model(model_ref & m) { + if (m_result.get()) + m_result->get_model(m); } -proof * tactic2solver_core::get_proof() { - if (m_ctx->m_result.get()) - return m_ctx->m_result->get_proof(); +proof * tactic2solver::get_proof() { + if (m_result.get()) + return m_result->get_proof(); else return 0; } -std::string tactic2solver_core::reason_unknown() const { - if (m_ctx->m_result.get()) - return m_ctx->m_result->reason_unknown(); +std::string tactic2solver::reason_unknown() const { + if (m_result.get()) + return m_result->reason_unknown(); else return std::string("unknown"); } -unsigned tactic2solver_core::get_num_assertions() const { - if (m_ctx) - return m_ctx->m_assertions.size(); - else - return 0; +unsigned tactic2solver::get_num_assertions() const { + return m_assertions.size(); } -expr * tactic2solver_core::get_assertion(unsigned idx) const { - SASSERT(m_ctx); - return m_ctx->m_assertions.get(idx); +expr * tactic2solver::get_assertion(unsigned idx) const { + return m_assertions.get(idx); } -void tactic2solver_core::display(std::ostream & out) const { - if (m_ctx) { - ast_manager & m = m_ctx->m_assertions.m(); - unsigned num = m_ctx->m_assertions.size(); - out << "(solver"; - for (unsigned i = 0; i < num; i++) { - out << "\n " << mk_ismt2_pp(m_ctx->m_assertions.get(i), m, 2); - } - out << ")"; +void tactic2solver::display(std::ostream & out) const { + ast_manager & m = m_assertions.m(); + unsigned num = m_assertions.size(); + out << "(solver"; + for (unsigned i = 0; i < num; i++) { + out << "\n " << mk_ismt2_pp(m_assertions.get(i), m, 2); } - else { - out << "(solver)"; + out << ")"; +} + +solver * mk_tactic2solver(ast_manager & m, + tactic * t, + params_ref const & p, + bool produce_proofs, + bool produce_models, + bool produce_unsat_cores, + symbol const & logic) { + return alloc(tactic2solver, m, t, p, produce_proofs, produce_models, produce_unsat_cores, logic); +} + +class tactic2solver_factory : public solver_factory { + ref m_tactic; +public: + tactic2solver_factory(tactic * t):m_tactic(t) { } + + virtual ~tactic2solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + return mk_tactic2solver(m, m_tactic.get(), p, proofs_enabled, models_enabled, unsat_core_enabled, logic); + } +}; + +class tactic_factory2solver_factory : public solver_factory { + scoped_ptr m_factory; +public: + tactic_factory2solver_factory(tactic_factory * f):m_factory(f) { + } + + virtual ~tactic_factory2solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + tactic * t = (*m_factory)(m, p); + return mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, logic); + } +}; + +solver_factory * mk_tactic2solver_factory(tactic * t) { + return alloc(tactic2solver_factory, t); } -tactic2solver::tactic2solver(tactic * t): - m_tactic(t) { -} - -tactic2solver::~tactic2solver() { -} - -tactic * tactic2solver::get_tactic(ast_manager & m, params_ref const & p) { - m_tactic->cleanup(); - m_tactic->updt_params(p); - return m_tactic.get(); -} - -tactic_factory2solver::~tactic_factory2solver() { -} - -void tactic_factory2solver::set_tactic(tactic_factory * f) { - m_tactic_factory = f; -} - -tactic * tactic_factory2solver::get_tactic(ast_manager & m, params_ref const & p) { - if (m_tactic_factory == 0) - return 0; - return (*m_tactic_factory)(m, p); +solver_factory * mk_tactic_factory2solver_factory(tactic_factory * f) { + return alloc(tactic_factory2solver_factory, f); } diff --git a/src/solver/tactic2solver.h b/src/solver/tactic2solver.h index 0a057b04b..f20b1c4dd 100644 --- a/src/solver/tactic2solver.h +++ b/src/solver/tactic2solver.h @@ -22,88 +22,22 @@ Notes: #ifndef _TACTIC2SOLVER_H_ #define _TACTIC2SOLVER_H_ -#include"solver_na2as.h" -#include"tactic.h" +#include"params.h" +class ast_manager; +class tactic; +class tactic_factory; +class solver; +class solver_factory; -/** - \brief Simulates the incremental solver interface using a tactic. - - Every query will be solved from scratch. So, this is not a good - option for applications trying to solve many easy queries that a - similar to each other. -*/ -class tactic2solver_core : public solver_na2as { - struct ctx { - symbol m_logic; - expr_ref_vector m_assertions; - unsigned_vector m_scopes; - ref m_result; - tactic_ref m_tactic; - ctx(ast_manager & m, symbol const & logic); - ast_manager & m() const { return m_assertions.m(); } - }; - scoped_ptr m_ctx; - params_ref m_params; - bool m_produce_models; - bool m_produce_proofs; - bool m_produce_unsat_cores; -public: - tactic2solver_core():m_ctx(0), m_produce_models(false), m_produce_proofs(false), m_produce_unsat_cores(false) {} - virtual ~tactic2solver_core(); - - virtual tactic * get_tactic(ast_manager & m, params_ref const & p) = 0; - - virtual void updt_params(params_ref const & p); - virtual void collect_param_descrs(param_descrs & r); - - virtual void set_produce_proofs(bool f) { m_produce_proofs = f; } - virtual void set_produce_models(bool f) { m_produce_models = f; } - virtual void set_produce_unsat_cores(bool f) { m_produce_unsat_cores = f; } - - virtual void assert_expr(expr * t); - - virtual void init_core(ast_manager & m, symbol const & logic); - virtual void reset_core(); - virtual void push_core(); - virtual void pop_core(unsigned n); - virtual lbool check_sat_core(unsigned num_assumptions, expr * const * assumptions); - - virtual void set_cancel(bool f); - - virtual void collect_statistics(statistics & st) const; - virtual void get_unsat_core(ptr_vector & r); - virtual void get_model(model_ref & m); - virtual proof * get_proof(); - virtual std::string reason_unknown() const; - virtual void get_labels(svector & r) {} - - virtual void set_progress_callback(progress_callback * callback) {} - - virtual unsigned get_num_assertions() const; - virtual expr * get_assertion(unsigned idx) const; - - virtual void display(std::ostream & out) const; -}; - -class tactic2solver : public tactic2solver_core { - tactic_ref m_tactic; -public: - tactic2solver(tactic * t); - virtual ~tactic2solver(); - virtual tactic * get_tactic(ast_manager & m, params_ref const & p); -}; - - -class tactic_factory2solver : public tactic2solver_core { - scoped_ptr m_tactic_factory; -public: - virtual ~tactic_factory2solver(); - /** - \brief Set tactic that will be used to process the satisfiability queries. - */ - void set_tactic(tactic_factory * f); - virtual tactic * get_tactic(ast_manager & m, params_ref const & p); -}; +solver * mk_tactic2solver(ast_manager & m, + tactic * t = 0, + params_ref const & p = params_ref(), + bool produce_proofs = false, + bool produce_models = true, + bool produce_unsat_cores = false, + symbol const & logic = symbol::null); +solver_factory * mk_tactic2solver_factory(tactic * t); +solver_factory * mk_tactic_factory2solver_factory(tactic_factory * f); #endif diff --git a/src/tactic/arith/bv2int_rewriter.cpp b/src/tactic/arith/bv2int_rewriter.cpp index 0965f36f2..872981283 100644 --- a/src/tactic/arith/bv2int_rewriter.cpp +++ b/src/tactic/arith/bv2int_rewriter.cpp @@ -544,7 +544,7 @@ bool bv2int_rewriter::is_sbv2int(expr* n, expr_ref& s) { m_bv.is_extract(e2, lo1, hi1, e3) && lo1 == 0 && hi1 == hi-1 && m_arith.is_numeral(t2, k, is_int) && is_int && - k == m_bv.power_of_two(hi) + k == rational::power_of_two(hi) ) { s = e3; return true; diff --git a/src/tactic/arith/nla2bv_tactic.cpp b/src/tactic/arith/nla2bv_tactic.cpp index 188ea7d70..bd5af58f2 100644 --- a/src/tactic/arith/nla2bv_tactic.cpp +++ b/src/tactic/arith/nla2bv_tactic.cpp @@ -253,7 +253,7 @@ class nla2bv_tactic : public tactic { s_bv = m_arith.mk_sub(m_arith.mk_numeral(*up, true), s_bv); } else { - s_bv = m_arith.mk_sub(s_bv, m_arith.mk_numeral(m_bv.power_of_two(num_bits-1), true)); + s_bv = m_arith.mk_sub(s_bv, m_arith.mk_numeral(rational::power_of_two(num_bits-1), true)); } m_trail.push_back(s_bv); diff --git a/src/tactic/arith/pb2bv_tactic.cpp b/src/tactic/arith/pb2bv_tactic.cpp index 8790ca5a7..83a949579 100644 --- a/src/tactic/arith/pb2bv_tactic.cpp +++ b/src/tactic/arith/pb2bv_tactic.cpp @@ -583,7 +583,7 @@ private: return false; // size must be even // I implemented only the easy (and very common) case, where a_i = 2^{n-i-1} and c = 2^n - 1 unsigned n = sz/2; - if (c != m_bv_util.power_of_two(n) - numeral(1)) + if (c != rational::power_of_two(n) - numeral(1)) return false; for (unsigned i = 0; i < n; i++) { monomial const & m1 = p[i*2]; @@ -592,7 +592,7 @@ private: return false; if (m1.m_a != m2.m_a) return false; - if (m1.m_a != m_bv_util.power_of_two(n - i - 1)) + if (m1.m_a != rational::power_of_two(n - i - 1)) return false; } return true; diff --git a/src/tactic/core/ctx_simplify_tactic.cpp b/src/tactic/core/ctx_simplify_tactic.cpp index cca21b90e..831efa087 100644 --- a/src/tactic/core/ctx_simplify_tactic.cpp +++ b/src/tactic/core/ctx_simplify_tactic.cpp @@ -18,7 +18,7 @@ Notes: --*/ #include"ctx_simplify_tactic.h" #include"mk_simplified_app.h" -#include"num_occurs_goal.h" +#include"goal_num_occurs.h" #include"cooperate.h" #include"ast_ll_pp.h" #include"ast_smt2_pp.h" @@ -51,7 +51,7 @@ struct ctx_simplify_tactic::imp { unsigned m_scope_lvl; unsigned m_depth; unsigned m_num_steps; - num_occurs_goal m_occs; + goal_num_occurs m_occs; mk_simplified_app m_mk_app; unsigned long long m_max_memory; unsigned m_max_depth; diff --git a/src/tactic/core/elim_uncnstr_tactic.cpp b/src/tactic/core/elim_uncnstr_tactic.cpp index d1dca296a..00e14a41f 100644 --- a/src/tactic/core/elim_uncnstr_tactic.cpp +++ b/src/tactic/core/elim_uncnstr_tactic.cpp @@ -647,9 +647,9 @@ class elim_uncnstr_tactic : public tactic { unsigned bv_sz = m_bv_util.get_bv_size(arg1); rational MAX; if (is_signed) - MAX = m_bv_util.power_of_two(bv_sz - 1) - rational(1); + MAX = rational::power_of_two(bv_sz - 1) - rational(1); else - MAX = m_bv_util.power_of_two(bv_sz) - rational(1); + MAX = rational::power_of_two(bv_sz) - rational(1); app * u; bool is_new = mk_fresh_uncnstr_var_for(f, arg1, arg2, u); app * r = m().mk_or(u, m().mk_eq(t, m_bv_util.mk_numeral(MAX, bv_sz))); @@ -666,7 +666,7 @@ class elim_uncnstr_tactic : public tactic { unsigned bv_sz = m_bv_util.get_bv_size(arg1); rational MIN; if (is_signed) - MIN = -m_bv_util.power_of_two(bv_sz - 1); + MIN = -rational::power_of_two(bv_sz - 1); else MIN = rational(0); app * u; diff --git a/src/tactic/core/nnf_tactic.cpp b/src/tactic/core/nnf_tactic.cpp index a79a4ed06..19190c299 100644 --- a/src/tactic/core/nnf_tactic.cpp +++ b/src/tactic/core/nnf_tactic.cpp @@ -18,6 +18,7 @@ Revision History: --*/ #include"nnf.h" #include"tactical.h" +#include"filter_model_converter.h" class nnf_tactic : public tactic { params_ref m_params; @@ -100,6 +101,13 @@ public: } g->inc_depth(); result.push_back(g.get()); + unsigned num_extra_names = dnames.get_num_names(); + if (num_extra_names > 0) { + filter_model_converter * fmc = alloc(filter_model_converter, m); + mc = fmc; + for (unsigned i = 0; i < num_extra_names; i++) + fmc->insert(dnames.get_name_decl(i)); + } TRACE("nnf", g->display(tout);); SASSERT(g->is_well_sorted()); } diff --git a/src/tactic/fpa/fpa2bv_converter.cpp b/src/tactic/fpa/fpa2bv_converter.cpp index 8a4b31612..b53ad21eb 100644 --- a/src/tactic/fpa/fpa2bv_converter.cpp +++ b/src/tactic/fpa/fpa2bv_converter.cpp @@ -32,7 +32,7 @@ fpa2bv_converter::fpa2bv_converter(ast_manager & m) : m_mpz_manager(m_mpf_manager.mpz_manager()), m_bv_util(m), extra_assertions(m) { - m_plugin = static_cast(m.get_plugin(m.get_family_id("float"))); + m_plugin = static_cast(m.get_plugin(m.mk_family_id("float"))); } fpa2bv_converter::~fpa2bv_converter() { diff --git a/src/tactic/num_occurs_goal.cpp b/src/tactic/goal_num_occurs.cpp similarity index 75% rename from src/tactic/num_occurs_goal.cpp rename to src/tactic/goal_num_occurs.cpp index adc412434..6c94e307c 100644 --- a/src/tactic/num_occurs_goal.cpp +++ b/src/tactic/goal_num_occurs.cpp @@ -3,7 +3,7 @@ Copyright (c) 2012 Microsoft Corporation Module Name: - num_occurs_goal.cpp + goal_num_occurs.cpp Abstract: @@ -15,10 +15,10 @@ Author: Revision History: --*/ -#include"num_occurs_goal.h" +#include"goal_num_occurs.h" #include"goal.h" -void num_occurs_goal::operator()(goal const & g) { +void goal_num_occurs::operator()(goal const & g) { expr_fast_mark1 visited; unsigned sz = g.size(); for (unsigned i = 0; i < sz; i++) { diff --git a/src/tactic/num_occurs_goal.h b/src/tactic/goal_num_occurs.h similarity index 64% rename from src/tactic/num_occurs_goal.h rename to src/tactic/goal_num_occurs.h index 5e6e0cc94..33a25e03f 100644 --- a/src/tactic/num_occurs_goal.h +++ b/src/tactic/goal_num_occurs.h @@ -3,7 +3,7 @@ Copyright (c) 2012 Microsoft Corporation Module Name: - num_occurs_goal.h + goal_num_occurs.h Abstract: @@ -15,16 +15,16 @@ Author: Revision History: --*/ -#ifndef _NUM_OCCURS_GOAL_H_ -#define _NUM_OCCURS_GOAL_H_ +#ifndef _GOAL_NUM_OCCURS_H_ +#define _GOAL_NUM_OCCURS_H_ #include"num_occurs.h" class goal; -class num_occurs_goal : public num_occurs { +class goal_num_occurs : public num_occurs { public: - num_occurs_goal(bool ignore_ref_count1 = false, bool ignore_quantifiers = false): + goal_num_occurs(bool ignore_ref_count1 = false, bool ignore_quantifiers = false): num_occurs(ignore_ref_count1, ignore_quantifiers) { } diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp index 7a274a830..0e63255ca 100644 --- a/src/tactic/portfolio/smt_strategic_solver.cpp +++ b/src/tactic/portfolio/smt_strategic_solver.cpp @@ -18,7 +18,8 @@ Notes: --*/ #include"cmd_context.h" -#include"strategic_solver.h" +#include"combined_solver.h" +#include"tactic2solver.h" #include"qfbv_tactic.h" #include"qflia_tactic.h" #include"qfnia_tactic.h" @@ -36,57 +37,76 @@ Notes: #include"horn_tactic.h" #include"smt_solver.h" -MK_SIMPLE_TACTIC_FACTORY(qfuf_fct, mk_qfuf_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfidl_fct, mk_qfidl_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfauflia_fct, mk_qfauflia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(auflia_fct, mk_auflia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(auflira_fct, mk_auflira_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(aufnira_fct, mk_aufnira_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(ufnia_fct, mk_ufnia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(uflra_fct, mk_uflra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(lra_fct, mk_lra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfbv_fct, mk_qfbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(default_fct, mk_default_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfaufbv_fct, mk_qfaufbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qflra_fct, mk_qflra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qflia_fct, mk_qflia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfufbv_fct, mk_qfufbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfnia_fct, mk_qfnia_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qfnra_fct, mk_qfnra_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(qffpa_fct, mk_qffpa_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(ufbv_fct, mk_ufbv_tactic(m, p)); -MK_SIMPLE_TACTIC_FACTORY(horn_fct, mk_horn_tactic(m, p)); - -static void init(strategic_solver * s) { - s->set_default_tactic(alloc(default_fct)); - s->set_tactic_for(symbol("QF_UF"), alloc(qfuf_fct)); - s->set_tactic_for(symbol("QF_BV"), alloc(qfbv_fct)); - s->set_tactic_for(symbol("QF_IDL"), alloc(qfidl_fct)); - s->set_tactic_for(symbol("QF_LIA"), alloc(qflia_fct)); - s->set_tactic_for(symbol("QF_LRA"), alloc(qflra_fct)); - s->set_tactic_for(symbol("QF_NIA"), alloc(qfnia_fct)); - s->set_tactic_for(symbol("QF_NRA"), alloc(qfnra_fct)); - s->set_tactic_for(symbol("QF_AUFLIA"), alloc(qfauflia_fct)); - s->set_tactic_for(symbol("QF_AUFBV"), alloc(qfaufbv_fct)); - s->set_tactic_for(symbol("QF_ABV"), alloc(qfaufbv_fct)); - s->set_tactic_for(symbol("QF_UFBV"), alloc(qfufbv_fct)); - s->set_tactic_for(symbol("AUFLIA"), alloc(auflia_fct)); - s->set_tactic_for(symbol("AUFLIRA"), alloc(auflira_fct)); - s->set_tactic_for(symbol("AUFNIRA"), alloc(aufnira_fct)); - s->set_tactic_for(symbol("UFNIA"), alloc(ufnia_fct)); - s->set_tactic_for(symbol("UFLRA"), alloc(uflra_fct)); - s->set_tactic_for(symbol("LRA"), alloc(lra_fct)); - s->set_tactic_for(symbol("UFBV"), alloc(ufbv_fct)); - s->set_tactic_for(symbol("BV"), alloc(ufbv_fct)); - s->set_tactic_for(symbol("QF_FPA"), alloc(qffpa_fct)); - s->set_tactic_for(symbol("QF_FPABV"), alloc(qffpa_fct)); - s->set_tactic_for(symbol("HORN"), alloc(horn_fct)); +tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) { + if (logic=="QF_UF") + return mk_qfuf_tactic(m, p); + else if (logic=="QF_BV") + return mk_qfbv_tactic(m, p); + else if (logic=="QF_IDL") + return mk_qfidl_tactic(m, p); + else if (logic=="QF_LIA") + return mk_qflia_tactic(m, p); + else if (logic=="QF_LRA") + return mk_qflra_tactic(m, p); + else if (logic=="QF_NIA") + return mk_qfnia_tactic(m, p); + else if (logic=="QF_NRA") + return mk_qfnra_tactic(m, p); + else if (logic=="QF_AUFLIA") + return mk_qfauflia_tactic(m, p); + else if (logic=="QF_AUFBV") + return mk_qfaufbv_tactic(m, p); + else if (logic=="QF_ABV") + return mk_qfaufbv_tactic(m, p); + else if (logic=="QF_UFBV") + return mk_qfufbv_tactic(m, p); + else if (logic=="AUFLIA") + return mk_auflia_tactic(m, p); + else if (logic=="AUFLIRA") + return mk_auflira_tactic(m, p); + else if (logic=="AUFNIRA") + return mk_aufnira_tactic(m, p); + else if (logic=="UFNIA") + return mk_ufnia_tactic(m, p); + else if (logic=="UFLRA") + return mk_uflra_tactic(m, p); + else if (logic=="LRA") + return mk_lra_tactic(m, p); + else if (logic=="UFBV") + return mk_ufbv_tactic(m, p); + else if (logic=="BV") + return mk_ufbv_tactic(m, p); + else if (logic=="QF_FPA") + return mk_qffpa_tactic(m, p); + else if (logic=="QF_FPABV") + return mk_qffpa_tactic(m, p); + else if (logic=="HORN") + return mk_horn_tactic(m, p); + else + return mk_default_tactic(m, p); } -solver * mk_smt_strategic_solver(bool force_tactic) { - strategic_solver * s = alloc(strategic_solver); - s->force_tactic(force_tactic); - s->set_inc_solver(mk_smt_solver()); - init(s); - return s; +class smt_strategic_solver_factory : public solver_factory { + symbol m_logic; +public: + smt_strategic_solver_factory(symbol const & logic):m_logic(logic) {} + + virtual ~smt_strategic_solver_factory() {} + + virtual solver * operator()(ast_manager & m, params_ref const & p, bool proofs_enabled, bool models_enabled, bool unsat_core_enabled, symbol const & logic) { + symbol l; + if (m_logic != symbol::null) + l = m_logic; + else + l = logic; + tactic * t = mk_tactic_for_logic(m, p, l); + return mk_combined_solver(mk_tactic2solver(m, t, p, proofs_enabled, models_enabled, unsat_core_enabled, l), + mk_smt_solver(m, p, l), + p); + } +}; + +solver_factory * mk_smt_strategic_solver_factory(symbol const & logic) { + return alloc(smt_strategic_solver_factory, logic); } + diff --git a/src/tactic/portfolio/smt_strategic_solver.h b/src/tactic/portfolio/smt_strategic_solver.h index 060721e09..1d132532a 100644 --- a/src/tactic/portfolio/smt_strategic_solver.h +++ b/src/tactic/portfolio/smt_strategic_solver.h @@ -20,8 +20,8 @@ Notes: #ifndef _SMT_STRATEGIC_SOLVER_H_ #define _SMT_STRATEGIC_SOLVER_H_ -class solver; -// Create a strategic solver for the Z3 API -solver * mk_smt_strategic_solver(bool force_tactic=false); +class solver_factory; + +solver_factory * mk_smt_strategic_solver_factory(symbol const & logic = symbol::null); #endif diff --git a/src/tactic/probe.cpp b/src/tactic/probe.cpp index 2940e93b9..1a696dc78 100644 --- a/src/tactic/probe.cpp +++ b/src/tactic/probe.cpp @@ -326,7 +326,7 @@ class num_consts_probe : public probe { unsigned m_counter; proc(ast_manager & _m, bool b, char const * family):m(_m), m_bool(b), m_counter(0) { if (family != 0) - m_fid = m.get_family_id(family); + m_fid = m.mk_family_id(family); else m_fid = null_family_id; } diff --git a/src/tactic/smtlogics/qflia_tactic.cpp b/src/tactic/smtlogics/qflia_tactic.cpp index 6b05cff96..6fbf34255 100644 --- a/src/tactic/smtlogics/qflia_tactic.cpp +++ b/src/tactic/smtlogics/qflia_tactic.cpp @@ -172,6 +172,8 @@ tactic * mk_qflia_tactic(ast_manager & m, params_ref const & p) { params_ref main_p; main_p.set_bool("elim_and", true); main_p.set_bool("som", true); + main_p.set_bool("blast_distinct", true); + main_p.set_uint("blast_distinct_threshold", 128); // main_p.set_bool("push_ite_arith", true); params_ref pull_ite_p; diff --git a/src/tactic/tactic.cpp b/src/tactic/tactic.cpp index 4bf9e48f4..198872cf5 100644 --- a/src/tactic/tactic.cpp +++ b/src/tactic/tactic.cpp @@ -175,7 +175,6 @@ tactic * mk_fail_if_undecided_tactic() { void exec(tactic & t, goal_ref const & in, goal_ref_buffer & result, model_converter_ref & mc, proof_converter_ref & pc, expr_dependency_ref & core) { t.reset_statistics(); - t.reset_cancel(); try { t(in, result, mc, pc, core); t.cleanup(); diff --git a/src/tactic/tactical.cpp b/src/tactic/tactical.cpp index 785a9d82e..ca66b7a14 100644 --- a/src/tactic/tactical.cpp +++ b/src/tactic/tactical.cpp @@ -116,7 +116,6 @@ protected: m_t2->set_cancel(f); } - template tactic * translate_core(ast_manager & m) { tactic * new_t1 = m_t1->translate(m); diff --git a/src/test/bv_simplifier_plugin.cpp b/src/test/bv_simplifier_plugin.cpp index 4a472425e..635143021 100644 --- a/src/test/bv_simplifier_plugin.cpp +++ b/src/test/bv_simplifier_plugin.cpp @@ -79,7 +79,7 @@ public: m_arith(m_manager), m_simp(m_manager, m_bsimp, m_bv_params), m_bv_util(m_manager), - m_fid(m_manager.get_family_id("bv")) { + m_fid(m_manager.mk_family_id("bv")) { reg_decl_plugins(m_manager); } @@ -139,7 +139,7 @@ public: m_simp.reduce(ar->get_decl(), ar->get_num_args(), ar->get_args(), e); SASSERT(((a >> 8) | (a << 24)) == u32(e.get())); - params[0] = parameter(m_manager.mk_sort(m_manager.get_family_id("arith"), INT_SORT)); + params[0] = parameter(m_manager.mk_sort(m_manager.mk_family_id("arith"), INT_SORT)); ar = m_manager.mk_app(m_fid, OP_BV2INT, 1, params, 1, es); expr* es2[1] = { ar.get() }; params[0] = parameter(32); diff --git a/src/test/expr_rand.cpp b/src/test/expr_rand.cpp index 1ceeba8b8..19a07e98a 100644 --- a/src/test/expr_rand.cpp +++ b/src/test/expr_rand.cpp @@ -18,7 +18,7 @@ void tst_expr_arith(unsigned num_files) { er.seed(rand_seed); er.initialize_arith(20); - family_id fid = m.get_family_id("arith"); + family_id fid = m.mk_family_id("arith"); sort* int_ty = m.mk_sort(fid, INT_SORT, 0, 0); sort* real_ty = m.mk_sort(fid, REAL_SORT, 0, 0); @@ -56,7 +56,7 @@ void tst_expr_rand(unsigned num_files) { parameter p2(2); parameter p8(8); parameter p32(32); - family_id bvfid = m.get_family_id("bv"); + family_id bvfid = m.mk_family_id("bv"); sort* bv1 = m.mk_sort(bvfid, BV_SORT, 1, &p1); sort* bv2 = m.mk_sort(bvfid, BV_SORT, 1, &p2); sort* bv8 = m.mk_sort(bvfid, BV_SORT, 1, &p8); diff --git a/src/test/fuzzing/expr_rand.cpp b/src/test/fuzzing/expr_rand.cpp index e1a7631c4..a2aca7e6e 100644 --- a/src/test/fuzzing/expr_rand.cpp +++ b/src/test/fuzzing/expr_rand.cpp @@ -82,7 +82,7 @@ expr* expr_rand::choose_expr(sort* s) { void expr_rand::initialize_arith(unsigned num_vars) { arith_util u(m_manager); - family_id afid = m_manager.get_family_id("arith"); + family_id afid = m_manager.mk_family_id("arith"); sort* i_ty = m_manager.mk_sort(afid, INT_SORT, 0, 0); for(unsigned i = 0; i < num_vars; ++i) { add_var(i_ty); @@ -106,7 +106,7 @@ void expr_rand::initialize_arith(unsigned num_vars) { void expr_rand::initialize_bv(unsigned num_vars) { bv_util u(m_manager); family_id bfid = m_manager.get_basic_family_id(); - family_id bvfid = m_manager.get_family_id("bv"); + family_id bvfid = m_manager.mk_family_id("bv"); const unsigned num_sizes = 6; @@ -237,7 +237,7 @@ void expr_rand::initialize_bv(unsigned num_vars) { } void expr_rand::initialize_array(unsigned num_vars, sort* dom, sort* rng) { - family_id afid = m_manager.get_family_id("array"); + family_id afid = m_manager.mk_family_id("array"); parameter p1(dom), p2(rng); parameter ps[2] = { p1, p2 }; sort* a = m_manager.mk_sort(afid, ARRAY_SORT, 2, ps); diff --git a/src/test/get_implied_equalities.cpp b/src/test/get_implied_equalities.cpp index 91c71438f..2576920cc 100644 --- a/src/test/get_implied_equalities.cpp +++ b/src/test/get_implied_equalities.cpp @@ -3,11 +3,11 @@ #include "debug.h" static Z3_ast mk_var(Z3_context ctx, char const* name, Z3_sort s) { - return Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, name), s); + return Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, name), s); } static Z3_ast mk_int_var(Z3_context ctx, char const* name) { - return mk_var(ctx, name, Z3_mk_int_sort(ctx)); + return mk_var(ctx, name, Z3_mk_int_sort(ctx)); } @@ -29,13 +29,15 @@ static void tst_get_implied_equalities1() { unsigned i; Z3_ast terms[7] = { a, b, c, d, fa, fb, fc }; unsigned class_ids[7] = { 0, 0, 0, 0, 0, 0, 0 }; + Z3_solver solver = Z3_mk_simple_solver(ctx); + Z3_solver_inc_ref(ctx, solver); - Z3_assert_cnstr(ctx, Z3_mk_eq(ctx, a, b)); - Z3_assert_cnstr(ctx, Z3_mk_eq(ctx, b, d)); - Z3_assert_cnstr(ctx, Z3_mk_le(ctx, fa, fc)); - Z3_assert_cnstr(ctx, Z3_mk_le(ctx, fc, d)); + Z3_solver_assert(ctx, solver, Z3_mk_eq(ctx, a, b)); + Z3_solver_assert(ctx, solver, Z3_mk_eq(ctx, b, d)); + Z3_solver_assert(ctx, solver, Z3_mk_le(ctx, fa, fc)); + Z3_solver_assert(ctx, solver, Z3_mk_le(ctx, fc, d)); - Z3_get_implied_equalities(ctx, num_terms, terms, class_ids); + Z3_get_implied_equalities(ctx, solver, num_terms, terms, class_ids); for (i = 0; i < num_terms; ++i) { printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); } @@ -48,8 +50,8 @@ static void tst_get_implied_equalities1() { SASSERT(class_ids[4] == class_ids[5]); printf("asserting b <= f(a)\n"); - Z3_assert_cnstr(ctx, Z3_mk_le(ctx, b, fa)); - Z3_get_implied_equalities(ctx, num_terms, terms, class_ids); + Z3_solver_assert(ctx, solver, Z3_mk_le(ctx, b, fa)); + Z3_get_implied_equalities(ctx, solver, num_terms, terms, class_ids); for (i = 0; i < num_terms; ++i) { printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); } @@ -61,6 +63,7 @@ static void tst_get_implied_equalities1() { SASSERT(class_ids[6] == class_ids[0]); + Z3_solver_dec_ref(ctx, solver); /* delete logical context */ Z3_del_context(ctx); } @@ -72,6 +75,8 @@ static void tst_get_implied_equalities2() { Z3_config cfg = Z3_mk_config(); Z3_context ctx = Z3_mk_context(cfg); Z3_del_config(cfg); + Z3_solver solver = Z3_mk_simple_solver(ctx); + Z3_solver_inc_ref(ctx, solver); Z3_sort int_ty = Z3_mk_int_sort(ctx); Z3_ast a = mk_int_var(ctx,"a"); Z3_ast b = mk_int_var(ctx,"b"); @@ -87,7 +92,7 @@ static void tst_get_implied_equalities2() { Z3_ast terms[5] = { x, y, z, u, v}; unsigned class_ids[5] = { 0, 0, 0, 0, 0}; - Z3_get_implied_equalities(ctx, num_terms, terms, class_ids); + Z3_get_implied_equalities(ctx, solver, num_terms, terms, class_ids); for (i = 0; i < num_terms; ++i) { printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); } @@ -100,9 +105,10 @@ static void tst_get_implied_equalities2() { SASSERT(class_ids[2] != class_ids[1]); SASSERT(class_ids[3] != class_ids[1]); SASSERT(class_ids[4] != class_ids[1]); - SASSERT(class_ids[3] != class_ids[2]); + SASSERT(class_ids[3] != class_ids[2]); /* delete logical context */ + Z3_solver_dec_ref(ctx, solver); Z3_del_context(ctx); } diff --git a/src/test/model_retrieval.cpp b/src/test/model_retrieval.cpp index da6c3ddd0..f40f89d22 100644 --- a/src/test/model_retrieval.cpp +++ b/src/test/model_retrieval.cpp @@ -18,7 +18,7 @@ void tst_model_retrieval() ast_manager m; reg_decl_plugins(m); - family_id array_fid = m.get_family_id(symbol("array")); + family_id array_fid = m.mk_family_id(symbol("array")); array_util au(m); // arr_s and select_fn creation copy-pasted from z3.cpp diff --git a/src/util/cancel_eh.h b/src/util/cancel_eh.h index 74c5040a2..0401e6f03 100644 --- a/src/util/cancel_eh.h +++ b/src/util/cancel_eh.h @@ -29,6 +29,7 @@ class cancel_eh : public event_handler { T & m_obj; public: cancel_eh(T & o):m_obj(o) {} + ~cancel_eh() { m_obj.reset_cancel(); } virtual void operator()() { m_obj.cancel(); } diff --git a/src/util/gparams.cpp b/src/util/gparams.cpp index 1305a1e02..8b1fbe40e 100644 --- a/src/util/gparams.cpp +++ b/src/util/gparams.cpp @@ -52,6 +52,7 @@ char const * g_params_renames[] = { "qi_cost", "smt.qi.cost", "qi_eager_threshold", "smt.qi.eager_threshold", "nl_arith", "smt.arith.nl", + "pull_nested_quantifiers", "smt.pull_nested_quantifiers", "nnf_sk_hack", "nnf.sk_hack", "model_v2", "model.v2", "pi_non_nested_arith_weight", "pi.non_nested_arith_weight", diff --git a/src/util/rational.cpp b/src/util/rational.cpp index 0a91bd8da..122db7217 100644 --- a/src/util/rational.cpp +++ b/src/util/rational.cpp @@ -27,6 +27,31 @@ synch_mpq_manager * rational::g_mpq_manager = 0; rational rational::m_zero(0); rational rational::m_one(1); rational rational::m_minus_one(-1); +vector rational::m_powers_of_two; + +void mk_power_up_to(vector & pws, unsigned n) { + if (pws.empty()) { + pws.push_back(rational(1)); + } + unsigned sz = pws.size(); + rational curr = pws[sz - 1]; + rational two(2); + for (unsigned i = sz; i <= n; i++) { + curr *= two; + pws.push_back(curr); + } +} + +rational rational::power_of_two(unsigned k) { + rational result; + #pragma omp critical (powers_of_two) + { + if (k >= m_powers_of_two.size()) + mk_power_up_to(m_powers_of_two, k+1); + result = m_powers_of_two[k]; + } + return result; +} void rational::initialize() { if (!g_mpq_manager) { @@ -35,6 +60,7 @@ void rational::initialize() { } void rational::finalize() { + m_powers_of_two.finalize(); dealloc(g_mpq_manager); g_mpq_manager = 0; } diff --git a/src/util/rational.h b/src/util/rational.h index f0406f30a..fc03228bf 100644 --- a/src/util/rational.h +++ b/src/util/rational.h @@ -26,14 +26,13 @@ class rational { static rational m_zero; static rational m_one; static rational m_minus_one; - + static vector m_powers_of_two; static synch_mpq_manager * g_mpq_manager; - + static synch_mpq_manager & m() { return *g_mpq_manager; } public: static void initialize(); - static void finalize(); /* ADD_INITIALIZER('rational::initialize();') @@ -272,6 +271,8 @@ public: return result; } + static rational power_of_two(unsigned k); + bool is_power_of_two(unsigned & shift) { return m().is_power_of_two(m_val, shift); } diff --git a/src/util/scoped_timer.cpp b/src/util/scoped_timer.cpp index d475e5489..d0a79cec6 100644 --- a/src/util/scoped_timer.cpp +++ b/src/util/scoped_timer.cpp @@ -73,9 +73,6 @@ struct scoped_timer::imp { pthread_cond_t m_condition_var; #elif defined(_LINUX_) || defined(_FREEBSD_) // Linux & FreeBSD - static void * g_timer; - void (*m_old_handler)(int); - void * m_old_timer; timer_t m_timerid; #else // Other @@ -128,8 +125,9 @@ struct scoped_timer::imp { return st; } #elif defined(_LINUX_) || defined(_FREEBSD_) - static void sig_handler(int) { - static_cast(g_timer)->m_eh->operator()(); + static void sig_handler(union sigval s) { + void * ptr = s.sival_ptr; + static_cast(ptr)->m_eh->operator()(); } #else // Other @@ -156,23 +154,11 @@ struct scoped_timer::imp { throw default_exception("failed to start timer thread"); #elif defined(_LINUX_) || defined(_FREEBSD_) // Linux & FreeBSD - if (omp_in_parallel()) { - // It doesn't work in with more than one thread. - // SIGEV_SIGNAL: the event is handled by the process not by the thread that installed the handler. - // SIGEV_THREAD: the event is handled by a new thread (Z3 crashes with this configuration). - // - // It seems the way to go is SIGEV_SIGNAL, but I have to find a way to identify the thread the event is meant to. - return; - } - m_old_timer = g_timer; - g_timer = this; - m_old_handler = signal(SIG, sig_handler); - struct sigevent sev; memset(&sev, 0, sizeof(sigevent)); - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIG; - sev.sigev_value.sival_ptr = &m_timerid; + sev.sigev_notify = SIGEV_THREAD; + sev.sigev_value.sival_ptr = this; + sev.sigev_notify_function = sig_handler; if (timer_create(CLOCKID, &sev, &m_timerid) == -1) throw default_exception("failed to create timer"); @@ -182,6 +168,7 @@ struct scoped_timer::imp { its.it_value.tv_nsec = nano % 1000000000ull; its.it_interval.tv_sec = 0; // timer experies once its.it_interval.tv_nsec = 0; + if (timer_settime(m_timerid, 0, &its, NULL) == -1) throw default_exception("failed to set timer"); #else @@ -203,12 +190,7 @@ struct scoped_timer::imp { throw default_exception("failed to destroy pthread attributes object"); #elif defined(_LINUX_) || defined(_FREEBSD_) // Linux & FreeBSD - if (omp_in_parallel()) - return; // see comments in the constructor. timer_delete(m_timerid); - if (m_old_handler != SIG_ERR) - signal(SIG, m_old_handler); - g_timer = m_old_timer; #else // Other Platforms #endif @@ -216,16 +198,6 @@ struct scoped_timer::imp { }; -#if defined(_WINDOWS) || defined(_CYGWIN) -#elif defined(__APPLE__) && defined(__MACH__) -// Mac OS X -#elif defined(_LINUX_) || defined(_FREEBSD_) -// Linux & FreeBSD -void * scoped_timer::imp::g_timer = 0; -#else -// Other platforms -#endif - scoped_timer::scoped_timer(unsigned ms, event_handler * eh) { if (ms != UINT_MAX) m_imp = alloc(imp, ms, eh);