From 0e03fe9bf20859d4fc764e5e8ddc9c1bbec1ee4b Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Mon, 21 Nov 2016 00:05:59 +0000 Subject: [PATCH 01/47] Fix inconsistent emission of OCaml enumeration files. The ordering of emitted enum values is not consistent between python 2 or 3. The root cause of the problem was a dictionary's keys being iterated over which has no defined order. This has been fixed by iterating over the dictionary's items and ordering by values. We could order by key rather than the values but seeing as these represent an enum, ordering by value makes more sense. --- scripts/mk_util.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index 235453845..a5440946c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2986,21 +2986,22 @@ def mk_z3consts_ml(api_files): if m: name = words[1] if name not in DeprecatedEnums: + sorted_decls = sorted(decls.items(), key=lambda pair: pair[1]) efile.write('(** %s *)\n' % name[3:]) efile.write('type %s =\n' % name[3:]) # strip Z3_ - for k, i in decls.items(): + for k, i in sorted_decls: efile.write(' | %s \n' % k[3:]) # strip Z3_ efile.write('\n') efile.write('(** Convert %s to int*)\n' % name[3:]) efile.write('let int_of_%s x : int =\n' % (name[3:])) # strip Z3_ efile.write(' match x with\n') - for k, i in decls.items(): + for k, i in sorted_decls: efile.write(' | %s -> %d\n' % (k[3:], i)) efile.write('\n') efile.write('(** Convert int to %s*)\n' % name[3:]) efile.write('let %s_of_int x : %s =\n' % (name[3:],name[3:])) # strip Z3_ efile.write(' match x with\n') - for k, i in decls.items(): + for k, i in sorted_decls: efile.write(' | %d -> %s\n' % (i, k[3:])) # use Z3.Exception? efile.write(' | _ -> raise (Failure "undefined enum value")\n\n') @@ -3068,7 +3069,7 @@ def mk_z3consts_ml(api_files): # if name not in DeprecatedEnums: # efile.write('(** %s *)\n' % name[3:]) # efile.write('type %s =\n' % name[3:]) # strip Z3_ - # for k, i in decls.items(): + # for k, i in sorted(decls.items(), key=lambda pair: pair[1]): # efile.write(' | %s \n' % k[3:]) # strip Z3_ # efile.write('\n') # efile.write('(** Convert %s to int*)\n' % name[3:]) From 76bbecf4fe3232bbc67e7d1d06a6f9cdf5a8dc85 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Mon, 21 Nov 2016 00:45:43 +0000 Subject: [PATCH 02/47] Refactor `mk_z3consts_ml()` code into `mk_z3consts_ml_internal()` and move that into `mk_genfile_common.py`. Then adapt `mk_util.py` and `mk_consts_files.py` to call into the code at its new location. The purpose of this change is to have Python code common to the Python and CMake build systems separate from Python code that is only used for the Python build system. --- scripts/mk_consts_files.py | 10 ++ scripts/mk_genfile_common.py | 174 +++++++++++++++++++++++++++++++++++ scripts/mk_util.py | 168 ++------------------------------- 3 files changed, 190 insertions(+), 162 deletions(-) diff --git a/scripts/mk_consts_files.py b/scripts/mk_consts_files.py index e582d8468..d0502c19d 100755 --- a/scripts/mk_consts_files.py +++ b/scripts/mk_consts_files.py @@ -22,6 +22,7 @@ def main(args): dest="java_package_name", default=None, help="Name to give the Java package (e.g. ``com.microsoft.z3``).") + parser.add_argument("--ml-output-dir", dest="ml_output_dir", default=None) pargs = parser.parse_args(args) if not mk_genfile_common.check_files_exist(pargs.api_files): @@ -60,6 +61,15 @@ def main(args): logging.info('Generated "{}"'.format(generated_file)) count += 1 + if pargs.ml_output_dir: + if not mk_genfile_common.check_dir_exists(pargs.ml_output_dir): + return 1 + output = mk_genfile_common.mk_z3consts_ml_internal( + pargs.api_files, + pargs.ml_output_dir) + logging.info('Generated "{}"'.format(output)) + count += 1 + if count == 0: logging.info('No files generated. You need to specific an output directory' ' for the relevant langauge bindings') diff --git a/scripts/mk_genfile_common.py b/scripts/mk_genfile_common.py index 7e7cb5584..98346f99f 100644 --- a/scripts/mk_genfile_common.py +++ b/scripts/mk_genfile_common.py @@ -376,6 +376,180 @@ def mk_z3consts_java_internal(api_files, package_name, output_dir): api.close() return generated_enumeration_files +# Extract enumeration types from z3_api.h, and add ML definitions +def mk_z3consts_ml_internal(api_files, output_dir): + """ + Generate ``z3enums.ml`` from the list of API header files + in ``api_files`` and write the output file into + the ``output_dir`` directory + + Returns the path to the generated file. + """ + assert os.path.isdir(output_dir) + assert isinstance(api_files, list) + blank_pat = re.compile("^ *$") + comment_pat = re.compile("^ *//.*$") + typedef_pat = re.compile("typedef enum *") + typedef2_pat = re.compile("typedef enum { *") + openbrace_pat = re.compile("{ *") + closebrace_pat = re.compile("}.*;") + + + DeprecatedEnums = [ 'Z3_search_failure' ] + if not os.path.exists(output_dir): + os.mkdir(output_dir) + + efile = open('%s.ml' % os.path.join(output_dir, "z3enums"), 'w') + z3consts_output_path = efile.name + efile.write('(* Automatically generated file *)\n\n') + efile.write('(** The enumeration types of Z3. *)\n\n') + for api_file in api_files: + api = open(api_file, 'r') + + SEARCHING = 0 + FOUND_ENUM = 1 + IN_ENUM = 2 + + mode = SEARCHING + decls = {} + idx = 0 + + linenum = 1 + for line in api: + m1 = blank_pat.match(line) + m2 = comment_pat.match(line) + if m1 or m2: + # skip blank lines and comments + linenum = linenum + 1 + elif mode == SEARCHING: + m = typedef_pat.match(line) + if m: + mode = FOUND_ENUM + m = typedef2_pat.match(line) + if m: + mode = IN_ENUM + decls = {} + idx = 0 + elif mode == FOUND_ENUM: + m = openbrace_pat.match(line) + if m: + mode = IN_ENUM + decls = {} + idx = 0 + else: + assert False, "Invalid %s, line: %s" % (api_file, linenum) + else: + assert mode == IN_ENUM + words = re.split('[^\-a-zA-Z0-9_]+', line) + m = closebrace_pat.match(line) + if m: + name = words[1] + if name not in DeprecatedEnums: + sorted_decls = sorted(decls.items(), key=lambda pair: pair[1]) + efile.write('(** %s *)\n' % name[3:]) + efile.write('type %s =\n' % name[3:]) # strip Z3_ + for k, i in sorted_decls: + efile.write(' | %s \n' % k[3:]) # strip Z3_ + efile.write('\n') + efile.write('(** Convert %s to int*)\n' % name[3:]) + efile.write('let int_of_%s x : int =\n' % (name[3:])) # strip Z3_ + efile.write(' match x with\n') + for k, i in sorted_decls: + efile.write(' | %s -> %d\n' % (k[3:], i)) + efile.write('\n') + efile.write('(** Convert int to %s*)\n' % name[3:]) + efile.write('let %s_of_int x : %s =\n' % (name[3:],name[3:])) # strip Z3_ + efile.write(' match x with\n') + for k, i in sorted_decls: + efile.write(' | %d -> %s\n' % (i, k[3:])) + # use Z3.Exception? + efile.write(' | _ -> raise (Failure "undefined enum value")\n\n') + mode = SEARCHING + else: + if words[2] != '': + if len(words[2]) > 1 and words[2][1] == 'x': + idx = int(words[2], 16) + else: + idx = int(words[2]) + decls[words[1]] = idx + idx = idx + 1 + linenum = linenum + 1 + api.close() + efile.close() + return z3consts_output_path + # efile = open('%s.mli' % os.path.join(gendir, "z3enums"), 'w') + # efile.write('(* Automatically generated file *)\n\n') + # efile.write('(** The enumeration types of Z3. *)\n\n') + # for api_file in api_files: + # api_file_c = ml.find_file(api_file, ml.name) + # api_file = os.path.join(api_file_c.src_dir, api_file) + + # api = open(api_file, 'r') + + # SEARCHING = 0 + # FOUND_ENUM = 1 + # IN_ENUM = 2 + + # mode = SEARCHING + # decls = {} + # idx = 0 + + # linenum = 1 + # for line in api: + # m1 = blank_pat.match(line) + # m2 = comment_pat.match(line) + # if m1 or m2: + # # skip blank lines and comments + # linenum = linenum + 1 + # elif mode == SEARCHING: + # m = typedef_pat.match(line) + # if m: + # mode = FOUND_ENUM + # m = typedef2_pat.match(line) + # if m: + # mode = IN_ENUM + # decls = {} + # idx = 0 + # elif mode == FOUND_ENUM: + # m = openbrace_pat.match(line) + # if m: + # mode = IN_ENUM + # decls = {} + # idx = 0 + # else: + # assert False, "Invalid %s, line: %s" % (api_file, linenum) + # else: + # assert mode == IN_ENUM + # words = re.split('[^\-a-zA-Z0-9_]+', line) + # m = closebrace_pat.match(line) + # if m: + # name = words[1] + # if name not in DeprecatedEnums: + # efile.write('(** %s *)\n' % name[3:]) + # efile.write('type %s =\n' % name[3:]) # strip Z3_ + # for k, i in sorted(decls.items(), key=lambda pair: pair[1]): + # efile.write(' | %s \n' % k[3:]) # strip Z3_ + # efile.write('\n') + # efile.write('(** Convert %s to int*)\n' % name[3:]) + # efile.write('val int_of_%s : %s -> int\n' % (name[3:], name[3:])) # strip Z3_ + # efile.write('(** Convert int to %s*)\n' % name[3:]) + # efile.write('val %s_of_int : int -> %s\n' % (name[3:],name[3:])) # strip Z3_ + # efile.write('\n') + # mode = SEARCHING + # else: + # if words[2] != '': + # if len(words[2]) > 1 and words[2][1] == 'x': + # idx = int(words[2], 16) + # else: + # idx = int(words[2]) + # decls[words[1]] = idx + # idx = idx + 1 + # linenum = linenum + 1 + # api.close() + # efile.close() + # if VERBOSE: + # print ('Generated "%s/z3enums.mli"' % ('%s' % gendir)) + ############################################################################### # Functions for generating a "module definition file" for MSVC diff --git a/scripts/mk_util.py b/scripts/mk_util.py index a5440946c..d644b269c 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2924,173 +2924,17 @@ def mk_z3consts_java(api_files): # Extract enumeration types from z3_api.h, and add ML definitions def mk_z3consts_ml(api_files): - blank_pat = re.compile("^ *$") - comment_pat = re.compile("^ *//.*$") - typedef_pat = re.compile("typedef enum *") - typedef2_pat = re.compile("typedef enum { *") - openbrace_pat = re.compile("{ *") - closebrace_pat = re.compile("}.*;") - ml = get_component(ML_COMPONENT) - - DeprecatedEnums = [ 'Z3_search_failure' ] - gendir = ml.src_dir - if not os.path.exists(gendir): - os.mkdir(gendir) - - efile = open('%s.ml' % os.path.join(gendir, "z3enums"), 'w') - efile.write('(* Automatically generated file *)\n\n') - efile.write('(** The enumeration types of Z3. *)\n\n') + full_path_api_files = [] for api_file in api_files: api_file_c = ml.find_file(api_file, ml.name) api_file = os.path.join(api_file_c.src_dir, api_file) - - api = open(api_file, 'r') - - SEARCHING = 0 - FOUND_ENUM = 1 - IN_ENUM = 2 - - mode = SEARCHING - decls = {} - idx = 0 - - linenum = 1 - for line in api: - m1 = blank_pat.match(line) - m2 = comment_pat.match(line) - if m1 or m2: - # skip blank lines and comments - linenum = linenum + 1 - elif mode == SEARCHING: - m = typedef_pat.match(line) - if m: - mode = FOUND_ENUM - m = typedef2_pat.match(line) - if m: - mode = IN_ENUM - decls = {} - idx = 0 - elif mode == FOUND_ENUM: - m = openbrace_pat.match(line) - if m: - mode = IN_ENUM - decls = {} - idx = 0 - else: - assert False, "Invalid %s, line: %s" % (api_file, linenum) - else: - assert mode == IN_ENUM - words = re.split('[^\-a-zA-Z0-9_]+', line) - m = closebrace_pat.match(line) - if m: - name = words[1] - if name not in DeprecatedEnums: - sorted_decls = sorted(decls.items(), key=lambda pair: pair[1]) - efile.write('(** %s *)\n' % name[3:]) - efile.write('type %s =\n' % name[3:]) # strip Z3_ - for k, i in sorted_decls: - efile.write(' | %s \n' % k[3:]) # strip Z3_ - efile.write('\n') - efile.write('(** Convert %s to int*)\n' % name[3:]) - efile.write('let int_of_%s x : int =\n' % (name[3:])) # strip Z3_ - efile.write(' match x with\n') - for k, i in sorted_decls: - efile.write(' | %s -> %d\n' % (k[3:], i)) - efile.write('\n') - efile.write('(** Convert int to %s*)\n' % name[3:]) - efile.write('let %s_of_int x : %s =\n' % (name[3:],name[3:])) # strip Z3_ - efile.write(' match x with\n') - for k, i in sorted_decls: - efile.write(' | %d -> %s\n' % (i, k[3:])) - # use Z3.Exception? - efile.write(' | _ -> raise (Failure "undefined enum value")\n\n') - mode = SEARCHING - else: - if words[2] != '': - if len(words[2]) > 1 and words[2][1] == 'x': - idx = int(words[2], 16) - else: - idx = int(words[2]) - decls[words[1]] = idx - idx = idx + 1 - linenum = linenum + 1 - api.close() - efile.close() + full_path_api_files.append(api_file) + generated_file = mk_genfile_common.mk_z3consts_ml_internal( + full_path_api_files, + ml.src_dir) if VERBOSE: - print ('Generated "%s/z3enums.ml"' % ('%s' % gendir)) - # efile = open('%s.mli' % os.path.join(gendir, "z3enums"), 'w') - # efile.write('(* Automatically generated file *)\n\n') - # efile.write('(** The enumeration types of Z3. *)\n\n') - # for api_file in api_files: - # api_file_c = ml.find_file(api_file, ml.name) - # api_file = os.path.join(api_file_c.src_dir, api_file) - - # api = open(api_file, 'r') - - # SEARCHING = 0 - # FOUND_ENUM = 1 - # IN_ENUM = 2 - - # mode = SEARCHING - # decls = {} - # idx = 0 - - # linenum = 1 - # for line in api: - # m1 = blank_pat.match(line) - # m2 = comment_pat.match(line) - # if m1 or m2: - # # skip blank lines and comments - # linenum = linenum + 1 - # elif mode == SEARCHING: - # m = typedef_pat.match(line) - # if m: - # mode = FOUND_ENUM - # m = typedef2_pat.match(line) - # if m: - # mode = IN_ENUM - # decls = {} - # idx = 0 - # elif mode == FOUND_ENUM: - # m = openbrace_pat.match(line) - # if m: - # mode = IN_ENUM - # decls = {} - # idx = 0 - # else: - # assert False, "Invalid %s, line: %s" % (api_file, linenum) - # else: - # assert mode == IN_ENUM - # words = re.split('[^\-a-zA-Z0-9_]+', line) - # m = closebrace_pat.match(line) - # if m: - # name = words[1] - # if name not in DeprecatedEnums: - # efile.write('(** %s *)\n' % name[3:]) - # efile.write('type %s =\n' % name[3:]) # strip Z3_ - # for k, i in sorted(decls.items(), key=lambda pair: pair[1]): - # efile.write(' | %s \n' % k[3:]) # strip Z3_ - # efile.write('\n') - # efile.write('(** Convert %s to int*)\n' % name[3:]) - # efile.write('val int_of_%s : %s -> int\n' % (name[3:], name[3:])) # strip Z3_ - # efile.write('(** Convert int to %s*)\n' % name[3:]) - # efile.write('val %s_of_int : int -> %s\n' % (name[3:],name[3:])) # strip Z3_ - # efile.write('\n') - # mode = SEARCHING - # else: - # if words[2] != '': - # if len(words[2]) > 1 and words[2][1] == 'x': - # idx = int(words[2], 16) - # else: - # idx = int(words[2]) - # decls[words[1]] = idx - # idx = idx + 1 - # linenum = linenum + 1 - # api.close() - # efile.close() - # if VERBOSE: - # print ('Generated "%s/z3enums.mli"' % ('%s' % gendir)) + print ('Generated "%s"' % generated_file) def mk_gui_str(id): return '4D2F40D8-E5F9-473B-B548-%012d' % id From 2e74a2c54e5935cdd1c8678d3a0641e7132da023 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Mon, 21 Nov 2016 01:04:55 +0000 Subject: [PATCH 03/47] Refactor `update_api.mk_ml()` so that the source and output directories can be different. This feature will be needed by the CMake build system to build the OCaml bindings. --- scripts/mk_util.py | 3 ++- scripts/update_api.py | 32 ++++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index d644b269c..fd8962bda 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2870,7 +2870,8 @@ def mk_bindings(api_files): dotnet_output_dir=dotnet_output_dir, java_output_dir=java_output_dir, java_package_name=java_package_name, - ml_output_dir=ml_output_dir + ml_output_dir=ml_output_dir, + ml_src_dir=ml_output_dir ) cp_z3py_to_build() if is_ml_enabled(): diff --git a/scripts/update_api.py b/scripts/update_api.py index 3a3b2c40a..e531a103c 100755 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1195,13 +1195,13 @@ def ml_alloc_and_store(t, lhs, rhs): alloc_str = '%s = caml_alloc_custom(&%s, sizeof(%s), 0, 1); ' % (lhs, pops, pts) return alloc_str + ml_set_wrap(t, lhs, rhs) -def mk_ml(ml_dir): +def mk_ml(ml_src_dir, ml_output_dir): global Type2Str - ml_nativef = os.path.join(ml_dir, 'z3native.ml') + ml_nativef = os.path.join(ml_output_dir, 'z3native.ml') ml_native = open(ml_nativef, 'w') ml_native.write('(* Automatically generated file *)\n\n') - ml_pref = open(os.path.join(ml_dir, 'z3native.ml.pre'), 'r') + ml_pref = open(os.path.join(ml_src_dir, 'z3native.ml.pre'), 'r') for s in ml_pref: ml_native.write(s); ml_pref.close() @@ -1250,14 +1250,14 @@ def mk_ml(ml_dir): if mk_util.is_verbose(): print ('Generated "%s"' % ml_nativef) - mk_z3native_stubs_c(ml_dir) + mk_z3native_stubs_c(ml_src_dir, ml_output_dir) -def mk_z3native_stubs_c(ml_dir): # C interface - ml_wrapperf = os.path.join(ml_dir, 'z3native_stubs.c') +def mk_z3native_stubs_c(ml_src_dir, ml_output_dir): # C interface + ml_wrapperf = os.path.join(ml_output_dir, 'z3native_stubs.c') ml_wrapper = open(ml_wrapperf, 'w') ml_wrapper.write('// Automatically generated file\n\n') - ml_pref = open(os.path.join(ml_dir, 'z3native_stubs.c.pre'), 'r') + ml_pref = open(os.path.join(ml_src_dir, 'z3native_stubs.c.pre'), 'r') for s in ml_pref: ml_wrapper.write(s); ml_pref.close() @@ -1666,7 +1666,8 @@ def generate_files(api_files, dotnet_output_dir=None, java_output_dir=None, java_package_name=None, - ml_output_dir=None): + ml_output_dir=None, + ml_src_dir=None): """ Scan the api files in ``api_files`` and emit the relevant API files into the output directories specified. If an output directory is set to ``None`` @@ -1741,7 +1742,8 @@ def generate_files(api_files, mk_java(java_output_dir, java_package_name) if ml_output_dir: - mk_ml(ml_output_dir) + assert not ml_src_dir is None + mk_ml(ml_src_dir, ml_output_dir) def main(args): logging.basicConfig(level=logging.INFO) @@ -1768,6 +1770,10 @@ def main(args): dest="java_package_name", default=None, help="Name to give the Java package (e.g. ``com.microsoft.z3``).") + parser.add_argument("--ml-src-dir", + dest="ml_src_dir", + default=None, + help="Directory containing OCaml source files. If not specified no files are emitted") parser.add_argument("--ml-output-dir", dest="ml_output_dir", default=None, @@ -1779,6 +1785,11 @@ def main(args): logging.error('--java-package-name must be specified') return 1 + if pargs.ml_output_dir: + if pargs.ml_src_dir is None: + logging.error('--ml-src-dir must be specified') + return 1 + for api_file in pargs.api_files: if not os.path.exists(api_file): logging.error('"{}" does not exist'.format(api_file)) @@ -1790,7 +1801,8 @@ def main(args): dotnet_output_dir=pargs.dotnet_output_dir, java_output_dir=pargs.java_output_dir, java_package_name=pargs.java_package_name, - ml_output_dir=pargs.ml_output_dir) + ml_output_dir=pargs.ml_output_dir, + ml_src_dir=pargs.ml_src_dir) return 0 if __name__ == '__main__': From 1eec0799ca75825918f00407b454ee6507d415c3 Mon Sep 17 00:00:00 2001 From: Andrew Dutcher Date: Thu, 22 Dec 2016 14:26:41 -0800 Subject: [PATCH 04/47] Add -fpic to armv7/armv8 build --- scripts/mk_util.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/mk_util.py b/scripts/mk_util.py index cdd7bdeec..8b97909f6 100644 --- a/scripts/mk_util.py +++ b/scripts/mk_util.py @@ -2441,7 +2441,7 @@ def mk_config(): CXXFLAGS = '%s -O3 -D _EXTERNAL_RELEASE -fomit-frame-pointer' % CXXFLAGS if is_CXX_clangpp(): CXXFLAGS = '%s -Wno-unknown-pragmas -Wno-overloaded-virtual -Wno-unused-value' % CXXFLAGS - sysname = os.uname()[0] + sysname, _, _, _, machine = os.uname() if sysname == 'Darwin': SO_EXT = '.dylib' SLIBFLAGS = '-dynamiclib' @@ -2492,7 +2492,9 @@ def mk_config(): # and to make it create an import library. SLIBEXTRAFLAGS = '%s -static-libgcc -static-libstdc++ -Wl,--out-implib,libz3.dll.a' % SLIBEXTRAFLAGS LDFLAGS = '%s -static-libgcc -static-libstdc++' % LDFLAGS - + if sysname == 'Linux' and machine.startswith('armv7') or machine.startswith('armv8'): + CXXFLAGS = '%s -fpic' % CXXFLAGS + config.write('PREFIX=%s\n' % PREFIX) config.write('CC=%s\n' % CC) config.write('CXX=%s\n' % CXX) From a4d5c4a00a06045ac2d960d19aa9aea156d78ca4 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 30 Dec 2016 18:05:19 -0800 Subject: [PATCH 05/47] make get_consequence call skip check-sat if a model is already there Signed-off-by: Nikolaj Bjorner --- src/sat/sat_solver.cpp | 14 +++++++++++++- src/sat/sat_solver/inc_sat_solver.cpp | 2 +- src/smt/theory_pb.cpp | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index a5c9005df..8a75e8dfc 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -123,6 +123,7 @@ namespace sat { // ----------------------- bool_var solver::mk_var(bool ext, bool dvar) { + m_model_is_current = false; m_stats.m_mk_var++; bool_var v = m_level.size(); m_watches.push_back(watch_list()); @@ -148,6 +149,7 @@ namespace sat { } void solver::mk_clause(unsigned num_lits, literal * lits) { + m_model_is_current = false; DEBUG_CODE({ for (unsigned i = 0; i < num_lits; i++) SASSERT(m_eliminated[lits[i].var()] == false); @@ -3118,7 +3120,11 @@ namespace sat { lbool solver::get_consequences(literal_vector const& asms, bool_var_vector const& vars, vector& conseq) { literal_vector lits; - lbool is_sat = check(asms.size(), asms.c_ptr()); + lbool is_sat = l_true; + + if (!m_model_is_current) { + is_sat = check(asms.size(), asms.c_ptr()); + } if (is_sat != l_true) { return is_sat; } @@ -3212,6 +3218,12 @@ namespace sat { << " unfixed: " << lits.size() - conseq.size() - vars.size() << ")\n";); + if (!vars.empty() && + m_config.m_restart_max != 0 && + m_config.m_restart_max <= num_iterations) { + return l_undef; + } + } return l_true; } diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index e3a220cd2..6d3a5b552 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -257,7 +257,7 @@ public: r = internalize_vars(vars, bvars); r = m_solver.get_consequences(m_asms, bvars, lconseq); - if (r != l_true) return r; + if (r == l_false) return r; // build map from bound variables to // the consequences that cover them. diff --git a/src/smt/theory_pb.cpp b/src/smt/theory_pb.cpp index 1885fc9c4..507cb6d43 100644 --- a/src/smt/theory_pb.cpp +++ b/src/smt/theory_pb.cpp @@ -1752,7 +1752,7 @@ namespace smt { // verbose_stream() << "(pb.conflict min size: " << l_size << ")\n"; // s_min_l_size = l_size; //} - //IF_VERBOSE(1, verbose_stream() << "(pb.conflict " << m_ineq_literals.size() << " " << m_lemma.size() << "\n";); + IF_VERBOSE(1, verbose_stream() << "(pb.conflict " << m_ineq_literals.size() << " " << m_lemma.size() << ")\n";); switch(is_true) { case l_true: UNREACHABLE(); From 74d3de01b3ef16d59d316c84b49f30a3e4a683b2 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 2 Jan 2017 10:07:02 -0800 Subject: [PATCH 06/47] enable incremental consequence finding with restart timeout Signed-off-by: Nikolaj Bjorner --- src/sat/sat_params.pyg | 2 +- src/sat/sat_solver.cpp | 146 ++++++++++++++++++++++---- src/sat/sat_solver.h | 12 ++- src/sat/sat_solver/inc_sat_solver.cpp | 11 +- 4 files changed, 141 insertions(+), 30 deletions(-) diff --git a/src/sat/sat_params.pyg b/src/sat/sat_params.pyg index 80e6f403f..de1759486 100644 --- a/src/sat/sat_params.pyg +++ b/src/sat/sat_params.pyg @@ -7,7 +7,7 @@ def_module_params('sat', ('phase.caching.off', UINT, 100, 'phase caching off period (in number of conflicts)'), ('restart', SYMBOL, 'luby', 'restart strategy: luby or geometric'), ('restart.initial', UINT, 100, 'initial restart (number of conflicts)'), - ('restart.max', UINT, 0, 'maximal number of restarts. Ignored if set to 0'), + ('restart.max', UINT, UINT_MAX, 'maximal number of restarts.'), ('restart.factor', DOUBLE, 1.5, 'restart increment factor for geometric strategy'), ('random_freq', DOUBLE, 0.01, 'frequency of random case splits'), ('random_seed', UINT, 0, 'random seed'), diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index 8a75e8dfc..5c004b1a2 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -768,7 +768,7 @@ namespace sat { if (check_inconsistent()) return l_false; gc(); - if (m_config.m_restart_max != 0 && m_config.m_restart_max <= m_restarts) { + if (m_config.m_restart_max <= m_restarts) { IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "(sat \"abort: max-restarts\")\n";); return l_undef; } @@ -3122,6 +3122,9 @@ namespace sat { literal_vector lits; lbool is_sat = l_true; + if (m_config.m_restart_max != UINT_MAX && !m_model_is_current) { + return get_bounded_consequences(asms, vars, conseq); + } if (!m_model_is_current) { is_sat = check(asms.size(), asms.c_ptr()); } @@ -3142,9 +3145,89 @@ namespace sat { return is_sat; } + void solver::fixup_consequence_core() { + index_set s; + for (unsigned i = 0; i < m_core.size(); ++i) { + s |= m_antecedents.find(m_core[i].var()); + } + m_core.reset(); + index_set::iterator it = s.begin(), end = s.end(); + for (; it != end; ++it) { + m_core.push_back(to_literal(*it)); + } + } + + + lbool solver::get_bounded_consequences(literal_vector const& asms, bool_var_vector const& vars, vector& conseq) { + bool_var_set unfixed_vars; + unsigned num_units = 0, num_iterations = 0; + for (unsigned i = 0; i < vars.size(); ++i) { + unfixed_vars.insert(vars[i]); + } + m_antecedents.reset(); + pop_to_base_level(); + if (inconsistent()) return l_false; + init_search(); + propagate(false); + if (inconsistent()) return l_false; + if (asms.empty()) { + bool_var v = mk_var(true, false); + literal lit(v, false); + init_assumptions(1, &lit, 0, 0); + } + else { + init_assumptions(asms.size(), asms.c_ptr(), 0, 0); + } + propagate(false); + if (check_inconsistent()) return l_false; + + extract_fixed_consequences(num_units, asms, unfixed_vars, conseq); + + simplify_problem(); + if (check_inconsistent()) { + fixup_consequence_core(); + return l_false; + } + + while (true) { + ++num_iterations; + SASSERT(!inconsistent()); + + lbool r = bounded_search(); + if (r != l_undef) { + fixup_consequence_core(); + return r; + } + + extract_fixed_consequences(num_units, asms, unfixed_vars, conseq); + + if (m_conflicts > m_config.m_max_conflicts) { + IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "(sat \"abort: max-conflicts = " << m_conflicts << "\")\n";); + return l_undef; + } + + restart(); + simplify_problem(); + if (check_inconsistent()) { + fixup_consequence_core(); + return l_false; + } + gc(); + + if (m_config.m_restart_max <= num_iterations) { + IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "(sat \"abort: max-restarts\")\n";); + return l_undef; + } + } + } + lbool solver::get_consequences(literal_vector const& asms, literal_vector const& lits, vector& conseq) { m_antecedents.reset(); - literal_set vars(lits), assumptions(asms); + literal_set unfixed_lits(lits), assumptions(asms); + bool_var_set unfixed_vars; + for (unsigned i = 0; i < lits.size(); ++i) { + unfixed_vars.insert(lits[i].var()); + } pop_to_base_level(); if (inconsistent()) return l_false; @@ -3163,11 +3246,15 @@ namespace sat { if (check_inconsistent()) return l_false; unsigned num_units = 0, num_iterations = 0; - extract_fixed_consequences(num_units, assumptions, vars, conseq); - while (!vars.empty()) { + extract_fixed_consequences(num_units, assumptions, unfixed_vars, conseq); + update_unfixed_literals(unfixed_lits, unfixed_vars); + while (!unfixed_lits.empty()) { + if (scope_lvl() > 1) { + pop(scope_lvl() - 1); + } ++num_iterations; checkpoint(); - literal_set::iterator it = vars.begin(), end = vars.end(); + literal_set::iterator it = unfixed_lits.begin(), end = unfixed_lits.end(); unsigned num_resolves = 0; lbool is_sat = l_true; for (; it != end; ++it) { @@ -3208,45 +3295,58 @@ namespace sat { m_inconsistent = false; } if (is_sat == l_true) { - delete_unfixed(vars); + delete_unfixed(unfixed_lits, unfixed_vars); } - extract_fixed_consequences(num_units, assumptions, vars, conseq); + extract_fixed_consequences(num_units, assumptions, unfixed_vars, conseq); + update_unfixed_literals(unfixed_lits, unfixed_vars); IF_VERBOSE(1, verbose_stream() << "(sat.get-consequences" << " iterations: " << num_iterations - << " variables: " << vars.size() + << " variables: " << unfixed_lits.size() << " fixed: " << conseq.size() - << " unfixed: " << lits.size() - conseq.size() - vars.size() + << " unfixed: " << lits.size() - conseq.size() - unfixed_lits.size() << ")\n";); - if (!vars.empty() && - m_config.m_restart_max != 0 && - m_config.m_restart_max <= num_iterations) { + if (!unfixed_lits.empty() && m_config.m_restart_max <= num_iterations) { return l_undef; } - } return l_true; } - void solver::delete_unfixed(literal_set& unfixed) { + void solver::delete_unfixed(literal_set& unfixed_lits, bool_var_set& unfixed_vars) { literal_set to_keep; - literal_set::iterator it = unfixed.begin(), end = unfixed.end(); + literal_set::iterator it = unfixed_lits.begin(), end = unfixed_lits.end(); for (; it != end; ++it) { literal lit = *it; if (value(lit) == l_true) { to_keep.insert(lit); } + else { + unfixed_vars.remove(lit.var()); + } } - unfixed = to_keep; + unfixed_lits = to_keep; } - void solver::extract_fixed_consequences(unsigned& start, literal_set const& assumptions, literal_set& unfixed, vector& conseq) { - if (scope_lvl() > 1) { - pop(scope_lvl() - 1); + void solver::update_unfixed_literals(literal_set& unfixed_lits, bool_var_set& unfixed_vars) { + literal_vector to_delete; + literal_set::iterator it = unfixed_lits.begin(), end = unfixed_lits.end(); + for (; it != end; ++it) { + literal lit = *it; + if (!unfixed_vars.contains(lit.var())) { + to_delete.push_back(lit); + } } + for (unsigned i = 0; i < to_delete.size(); ++i) { + unfixed_lits.remove(to_delete[i]); + } + } + + + void solver::extract_fixed_consequences(unsigned& start, literal_set const& assumptions, bool_var_set& unfixed, vector& conseq) { SASSERT(!inconsistent()); unsigned sz = m_trail.size(); - for (unsigned i = start; i < sz; ++i) { + for (unsigned i = start; i < sz && lvl(m_trail[i]) <= 1; ++i) { extract_fixed_consequences(m_trail[i], assumptions, unfixed, conseq); } start = sz; @@ -3288,7 +3388,7 @@ namespace sat { } } - void solver::extract_fixed_consequences(literal lit, literal_set const& assumptions, literal_set& unfixed, vector& conseq) { + void solver::extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector& conseq) { index_set s; if (assumptions.contains(lit)) { s.insert(lit.index()); @@ -3298,14 +3398,14 @@ namespace sat { extract_assumptions(lit, s); } m_antecedents.insert(lit.var(), s); - if (unfixed.contains(lit)) { + if (unfixed.contains(lit.var())) { literal_vector cons; cons.push_back(lit); index_set::iterator it = s.begin(), end = s.end(); for (; it != end; ++it) { cons.push_back(to_literal(*it)); } - unfixed.remove(lit); + unfixed.remove(lit.var()); conseq.push_back(cons); } } diff --git a/src/sat/sat_solver.h b/src/sat/sat_solver.h index aa45a1043..a9037c65a 100644 --- a/src/sat/sat_solver.h +++ b/src/sat/sat_solver.h @@ -457,11 +457,17 @@ namespace sat { lbool get_consequences(literal_vector const& assms, literal_vector const& lits, vector& conseq); - void delete_unfixed(literal_set& unfixed); + lbool get_bounded_consequences(literal_vector const& assms, bool_var_vector const& vars, vector& conseq); - void extract_fixed_consequences(unsigned& start, literal_set const& assumptions, literal_set& unfixed, vector& conseq); + void delete_unfixed(literal_set& unfixed_lits, bool_var_set& unfixed_vars); - void extract_fixed_consequences(literal lit, literal_set const& assumptions, literal_set& unfixed, vector& conseq); + void extract_fixed_consequences(unsigned& start, literal_set const& assumptions, bool_var_set& unfixed, vector& conseq); + + void extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector& conseq); + + void update_unfixed_literals(literal_set& unfixed_lits, bool_var_set& unfixed_vars); + + void fixup_consequence_core(); // ----------------------- // diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index 6d3a5b552..b7ce92108 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -252,12 +252,17 @@ public: m_solver.pop_to_base_level(); lbool r = internalize_formulas(); if (r != l_true) return r; + r = internalize_vars(vars, bvars); + if (r != l_true) return r; r = internalize_assumptions(assumptions.size(), assumptions.c_ptr(), dep2asm); if (r != l_true) return r; - r = internalize_vars(vars, bvars); - r = m_solver.get_consequences(m_asms, bvars, lconseq); - if (r == l_false) return r; + if (r == l_false) { + if (!m_asms.empty()) { + extract_core(dep2asm); + } + return r; + } // build map from bound variables to // the consequences that cover them. From cb75a55095bc33cce8da48d9f80910e36f90c3d8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 3 Jan 2017 13:41:08 +0000 Subject: [PATCH 07/47] Fixed initialization order warning. --- src/sat/sat_config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sat/sat_config.cpp b/src/sat/sat_config.cpp index 58505f8ac..7e0a7c50c 100644 --- a/src/sat/sat_config.cpp +++ b/src/sat/sat_config.cpp @@ -23,10 +23,10 @@ Revision History: namespace sat { config::config(params_ref const & p): + m_restart_max(0), m_always_true("always_true"), m_always_false("always_false"), m_caching("caching"), - m_restart_max(0), m_random("random"), m_geometric("geometric"), m_luby("luby"), From ae9a3bfc241ce9490d74aa8af4916195deadfe81 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 4 Jan 2017 09:14:09 -0800 Subject: [PATCH 08/47] add operator for issue #860 Signed-off-by: Nikolaj Bjorner --- src/api/api_ast.cpp | 3 ++- src/api/dotnet/Solver.cs | 9 +++++++++ src/api/z3_api.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index efa3ec098..08a931fdc 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -1063,9 +1063,10 @@ extern "C" { case OP_BV2INT: return Z3_OP_BV2INT; case OP_CARRY: return Z3_OP_CARRY; case OP_XOR3: return Z3_OP_XOR3; + case OP_BIT2BOOL: return Z3_OP_BIT2BOOL; case OP_BSMUL_NO_OVFL: return Z3_OP_BSMUL_NO_OVFL; case OP_BUMUL_NO_OVFL: return Z3_OP_BUMUL_NO_OVFL; - case OP_BSMUL_NO_UDFL: return Z3_OP_BSMUL_NO_UDFL; + case OP_BSMUL_NO_UDFL: return Z3_OP_BSMUL_NO_UDFL; case OP_BSDIV_I: return Z3_OP_BSDIV_I; case OP_BUDIV_I: return Z3_OP_BUDIV_I; case OP_BSREM_I: return Z3_OP_BSREM_I; diff --git a/src/api/dotnet/Solver.cs b/src/api/dotnet/Solver.cs index 8cb7670d7..dff2677df 100644 --- a/src/api/dotnet/Solver.cs +++ b/src/api/dotnet/Solver.cs @@ -18,6 +18,7 @@ Notes: --*/ using System; +using System.Linq; using System.Collections.Generic; using System.Diagnostics.Contracts; @@ -126,6 +127,14 @@ namespace Microsoft.Z3 Assert(constraints); } + /// + /// Alias for Assert. + /// + public void Add(IEnumerable constraints) + { + Assert(constraints.ToArray()); + } + /// /// Assert multiple constraints into the solver, and track them (in the unsat) core /// using the Boolean constants in ps. diff --git a/src/api/z3_api.h b/src/api/z3_api.h index 356f933d4..b80ce3177 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -1060,6 +1060,7 @@ typedef enum { Z3_OP_EXT_ROTATE_LEFT, Z3_OP_EXT_ROTATE_RIGHT, + Z3_OP_BIT2BOOL, Z3_OP_INT2BV, Z3_OP_BV2INT, Z3_OP_CARRY, From ddf4bc548f9ae50c849ff2a50ba9466525193f1e Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Wed, 4 Jan 2017 19:04:43 -0800 Subject: [PATCH 09/47] allow disabling exceptions from C++. Issue #861 Signed-off-by: Nikolaj Bjorner --- src/api/c++/z3++.h | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index 86dc77ad5..3f1ed614f 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -132,16 +132,19 @@ namespace z3 { \brief A Context manages all other Z3 objects, global configuration options, etc. */ class context { + bool m_enable_exceptions; Z3_context m_ctx; static void error_handler(Z3_context /*c*/, Z3_error_code /*e*/) { /* do nothing */ } void init(config & c) { m_ctx = Z3_mk_context_rc(c); + m_enable_exceptions = true; Z3_set_error_handler(m_ctx, error_handler); Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT); } void init_interp(config & c) { m_ctx = Z3_mk_interpolation_context(c); + m_enable_exceptions = true; Z3_set_error_handler(m_ctx, error_handler); Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT); } @@ -159,12 +162,24 @@ namespace z3 { /** \brief Auxiliary method used to check for API usage errors. */ - void check_error() const { + Z3_error_code check_error() const { Z3_error_code e = Z3_get_error_code(m_ctx); - if (e != Z3_OK) + if (e != Z3_OK && enable_exceptions()) throw exception(Z3_get_error_msg(m_ctx, e)); + return e; } + /** + \brief The C++ API uses by defaults exceptions on errors. + For applications that don't work well with exceptions (there should be only few) + you have the ability to turn off exceptions. The tradeoffs are that applications + have to very careful about using check_error() after calls that may result in an errornous + state. + */ + void set_enable_exceptions(bool f) { m_enable_exceptions = f; } + + bool enable_exceptions() const { return m_enable_exceptions; } + /** \brief Update global parameter \c param with string \c value. */ @@ -676,8 +691,8 @@ namespace z3 { \pre is_numeral() */ int get_numeral_int() const { - int result; - if (!is_numeral_i(result)) { + int result = 0; + if (!is_numeral_i(result) && ctx().enable_exceptions()) { throw exception("numeral does not fit in machine int"); } return result; @@ -691,8 +706,8 @@ namespace z3 { */ unsigned get_numeral_uint() const { assert(is_numeral()); - unsigned result; - if (!is_numeral_u(result)) { + unsigned result = 0; + if (!is_numeral_u(result) && ctx().enable_exceptions()) { throw exception("numeral does not fit in machine uint"); } return result; @@ -706,8 +721,8 @@ namespace z3 { */ __int64 get_numeral_int64() const { assert(is_numeral()); - __int64 result; - if (!is_numeral_i64(result)) { + __int64 result = 0; + if (!is_numeral_i64(result) && ctx().enable_exceptions()) { throw exception("numeral does not fit in machine __int64"); } return result; @@ -721,8 +736,8 @@ namespace z3 { */ __uint64 get_numeral_uint64() const { assert(is_numeral()); - __uint64 result; - if (!is_numeral_u64(result)) { + __uint64 result = 0; + if (!is_numeral_u64(result) && ctx().enable_exceptions()) { throw exception("numeral does not fit in machine __uint64"); } return result; @@ -1615,7 +1630,7 @@ namespace z3 { Z3_ast r = 0; Z3_bool status = Z3_model_eval(ctx(), m_model, n, model_completion, &r); check_error(); - if (status == Z3_FALSE) + if (status == Z3_FALSE && ctx().enable_exceptions()) throw exception("failed to evaluate expression"); return expr(ctx(), r); } From e9edcdc6e6b2fb08a2b1959d8e583fabba5cbd26 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Thu, 5 Jan 2017 16:09:16 -0500 Subject: [PATCH 10/47] moderate exception behavior for issue #861 Signed-off-by: Nikolaj Bjorner --- src/api/c++/z3++.h | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/api/c++/z3++.h b/src/api/c++/z3++.h index 3f1ed614f..1556064d6 100644 --- a/src/api/c++/z3++.h +++ b/src/api/c++/z3++.h @@ -345,7 +345,7 @@ namespace z3 { object(context & c):m_ctx(&c) {} object(object const & s):m_ctx(s.m_ctx) {} context & ctx() const { return *m_ctx; } - void check_error() const { m_ctx->check_error(); } + Z3_error_code check_error() const { return m_ctx->check_error(); } friend void check_context(object const & a, object const & b); }; inline void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); } @@ -687,12 +687,18 @@ namespace z3 { /** \brief Return int value of numeral, throw if result cannot fit in machine int + + It only makes sense to use this function if the caller can ensure that + the result is an integer or if exceptions are enabled. + If exceptions are disabled, then use the the is_numeral_i function. \pre is_numeral() */ int get_numeral_int() const { int result = 0; - if (!is_numeral_i(result) && ctx().enable_exceptions()) { + if (!is_numeral_i(result)) { + assert(ctx().enable_exceptions()); + if (!ctx().enable_exceptions()) return 0; throw exception("numeral does not fit in machine int"); } return result; @@ -701,13 +707,18 @@ namespace z3 { /** \brief Return uint value of numeral, throw if result cannot fit in machine uint - + + It only makes sense to use this function if the caller can ensure that + the result is an integer or if exceptions are enabled. + If exceptions are disabled, then use the the is_numeral_u function. \pre is_numeral() */ unsigned get_numeral_uint() const { assert(is_numeral()); unsigned result = 0; - if (!is_numeral_u(result) && ctx().enable_exceptions()) { + if (!is_numeral_u(result)) { + assert(ctx().enable_exceptions()); + if (!ctx().enable_exceptions()) return 0; throw exception("numeral does not fit in machine uint"); } return result; @@ -722,7 +733,9 @@ namespace z3 { __int64 get_numeral_int64() const { assert(is_numeral()); __int64 result = 0; - if (!is_numeral_i64(result) && ctx().enable_exceptions()) { + if (!is_numeral_i64(result)) { + assert(ctx().enable_exceptions()); + if (!ctx().enable_exceptions()) return 0; throw exception("numeral does not fit in machine __int64"); } return result; @@ -737,7 +750,9 @@ namespace z3 { __uint64 get_numeral_uint64() const { assert(is_numeral()); __uint64 result = 0; - if (!is_numeral_u64(result) && ctx().enable_exceptions()) { + if (!is_numeral_u64(result)) { + assert(ctx().enable_exceptions()); + if (!ctx().enable_exceptions()) return 0; throw exception("numeral does not fit in machine __uint64"); } return result; From c69a86e647c65ac5c01daa63fc4ed666f0411fc7 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 6 Jan 2017 19:34:50 -0500 Subject: [PATCH 11/47] fix bug in antecedent collection for consequence finding: once an antecedent is set, it should not be cleared Signed-off-by: Nikolaj Bjorner --- src/sat/sat_solver.cpp | 26 ++++++++++++++++++++++++++ src/sat/sat_solver.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index 5c004b1a2..10c97b296 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -1114,6 +1114,13 @@ namespace sat { for (unsigned i = 0; !inconsistent() && i < m_assumptions.size(); ++i) { assign(m_assumptions[i], justification()); } + TRACE("sat", + for (unsigned i = 0; i < m_assumptions.size(); ++i) { + index_set s; + if (m_antecedents.find(m_assumptions[i].var(), s)) { + tout << m_assumptions[i] << ": "; display_index_set(tout, s) << "\n"; + } + }); } } @@ -3147,7 +3154,9 @@ namespace sat { void solver::fixup_consequence_core() { index_set s; + TRACE("sat", tout << m_core << "\n";); for (unsigned i = 0; i < m_core.size(); ++i) { + TRACE("sat", tout << m_core[i] << ": "; display_index_set(tout, m_antecedents.find(m_core[i].var())) << "\n";); s |= m_antecedents.find(m_core[i].var()); } m_core.reset(); @@ -3155,6 +3164,7 @@ namespace sat { for (; it != end; ++it) { m_core.push_back(to_literal(*it)); } + TRACE("sat", tout << m_core << "\n";); } @@ -3164,6 +3174,7 @@ namespace sat { for (unsigned i = 0; i < vars.size(); ++i) { unfixed_vars.insert(vars[i]); } + TRACE("sat", tout << asms << "\n";); m_antecedents.reset(); pop_to_base_level(); if (inconsistent()) return l_false; @@ -3222,6 +3233,7 @@ namespace sat { } lbool solver::get_consequences(literal_vector const& asms, literal_vector const& lits, vector& conseq) { + TRACE("sat", tout << asms << "\n";); m_antecedents.reset(); literal_set unfixed_lits(lits), assumptions(asms); bool_var_set unfixed_vars; @@ -3386,10 +3398,24 @@ namespace sat { UNREACHABLE(); break; } + TRACE("sat", display_index_set(tout << lit << ": " , s) << "\n";); } + std::ostream& solver::display_index_set(std::ostream& out, index_set const& s) const { + index_set::iterator it = s.begin(); + index_set::iterator end = s.end(); + for (; it != end; ++it) { + out << to_literal(*it) << " "; + } + return out; + } + + void solver::extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector& conseq) { index_set s; + if (m_antecedents.contains(lit.var())) { + return; + } if (assumptions.contains(lit)) { s.insert(lit.index()); } diff --git a/src/sat/sat_solver.h b/src/sat/sat_solver.h index a9037c65a..1700dfb7e 100644 --- a/src/sat/sat_solver.h +++ b/src/sat/sat_solver.h @@ -455,6 +455,8 @@ namespace sat { void extract_assumptions(literal lit, index_set& s); + std::ostream& display_index_set(std::ostream& out, index_set const& s) const; + lbool get_consequences(literal_vector const& assms, literal_vector const& lits, vector& conseq); lbool get_bounded_consequences(literal_vector const& assms, bool_var_vector const& vars, vector& conseq); From 8d09b6e4a8f241d77105f62d77a6a2c47daaab10 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 9 Jan 2017 21:23:00 -0800 Subject: [PATCH 12/47] add at-least and pbge to API, fix for issue #864 Signed-off-by: Nikolaj Bjorner --- src/api/api_ast.cpp | 2 + src/api/api_pb.cpp | 32 +++++++++++++++ src/api/dotnet/Context.cs | 26 ++++++++++++ src/api/python/z3/z3.py | 61 ++++++++++++++--------------- src/api/z3_api.h | 28 +++++++++++++ src/smt/smt_bool_var_data.h | 10 +++++ src/smt/smt_conflict_resolution.cpp | 27 +++++++++---- src/smt/smt_context.cpp | 22 +++++++---- src/smt/smt_context.h | 6 ++- src/smt/smt_context_inv.cpp | 14 +++++++ src/smt/smt_literal.cpp | 2 + 11 files changed, 182 insertions(+), 48 deletions(-) diff --git a/src/api/api_ast.cpp b/src/api/api_ast.cpp index 08a931fdc..fd2776079 100644 --- a/src/api/api_ast.cpp +++ b/src/api/api_ast.cpp @@ -1211,7 +1211,9 @@ extern "C" { switch(_d->get_decl_kind()) { case OP_PB_LE: return Z3_OP_PB_LE; case OP_PB_GE: return Z3_OP_PB_GE; + case OP_PB_EQ: return Z3_OP_PB_EQ; case OP_AT_MOST_K: return Z3_OP_PB_AT_MOST; + case OP_AT_LEAST_K: return Z3_OP_PB_AT_LEAST; default: return Z3_OP_INTERNAL; } } diff --git a/src/api/api_pb.cpp b/src/api/api_pb.cpp index b7c28c34f..ee504146f 100644 --- a/src/api/api_pb.cpp +++ b/src/api/api_pb.cpp @@ -39,6 +39,20 @@ extern "C" { } + Z3_ast Z3_API Z3_mk_atleast(Z3_context c, unsigned num_args, + Z3_ast const args[], unsigned k) { + Z3_TRY; + LOG_Z3_mk_atmost(c, num_args, args, k); + RESET_ERROR_CODE(); + parameter param(k); + pb_util util(mk_c(c)->m()); + ast* a = util.mk_at_least_k(num_args, to_exprs(args), k); + mk_c(c)->save_ast_trail(a); + check_sorts(c, a); + RETURN_Z3(of_ast(a)); + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_pble(Z3_context c, unsigned num_args, Z3_ast const args[], int _coeffs[], int k) { @@ -57,6 +71,24 @@ extern "C" { Z3_CATCH_RETURN(0); } + Z3_ast Z3_API Z3_mk_pbge(Z3_context c, unsigned num_args, + Z3_ast const args[], int _coeffs[], + int k) { + Z3_TRY; + LOG_Z3_mk_pble(c, num_args, args, _coeffs, k); + RESET_ERROR_CODE(); + pb_util util(mk_c(c)->m()); + vector coeffs; + for (unsigned i = 0; i < num_args; ++i) { + coeffs.push_back(rational(_coeffs[i])); + } + ast* a = util.mk_ge(num_args, coeffs.c_ptr(), to_exprs(args), rational(k)); + mk_c(c)->save_ast_trail(a); + check_sorts(c, a); + RETURN_Z3(of_ast(a)); + Z3_CATCH_RETURN(0); + } + Z3_ast Z3_API Z3_mk_pbeq(Z3_context c, unsigned num_args, Z3_ast const args[], int _coeffs[], int k) { diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs index f12ad58ea..f5c4dc99d 100644 --- a/src/api/dotnet/Context.cs +++ b/src/api/dotnet/Context.cs @@ -2692,6 +2692,18 @@ namespace Microsoft.Z3 AST.ArrayToNative(args), k)); } + /// + /// Create an at-least-k constraint. + /// + public BoolExpr MkAtLeast(BoolExpr[] args, uint k) + { + Contract.Requires(args != null); + Contract.Requires(Contract.Result() != null); + CheckContextMatch(args); + return new BoolExpr(this, Native.Z3_mk_atleast(nCtx, (uint) args.Length, + AST.ArrayToNative(args), k)); + } + /// /// Create a pseudo-Boolean less-or-equal constraint. /// @@ -2707,6 +2719,20 @@ namespace Microsoft.Z3 coeffs, k)); } + /// + /// Create a pseudo-Boolean greater-or-equal constraint. + /// + public BoolExpr MkPBGe(int[] coeffs, BoolExpr[] args, int k) + { + Contract.Requires(args != null); + Contract.Requires(coeffs != null); + Contract.Requires(args.Length == coeffs.Length); + Contract.Requires(Contract.Result() != null); + CheckContextMatch(args); + return new BoolExpr(this, Native.Z3_mk_pbge(nCtx, (uint) args.Length, + AST.ArrayToNative(args), + coeffs, k)); + } /// /// Create a pseudo-Boolean equal constraint. /// diff --git a/src/api/python/z3/z3.py b/src/api/python/z3/z3.py index 22b2f60e6..01dacace7 100644 --- a/src/api/python/z3/z3.py +++ b/src/api/python/z3/z3.py @@ -7617,11 +7617,6 @@ def AtLeast(*args): >>> a, b, c = Bools('a b c') >>> f = AtLeast(a, b, c, 2) """ - def mk_not(a): - if is_not(a): - return a.arg(0) - else: - return Not(a) args = _get_args(args) if __debug__: _z3_assert(len(args) > 1, "Non empty list of arguments expected") @@ -7629,10 +7624,25 @@ def AtLeast(*args): if __debug__: _z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression") args1 = _coerce_expr_list(args[:-1], ctx) - args1 = [ mk_not(a) for a in args1 ] - k = len(args1) - args[-1] + k = args[-1] _args, sz = _to_ast_array(args1) - return BoolRef(Z3_mk_atmost(ctx.ref(), sz, _args, k), ctx) + return BoolRef(Z3_mk_atleast(ctx.ref(), sz, _args, k), ctx) + + +def _pb_args_coeffs(args): + args = _get_args(args) + args, coeffs = zip(*args) + if __debug__: + _z3_assert(len(args) > 0, "Non empty list of arguments expected") + ctx = _ctx_from_ast_arg_list(args) + if __debug__: + _z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression") + args = _coerce_expr_list(args, ctx) + _args, sz = _to_ast_array(args) + _coeffs = (ctypes.c_int * len(coeffs))() + for i in range(len(coeffs)): + _coeffs[i] = coeffs[i] + return ctx, sz, _args, _coeffs def PbLe(args, k): """Create a Pseudo-Boolean inequality k constraint. @@ -7640,38 +7650,25 @@ def PbLe(args, k): >>> a, b, c = Bools('a b c') >>> f = PbLe(((a,1),(b,3),(c,2)), 3) """ - args = _get_args(args) - args, coeffs = zip(*args) - if __debug__: - _z3_assert(len(args) > 0, "Non empty list of arguments expected") - ctx = _ctx_from_ast_arg_list(args) - if __debug__: - _z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression") - args = _coerce_expr_list(args, ctx) - _args, sz = _to_ast_array(args) - _coeffs = (ctypes.c_int * len(coeffs))() - for i in range(len(coeffs)): - _coeffs[i] = coeffs[i] + ctx, sz, _args, _coeffs = _pb_args_coeffs(args) return BoolRef(Z3_mk_pble(ctx.ref(), sz, _args, _coeffs, k), ctx) +def PbGe(args, k): + """Create a Pseudo-Boolean inequality k constraint. + + >>> a, b, c = Bools('a b c') + >>> f = PbGe(((a,1),(b,3),(c,2)), 3) + """ + ctx, sz, _args, _coeffs = _pb_args_coeffs(args) + return BoolRef(Z3_mk_pbge(ctx.ref(), sz, _args, _coeffs, k), ctx) + def PbEq(args, k): """Create a Pseudo-Boolean inequality k constraint. >>> a, b, c = Bools('a b c') >>> f = PbEq(((a,1),(b,3),(c,2)), 3) """ - args = _get_args(args) - args, coeffs = zip(*args) - if __debug__: - _z3_assert(len(args) > 0, "Non empty list of arguments expected") - ctx = _ctx_from_ast_arg_list(args) - if __debug__: - _z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression") - args = _coerce_expr_list(args, ctx) - _args, sz = _to_ast_array(args) - _coeffs = (ctypes.c_int * len(coeffs))() - for i in range(len(coeffs)): - _coeffs[i] = coeffs[i] + ctx, sz, _args, _coeffs = _pb_args_coeffs(args) return BoolRef(Z3_mk_pbeq(ctx.ref(), sz, _args, _coeffs, k), ctx) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index b80ce3177..fcf22961c 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -855,6 +855,9 @@ typedef enum - Z3_OP_PB_AT_MOST: Cardinality constraint. E.g., x + y + z <= 2 + - Z3_OP_PB_AT_LEAST: Cardinality constraint. + E.g., x + y + z >= 2 + - Z3_OP_PB_LE: Generalized Pseudo-Boolean cardinality constraint. Example 2*x + 3*y <= 4 @@ -1174,6 +1177,7 @@ typedef enum { // Pseudo Booleans Z3_OP_PB_AT_MOST=0x900, + Z3_OP_PB_AT_LEAST, Z3_OP_PB_LE, Z3_OP_PB_GE, Z3_OP_PB_EQ, @@ -3966,6 +3970,17 @@ extern "C" { Z3_ast Z3_API Z3_mk_atmost(Z3_context c, unsigned num_args, Z3_ast const args[], unsigned k); + + /** + \brief Pseudo-Boolean relations. + + Encode p1 + p2 + ... + pn >= k + + def_API('Z3_mk_atleast', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in(UINT))) + */ + + Z3_ast Z3_mk_atleast(Z3_context c, unsigned num_args, + Z3_ast const args[], unsigned k); /** \brief Pseudo-Boolean relations. @@ -3978,6 +3993,19 @@ extern "C" { Z3_ast const args[], int coeffs[], int k); + + /** + \brief Pseudo-Boolean relations. + + Encode k1*p1 + k2*p2 + ... + kn*pn >= k + + def_API('Z3_mk_pbge', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in_array(1,INT), _in(INT))) + */ + + Z3_ast Z3_mk_pbge(Z3_context c, unsigned num_args, + Z3_ast const args[], int coeffs[], + int k); + /** \brief Pseudo-Boolean relations. diff --git a/src/smt/smt_bool_var_data.h b/src/smt/smt_bool_var_data.h index e65036d9c..af0b7f9d2 100644 --- a/src/smt/smt_bool_var_data.h +++ b/src/smt/smt_bool_var_data.h @@ -24,7 +24,9 @@ Revision History: namespace smt { struct bool_var_data { + private: b_justification m_justification; + public: unsigned m_scope_lvl:24; //!< scope level of when the variable was assigned. unsigned m_mark:1; unsigned m_assumption:1; @@ -45,6 +47,14 @@ namespace smt { public: unsigned get_intern_level() const { return m_iscope_lvl; } + + b_justification justification() const { return m_justification; } + + void set_axiom() { m_justification = b_justification::mk_axiom(); } + + void set_null_justification() { m_justification = null_b_justification; } + + void set_justification(b_justification const& j) { m_justification = j; } bool is_atom() const { return m_atom; } diff --git a/src/smt/smt_conflict_resolution.cpp b/src/smt/smt_conflict_resolution.cpp index 4568abb55..7dd9144fe 100644 --- a/src/smt/smt_conflict_resolution.cpp +++ b/src/smt/smt_conflict_resolution.cpp @@ -496,13 +496,15 @@ namespace smt { unsigned idx = skip_literals_above_conflict_level(); + TRACE("conflict", m_ctx.display_literal_verbose(tout, not_l); m_ctx.display(tout << " ", conflict);); + // save space for first uip m_lemma.push_back(null_literal); m_lemma_atoms.push_back(0); unsigned num_marks = 0; if (not_l != null_literal) { - TRACE("conflict", tout << "not_l: "; m_ctx.display_literal(tout, not_l); tout << "\n";); + TRACE("conflict", tout << "not_l: "; m_ctx.display_literal_verbose(tout, not_l); tout << "\n";); process_antecedent(not_l, num_marks); } @@ -514,7 +516,7 @@ namespace smt { get_manager().trace_stream() << "\n"; } - TRACE("conflict", tout << "processing consequent: "; m_ctx.display_literal(tout, consequent); tout << "\n"; + TRACE("conflict", tout << "processing consequent: "; m_ctx.display_literal_verbose(tout, consequent); tout << "\n"; tout << "num_marks: " << num_marks << ", js kind: " << js.get_kind() << "\n";); SASSERT(js != null_b_justification); switch (js.get_kind()) { @@ -1076,6 +1078,7 @@ namespace smt { return true; SASSERT(js.get_kind() != b_justification::BIN_CLAUSE); CTRACE("visit_b_justification_bug", js.get_kind() == b_justification::AXIOM, tout << "l: " << l << "\n"; m_ctx.display(tout);); + if (js.get_kind() == b_justification::AXIOM) return true; SASSERT(js.get_kind() != b_justification::AXIOM); @@ -1089,14 +1092,17 @@ namespace smt { i = 1; } else { + SASSERT(cls->get_literal(1) == l); if (get_proof(~cls->get_literal(0)) == 0) visited = false; i = 2; } } - for (; i < num_lits; i++) + for (; i < num_lits; i++) { + SASSERT(cls->get_literal(i) != l); if (get_proof(~cls->get_literal(i)) == 0) visited = false; + } return visited; } else @@ -1251,14 +1257,19 @@ namespace smt { } tout << "\n";); init_mk_proof(); - literal consequent = false_literal; - if (not_l != null_literal) - consequent = ~not_l; - visit_b_justification(consequent, conflict); - if (not_l != null_literal) + literal consequent; + if (not_l == null_literal) { + consequent = false_literal; + } + else { + consequent = ~not_l; m_todo_pr.push_back(tp_elem(not_l)); + } + visit_b_justification(consequent, conflict); + while (!m_todo_pr.empty()) { tp_elem & elem = m_todo_pr.back(); + switch (elem.m_kind) { case tp_elem::EQUALITY: { enode * lhs = elem.m_lhs; diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index e6d4d0c07..476a419eb 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -261,10 +261,11 @@ namespace smt { m_assignment[false_literal.index()] = l_false; if (m_manager.proofs_enabled()) { proof * pr = m_manager.mk_true_proof(); - m_bdata[true_bool_var].m_justification = b_justification(mk_justification(justification_proof_wrapper(*this, pr))); + + set_justification(true_bool_var, m_bdata[true_bool_var], b_justification(mk_justification(justification_proof_wrapper(*this, pr)))); } else { - m_bdata[true_bool_var].m_justification = b_justification::mk_axiom(); + m_bdata[true_bool_var].set_axiom(); } m_true_enode = mk_enode(t, true, true, false); // internalizer is marking enodes as interpreted whenever the associated ast is a value and a constant. @@ -292,6 +293,12 @@ namespace smt { std::swap(lhs, rhs); return m_manager.mk_eq(lhs, rhs); } + + void context::set_justification(bool_var v, bool_var_data& d, b_justification const& j) { + SASSERT(validate_justification(v, d, j)); + d.set_justification(j); + } + void context::assign_core(literal l, b_justification j, bool decision) { TRACE("assign_core", tout << (decision?"decision: ":"propagating: ") << l << " "; @@ -302,7 +309,7 @@ namespace smt { m_assignment[l.index()] = l_true; m_assignment[(~l).index()] = l_false; bool_var_data & d = get_bdata(l.var()); - d.m_justification = j; + set_justification(l.var(), d, j); d.m_scope_lvl = m_scope_lvl; if (m_fparams.m_restart_adaptive && d.m_phase_available) { m_agility *= m_fparams.m_agility_factor; @@ -1406,7 +1413,8 @@ namespace smt { else { TRACE("add_diseq", display_eq_detail(tout, bool_var2enode(v));); if (!add_diseq(get_enode(lhs), get_enode(rhs)) && !inconsistent()) { - set_conflict(b_justification(mk_justification(eq_propagation_justification(get_enode(lhs), get_enode(rhs)))), ~l); + literal not_eq = literal(l.var(), true); + set_conflict(b_justification(mk_justification(eq_propagation_justification(get_enode(lhs), get_enode(rhs)))), not_eq); } } } @@ -2042,7 +2050,7 @@ namespace smt { m_assignment[(~l).index()] = l_undef; bool_var v = l.var(); bool_var_data & d = get_bdata(v); - d.m_justification = null_b_justification; + d.set_null_justification(); m_case_split_queue->unassign_var_eh(v); } @@ -2593,10 +2601,10 @@ namespace smt { cls->set_justification(0); m_justifications.push_back(js); } - m_bdata[v0].m_justification = b_justification(js); + set_justification(v0, m_bdata[v0], b_justification(js)); } else - m_bdata[v0].m_justification = b_justification::mk_axiom(); + m_bdata[v0].set_axiom(); } } del_clause(cls); diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index c63d0614d..0d758196e 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -363,9 +363,11 @@ namespace smt { void get_assignments(expr_ref_vector& assignments); b_justification get_justification(bool_var v) const { - return get_bdata(v).m_justification; + return get_bdata(v).justification(); } + void set_justification(bool_var v, bool_var_data& d, b_justification const& j); + bool has_th_justification(bool_var v, theory_id th_id) const { b_justification js = get_justification(v); return js.get_kind() == b_justification::JUSTIFICATION && js.get_justification()->get_from_theory() == th_id; @@ -1381,6 +1383,8 @@ namespace smt { void validate_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector const& conseq, expr_ref_vector const& unfixed); + bool validate_justification(bool_var v, bool_var_data const& d, b_justification const& j); + void justify(literal lit, index_set& s); void extract_cores(expr_ref_vector const& asms, vector& cores, unsigned& min_core_size); diff --git a/src/smt/smt_context_inv.cpp b/src/smt/smt_context_inv.cpp index 5e3b091bc..7d009a037 100644 --- a/src/smt/smt_context_inv.cpp +++ b/src/smt/smt_context_inv.cpp @@ -402,6 +402,20 @@ namespace smt { #endif + bool context::validate_justification(bool_var v, bool_var_data const& d, b_justification const& j) { + if (j.get_kind() == b_justification::CLAUSE && v != true_bool_var) { + clause* cls = j.get_clause(); + unsigned num_lits = cls->get_num_literals(); + literal l = cls->get_literal(0); + if (l.var() != v) { + l = cls->get_literal(1); + } + SASSERT(l.var() == v); + SASSERT(m_assignment[l.index()] == l_true); + } + return true; + } + bool context::validate_model() { if (!m_proto_model) { return true; diff --git a/src/smt/smt_literal.cpp b/src/smt/smt_literal.cpp index d510027f0..e6e795ed4 100644 --- a/src/smt/smt_literal.cpp +++ b/src/smt/smt_literal.cpp @@ -27,6 +27,8 @@ namespace smt { out << "true"; else if (*this == false_literal) out << "false"; + else if (*this == null_literal) + out << "null"; else if (sign()) out << "(not " << mk_pp(bool_var2expr_map[var()], m) << ")"; else From 331658f20809a7ea32c3899f3cae37ffa63a7d4f Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Mon, 9 Jan 2017 21:30:54 -0800 Subject: [PATCH 13/47] remove polynomial factorization as suggested by issue #852 Signed-off-by: Nikolaj Bjorner --- .../cmake/src/math/polynomial/CMakeLists.txt | 1 - src/math/polynomial/polynomial.cpp | 1 - .../polynomial/polynomial_factorization.cpp | 1143 ----------------- .../polynomial/polynomial_factorization.h | 65 - 4 files changed, 1210 deletions(-) delete mode 100644 src/math/polynomial/polynomial_factorization.cpp delete mode 100644 src/math/polynomial/polynomial_factorization.h diff --git a/contrib/cmake/src/math/polynomial/CMakeLists.txt b/contrib/cmake/src/math/polynomial/CMakeLists.txt index 1792f50aa..1d320d751 100644 --- a/contrib/cmake/src/math/polynomial/CMakeLists.txt +++ b/contrib/cmake/src/math/polynomial/CMakeLists.txt @@ -3,7 +3,6 @@ z3_add_component(polynomial algebraic_numbers.cpp polynomial_cache.cpp polynomial.cpp - polynomial_factorization.cpp rpolynomial.cpp sexpr2upolynomial.cpp upolynomial.cpp diff --git a/src/math/polynomial/polynomial.cpp b/src/math/polynomial/polynomial.cpp index 93858b6be..1a4aa8304 100644 --- a/src/math/polynomial/polynomial.cpp +++ b/src/math/polynomial/polynomial.cpp @@ -25,7 +25,6 @@ Notes: #include"scoped_ptr_vector.h" #include"cooperate.h" #include"upolynomial_factorization.h" -#include"polynomial_factorization.h" #include"polynomial_primes.h" #include"permutation.h" #include"algebraic_numbers.h" diff --git a/src/math/polynomial/polynomial_factorization.cpp b/src/math/polynomial/polynomial_factorization.cpp deleted file mode 100644 index 4bf227d44..000000000 --- a/src/math/polynomial/polynomial_factorization.cpp +++ /dev/null @@ -1,1143 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - polynomial_factorization.cpp - -Abstract: - - Implementation of polynomial factorization. - -Author: - - Dejan (t-dejanj) 2011-11-15 - -Notes: - - [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 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. - ---*/ -#if 0 -// disabled for reorg - -#include"trace.h" -#include"util.h" -#include"polynomial_factorization.h" -#include"upolynomial_factorization_int.h" -#include"prime_generator.h" - -using namespace std; - -namespace polynomial { - -typedef upolynomial::manager::scoped_numeral scoped_numeral; - -/** - Generates a substitution of values for f -> f_univariate in order to reduce the factorization to the - univariate case. - - @param f multivariate polynomial (square-free, primitive, vars(f) > 1) - @param x the variable we want to keep as the univarate one - @param f_lc the leading coefficient of f in x - @param vars the vector of all variables from f witouth x - @param size the bound to use for selecting the values, i.e. |a_i| <= size - @param a the output values corresponding to vairables in (place place for x should be ignored) - @param f_univariate the output substitution -*/ -void generate_substitution_values( - polynomial_ref const & f, var x, polynomial_ref const & f_lc, var_vector const & vars, unsigned & size, - upolynomial::numeral_vector & a, upolynomial::manager upm, upolynomial::numeral_vector & f_u) { - - SASSERT(a.size() == vars.size()); - - TRACE("polynomial::factorization", tout << "polynomial::generate_substitution_values(f = " << f << ", f_lc = " << f_lc << ")";); - - // f = f_n x^n + ... + f_0, square-free and primitive - // this means - // f_lc = f_n - // since f is primitive, - // we are looking for numbers a_i such that - // (1) f_lc doesn't vanish - // (2) f_u = f(a_0, ..., a_n, x) is square-free - - manager & pm = f.m(); - numeral_manager & nm = pm.m(); - - // polynomial to use for subtituting into the lc(f) - polynomial_ref f_lc_subst(pm); - - // random generator - random_gen generator; - - // increase the size every once in a while (RETHINK THIS) - unsigned inc_size_c = 0; - unsigned inc_size_c_max = size; - - while (true) { - - // see if we should increase the size of the substitution - if ((++ inc_size_c) % inc_size_c_max == 0) { - size ++; - inc_size_c = 0; - inc_size_c_max *= 2; - } - - // the head coefficient we'll substitute in - f_lc_subst = f_lc; - - bool vanished = false; - for (unsigned i = 0; i < vars.size() && !vanished; ++ i) { - SASSERT(vars[i] != x); - - // the value for x_i - nm.set(a[i], (int)generator(2*size+1) - (int)size); - - // substitute - f_lc_subst = pm.substitute(f_lc_subst, x, a[i]); - - // did it vanish - vanished = pm.is_zero(f_lc_subst); - } - - if (vanished) { - // leading coefficient vanished, try again - continue; - } - - // substitute into f and get the univariate one - polynomial_ref f_subst(pm); - f_subst = pm.substitute(f, vars.size(), vars.c_ptr(), a.c_ptr()); - upm.to_numeral_vector(f_subst, f_u); - - // if the result is not square-free we try again - if (!upm.is_square_free(f_u)) - continue; - - // found it, break - break; - } -} - -/** - \brief Bound for the coefficients of the factorst of the multivariate polynomial f. R - Returns power of p -> p^e that covers the bound - - We use the gelfond bound here: - d_i: degree of x_i in f(x1, ..., x_n) - bound = |f| * 2^(\sum d_i - (n-1)/2)) -*/ -void multivariate_factor_coefficient_bound(polynomial_ref const & f, var x, numeral const & p, unsigned & e, numeral & p_e, var2degree & d) { - manager & pm = f.m(); - numeral_manager & nm = pm.m(); - - // compute g = lc(f)*f - polynomial_ref f_lc(pm), g(pm); - f_lc = pm.coeff(f, x, pm.degree(f, x)); - g = pm.mul(f, f_lc); - - // get the norm - scoped_numeral g_norm(nm); - pm.abs_norm(g, g_norm); - - // get the variable degrees - var_vector vars; - pm.vars(f, vars); - unsigned power = 0; - for (unsigned i = 0; i < vars.size(); ++ i) { - unsigned c_d = pm.degree(g, vars[i]); - d.set_degree(vars[i], c_d + 1); - power += c_d; - } - power = power - (vars.size()-1)/2; - - // compute the bound - scoped_numeral bound(nm); - nm.set(bound, 2); - nm.power(bound, power, bound); - nm.mul(g_norm, bound, bound); - - // return the first power of two that is bigger than the norm - e = 1; - nm.set(p_e, p); - while (nm.lt(p_e, bound)) { - nm.mul(p_e, p_e, p_e); - e *= 2; - } -} - -// check that A*S+B*T=C in zp mod ideal -bool check_solve(zp_manager & zp_pm, var2degree const & ideal, - zp_polynomial_ref const & A, zp_polynomial_ref const & B, zp_polynomial_ref const & C, - zp_polynomial_ref const & S, zp_polynomial_ref const & T) { - zp_polynomial_ref AS(zp_pm), BT(zp_pm), sum(zp_pm); - AS = zp_pm.mul(A, S); AS = zp_pm.mod_d(AS, ideal); - BT = zp_pm.mul(B, T); BT = zp_pm.mod_d(BT, ideal); - sum = zp_pm.add(AS, BT); - - TRACE("polynomial::factorization::multivariate", - tout << "zp_pm = Z_" << zp_pm.m().m().to_string(zp_pm.m().p()) << endl; - tout << "ideal = " << ideal << endl; - tout << "A = " << A << endl; - tout << "B = " << B << endl; - tout << "S = " << S << endl; - tout << "T = " << T << endl; - tout << "C = " << C << endl; - tout << "sum = " << sum << endl; - ); - - bool result = zp_pm.eq(sum, C); - return result; -} - -/** - Solve the equation A*S + B*T = C, given, AU + BV = 1, with deg(T) < deg(A) - S = U*C + tB - T = V*C - tA - we divide VC with A to get (T, t) -*/ -template -void solve(zp_manager & zp_pm, var x, var2degree const & ideal, - zp_polynomial_ref const & A, zp_polynomial_ref const & U, - zp_polynomial_ref const & B, zp_polynomial_ref const & V, - zp_polynomial_ref const & C, - output_manager & out_pm, - typename output_manager::polynomial_ref & S_out, - typename output_manager::polynomial_ref & T_out) { - TRACE("polynomial::factorization::multivariate", - tout << "polynomial::solve(" << endl; - tout << "zp_pm = Z_" << zp_pm.m().m().to_string(zp_pm.m().p()) << endl; - tout << "ideal = " << ideal << endl; - tout << "A = " << A << endl; - tout << "B = " << B << endl; - tout << "U = " << U << endl; - tout << "V = " << V << endl; - tout << "C = " << C << endl; - ); - - // solution is S = C*U + tB, T = C*V - tA - zp_polynomial_ref CV(zp_pm); - CV = zp_pm.mul(C, V); CV = zp_pm.mod_d(CV, ideal); - zp_polynomial_ref CU(zp_pm); - CU = zp_pm.mul(C, U); CU = zp_pm.mod_d(CU, ideal); - zp_polynomial_ref t(zp_pm), T(zp_pm); - zp_pm.exact_pseudo_division_mod_d(CV, A, x, ideal, t, T); - - zp_polynomial_ref tB(zp_pm); - tB = zp_pm.mul(t, B); tB = zp_pm.mod_d(tB, ideal); - zp_polynomial_ref S(zp_pm); - S = zp_pm.add(CU, tB); - - SASSERT(check_solve(zp_pm, ideal, A, B, C, S, T)); - - // convert to the other manager - S_out = convert(zp_pm, S, out_pm); - T_out = convert(zp_pm, T, out_pm); - - TRACE("polynomial::factorization::multivariate", - tout << "CU = " << CU << endl; - tout << "CV = " << CV << endl; - tout << "t = " << t << endl; - tout << "--- solution ---" << endl; - tout << "S = " << S_out << endl; - tout << "T = " << T_out << endl; - ); -} - -/** - A, B, U, V: multivariate polynomials in Z_p[x, ...], mod ..., also the output polynomials, y is not there - C: C = A*B in Z_p[x, ...] mod p, ... - - ideal: all the vars we care about in the ideal - - y, the variable we are lifting is not in ideal_vars, we will add it - - A monic, A*U+B*V = 1 - - p is not necessary prime, it's a power of a prime - - we're doing quadratic lifting here - - output: added y, i.e. - * all polynomials in Z_p[x, ..., y] mod (..., y^d) -*/ -void multivariate_hansel_lift_ideal( - zp_manager & zp_pm, var x, - zp_polynomial_ref const & C, - zp_polynomial_ref & A, zp_polynomial_ref & U, zp_polynomial_ref & B, zp_polynomial_ref & V, - var2degree & ideal, var y, unsigned d) { - numeral_manager & nm = zp_pm.m().m(); - - TRACE("polynomial::factorization::multivariate", - tout << "polynomial::multiratiate_hensel_lift_ideal" << endl; - tout << "zp_pm is Z_" << zp_pm.m().m().to_string(zp_pm.m().p()) << endl; - tout << "x = x" << x << endl; - tout << "y = x" << y << endl; - tout << "C = " << C << endl; - tout << "A = " << A << endl; - tout << "B = " << B << endl; - tout << "U = " << U << endl; - tout << "V = " << V << endl; - tout << "ideal = " << ideal << endl; - ); - - // constant 1 - scoped_numeral one(nm); - nm.set(one, 1); - zp_polynomial_ref one_p(zp_pm); - one_p = zp_pm.mk_const(one); - - SASSERT(zp_pm.degree(A, y) == 0 && zp_pm.degree(B, y) == 0 && zp_pm.degree(U, y) == 0 && zp_pm.degree(V, y) == 0); - - // update the ideal, and start with y - ideal.set_degree(y, 1); - unsigned current_d = 1; - zp_polynomial_ref current_power(zp_pm); - current_power = zp_pm.mk_polynomial(y); - - // lift quadratic until we are over the asked for - while (current_d < d) { - - TRACE("polynomial::factorization::multivariate", - tout << "zp_pm = Z_" << nm.to_string(zp_pm.m().p()) << endl; - tout << "ideal = " << ideal << endl; - tout << "C = " << C << endl; - tout << "A = " << A << endl; - tout << "B = " << B << endl; - ); - - // again, classic hensel: - // since C = A*B mod (p, ideal, y^k) we know that (C - A*B) = 0 mod (p, ideal, y^k) - // f = (C - A*B) mod (p, ideal, y^k) and thus divisible by y^current_d = current_power - zp_polynomial_ref f(zp_pm); - f = zp_pm.mul(A, B); - - TRACE("polynomial::factorization::multivariate", - tout << "zp_pm = Z_" << nm.to_string(zp_pm.m().p()) << endl; - tout << "ideal = " << ideal << endl; - tout << "C = " << C << endl; - tout << "A = " << A << endl; - tout << "B = " << B << endl; - tout << "f = " << f << endl; - ); - - f = zp_pm.sub(C, f); - f = zp_pm.exact_div(f, current_power); - f = zp_pm.mod_d(f, ideal); - - TRACE("polynomial::factorization::multivariate", - tout << "A = " << A << endl; - tout << "B = " << B << endl; - ); - - // get the S, T, solution to A*S+B*T = f, with d(T, x) < d(A, x) - // but we know that S = U*f + Bt, T = V*f - At, so we do division - zp_polynomial_ref S(zp_pm), T(zp_pm); - solve(zp_pm, x, ideal, A, U, B, V, f, zp_pm, S, T); - // now, lets lift A and B - // we want A1 = A + T*y^d, B1 = B + S*y^d with A1*B1 = C mod (ideal, y^(2*k)) - // hence A*B + y^d*(A*S+B*T) = C - S = zp_pm.mul(S, current_power); - T = zp_pm.mul(T, current_power); - A = zp_pm.add(A, T); - B = zp_pm.add(B, S); - - TRACE("polynomial::factorization::multivariate", - tout << "A = " << A << endl; - tout << "B = " << B << endl; - ); - - // again, classic quadratic hensel - // we need A*U1 + B*V1 = 1 mod (p, ideal, y^2), from above - // U1 = U + S*y^d, V1 = V + T*y^d, hence A*U + B*V + y^d(S + T) = 1 mod new ideal^2 - // we know that y^d divides (1-UA-BV) so we compute f = (1-UA-BV)/y^d - // UA + VB + y^d(SA + TB) = 1 (mod ideal^2) - // SA + TB = f (mod ideal) - // we solve for S, T again, and do as above - zp_polynomial_ref UA(zp_pm), BV(zp_pm); - f = zp_pm.mk_const(one); - UA = zp_pm.mul(U, A); - BV = zp_pm.mul(V, B); - f = zp_pm.sub(f, UA); f = zp_pm.sub(f, BV); - - TRACE("polynomial::factorization::multivariate", - tout << "ideal = " << ideal << endl; - tout << "current_power = " << current_power << endl; - tout << "UA = " << UA << endl; - tout << "BV = " << BV << endl; - tout << "f = " << f << endl; - tout << "x = x" << x << endl; - tout << "y = x" << y << endl; - ); - - f = zp_pm.exact_div(f, current_power); - f = zp_pm.mod_d(f, ideal); - - // get the S, T, solution to A*S+B*T = f, with d(T, x) < d(A, x) - solve(zp_pm, x, ideal, A, U, B, V, f, zp_pm, S, T); - // now, lets lift U and V - S = zp_pm.mul(S, current_power); - U = zp_pm.add(U, S); - T = zp_pm.mul(T, current_power); - V = zp_pm.add(V, T); - - // lift the ideal - current_d *= 2; - current_power = zp_pm.mul(current_power, current_power); - ideal.set_degree(y, current_d); - - // move, A, B, C, D into the ideal - A = zp_pm.mod_d(A, ideal); - B = zp_pm.mod_d(B, ideal); - S = zp_pm.mod_d(S, ideal); - T = zp_pm.mod_d(T, ideal); - - TRACE("polynomial::factorization::multivariate", - tout << "current_d = " << d << endl; - tout << "zp_pm is Z_" << zp_pm.m().m().to_string(zp_pm.m().p()) << endl; - tout << "x = x" << x << endl; - tout << "y = x" << y << endl; - tout << "C = " << C << endl; - tout << "A = " << A << endl; - tout << "B = " << B << endl; - tout << "U = " << U << endl; - tout << "V = " << V << endl; - tout << "ideal = " << ideal << endl; - ); - - SASSERT(check_solve(zp_pm, ideal, A, B, one_p, U, V)); - } -} - -template -bool are_equal_in( - manager_to_check pm, - typename manager_1::polynomial_ref const & A, - typename manager_2::polynomial_ref const & B) { - typename manager_to_check::polynomial_ref A_pm(pm), B_pm(pm); - - A_pm = convert(A.m(), A, pm); - B_pm = convert(B.m(), B, pm); - - bool equal = pm.eq(A_pm, B_pm); - return equal; -} - -/** - C: target multivariate polynomial mod ideal, p^e, the manager is in p^e - x: main variable - A, B, U, V: univariate polynomials in Z_p[x] such that U*A+B*V=1 mod ideal, these guys managers are in Z_p - - output: A_lifted, B_lifted, A = A_lifted mod ideal - A_lifted*B_lifted = f mod x_i^d_i, p^e -*/ -void multivariate_hansel_lift_zp( - manager & pm, zp_manager & zp_pm, zp_manager & zpe_pm, - zp_polynomial_ref const & C_pe, var x, unsigned e, - zp_polynomial_ref const & A_p, zp_polynomial_ref const & U_p, - zp_polynomial_ref const & B_p, zp_polynomial_ref const & V_p, - var2degree const & ideal, - zp_polynomial_ref & A_lifted, zp_polynomial_ref & B_lifted) { - TRACE("polynomial::factorization::multivariate", - tout << "polynomial::multiratiate_hensel_lift_zp:" << endl; - tout << "zp_pm = Z_" << zp_pm.m().m().to_string(zp_pm.m().p()) << endl; - tout << "zpe_pm = Z_" << zpe_pm.m().m().to_string(zpe_pm.m().p()) << endl; - tout << "x = x" << x << endl; - tout << "ideal = " << ideal << endl; - tout << "C_pe = " << C_pe << "," << endl; - tout << "A_p = " << A_p << "," << endl; - tout << "B_p = " << B_p << "," << endl; - ); - - // fixed zpe_pm - // upolynomial::zp_numeral_manager & zpe_nm = zpe_pm.m(); - // numeral const & pe = zpe_nm.p(); - // fixed zp_pm - upolynomial::zp_numeral_manager & zp_nm = zp_pm.m(); - numeral const & p = zp_nm.p(); - // regular numeral manager and mangager - numeral_manager & nm = zp_nm.m(); - - // sliding zpk_pm mod p^k - upolynomial::zp_numeral_manager zpk_nm(nm, p); - zp_manager zpk_pm(zpk_nm, &zp_pm.mm()); // in the end we copy the result over to zpe - unsigned k = 1; - upolynomial::scoped_numeral pk(nm); - nm.set(pk, zpk_nm.p()); - - // constant 1 - scoped_numeral one(nm); - nm.set(one, 1); - zp_polynomial_ref one_p(zpk_pm); - one_p = zpk_pm.mk_const(one); - - // lift until you get over the requested power of e - zp_polynomial_ref A_pk(zpk_pm), B_pk(zpk_pm), U_pk(zpk_pm), V_pk(zpk_pm); - - A_pk = convert(zp_pm, A_p, zpk_pm); - B_pk = convert(zp_pm, B_p, zpk_pm); - U_pk = convert(zp_pm, U_p, zpk_pm); - V_pk = convert(zp_pm, V_p, zpk_pm); - - TRACE("polynomial::factorization::multivariate", - tout << "zpk_pm = Z_" << zpk_pm.m().m().to_string(zpk_pm.m().p()) << endl; - tout << "A_pk = " << A_pk << endl; - tout << "B_pk = " << B_pk << endl; - tout << "U_pk = " << U_pk << endl; - tout << "V_pk = " << V_pk << endl; - ); - - SASSERT(check_solve(zpk_pm, ideal, A_pk, B_pk, one_p, U_pk, V_pk)); - - while (k < e) { - - // standard hensel: - // (C - AB) and is divisible by p^k, so we compute f = (C - AB)/p^k mod ideal in Z[...] - zp_polynomial_ref f_pk(zpk_pm); - polynomial_ref A_pk_in_Z(pm), B_pk_in_Z(pm), AB_in_Z(pm), f_in_Z(pm); - f_in_Z = convert(zpe_pm, C_pe, pm); - A_pk_in_Z = convert(zpk_pm, A_pk, pm); - B_pk_in_Z = convert(zpk_pm, B_pk, pm); - AB_in_Z = pm.mul(A_pk_in_Z, B_pk_in_Z); - AB_in_Z = pm.mod_d(AB_in_Z, ideal); - f_in_Z = pm.sub(f_in_Z, AB_in_Z); - f_in_Z = pm.exact_div(f_in_Z, pk); - f_in_Z = pm.mod_d(f_in_Z, ideal); - f_pk = convert(pm, f_in_Z, zpk_pm); - - TRACE("polynomial::factorization::multivariate", - tout << "zpk_pm = Z_" << zpk_pm.m().m().to_string(zpk_pm.m().p()) << endl; - tout << "f_pk = " << f_pk << endl; - ); - - // standard hensel we need to lift to p^(2k) - // we have U*A+V*B = 1, C = A*B, so p^k divides C - AB - // we want A1 = A + p^k*S, B1 = B + p^k*T, and also - // C - (A + p^k*S)*(B + p^k*T) = 0 mod (p^2k) - // C - A*B = p^k (T*A + S*B), i.e. - // f = (C - A*B)/p^k = (T*A + S*B), so we solve this equation in Z_p^k - polynomial_ref S_in_Z(pm), T_in_Z(pm); - solve(zpk_pm, x, ideal, A_pk, U_pk, B_pk, V_pk, f_pk, pm, T_in_Z, S_in_Z); - - TRACE("polynomial::factorization::multivariate", - tout << "zpk_pm = Z_" << zpk_pm.m().m().to_string(zpk_pm.m().p()) << endl; - tout << "S_in_Z = " << S_in_Z << endl; - tout << "T_in_Z = " << T_in_Z << endl; - ); - - // lift A and B to, A = A + p^k*S, B = B + p^k*T - polynomial_ref A_next_in_Z(pm), B_next_in_Z(pm); - S_in_Z = pm.mul(pk, S_in_Z); - S_in_Z = pm.mod_d(S_in_Z, ideal); - A_next_in_Z = convert(zpk_pm, A_pk, pm); - A_next_in_Z = pm.add(A_next_in_Z, S_in_Z); - T_in_Z = pm.mul(pk, T_in_Z); - T_in_Z = pm.mod_d(T_in_Z, ideal); - B_next_in_Z = convert(zpk_pm, B_pk, pm); - B_next_in_Z = pm.add(B_next_in_Z, T_in_Z); - - TRACE("polynomial::factorization::multivariate", - tout << "pk = " << nm.to_string(pk) << endl; - tout << "zpk_pm = Z_" << zpk_pm.m().m().to_string(zpk_pm.m().p()) << endl; - tout << "S_in_Z = " << S_in_Z << endl; - tout << "T_in_Z = " << T_in_Z << endl; - tout << "A_pk = " << A_pk << endl; - tout << "B_pk = " << B_pk << endl; - tout << "A_next_in_Z = " << A_next_in_Z << endl; - tout << "B_next_in_Z = " << B_next_in_Z << endl; - ); - - bool eq1 = are_equal_in(zpk_pm, A_next_in_Z, A_pk); - SASSERT(eq1); - bool eq2 = are_equal_in(zpk_pm, B_next_in_Z, B_pk); - SASSERT(eq2); - - // again, classic quadratic hensel - // we need A*U1 + B*V1 = 1 mod p^2k, from above - // U1 = U + p^k*S, V1 = V + p^k*T, hence A*U + B*V + p^k*(S + T) = 1 mod (p^2k) - // we know that p^k divides (1-UA-BV) so we compute f = (1-UA-BV)/p^k - // UA + VB + p^k(SA + TB) = 1 (mod p^k) - // SA + TB = f (mod ideal) - // we solve for S, T again, and do as above - polynomial_ref U_pk_in_Z(pm), V_pk_in_Z(pm), UA_in_Z(pm), BV_in_Z(pm); - U_pk_in_Z = convert(zpk_pm, U_pk, pm); - V_pk_in_Z = convert(zpk_pm, V_pk, pm); - f_in_Z = pm.mk_const(one); - UA_in_Z = pm.mul(U_pk_in_Z, A_next_in_Z); - UA_in_Z = pm.mod_d(UA_in_Z, ideal); - BV_in_Z = pm.mul(V_pk_in_Z, B_next_in_Z); - BV_in_Z = pm.mod_d(BV_in_Z, ideal); - f_in_Z = pm.sub(f_in_Z, UA_in_Z); - f_in_Z = pm.sub(f_in_Z, BV_in_Z); - - TRACE("polynomial::factorization::multivariate", - tout << "pk = " << nm.to_string(pk) << endl; - tout << "zpk_pm = Z_" << zpk_pm.m().m().to_string(zpk_pm.m().p()) << endl; - tout << "U_pk_in_Z = " << U_pk_in_Z << endl; - tout << "V_pk_in_Z = " << V_pk_in_Z << endl; - tout << "UA_in_Z = " << UA_in_Z << endl; - tout << "BV_in_Z = " << BV_in_Z << endl; - tout << "f_in_Z = " << f_in_Z << endl; - ); - - f_in_Z = pm.exact_div(f_in_Z, pk); - f_pk = convert(pm, f_in_Z, zpk_pm); - - // get the S, T, solution to A*S+B*T = f, with d(T, x) < d(A, x) - solve(zpk_pm, x, ideal, A_pk, U_pk, B_pk, V_pk, f_pk, pm, S_in_Z, T_in_Z); - - TRACE("polynomial::factorization::multivariate", - tout << "pk = " << nm.to_string(pk) << endl; - tout << "zpk_pm = Z_" << zpk_pm.m().m().to_string(zpk_pm.m().p()) << endl; - tout << "S_in_Z = " << S_in_Z << endl; - tout << "T_in_Z = " << T_in_Z << endl; - ); - - // go to the next zpk - scoped_numeral next_pk(nm); - nm.mul(pk, pk, next_pk); - zpk_nm.set_p(next_pk); - - TRACE("polynomial::factorization::multivariate", - tout << "zp_pk = Z_" << zpk_pm.m().m().to_string(zpk_pm.m().p()) << endl; - ); - - // lift U - zp_polynomial_ref S_pk(zpk_pm); - S_in_Z = pm.mul(pk, S_in_Z); - S_pk = convert(pm, S_in_Z, zpk_pm); - - TRACE("polynomial::factorization::multivariate", - tout << "S_pk = " << S_pk << endl; - ); - - U_pk = zpk_pm.add(U_pk, S_pk); - // lift V - zp_polynomial_ref T_pk(zpk_pm); - T_in_Z = pm.mul(pk, T_in_Z); - T_pk = convert(pm, T_in_Z, zpk_pm); - - TRACE("polynomial::factorization::multivariate", - tout << "T_pk = " << T_pk << endl; - ); - - V_pk = zpk_pm.add(V_pk, T_pk); - - // lift A and B - TRACE("polynomial::factorization::multivariate", - tout << "A_pk_in_Z = " << A_pk_in_Z << endl; - tout << "B_pk_in_Z = " << B_pk_in_Z << endl; - ); - A_pk = convert(pm, A_pk_in_Z, zpk_pm); - B_pk = convert(pm, B_pk_in_Z, zpk_pm); - - // move to the next pk - k *= 2; - nm.set(pk, next_pk); - - TRACE("polynomial::factorization::multivariate", - tout << "zp_pk = Z_" << zpk_pm.m().m().to_string(zpk_pm.m().p()) << endl; - tout << "A_pk = " << A_pk << endl; - tout << "B_pk = " << B_pk << endl; - tout << "U_pk = " << U_pk << endl; - tout << "V_pk = " << V_pk << endl; - tout << "C_pe = " << C_pe << endl; - ); - - SASSERT(check_solve(zpk_pm, ideal, A_pk, B_pk, one_p, U_pk, V_pk)); - } - - // now convert to the non-sliding zpe_manager - SASSERT(k == e); - A_lifted = convert(zpk_pm, A_pk, zpe_pm); - B_lifted = convert(zpk_pm, B_pk, zpe_pm); -} - -/** - f: target multivariate polynomial mod x_i^d_i, p^e - x: main variable - all_vars: all variables (including x) - A, B, U, V: univariate polynomials in Z_p[x] such that U*A+B*V=1 from ext gcd - - output: A_lifted, B_lifted d(A) = d(A_lifted), A = A_lifted mod x_i^d_i, p - A_lifted*B_lifted = f mod x_i^d_i, p^e -*/ -void multivariate_hensel_lift( - manager & pm, zp_manager & zp_pm, zp_manager & zpe_pm, - zp_polynomial_ref const & f, var x, unsigned e, var_vector const & all_vars, - upolynomial::zp_manager & zp_upm, - upolynomial::numeral_vector const & U, upolynomial::numeral_vector const & A, - upolynomial::numeral_vector const & V, upolynomial::numeral_vector const & B, - var2degree & target_ideal, zp_polynomial_ref & A_lifted, zp_polynomial_ref & B_lifted) { - upolynomial::zp_numeral_manager & zp_nm = zp_upm.m(); - upolynomial::numeral_manager & nm = zp_nm.m(); - - TRACE("polynomial::factorization::multivariate", - tout << "polynomial::multiratiate_hensel_lift(" << endl; - tout << "f = " << f << "," << endl; - tout << "x = x" << x << "," << endl; - tout << "e = " << e << "," << endl; - tout << "U = "; zp_upm.display(tout, U); tout << "," << endl; - tout << "A = "; zp_upm.display(tout, A); tout << "," << endl; - tout << "V = "; zp_upm.display(tout, V); tout << "," << endl; - tout << "B = "; zp_upm.display(tout, B); tout << "," << endl; - tout << "target_ideal = " << target_ideal << "," << endl; - tout << "p = " << nm.to_string(zp_pm.m().p()) << endl; - tout << "pe = " << nm.to_string(zpe_pm.m().p()) << endl; - ); - - // multivariate versions of A, B, U, V that we keep lifting over ideal x_i^d_i - zp_polynomial_ref A_m_p(zp_pm), B_m_p(zp_pm), U_m_p(zp_pm), V_m_p(zp_pm); - A_m_p = zp_pm.to_polynomial(A, x); - B_m_p = zp_pm.to_polynomial(B, x); - U_m_p = zp_pm.to_polynomial(U, x); - V_m_p = zp_pm.to_polynomial(V, x); - - TRACE("polynomial::factorization::multivariate", - tout << "A_m_p = " << A_m_p << endl; - tout << "B_m_p = " << B_m_p << endl; - tout << "U_m_p = " << U_m_p << endl; - tout << "V_m_p = " << V_m_p << endl; - ); - - // the the target in Z_p[...] - zp_polynomial_ref C_m_p(zp_pm); - C_m_p = convert(zpe_pm, f, zp_pm); - - // lift each variable individually - var2degree lifted_ideal; - unsigned_vector lifted_degs; - for (unsigned i = 0; i < all_vars.size(); ++ i) { - if (all_vars[i] == x) { - // skip the main variable - continue; - } - // current variable and degree we are lifting to, y^(d_y), at least - var y = all_vars[i]; - // lift to y^(d_y) - multivariate_hansel_lift_ideal(zp_pm, x, C_m_p, A_m_p, U_m_p, B_m_p, V_m_p, lifted_ideal, y, target_ideal.degree(y)); - } - - TRACE("polynomial::factorization::multivariate", - tout << "A_m_p = " << A_m_p << endl; - tout << "B_m_p = " << B_m_p << endl; - tout << "U_m_p = " << U_m_p << endl; - tout << "V_m_p = " << V_m_p << endl; - tout << "lifted_ideal = " << lifted_ideal << endl; - ); - - // now lift it all to p^e - multivariate_hansel_lift_zp(pm, zp_pm, zpe_pm, f, x, e, A_m_p, U_m_p, B_m_p, V_m_p, lifted_ideal, A_lifted, B_lifted); -} - - -/** - f: multivariate polynomial - x: main variable - all_vars: all variables (including x) - f_u: f mod x_1, ..., x_n (excluding mod x), i.e. this is f(0, x), f_u is square_free - f_u_zp_factors: monic factors of f_u (mod p), pairvise gcd = 1 - - we're lifting the factors to mod x_1^d_1, ..., x_n&d_n (excliding x), mod p^e - i.e. such that f congruent to the new factors. output goes to f_zpe factors. -*/ -void multivariate_hensel_lift( - manager & pm, zp_manager & zp_pm, zp_manager & zpe_pm, - polynomial_ref const & f, var x, unsigned e, var_vector const & all_vars, - upolynomial::manager & upm, upolynomial::numeral_vector const & f_u, - upolynomial::zp_factors const & f_u_zp_factors, - var2degree & target_ideal, - zp_factors & f_zpe_factors) { - SASSERT(f_u_zp_factors.distinct_factors() > 1); - - TRACE("polynomial::factorization::multivariate", - tout << "polynomial::multivariate_hensel_lift(" << endl; - tout << "f = " << f << "," << endl; - tout << "x = x" << x << "," << endl; - tout << "e = " << e << "," << endl; - tout << "f_u = "; upm.display(tout, f_u); tout << "," << endl; - tout << "f_u_zp_factors" << f_u_zp_factors << "," << endl; - tout << "target_ideal = " << target_ideal << "," << endl; - tout << "f_zpe_factors = " << f_zpe_factors << ")" << endl; - ); - - // managers and all - numeral_manager & nm = pm.m(); - upolynomial::zp_manager & zp_upm = f_u_zp_factors.upm(); - // upolynomial::zp_numeral_manager & zp_nm = zp_upm.m(); - upolynomial::zp_numeral_manager & zpe_nm = zpe_pm.m(); - upolynomial::zp_manager zpe_upm(zpe_nm); - - // the targed product we want (mod x_i^d_i, mod p^e) - zp_polynomial_ref f_target_zpe(zpe_pm); - f_target_zpe = convert(pm, f, zpe_pm); - f_target_zpe = zpe_pm.mod_d(f_target_zpe, target_ideal); - - TRACE("polynomial::factorization::multivariate", - tout << "target_ideal = " << target_ideal << endl; - tout << "f_target_zpe = " << f_target_zpe << endl; - ); - - // we do the product by doing individual lifting like in the univarate case - zp_polynomial_ref B(zp_pm), C_p(zp_pm); - zp_polynomial_ref A_lifted(zpe_pm), B_lifted(zpe_pm); - upolynomial::scoped_numeral_vector B_u(nm), C_u(nm), tmp_u(nm); - upolynomial::scoped_numeral_vector U(nm), V(nm); - for (int i = 0, i_end = f_u_zp_factors.distinct_factors() - 1; i < i_end; ++ i) - { - // get the univarate ones to lift now - upolynomial::numeral_vector const & A_u = f_u_zp_factors[i]; - // current starting product is f_target_zpe(0, x) in *Z_p* - zp_upm.to_numeral_vector(f_target_zpe, x, C_u); - // we get the rest into B (mod p) - zp_upm.exact_div(C_u, A_u, B_u); - - TRACE("polynomial::factorization::multivariate", - tout << "p = " << nm.to_string(zp_upm.m().p()) << endl; - tout << "f_target_zpe = " << f_target_zpe << endl; - tout << "A_u = "; upm.display(tout, A_u); tout << endl; - tout << "B_u = "; upm.display(tout, B_u); tout << endl; - tout << "C_u = "; upm.display(tout, C_u); tout << endl; - ); - - // and get the U, V, such that A*U+B*V = 1 - zp_upm.ext_gcd(A_u, B_u, U, V, tmp_u); - - TRACE("polynomial::factorization::multivariate", - tout << "U = "; upm.display(tout, U); tout << endl; - tout << "V = "; upm.display(tout, V); tout << endl; - tout << "gcd = "; upm.display(tout, tmp_u); tout << endl; - ); - - // do the lifting for this pair - multivariate_hensel_lift(pm, zp_pm, zpe_pm, f_target_zpe, x, e, all_vars, zp_upm, U, A_u, V, B_u, target_ideal, A_lifted, B_lifted); - - // add the lifted A to the output - f_zpe_factors.push_back(A_lifted, 1); - // move to the new target by dividing with the lifted A - f_target_zpe = zpe_pm.exact_div(f_target_zpe, A_lifted); - } - - // add the last f_target - f_zpe_factors.push_back(f_target_zpe, 1); -} - -class mfactorization_combination_iterator : public upolynomial::factorization_combination_iterator_base { - - /** main variable */ - var m_x; - -public: - - mfactorization_combination_iterator(zp_factors const & factors, var x) - : upolynomial::factorization_combination_iterator_base(factors) - {} - - /** - \brief Filter the ones not in the degree set. - */ - bool filter_current() const { - return false; - } - - /** - \brief Returns the degree of the current selection. - */ - unsigned current_degree() const { - unsigned degree = 0; - zp_manager & pm = m_factors.pm(); - for (unsigned i = 0; i < left_size(); ++ i) { - degree += pm.degree(m_factors[m_current[i]], m_x); - } - return degree; - } - - void left(zp_polynomial_ref & out) const { - SASSERT(m_current_size > 0); - zp_manager & zp_pm = m_factors.pm(); - out = m_factors[m_current[0]]; - for (int i = 1; i < m_current_size; ++ i) { - out = zp_pm.mul(out, m_factors[m_current[i]]); - } - } - - void get_left_tail_coeff(numeral const & m, numeral & out) { - zp_manager & zp_pm = m_factors.pm(); - upolynomial::zp_numeral_manager & zp_nm = zp_pm.m(); - zp_nm.set(out, m); - for (int i = 0; i < m_current_size; ++ i) { - zp_nm.mul(out, zp_pm.numeral_tc(m_factors[m_current[i]]), out); - } - } - - void get_right_tail_coeff(numeral const & m, numeral & out) { - zp_manager & zp_pm = m_factors.pm(); - upolynomial::zp_numeral_manager & zp_nm = zp_pm.m(); - zp_nm.set(out, m); - - unsigned current = 0; - unsigned selection_i = 0; - - // selection is ordered, so we just take the ones in between that are not disable - while (current < m_factors.distinct_factors()) { - if (!m_enabled[current]) { - // by skipping the disabled we never skip a selected one - current ++; - } else { - if (selection_i >= m_current.size() || (int) current < m_current[selection_i]) { - SASSERT(m_factors.get_degree(current) == 1); - zp_nm.mul(out, zp_pm.numeral_tc(m_factors[current]), out); - current ++; - } else { - current ++; - selection_i ++; - } - } - } - } - - void right(zp_polynomial_ref & out) const { - SASSERT(m_current_size > 0); - zp_manager & zp_pm = m_factors.pm(); - upolynomial::zp_numeral_manager & zp_nm = zp_pm.m(); - - unsigned current = 0; - unsigned selection_i = 0; - - numeral one; - zp_nm.set(one, 1); - out = zp_pm.mk_const(one); - - // selection is ordered, so we just take the ones in between that are not disable - while (current < m_factors.distinct_factors()) { - if (!m_enabled[current]) { - // by skipping the disabled we never skip a selected one - current ++; - } else { - if (selection_i >= m_current.size() || (int) current < m_current[selection_i]) { - SASSERT(m_factors.get_degree(current) == 1); - out = zp_pm.mul(out, m_factors[current]); - current ++; - } else { - current ++; - selection_i ++; - } - } - } - } -}; - - -// the multivariate factorization -bool factor_square_free_primitive(polynomial_ref const & f, factors & f_factors) { - - TRACE("polynomial::factorization", tout << "polynomial::factor_square_free_primitive(f = " << f << ", factors = " << f_factors << ")" << endl;); - - manager & pm = f.m(); - numeral_manager & nm = pm.m(); - - // to start with, maybe this should be part of input - var x = pm.max_var(f); - // get all the variables - var_vector vars, vars_no_x; - pm.vars(f, vars); - for(unsigned i = 0; i < vars.size(); ++ i) { - if (vars[i] != x) { - vars_no_x.push_back(vars[i]); - } - } - SASSERT(vars.size() > 1); - - // degree of the main variable - unsigned x_degree = pm.degree(f, x); - // the leading coefficient - polynomial_ref f_lc(pm); - f_lc = pm.coeff(f, x, x_degree); - - // the vector of values we substitute - upolynomial::scoped_numeral_vector a(nm); - - // the univariate polynomial - upolynomial::manager upm(nm); - upolynomial::scoped_numeral_vector f_u(upm); - - // generate the values to substitute and substitute them to get f_u(x) = f(a, x), the univariate version of f - unsigned size = 1; - a.resize(vars_no_x.size()); - for (unsigned i = 0; i < a.size(); ++ i) { nm.reset(a[i]); } - generate_substitution_values(f, x, f_lc, vars_no_x, size, a, upm, f_u); - - TRACE("polynomial::factorization::multivariate", - tout << "f_u = "; upm.display(tout, f_u); tout << endl; - tout << "substitution:" << endl; - for (unsigned i = 0; i < vars_no_x.size(); ++ i) { - tout << "x" << vars[i] << " -> " << nm.to_string(a[i]) << endl; - }); - - // the primitive part of f_u - scoped_numeral f_u_lc(nm); - upolynomial::scoped_numeral_vector f_u_pp(nm); - upm.get_primitive_and_content(f_u, f_u_pp, f_u_lc); - - TRACE("polynomial::factorization::multivariate", - tout << "f_u_lc" << nm.to_string(f_u_lc) << endl; - tout << "f_u_pp = "; upm.display(tout, f_u_pp); tout << endl; - ); - - // factor the univariate one - upolynomial::factors factors_u(upm); - upolynomial::factor_square_free(upm, f_u, factors_u); - - TRACE("polynomial::factorization::multivariate", - tout << "factors_u = " << factors_u << endl; - ); - - // if there is no univariate factors, it's irreducible - if (factors_u.distinct_factors() == 1) { - f_factors.push_back(f, 1); - return false; - } - - // translate f with a, so that we work modulo x_i^k and not (x_i - a_i)^k - polynomial_ref f_t(pm); - // Do the translation, we must have that a[x] = 0 - pm.translate(f, vars_no_x, a, f_t); - - TRACE("polynomial::factorization::multivariate", - tout << "f_t = " << f_t << endl; - ); - - // the zp manager stuff, we'll be changing the base - upolynomial::zp_numeral_manager zp_nm(nm, 2); - upolynomial::zp_manager zp_upm(zp_nm); - - // get the first prime number p that keeps f square-free - scoped_numeral p(nm); - prime_iterator prime_it; - upolynomial::scoped_numeral_vector f_u_pp_zp(nm); - do { - // create Z_p with the next prime - nm.set(p, prime_it.next()); - // translate to Zp[x] - zp_nm.set_p(p); - upolynomial::to_zp_manager(zp_upm, f_u_pp, f_u_pp_zp); - } while (!zp_upm.is_square_free(f_u_pp_zp)); - - TRACE("polynomial::factorization::multivariate", - tout << "p = " << p << endl; - tout << "f_t = " << f_t << endl; - ); - - // convert factors of f to factors modulo p (monic ones) - upolynomial::zp_factors factors_u_zp(zp_upm); - upolynomial::scoped_numeral_vector current_factor(nm); - for (unsigned i = 0; i < factors_u.distinct_factors(); ++ i) { - upolynomial::to_zp_manager(zp_upm, factors_u[i], current_factor); - zp_upm.mk_monic(current_factor); - factors_u_zp.push_back_swap(current_factor, 1); - } - - TRACE("polynomial::factorization::multivariate", - tout << "factors_u_zp = " << factors_u_zp << endl; - ); - - // compute factor coefficient bound (pover p^e) of the translated f with the leading coefficient added, i.e. - // f_t*lc(f_t, x) = f_t*lc(f, x) - unsigned e; - scoped_numeral p_e(nm); - var2degree target_ideal; - upolynomial::scoped_numeral f_t_lc(nm); - nm.set(f_t_lc, pm.numeral_lc(f_t, x)); - polynomial_ref f_t_with_lc(pm); - f_t_with_lc = pm.mul(f_t_lc, f_t); - multivariate_factor_coefficient_bound(f_t_with_lc, x, p, e, p_e, target_ideal); - - TRACE("polynomial::factorization::multivariate", - tout << "target_ideal = " << target_ideal << endl; - ); - - // do the multivariate lifting of the translated one f_t - upolynomial::zp_numeral_manager zpe_nm(nm, p_e); - zp_manager zpe_pm(zpe_nm, &pm.mm()); - zp_manager zp_pm(zp_nm, &pm.mm()); - zp_factors factors_zpe(zpe_pm); - multivariate_hensel_lift(pm, zp_pm, zpe_pm, f_t, x, e, vars, upm, f_u_pp_zp, factors_u_zp, target_ideal, factors_zpe); - - TRACE("polynomial::factorization::multivariate", - tout << "factors_zpe = " << factors_zpe << endl; - ); - - // try the factors from the lifted combinations - factors f_t_factors(pm); - bool remove = false; - mfactorization_combination_iterator it(factors_zpe, x); - unsigned max_degre = pm.degree(f_t, x) / 2; - zp_polynomial_ref zpe_trial_factor(zpe_pm); - while (it.next(remove)) { - // - // our bound ensures we can extract the right factors of degree at most 1/2 of the original - // so, if out trial factor has degree bigger than 1/2, we need to take the rest of the factors - // but, if we take the rest and it works, it doesn't meen that the rest is factorized, so we still take out - // the original factor - // - bool using_left = it.current_degree() <= max_degre; - if (using_left) { - // do a quick check first - it.left(zpe_trial_factor); - } else { - // do a quick check first - it.right(zpe_trial_factor); - } - // add the lc(f_pp) to the trial divisor - zpe_trial_factor = zpe_pm.mul(f_t_lc, zpe_trial_factor); - polynomial_ref trial_factor(pm), trial_factor_quo(pm); - trial_factor = convert(zpe_pm, zpe_trial_factor, pm); - bool true_factor = true; - trial_factor_quo = pm.exact_div(f_t_with_lc, trial_factor); - // if division is precise we have a factor - if (true_factor) { - if (!using_left) { - // as noted above, we still use the original factor - trial_factor.swap(trial_factor_quo); - } - // We need to get the content out of the factor - upolynomial::scoped_numeral trial_factor_cont(nm); - pm.int_content(f_t, trial_factor_cont); - trial_factor = pm.exact_div(trial_factor, trial_factor_cont); - // add the factor - f_t_factors.push_back(trial_factor, 1); - // we continue with the int-primitive quotient (with the lc added back) - // but we also have to keep lc(f_t)*f_t - pm.int_content(trial_factor_quo, f_t_lc); // content - trial_factor_quo = pm.exact_div(trial_factor_quo, f_t_lc); - nm.set(f_t_lc, pm.numeral_lc(trial_factor_quo, x)); - f_t = pm.mul(f_t_lc, trial_factor_quo); - // but we also remove it from the iterator - remove = true; - } else { - // don't remove this combination - remove = false; - } - } - - // translate the factor back - for (unsigned i = 0; i < a.size(); ++ i) { - nm.neg(a[i]); - } - for (unsigned i = 0; i < f_t_factors.distinct_factors(); ++ i) { - polynomial_ref factor(pm); - pm.translate(f_t_factors[i], vars_no_x, a, factor); - f_factors.push_back(factor, 1); - } - - TRACE("polynomial::factorization", tout << "polynomial::factor_square_free_primitive(f = " << f << ") => " << f_factors << endl;); - return true; -} - -}; // end polynomial namespace - -#endif diff --git a/src/math/polynomial/polynomial_factorization.h b/src/math/polynomial/polynomial_factorization.h deleted file mode 100644 index f069121ba..000000000 --- a/src/math/polynomial/polynomial_factorization.h +++ /dev/null @@ -1,65 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - polynomial_factorization.h - -Abstract: - - Methods for factoring polynomials. - -Author: - - Dejan (t-dejanj) 2011-11-29 - -Notes: - - [1] Elwyn Ralph Berlekamp. Factoring Polynomials over Finite Fields. Bell System Technical Journal, - 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. - ---*/ - -#pragma once - -#if 0 -// Disabled for reorg -#include "polynomial.h" -#include "upolynomial.h" -#include "bit_vector.h" -#include "z3_exception.h" - -namespace polynomial { - - /** - \brief Something to throw when we are in trouble. - */ - class factorization_exception : public default_exception { - public: - factorization_exception(char const * msg) : default_exception(msg) {} - }; - - /** - \brief Factor the polynomial f from Z[x1, ..., x_n]. Returns the index of the last factor that is completely - factored. I.e., if the method returns m, then f_1, ..., f_m are true irreducible factors, and the rest might - be further reducible. - */ - unsigned factor(polynomial_ref & f, factors & factors); - - /** - \brief Factor the square-free primitive polynomial f from Z[x1, ..., x_n]. Returns true if the factorization - was sucesseful, i.e. it was completed and the result is complete. Otherwise the quarantee is that the all but - the last factor are irreducible. - */ - bool factor_square_free_primitive(polynomial_ref const & f, factors & factors); -} - -inline std::ostream & operator<<(std::ostream & out, polynomial::factors & factors) { - factors.display(out); - return out; -} - -#endif From 8f95ee01e199b874f6542dbedaa3f0cb9ba804d4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 10 Jan 2017 14:02:59 +0000 Subject: [PATCH 14/47] Removed polynomial factorization test cases. Relates to #852 and fixes #865. --- src/test/main.cpp | 1 - src/test/polynomial.cpp | 1 - src/test/polynomial_factorization.cpp | 746 -------------------------- 3 files changed, 748 deletions(-) delete mode 100644 src/test/polynomial_factorization.cpp diff --git a/src/test/main.cpp b/src/test/main.cpp index 320eddd7b..9239d0119 100644 --- a/src/test/main.cpp +++ b/src/test/main.cpp @@ -193,7 +193,6 @@ int main(int argc, char ** argv) { TST(polynomial); TST(upolynomial); TST(algebraic); - TST(polynomial_factorization); TST(prime_generator); TST(permutation); TST(nlsat); diff --git a/src/test/polynomial.cpp b/src/test/polynomial.cpp index 56eb61a11..03eb321cd 100644 --- a/src/test/polynomial.cpp +++ b/src/test/polynomial.cpp @@ -18,7 +18,6 @@ Notes: --*/ #if !defined(__clang__) #include"polynomial.h" -#include"polynomial_factorization.h" #include"polynomial_var2value.h" #include"polynomial_cache.h" #include"linear_eq_solver.h" diff --git a/src/test/polynomial_factorization.cpp b/src/test/polynomial_factorization.cpp deleted file mode 100644 index 361ca4630..000000000 --- a/src/test/polynomial_factorization.cpp +++ /dev/null @@ -1,746 +0,0 @@ -/*++ -Copyright (c) 2011 Microsoft Corporation - -Module Name: - - polynomial_factorization.cpp - -Abstract: - - Testing of factorization. - -Author: - - Dejan (t-dejanj) 2011-11-29 - -Notes: - ---*/ -#include"upolynomial_factorization_int.h" -#include"timeit.h" -#include"polynomial.h" -#include"rlimit.h" -#if 0 -#include"polynomial_factorization.h" -#endif - -using std::cout; -using std::endl; - -// some prime numbers -unsigned primes[] = { - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 -}; - -// [i,l]: how many factors the Knuth example has over p_i, when i = 0 it's Z, p_1 = 2, for l=0 distinct, for l = 1 total -unsigned knuth_factors[2][11] = { - // x^8 + x^6 + 10*x^4 + 10*x^3 + 8*x^2 + 2*x + 8 - {2, 2, 3, 3, 2, 3, 1, 4, 3, 1, 1}, - {8, 2, 3, 3, 2, 3, 1, 4, 3, 1, 1}, -}; - -// [k,l,i]: how many factors the S_k has over p_i, when i = 0 it's Z, p_1 = 2, for l=0 distinct, for l = 1 total -unsigned swinnerton_dyer_factors[5][2][11] = { - // S1 = (x^2) - 2 - { - // 2, 3, 5, 7,11,13,17,19,23,29, Z - {1, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1}, - {2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1} - }, - // S2 = (x^4) - 10*(x^2) + 1 - { - {1, 1, 2, 2, 2, 2, 2, 2, 4, 2, 1}, - {4, 2, 2, 2, 2, 2, 2, 2, 4, 2, 1} - }, - // S3 = (x^8) - 40*(x^6) + 352*(x^4) - 960*(x^2) + 576 - { - {1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 1}, - {8, 6, 4, 4, 4, 4, 4, 4, 4, 4, 1} - }, - // S4 = (x^16) - 136*(x^14) + 6476*(x^12) - 141912*(x^10) + 1513334*(x^8) - 7453176*(x^6) + 13950764*(x^4) - 5596840*(x^2) + 46225 - { - {1, 4, 3, 4, 8, 8, 8, 8, 8, 8, 1}, - {16, 12, 10, 8, 8, 8, 8, 8, 8, 8, 1} - }, - // SA = S1*S2*S3*S4 - { - //p = 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, Z - { 2, 6, 3, 6, 15, 11, 16, 15, 18, 15, 1}, - {30, 21, 17, 16, 15, 15, 16, 15, 18, 15, 1} - } -}; - -int random_polynomial[20][2][11] = { - { - // 3*x^10 + 2*x^9 + 4*x^8 + 4*x^7 + 4*x^6 + x^5 + 3*x^2 + 3*x - { 4, 3, 4, 4, 3, 4, 4, 4, 3, 4, 2 }, - { 7, 7, 4, 4, 3, 4, 4, 4, 3, 4, 2 }, - }, - { - // 4*x^9 + 4*x^8 + x^7 + x^6 + 2*x^5 + 3*x^4 + 4*x^2 + 4*x - { 2, 2, 3, 3, 4, 2, 5, 3, 4, 2, 2 }, - { 5, 2, 3, 3, 4, 2, 5, 3, 5, 2, 2 }, - }, - { - // 3*x^10 + 4*x^9 + 3*x^8 + x^6 + 4*x^5 + 4*x^4 + x^2 - { 3, 2, 4, 4, 5, 3, 4, 2, 4, 5, 2 }, - { 6, 3, 5, 5, 6, 4, 5, 3, 5, 7, 3 }, - }, - { - // x^10 + 4*x^9 + x^8 + 3*x^7 + 3*x^4 + 3*x^3 + x^2 + 4*x - { 3, 4, 4, 3, 3, 3, 4, 4, 5, 3, 2 }, - { 8, 4, 4, 3, 3, 3, 4, 4, 5, 3, 2 }, - }, - { - // x^9 + 2*x^8 + 3*x^7 + x^6 + 2*x^5 + 4*x^4 + 3*x^2 - { 3, 3, 3, 3, 4, 4, 4, 3, 3, 4, 2 }, - { 5, 6, 4, 5, 5, 6, 5, 4, 4, 5, 3 }, - }, - { - // x^10 + x^9 + 4*x^7 + x^6 + 3*x^5 + x^4 + x^3 + x - { 3, 2, 3, 3, 3, 5, 3, 2, 4, 4, 2 }, - { 3, 2, 3, 3, 3, 5, 3, 2, 4, 4, 2 }, - }, - { - // 4*x^10 + 4*x^9 + x^8 + 2*x^7 + 3*x^6 + 4*x^5 + 3*x^4 + x^3 + 2*x^2 + 4*x - { 3, 3, 2, 5, 3, 4, 2, 4, 5, 5, 2 }, - { 5, 3, 2, 5, 3, 4, 2, 4, 5, 5, 2 }, - }, - { - // 3*x^10 + 4*x^9 + 3*x^8 + x^7 + x^6 + 2*x^5 + x^4 + 2*x^3 + 2*x^2 + x - { 3, 4, 6, 4, 4, 4, 4, 6, 6, 4, 3 }, - { 4, 4, 7, 4, 4, 4, 4, 6, 6, 4, 3 }, - }, - { - // 4*x^10 + x^9 + x^7 + 2*x^5 + 3*x^3 + x^2 + 4*x - { 3, 3, 3, 4, 4, 5, 4, 5, 2, 4, 2 }, - { 4, 4, 3, 4, 4, 5, 4, 5, 2, 4, 2 }, - }, - { - // x^10 + 3*x^9 + 3*x^8 + x^7 + 3*x^6 + 3*x^5 + 3*x^4 + x^2 + 3*x - { 2, 3, 4, 4, 3, 3, 4, 3, 3, 4, 2 }, - { 2, 4, 5, 4, 3, 3, 4, 3, 3, 4, 2 }, - }, - { - // x^10 + x^9 + 2*x^8 + x^7 + 4*x^6 + 2*x^5 + 3*x^4 + 4*x^3 + x^2 + 2*x - { 3, 4, 4, 3, 3, 3, 3, 4, 5, 3, 2 }, - { 4, 4, 4, 3, 3, 3, 3, 4, 5, 3, 2 }, - }, - { - // 3*x^9 + x^8 + 3*x^7 + 3*x^6 + x^5 + 2*x^4 + 4*x^3 + 4*x^2 + 3*x - { 4, 3, 3, 3, 5, 3, 6, 4, 2, 2, 2 }, - { 6, 4, 3, 3, 5, 3, 6, 4, 2, 2, 2 }, - }, - { - // 2*x^10 + 3*x^9 + 2*x^8 + 4*x^7 + x^6 + 3*x^5 + 2*x^3 + 3*x^2 + 2*x + 2 - { 3, 3, 3, 5, 4, 5, 6, 7, 4, 6, 3 }, - { 8, 4, 3, 7, 4, 5, 6, 7, 4, 7, 3 }, - }, - { - // 3*x^10 + x^9 + 4*x^8 + 2*x^7 + x^6 + 4*x^5 + x^4 + 3*x^3 + x + 2 - { 3, 3, 3, 2, 6, 4, 4, 4, 3, 3, 2 }, - { 3, 3, 3, 2, 6, 5, 4, 5, 3, 3, 2 }, - }, - { - // 4*x^10 + 2*x^9 + x^8 + x^6 + x^5 + 3*x^4 + 4*x^3 + x^2 + x - { 3, 4, 2, 4, 4, 4, 4, 2, 3, 3, 2 }, - { 6, 4, 2, 4, 4, 4, 4, 2, 3, 3, 2 }, - }, - { - // 4*x^10 + 2*x^7 + 4*x^6 + 2*x^3 + x - { 1, 3, 3, 3, 4, 4, 4, 3, 3, 2, 2 }, - { 1, 3, 3, 3, 4, 4, 4, 3, 3, 2, 2 }, - }, - { - // 4*x^10 + x^9 + x^8 + 4*x^7 + 4*x^4 + 2*x^2 + x + 4 - { 3, 4, 2, 5, 3, 6, 3, 6, 3, 3, 2 }, - { 3, 6, 2, 5, 3, 6, 3, 6, 3, 3, 2 }, - }, - { - // 3*x^10 + 2*x^8 + x^7 + x^6 + 3*x^4 + 3*x^3 + 4*x^2 + 3*x - { 4, 3, 4, 3, 3, 3, 2, 4, 4, 3, 2 }, - { 5, 4, 4, 3, 3, 3, 2, 4, 4, 3, 2 }, - }, - { - // x^10 + 2*x^9 + 2*x^6 + 4*x^3 + 4*x^2 - { 1, 2, 2, 3, 3, 4, 3, 3, 3, 3, 2 }, - { 10, 3, 3, 4, 4, 6, 4, 4, 4, 4, 3 }, - }, - { - // x^10 + 2*x^9 + 2*x^8 + 4*x^7 + 4*x^6 + x^5 + x^3 + x^2 + 3*x - { 2, 4, 2, 3, 3, 3, 5, 5, 6, 2, 2 }, - { 2, 5, 2, 3, 3, 3, 5, 5, 6, 2, 2 }, - } -}; - -#if 0 -static void tst_square_free_finite_1() { - polynomial::numeral_manager nm; - reslimit rl; polynomial::manager pm(rl, nm); - - // example from Knuth, p. 442 - polynomial_ref x(pm); - x = pm.mk_polynomial(pm.mk_var()); - - // polynomials \prod_{i < p} (x - i)^i - for (unsigned prime_i = 0; prime_i < 5; ++ prime_i) - { - int p = primes[prime_i]; - - // make the polynomial - polynomial_ref f(pm); - f = x - 1; - for (int i = 2; i < p; ++ i) { - f = f*((x + (-i))^i); - } - cout << "Factoring " << f << " into square-free over Z_" << p << endl; - - // convert to univariate over Z_p - upolynomial::zp_manager upm(nm); - upm.set_zp(p); - upolynomial::numeral_vector f_u; - upm.to_numeral_vector(f, f_u); - - cout << "Input: "; upm.display(cout, f_u); cout << endl; - - // factor it - upolynomial::zp_factors f_factors(upm); - cout << "Start: " << f_factors << endl; - - upolynomial::zp_square_free_factor(upm, f_u, f_factors); - - upolynomial::numeral_vector mult; - f_factors.multiply(mult); - cout << "Multiplied: "; upm.display(cout, mult); cout << endl; - - SASSERT(upm.eq(mult, f_u)); - - // remove the temps - upm.reset(f_u); - upm.reset(mult); - } -} - -static void tst_factor_finite_1() { - - polynomial::numeral_manager nm; - reslimit rl; polynomial::manager pm(rl, nm); - - // example from Knuth, p. 442 - polynomial_ref x(pm); - x = pm.mk_polynomial(pm.mk_var()); - polynomial_ref K(pm); - K = (x^8) + (x^6) + 10*(x^4) + 10*(x^3) + 8*(x^2) + 2*x + 8; - - // factor them for all the prime numbers - for (unsigned prime_i = 0; prime_i < sizeof(primes)/sizeof(unsigned); ++ prime_i) - { - // make the Z_p - unsigned prime = primes[prime_i]; - upolynomial::zp_manager upm(nm); - upm.set_zp(prime); - - // make the polynomial in Z_p - upolynomial::numeral_vector K_u; - upm.to_numeral_vector(K, K_u); - - cout << "Factoring " << K << "("; upm.display(cout, K_u); cout << ") in Z_" << prime << endl; - cout << "Expecting " << knuth_factors[0][prime_i] << " distinct factors, " << knuth_factors[1][prime_i] << " total" << endl; - - // factor it - upolynomial::zp_factors factors(upm); - /* bool factorized = */ upolynomial::zp_factor(upm, K_u, factors); - - // check the result - unsigned distinct = factors.distinct_factors(); - unsigned total = factors.total_factors(); - - cout << "Got " << factors << endl; - cout << "Thats " << distinct << " distinct factors, " << total << " total" << endl; - - SASSERT(knuth_factors[0][prime_i] == distinct); - SASSERT(knuth_factors[1][prime_i] == total); - - upolynomial::numeral_vector multiplied; - factors.multiply(multiplied); - SASSERT(upm.eq(K_u, multiplied)); - upm.reset(multiplied); - - // remove the temp - upm.reset(K_u); - } -} - -static void tst_factor_finite_2() { - - polynomial::numeral_manager nm; - reslimit rl; polynomial::manager pm(rl, nm); - - polynomial_ref x(pm); - x = pm.mk_polynomial(pm.mk_var()); - - // Swinnerton-Dyer polynomials (irreducible, modular factors of degree at most 2) - polynomial_ref S1 = (x^2) - 2; - polynomial_ref S2 = (x^4) - 10*(x^2) + 1; - polynomial_ref S3 = (x^8) - 40*(x^6) + 352*(x^4) - 960*(x^2) + 576; - polynomial_ref S4 = (x^16) - 136*(x^14) + 6476*(x^12) - 141912*(x^10) + 1513334*(x^8) - 7453176*(x^6) + 13950764*(x^4) - 5596840*(x^2) + 46225; - - vector S; - S.push_back(S1); - S.push_back(S2); - S.push_back(S3); - S.push_back(S4); - S.push_back(S1*S2*S3*S4); - - // factor all the S_i them for all the prime numbers - for (unsigned S_i = 0; S_i < S.size(); ++ S_i) { - for (unsigned prime_i = 0; prime_i < sizeof(primes)/sizeof(unsigned); ++ prime_i) { - unsigned prime = primes[prime_i]; - - upolynomial::zp_manager upm(nm); - upm.set_zp(prime); - - upolynomial::numeral_vector S_i_u; - upm.to_numeral_vector(S[S_i], S_i_u); - - cout << "Factoring "; upm.display(cout, S_i_u); cout << " over Z_" << prime << endl; - cout << "Expecting " << swinnerton_dyer_factors[S_i][0][prime_i] << " distinct factors, " << swinnerton_dyer_factors[S_i][1][prime_i] << " total" << endl; - - upolynomial::zp_factors factors(upm); - upolynomial::zp_factor(upm, S_i_u, factors); - - // check the result - unsigned distinct = factors.distinct_factors(); - unsigned total = factors.total_factors(); - - cout << "Got " << factors << endl; - cout << "Thats " << distinct << " distinct factors, " << total << " total" << endl; - - SASSERT(swinnerton_dyer_factors[S_i][0][prime_i] == distinct); - SASSERT(swinnerton_dyer_factors[S_i][1][prime_i] == total); - - upolynomial::numeral_vector multiplied; - factors.multiply(multiplied); - SASSERT(upm.eq(S_i_u, multiplied)); - upm.reset(multiplied); - - // remove the temp - upm.reset(S_i_u); - } - } -} - -static void tst_factor_finite_3() { - - polynomial::numeral_manager nm; - reslimit rl; polynomial::manager pm(rl, nm); - - polynomial_ref x(pm); - x = pm.mk_polynomial(pm.mk_var()); - - // random polynomials - vector random_p; - random_p.push_back( 3*(x^10) + 2*(x^9) + 4*(x^8) + 4*(x^7) + 4*(x^6) + 1*(x^5) + 3*(x^2) + 3*x + 0 ); - random_p.push_back( 4*(x^9) + 4*(x^8) + 1*(x^7) + 1*(x^6) + 2*(x^5) + 3*(x^4) + 4*(x^2) + 4*x + 0 ); - random_p.push_back( 3*(x^10) + 4*(x^9) + 3*(x^8) + 1*(x^6) + 4*(x^5) + 4*(x^4) + 1*(x^2) + 0 ); - random_p.push_back( 1*(x^10) + 4*(x^9) + 1*(x^8) + 3*(x^7) + 3*(x^4) + 3*(x^3) + 1*(x^2) + 4*x + 0 ); - random_p.push_back( 1*(x^9) + 2*(x^8) + 3*(x^7) + 1*(x^6) + 2*(x^5) + 4*(x^4) + 3*(x^2) + 0 ); - random_p.push_back( 1*(x^10) + 1*(x^9) + 4*(x^7) + 1*(x^6) + 3*(x^5) + 1*(x^4) + 1*(x^3) + 1*x + 0 ); - random_p.push_back( 4*(x^10) + 4*(x^9) + 1*(x^8) + 2*(x^7) + 3*(x^6) + 4*(x^5) + 3*(x^4) + 1*(x^3) + 2*(x^2) + 4*x + 0 ); - random_p.push_back( 3*(x^10) + 4*(x^9) + 3*(x^8) + 1*(x^7) + 1*(x^6) + 2*(x^5) + 1*(x^4) + 2*(x^3) + 2*(x^2) + 1*x + 0 ); - random_p.push_back( 4*(x^10) + 1*(x^9) + 1*(x^7) + 2*(x^5) + 3*(x^3) + 1*(x^2) + 4*x + 0 ); - random_p.push_back( 1*(x^10) + 3*(x^9) + 3*(x^8) + 1*(x^7) + 3*(x^6) + 3*(x^5) + 3*(x^4) + 1*(x^2) + 3*x + 0 ); - random_p.push_back( 1*(x^10) + 1*(x^9) + 2*(x^8) + 1*(x^7) + 4*(x^6) + 2*(x^5) + 3*(x^4) + 4*(x^3) + 1*(x^2) + 2*x + 0 ); - random_p.push_back( 3*(x^9) + 1*(x^8) + 3*(x^7) + 3*(x^6) + 1*(x^5) + 2*(x^4) + 4*(x^3) + 4*(x^2) + 3*x + 0 ); - random_p.push_back( 2*(x^10) + 3*(x^9) + 2*(x^8) + 4*(x^7) + 1*(x^6) + 3*(x^5) + 2*(x^3) + 3*(x^2) + 2*x + 2 ); - random_p.push_back( 3*(x^10) + 1*(x^9) + 4*(x^8) + 2*(x^7) + 1*(x^6) + 4*(x^5) + 1*(x^4) + 3*(x^3) + 1*x + 2 ); - random_p.push_back( 4*(x^10) + 2*(x^9) + 1*(x^8) + 1*(x^6) + 1*(x^5) + 3*(x^4) + 4*(x^3) + 1*(x^2) + 1*x + 0 ); - random_p.push_back( 4*(x^10) + 2*(x^7) + 4*(x^6) + 2*(x^3) + 1*x + 0 ); - random_p.push_back( 4*(x^10) + 1*(x^9) + 1*(x^8) + 4*(x^7) + 4*(x^4) + 2*(x^2) + 1*x + 4 ); - random_p.push_back( 3*(x^10) + 2*(x^8) + 1*(x^7) + 1*(x^6) + 3*(x^4) + 3*(x^3) + 4*(x^2) + 3*x + 0 ); - random_p.push_back( 1*(x^10) + 2*(x^9) + 2*(x^6) + 4*(x^3) + 4*(x^2) + 0 ); - random_p.push_back( 1*(x^10) + 2*(x^9) + 2*(x^8) + 4*(x^7) + 4*(x^6) + 1*(x^5) + 1*(x^3) + 1*(x^2) + 3*x + 0 ); - - // factor all the randoms them for all the prime numbers - for (unsigned random_i = 0; random_i < random_p.size(); ++ random_i) { - for (unsigned prime_i = 0; prime_i < sizeof(primes)/sizeof(unsigned); ++ prime_i) { - unsigned prime = primes[prime_i]; - - upolynomial::zp_manager upm(nm); - upm.set_zp(prime); - - upolynomial::numeral_vector poly; - upm.to_numeral_vector(random_p[random_i], poly); - - cout << "Factoring "; upm.display(cout, poly); cout << " over Z_" << prime << endl; - cout << "Expecting " << swinnerton_dyer_factors[random_i][0][prime_i] << " distinct factors, " << random_polynomial[random_i][1][prime_i] << " total" << endl; - - upolynomial::zp_factors factors(upm); - upolynomial::zp_factor(upm, poly, factors); - - // check the result - unsigned distinct = factors.distinct_factors(); - unsigned total = factors.total_factors(); - - cout << "Got " << factors << endl; - cout << "Thats " << distinct << " distinct factors, " << total << " total" << endl; - - // SASSERT(random_polynomial[random_i][0][prime_i] == distinct); - // SASSERT(random_polynomial[random_i][1][prime_i] == total); - - upolynomial::numeral_vector multiplied; - factors.multiply(multiplied); - bool equal = upm.eq(poly, multiplied); - cout << (equal ? "equal" : "not equal") << endl; - SASSERT(equal); - upm.reset(multiplied); - - // remove the temp - upm.reset(poly); - } - } -} - -static void tst_factor_enumeration() { - polynomial::numeral_manager nm; - reslimit rl; polynomial::manager pm(rl, nm); - - polynomial_ref x(pm); - x = pm.mk_polynomial(pm.mk_var()); - - vector factors; - for (int i = 0; i < 5; ++ i) { - polynomial_ref factor(pm); - factor = x + i; - factors.push_back(factor); - } - - upolynomial::manager upm(nm); - - upolynomial::zp_manager upm_13(nm); - upm_13.set_zp(13); - upolynomial::zp_factors factors_13(upm_13); - - upolynomial::numeral constant; - nm.set(constant, 10); - factors_13.set_constant(constant); - - for (unsigned i = 0; i < 5; ++ i) { - upolynomial::numeral_vector ufactor; - upm_13.to_numeral_vector(factors[i], ufactor); - factors_13.push_back(ufactor, 1); - upm.reset(ufactor); - } - - cout << "All: " << factors_13 << endl; - - upolynomial::factorization_degree_set degrees(factors_13); - degrees.display(cout); cout << endl; - - scoped_mpz_vector left(nm), right(nm); - upolynomial::ufactorization_combination_iterator it(factors_13, degrees); - unsigned i = 0; - it.display(cout); - bool remove = false; - while (it.next(remove)) { - it.left(left); - it.right(right); - cout << "Left " << i << ": "; upm.display(cout, left); cout << endl; - cout << "Right " << i << ": "; upm.display(cout, right); cout << endl; - i ++; - if (i % 3 == 0) { - remove = true; - } else { - remove = false; - } - it.display(cout); - } - // SASSERT(i == 15); - - return; - - for (unsigned i = 0; i < 5; ++ i) { - factors_13.set_degree(i, factors_13.get_degree(i) + i); - } - cout << "Different: " << factors_13 << " of degree " << factors_13.get_degree() << endl; - upolynomial::factorization_degree_set degrees1(factors_13); - degrees1.display(cout); cout << endl; // [0, ..., 15] - - polynomial_ref tmp1 = (x^3) + 1; - polynomial_ref tmp2 = (x^5) + 2; - polynomial_ref tmp3 = (x^7) + 3; - upolynomial::numeral_vector up1, up2, up3; - upm_13.to_numeral_vector(tmp1, up1); - upm_13.to_numeral_vector(tmp2, up2); - upm_13.to_numeral_vector(tmp3, up3); - upolynomial::zp_factors tmp(upm_13); - tmp.push_back(up1, 1); - tmp.push_back(up2, 1); - tmp.push_back(up3, 1); - upm_13.reset(up1); - upm_13.reset(up2); - upm_13.reset(up3); - - cout << "Different: " << tmp << " of degree " << tmp.get_degree() << endl; - upolynomial::factorization_degree_set degrees2(tmp); - degrees2.display(cout); cout << endl; - - tmp1 = (x^2) + 1; - tmp2 = (x^10) + 2; - tmp3 = x + 3; - upm_13.to_numeral_vector(tmp1, up1); - upm_13.to_numeral_vector(tmp2, up2); - upm_13.to_numeral_vector(tmp3, up3); - tmp.clear(); - tmp.push_back(up1, 2); - tmp.push_back(up2, 1); - tmp.push_back(up3, 1); - cout << "Different: " << tmp << " of degree " << tmp.get_degree() << endl; - upm_13.reset(up1); - upm_13.reset(up2); - upm_13.reset(up3); - upolynomial::factorization_degree_set degrees3(tmp); - degrees3.display(cout); cout << endl; - degrees1.intersect(degrees3); - degrees1.display(cout); cout << endl; -} - -static void tst_factor_square_free_univariate_1(unsigned max_length) { - - polynomial::numeral_manager nm; - upolynomial::numeral test; - upolynomial::numeral p; - nm.set(test, -9); - nm.set(p, 5); - nm.mod(test, p, test); - - reslimit rl; polynomial::manager pm(rl, nm); - - polynomial_ref x(pm); - x = pm.mk_polynomial(pm.mk_var()); - - cout << "R. = QQ['x']" << endl; - - // let's start with \prod (p_i x^{p_{i+1} - p_{i+1}) - unsigned n_primes = sizeof(primes)/sizeof(unsigned); - max_length = std::min(max_length, n_primes); - for(unsigned length = 1; length < max_length; ++ length) { - - // starting from prime_i going for length - for(unsigned start_i = 0; start_i < n_primes; ++ start_i) { - - polynomial_ref f(pm); - - bool first = true; - for (unsigned prime_i = 0; prime_i < length; ++ prime_i) { - int p1 = primes[(start_i + prime_i) % n_primes]; - int p2 = primes[(start_i + prime_i + 1) % n_primes]; - if (first) { - f = (p1*(x^p2) - p2); - first = false; - } else { - f = f*(p1*(x^p2) - p2); - } - } - - upolynomial::manager upm(nm); - scoped_mpz_vector f_u(nm); - upm.to_numeral_vector(f, f_u); - - cout << "factoring "; upm.display(cout, f_u); cout << endl; - cout << "expecting " << length << " factors "; - upolynomial::factors factors(upm); - /* bool ok = */ upolynomial::factor_square_free(upm, f_u, factors); - cout << "got " << factors << endl; - - SASSERT(factors.distinct_factors() == length); - } - } -} - -static void tst_factor_square_free_univariate_2() { - polynomial::numeral_manager nm; - reslimit rl; polynomial::manager pm(rl, nm); - - polynomial_ref x(pm); - x = pm.mk_polynomial(pm.mk_var()); - - // Swinnerton-Dyer polynomials (irreducible, modular factors of degree at most 2) - polynomial_ref S1 = (x^2) - 2; - polynomial_ref S2 = (x^4) - 10*(x^2) + 1; - polynomial_ref S3 = (x^8) - 40*(x^6) + 352*(x^4) - 960*(x^2) + 576; - polynomial_ref S4 = (x^16) - 136*(x^14) + 6476*(x^12) - 141912*(x^10) + 1513334*(x^8) - 7453176*(x^6) + 13950764*(x^4) - 5596840*(x^2) + 46225; - - vector S; - S.push_back(S1); - S.push_back(S2); - S.push_back(S3); - S.push_back(S4); - - upolynomial::manager upm(nm); - - // factor all the S_i them for all the prime numbers - for (unsigned S_i = 0; S_i < S.size(); ++ S_i) { - upolynomial::numeral_vector S_i_u; - upm.to_numeral_vector(S[S_i], S_i_u); - - cout << "Factoring "; upm.display(cout, S_i_u); cout << " over Z " << endl; - upolynomial::factors factors(upm); - upolynomial::factor_square_free(upm, S_i_u, factors); - - // check the result - cout << "Got " << factors << endl; - - // remove the temp - upm.reset(S_i_u); - } -} - -static void tst_factor_square_free_univariate_3() { - polynomial::numeral_manager nm; - reslimit rl; polynomial::manager pm(rl, nm); - - polynomial_ref x(pm); - x = pm.mk_polynomial(pm.mk_var()); - - polynomial_ref deg70 = (x^70) - 6*(x^65) - (x^60) + 60*(x^55) - 54*(x^50) - 230*(x^45) + 274*(x^40) + 542*(x^35) - 615*(x^30) - 1120*(x^25) + 1500*(x^20) - 160*(x^15) - 395*(x^10) + 76*(x^5) + 34; - - upolynomial::manager upm(nm); - upolynomial::numeral_vector deg70_u; - - upm.to_numeral_vector(deg70, deg70_u); - - cout << "Factoring "; upm.display(cout, deg70_u); cout << " over Z " << endl; - upolynomial::factors factors(upm); - upolynomial::factor_square_free(upm, deg70_u, factors); - - cout << "Got " << factors << endl; - - upm.reset(deg70_u); -} -#endif - -void tst_factor_swinnerton_dyer_big(unsigned max) { - polynomial::numeral_manager nm; - reslimit rl; polynomial::manager pm(rl, nm); - - polynomial_ref x(pm); - x = pm.mk_polynomial(pm.mk_var()); - - vector roots; - vector vars; - - unsigned n = std::min(max, static_cast(sizeof(primes)/sizeof(unsigned))); - for(unsigned prime_i = 0; prime_i < n; ++ prime_i) { - - int prime = primes[prime_i]; - - cout << "Computing Swinnerton-Dyer[" << prime_i + 1 << "]" << endl; - - polynomial_ref y(pm); - vars.push_back(pm.mk_var()); - y = pm.mk_polynomial(vars.back()); - - polynomial_ref p(pm); - p = (y^2) - prime; - roots.push_back(p); - - polynomial_ref computation = x; - for (unsigned i = 0; i < roots.size(); ++ i) { - polynomial_ref var(pm); - var = pm.mk_polynomial(vars[i]); - computation = computation - var; - } - - { - timeit timer(true, "computing swinnerton-dyer"); - - for (unsigned i = 0; i < roots.size(); ++ i) { - polynomial_ref tmp(pm); - pm.resultant(computation, roots[i], vars[i], tmp); - computation = tmp; - } - } - - cout << "Computed Swinnerton-Dyer[" << prime_i + 1 << "], degree = " << pm.total_degree(computation) << ", size = " << pm.size(computation) << endl; - - cout << "Starting factoring " << endl; - - { - timeit timer(true, "factoring swinnerton-dyer"); - - reslimit rl; - upolynomial::manager upm(rl, nm); - scoped_mpz_vector sd_u(nm); - upm.to_numeral_vector(computation, sd_u); - upolynomial::factors factors(upm); - upolynomial::factor_square_free(upm, sd_u, factors); - cout << "Got " << factors.distinct_factors() << " factors" << endl; - } - - } -} - -static void tst_factor_square_free_multivariate_1(unsigned max_n) { -#if 0 - polynomial::numeral_manager nm; - upolynomial::numeral test; - upolynomial::numeral p; - nm.set(test, -9); - nm.set(p, 5); - nm.mod(test, p, test); - - reslimit rl; polynomial::manager pm(rl, nm); - - polynomial_ref x(pm); - x = pm.mk_polynomial(pm.mk_var()); - - polynomial_ref y(pm); - y = pm.mk_polynomial(pm.mk_var()); - - // lets start simple x^n - y^n - for (unsigned prime_i = 0; prime_i < sizeof(primes)/sizeof(unsigned); ++ prime_i) { - unsigned prime = primes[prime_i]; - - if (prime > max_n) { - break; - } - - polynomial_ref f = (x^prime) - (y^prime); - cout << "factoring: " << f << endl; - - // factor - polynomial::factors factors(pm); - polynomial::factor_square_free_primitive(f, factors); - - cout << "got: " << factors << endl; - } -#endif -} - - -void tst_polynomial_factorization() { - - enable_trace("polynomial::factorization"); - // enable_trace("polynomial::factorization::bughunt"); - enable_trace("polynomial::factorization::multivariate"); - // enable_trace("upolynomial"); - - // Z_p square-free factorization tests - // tst_square_free_finite_1(); - - // Z_p factorization tests - // tst_factor_finite_1(); - // tst_factor_finite_2(); - // tst_factor_finite_3(); - - // Z factorization - // tst_factor_enumeration(); - // tst_factor_square_free_univariate_1(3); - // tst_factor_square_free_univariate_2(); - // tst_factor_square_free_univariate_3(); - // tst_factor_swinnerton_dyer_big(3); - - // Multivariate factorization - tst_factor_square_free_multivariate_1(3); -} From 8047f0d91ae249d1e86c36bebc7c3b6e91c1ebfe Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 10 Jan 2017 14:06:30 +0000 Subject: [PATCH 15/47] GCC compilation/keyword fix. Relates to #864 --- src/smt/smt_context.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index 476a419eb..ea97d1a64 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -1413,8 +1413,8 @@ namespace smt { else { TRACE("add_diseq", display_eq_detail(tout, bool_var2enode(v));); if (!add_diseq(get_enode(lhs), get_enode(rhs)) && !inconsistent()) { - literal not_eq = literal(l.var(), true); - set_conflict(b_justification(mk_justification(eq_propagation_justification(get_enode(lhs), get_enode(rhs)))), not_eq); + literal n_eq = literal(l.var(), true); + set_conflict(b_justification(mk_justification(eq_propagation_justification(get_enode(lhs), get_enode(rhs)))), n_eq); } } } From dda1774fa184e60744901ed42940d33d7122079a Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 10 Jan 2017 08:21:49 -0800 Subject: [PATCH 16/47] update CMakeList to remove polynomial-factorization Signed-off-by: Nikolaj Bjorner --- contrib/cmake/src/test/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/cmake/src/test/CMakeLists.txt b/contrib/cmake/src/test/CMakeLists.txt index 6f6615e0c..6ea07e84c 100644 --- a/contrib/cmake/src/test/CMakeLists.txt +++ b/contrib/cmake/src/test/CMakeLists.txt @@ -82,7 +82,6 @@ add_executable(test-z3 pdr.cpp permutation.cpp polynomial.cpp - polynomial_factorization.cpp polynorm.cpp prime_generator.cpp proof_checker.cpp From ba9d36605ba4b1b393edb267baa7f91b0c3b7d5d Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 10 Jan 2017 20:12:08 +0000 Subject: [PATCH 17/47] Formatting, whitespace --- src/smt/smt_context.h | 156 +++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/src/smt/smt_context.h b/src/smt/smt_context.h index 0d758196e..b9b068442 100644 --- a/src/smt/smt_context.h +++ b/src/smt/smt_context.h @@ -50,9 +50,9 @@ Revision History: #include"statistics.h" #include"progress_callback.h" -// there is a significant space overhead with allocating 1000+ contexts in +// there is a significant space overhead with allocating 1000+ contexts in // the case that each context only references a few expressions. -// Using a map instead of a vector for the literals can compress space +// Using a map instead of a vector for the literals can compress space // consumption. #ifdef SPARSE_MAP #define USE_BOOL_VAR_VECTOR 0 @@ -98,7 +98,7 @@ namespace smt { // Remark: boolean expressions can also be internalized as // enodes. Examples: boolean expression nested in an // uninterpreted function. - expr_ref_vector m_e_internalized_stack; // stack of the expressions already internalized as enodes. + expr_ref_vector m_e_internalized_stack; // stack of the expressions already internalized as enodes. ptr_vector m_justifications; @@ -116,7 +116,7 @@ namespace smt { plugin_manager m_theories; // mapping from theory_id -> theory ptr_vector m_theory_set; // set of theories for fast traversal vector m_decl2enodes; // decl -> enode (for decls with arity > 0) - cg_table m_cg_table; + cg_table m_cg_table; dyn_ack_manager m_dyn_ack_manager; struct new_eq { enode * m_lhs; @@ -140,7 +140,7 @@ namespace smt { svector m_propagated_th_eqs; svector m_propagated_th_diseqs; svector m_diseq_vector; -#endif +#endif enode * m_is_diseq_tmp; // auxiliary enode used to find congruent equality atoms. tmp_enode m_tmp_enode; @@ -161,8 +161,8 @@ namespace smt { vector m_watches; //!< per literal vector m_lit_occs; //!< index for backward subsumption svector m_bdata; //!< mapping bool_var -> data - svector m_activity; - clause_vector m_aux_clauses; + svector m_activity; + clause_vector m_aux_clauses; clause_vector m_lemmas; vector m_clauses_to_reinit; expr_ref_vector m_units_to_reassert; @@ -176,7 +176,7 @@ namespace smt { bool m_phase_cache_on; unsigned m_phase_counter; //!< auxiliary variable used to decide when to turn on/off phase caching bool m_phase_default; //!< default phase when using phase caching - + // A conflict is usually a single justification. That is, a justification // for false. If m_not_l is not null_literal, then m_conflict is a // justification for l, and the conflict is union of m_no_l and m_conflict; @@ -220,10 +220,10 @@ namespace smt { // Unsat core extraction // // ----------------------------------- - typedef u_map literal2assumption; + typedef u_map literal2assumption; literal_vector m_assumptions; literal2assumption m_literal2assumption; // maps an expression associated with a literal to the original assumption - expr_ref_vector m_unsat_core; + expr_ref_vector m_unsat_core; // ----------------------------------- // @@ -261,7 +261,7 @@ namespace smt { SASSERT(e_internalized(n)); return m_app2enode[n->get_id()]; } - + /** \brief Similar to get_enode, but returns 0 if n is to e_internalized. */ @@ -323,7 +323,7 @@ namespace smt { literal enode2literal(enode const * n) const { SASSERT(n->is_bool()); return n == m_false_enode ? false_literal : literal(enode2bool_var(n)); - } + } unsigned get_num_bool_vars() const { return m_b_internalized_stack.size(); @@ -336,7 +336,7 @@ namespace smt { bool_var_data const & get_bdata(bool_var v) const { return m_bdata[v]; } - + lbool get_lit_assignment(unsigned lit_idx) const { return static_cast(m_assignment[lit_idx]); } @@ -349,8 +349,8 @@ namespace smt { return get_assignment(literal(v)); } - literal_vector const & assigned_literals() const { - return m_assigned_literals; + literal_vector const & assigned_literals() const { + return m_assigned_literals; } lbool get_assignment(expr * n) const; @@ -425,7 +425,7 @@ namespace smt { unsigned get_assign_level(literal l) const { return get_assign_level(l.var()); } - + /** \brief Return the scope level when v was internalized. */ @@ -436,7 +436,7 @@ namespace smt { theory * get_theory(theory_id th_id) const { return m_theories.get_plugin(th_id); } - + ptr_vector::const_iterator begin_theories() const { return m_theories.begin(); } @@ -450,7 +450,7 @@ namespace smt { } unsigned get_base_level() const { - return m_base_lvl; + return m_base_lvl; } bool at_base_level() const { @@ -470,11 +470,11 @@ namespace smt { } expr * bool_var2expr(bool_var v) const { - return m_bool_var2expr[v]; + return m_bool_var2expr[v]; } - + void literal2expr(literal l, expr_ref & result) const { - if (l == true_literal) + if (l == true_literal) result = m_manager.mk_true(); else if (l == false_literal) result = m_manager.mk_false(); @@ -501,7 +501,7 @@ namespace smt { unsigned id = decl->get_decl_id(); return id < m_decl2enodes.size() ? m_decl2enodes[id].begin() : 0; } - + enode_vector::const_iterator end_enodes_of(func_decl const * decl) const { unsigned id = decl->get_decl_id(); return id < m_decl2enodes.size() ? m_decl2enodes[id].end() : 0; @@ -591,7 +591,7 @@ namespace smt { void push_scope(); unsigned pop_scope_core(unsigned num_scopes); - + void pop_scope(unsigned num_scopes); void undo_trail_stack(unsigned old_size); @@ -617,13 +617,13 @@ namespace smt { bool is_empty_clause(clause const * c) const; void cache_generation(unsigned new_scope_lvl); - + void cache_generation(clause const * cls, unsigned new_scope_lvl); void cache_generation(unsigned num_lits, literal const * lits, unsigned new_scope_lvl); void cache_generation(expr * n, unsigned new_scope_lvl); - + void reset_cache_generation(); void reinit_clauses(unsigned num_scopes, unsigned num_bool_vars); @@ -632,14 +632,14 @@ namespace smt { // ----------------------------------- // - // Internalization + // Internalization // // ----------------------------------- public: bool b_internalized(expr const * n) const { return get_bool_var_of_id_option(n->get_id()) != null_bool_var; } - + bool lit_internalized(expr const * n) const { return m_manager.is_false(n) || (m_manager.is_not(n) ? b_internalized(to_app(n)->get_arg(0)) : b_internalized(n)); } @@ -648,7 +648,7 @@ namespace smt { return m_app2enode.get(n->get_id(), 0) != 0; } - unsigned get_num_b_internalized() const { + unsigned get_num_b_internalized() const { return m_b_internalized_stack.size(); } @@ -656,7 +656,7 @@ namespace smt { return m_b_internalized_stack.get(idx); } - unsigned get_num_e_internalized() const { + unsigned get_num_e_internalized() const { return m_e_internalized_stack.size(); } @@ -693,9 +693,9 @@ namespace smt { void ts_visit_child(expr * n, bool gate_ctx, svector & tcolors, svector & fcolors, svector & todo, bool & visited); bool ts_visit_children(expr * n, bool gate_ctx, svector & tcolors, svector & fcolors, svector & todo); - + void top_sort_expr(expr * n, svector & sorted_exprs); - + void assert_default(expr * n, proof * pr); void assert_distinct(app * n, proof * pr); @@ -723,7 +723,7 @@ namespace smt { void internalize_term(app * n); void internalize_ite_term(app * n); - + bool internalize_theory_term(app * n); void internalize_uninterpreted(app * n); @@ -754,7 +754,7 @@ namespace smt { bool simplify_aux_lemma_literals(unsigned & num_lits, literal * lits); void mark_for_reinit(clause * cls, unsigned scope_lvl, bool reinternalize_atoms); - + unsigned get_max_iscope_lvl(unsigned num_lits, literal const * lits) const; bool use_binary_clause_opt(literal l1, literal l2, bool lemma) const; @@ -786,7 +786,7 @@ namespace smt { void add_and_rel_watches(app * n); void add_or_rel_watches(app * n); - + void add_ite_rel_watches(app * n); void mk_not_cnstr(app * n); @@ -798,7 +798,7 @@ namespace smt { void mk_iff_cnstr(app * n); void mk_ite_cnstr(app * n); - + bool lit_occs_enabled() const { return m_fparams.m_phase_selection==PS_OCCURRENCE; } void add_lit_occs(clause * cls); @@ -821,7 +821,7 @@ namespace smt { bool_var mk_bool_var(expr * n); - + enode * mk_enode(app * n, bool suppress_args, bool merge_tf, bool cgc_enabled); void attach_th_var(enode * n, theory * th, theory_var v); @@ -830,7 +830,7 @@ namespace smt { justification * mk_justification(Justification const & j) { justification * js = new (m_region) Justification(j); SASSERT(js->in_region()); - if (js->has_del_eh()) + if (js->has_del_eh()) m_justifications.push_back(js); return js; } @@ -851,10 +851,10 @@ namespace smt { unsigned m_num_conflicts_since_lemma_gc; unsigned m_restart_threshold; unsigned m_restart_outer_threshold; - unsigned m_luby_idx; + unsigned m_luby_idx; double m_agility; unsigned m_lemma_gc_threshold; - + void assign_core(literal l, b_justification j, bool decision = false); void trace_assign(literal l, b_justification j, bool decision) const; @@ -880,7 +880,7 @@ namespace smt { friend class set_true_first_trail; void set_true_first_flag(bool_var v); - + bool try_true_first(bool_var v) const { return get_bdata(v).try_true_first(); } bool assume_eq(enode * lhs, enode * rhs); @@ -901,13 +901,13 @@ namespace smt { d.m_phase = phase; } - void force_phase(literal l) { + void force_phase(literal l) { force_phase(l.var(), !l.sign()); } bool contains_instance(quantifier * q, unsigned num_bindings, enode * const * bindings); - bool add_instance(quantifier * q, app * pat, unsigned num_bindings, enode * const * bindings, unsigned max_generation, + bool add_instance(quantifier * q, app * pat, unsigned num_bindings, enode * const * bindings, unsigned max_generation, unsigned min_top_generation, unsigned max_top_generation, ptr_vector & used_enodes); void set_global_generation(unsigned generation) { m_generation = generation; } @@ -960,7 +960,7 @@ namespace smt { void assign_quantifier(quantifier * q); - void set_conflict(b_justification js, literal not_l); + void set_conflict(b_justification js, literal not_l); void set_conflict(b_justification js) { set_conflict(js, null_literal); @@ -999,12 +999,12 @@ namespace smt { #define INV_ACTIVITY_LIMIT 1e-100 void rescale_bool_var_activity(); - + public: void inc_bvar_activity(bool_var v) { double & act = m_activity[v]; act += m_bvar_inc; - if (act > ACTIVITY_LIMIT) + if (act > ACTIVITY_LIMIT) rescale_bool_var_activity(); m_case_split_queue->activity_increased_eh(v); } @@ -1033,7 +1033,7 @@ namespace smt { } return false; } - + bool can_delete(clause * cls) const { if (cls->in_reinit_stack()) return false; @@ -1055,7 +1055,7 @@ namespace smt { bool validate_assumptions(unsigned num_assumptions, expr * const * assumptions); void init_assumptions(unsigned num_assumptions, expr * const * assumptions); - + void reset_assumptions(); void mk_unsat_core(); @@ -1075,9 +1075,9 @@ namespace smt { void tick(unsigned & counter) const; lbool bounded_search(); - + final_check_status final_check(); - + void check_proof(proof * pr); void forget_phase_of_vars_in_current_level(); @@ -1104,7 +1104,7 @@ namespace smt { public: // event handler for relevancy_propagator class - void relevant_eh(expr * n); + void relevant_eh(expr * n); bool is_relevant(expr * n) const { return !relevancy() || is_relevant_core(n); @@ -1128,9 +1128,9 @@ namespace smt { void mark_as_relevant(enode * n) { mark_as_relevant(n->get_owner()); } void mark_as_relevant(bool_var v) { mark_as_relevant(bool_var2expr(v)); } - + void mark_as_relevant(literal l) { mark_as_relevant(l.var()); } - + template relevancy_eh * mk_relevancy_eh(Eh const & eh) { return m_relevancy_propagator->mk_relevancy_eh(eh); @@ -1151,9 +1151,9 @@ namespace smt { void propagate_th_eqs(); void propagate_th_diseqs(); - + bool can_theories_propagate() const; - + bool propagate(); public: @@ -1169,7 +1169,7 @@ namespace smt { // ----------------------------------- // - // Pretty Printing + // Pretty Printing // // ----------------------------------- protected: @@ -1217,7 +1217,7 @@ namespace smt { void display_binary_clauses(std::ostream & out) const; void display_assignment(std::ostream & out) const; - + void display_eqc(std::ostream & out) const; void display_app_enode_map(std::ostream & out) const; @@ -1237,15 +1237,15 @@ namespace smt { void display_lemma_as_smt_problem(std::ostream & out, unsigned num_antecedents, literal const * antecedents, literal consequent = false_literal, symbol const& logic = symbol::null) const; void display_lemma_as_smt_problem(unsigned num_antecedents, literal const * antecedents, literal consequent = false_literal, symbol const& logic = symbol::null) const; - void display_lemma_as_smt_problem(std::ostream & out, unsigned num_antecedents, literal const * antecedents, - unsigned num_antecedent_eqs, enode_pair const * antecedent_eqs, + void display_lemma_as_smt_problem(std::ostream & out, unsigned num_antecedents, literal const * antecedents, + unsigned num_antecedent_eqs, enode_pair const * antecedent_eqs, literal consequent = false_literal, symbol const& logic = symbol::null) const; - void display_lemma_as_smt_problem(unsigned num_antecedents, literal const * antecedents, - unsigned num_antecedent_eqs, enode_pair const * antecedent_eqs, + void display_lemma_as_smt_problem(unsigned num_antecedents, literal const * antecedents, + unsigned num_antecedent_eqs, enode_pair const * antecedent_eqs, literal consequent = false_literal, symbol const& logic = symbol::null) const; - void display_assignment_as_smtlib2(std::ostream& out, symbol const& logic = symbol::null) const; + void display_assignment_as_smtlib2(std::ostream& out, symbol const& logic = symbol::null) const; void display_normalized_enodes(std::ostream & out) const; @@ -1291,13 +1291,13 @@ namespace smt { bool check_invariant() const; bool check_eqc_bool_assignment() const; - + bool check_missing_clause_propagation(clause_vector const & v) const; bool check_missing_bin_clause_propagation() const; bool check_missing_eq_propagation() const; - + bool check_missing_congruence() const; bool check_missing_bool_enode_propagation() const; @@ -1359,7 +1359,7 @@ namespace smt { static literal translate_literal( literal lit, context& src_ctx, context& dst_ctx, vector b2v, ast_translation& tr); - + /* \brief Utilities for consequence finding. */ @@ -1368,7 +1368,7 @@ namespace smt { u_map m_antecedents; void extract_fixed_consequences(literal lit, obj_map& var2val, index_set const& assumptions, expr_ref_vector& conseq); void extract_fixed_consequences(unsigned& idx, obj_map& var2val, index_set const& assumptions, expr_ref_vector& conseq); - + void display_consequence_progress(std::ostream& out, unsigned it, unsigned nv, unsigned fixed, unsigned unfixed, unsigned eq); unsigned delete_unfixed(obj_map& var2val, expr_ref_vector& unfixed); @@ -1380,7 +1380,7 @@ namespace smt { literal mk_diseq(expr* v, expr* val); - void validate_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars, + void validate_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector const& conseq, expr_ref_vector const& unfixed); bool validate_justification(bool_var v, bool_var_data const& d, b_justification const& j); @@ -1430,18 +1430,18 @@ namespace smt { void pop(unsigned num_scopes); - lbool check(unsigned num_assumptions = 0, expr * const * assumptions = 0, bool reset_cancel = true); + lbool check(unsigned num_assumptions = 0, expr * const * assumptions = 0, bool reset_cancel = true); lbool get_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector& conseq, expr_ref_vector& unfixed); lbool find_mutexes(expr_ref_vector const& vars, vector& mutexes); lbool preferred_sat(expr_ref_vector const& asms, vector& cores); - + lbool setup_and_check(bool reset_cancel = true); - + // return 'true' if assertions are inconsistent. - bool reduce_assertions(); + bool reduce_assertions(); bool resource_limits_exceeded(); @@ -1466,15 +1466,15 @@ namespace smt { } bool already_internalized() const { return m_e_internalized_stack.size() > 2 || m_b_internalized_stack.size() > 1; } - + unsigned get_unsat_core_size() const { return m_unsat_core.size(); } - + expr * get_unsat_core_expr(unsigned idx) const { return m_unsat_core.get(idx); } - + void get_model(model_ref & m) const; bool update_model(bool refinalize); @@ -1482,17 +1482,17 @@ namespace smt { void get_proto_model(proto_model_ref & m) const; bool validate_model(); - + unsigned get_num_asserted_formulas() const { return m_asserted_formulas.get_num_formulas(); } unsigned get_asserted_formulas_last_level() const { return m_asserted_formulas.get_formulas_last_level(); } expr * get_asserted_formula(unsigned idx) const { return m_asserted_formulas.get_formula(idx); } - + proof * get_asserted_formula_proof(unsigned idx) const { return m_asserted_formulas.get_formula_proof(idx); } - + expr * const * get_asserted_formulas() const { return m_asserted_formulas.get_formulas(); } - + proof * const * get_asserted_formula_proofs() const { return m_asserted_formulas.get_formula_proofs(); } void get_assumptions_core(ptr_vector & result); @@ -1504,7 +1504,7 @@ namespace smt { void display_unsat_core(std::ostream & out) const; void collect_statistics(::statistics & st) const; - + void display_statistics(std::ostream & out) const; void display_istatistics(std::ostream & out) const; From 384468bc997199bc2442155352999e534f49cd1c Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 10 Jan 2017 20:21:51 +0000 Subject: [PATCH 18/47] Added option to extend unsat cores with literals that (potentially) provide quantifier instances. --- src/smt/params/smt_params_helper.pyg | 7 +- src/smt/smt_solver.cpp | 182 +++++++++++++++++++++++---- 2 files changed, 160 insertions(+), 29 deletions(-) diff --git a/src/smt/params/smt_params_helper.pyg b/src/smt/params/smt_params_helper.pyg index 739af8bfe..178b2117f 100644 --- a/src/smt/params/smt_params_helper.pyg +++ b/src/smt/params/smt_params_helper.pyg @@ -1,4 +1,4 @@ -def_module_params(module_name='smt', +def_module_params(module_name='smt', class_name='smt_params_helper', description='smt solver based on lazy smt', export=True, @@ -17,7 +17,7 @@ def_module_params(module_name='smt', ('pull_nested_quantifiers', BOOL, False, 'pull nested quantifiers'), ('refine_inj_axioms', BOOL, True, 'refine injectivity axioms'), ('timeout', UINT, UINT_MAX, 'timeout (in milliseconds) (UINT_MAX and 0 mean no timeout)'), - ('rlimit', UINT, 0, 'resource limit (0 means no limit)'), + ('rlimit', UINT, 0, 'resource limit (0 means no limit)'), ('max_conflicts', UINT, UINT_MAX, 'maximum number of conflicts before giving up.'), ('mbqi', BOOL, True, 'model based quantifier instantiation (MBQI)'), ('mbqi.max_cexs', UINT, 1, 'initial maximal number of counterexamples used in MBQI, each counterexample generates a quantifier instantiation'), @@ -62,5 +62,6 @@ def_module_params(module_name='smt', ('dack.gc_inv_decay', DOUBLE, 0.8, 'Dynamic ackermannization garbage collection decay'), ('dack.threshold', UINT, 10, ' number of times the congruence rule must be used before Leibniz\'s axiom is expanded'), ('core.validate', BOOL, False, 'validate unsat core produced by SMT context'), - ('core.minimize', BOOL, False, 'minimize unsat core produced by SMT context') + ('core.minimize', BOOL, False, 'minimize unsat core produced by SMT context'), + ('core.extend_patterns', BOOL, False, 'extend unsat core with literals that trigger (potential) quantifier instances') )) diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp index 2ea4fea20..703e4489e 100644 --- a/src/smt/smt_solver.cpp +++ b/src/smt/smt_solver.cpp @@ -22,42 +22,62 @@ Notes: #include"smt_params.h" #include"smt_params_helper.hpp" #include"mus.h" - +#include"for_each_expr.h" +#include"ast_smt2_pp.h" +#include"func_decl_dependencies.h" +#include"dec_ref_util.h" namespace smt { class solver : public solver_na2as { - smt_params m_smt_params; - params_ref m_params; - smt::kernel m_context; - progress_callback * m_callback; - symbol m_logic; - bool m_minimizing_core; + smt_params m_smt_params; + params_ref m_params; + smt::kernel m_context; + progress_callback * m_callback; + symbol m_logic; + bool m_minimizing_core; + bool m_core_extend_patterns; + obj_map m_name2assertion; + public: - solver(ast_manager & m, params_ref const & p, symbol const & l): + solver(ast_manager & m, params_ref const & p, symbol const & l) : solver_na2as(m), m_smt_params(p), m_params(p), m_context(m, m_smt_params), - m_minimizing_core(false) { + m_minimizing_core(false), + m_core_extend_patterns(false) { m_logic = l; if (m_logic != symbol::null) m_context.set_logic(m_logic); + smt_params_helper smth(p); + m_core_extend_patterns = smth.core_extend_patterns(); } - virtual solver* translate(ast_manager& m, params_ref const& p) { - solver* result = alloc(solver, m, p, m_logic); + virtual solver * translate(ast_manager & m, params_ref const & p) { + solver * result = alloc(solver, m, p, m_logic); smt::kernel::copy(m_context, result->m_context); + + ast_translation translator(get_manager(), m); + obj_map::iterator it = m_name2assertion.begin(); + obj_map::iterator end = m_name2assertion.end(); + for (; it != end; it++) + result->m_name2assertion.insert(translator(it->m_key), + translator(it->m_value)); + return result; } - + virtual ~solver() { + dec_ref_values(get_manager(), m_name2assertion); } virtual void updt_params(params_ref const & p) { m_smt_params.updt_params(p); m_params.copy(p); m_context.updt_params(p); + smt_params_helper smth(p); + m_core_extend_patterns = smth.core_extend_patterns(); } virtual void collect_param_descrs(param_descrs & r) { @@ -81,6 +101,12 @@ namespace smt { m_context.assert_expr(t); } + virtual void assert_expr(expr * t, expr * a) { + solver_na2as::assert_expr(t, a); + get_manager().inc_ref(t); + m_name2assertion.insert(a, t); + } + virtual void push_core() { m_context.push(); } @@ -97,7 +123,7 @@ namespace smt { struct scoped_minimize_core { solver& s; expr_ref_vector m_assumptions; - scoped_minimize_core(solver& s): s(s), m_assumptions(s.m_assumptions) { + scoped_minimize_core(solver& s) : s(s), m_assumptions(s.m_assumptions) { s.m_minimizing_core = true; s.m_assumptions.reset(); } @@ -114,17 +140,19 @@ namespace smt { r.push_back(m_context.get_unsat_core_expr(i)); } - if (m_minimizing_core || smt_params_helper(m_params).core_minimize() == false) { - return; - } - scoped_minimize_core scm(*this); - mus mus(*this); - mus.add_soft(r.size(), r.c_ptr()); - ptr_vector r2; - if (l_true == mus.get_mus(r2)) { - r.reset(); - r.append(r2); + if (m_minimizing_core && smt_params_helper(m_params).core_minimize()) { + scoped_minimize_core scm(*this); + mus mus(*this); + mus.add_soft(r.size(), r.c_ptr()); + ptr_vector r2; + if (l_true == mus.get_mus(r2)) { + r.reset(); + r.append(r2); + } } + + if (m_core_extend_patterns) + add_pattern_literals_to_core(r); } virtual void get_model(model_ref & m) { @@ -149,7 +177,7 @@ namespace smt { r.append(tmp.size(), tmp.c_ptr()); } - virtual ast_manager& get_manager() const { return m_context.m(); } + virtual ast_manager & get_manager() const { return m_context.m(); } virtual void set_progress_callback(progress_callback * callback) { m_callback = callback; @@ -159,12 +187,114 @@ namespace smt { virtual unsigned get_num_assertions() const { return m_context.size(); } - + virtual expr * get_assertion(unsigned idx) const { SASSERT(idx < get_num_assertions()); return m_context.get_formulas()[idx]; - } + } + struct collect_fds_proc { + ast_manager & m; + func_decl_set & m_fds; + collect_fds_proc(ast_manager & m, func_decl_set & fds) : + m(m), m_fds(fds) { + } + void operator()(var * n) {} + void operator()(app * n) { + func_decl * fd = n->get_decl(); + if (fd->get_family_id() == null_family_id) + m_fds.insert_if_not_there(fd); + } + void operator()(quantifier * n) {} + }; + + struct collect_pattern_fds_proc { + ast_manager & m; + expr_fast_mark1 m_visited; + func_decl_set & m_fds; + collect_pattern_fds_proc(ast_manager & m, func_decl_set & fds) : + m(m), m_fds(fds) { + m_visited.reset(); + } + void operator()(var * n) {} + void operator()(app * n) {} + void operator()(quantifier * n) { + collect_fds_proc p(m, m_fds); + + unsigned sz = n->get_num_patterns(); + for (unsigned i = 0; i < sz; i++) + quick_for_each_expr(p, m_visited, n->get_pattern(i)); + + sz = n->get_num_no_patterns(); + for (unsigned i = 0; i < sz; i++) + quick_for_each_expr(p, m_visited, n->get_no_pattern(i)); + } + }; + + void collect_pattern_func_decls(expr_ref & e, func_decl_set & fds) { + collect_pattern_fds_proc p(get_manager(), fds); + expr_mark visited; + for_each_expr(p, visited, e); + } + + void compute_assrtn_fds(ptr_vector & core, vector & assrtn_fds) { + assrtn_fds.resize(m_name2assertion.size()); + obj_map::iterator ait = m_name2assertion.begin(); + obj_map::iterator aend = m_name2assertion.end(); + for (unsigned i = 0; ait != aend; ait++, i++) { + if (core.contains(ait->m_key)) + continue; + collect_fds_proc p(m, assrtn_fds[i]); + expr_fast_mark1 visited; + quick_for_each_expr(p, visited, ait->m_value); + } + } + + bool fds_intersect(func_decl_set & pattern_fds, func_decl_set & assrtn_fds) { + func_decl_set::iterator it = pattern_fds.begin(); + func_decl_set::iterator end = pattern_fds.end(); + for (; it != end; it++) { + func_decl * fd = *it; + if (assrtn_fds.contains(fd)) + return true; + } + return false; + } + + void add_pattern_literals_to_core(ptr_vector & core) { + ast_manager & m = get_manager(); + expr_ref_vector new_core_literals(m); + + func_decl_set pattern_fds; + vector assrtn_fds; + + do { + new_core_literals.reset(); + + unsigned sz = core.size(); + for (unsigned i = 0; i < sz; i++) { + expr_ref name(core[i], m); + expr_ref assrtn(m_name2assertion.find(name), m); + collect_pattern_func_decls(assrtn, pattern_fds); + } + + if (!pattern_fds.empty()) { + if (assrtn_fds.empty()) + compute_assrtn_fds(core, assrtn_fds); + + obj_map::iterator ait = m_name2assertion.begin(); + obj_map::iterator aend = m_name2assertion.end(); + for (unsigned i = 0; ait != aend; ait++, i++) { + if (!core.contains(ait->m_key) && + fds_intersect(pattern_fds, assrtn_fds[i])) + new_core_literals.push_back(ait->m_key); + } + } + + core.append(new_core_literals.size(), new_core_literals.c_ptr()); + } + while (!new_core_literals.empty()); + } }; }; From d8d869822fbe4026e7e9311a6bac8f0a62fdf091 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 10 Jan 2017 21:04:44 +0000 Subject: [PATCH 19/47] Cleaned up #include in api* objects. --- scripts/update_api.py | 1 + src/api/api_algebraic.cpp | 39 ++++++------ src/api/api_arith.cpp | 25 ++++---- src/api/api_array.cpp | 31 +++++----- src/api/api_bv.cpp | 37 ++++++------ src/api/api_datatype.cpp | 119 ++++++++++++++++++------------------ src/api/api_interp.cpp | 5 +- src/api/api_log.cpp | 1 - src/api/api_pb.cpp | 16 +++-- src/api/api_polynomial.cpp | 5 +- src/api/api_quant.cpp | 121 ++++++++++++++++++------------------- src/api/api_seq.cpp | 37 ++++++------ 12 files changed, 213 insertions(+), 224 deletions(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index e531a103c..b8978ff21 100755 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -1574,6 +1574,7 @@ def write_log_h_preamble(log_h): log_h.write('#define _Z3_UNUSED\n') log_h.write('#endif\n') # + log_h.write('#include\n') log_h.write('extern std::ostream * g_z3_log;\n') log_h.write('extern bool g_z3_log_enabled;\n') log_h.write('class z3_log_ctx { bool m_prev; public: z3_log_ctx():m_prev(g_z3_log_enabled) { g_z3_log_enabled = false; } ~z3_log_ctx() { g_z3_log_enabled = m_prev; } bool enabled() const { return m_prev; } };\n') diff --git a/src/api/api_algebraic.cpp b/src/api/api_algebraic.cpp index 2e14a1bd8..c4e4dac5d 100644 --- a/src/api/api_algebraic.cpp +++ b/src/api/api_algebraic.cpp @@ -7,7 +7,7 @@ Module Name: Abstract: - Additional APIs for handling Z3 algebraic numbers encoded as + Additional APIs for handling Z3 algebraic numbers encoded as Z3_ASTs Author: @@ -15,9 +15,8 @@ Author: Leonardo de Moura (leonardo) 2012-12-07 Notes: - + --*/ -#include #include"z3.h" #include"api_log_macros.h" #include"api_context.h" @@ -74,9 +73,9 @@ extern "C" { bool Z3_algebraic_is_value_core(Z3_context c, Z3_ast a) { api::context * _c = mk_c(c); - return - is_expr(a) && - (_c->autil().is_numeral(to_expr(a)) || + return + is_expr(a) && + (_c->autil().is_numeral(to_expr(a)) || _c->autil().is_irrational_algebraic_numeral(to_expr(a))); } @@ -162,9 +161,9 @@ extern "C" { Z3_ast Z3_API Z3_algebraic_add(Z3_context c, Z3_ast a, Z3_ast b) { Z3_TRY; LOG_Z3_algebraic_add(c, a, b); - RESET_ERROR_CODE(); - CHECK_IS_ALGEBRAIC_X(a, 0); - CHECK_IS_ALGEBRAIC_X(b, 0); + RESET_ERROR_CODE(); + CHECK_IS_ALGEBRAIC_X(a, 0); + CHECK_IS_ALGEBRAIC_X(b, 0); BIN_OP(+,add); Z3_CATCH_RETURN(0); } @@ -172,9 +171,9 @@ extern "C" { Z3_ast Z3_API Z3_algebraic_sub(Z3_context c, Z3_ast a, Z3_ast b) { Z3_TRY; LOG_Z3_algebraic_sub(c, a, b); - RESET_ERROR_CODE(); - CHECK_IS_ALGEBRAIC_X(a, 0); - CHECK_IS_ALGEBRAIC_X(b, 0); + RESET_ERROR_CODE(); + CHECK_IS_ALGEBRAIC_X(a, 0); + CHECK_IS_ALGEBRAIC_X(b, 0); BIN_OP(-,sub); Z3_CATCH_RETURN(0); } @@ -182,9 +181,9 @@ extern "C" { Z3_ast Z3_API Z3_algebraic_mul(Z3_context c, Z3_ast a, Z3_ast b) { Z3_TRY; LOG_Z3_algebraic_mul(c, a, b); - RESET_ERROR_CODE(); - CHECK_IS_ALGEBRAIC_X(a, 0); - CHECK_IS_ALGEBRAIC_X(b, 0); + RESET_ERROR_CODE(); + CHECK_IS_ALGEBRAIC_X(a, 0); + CHECK_IS_ALGEBRAIC_X(b, 0); BIN_OP(*,mul); Z3_CATCH_RETURN(0); } @@ -219,8 +218,8 @@ extern "C" { algebraic_numbers::manager & _am = am(c); scoped_anum _r(_am); if (is_rational(c, a)) { - scoped_anum av(_am); - _am.set(av, get_rational(c, a).to_mpq()); + scoped_anum av(_am); + _am.set(av, get_rational(c, a).to_mpq()); _am.root(av, k, _r); } else { @@ -241,8 +240,8 @@ extern "C" { algebraic_numbers::manager & _am = am(c); scoped_anum _r(_am); if (is_rational(c, a)) { - scoped_anum av(_am); - _am.set(av, get_rational(c, a).to_mpq()); + scoped_anum av(_am); + _am.set(av, get_rational(c, a).to_mpq()); _am.power(av, k, _r); } else { @@ -328,7 +327,7 @@ extern "C" { scoped_anum tmp(_am); for (unsigned i = 0; i < n; i++) { if (is_rational(c, a[i])) { - _am.set(tmp, get_rational(c, a[i]).to_mpq()); + _am.set(tmp, get_rational(c, a[i]).to_mpq()); as.push_back(tmp); } else if (is_irrational(c, a[i])) { diff --git a/src/api/api_arith.cpp b/src/api/api_arith.cpp index dcd250c98..51aea9676 100644 --- a/src/api/api_arith.cpp +++ b/src/api/api_arith.cpp @@ -15,7 +15,6 @@ Author: Revision History: --*/ -#include #include"z3.h" #include"api_log_macros.h" #include"api_context.h" @@ -37,7 +36,7 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } - + Z3_sort Z3_API Z3_mk_real_sort(Z3_context c) { Z3_TRY; LOG_Z3_mk_real_sort(c); @@ -50,7 +49,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_real(Z3_context c, int num, int den) { Z3_TRY; LOG_Z3_mk_real(c, num, den); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); if (den == 0) { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); @@ -60,7 +59,7 @@ extern "C" { RETURN_Z3(of_ast(a)); Z3_CATCH_RETURN(0); } - + MK_ARITH_OP(Z3_mk_add, OP_ADD); MK_ARITH_OP(Z3_mk_mul, OP_MUL); MK_BINARY_ARITH_OP(Z3_mk_power, OP_POWER); @@ -70,17 +69,17 @@ extern "C" { Z3_ast Z3_API Z3_mk_div(Z3_context c, Z3_ast n1, Z3_ast n2) { Z3_TRY; LOG_Z3_mk_div(c, n1, n2); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); decl_kind k = OP_IDIV; sort* ty = mk_c(c)->m().get_sort(to_expr(n1)); sort* real_ty = mk_c(c)->m().mk_sort(mk_c(c)->get_arith_fid(), REAL_SORT); if (ty == real_ty) { k = OP_DIV; } - expr * args[2] = { to_expr(n1), to_expr(n2) }; - ast* a = mk_c(c)->m().mk_app(mk_c(c)->get_arith_fid(), k, 0, 0, 2, args); - mk_c(c)->save_ast_trail(a); - check_sorts(c, a); + expr * args[2] = { to_expr(n1), to_expr(n2) }; + ast* a = mk_c(c)->m().mk_app(mk_c(c)->get_arith_fid(), k, 0, 0, 2, args); + mk_c(c)->save_ast_trail(a); + check_sorts(c, a); RETURN_Z3(of_ast(a)); Z3_CATCH_RETURN(0); } @@ -142,7 +141,7 @@ extern "C" { rational l; mk_c(c)->autil().am().get_lower(val, l, precision); expr * r = mk_c(c)->autil().mk_numeral(l, false); - mk_c(c)->save_ast_trail(r); + mk_c(c)->save_ast_trail(r); RETURN_Z3(of_expr(r)); Z3_CATCH_RETURN(0); } @@ -160,7 +159,7 @@ extern "C" { rational l; mk_c(c)->autil().am().get_upper(val, l, precision); expr * r = mk_c(c)->autil().mk_numeral(l, false); - mk_c(c)->save_ast_trail(r); + mk_c(c)->save_ast_trail(r); RETURN_Z3(of_expr(r)); Z3_CATCH_RETURN(0); } @@ -176,7 +175,7 @@ extern "C" { RETURN_Z3(0); } expr * r = mk_c(c)->autil().mk_numeral(numerator(val), true); - mk_c(c)->save_ast_trail(r); + mk_c(c)->save_ast_trail(r); RETURN_Z3(of_expr(r)); Z3_CATCH_RETURN(0); } @@ -192,7 +191,7 @@ extern "C" { RETURN_Z3(0); } expr * r = mk_c(c)->autil().mk_numeral(denominator(val), true); - mk_c(c)->save_ast_trail(r); + mk_c(c)->save_ast_trail(r); RETURN_Z3(of_expr(r)); Z3_CATCH_RETURN(0); } diff --git a/src/api/api_array.cpp b/src/api/api_array.cpp index d3dda5d9d..ed431882e 100644 --- a/src/api/api_array.cpp +++ b/src/api/api_array.cpp @@ -15,7 +15,6 @@ Author: Revision History: --*/ -#include #include"z3.h" #include"api_log_macros.h" #include"api_context.h" @@ -27,7 +26,7 @@ extern "C" { Z3_sort Z3_API Z3_mk_array_sort(Z3_context c, Z3_sort domain, Z3_sort range) { Z3_TRY; LOG_Z3_mk_array_sort(c, domain, range); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); parameter params[2] = { parameter(to_sort(domain)), parameter(to_sort(range)) }; sort * ty = mk_c(c)->m().mk_sort(mk_c(c)->get_array_fid(), ARRAY_SORT, 2, params); mk_c(c)->save_ast_trail(ty); @@ -57,7 +56,7 @@ extern "C" { RETURN_Z3(of_ast(r)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_store(Z3_context c, Z3_ast a, Z3_ast i, Z3_ast v) { Z3_TRY; LOG_Z3_mk_store(c, a, i, v); @@ -82,7 +81,7 @@ extern "C" { RETURN_Z3(of_ast(r)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_map(Z3_context c, Z3_func_decl f, unsigned n, Z3_ast const* args) { Z3_TRY; LOG_Z3_mk_map(c, f, n, args); @@ -94,7 +93,7 @@ extern "C" { ast_manager & m = mk_c(c)->m(); func_decl* _f = to_func_decl(f); expr* const* _args = to_exprs(args); - + ptr_vector domain; for (unsigned i = 0; i < n; ++i) { domain.push_back(m.get_sort(_args[i])); @@ -111,7 +110,7 @@ extern "C" { Z3_ast Z3_API Z3_mk_const_array(Z3_context c, Z3_sort domain, Z3_ast v) { Z3_TRY; LOG_Z3_mk_const_array(c, domain, v); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); expr * _v = to_expr(v); sort * _range = m.get_sort(_v); @@ -123,14 +122,14 @@ extern "C" { app * r = m.mk_app(cd, 1, &_v); mk_c(c)->save_ast_trail(r); check_sorts(c, r); - RETURN_Z3(of_ast(r)); + RETURN_Z3(of_ast(r)); Z3_CATCH_RETURN(0); } Z3_ast Z3_API Z3_mk_array_default(Z3_context c, Z3_ast array) { Z3_TRY; LOG_Z3_mk_array_default(c, array); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); expr * _a = to_expr(array); @@ -138,12 +137,12 @@ extern "C" { app * r = m.mk_app(f, 1, &_a); mk_c(c)->save_ast_trail(r); check_sorts(c, r); - RETURN_Z3(of_ast(r)); + RETURN_Z3(of_ast(r)); Z3_CATCH_RETURN(0); } Z3_ast mk_app_array_core(Z3_context c, Z3_sort domain, Z3_ast v) { - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); expr * _v = to_expr(v); sort * _range = m.get_sort(_v); @@ -178,7 +177,7 @@ extern "C" { LOG_Z3_mk_full_set(c, domain); RESET_ERROR_CODE(); Z3_ast r = mk_app_array_core(c, domain, Z3_mk_true(c)); - RETURN_Z3(r); + RETURN_Z3(r); Z3_CATCH_RETURN(0); } @@ -205,8 +204,8 @@ extern "C" { Z3_TRY; LOG_Z3_get_array_sort_domain(c, t); RESET_ERROR_CODE(); - CHECK_VALID_AST(t, 0); - if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() && + CHECK_VALID_AST(t, 0); + if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() && to_sort(t)->get_decl_kind() == ARRAY_SORT) { Z3_sort r = reinterpret_cast(to_sort(t)->get_parameter(0).get_ast()); RETURN_Z3(r); @@ -215,13 +214,13 @@ extern "C" { RETURN_Z3(0); Z3_CATCH_RETURN(0); } - + Z3_sort Z3_API Z3_get_array_sort_range(Z3_context c, Z3_sort t) { Z3_TRY; LOG_Z3_get_array_sort_range(c, t); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); CHECK_VALID_AST(t, 0); - if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() && + if (to_sort(t)->get_family_id() == mk_c(c)->get_array_fid() && to_sort(t)->get_decl_kind() == ARRAY_SORT) { Z3_sort r = reinterpret_cast(to_sort(t)->get_parameter(1).get_ast()); RETURN_Z3(r); diff --git a/src/api/api_bv.cpp b/src/api/api_bv.cpp index 353cf913c..ff090ef54 100644 --- a/src/api/api_bv.cpp +++ b/src/api/api_bv.cpp @@ -15,7 +15,6 @@ Author: Revision History: --*/ -#include #include"z3.h" #include"api_log_macros.h" #include"api_context.h" @@ -27,7 +26,7 @@ extern "C" { Z3_sort Z3_API Z3_mk_bv_sort(Z3_context c, unsigned sz) { Z3_TRY; LOG_Z3_mk_bv_sort(c, sz); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); if (sz == 0) { SET_ERROR_CODE(Z3_INVALID_ARG); } @@ -39,7 +38,7 @@ extern "C" { #define MK_BV_UNARY(NAME, OP) MK_UNARY(NAME, mk_c(c)->get_bv_fid(), OP, SKIP) #define MK_BV_BINARY(NAME, OP) MK_BINARY(NAME, mk_c(c)->get_bv_fid(), OP, SKIP) - + MK_BV_UNARY(Z3_mk_bvnot, OP_BNOT); MK_BV_UNARY(Z3_mk_bvredand, OP_BREDAND); MK_BV_UNARY(Z3_mk_bvredor, OP_BREDOR); @@ -75,11 +74,11 @@ extern "C" { expr * _n = to_expr(n); parameter params[2] = { parameter(high), parameter(low) }; expr * a = mk_c(c)->m().mk_app(mk_c(c)->get_bv_fid(), OP_EXTRACT, 2, params, 1, &_n); - mk_c(c)->save_ast_trail(a); + mk_c(c)->save_ast_trail(a); check_sorts(c, a); return of_ast(a); } - + Z3_ast Z3_API Z3_mk_extract(Z3_context c, unsigned high, unsigned low, Z3_ast n) { Z3_TRY; LOG_Z3_mk_extract(c, high, low, n); @@ -88,7 +87,7 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } - + #define MK_BV_PUNARY(NAME, OP) \ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \ Z3_TRY; \ @@ -113,7 +112,7 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \ Z3_ast Z3_API Z3_mk_bv2int(Z3_context c, Z3_ast n, Z3_bool is_signed) { Z3_TRY; LOG_Z3_mk_bv2int(c, n, is_signed); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); Z3_sort int_s = Z3_mk_int_sort(c); if (is_signed) { Z3_ast r = Z3_mk_bv2int(c, n, false); @@ -125,7 +124,7 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \ Z3_inc_ref(c, bound); Z3_ast zero = Z3_mk_int(c, 0, s); Z3_inc_ref(c, zero); - Z3_ast pred = Z3_mk_bvslt(c, n, zero); + Z3_ast pred = Z3_mk_bvslt(c, n, zero); Z3_inc_ref(c, pred); // if n <_sigend 0 then r - s^sz else r Z3_ast args[2] = { r, bound }; @@ -140,19 +139,19 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \ RETURN_Z3(res); } else { - expr * _n = to_expr(n); - parameter p(to_sort(int_s)); - ast* a = mk_c(c)->m().mk_app(mk_c(c)->get_bv_fid(), OP_BV2INT, 1, &p, 1, &_n); - mk_c(c)->save_ast_trail(a); - check_sorts(c, a); - RETURN_Z3(of_ast(a)); + expr * _n = to_expr(n); + parameter p(to_sort(int_s)); + ast* a = mk_c(c)->m().mk_app(mk_c(c)->get_bv_fid(), OP_BV2INT, 1, &p, 1, &_n); + mk_c(c)->save_ast_trail(a); + check_sorts(c, a); + RETURN_Z3(of_ast(a)); } Z3_CATCH_RETURN(0); } /** \brief Create a bit-vector of sort \s with 1 in the most significant bit position. - + The sort \s must be a bit-vector sort. This function is a shorthand for shl(1, N-1) @@ -343,7 +342,7 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \ return Z3_mk_not(c, eq); Z3_CATCH_RETURN(0); } - + // only for signed machine integers Z3_ast Z3_API Z3_mk_bvsdiv_no_overflow(Z3_context c, Z3_ast t1, Z3_ast t2) { Z3_TRY; @@ -369,7 +368,7 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \ return result; Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_bvsub(Z3_context c, Z3_ast n1, Z3_ast n2) { Z3_TRY; LOG_Z3_mk_bvsub(c, n1, n2); @@ -389,7 +388,7 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \ unsigned Z3_API Z3_get_bv_sort_size(Z3_context c, Z3_sort t) { Z3_TRY; LOG_Z3_get_bv_sort_size(c, t); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); CHECK_VALID_AST(t, 0); if (to_sort(t)->get_family_id() == mk_c(c)->get_bv_fid() && to_sort(t)->get_decl_kind() == BV_SORT) { return to_sort(t)->get_parameter(0).get_int(); @@ -398,5 +397,5 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) { \ return 0; Z3_CATCH_RETURN(0); } - + }; diff --git a/src/api/api_datatype.cpp b/src/api/api_datatype.cpp index 706ba9d89..5096c8e80 100644 --- a/src/api/api_datatype.cpp +++ b/src/api/api_datatype.cpp @@ -15,7 +15,6 @@ Author: Revision History: --*/ -#include #include"z3.h" #include"api_log_macros.h" #include"api_context.h" @@ -24,16 +23,16 @@ Revision History: extern "C" { - Z3_sort Z3_API Z3_mk_tuple_sort(Z3_context c, + Z3_sort Z3_API Z3_mk_tuple_sort(Z3_context c, Z3_symbol name, - unsigned num_fields, + unsigned num_fields, Z3_symbol const field_names[], Z3_sort const field_sorts[], Z3_func_decl * mk_tuple_decl, Z3_func_decl proj_decls[]) { Z3_TRY; LOG_Z3_mk_tuple_sort(c, name, num_fields, field_names, field_sorts, mk_tuple_decl, proj_decls); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); mk_c(c)->reset_last_result(); ast_manager& m = mk_c(c)->m(); datatype_util& dt_util = mk_c(c)->dtutil(); @@ -43,14 +42,14 @@ extern "C" { std::string recognizer_s("is_"); recognizer_s += to_symbol(name).str(); symbol recognizer(recognizer_s.c_str()); - + ptr_vector acc; for (unsigned i = 0; i < num_fields; ++i) { acc.push_back(mk_accessor_decl(to_symbol(field_names[i]), type_ref(to_sort(field_sorts[i])))); } constructor_decl* constrs[1] = { mk_constructor_decl(to_symbol(name), recognizer, acc.size(), acc.c_ptr()) }; - + { datatype_decl * dt = mk_datatype_decl(to_symbol(name), 1, constrs); bool is_ok = mk_c(c)->get_dt_plugin()->mk_datatypes(1, &dt, tuples); @@ -63,7 +62,7 @@ extern "C" { } // create tuple type - SASSERT(tuples.size() == 1); + SASSERT(tuples.size() == 1); tuple = tuples[0].get(); mk_c(c)->save_multiple_ast_trail(tuple); @@ -72,9 +71,9 @@ extern "C" { SASSERT(!dt_util.is_recursive(tuple)); ptr_vector const * decls = dt_util.get_datatype_constructors(tuple); func_decl* decl = (*decls)[0]; - mk_c(c)->save_multiple_ast_trail(decl); + mk_c(c)->save_multiple_ast_trail(decl); *mk_tuple_decl = of_func_decl(decl); - + // Create projections ptr_vector const * accs = dt_util.get_constructor_accessors(decl); if (!accs) { @@ -90,8 +89,8 @@ extern "C" { RETURN_Z3_mk_tuple_sort(of_sort(tuple)); Z3_CATCH_RETURN(0); } - - Z3_sort Z3_API Z3_mk_enumeration_sort(Z3_context c, + + Z3_sort Z3_API Z3_mk_enumeration_sort(Z3_context c, Z3_symbol name, unsigned n, Z3_symbol const enum_names[], @@ -106,7 +105,7 @@ extern "C" { sort_ref_vector sorts(m); sort* e; - + ptr_vector constrs; for (unsigned i = 0; i < n; ++i) { symbol e_name(to_symbol(enum_names[i])); @@ -128,9 +127,9 @@ extern "C" { RETURN_Z3(0); } } - + // create enum type. - SASSERT(sorts.size() == 1); + SASSERT(sorts.size() == 1); e = sorts[0].get(); mk_c(c)->save_multiple_ast_trail(e); @@ -141,10 +140,10 @@ extern "C" { SASSERT(decls && decls->size() == n); for (unsigned i = 0; i < n; ++i) { func_decl* decl = (*decls)[i]; - mk_c(c)->save_multiple_ast_trail(decl); + mk_c(c)->save_multiple_ast_trail(decl); enum_consts[i] = of_func_decl(decl); decl = dt_util.get_constructor_recognizer(decl); - mk_c(c)->save_multiple_ast_trail(decl); + mk_c(c)->save_multiple_ast_trail(decl); enum_testers[i] = of_func_decl(decl); } @@ -168,11 +167,11 @@ extern "C" { ast_manager& m = mk_c(c)->m(); mk_c(c)->reset_last_result(); datatype_util data_util(m); - accessor_decl* head_tail[2] = { + accessor_decl* head_tail[2] = { mk_accessor_decl(symbol("head"), type_ref(to_sort(elem_sort))), mk_accessor_decl(symbol("tail"), type_ref(0)) }; - constructor_decl* constrs[2] = { + constructor_decl* constrs[2] = { mk_constructor_decl(symbol("nil"), symbol("is_nil"), 0, 0), // Leo: SMT 2.0 document uses 'insert' instead of cons mk_constructor_decl(symbol("cons"), symbol("is_cons"), 2, head_tail) @@ -197,22 +196,22 @@ extern "C" { func_decl* f; if (nil_decl) { f = cnstrs[0]; - mk_c(c)->save_multiple_ast_trail(f); + mk_c(c)->save_multiple_ast_trail(f); *nil_decl = of_func_decl(f); } if (is_nil_decl) { f = data_util.get_constructor_recognizer(cnstrs[0]); - mk_c(c)->save_multiple_ast_trail(f); + mk_c(c)->save_multiple_ast_trail(f); *is_nil_decl = of_func_decl(f); } if (cons_decl) { f = cnstrs[1]; - mk_c(c)->save_multiple_ast_trail(f); + mk_c(c)->save_multiple_ast_trail(f); *cons_decl = of_func_decl(f); } if (is_cons_decl) { f = data_util.get_constructor_recognizer(cnstrs[1]); - mk_c(c)->save_multiple_ast_trail(f); + mk_c(c)->save_multiple_ast_trail(f); *is_cons_decl = of_func_decl(f); } if (head_decl) { @@ -220,7 +219,7 @@ extern "C" { SASSERT(acc); SASSERT(acc->size() == 2); f = (*acc)[0]; - mk_c(c)->save_multiple_ast_trail(f); + mk_c(c)->save_multiple_ast_trail(f); *head_decl = of_func_decl(f); } if (tail_decl) { @@ -228,7 +227,7 @@ extern "C" { SASSERT(acc); SASSERT(acc->size() == 2); f = (*acc)[1]; - mk_c(c)->save_multiple_ast_trail(f); + mk_c(c)->save_multiple_ast_trail(f); *tail_decl = of_func_decl(f); } RETURN_Z3_mk_list_sort(of_sort(s)); @@ -255,7 +254,7 @@ extern "C" { ) { Z3_TRY; LOG_Z3_mk_constructor(c, name, tester, num_fields, field_names, sorts, sort_refs); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); ast_manager& m = mk_c(c)->m(); constructor* cnstr = alloc(constructor, m); cnstr->m_name = to_symbol(name); @@ -291,7 +290,7 @@ extern "C" { if (!f) { SET_ERROR_CODE(Z3_INVALID_ARG); return; - } + } if (constructor_decl) { mk_c(c)->save_multiple_ast_trail(f); *constructor_decl = of_func_decl(f); @@ -301,15 +300,15 @@ extern "C" { mk_c(c)->save_multiple_ast_trail(f2); *tester = of_func_decl(f2); } - + ptr_vector const* accs = data_util.get_constructor_accessors(f); if (!accs && num_fields > 0) { SET_ERROR_CODE(Z3_INVALID_ARG); - return; + return; } for (unsigned i = 0; i < num_fields; ++i) { func_decl* f2 = (*accs)[i]; - mk_c(c)->save_multiple_ast_trail(f2); + mk_c(c)->save_multiple_ast_trail(f2); accessors[i] = of_func_decl(f2); } RETURN_Z3_query_constructor; @@ -324,7 +323,7 @@ extern "C" { Z3_CATCH; } - static datatype_decl* mk_datatype_decl(Z3_context c, + static datatype_decl* mk_datatype_decl(Z3_context c, Z3_symbol name, unsigned num_constructors, Z3_constructor constructors[]) { @@ -342,7 +341,7 @@ extern "C" { } constrs.push_back(mk_constructor_decl(cn->m_name, cn->m_tester, acc.size(), acc.c_ptr())); } - return mk_datatype_decl(to_symbol(name), num_constructors, constrs.c_ptr()); + return mk_datatype_decl(to_symbol(name), num_constructors, constrs.c_ptr()); } Z3_sort Z3_API Z3_mk_datatype(Z3_context c, @@ -352,9 +351,9 @@ extern "C" { Z3_TRY; LOG_Z3_mk_datatype(c, name, num_constructors, constructors); RESET_ERROR_CODE(); - ast_manager& m = mk_c(c)->m(); + ast_manager& m = mk_c(c)->m(); datatype_util data_util(m); - + sort_ref_vector sorts(m); { datatype_decl * data = mk_datatype_decl(c, name, num_constructors, constructors); @@ -370,7 +369,7 @@ extern "C" { mk_c(c)->save_ast_trail(s); ptr_vector const* cnstrs = data_util.get_datatype_constructors(s); - + for (unsigned i = 0; i < num_constructors; ++i) { constructor* cn = reinterpret_cast(constructors[i]); cn->m_constructor = (*cnstrs)[i]; @@ -411,7 +410,7 @@ extern "C" { Z3_TRY; LOG_Z3_mk_datatypes(c, num_sorts, sort_names, sorts, constructor_lists); RESET_ERROR_CODE(); - ast_manager& m = mk_c(c)->m(); + ast_manager& m = mk_c(c)->m(); mk_c(c)->reset_last_result(); datatype_util data_util(m); @@ -423,7 +422,7 @@ extern "C" { sort_ref_vector _sorts(m); bool ok = mk_c(c)->get_dt_plugin()->mk_datatypes(datas.size(), datas.c_ptr(), _sorts); del_datatype_decls(datas.size(), datas.c_ptr()); - + if (!ok) { SET_ERROR_CODE(Z3_INVALID_ARG); return; @@ -437,8 +436,8 @@ extern "C" { constructor_list* cl = reinterpret_cast(constructor_lists[i]); ptr_vector const* cnstrs = data_util.get_datatype_constructors(s); for (unsigned j = 0; j < cl->size(); ++j) { - constructor* cn = (*cl)[j]; - cn->m_constructor = (*cnstrs)[j]; + constructor* cn = (*cl)[j]; + cn->m_constructor = (*cnstrs)[j]; } } RETURN_Z3_mk_datatypes; @@ -452,15 +451,15 @@ extern "C" { CHECK_VALID_AST(t, 0); sort * _t = to_sort(t); datatype_util& dt_util = mk_c(c)->dtutil(); - + if (!dt_util.is_datatype(_t)) { SET_ERROR_CODE(Z3_INVALID_ARG); - return 0; + return 0; } ptr_vector const * decls = dt_util.get_datatype_constructors(_t); if (!decls) { SET_ERROR_CODE(Z3_INVALID_ARG); - return 0; + return 0; } return decls->size(); Z3_CATCH_RETURN(0); @@ -468,7 +467,7 @@ extern "C" { Z3_func_decl get_datatype_sort_constructor_core(Z3_context c, Z3_sort t, unsigned idx) { RESET_ERROR_CODE(); - CHECK_VALID_AST(t, 0); + CHECK_VALID_AST(t, 0); sort * _t = to_sort(t); datatype_util& dt_util = mk_c(c)->dtutil(); if (!dt_util.is_datatype(_t)) { @@ -497,10 +496,10 @@ extern "C" { Z3_func_decl Z3_API Z3_get_datatype_sort_recognizer(Z3_context c, Z3_sort t, unsigned idx) { Z3_TRY; LOG_Z3_get_datatype_sort_recognizer(c, t, idx); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); sort * _t = to_sort(t); datatype_util& dt_util = mk_c(c)->dtutil(); - + if (!dt_util.is_datatype(_t)) { SET_ERROR_CODE(Z3_INVALID_ARG); RETURN_Z3(0); @@ -520,13 +519,13 @@ extern "C" { Z3_func_decl Z3_API Z3_get_datatype_sort_constructor_accessor(Z3_context c, Z3_sort t, unsigned idx_c, unsigned idx_a) { Z3_TRY; LOG_Z3_get_datatype_sort_constructor_accessor(c, t, idx_c, idx_a); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); sort * _t = to_sort(t); datatype_util& dt_util = mk_c(c)->dtutil(); - + if (!dt_util.is_datatype(_t)) { SET_ERROR_CODE(Z3_INVALID_ARG); - RETURN_Z3(0); + RETURN_Z3(0); } ptr_vector const * decls = dt_util.get_datatype_constructors(_t); if (!decls || idx_c >= decls->size()) { @@ -536,24 +535,24 @@ extern "C" { func_decl* decl = (*decls)[idx_c]; if (decl->get_arity() <= idx_a) { SET_ERROR_CODE(Z3_INVALID_ARG); - RETURN_Z3(0); + RETURN_Z3(0); } ptr_vector const * accs = dt_util.get_constructor_accessors(decl); SASSERT(accs && accs->size() == decl->get_arity()); if (!accs || accs->size() <= idx_a) { SET_ERROR_CODE(Z3_INVALID_ARG); - RETURN_Z3(0); + RETURN_Z3(0); } decl = (*accs)[idx_a]; mk_c(c)->save_ast_trail(decl); - RETURN_Z3(of_func_decl(decl)); + RETURN_Z3(of_func_decl(decl)); Z3_CATCH_RETURN(0); } Z3_func_decl Z3_API Z3_get_tuple_sort_mk_decl(Z3_context c, Z3_sort t) { Z3_TRY; LOG_Z3_get_tuple_sort_mk_decl(c, t); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); sort * tuple = to_sort(t); datatype_util& dt_util = mk_c(c)->dtutil(); if (!dt_util.is_datatype(tuple) || dt_util.is_recursive(tuple) || dt_util.get_datatype_num_constructors(tuple) != 1) { @@ -564,34 +563,34 @@ extern "C" { RETURN_Z3(r); Z3_CATCH_RETURN(0); } - + unsigned Z3_API Z3_get_tuple_sort_num_fields(Z3_context c, Z3_sort t) { Z3_TRY; LOG_Z3_get_tuple_sort_num_fields(c, t); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); sort * tuple = to_sort(t); datatype_util& dt_util = mk_c(c)->dtutil(); if (!dt_util.is_datatype(tuple) || dt_util.is_recursive(tuple) || dt_util.get_datatype_num_constructors(tuple) != 1) { SET_ERROR_CODE(Z3_INVALID_ARG); - return 0; + return 0; } ptr_vector const * decls = dt_util.get_datatype_constructors(tuple); if (!decls || decls->size() != 1) { SET_ERROR_CODE(Z3_INVALID_ARG); - return 0; + return 0; } ptr_vector const * accs = dt_util.get_constructor_accessors((*decls)[0]); if (!accs) { - return 0; + return 0; } return accs->size(); Z3_CATCH_RETURN(0); } - + Z3_func_decl Z3_API Z3_get_tuple_sort_field_decl(Z3_context c, Z3_sort t, unsigned i) { Z3_TRY; LOG_Z3_get_tuple_sort_field_decl(c, t, i); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); sort * tuple = to_sort(t); datatype_util& dt_util = mk_c(c)->dtutil(); if (!dt_util.is_datatype(tuple) || dt_util.is_recursive(tuple) || dt_util.get_datatype_num_constructors(tuple) != 1) { @@ -619,14 +618,14 @@ extern "C" { } Z3_ast Z3_datatype_update_field( - Z3_context c, Z3_func_decl f, Z3_ast t, Z3_ast v) { + Z3_context c, Z3_func_decl f, Z3_ast t, Z3_ast v) { Z3_TRY; LOG_Z3_datatype_update_field(c, f, t, v); RESET_ERROR_CODE(); ast_manager & m = mk_c(c)->m(); func_decl* _f = to_func_decl(f); expr* _t = to_expr(t); - expr* _v = to_expr(v); + expr* _v = to_expr(v); expr* args[2] = { _t, _v }; sort* domain[2] = { m.get_sort(_t), m.get_sort(_v) }; parameter param(_f); diff --git a/src/api/api_interp.cpp b/src/api/api_interp.cpp index b14f3db72..10aa06568 100644 --- a/src/api/api_interp.cpp +++ b/src/api/api_interp.cpp @@ -15,7 +15,6 @@ Revision History: --*/ -#include #include #include #include"z3.h" @@ -375,7 +374,7 @@ extern "C" { for(int i = 0; i < num_theory; i++) fmlas[i] = Z3_mk_implies(ctx,Z3_mk_true(ctx),fmlas[i]); std::copy(cnsts,cnsts+num,fmlas.begin()+num_theory); - Z3_string smt = Z3_benchmark_to_smtlib_string(ctx,"none","AUFLIA","unknown","",num_fmlas-1,&fmlas[0],fmlas[num_fmlas-1]); + Z3_string smt = Z3_benchmark_to_smtlib_string(ctx,"none","AUFLIA","unknown","",num_fmlas-1,&fmlas[0],fmlas[num_fmlas-1]); std::ofstream f(filename); if(num_theory) f << ";! THEORY=" << num_theory << "\n"; @@ -469,7 +468,7 @@ extern "C" { } f.close(); -#if 0 +#if 0 if(!parents){ diff --git a/src/api/api_log.cpp b/src/api/api_log.cpp index 43cb607c8..43ed98986 100644 --- a/src/api/api_log.cpp +++ b/src/api/api_log.cpp @@ -15,7 +15,6 @@ Author: Revision History: --*/ -#include #include #include"z3.h" #include"api_log_macros.h" diff --git a/src/api/api_pb.cpp b/src/api/api_pb.cpp index ee504146f..f19fd8661 100644 --- a/src/api/api_pb.cpp +++ b/src/api/api_pb.cpp @@ -15,7 +15,6 @@ Author: Revision History: --*/ -#include #include"z3.h" #include"api_log_macros.h" #include"api_context.h" @@ -23,8 +22,8 @@ Revision History: #include"pb_decl_plugin.h" extern "C" { - - Z3_ast Z3_API Z3_mk_atmost(Z3_context c, unsigned num_args, + + Z3_ast Z3_API Z3_mk_atmost(Z3_context c, unsigned num_args, Z3_ast const args[], unsigned k) { Z3_TRY; LOG_Z3_mk_atmost(c, num_args, args, k); @@ -38,9 +37,8 @@ extern "C" { Z3_CATCH_RETURN(0); } - - Z3_ast Z3_API Z3_mk_atleast(Z3_context c, unsigned num_args, - Z3_ast const args[], unsigned k) { + Z3_ast Z3_API Z3_mk_atleast(Z3_context c, unsigned num_args, + Z3_ast const args[], unsigned k) { Z3_TRY; LOG_Z3_mk_atmost(c, num_args, args, k); RESET_ERROR_CODE(); @@ -53,7 +51,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_pble(Z3_context c, unsigned num_args, + Z3_ast Z3_API Z3_mk_pble(Z3_context c, unsigned num_args, Z3_ast const args[], int _coeffs[], int k) { Z3_TRY; @@ -71,7 +69,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_pbge(Z3_context c, unsigned num_args, + Z3_ast Z3_API Z3_mk_pbge(Z3_context c, unsigned num_args, Z3_ast const args[], int _coeffs[], int k) { Z3_TRY; @@ -89,7 +87,7 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_pbeq(Z3_context c, unsigned num_args, + Z3_ast Z3_API Z3_mk_pbeq(Z3_context c, unsigned num_args, Z3_ast const args[], int _coeffs[], int k) { Z3_TRY; diff --git a/src/api/api_polynomial.cpp b/src/api/api_polynomial.cpp index 979d2ea50..eebe36717 100644 --- a/src/api/api_polynomial.cpp +++ b/src/api/api_polynomial.cpp @@ -14,9 +14,8 @@ Author: Leonardo de Moura (leonardo) 2012-12-08 Notes: - + --*/ -#include #include"z3.h" #include"api_log_macros.h" #include"api_context.h" @@ -35,7 +34,7 @@ namespace api { pmanager::~pmanager() { } - + }; extern "C" { diff --git a/src/api/api_quant.cpp b/src/api/api_quant.cpp index ddcd90cca..bf64aa571 100644 --- a/src/api/api_quant.cpp +++ b/src/api/api_quant.cpp @@ -15,7 +15,6 @@ Author: Revision History: --*/ -#include #include"z3.h" #include"api_log_macros.h" #include"api_context.h" @@ -26,17 +25,17 @@ Revision History: extern "C" { Z3_ast Z3_API Z3_mk_quantifier( - Z3_context c, - Z3_bool is_forall, - unsigned weight, - unsigned num_patterns, Z3_pattern const patterns[], - unsigned num_decls, Z3_sort const sorts[], - Z3_symbol const decl_names[], - Z3_ast body) + Z3_context c, + Z3_bool is_forall, + unsigned weight, + unsigned num_patterns, Z3_pattern const patterns[], + unsigned num_decls, Z3_sort const sorts[], + Z3_symbol const decl_names[], + Z3_ast body) { return Z3_mk_quantifier_ex( - c, - is_forall, + c, + is_forall, weight, 0, 0, @@ -50,15 +49,15 @@ extern "C" { } Z3_ast mk_quantifier_ex_core( - Z3_context c, - Z3_bool is_forall, - unsigned weight, + Z3_context c, + Z3_bool is_forall, + unsigned weight, Z3_symbol quantifier_id, Z3_symbol skolem_id, - unsigned num_patterns, Z3_pattern const patterns[], - unsigned num_no_patterns, Z3_ast const no_patterns[], - unsigned num_decls, Z3_sort const sorts[], - Z3_symbol const decl_names[], + unsigned num_patterns, Z3_pattern const patterns[], + unsigned num_no_patterns, Z3_ast const no_patterns[], + unsigned num_decls, Z3_sort const sorts[], + Z3_symbol const decl_names[], Z3_ast body) { Z3_TRY; RESET_ERROR_CODE(); @@ -86,9 +85,9 @@ extern "C" { expr_ref result(mk_c(c)->m()); if (num_decls > 0) { result = mk_c(c)->m().mk_quantifier( - (0 != is_forall), - names.size(), ts, names.c_ptr(), to_expr(body), - weight, + (0 != is_forall), + names.size(), ts, names.c_ptr(), to_expr(body), + weight, to_symbol(quantifier_id), to_symbol(skolem_id), num_patterns, ps, @@ -104,44 +103,44 @@ extern "C" { } Z3_ast Z3_API Z3_mk_quantifier_ex( - Z3_context c, - Z3_bool is_forall, - unsigned weight, + Z3_context c, + Z3_bool is_forall, + unsigned weight, Z3_symbol quantifier_id, Z3_symbol skolem_id, - unsigned num_patterns, Z3_pattern const patterns[], - unsigned num_no_patterns, Z3_ast const no_patterns[], - unsigned num_decls, Z3_sort const sorts[], - Z3_symbol const decl_names[], + unsigned num_patterns, Z3_pattern const patterns[], + unsigned num_no_patterns, Z3_ast const no_patterns[], + unsigned num_decls, Z3_sort const sorts[], + Z3_symbol const decl_names[], Z3_ast body) { - LOG_Z3_mk_quantifier_ex(c, is_forall, weight, quantifier_id, skolem_id, num_patterns, patterns, + LOG_Z3_mk_quantifier_ex(c, is_forall, weight, quantifier_id, skolem_id, num_patterns, patterns, num_no_patterns, no_patterns, num_decls, sorts, decl_names, body); - Z3_ast r = mk_quantifier_ex_core(c, is_forall, weight, quantifier_id, skolem_id, num_patterns, patterns, + Z3_ast r = mk_quantifier_ex_core(c, is_forall, weight, quantifier_id, skolem_id, num_patterns, patterns, num_no_patterns, no_patterns, num_decls, sorts, decl_names, body); RETURN_Z3(r); } - - Z3_ast Z3_API Z3_mk_forall(Z3_context c, - unsigned weight, - unsigned num_patterns, Z3_pattern const patterns[], - unsigned num_decls, Z3_sort const types[], - Z3_symbol const decl_names[], + + Z3_ast Z3_API Z3_mk_forall(Z3_context c, + unsigned weight, + unsigned num_patterns, Z3_pattern const patterns[], + unsigned num_decls, Z3_sort const types[], + Z3_symbol const decl_names[], Z3_ast body) { return Z3_mk_quantifier(c, 1, weight, num_patterns, patterns, num_decls, types, decl_names, body); } - - Z3_ast Z3_API Z3_mk_exists(Z3_context c, - unsigned weight, - unsigned num_patterns, Z3_pattern const patterns[], - unsigned num_decls, Z3_sort const types[], - Z3_symbol const decl_names[], + + Z3_ast Z3_API Z3_mk_exists(Z3_context c, + unsigned weight, + unsigned num_patterns, Z3_pattern const patterns[], + unsigned num_decls, Z3_sort const types[], + Z3_symbol const decl_names[], Z3_ast body) { return Z3_mk_quantifier(c, 0, weight, num_patterns, patterns, num_decls, types, decl_names, body); } - Z3_ast Z3_API Z3_mk_quantifier_const_ex(Z3_context c, + Z3_ast Z3_API Z3_mk_quantifier_const_ex(Z3_context c, Z3_bool is_forall, unsigned weight, Z3_symbol quantifier_id, @@ -166,7 +165,7 @@ extern "C" { } if (num_bound == 0) { SET_ERROR_CODE(Z3_INVALID_USAGE); - RETURN_Z3(0); + RETURN_Z3(0); } for (unsigned i = 0; i < num_bound; ++i) { app* a = to_app(bound[i]); @@ -191,7 +190,7 @@ extern "C" { app* pat = to_pattern(patterns[i]); SASSERT(mk_c(c)->m().is_pattern(pat)); expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), pat, result); - SASSERT(result.get()->get_kind() == AST_APP); + SASSERT(result.get()->get_kind() == AST_APP); pinned.push_back(result.get()); SASSERT(mk_c(c)->m().is_pattern(result.get())); _patterns.push_back(of_pattern(result.get())); @@ -205,25 +204,25 @@ extern "C" { } app* pat = to_app(to_expr(no_patterns[i])); expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), pat, result); - SASSERT(result.get()->get_kind() == AST_APP); + SASSERT(result.get()->get_kind() == AST_APP); pinned.push_back(result.get()); _no_patterns.push_back(of_ast(result.get())); } expr_ref abs_body(mk_c(c)->m()); expr_abstract(mk_c(c)->m(), 0, num_bound, bound_asts.c_ptr(), to_expr(body), abs_body); - Z3_ast result = mk_quantifier_ex_core(c, is_forall, weight, + Z3_ast result = mk_quantifier_ex_core(c, is_forall, weight, quantifier_id, skolem_id, - num_patterns, _patterns.c_ptr(), + num_patterns, _patterns.c_ptr(), num_no_patterns, _no_patterns.c_ptr(), - names.size(), types.c_ptr(), names.c_ptr(), + names.size(), types.c_ptr(), names.c_ptr(), of_ast(abs_body.get())); RETURN_Z3(result); Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_mk_quantifier_const(Z3_context c, + Z3_ast Z3_API Z3_mk_quantifier_const(Z3_context c, Z3_bool is_forall, unsigned weight, unsigned num_bound, @@ -231,14 +230,14 @@ extern "C" { unsigned num_patterns, Z3_pattern const patterns[], Z3_ast body) { - return Z3_mk_quantifier_const_ex(c, is_forall, weight, 0, 0, - num_bound, bound, + return Z3_mk_quantifier_const_ex(c, is_forall, weight, 0, 0, + num_bound, bound, num_patterns, patterns, 0, 0, body); } - Z3_ast Z3_API Z3_mk_forall_const(Z3_context c, + Z3_ast Z3_API Z3_mk_forall_const(Z3_context c, unsigned weight, unsigned num_bound, Z3_app const bound[], @@ -248,7 +247,7 @@ extern "C" { return Z3_mk_quantifier_const(c, true, weight, num_bound, bound, num_patterns, patterns, body); } - Z3_ast Z3_API Z3_mk_exists_const(Z3_context c, + Z3_ast Z3_API Z3_mk_exists_const(Z3_context c, unsigned weight, unsigned num_bound, Z3_app const bound[], @@ -257,7 +256,7 @@ extern "C" { Z3_ast body) { return Z3_mk_quantifier_const(c, false, weight, num_bound, bound, num_patterns, patterns, body); } - + Z3_pattern Z3_API Z3_mk_pattern(Z3_context c, unsigned num_patterns, Z3_ast const terms[]) { Z3_TRY; LOG_Z3_mk_pattern(c, num_patterns, terms); @@ -273,7 +272,7 @@ extern "C" { RETURN_Z3(of_pattern(a)); Z3_CATCH_RETURN(0); } - + Z3_ast Z3_API Z3_mk_bound(Z3_context c, unsigned index, Z3_sort ty) { Z3_TRY; LOG_Z3_mk_bound(c, index, ty); @@ -436,7 +435,7 @@ extern "C" { else { SET_ERROR_CODE(Z3_SORT_ERROR); return 0; - } + } Z3_CATCH_RETURN(0); } @@ -450,7 +449,7 @@ extern "C" { } else { SET_ERROR_CODE(Z3_SORT_ERROR); - return 0; + return 0; } Z3_CATCH_RETURN(0); } @@ -471,13 +470,13 @@ extern "C" { Z3_CATCH_RETURN(0); } - Z3_ast Z3_API Z3_pattern_to_ast(Z3_context c, Z3_pattern p) { + Z3_ast Z3_API Z3_pattern_to_ast(Z3_context c, Z3_pattern p) { RESET_ERROR_CODE(); - return (Z3_ast)(p); - } + return (Z3_ast)(p); + } Z3_API char const * Z3_pattern_to_string(Z3_context c, Z3_pattern p) { return Z3_ast_to_string(c, reinterpret_cast(p)); } - + }; diff --git a/src/api/api_seq.cpp b/src/api/api_seq.cpp index 138ea6fb0..478ee6274 100644 --- a/src/api/api_seq.cpp +++ b/src/api/api_seq.cpp @@ -16,7 +16,6 @@ Author: Revision History: --*/ -#include #include"z3.h" #include"api_log_macros.h" #include"api_context.h" @@ -28,7 +27,7 @@ extern "C" { Z3_sort Z3_API Z3_mk_seq_sort(Z3_context c, Z3_sort domain) { Z3_TRY; LOG_Z3_mk_seq_sort(c, domain); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); sort * ty = mk_c(c)->sutil().str.mk_seq(to_sort(domain)); mk_c(c)->save_ast_trail(ty); RETURN_Z3(of_sort(ty)); @@ -38,7 +37,7 @@ extern "C" { Z3_sort Z3_API Z3_mk_re_sort(Z3_context c, Z3_sort domain) { Z3_TRY; LOG_Z3_mk_re_sort(c, domain); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); sort * ty = mk_c(c)->sutil().re.mk_re(to_sort(domain)); mk_c(c)->save_ast_trail(ty); RETURN_Z3(of_sort(ty)); @@ -48,14 +47,14 @@ extern "C" { Z3_ast Z3_API Z3_mk_string(Z3_context c, Z3_string str) { Z3_TRY; LOG_Z3_mk_string(c, str); - RESET_ERROR_CODE(); + RESET_ERROR_CODE(); zstring s(str, zstring::ascii); app* a = mk_c(c)->sutil().str.mk_string(s); mk_c(c)->save_ast_trail(a); RETURN_Z3(of_ast(a)); Z3_CATCH_RETURN(0); } - + Z3_sort Z3_API Z3_mk_string_sort(Z3_context c) { Z3_TRY; LOG_Z3_mk_string_sort(c); @@ -71,8 +70,8 @@ extern "C" { LOG_Z3_is_seq_sort(c, s); RESET_ERROR_CODE(); bool result = mk_c(c)->sutil().is_seq(to_sort(s)); - return result?Z3_TRUE:Z3_FALSE; - Z3_CATCH_RETURN(Z3_FALSE); + return result?Z3_TRUE:Z3_FALSE; + Z3_CATCH_RETURN(Z3_FALSE); } Z3_bool Z3_API Z3_is_re_sort(Z3_context c, Z3_sort s) { @@ -80,8 +79,8 @@ extern "C" { LOG_Z3_is_re_sort(c, s); RESET_ERROR_CODE(); bool result = mk_c(c)->sutil().is_re(to_sort(s)); - return result?Z3_TRUE:Z3_FALSE; - Z3_CATCH_RETURN(Z3_FALSE); + return result?Z3_TRUE:Z3_FALSE; + Z3_CATCH_RETURN(Z3_FALSE); } Z3_bool Z3_API Z3_is_string_sort(Z3_context c, Z3_sort s) { @@ -89,8 +88,8 @@ extern "C" { LOG_Z3_is_string_sort(c, s); RESET_ERROR_CODE(); bool result = mk_c(c)->sutil().is_string(to_sort(s)); - return result?Z3_TRUE:Z3_FALSE; - Z3_CATCH_RETURN(Z3_FALSE); + return result?Z3_TRUE:Z3_FALSE; + Z3_CATCH_RETURN(Z3_FALSE); } Z3_bool Z3_API Z3_is_string(Z3_context c, Z3_ast s) { @@ -98,7 +97,7 @@ extern "C" { LOG_Z3_is_string(c, s); RESET_ERROR_CODE(); bool result = mk_c(c)->sutil().str.is_string(to_expr(s)); - return result?Z3_TRUE:Z3_FALSE; + return result?Z3_TRUE:Z3_FALSE; Z3_CATCH_RETURN(Z3_FALSE); } @@ -125,7 +124,7 @@ extern "C" { mk_c(c)->save_ast_trail(a); \ RETURN_Z3(of_ast(a)); \ Z3_CATCH_RETURN(0); \ - } + } MK_SORTED(Z3_mk_seq_empty, mk_c(c)->sutil().str.mk_empty); @@ -143,13 +142,13 @@ extern "C" { MK_BINARY(Z3_mk_seq_in_re, mk_c(c)->get_seq_fid(), OP_SEQ_IN_RE, SKIP); Z3_ast Z3_API Z3_mk_re_loop(Z3_context c, Z3_ast r, unsigned lo, unsigned hi) { - Z3_TRY; - LOG_Z3_mk_re_loop(c, r, lo, hi); - RESET_ERROR_CODE(); + Z3_TRY; + LOG_Z3_mk_re_loop(c, r, lo, hi); + RESET_ERROR_CODE(); app* a = hi == 0 ? mk_c(c)->sutil().re.mk_loop(to_expr(r), lo) : mk_c(c)->sutil().re.mk_loop(to_expr(r), lo, hi); - mk_c(c)->save_ast_trail(a); - RETURN_Z3(of_ast(a)); - Z3_CATCH_RETURN(0); + mk_c(c)->save_ast_trail(a); + RETURN_Z3(of_ast(a)); + Z3_CATCH_RETURN(0); } MK_UNARY(Z3_mk_re_plus, mk_c(c)->get_seq_fid(), OP_RE_PLUS, SKIP); From 9f499055826112e9ebc8b2a06bb7576d507aee46 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 10 Jan 2017 21:05:27 +0000 Subject: [PATCH 20/47] Formatting, whitespace, and Z3_API annotations. --- src/api/z3_api.h | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/api/z3_api.h b/src/api/z3_api.h index fcf22961c..65c155d63 100644 --- a/src/api/z3_api.h +++ b/src/api/z3_api.h @@ -1953,7 +1953,7 @@ extern "C" { The datatype may be recursive. Return the datatype sort. \param c logical context. - \param name name of datatype. + \param name name of datatype. \param num_constructors number of constructors passed in. \param constructors array of constructor containers. @@ -3088,7 +3088,7 @@ extern "C" { \param c logical context. \param numeral A string representing the numeral value in decimal notation. The string may be of the form \code{[num]*[.[num]*][E[+|-][num]+]}. - If the given sort is a real, then the numeral can be a rational, that is, a string of the form \ccode{[num]* / [num]*}. + If the given sort is a real, then the numeral can be a rational, that is, a string of the form \ccode{[num]* / [num]*}. \param ty The sort of the numeral. In the current implementation, the given sort can be an int, real, finite-domain, or bit-vectors of arbitrary size. \sa Z3_mk_int @@ -3393,7 +3393,7 @@ extern "C" { \c lo number of times, and with an unbounded upper bound. def_API('Z3_mk_re_loop', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in(UINT))) - */ + */ Z3_ast Z3_API Z3_mk_re_loop(Z3_context c, Z3_ast r, unsigned lo, unsigned hi); /** @@ -3430,7 +3430,7 @@ extern "C" { def_API('Z3_mk_re_full' ,AST ,(_in(CONTEXT), _in(SORT))) */ Z3_ast Z3_API Z3_mk_re_full(Z3_context c, Z3_sort re); - + /*@}*/ @@ -3966,11 +3966,9 @@ extern "C" { def_API('Z3_mk_atmost', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in(UINT))) */ - Z3_ast Z3_API Z3_mk_atmost(Z3_context c, unsigned num_args, Z3_ast const args[], unsigned k); - /** \brief Pseudo-Boolean relations. @@ -3978,9 +3976,9 @@ extern "C" { def_API('Z3_mk_atleast', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in(UINT))) */ - - Z3_ast Z3_mk_atleast(Z3_context c, unsigned num_args, + Z3_ast Z3_API Z3_mk_atleast(Z3_context c, unsigned num_args, Z3_ast const args[], unsigned k); + /** \brief Pseudo-Boolean relations. @@ -3988,12 +3986,10 @@ extern "C" { def_API('Z3_mk_pble', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in_array(1,INT), _in(INT))) */ - Z3_ast Z3_API Z3_mk_pble(Z3_context c, unsigned num_args, Z3_ast const args[], int coeffs[], int k); - /** \brief Pseudo-Boolean relations. @@ -4001,8 +3997,7 @@ extern "C" { def_API('Z3_mk_pbge', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in_array(1,INT), _in(INT))) */ - - Z3_ast Z3_mk_pbge(Z3_context c, unsigned num_args, + Z3_ast Z3_API Z3_mk_pbge(Z3_context c, unsigned num_args, Z3_ast const args[], int coeffs[], int k); @@ -4013,7 +4008,6 @@ extern "C" { def_API('Z3_mk_pbeq', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in_array(1,INT), _in(INT))) */ - Z3_ast Z3_API Z3_mk_pbeq(Z3_context c, unsigned num_args, Z3_ast const args[], int coeffs[], int k); @@ -5228,7 +5222,7 @@ extern "C" { /*@}*/ /** - \brief Return a string describing the given error code. + \brief Return a string describing the given error code. Retained function name for backwards compatibility within v4.1 */ Z3_string Z3_API Z3_get_error_msg_ex(Z3_context c, Z3_error_code err); @@ -6001,11 +5995,11 @@ extern "C" { /** \brief retrieve consequences from solver that determine values of the supplied function symbols. - + def_API('Z3_solver_get_consequences', INT, (_in(CONTEXT), _in(SOLVER), _in(AST_VECTOR), _in(AST_VECTOR), _in(AST_VECTOR))) */ - Z3_lbool Z3_API Z3_solver_get_consequences(Z3_context c, + Z3_lbool Z3_API Z3_solver_get_consequences(Z3_context c, Z3_solver s, Z3_ast_vector assumptions, Z3_ast_vector variables, From 650ea7b9ccd25c1ec3e372baae944a9a0faa73ba Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 11 Jan 2017 18:40:11 +0000 Subject: [PATCH 21/47] Bugfix for smt.core.extend_patterns --- src/smt/smt_solver.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp index 703e4489e..c843c2f78 100644 --- a/src/smt/smt_solver.cpp +++ b/src/smt/smt_solver.cpp @@ -103,6 +103,7 @@ namespace smt { virtual void assert_expr(expr * t, expr * a) { solver_na2as::assert_expr(t, a); + SASSERT(!m_name2assertion.contains(a)); get_manager().inc_ref(t); m_name2assertion.insert(a, t); } @@ -112,6 +113,17 @@ namespace smt { } virtual void pop_core(unsigned n) { + unsigned lvl = m_scopes.size(); + SASSERT(n <= lvl); + unsigned new_lvl = lvl - n; + unsigned old_sz = m_scopes[new_lvl]; + for (unsigned i = m_assumptions.size() - 1; i >= old_sz; i--) { + expr * key = m_assumptions[i].get(); + SASSERT(m_name2assertion.contains(key)); + expr * value = m_name2assertion.find(key); + m.dec_ref(value); + m_name2assertion.erase(key); + } m_context.pop(n); } @@ -274,6 +286,7 @@ namespace smt { unsigned sz = core.size(); for (unsigned i = 0; i < sz; i++) { expr_ref name(core[i], m); + SASSERT(m_name2assertion.contains(name)); expr_ref assrtn(m_name2assertion.find(name), m); collect_pattern_func_decls(assrtn, pattern_fds); } From f7ebe1604671e75925b841b397f51c185db03544 Mon Sep 17 00:00:00 2001 From: Daniel Perelman Date: Wed, 11 Jan 2017 16:56:28 -0800 Subject: [PATCH 22/47] Omit '.dll' from library name for DllImport. --- scripts/update_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_api.py b/scripts/update_api.py index b8978ff21..031b39c75 100755 --- a/scripts/update_api.py +++ b/scripts/update_api.py @@ -365,7 +365,7 @@ def mk_dotnet(dotnet): dotnet.write(' public delegate void Z3_error_handler(Z3_context c, Z3_error_code e);\n\n') dotnet.write(' public class LIB\n') dotnet.write(' {\n') - dotnet.write(' const string Z3_DLL_NAME = \"libz3.dll\";\n' + dotnet.write(' const string Z3_DLL_NAME = \"libz3\";\n' ' \n') dotnet.write(' [DllImport(Z3_DLL_NAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n') dotnet.write(' public extern static void Z3_set_error_handler(Z3_context a0, Z3_error_handler a1);\n\n') From 3370adcdffd93e00a08ef6dbdf44a3562cb7a1bc Mon Sep 17 00:00:00 2001 From: Daniel Perelman Date: Wed, 11 Jan 2017 17:02:26 -0800 Subject: [PATCH 23/47] Mark void DummyContracts as Conditional to avoid compiling their arguments. --- src/api/dotnet/core/DummyContracts.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/api/dotnet/core/DummyContracts.cs b/src/api/dotnet/core/DummyContracts.cs index e0002e5be..49b498b1a 100644 --- a/src/api/dotnet/core/DummyContracts.cs +++ b/src/api/dotnet/core/DummyContracts.cs @@ -44,15 +44,21 @@ namespace System.Diagnostics.Contracts public static class Contract { + [Conditional("false")] public static void Ensures(bool b) { } + [Conditional("false")] public static void Requires(bool b) { } + [Conditional("false")] public static void Assume(bool b, string msg) { } + [Conditional("false")] public static void Assert(bool b) { } public static bool ForAll(bool b) { return true; } public static bool ForAll(Object c, Func p) { return true; } public static bool ForAll(int from, int to, Predicate p) { return true; } + [Conditional("false")] public static void Invariant(bool b) { } public static T[] Result() { return new T[1]; } + [Conditional("false")] public static void EndContractBlock() { } public static T ValueAtReturn(out T v) { T[] t = new T[1]; v = t[0]; return v; } } From 2458db30cf0329128db4c92e79909284892619f0 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 12 Jan 2017 12:49:26 +0000 Subject: [PATCH 24/47] Corner-case fix for smt::solver::pop_core --- src/smt/smt_solver.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/smt/smt_solver.cpp b/src/smt/smt_solver.cpp index c843c2f78..f80ff09f4 100644 --- a/src/smt/smt_solver.cpp +++ b/src/smt/smt_solver.cpp @@ -113,16 +113,19 @@ namespace smt { } virtual void pop_core(unsigned n) { - unsigned lvl = m_scopes.size(); - SASSERT(n <= lvl); - unsigned new_lvl = lvl - n; - unsigned old_sz = m_scopes[new_lvl]; - for (unsigned i = m_assumptions.size() - 1; i >= old_sz; i--) { - expr * key = m_assumptions[i].get(); - SASSERT(m_name2assertion.contains(key)); - expr * value = m_name2assertion.find(key); - m.dec_ref(value); - m_name2assertion.erase(key); + unsigned cur_sz = m_assumptions.size(); + if (n > 0 && cur_sz > 0) { + unsigned lvl = m_scopes.size(); + SASSERT(n <= lvl); + unsigned new_lvl = lvl - n; + unsigned old_sz = m_scopes[new_lvl]; + for (unsigned i = cur_sz - 1; i >= old_sz; i--) { + expr * key = m_assumptions[i].get(); + SASSERT(m_name2assertion.contains(key)); + expr * value = m_name2assertion.find(key); + m.dec_ref(value); + m_name2assertion.erase(key); + } } m_context.pop(n); } From 43eb6cc022308c0d027c4053348b202c4420c0c2 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 13 Jan 2017 20:43:53 +0000 Subject: [PATCH 25/47] CI trigger From 37916fe7e9b17ff296de10e942ce68e548582ce6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Fri, 13 Jan 2017 21:33:11 +0000 Subject: [PATCH 26/47] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 502b32147..204fb371e 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,12 @@ Z3 can be built using [Visual Studio][1], a [Makefile][2] or using [CMake][3]. I See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z3. +## Build status + +| Windows | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | +| ------- | ---------- | ---------- | ---------- | --- | +![windows-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge) + [1]: #building-z3-on-windows-using-visual-studio-command-prompt [2]: #building-z3-using-make-and-gccclang [3]: #building-z3-using-cmake From bc6b3007de3727a284cf5f19c268d52cf4e75313 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Fri, 13 Jan 2017 20:53:22 -0800 Subject: [PATCH 27/47] remove unused features related to weighted check-sat Signed-off-by: Nikolaj Bjorner --- contrib/cmake/src/sat/CMakeLists.txt | 2 - src/opt/maxres.cpp | 12 +- src/opt/pb_sls.cpp | 46 +- src/sat/sat_bceq.cpp | 530 -------------------- src/sat/sat_bceq.h | 89 ---- src/sat/sat_config.cpp | 2 - src/sat/sat_config.h | 2 - src/sat/sat_mus.cpp | 37 +- src/sat/sat_mus.h | 2 - src/sat/sat_params.pyg | 2 - src/sat/sat_sls.cpp | 686 -------------------------- src/sat/sat_sls.h | 115 ----- src/sat/sat_solver.cpp | 143 +----- src/sat/sat_solver.h | 16 +- src/sat/sat_solver/inc_sat_solver.cpp | 29 +- src/sat/sat_solver/inc_sat_solver.h | 1 - 16 files changed, 58 insertions(+), 1656 deletions(-) delete mode 100644 src/sat/sat_bceq.cpp delete mode 100644 src/sat/sat_bceq.h delete mode 100644 src/sat/sat_sls.cpp delete mode 100644 src/sat/sat_sls.h diff --git a/contrib/cmake/src/sat/CMakeLists.txt b/contrib/cmake/src/sat/CMakeLists.txt index cfc3835c1..3eec21ec3 100644 --- a/contrib/cmake/src/sat/CMakeLists.txt +++ b/contrib/cmake/src/sat/CMakeLists.txt @@ -2,7 +2,6 @@ z3_add_component(sat SOURCES dimacs.cpp sat_asymm_branch.cpp - sat_bceq.cpp sat_clause.cpp sat_clause_set.cpp sat_clause_use_list.cpp @@ -16,7 +15,6 @@ z3_add_component(sat sat_probing.cpp sat_scc.cpp sat_simplifier.cpp - sat_sls.cpp sat_solver.cpp sat_watched.cpp COMPONENT_DEPENDENCIES diff --git a/src/opt/maxres.cpp b/src/opt/maxres.cpp index 54e7f351c..83f0849b2 100644 --- a/src/opt/maxres.cpp +++ b/src/opt/maxres.cpp @@ -302,17 +302,7 @@ public: } lbool check_sat(unsigned sz, expr* const* asms) { - if (m_st == s_primal_dual && m_c.sat_enabled()) { - rational max_weight = m_upper; - vector weights; - for (unsigned i = 0; i < sz; ++i) { - weights.push_back(get_weight(asms[i])); - } - return inc_sat_check_sat(s(), sz, asms, weights.c_ptr(), max_weight); - } - else { - return s().check_sat(sz, asms); - } + return s().check_sat(sz, asms); } void found_optimum() { diff --git a/src/opt/pb_sls.cpp b/src/opt/pb_sls.cpp index 95b489394..32c144652 100644 --- a/src/opt/pb_sls.cpp +++ b/src/opt/pb_sls.cpp @@ -20,9 +20,49 @@ Notes: #include "smt_literal.h" #include "ast_pp.h" #include "th_rewriter.h" -#include "sat_sls.h" +#include "sat_types.h" namespace smt { + + class index_set { + + unsigned_vector m_elems; + unsigned_vector m_index; + public: + unsigned num_elems() const { return m_elems.size(); } + unsigned operator[](unsigned idx) const { return m_elems[idx]; } + void reset() { m_elems.reset(); m_index.reset(); } + bool empty() const { return m_elems.empty(); } + + bool contains(unsigned idx) const { + return + (idx < m_index.size()) && + (m_index[idx] < m_elems.size()) && + (m_elems[m_index[idx]] == idx); + } + + void insert(unsigned idx) { + m_index.reserve(idx+1); + if (!contains(idx)) { + m_index[idx] = m_elems.size(); + m_elems.push_back(idx); + } + } + + void remove(unsigned idx) { + if (!contains(idx)) return; + unsigned pos = m_index[idx]; + m_elems[pos] = m_elems.back(); + m_index[m_elems[pos]] = pos; + m_elems.pop_back(); + } + + unsigned choose(random_gen& rnd) const { + SASSERT(!empty()); + return m_elems[rnd(num_elems())]; + } + }; + struct pb_sls::imp { struct clause { @@ -73,8 +113,8 @@ namespace smt { expr_ref_vector m_trail; obj_map m_decl2var; // map declarations to Boolean variables. ptr_vector m_var2decl; // reverse map - sat::index_set m_hard_false; // list of hard clauses that are false. - sat::index_set m_soft_false; // list of soft clauses that are false. + index_set m_hard_false; // list of hard clauses that are false. + index_set m_soft_false; // list of soft clauses that are false. unsigned m_max_flips; // maximal number of flips unsigned m_non_greedy_percent; // percent of moves to do non-greedy style random_gen m_rng; diff --git a/src/sat/sat_bceq.cpp b/src/sat/sat_bceq.cpp deleted file mode 100644 index fa0309327..000000000 --- a/src/sat/sat_bceq.cpp +++ /dev/null @@ -1,530 +0,0 @@ -/*++ -Copyright (c) 2014 Microsoft Corporation - -Module Name: - - sat_bceq.cpp - -Abstract: - - Find equivalent literals based on blocked clause decomposition. - -Author: - - Nikolaj Bjorner (nbjorner) 2014-09-27. - - -Revision History: - ---*/ -#include"sat_bceq.h" -#include"sat_solver.h" -#include"trace.h" -#include"bit_vector.h" -#include"map.h" -#include"sat_elim_eqs.h" - -namespace sat { - - void bceq::use_list::init(unsigned num_vars) { - m_clauses.reset(); - m_clauses.resize(2*num_vars); - } - - void bceq::use_list::insert(clause& c) { - unsigned sz = c.size(); - for (unsigned i = 0; i < sz; i++) { - m_clauses[c[i].index()].push_back(&c); - } - } - - void bceq::use_list::erase(clause& c) { - unsigned sz = c.size(); - for (unsigned i = 0; i < sz; i++) { - m_clauses[c[i].index()].erase(&c); - } - } - - ptr_vector& bceq::use_list::get(literal lit) { - return m_clauses[lit.index()]; - } - - bceq::bceq(solver & s): - m_solver(s) { - } - - void bceq::register_clause(clause* cls) { - m_clauses.setx(cls->id(), cls, 0); - } - - void bceq::unregister_clause(clause* cls) { - m_clauses.setx(cls->id(), 0, 0); - } - - void bceq::init() { - m_clauses.reset(); - m_bin_clauses.reset(); - m_L.reset(); - m_R.reset(); - m_L_blits.reset(); - m_R_blits.reset(); - m_bce_use_list.reset(); - clause * const* it = m_solver.begin_clauses(); - clause * const* end = m_solver.end_clauses(); - for (; it != end; ++it) { - clause* cls = *it; - if (!cls->was_removed()) { - m_use_list->insert(*cls); - register_clause(cls); - } - } - bin_clauses bc; - m_solver.collect_bin_clauses(bc, false); // exclude roots. - literal lits[2]; - for (unsigned i = 0; i < bc.size(); ++i) { - lits[0] = bc[i].first; - lits[1] = bc[i].second; - clause* cls = m_solver.m_cls_allocator.mk_clause(2, lits, false); - m_use_list->insert(*cls); - m_bin_clauses.push_back(cls); - register_clause(cls); - } - TRACE("sat", - for (unsigned i = 0; i < m_clauses.size(); ++i) { - clause const* cls = m_clauses[i]; - if (cls) tout << *cls << "\n"; - }); - } - - void bceq::pure_decompose() { - // while F != empty - // pick a clause and variable x in clause. - // get use list U1 of x and U2 of ~x - // assume |U1| >= |U2| - // add U1 to clause set. - for (unsigned i = 0; i < m_clauses.size(); ++i) { - clause* cls = m_clauses[i]; - if (cls) { - SASSERT(i == cls->id()); - pure_decompose((*cls)[0]); - SASSERT(!m_clauses[i]); - } - } - m_L.reverse(); - m_L_blits.reverse(); - } - - void bceq::pure_decompose(literal lit) { - clause_use_list& pos = m_use_list->get(lit); - clause_use_list& neg = m_use_list->get(~lit); - unsigned sz1 = m_L.size(); - unsigned sz2 = m_R.size(); - pure_decompose(pos, m_L); - pure_decompose(neg, m_R); - unsigned delta1 = m_L.size() - sz1; - unsigned delta2 = m_R.size() - sz2; - if (delta1 < delta2) { - m_L_blits.resize(sz1+delta2, ~lit); - m_R_blits.resize(sz2+delta1, lit); - for (unsigned i = 0; i < delta1; ++i) { - std::swap(m_L[sz1 + i], m_R[sz2 + i]); - } - for (unsigned i = delta1; i < delta2; ++i) { - m_L.push_back(m_R[sz2 + i]); - } - m_R.resize(sz2 + delta1); - std::swap(delta1, delta2); - } - else { - m_L_blits.resize(sz1+delta1, lit); - m_R_blits.resize(sz2+delta2, ~lit); - } - TRACE("bceq", tout << lit << " " << "pos: " << delta1 << " " << "neg: " << delta2 << "\n";); - } - - void bceq::pure_decompose(clause_use_list& uses, svector& clauses) { - unsigned sz = uses.size(); - for (unsigned i = 0; i < sz; ++i) { - clause& cls = *uses[i]; - if (!cls.was_removed() && m_clauses[cls.id()]) { - clauses.push_back(&cls); - m_clauses[cls.id()] = 0; - } - } - } - - void bceq::post_decompose() { - m_marked.reset(); - m_marked.resize(2*m_solver.num_vars(), false); - use_list ul; - use_list* save = m_use_list; - m_use_list = &ul; - ul.init(m_solver.num_vars()); - for (unsigned i = 0; i < m_L.size(); ++i) { - ul.insert(*m_L[i]); - } - - // cheap pass: add clauses from R in order - // such that they are blocked with respect to - // predecessors. - m_removed.reset(); - for (unsigned i = 0; i < m_R.size(); ++i) { - literal lit = find_blocked(*m_R[i]); - if (lit != null_literal) { - m_L.push_back(m_R[i]); - m_L_blits.push_back(lit); - ul.insert(*m_R[i]); - m_R[i] = m_R.back(); - m_R_blits[i] = m_R_blits.back(); - m_R.pop_back(); - m_R_blits.pop_back(); - --i; - } - } - // expensive pass: add clauses from R as long - // as BCE produces the empty set of clauses. - m_bce_use_list.init(m_solver.num_vars()); - for (unsigned i = 0; i < m_L.size(); ++i) { - m_bce_use_list.insert(*m_L[i]); - } - for (unsigned i = 0; i < m_R.size(); ++i) { - if (bce(*m_R[i])) { - m_R[i] = m_R.back(); - m_R_blits[i] = m_R_blits.back(); - m_R.pop_back(); - m_R_blits.pop_back(); - --i; - } - } - m_use_list = save; - } - - - // Note: replay blocked clause elimination: - // Suppose C u { c1 } is blocked. - // annotate each clause by blocking literal. - // for new clause c2, check if C u { c2 } is blocked. - // For each c in C record which literal it is blocked. - // (Order the clauses in C by block ordering) - // l | c is blocked, - // -> c2 contains ~l => check if c c2 is blocked - // - bool bceq::bce(clause& cls0) { - IF_VERBOSE(1, verbose_stream() << "bce " << m_L.size() << " " << m_R.size() << " " << cls0 << "\n";); - unsigned_vector& live_clauses = m_live_clauses; - live_clauses.reset(); - m_use_list = &m_bce_use_list; - m_bce_use_list.insert(cls0); - svector& clauses = m_L; - literal_vector& blits = m_L_blits; - clauses.push_back(&cls0); - blits.push_back(null_literal); - bool removed = false; - m_removed.reset(); - for (unsigned i = 0; i < clauses.size(); ++i) { - clause& cls1 = *clauses[i]; - literal lit = find_blocked(cls1); - if (lit == null_literal) { - live_clauses.push_back(i); - } - else { - m_removed.setx(cls1.id(), true, false); - removed = true; - } - } - while (removed) { - removed = false; - //std::cout << live_clauses.size() << " "; - for (unsigned i = 0; i < live_clauses.size(); ++i) { - clause& cls1 = *clauses[live_clauses[i]]; - literal lit = find_blocked(cls1); - if (lit != null_literal) { - m_removed.setx(cls1.id(), true, false); - removed = true; - live_clauses[i] = live_clauses.back(); - live_clauses.pop_back(); - --i; - } - } - } - //std::cout << "\n"; - m_bce_use_list.erase(cls0); - clauses.pop_back(); - blits.pop_back(); - return live_clauses.empty(); - } - - literal bceq::find_blocked(clause const& cls) { - TRACE("bceq", tout << cls << "\n";); - - unsigned sz = cls.size(); - for (unsigned i = 0; i < sz; ++i) { - m_marked[(~cls[i]).index()] = true; - } - literal result = null_literal; - for (unsigned i = 0; i < sz; ++i) { - literal lit = cls[i]; - if (is_blocked(lit)) { - TRACE("bceq", tout << "is blocked " << lit << " : " << cls << "\n";); - result = lit; - break; - } - } - for (unsigned i = 0; i < sz; ++i) { - m_marked[(~cls[i]).index()] = false; - } - return result; - } - - bool bceq::is_blocked(literal lit) const { - clause_use_list& uses = m_use_list->get(~lit); - unsigned sz = uses.size(); - for (unsigned i = 0; i < sz; ++i) { - clause const& cls = *uses[i]; - unsigned sz = cls.size(); - bool is_axiom = m_removed.get(cls.id(), false); - for (unsigned i = 0; !is_axiom && i < sz; ++i) { - is_axiom = m_marked[cls[i].index()] && cls[i] != ~lit; - } - - TRACE("bceq", tout << "resolvent " << lit << " : " << cls << " " << (is_axiom?"axiom":"non-axiom") << "\n";); - if (!is_axiom) { - return false; - } - } - return true; - } - - - void bceq::init_rbits() { - m_rbits.reset(); - for (unsigned i = 0; i < m_solver.num_vars(); ++i) { - uint64 lo = m_rand() + (m_rand() << 16); - uint64 hi = m_rand() + (m_rand() << 16); - m_rbits.push_back(lo + (hi << 32ULL)); - } - } - - void bceq::init_reconstruction_stack() { - m_rstack.reset(); - m_bstack.reset(); - // decomposition already creates a blocked stack in the proper order. - m_rstack.append(m_L); - m_bstack.append(m_L_blits); - } - - uint64 bceq::eval_clause(clause const& cls) const { - uint64 b = 0; - unsigned sz = cls.size(); - for (unsigned i = 0; i < sz; ++i) { - literal lit = cls[i]; - uint64 val = m_rbits[lit.var()]; - if (lit.sign()) { - val = ~val; - } - b |= val; - } - return b; - } - - void bceq::sat_sweep() { - init_rbits(); - init_reconstruction_stack(); - for (unsigned i = 0; i < m_rstack.size(); ++i) { - clause const& cls = *m_rstack[i]; - literal block_lit = m_bstack[i]; - uint64 b = eval_clause(cls); - // v = 0, b = 0 -> v := 1 - // v = 0, b = 1 -> v := 0 - // v = 1, b = 0 -> v := 0 - // v = 1, b = 1 -> v := 1 - m_rbits[block_lit.var()] ^= ~b; - - } - DEBUG_CODE(verify_sweep();); - } - - void bceq::verify_sweep() { - DEBUG_CODE( - for (unsigned i = 0; i < m_L.size(); ++i) { - uint64 b = eval_clause(*m_L[i]); - SASSERT((~b) == 0); - }); - } - - struct u64_hash { unsigned operator()(uint64 u) const { return (unsigned)u; } }; - - struct u64_eq { bool operator()(uint64 u1, uint64 u2) const { return u1 == u2; } }; - - void bceq::extract_partition() { - unsigned num_vars = m_solver.num_vars(); - map table; - union_find<> union_find(m_union_find_ctx); - for (unsigned i = 0; i < num_vars; ++i) { - m_s->mk_var(true, true); - union_find.mk_var(); - } - for (unsigned i = 0; i < m_L.size(); ++i) { - m_s->mk_clause(m_L[i]->size(), m_L[i]->begin()); - } - for (unsigned i = 0; i < num_vars; ++i) { - uint64 val = m_rbits[i]; - unsigned index; - if (table.find(val, index)) { - union_find.merge(i, index); - } - else if (table.find(~val, index)) { - union_find.merge(i, index); - } - else { - table.insert(val, i); - } - } - TRACE("sat", union_find.display(tout);); - - // - // Preliminary version: - // A more appropriate is to walk each pair, - // and refine partition based on SAT results. - // - for (unsigned i = 0; i < num_vars; ++i) { - if (!union_find.is_root(i)) continue; - unsigned v = union_find.next(i); - unsigned last_v = UINT_MAX; - if (!m_solver.was_eliminated(i)) { - last_v = i; - } - while (v != i) { - if (!m_solver.was_eliminated(v)) { - if (last_v != UINT_MAX) { - if (check_equality(v, last_v)) { - // last_v was eliminated. - - } - else { - // TBD: refine partition. - } - } - last_v = v; - } - v = union_find.next(v); - } - } - } - - bool bceq::check_equality(unsigned v1, unsigned v2) { - TRACE("sat", tout << "check: " << v1 << " = " << v2 << "\n";); - uint64 val1 = m_rbits[v1]; - uint64 val2 = m_rbits[v2]; - literal l1 = literal(v1, false); - literal l2 = literal(v2, false); - if (val1 != val2) { - SASSERT(val1 == ~val2); - l2.neg(); - } - if (is_already_equiv(l1, l2)) { - TRACE("sat", tout << "Already equivalent: " << l1 << " " << l2 << "\n";); - return false; - } - - literal lits[2]; - lits[0] = l1; - lits[1] = ~l2; - lbool is_sat = m_s->check(2, lits); - if (is_sat == l_false) { - lits[0] = ~l1; - lits[1] = l2; - is_sat = m_s->check(2, lits); - } - if (is_sat == l_false) { - TRACE("sat", tout << "Found equivalent: " << l1 << " " << l2 << "\n";); - assert_equality(l1, l2); - } - else { - TRACE("sat", tout << "Not equivalent: " << l1 << " " << l2 << "\n";); - // TBD: if is_sat == l_true, then refine partition. - } - return is_sat == l_false; - } - - bool bceq::is_already_equiv(literal l1, literal l2) { - watch_list const& w1 = m_solver.get_wlist(l1); - bool found = false; - for (unsigned i = 0; !found && i < w1.size(); ++i) { - watched const& w = w1[i]; - found = w.is_binary_clause() && w.get_literal() == ~l2; - } - if (!found) return false; - found = false; - watch_list const& w2 = m_solver.get_wlist(~l1); - for (unsigned i = 0; !found && i < w2.size(); ++i) { - watched const& w = w2[i]; - found = w.is_binary_clause() && w.get_literal() == l2; - } - return found; - } - - void bceq::assert_equality(literal l1, literal l2) { - if (l2.sign()) { - l1.neg(); - l2.neg(); - } - literal_vector roots; - bool_var_vector vars; - for (unsigned i = 0; i < m_solver.num_vars(); ++i) { - roots.push_back(literal(i, false)); - } - roots[l2.var()] = l1; - vars.push_back(l2.var()); - elim_eqs elim(m_solver); - IF_VERBOSE(1, - for (unsigned i = 0; i < vars.size(); ++i) { - verbose_stream() << "var: " << vars[i] << " root: " << roots[vars[i]] << "\n"; - }); - elim(roots, vars); - } - - void bceq::cleanup() { - m_solver.del_clauses(m_bin_clauses.begin(), m_bin_clauses.end()); - m_bin_clauses.reset(); - } - - - void bceq::operator()() { - if (!m_solver.m_config.m_bcd) return; - flet _disable_bcd(m_solver.m_config.m_bcd, false); - flet _disable_min(m_solver.m_config.m_core_minimize, false); - flet _disable_opt(m_solver.m_config.m_optimize_model, false); - flet _bound_maxc(m_solver.m_config.m_max_conflicts, 1500); - - use_list ul; - solver s(m_solver.m_params, m_solver.rlimit(), 0); - s.m_config.m_bcd = false; - s.m_config.m_core_minimize = false; - s.m_config.m_optimize_model = false; - s.m_config.m_max_conflicts = 1500; - m_use_list = &ul; - m_s = &s; - ul.init(m_solver.num_vars()); - init(); - pure_decompose(); - post_decompose(); - IF_VERBOSE(1, verbose_stream() << "Decomposed set " << m_L.size() << " rest: " << m_R.size() << "\n";); - - TRACE("sat", - tout << "Decomposed set " << m_L.size() << "\n"; - for (unsigned i = 0; i < m_L.size(); ++i) { - clause const* cls = m_L[i]; - if (cls) tout << *cls << "\n"; - } - tout << "remainder " << m_R.size() << "\n"; - for (unsigned i = 0; i < m_R.size(); ++i) { - clause const* cls = m_R[i]; - if (cls) tout << *cls << "\n"; - } - ); - sat_sweep(); - extract_partition(); - cleanup(); - } -}; diff --git a/src/sat/sat_bceq.h b/src/sat/sat_bceq.h deleted file mode 100644 index c9d01e78b..000000000 --- a/src/sat/sat_bceq.h +++ /dev/null @@ -1,89 +0,0 @@ -/*++ -Copyright (c) 2014 Microsoft Corporation - -Module Name: - - sat_bceq.h - -Abstract: - - Find equivalent literals based on blocked clause decomposition. - -Author: - - Nikolaj Bjorner (nbjorner) 2014-09-27. - -Revision History: - ---*/ -#ifndef SAT_BCEQ_H_ -#define SAT_BCEQ_H_ - -#include"sat_types.h" -#include"union_find.h" - - -namespace sat { - class solver; - - class bceq { - typedef ptr_vector clause_use_list; - class use_list { - vector > m_clauses; - public: - use_list() {} - void init(unsigned num_vars); - void reset() { m_clauses.reset(); } - void erase(clause& c); - void insert(clause& c); - ptr_vector& get(literal lit); - }; - typedef std::pair bin_clause; - typedef svector bin_clauses; - solver & m_solver; - use_list* m_use_list; - use_list m_bce_use_list; - solver* m_s; - random_gen m_rand; - svector m_clauses; - svector m_L; - svector m_R; - literal_vector m_L_blits; - literal_vector m_R_blits; - svector m_bin_clauses; - svector m_rbits; - svector m_rstack; // stack of blocked clauses - literal_vector m_bstack; // stack of blocking literals - svector m_marked; - svector m_removed; // set of clauses removed (not considered in clause set during BCE) - union_find_default_ctx m_union_find_ctx; - unsigned_vector m_live_clauses; - - void init(); - void register_clause(clause* cls); - void unregister_clause(clause* cls); - void pure_decompose(); - void pure_decompose(literal lit); - void pure_decompose(ptr_vector& uses, svector& clauses); - void post_decompose(); - literal find_blocked(clause const& cls); - bool bce(clause& cls); - bool is_blocked(literal lit) const; - void init_rbits(); - void init_reconstruction_stack(); - void sat_sweep(); - void cleanup(); - uint64 eval_clause(clause const& cls) const; - void verify_sweep(); - void extract_partition(); - bool check_equality(unsigned v1, unsigned v2); - bool is_already_equiv(literal l1, literal l2); - void assert_equality(literal l1, literal l2); - public: - bceq(solver & s); - void operator()(); - }; - -}; - -#endif diff --git a/src/sat/sat_config.cpp b/src/sat/sat_config.cpp index 7e0a7c50c..4e01bfe55 100644 --- a/src/sat/sat_config.cpp +++ b/src/sat/sat_config.cpp @@ -111,8 +111,6 @@ namespace sat { m_minimize_lemmas = p.minimize_lemmas(); m_core_minimize = p.core_minimize(); m_core_minimize_partial = p.core_minimize_partial(); - m_optimize_model = p.optimize_model(); - m_bcd = p.bcd(); m_dyn_sub_res = p.dyn_sub_res(); } diff --git a/src/sat/sat_config.h b/src/sat/sat_config.h index 1cdabddef..910ca0360 100644 --- a/src/sat/sat_config.h +++ b/src/sat/sat_config.h @@ -72,8 +72,6 @@ namespace sat { bool m_dyn_sub_res; bool m_core_minimize; bool m_core_minimize_partial; - bool m_optimize_model; - bool m_bcd; symbol m_always_true; diff --git a/src/sat/sat_mus.cpp b/src/sat/sat_mus.cpp index 7b3277b6c..380b8ee94 100644 --- a/src/sat/sat_mus.cpp +++ b/src/sat/sat_mus.cpp @@ -20,11 +20,10 @@ Notes: #include "sat_solver.h" #include "sat_mus.h" -#include "sat_sls.h" namespace sat { - mus::mus(solver& s):s(s), m_is_active(false), m_best_value(0), m_restart(0), m_max_restarts(0) {} + mus::mus(solver& s):s(s), m_is_active(false),m_restart(0), m_max_restarts(0) {} mus::~mus() {} @@ -32,7 +31,6 @@ namespace sat { m_core.reset(); m_mus.reset(); m_model.reset(); - m_best_value = 0; m_max_restarts = (s.m_stats.m_restart - m_restart) + 10; m_restart = s.m_stats.m_restart; } @@ -45,21 +43,13 @@ namespace sat { } void mus::update_model() { - double new_value = s.m_wsls.evaluate_model(s.m_model); if (m_model.empty()) { m_model.append(s.m_model); - m_best_value = new_value; - } - else if (m_best_value > new_value) { - m_model.reset(); - m_model.append(s.m_model); - m_best_value = new_value; } } lbool mus::operator()() { flet _disable_min(s.m_config.m_core_minimize, false); - flet _disable_opt(s.m_config.m_optimize_model, false); flet _is_active(m_is_active, true); IF_VERBOSE(3, verbose_stream() << "(sat.mus " << s.get_core() << ")\n";); reset(); @@ -120,9 +110,6 @@ namespace sat { SASSERT(value_at(lit, s.get_model()) == l_false); mus.push_back(lit); update_model(); - if (!core.empty()) { - // mr(); // TBD: measure - } break; } case l_false: @@ -262,27 +249,5 @@ namespace sat { IF_VERBOSE(3, verbose_stream() << "core verification: " << is_sat << " " << core << "\n";); } - void mus::mr() { - sls sls(s); - literal_vector tabu; - tabu.append(m_mus); - tabu.append(m_core); - bool reuse_model = false; - for (unsigned i = m_mus.size(); i < tabu.size(); ++i) { - tabu[i] = ~tabu[i]; - lbool is_sat = sls(tabu.size(), tabu.c_ptr(), reuse_model); - tabu[i] = ~tabu[i]; - if (is_sat == l_true) { - m_mus.push_back(tabu[i]); - m_core.erase(tabu[i]); - IF_VERBOSE(3, verbose_stream() << "in core " << tabu[i] << "\n";); - reuse_model = true; - } - else { - IF_VERBOSE(3, verbose_stream() << "NOT in core " << tabu[i] << "\n";); - reuse_model = false; - } - } - } } diff --git a/src/sat/sat_mus.h b/src/sat/sat_mus.h index 617bbc757..74f6d75f0 100644 --- a/src/sat/sat_mus.h +++ b/src/sat/sat_mus.h @@ -26,7 +26,6 @@ namespace sat { literal_vector m_mus; bool m_is_active; model m_model; // model obtained during minimal unsat core - double m_best_value; unsigned m_restart; unsigned m_max_restarts; @@ -41,7 +40,6 @@ namespace sat { lbool mus1(); lbool mus2(); lbool qx(literal_set& assignment, literal_set& support, bool has_support); - void mr(); void reset(); void set_core(); void update_model(); diff --git a/src/sat/sat_params.pyg b/src/sat/sat_params.pyg index de1759486..21a50bea2 100644 --- a/src/sat/sat_params.pyg +++ b/src/sat/sat_params.pyg @@ -22,6 +22,4 @@ def_module_params('sat', ('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'), ('core.minimize', BOOL, False, 'minimize computed core'), ('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'), - ('optimize_model', BOOL, False, 'enable optimization of soft constraints'), - ('bcd', BOOL, False, 'enable blocked clause decomposition for equality extraction'), ('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks'))) diff --git a/src/sat/sat_sls.cpp b/src/sat/sat_sls.cpp deleted file mode 100644 index 7efc0ce0b..000000000 --- a/src/sat/sat_sls.cpp +++ /dev/null @@ -1,686 +0,0 @@ -/*++ -Copyright (c) 2014 Microsoft Corporation - -Module Name: - - sat_sls.cpp - -Abstract: - - SLS for clauses in SAT solver - -Author: - - Nikolaj Bjorner (nbjorner) 2014-12-8 - -Notes: - ---*/ - -#include "sat_sls.h" -#include "sat_solver.h" - -namespace sat { - - bool index_set::contains(unsigned idx) const { - return - (idx < m_index.size()) && - (m_index[idx] < m_elems.size()) && - (m_elems[m_index[idx]] == idx); - } - - void index_set::insert(unsigned idx) { - m_index.reserve(idx+1); - if (!contains(idx)) { - m_index[idx] = m_elems.size(); - m_elems.push_back(idx); - } - } - - void index_set::remove(unsigned idx) { - if (!contains(idx)) return; - unsigned pos = m_index[idx]; - m_elems[pos] = m_elems.back(); - m_index[m_elems[pos]] = pos; - m_elems.pop_back(); - } - - unsigned index_set::choose(random_gen& rnd) const { - SASSERT(!empty()); - return m_elems[rnd(num_elems())]; - } - - sls::sls(solver& s): s(s) { - m_prob_choose_min_var = 43; - m_clause_generation = 0; - } - - sls::~sls() { - for (unsigned i = 0; i < m_bin_clauses.size(); ++i) { - m_alloc.del_clause(m_bin_clauses[i]); - } - } - - lbool sls::operator()(unsigned sz, literal const* tabu, bool reuse_model) { - init(sz, tabu, reuse_model); - unsigned i; - for (i = 0; !m_false.empty() && !s.canceled() && i < m_max_tries; ++i) { - flip(); - } - IF_VERBOSE(2, verbose_stream() << "tries " << i << "\n";); - if (m_false.empty()) { - SASSERT(s.check_model(m_model)); - return l_true; - } - return l_undef; - } - - void sls::init(unsigned sz, literal const* tabu, bool reuse_model) { - bool same_generation = (m_clause_generation == s.m_stats.m_non_learned_generation); - if (!same_generation) { - init_clauses(); - init_use(); - IF_VERBOSE(0, verbose_stream() << s.m_stats.m_non_learned_generation << " " << m_clause_generation << "\n";); - } - if (!reuse_model) { - init_model(); - } - init_tabu(sz, tabu); - m_clause_generation = s.m_stats.m_non_learned_generation; - - m_max_tries = 10*(s.num_vars() + m_clauses.size()); - - } - - void sls::init_clauses() { - for (unsigned i = 0; i < m_bin_clauses.size(); ++i) { - m_alloc.del_clause(m_bin_clauses[i]); - } - m_bin_clauses.reset(); - m_clauses.reset(); - clause * const * it = s.begin_clauses(); - clause * const * end = s.end_clauses(); - for (; it != end; ++it) { - m_clauses.push_back(*it); - } - svector bincs; - s.collect_bin_clauses(bincs, false); - literal lits[2]; - for (unsigned i = 0; i < bincs.size(); ++i) { - lits[0] = bincs[i].first; - lits[1] = bincs[i].second; - clause* cl = m_alloc.mk_clause(2, lits, false); - m_clauses.push_back(cl); - m_bin_clauses.push_back(cl); - } - } - - void sls::init_model() { - m_num_true.reset(); - m_model.reset(); - m_model.append(s.get_model()); - unsigned sz = m_clauses.size(); - for (unsigned i = 0; i < sz; ++i) { - clause const& c = *m_clauses[i]; - unsigned n = 0; - unsigned csz = c.size(); - for (unsigned j = 0; j < csz; ++j) { - lbool val = value_at(c[j], m_model); - switch (val) { - case l_true: - ++n; - break; - case l_undef: - ++n; - m_model[c[j].var()] = c[j].sign()?l_false:l_true; - SASSERT(value_at(c[j], m_model) == l_true); - break; - default: - break; - } - } - m_num_true.push_back(n); - if (n == 0) { - m_false.insert(i); - } - } - } - - void sls::init_tabu(unsigned sz, literal const* tabu) { - // our main use is where m_model satisfies all the hard constraints. - // SASSERT(s.check_model(m_model)); - // SASSERT(m_false.empty()); - // ASSERT: m_num_true is correct count. - m_tabu.reset(); - m_tabu.resize(s.num_vars(), false); - for (unsigned i = 0; i < sz; ++i) { - literal lit = tabu[i]; - if (s.m_level[lit.var()] == 0) continue; - if (value_at(lit, m_model) == l_false) { - flip(lit); - } - m_tabu[lit.var()] = true; - } - for (unsigned i = 0; i < s.m_trail.size(); ++i) { - literal lit = s.m_trail[i]; - if (s.m_level[lit.var()] > 0) break; - if (value_at(lit, m_model) != l_true) { - flip(lit); - } - m_tabu[lit.var()] = true; - } - } - - void sls::init_use() { - m_use_list.reset(); - m_use_list.resize(s.num_vars()*2); - unsigned sz = m_clauses.size(); - for (unsigned i = 0; i < sz; ++i) { - clause const& c = *m_clauses[i]; - unsigned csz = c.size(); - for (unsigned j = 0; j < csz; ++j) { - m_use_list[c[j].index()].push_back(i); - } - } - DEBUG_CODE(check_use_list();); - } - - unsigned_vector const& sls::get_use(literal lit) { - SASSERT(lit.index() < m_use_list.size()); - return m_use_list[lit.index()]; - } - - unsigned sls::get_break_count(literal lit, unsigned min_break) { - SASSERT(value_at(lit, m_model) == l_false); - unsigned result = 0; - unsigned_vector const& uses = get_use(~lit); - unsigned sz = uses.size(); - for (unsigned i = 0; i < sz; ++i) { - if (m_num_true[uses[i]] == 1) { - ++result; - if (result > min_break) return result; - } - } - return result; - } - - bool sls::pick_flip(literal& lit) { - unsigned clause_idx = m_false.choose(m_rand); - clause const& c = *m_clauses[clause_idx]; - SASSERT(!c.satisfied_by(m_model)); - unsigned min_break = UINT_MAX; - unsigned sz = c.size(); - m_min_vars.reset(); - for (unsigned i = 0; i < sz; ++i) { - lit = c[i]; - if (m_tabu[lit.var()]) continue; - unsigned break_count = get_break_count(lit, min_break); - if (break_count < min_break) { - min_break = break_count; - m_min_vars.reset(); - m_min_vars.push_back(lit); - } - else if (break_count == min_break) { - m_min_vars.push_back(lit); - } - } - if (min_break == 0 || (!m_min_vars.empty() && m_rand(100) >= m_prob_choose_min_var)) { - lit = m_min_vars[m_rand(m_min_vars.size())]; - return true; - } - else if (min_break == UINT_MAX) { - return false; - } - else { - lit = c[m_rand(c.size())]; - return !m_tabu[lit.var()]; - } - } - - void sls::flip() { - literal lit; - if (pick_flip(lit)) { - flip(lit); - } - } - - void sls::flip(literal lit) { - //IF_VERBOSE(0, verbose_stream() << lit << " ";); - SASSERT(value_at(lit, m_model) == l_false); - SASSERT(!m_tabu[lit.var()]); - m_model[lit.var()] = lit.sign()?l_false:l_true; - SASSERT(value_at(lit, m_model) == l_true); - unsigned_vector const& use1 = get_use(lit); - unsigned sz = use1.size(); - for (unsigned i = 0; i < sz; ++i) { - unsigned cl = use1[i]; - m_num_true[cl]++; - SASSERT(m_num_true[cl] <= m_clauses[cl]->size()); - if (m_num_true[cl] == 1) m_false.remove(cl); - } - unsigned_vector const& use2 = get_use(~lit); - sz = use2.size(); - for (unsigned i = 0; i < sz; ++i) { - unsigned cl = use2[i]; - SASSERT(m_num_true[cl] > 0); - m_num_true[cl]--; - if (m_num_true[cl] == 0) m_false.insert(cl); - } - } - - void sls::check_invariant() { - DEBUG_CODE( - for (unsigned i = 0; i < m_clauses.size(); ++i) { - clause const& c = *m_clauses[i]; - bool is_sat = c.satisfied_by(m_model); - SASSERT(is_sat != m_false.contains(i)); - SASSERT(is_sat == (m_num_true[i] > 0)); - }); - } - - void sls::check_use_list() { - DEBUG_CODE( - for (unsigned i = 0; i < m_clauses.size(); ++i) { - clause const& c = *m_clauses[i]; - for (unsigned j = 0; j < c.size(); ++j) { - unsigned idx = c[j].index(); - SASSERT(m_use_list[idx].contains(i)); - } - } - - for (unsigned i = 0; i < m_use_list.size(); ++i) { - literal lit = to_literal(i); - for (unsigned j = 0; j < m_use_list[i].size(); ++j) { - clause const& c = *m_clauses[m_use_list[i][j]]; - bool found = false; - for (unsigned k = 0; !found && k < c.size(); ++k) { - found = c[k] == lit; - } - SASSERT(found); - } - }); - } - - void sls::display(std::ostream& out) const { - out << "Model\n"; - for (bool_var v = 0; v < m_model.size(); ++v) { - out << v << ": " << m_model[v] << "\n"; - } - out << "Clauses\n"; - unsigned sz = m_false.num_elems(); - for (unsigned i = 0; i < sz; ++i) { - out << *m_clauses[m_false[i]] << "\n"; - } - for (unsigned i = 0; i < m_clauses.size(); ++i) { - if (m_false.contains(i)) continue; - clause const& c = *m_clauses[i]; - out << c << " " << m_num_true[i] << "\n"; - } - bool has_tabu = false; - for (unsigned i = 0; !has_tabu && i < m_tabu.size(); ++i) { - has_tabu = m_tabu[i]; - } - if (has_tabu) { - out << "Tabu: "; - for (unsigned i = 0; i < m_tabu.size(); ++i) { - if (m_tabu[i]) { - literal lit(i, false); - if (value_at(lit, m_model) == l_false) lit.neg(); - out << lit << " "; - } - } - out << "\n"; - } - } - - - wsls::wsls(solver& s): - sls(s) - { - m_smoothing_probability = 1; // 1/1000 - } - - wsls::~wsls() {} - - void wsls::set_soft(unsigned sz, literal const* lits, double const* weights) { - m_soft.reset(); - m_weights.reset(); - m_soft.append(sz, lits); - m_weights.append(sz, weights); - } - - void wsls::opt(unsigned sz, literal const* tabu, bool reuse_model) { - init(sz, tabu, reuse_model); - - // - // Initialize m_clause_weights, m_hscore, m_sscore. - // - m_best_value = m_false.empty()?evaluate_model(m_model):-1.0; - m_best_model.reset(); - m_clause_weights.reset(); - m_hscore.reset(); - m_sscore.reset(); - m_H.reset(); - m_S.reset(); - m_best_model.append(s.get_model()); - m_clause_weights.resize(m_clauses.size(), 1); - m_sscore.resize(s.num_vars(), 0.0); - m_hscore.resize(s.num_vars(), 0); - for (unsigned i = 0; i < m_soft.size(); ++i) { - literal lit = m_soft[i]; - m_sscore[lit.var()] = m_weights[i]; - if (value_at(lit, m_model) == l_true) { - m_sscore[lit.var()] = -m_sscore[lit.var()]; - } - } - for (bool_var i = 0; i < s.num_vars(); ++i) { - m_hscore[i] = compute_hscore(i); - refresh_scores(i); - } - DEBUG_CODE(check_invariant();); - unsigned i = 0; - for (; !s.canceled() && m_best_value > 0 && i < m_max_tries; ++i) { - wflip(); - if (m_false.empty()) { - double val = evaluate_model(m_model); - if (val < m_best_value || m_best_value < 0.0) { - m_best_value = val; - m_best_model.reset(); - m_best_model.append(m_model); - s.set_model(m_best_model); - IF_VERBOSE(1, verbose_stream() << "new value: " << val << " @ " << i << "\n";); - if (i*2 > m_max_tries) { - m_max_tries *= 2; - } - } - } - } - TRACE("sat", display(tout);); - IF_VERBOSE(0, verbose_stream() << "tries " << i << "\n";); - } - - void wsls::wflip() { - literal lit; - if (pick_wflip(lit)) { - // IF_VERBOSE(0, verbose_stream() << lit << " ";); - wflip(lit); - } - } - - bool wsls::pick_wflip(literal & lit) { - unsigned idx; - if (!m_H.empty()) { - idx = m_H.choose(m_rand); - lit = literal(idx, false); - if (value_at(lit, m_model) == l_true) lit.neg(); - SASSERT(value_at(lit, m_model) == l_false); - TRACE("sat", tout << "flip H(" << m_H.num_elems() << ") " << lit << "\n";); - } - else if (!m_S.empty()) { - double score = 0.0; - m_min_vars.reset(); - for (unsigned i = 0; i < m_S.num_elems(); ++i) { - unsigned v = m_S[i]; - SASSERT(m_sscore[v] > 0.0); - if (m_sscore[v] > score) { - m_min_vars.reset(); - m_min_vars.push_back(literal(v, false)); - score = m_sscore[v]; - } - else if (m_sscore[v] == score) { - m_min_vars.push_back(literal(v, false)); - } - } - lit = m_min_vars[m_rand(m_min_vars.size())]; // pick with largest sscore. - SASSERT(value_at(lit, m_model) == l_false); - TRACE("sat", tout << "flip S(" << m_min_vars.size() << "," << score << ") " << lit << "\n";); - } - else { - update_hard_weights(); - if (!m_false.empty()) { - unsigned cls_idx = m_false.choose(m_rand); - clause const& c = *m_clauses[cls_idx]; - lit = c[m_rand(c.size())]; - TRACE("sat", tout << "flip hard(" << m_false.num_elems() << "," << c.size() << ") " << lit << "\n";); - } - else { - m_min_vars.reset(); - for (unsigned i = 0; i < m_soft.size(); ++i) { - lit = m_soft[i]; - if (value_at(lit, m_model) == l_false) { - m_min_vars.push_back(lit); - } - } - if (m_min_vars.empty()) { - SASSERT(m_best_value == 0.0); - UNREACHABLE(); // we should have exited the main loop before. - return false; - } - else { - lit = m_min_vars[m_rand(m_min_vars.size())]; - } - TRACE("sat", tout << "flip soft(" << m_min_vars.size() << ", " << m_sscore[lit.var()] << ") " << lit << "\n";); - - } - SASSERT(value_at(lit, m_model) == l_false); - } - return !m_tabu[lit.var()]; - } - - void wsls::wflip(literal lit) { - flip(lit); - unsigned v = lit.var(); - m_sscore[v] = -m_sscore[v]; - m_hscore[v] = compute_hscore(v); - refresh_scores(v); - recompute_hscores(lit); - } - - void wsls::update_hard_weights() { - unsigned csz = m_clauses.size(); - if (m_smoothing_probability >= m_rand(1000)) { - for (unsigned i = 0; i < csz; ++i) { - if (m_clause_weights[i] > 1 && !m_false.contains(i)) { - --m_clause_weights[i]; - if (m_num_true[i] == 1) { - clause const& c = *m_clauses[i]; - unsigned sz = c.size(); - for (unsigned j = 0; j < sz; ++j) { - if (value_at(c[j], m_model) == l_true) { - ++m_hscore[c[j].var()]; - refresh_scores(c[j].var()); - break; - } - } - } - } - } - } - else { - for (unsigned i = 0; i < csz; ++i) { - if (m_false.contains(i)) { - ++m_clause_weights[i]; - clause const& c = *m_clauses[i]; - unsigned sz = c.size(); - for (unsigned j = 0; j < sz; ++j) { - ++m_hscore[c[j].var()]; - refresh_scores(c[j].var()); - } - } - } - } - DEBUG_CODE(check_invariant();); - } - - double wsls::evaluate_model(model& mdl) { - SASSERT(m_false.empty()); - double result = 0.0; - for (unsigned i = 0; i < m_soft.size(); ++i) { - literal lit = m_soft[i]; - if (value_at(lit, mdl) != l_true) { - result += m_weights[i]; - } - } - return result; - } - - int wsls::compute_hscore(bool_var v) { - literal lit(v, false); - if (value_at(lit, m_model) == l_false) { - lit.neg(); - } - SASSERT(value_at(lit, m_model) == l_true); - int hs = 0; - unsigned_vector const& use1 = get_use(~lit); - unsigned sz = use1.size(); - for (unsigned i = 0; i < sz; ++i) { - unsigned cl = use1[i]; - if (m_num_true[cl] == 0) { - SASSERT(m_false.contains(cl)); - hs += m_clause_weights[cl]; - } - else { - SASSERT(!m_false.contains(cl)); - } - } - unsigned_vector const& use2 = get_use(lit); - sz = use2.size(); - for (unsigned i = 0; i < sz; ++i) { - unsigned cl = use2[i]; - if (m_num_true[cl] == 1) { - SASSERT(!m_false.contains(cl)); - hs -= m_clause_weights[cl]; - } - } - return hs; - } - - void wsls::recompute_hscores(literal lit) { - SASSERT(value_at(lit, m_model) == l_true); - TRACE("sat", tout << lit.var() << " := " << m_hscore[lit.var()] << "\n";); - unsigned_vector const& use1 = get_use(lit); - unsigned sz = use1.size(); - for (unsigned i = 0; i < sz; ++i) { - unsigned cl = use1[i]; - TRACE("sat", tout << *m_clauses[cl] << " " << m_num_true[cl] << "\n";); - SASSERT(m_num_true[cl] > 0); - if (m_num_true[cl] == 1) { - // num_true 0 -> 1 - // other literals don't have upside any more. - // subtract one from all other literals - adjust_all_values(lit, cl, -static_cast(m_clause_weights[cl])); - } - else if (m_num_true[cl] == 2) { - // num_true 1 -> 2, previous critical literal is no longer critical - adjust_pivot_value(lit, cl, +m_clause_weights[cl]); - } - } - unsigned_vector const& use2 = get_use(~lit); - sz = use2.size(); - for (unsigned i = 0; i < sz; ++i) { - unsigned cl = use2[i]; - TRACE("sat", tout << *m_clauses[cl] << " " << m_num_true[cl] << "\n";); - if (m_num_true[cl] == 0) { - // num_true 1 -> 0 - // all variables became critical. - adjust_all_values(~lit, cl, +m_clause_weights[cl]); - } - else if (m_num_true[cl] == 1) { - adjust_pivot_value(~lit, cl, -static_cast(m_clause_weights[cl])); - } - // else n+1 -> n >= 2 - } - } - - void wsls::adjust_all_values(literal lit, unsigned cl, int delta) { - clause const& c = *m_clauses[cl]; - unsigned sz = c.size(); - TRACE("sat", tout << lit << " " << c << " delta: " << delta << " nt: " << m_num_true[cl] << "\n";); - for (unsigned i = 0; i < sz; ++i) { - literal lit2 = c[i]; - if (lit2 != lit) { - TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";); - m_hscore[lit2.var()] += delta; - TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";); - refresh_scores(lit2.var()); - } - } - } - - void wsls::adjust_pivot_value(literal lit, unsigned cl, int delta) { - clause const& c = *m_clauses[cl]; - unsigned csz = c.size(); - for (unsigned j = 0; j < csz; ++j) { - literal lit2 = c[j]; - if (lit2 != lit && value_at(lit2, m_model) == l_true) { - TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";); - m_hscore[lit2.var()] += delta; - TRACE("sat", tout << lit2.var() << " := " << m_hscore[lit2.var()] << "\n";); - refresh_scores(lit2.var()); - break; - } - } - } - - void wsls::refresh_scores(bool_var v) { - if (m_hscore[v] > 0 && !m_tabu[v] && m_sscore[v] == 0) { - m_H.insert(v); - } - else { - m_H.remove(v); - } - if (m_sscore[v] > 0) { - if (m_hscore[v] == 0 && !m_tabu[v]) { - m_S.insert(v); - } - else { - m_S.remove(v); - } - } - else if (m_sscore[v] < 0) { - m_S.remove(v); - } - } - - void wsls::check_invariant() { - sls::check_invariant(); - // The hscore is the reward for flipping the truth value of variable v. - // hscore(v) = Sum weight(c) for num_true(c) = 0 and v in c - // - Sum weight(c) for num_true(c) = 1 and (v in c, M(v) or !v in c and !M(v)) - DEBUG_CODE( - for (unsigned v = 0; v < s.num_vars(); ++v) { - int hs = compute_hscore(v); - CTRACE("sat", hs != m_hscore[v], display(tout << v << " - computed: " << hs << " - assigned: " << m_hscore[v] << "\n");); - SASSERT(m_hscore[v] == hs); - } - - // The score(v) is the reward on soft clauses for flipping v. - for (unsigned j = 0; j < m_soft.size(); ++j) { - unsigned v = m_soft[j].var(); - double ss = (l_true == value_at(m_soft[j], m_model))?(-m_weights[j]):m_weights[j]; - SASSERT(m_sscore[v] == ss); - } - - // m_H are values such that m_hscore > 0 and sscore = 0. - for (bool_var v = 0; v < m_hscore.size(); ++v) { - SASSERT((m_hscore[v] > 0 && !m_tabu[v] && m_sscore[v] == 0) == m_H.contains(v)); - } - - // m_S are values such that hscore = 0, sscore > 0 - for (bool_var v = 0; v < m_sscore.size(); ++v) { - SASSERT((m_hscore[v] == 0 && m_sscore[v] > 0 && !m_tabu[v]) == m_S.contains(v)); - }); - } - - void wsls::display(std::ostream& out) const { - sls::display(out); - out << "Best model\n"; - for (bool_var v = 0; v < m_best_model.size(); ++v) { - out << v << ": " << m_best_model[v] << " h: " << m_hscore[v]; - if (m_sscore[v] != 0.0) out << " s: " << m_sscore[v]; - out << "\n"; - } - } - -}; - diff --git a/src/sat/sat_sls.h b/src/sat/sat_sls.h deleted file mode 100644 index f1bf55543..000000000 --- a/src/sat/sat_sls.h +++ /dev/null @@ -1,115 +0,0 @@ -/*++ -Copyright (c) 2014 Microsoft Corporation - -Module Name: - - sat_sls.h - -Abstract: - - SLS for clauses in SAT solver - -Author: - - Nikolaj Bjorner (nbjorner) 2014-12-8 - -Notes: - ---*/ -#ifndef SAT_SLS_H_ -#define SAT_SLS_H_ - -#include "util.h" -#include "sat_simplifier.h" - -namespace sat { - - class index_set { - unsigned_vector m_elems; - unsigned_vector m_index; - public: - unsigned num_elems() const { return m_elems.size(); } - unsigned operator[](unsigned idx) const { return m_elems[idx]; } - void reset() { m_elems.reset(); m_index.reset(); } - bool empty() const { return m_elems.empty(); } - bool contains(unsigned idx) const; - void insert(unsigned idx); - void remove(unsigned idx); - unsigned choose(random_gen& rnd) const; - }; - - class sls { - protected: - solver& s; - random_gen m_rand; - unsigned m_max_tries; - unsigned m_prob_choose_min_var; // number between 0 and 99. - unsigned m_clause_generation; - ptr_vector m_clauses; // vector of all clauses. - index_set m_false; // clauses currently false - vector m_use_list; // use lists for literals - unsigned_vector m_num_true; // per clause, count of # true literals - svector m_min_vars; // literals with smallest break count - model m_model; // current model - clause_allocator m_alloc; // clause allocator - clause_vector m_bin_clauses; // binary clauses - svector m_tabu; // variables that cannot be swapped - public: - sls(solver& s); - virtual ~sls(); - lbool operator()(unsigned sz, literal const* tabu, bool reuse_model); - void set_max_tries(unsigned mx) { m_max_tries = mx; } - virtual void display(std::ostream& out) const; - protected: - void init(unsigned sz, literal const* tabu, bool reuse_model); - void init_tabu(unsigned sz, literal const* tabu); - void init_model(); - void init_use(); - void init_clauses(); - unsigned_vector const& get_use(literal lit); - void flip(literal lit); - virtual void check_invariant(); - void check_use_list(); - private: - bool pick_flip(literal& lit); - void flip(); - unsigned get_break_count(literal lit, unsigned min_break); - }; - - /** - \brief sls with weighted soft clauses. - */ - class wsls : public sls { - unsigned_vector m_clause_weights; - svector m_hscore; - svector m_sscore; - literal_vector m_soft; - svector m_weights; - double m_best_value; - model m_best_model; - index_set m_H, m_S; - unsigned m_smoothing_probability; - public: - wsls(solver& s); - virtual ~wsls(); - void set_soft(unsigned sz, literal const* lits, double const* weights); - bool has_soft() const { return !m_soft.empty(); } - void opt(unsigned sz, literal const* tabu, bool reuse_model); - virtual void display(std::ostream& out) const; - double evaluate_model(model& mdl); - private: - void wflip(); - void wflip(literal lit); - void update_hard_weights(); - bool pick_wflip(literal & lit); - virtual void check_invariant(); - void refresh_scores(bool_var v); - int compute_hscore(bool_var v); - void recompute_hscores(literal lit); - void adjust_all_values(literal lit, unsigned cl, int delta); - void adjust_pivot_value(literal lit, unsigned cl, int delta); - }; - -}; - -#endif diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index 10c97b296..1ed343efa 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -20,7 +20,6 @@ Revision History: #include"sat_integrity_checker.h" #include"luby.h" #include"trace.h" -#include"sat_bceq.h" #include"max_cliques.h" // define to update glue during propagation @@ -42,7 +41,6 @@ namespace sat { m_asymm_branch(*this, p), m_probing(*this, p), m_mus(*this), - m_wsls(*this), m_inconsistent(false), m_num_frozen(0), m_activity_inc(128), @@ -55,7 +53,6 @@ namespace sat { m_conflicts = 0; m_next_simplify = 0; m_num_checkpoints = 0; - m_initializing_preferred = false; } solver::~solver() { @@ -713,7 +710,7 @@ namespace sat { // Search // // ----------------------- - lbool solver::check(unsigned num_lits, literal const* lits, double const* weights, double max_weight) { + lbool solver::check(unsigned num_lits, literal const* lits) { pop_to_base_level(); IF_VERBOSE(2, verbose_stream() << "(sat.sat-solver)\n";); SASSERT(scope_lvl() == 0); @@ -728,7 +725,7 @@ namespace sat { init_search(); propagate(false); if (inconsistent()) return l_false; - init_assumptions(num_lits, lits, weights, max_weight); + init_assumptions(num_lits, lits); propagate(false); if (check_inconsistent()) return l_false; cleanup(); @@ -914,12 +911,11 @@ namespace sat { } } - void solver::init_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight) { + void solver::init_assumptions(unsigned num_lits, literal const* lits) { if (num_lits == 0 && m_user_scope_literals.empty()) { return; } - retry_init_assumptions: reset_assumptions(); push(); @@ -943,16 +939,6 @@ namespace sat { assign(nlit, justification()); } - if (weights && !inconsistent()) { - if (m_config.m_optimize_model) { - m_wsls.set_soft(num_lits, lits, weights); - } - if (!init_weighted_assumptions(num_lits, lits, weights, max_weight)) { - goto retry_init_assumptions; - } - return; - } - for (unsigned i = 0; !inconsistent() && i < num_lits; ++i) { literal lit = lits[i]; SASSERT(is_external(lit.var())); @@ -962,109 +948,6 @@ namespace sat { } - bool solver::init_weighted_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight) { - flet _min1(m_config.m_core_minimize, false); - m_weight = 0; - m_blocker.reset(); - svector values; - unsigned num_cores = 0; - for (unsigned i = 0; !inconsistent() && i < num_lits; ++i) { - literal lit = lits[i]; - SASSERT(is_external(lit.var())); - TRACE("sat", tout << "propagate: " << lit << " " << value(lit) << "\n";); - SASSERT(m_scope_lvl == 1); - add_assumption(lit); - switch(value(lit)) { - case l_undef: - values.push_back(l_true); - assign(lit, justification()); - if (num_cores*2 >= num_lits) { - break; - } - propagate(false); - if (inconsistent()) { - flet _init(m_initializing_preferred, true); - while (inconsistent()) { - if (!resolve_conflict()) { - return true; - } - propagate(true); - } - if (m_scope_lvl == 0) { - return false; - } - // backjump to last consistent assumption: - unsigned j; - m_weight = 0; - m_blocker.reset(); - for (j = 0; j < i && value(lits[j]) == values[j]; ++j) { - if (values[j] == l_false) { - m_weight += weights[j]; - m_blocker.push_back(lits[j]); - } - } - SASSERT(value(lits[j]) != values[j]); - SASSERT(j <= i); - SASSERT(j == 0 || value(lits[j-1]) == values[j-1]); - for (unsigned k = i; k >= j; --k) { - if (is_assumption(lits[k])) { - pop_assumption(); - } - } - values.resize(j); - TRACE("sat", tout << "backjump " << (i - j + 1) << " steps " << num_cores << "\n";); - i = j - 1; - } - break; - - case l_false: - ++num_cores; - values.push_back(l_false); - SASSERT(!inconsistent()); - set_conflict(justification(), ~lit); - m_conflict_lvl = scope_lvl(); - resolve_conflict_for_unsat_core(); - IF_VERBOSE(3, verbose_stream() << "(sat.core: " << m_core << ")\n";); - update_min_core(); - SASSERT(m_min_core_valid); - m_weight += weights[i]; - if (m_weight <= max_weight) { - m_blocker.push_back(lit); - } - TRACE("sat", tout << "core: " << m_core << "\nassumptions: " << m_assumptions << "\n";); - SASSERT(m_core.size() <= m_assumptions.size()); - SASSERT(m_assumptions.size() <= i+1); - if (m_core.size() <= 3) { - m_inconsistent = true; - TRACE("opt", tout << "found small core: " << m_core << "\n";); - IF_VERBOSE(11, verbose_stream() << "(sat.core: " << m_core << ")\n";); - return true; - } - pop_assumption(); - m_inconsistent = false; - break; - case l_true: - values.push_back(l_true); - SASSERT(m_justification[lit.var()].get_kind() != justification::NONE || lvl(lit) == 0); - break; - } - } - TRACE("sat", tout << "initialized\n";); - IF_VERBOSE(11, verbose_stream() << "(sat.blocker: " << m_blocker << "\nCore: " << m_min_core << ")\n";); - if (m_weight >= max_weight) { - // block the current correction set candidate. - ++m_stats.m_blocked_corr_sets; - TRACE("opt", tout << "blocking soft correction set: " << m_blocker << "\n";); - IF_VERBOSE(11, verbose_stream() << "blocking " << m_blocker << "\n";); - pop_to_base_level(); - mk_clause_core(m_blocker); - return false; - } - return true; - } - - - void solver::update_min_core() { if (!m_min_core_valid || m_core.size() < m_min_core.size()) { m_min_core.reset(); @@ -1148,11 +1031,6 @@ namespace sat { m_min_core_valid = false; m_min_core.reset(); TRACE("sat", display(tout);); - - if (m_config.m_bcd) { - bceq bc(*this); - bc(); - } } /** @@ -1244,9 +1122,6 @@ namespace sat { m_model[v] = value(v); } TRACE("sat_mc_bug", m_mc.display(tout);); - if (m_config.m_optimize_model) { - m_wsls.opt(0, 0, false); - } m_mc(m_model); TRACE("sat", for (bool_var v = 0; v < num; v++) tout << v << ": " << m_model[v] << "\n";); @@ -1673,10 +1548,6 @@ namespace sat { if (m_not_l == literal()) tout << "null literal\n"; else tout << m_not_l << "\n";); - if (m_initializing_preferred) { - SASSERT(m_conflict_lvl <= 1); - return resolve_conflict_for_init(); - } if (m_conflict_lvl <= 1 && tracking_assumptions()) { resolve_conflict_for_unsat_core(); return false; @@ -3184,10 +3055,10 @@ namespace sat { if (asms.empty()) { bool_var v = mk_var(true, false); literal lit(v, false); - init_assumptions(1, &lit, 0, 0); + init_assumptions(1, &lit); } else { - init_assumptions(asms.size(), asms.c_ptr(), 0, 0); + init_assumptions(asms.size(), asms.c_ptr()); } propagate(false); if (check_inconsistent()) return l_false; @@ -3249,10 +3120,10 @@ namespace sat { if (asms.empty()) { bool_var v = mk_var(true, false); literal lit(v, false); - init_assumptions(1, &lit, 0, 0); + init_assumptions(1, &lit); } else { - init_assumptions(asms.size(), asms.c_ptr(), 0, 0); + init_assumptions(asms.size(), asms.c_ptr()); } propagate(false); if (check_inconsistent()) return l_false; diff --git a/src/sat/sat_solver.h b/src/sat/sat_solver.h index 1700dfb7e..d89afd898 100644 --- a/src/sat/sat_solver.h +++ b/src/sat/sat_solver.h @@ -33,7 +33,6 @@ Revision History: #include"sat_iff3_finder.h" #include"sat_probing.h" #include"sat_mus.h" -#include"sat_sls.h" #include"params.h" #include"statistics.h" #include"stopwatch.h" @@ -86,7 +85,6 @@ namespace sat { asymm_branch m_asymm_branch; probing m_probing; mus m_mus; // MUS for minimal core extraction - wsls m_wsls; // SLS facility for MaxSAT use bool m_inconsistent; // A conflict is usually a single justification. That is, a justification // for false. If m_not_l is not null_literal, then m_conflict is a @@ -141,9 +139,6 @@ namespace sat { friend class probing; friend class iff3_finder; friend class mus; - friend class sls; - friend class wsls; - friend class bceq; friend struct mk_stat; public: solver(params_ref const & p, reslimit& l, extension * ext); @@ -280,10 +275,7 @@ namespace sat { // // ----------------------- public: - lbool check(unsigned num_lits = 0, literal const* lits = 0) { - return check(num_lits, lits, 0, 0); - } - lbool check(unsigned num_lits, literal const* lits, double const* weights, double max_weight); + lbool check(unsigned num_lits = 0, literal const* lits = 0); model const & get_model() const { return m_model; } bool model_is_current() const { return m_model_is_current; } @@ -311,11 +303,7 @@ namespace sat { literal_vector m_min_core; bool m_min_core_valid; - literal_vector m_blocker; - double m_weight; - bool m_initializing_preferred; - void init_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight); - bool init_weighted_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight); + void init_assumptions(unsigned num_lits, literal const* lits); void reassert_min_core(); void update_min_core(); void resolve_weighted(); diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp index b7ce92108..33d10f428 100644 --- a/src/sat/sat_solver/inc_sat_solver.cpp +++ b/src/sat/sat_solver/inc_sat_solver.cpp @@ -105,13 +105,8 @@ public: virtual void set_progress_callback(progress_callback * callback) {} - virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) { - return check_sat(num_assumptions, assumptions, 0, 0); - } - void display_weighted(std::ostream& out, unsigned sz, expr * const * assumptions, unsigned const* weights) { - m_weights.reset(); if (weights != 0) { for (unsigned i = 0; i < sz; ++i) m_weights.push_back(weights[i]); } @@ -131,15 +126,11 @@ public: for (unsigned i = 0; i < m_asms.size(); ++i) { nweights.push_back((unsigned) m_weights[i]); } + m_weights.reset(); m_solver.display_wcnf(out, m_asms.size(), m_asms.c_ptr(), nweights.c_ptr()); } - lbool check_sat(unsigned sz, expr * const * assumptions, double const* weights, double max_weight) { - m_weights.reset(); - if (weights != 0) { - m_weights.append(sz, weights); - } - SASSERT(m_weights.empty() == (m_weights.c_ptr() == 0)); + virtual lbool check_sat(unsigned sz, expr * const * assumptions) { m_solver.pop_to_base_level(); dep2asm_t dep2asm; m_model = 0; @@ -148,10 +139,10 @@ public: r = internalize_assumptions(sz, assumptions, dep2asm); if (r != l_true) return r; - r = m_solver.check(m_asms.size(), m_asms.c_ptr(), m_weights.c_ptr(), max_weight); + r = m_solver.check(m_asms.size(), m_asms.c_ptr()); switch (r) { case l_true: - if (sz > 0 && !weights) { + if (sz > 0) { check_assumptions(dep2asm); } break; @@ -675,18 +666,6 @@ solver* mk_inc_sat_solver(ast_manager& m, params_ref const& p) { } -lbool inc_sat_check_sat(solver& _s, unsigned sz, expr*const* soft, rational const* _weights, rational const& max_weight) { - inc_sat_solver& s = dynamic_cast(_s); - vector weights; - for (unsigned i = 0; _weights && i < sz; ++i) { - weights.push_back(_weights[i].get_double()); - } - params_ref p; - p.set_bool("minimize_core", false); - s.updt_params(p); - return s.check_sat(sz, soft, weights.c_ptr(), max_weight.get_double()); -} - void inc_sat_display(std::ostream& out, solver& _s, unsigned sz, expr*const* soft, rational const* _weights) { inc_sat_solver& s = dynamic_cast(_s); vector weights; diff --git a/src/sat/sat_solver/inc_sat_solver.h b/src/sat/sat_solver/inc_sat_solver.h index 028f71b06..4b0bea50e 100644 --- a/src/sat/sat_solver/inc_sat_solver.h +++ b/src/sat/sat_solver/inc_sat_solver.h @@ -24,7 +24,6 @@ Notes: solver* mk_inc_sat_solver(ast_manager& m, params_ref const& p); -lbool inc_sat_check_sat(solver& s, unsigned sz, expr*const* soft, rational const* weights, rational const& max_weight); void inc_sat_display(std::ostream& out, solver& s, unsigned sz, expr*const* soft, rational const* _weights); From d8e4966a11887bc22d7b84e8da251500860bd174 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 14 Jan 2017 14:18:37 +0000 Subject: [PATCH 28/47] Added win64 build badge --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 204fb371e..e0821ac79 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,9 @@ See the [release notes](RELEASE_NOTES) for notes on various stable releases of Z ## Build status -| Windows | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | -| ------- | ---------- | ---------- | ---------- | --- | -![windows-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge) +| Windows x86 | Windows x64 | Ubuntu x64 | Ubuntu x86 | Debian x64 | OSX | +| ----------- | ----------- | ---------- | ---------- | ---------- | --- | +![win32-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/4/badge) | ![win64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/7/badge) | ![ubuntu-x64-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/3/badge) | ![ubuntu-x86-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/6/badge) | ![debian-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/5/badge) | ![osx-badge](https://cz3.visualstudio.com/_apis/public/build/definitions/bf14bcc7-ebd4-4240-812c-5972fa59e0ad/2/badge) [1]: #building-z3-on-windows-using-visual-studio-command-prompt [2]: #building-z3-using-make-and-gccclang From b30f3a6dbd570988f9cce3d949036ed0562782a3 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 14 Jan 2017 14:56:25 +0000 Subject: [PATCH 29/47] Separated win32/64 builds --- scripts/mk_win_dist.py | 88 +++++++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 27 deletions(-) diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index 92d89480f..9d3abaf2c 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -29,6 +29,9 @@ DOTNET_KEY_FILE=None JAVA_ENABLED=True GIT_HASH=False PYTHON_ENABLED=True +X86ONLY=False +X64ONLY=False +MAKEJOBS=getenv("MAKEJOBS", 24) def set_verbose(flag): global VERBOSE @@ -63,11 +66,13 @@ def display_help(): print(" --nojava do not include Java bindings in the binary distribution files.") print(" --nopython do not include Python bindings in the binary distribution files.") print(" --githash include git hash in the Zip file.") + print(" --x86-only x86 dist only.") + print(" --x64-only x64 dist only.") exit(0) # Parse configuration option for mk_make script def parse_options(): - global FORCE_MK, JAVA_ENABLED, GIT_HASH, DOTNET_ENABLED, DOTNET_KEY_FILE, PYTHON_ENABLED + global FORCE_MK, JAVA_ENABLED, GIT_HASH, DOTNET_ENABLED, DOTNET_KEY_FILE, PYTHON_ENABLED, X86ONLY, X64ONLY path = BUILD_DIR options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:hsf', ['build=', 'help', @@ -77,7 +82,9 @@ def parse_options(): 'nodotnet', 'dotnet-key=', 'githash', - 'nopython' + 'nopython', + 'x86-only', + 'x64-only' ]) for opt, arg in options: if opt in ('-b', '--build'): @@ -100,6 +107,10 @@ def parse_options(): JAVA_ENABLED = False elif opt == '--githash': GIT_HASH = True + elif opt == '--x86-only' and not X64ONLY: + X86ONLY = True + elif opt == '--x64-only' and not X86ONLY: + X64ONLY = True else: raise MKException("Invalid command line option '%s'" % opt) set_build_dir(path) @@ -111,7 +122,8 @@ def check_build_dir(path): # 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", os.path.join('scripts', 'mk_make.py'), "--parallel=24", "-b", path] + parallel = '--parallel=' + MAKEJOBS + opts = ["python", os.path.join('scripts', 'mk_make.py'), parallel, "-b", path] if DOTNET_ENABLED: opts.append('--dotnet') if not DOTNET_KEY_FILE is None: @@ -160,7 +172,7 @@ def exec_cmds(cmds): return res # Compile Z3 (if x64 == True, then it builds it in x64 mode). -def mk_z3_core(x64): +def mk_z3(x64): cmds = [] if x64: cmds.append('call "%VCINSTALLDIR%vcvarsall.bat" amd64') @@ -172,9 +184,9 @@ def mk_z3_core(x64): if exec_cmds(cmds) != 0: raise MKException("Failed to make z3, x64: %s" % x64) -def mk_z3(): - mk_z3_core(False) - mk_z3_core(True) +def mk_z3s(): + mk_z3(False) + mk_z3(True) def get_z3_name(x64): major, minor, build, revision = get_version() @@ -187,7 +199,7 @@ def get_z3_name(x64): else: return 'z3-%s.%s.%s-%s-win' % (major, minor, build, platform) -def mk_dist_dir_core(x64): +def mk_dist_dir(x64): if x64: platform = "x64" build_path = BUILD_X64_DIR @@ -204,14 +216,14 @@ def mk_dist_dir_core(x64): if is_verbose(): print("Generated %s distribution folder at '%s'" % (platform, dist_path)) -def mk_dist_dir(): - mk_dist_dir_core(False) - mk_dist_dir_core(True) +def mk_dist_dirs(): + mk_dist_dir(False) + mk_dist_dir(True) def get_dist_path(x64): return get_z3_name(x64) -def mk_zip_core(x64): +def mk_zip(x64): dist_path = get_dist_path(x64) old = os.getcwd() try: @@ -228,7 +240,7 @@ def mk_zip_core(x64): os.chdir(old) # Create a zip file for each platform -def mk_zip(): +def mk_zips(): mk_zip_core(False) mk_zip_core(True) @@ -238,7 +250,7 @@ VS_RUNTIME_PATS = [re.compile('vcomp.*\.dll'), re.compile('msvcr.*\.dll')] # Copy Visual Studio Runtime libraries -def cp_vs_runtime_core(x64): +def cp_vs_runtime(x64): if x64: platform = "x64" @@ -262,27 +274,49 @@ def cp_vs_runtime_core(x64): if is_verbose(): print("Copied '%s' to '%s'" % (f, bin_dist_path)) -def cp_vs_runtime(): - cp_vs_runtime_core(True) - cp_vs_runtime_core(False) +def cp_vs_runtimes(): + cp_vs_runtime(True) + cp_vs_runtime(False) -def cp_license(): - 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))) +def cp_license(x64): + shutil.copy("LICENSE.txt", os.path.join(DIST_DIR, get_dist_path(x64))) + +def cp_licenses(): + cp_license(True) + cp_license(False) # Entry point def main(): if os.name != 'nt': raise MKException("This script is for Windows only") + parse_options() check_vc_cmd_prompt() - mk_build_dirs() - mk_z3() - init_project_def() - mk_dist_dir() - cp_license() - cp_vs_runtime() - mk_zip() + + if X86ONLY: + mk_build_dir(BUILD_X86_DIR, False) + mk_z3(False) + init_project_def() + mk_dist_dir(False) + cp_license(False) + cp_vs_runtime(False) + mk_zip(False) + elif X64ONLY: + mk_build_dir(BUILD_X64_DIR, True) + mk_z3(True) + init_project_def() + mk_dist_dir(True) + cp_license(True) + cp_vs_runtime(True) + mk_zip(True) + else: + mk_build_dirs() + mk_z3s() + init_project_def() + mk_dist_dirs() + cp_licenses() + cp_vs_runtime() + mk_zip() main() From 340ba7780e012b45b4c5ce3be6077495f3591db5 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Sat, 14 Jan 2017 18:57:10 +0000 Subject: [PATCH 30/47] Added MAKEJOBS env var to mk_unix_dist.py --- scripts/mk_unix_dist.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/mk_unix_dist.py b/scripts/mk_unix_dist.py index 527797e66..488bc4364 100644 --- a/scripts/mk_unix_dist.py +++ b/scripts/mk_unix_dist.py @@ -27,6 +27,7 @@ DOTNET_KEY_FILE=None JAVA_ENABLED=True GIT_HASH=False PYTHON_ENABLED=True +MAKEJOBS=getenv("MAKEJOBS", '8') def set_verbose(flag): global VERBOSE @@ -139,7 +140,7 @@ class cd: def mk_z3(): with cd(BUILD_DIR): try: - return subprocess.call(['make', '-j', '8']) + return subprocess.call(['make', '-j', MAKEJOBS]) except: return 1 From 7df803c131a1acaa1f3138aa2af8006c712f48ad Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 15 Jan 2017 11:52:48 -0800 Subject: [PATCH 31/47] Fix unsound handling of upper bounds in wmax, thanks to Patrick Trentin for report and careful repros #847 Signed-off-by: Nikolaj Bjorner --- src/opt/maxres.cpp | 38 +++++++++++++++++++------------------- src/opt/wmax.cpp | 8 +++++--- src/sat/sat_solver.cpp | 37 +++++++++++++++++-------------------- src/sat/sat_solver.h | 6 ++---- src/smt/theory_wmaxsat.cpp | 2 +- 5 files changed, 44 insertions(+), 47 deletions(-) diff --git a/src/opt/maxres.cpp b/src/opt/maxres.cpp index 83f0849b2..7abbd48ee 100644 --- a/src/opt/maxres.cpp +++ b/src/opt/maxres.cpp @@ -93,7 +93,7 @@ private: mss m_mss; expr_ref_vector m_trail; strategy_t m_st; - rational m_max_upper; + rational m_max_upper; model_ref m_csmodel; unsigned m_correction_set_size; bool m_found_feasible_optimum; @@ -109,6 +109,7 @@ private: bool m_pivot_on_cs; // prefer smaller correction set to core. bool m_dump_benchmarks; // display benchmarks (into wcnf format) + std::string m_trace_id; typedef ptr_vector exprs; @@ -150,9 +151,7 @@ public: return is_uninterp_const(l) || (m.is_not(l, l) && is_uninterp_const(l)); - } - - + } void add_soft(expr* e, rational const& w) { TRACE("opt", tout << mk_pp(e, m) << " |-> " << w << "\n";); @@ -290,7 +289,7 @@ public: index = next_index(asms, index); } first = false; - IF_VERBOSE(3, verbose_stream() << "weight: " << get_weight(asms[0].get()) << " " << get_weight(asms[index-1].get()) << " num soft: " << index << "\n";); + // IF_VERBOSE(3, verbose_stream() << "weight: " << get_weight(asms[0].get()) << " " << get_weight(asms[index-1].get()) << " num soft: " << index << "\n";); m_last_index = index; is_sat = check_sat(index, asms.c_ptr()); } @@ -490,7 +489,7 @@ public: TRACE("opt", display_vec(tout << "minimized core: ", core);); IF_VERBOSE(10, display_vec(verbose_stream() << "core: ", core);); max_resolve(core, w); - fml = mk_not(m, mk_and(m, m_B.size(), m_B.c_ptr())); + fml = mk_not(m, mk_and(m, core.size(), core.c_ptr())); s().assert_expr(fml); m_lower += w; if (m_st == s_primal_dual) { @@ -530,7 +529,10 @@ public: } lbool minimize_core(exprs& core) { - if (m_c.sat_enabled() || core.empty()) { + if (core.empty()) { + return l_true; + } + if (m_c.sat_enabled()) { return l_true; } m_mus.reset(); @@ -607,8 +609,8 @@ public: // Soundness of this rule can be established using MaxRes // for (unsigned i = 1; i < core.size(); ++i) { - expr* b_i = m_B[i-1].get(); - expr* b_i1 = m_B[i].get(); + expr* b_i = core[i-1]; + expr* b_i1 = core[i]; if (i == 1) { d = to_app(b_i); } @@ -658,8 +660,8 @@ public: // d_i => d_{i-1} or b_{i-1} // for (unsigned i = 1; i < cs.size(); ++i) { - expr* b_i = m_B[i-1].get(); - expr* b_i1 = m_B[i].get(); + expr* b_i = cs[i - 1]; + expr* b_i1 = cs[i]; cls = m.mk_or(b_i, d); if (i > 2) { d = mk_fresh_bool("d"); @@ -680,10 +682,11 @@ public: s().assert_expr(fml); m_defs.push_back(fml); new_assumption(asum, w); + fml = m.mk_and(b_i1, cls); update_model(asum, fml); } - fml = m.mk_or(m_B.size(), m_B.c_ptr()); + fml = m.mk_or(cs.size(), cs.c_ptr()); s().assert_expr(fml); } @@ -739,7 +742,7 @@ public: nsoft.push_back(mk_not(m, m_soft[i])); } fml = u.mk_lt(nsoft.size(), m_weights.c_ptr(), nsoft.c_ptr(), m_upper); - s().assert_expr(fml); + s().assert_expr(fml); } bool is_true(model* mdl, expr* e) { @@ -757,10 +760,9 @@ public: } bool is_true(expr_ref_vector const& es) { - for (unsigned i = 0; i < es.size(); ++i) { - if (!is_true(es[i])) return false; - } - return true; + unsigned i = 0; + for (; i < es.size() && is_true(es[i]); ++i) { } + return i == es.size(); } void remove_soft(exprs const& core, expr_ref_vector& asms) { @@ -780,7 +782,6 @@ public: virtual void updt_params(params_ref& p) { maxsmt_solver_base::updt_params(p); opt_params _p(p); - m_hill_climb = _p.maxres_hill_climb(); m_add_upper_bound_block = _p.maxres_add_upper_bound_block(); m_max_num_cores = _p.maxres_max_num_cores(); @@ -858,7 +859,6 @@ public: IF_VERBOSE(0, verbose_stream() << "assignment is infeasible\n";); } } - }; opt::maxsmt_solver_base* opt::mk_maxres( diff --git a/src/opt/wmax.cpp b/src/opt/wmax.cpp index 228e14cd6..690e2000b 100644 --- a/src/opt/wmax.cpp +++ b/src/opt/wmax.cpp @@ -62,20 +62,21 @@ namespace opt { } m_upper = m_lower; bool was_sat = false; - expr_ref_vector disj(m), asms(m); + expr_ref_vector asms(m); vector cores; obj_map::iterator it = soft.begin(), end = soft.end(); for (; it != end; ++it) { expr* c = assert_weighted(wth(), it->m_key, it->m_value); if (!is_true(it->m_key)) { - disj.push_back(m.mk_not(c)); m_upper += it->m_value; } } wth().init_min_cost(m_upper - m_lower); - s().assert_expr(mk_or(disj)); trace_bounds("wmax"); + TRACE("opt", + s().display(tout); tout << "\n"; + tout << "lower: " << m_lower << " upper: " << m_upper << "\n";); while (!m.canceled() && m_lower < m_upper) { //mk_assumptions(asms); //is_sat = s().preferred_sat(asms, cores); @@ -84,6 +85,7 @@ namespace opt { is_sat = l_undef; } if (is_sat == l_false) { + TRACE("opt", tout << "Unsat\n";); break; } if (is_sat == l_true) { diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index 1ed343efa..eec94879a 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -211,7 +211,7 @@ namespace sat { if (propagate_bin_clause(l1, l2)) { if (scope_lvl() == 0) return; - if (!learned) + if (!learned) m_clauses_to_reinit.push_back(clause_wrapper(l1, l2)); } m_stats.m_mk_bin_clause++; @@ -234,19 +234,18 @@ namespace sat { } void solver::push_reinit_stack(clause & c) { + TRACE("sat_reinit", tout << "adding to reinit stack: " << c << "\n";); m_clauses_to_reinit.push_back(clause_wrapper(c)); - c.set_reinit_stack(true); + c.set_reinit_stack(true); } + clause * solver::mk_ter_clause(literal * lits, bool learned) { m_stats.m_mk_ter_clause++; clause * r = m_cls_allocator.mk_clause(3, lits, learned); - bool reinit; - attach_ter_clause(*r, reinit); - if (!learned && reinit) { - TRACE("sat_reinit", tout << "adding to reinit stack: " << *r << "\n";); - push_reinit_stack(*r); - } + bool reinit = attach_ter_clause(*r); + if (reinit && !learned) push_reinit_stack(*r); + if (learned) m_learned.push_back(r); else @@ -254,8 +253,8 @@ namespace sat { return r; } - void solver::attach_ter_clause(clause & c, bool & reinit) { - reinit = false; + bool solver::attach_ter_clause(clause & c) { + bool reinit = false; m_watches[(~c[0]).index()].push_back(watched(c[1], c[2])); m_watches[(~c[1]).index()].push_back(watched(c[0], c[2])); m_watches[(~c[2]).index()].push_back(watched(c[0], c[1])); @@ -276,18 +275,15 @@ namespace sat { reinit = true; } } + return reinit; } clause * solver::mk_nary_clause(unsigned num_lits, literal * lits, bool learned) { m_stats.m_mk_clause++; clause * r = m_cls_allocator.mk_clause(num_lits, lits, learned); SASSERT(!learned || r->is_learned()); - bool reinit; - attach_nary_clause(*r, reinit); - if (!learned && reinit) { - TRACE("sat_reinit", tout << "adding to reinit stack: " << *r << "\n";); - push_reinit_stack(*r); - } + bool reinit = attach_nary_clause(*r); + if (reinit && !learned) push_reinit_stack(*r); if (learned) m_learned.push_back(r); else @@ -295,8 +291,8 @@ namespace sat { return r; } - void solver::attach_nary_clause(clause & c, bool & reinit) { - reinit = false; + bool solver::attach_nary_clause(clause & c) { + bool reinit = false; clause_offset cls_off = m_cls_allocator.get_offset(&c); if (scope_lvl() > 0) { if (c.is_learned()) { @@ -325,15 +321,16 @@ namespace sat { literal block_lit = c[some_idx]; m_watches[(~c[0]).index()].push_back(watched(block_lit, cls_off)); m_watches[(~c[1]).index()].push_back(watched(block_lit, cls_off)); + return reinit; } void solver::attach_clause(clause & c, bool & reinit) { SASSERT(c.size() > 2); reinit = false; if (c.size() == 3) - attach_ter_clause(c, reinit); + reinit = attach_ter_clause(c); else - attach_nary_clause(c, reinit); + reinit = attach_nary_clause(c); } /** diff --git a/src/sat/sat_solver.h b/src/sat/sat_solver.h index d89afd898..f28d0aa5b 100644 --- a/src/sat/sat_solver.h +++ b/src/sat/sat_solver.h @@ -184,11 +184,9 @@ namespace sat { void mk_bin_clause(literal l1, literal l2, bool learned); bool propagate_bin_clause(literal l1, literal l2); clause * mk_ter_clause(literal * lits, bool learned); - void attach_ter_clause(clause & c, bool & reinit); - void attach_ter_clause(clause & c) { bool reinit; attach_ter_clause(c, reinit); } + bool attach_ter_clause(clause & c); clause * mk_nary_clause(unsigned num_lits, literal * lits, bool learned); - void attach_nary_clause(clause & c, bool & reinit); - void attach_nary_clause(clause & c) { bool reinit; attach_nary_clause(c, reinit); } + bool attach_nary_clause(clause & c); void attach_clause(clause & c, bool & reinit); void attach_clause(clause & c) { bool reinit; attach_clause(c, reinit); } unsigned select_watch_lit(clause const & cls, unsigned starting_at) const; diff --git a/src/smt/theory_wmaxsat.cpp b/src/smt/theory_wmaxsat.cpp index e396b67cc..3f153f500 100644 --- a/src/smt/theory_wmaxsat.cpp +++ b/src/smt/theory_wmaxsat.cpp @@ -180,7 +180,7 @@ namespace smt { final_check_status theory_wmaxsat::final_check_eh() { if (m_normalize) normalize(); - // std::cout << "cost: " << m_zcost << " min cost: " << m_zmin_cost << "\n"; + TRACE("opt", tout << "cost: " << m_zcost << " min cost: " << m_zmin_cost << "\n";); return FC_DONE; } From dd0d3d4510694132051801f05a5e3627406ba3ef Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 15 Jan 2017 11:59:09 -0800 Subject: [PATCH 32/47] use stirngs for env variables Signed-off-by: Nikolaj Bjorner --- scripts/mk_win_dist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index 9d3abaf2c..aed64d40e 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -31,7 +31,7 @@ GIT_HASH=False PYTHON_ENABLED=True X86ONLY=False X64ONLY=False -MAKEJOBS=getenv("MAKEJOBS", 24) +MAKEJOBS=getenv("MAKEJOBS", "24") def set_verbose(flag): global VERBOSE From 24eae3f6e0ad81c843d2de242b85002a8fe9314c Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 15 Jan 2017 12:06:56 -0800 Subject: [PATCH 33/47] fix crash with unary xor #870 Signed-off-by: Nikolaj Bjorner --- src/ast/rewriter/bool_rewriter.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ast/rewriter/bool_rewriter.cpp b/src/ast/rewriter/bool_rewriter.cpp index 05f47ada7..f6597fbc5 100644 --- a/src/ast/rewriter/bool_rewriter.cpp +++ b/src/ast/rewriter/bool_rewriter.cpp @@ -59,9 +59,12 @@ br_status bool_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * co mk_implies(args[0], args[1], result); return BR_DONE; case OP_XOR: - SASSERT(num_args == 2); - mk_xor(args[0], args[1], result); - return BR_DONE; + switch (num_args) { + case 0: return BR_FAILED; + case 1: result = args[0]; return BR_DONE; + case 2: mk_xor(args[0], args[1], result); return BR_DONE; + default: UNREACHABLE(); return BR_FAILED; + } default: return BR_FAILED; } From c4c9de08383bbe55d0f1d43e6f6c511fb43adc8d Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 15 Jan 2017 20:09:27 -0800 Subject: [PATCH 34/47] fix memory leaks from cancellations Signed-off-by: Nikolaj Bjorner --- src/muz/pdr/pdr_context.cpp | 47 ++++++++++++++++++++++---------- src/muz/pdr/pdr_context.h | 6 ++-- src/muz/pdr/pdr_dl_interface.cpp | 6 +--- src/smt/asserted_formulas.cpp | 4 +-- 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/muz/pdr/pdr_context.cpp b/src/muz/pdr/pdr_context.cpp index 32f8e1ef1..587488fc9 100644 --- a/src/muz/pdr/pdr_context.cpp +++ b/src/muz/pdr/pdr_context.cpp @@ -575,7 +575,7 @@ namespace pdr { // Predicates that are variable representatives. Other predicates at // positions the variables occur are made equivalent with these. expr_ref_vector conj(m); - app_ref_vector& var_reprs = *(alloc(app_ref_vector, m)); + app_ref_vector var_reprs(m); ptr_vector aux_vars; unsigned ut_size = rule.get_uninterpreted_tail_size(); @@ -584,8 +584,9 @@ namespace pdr { init_atom(pts, rule.get_head(), var_reprs, conj, UINT_MAX); for (unsigned i = 0; i < ut_size; ++i) { if (rule.is_neg_tail(i)) { - dealloc(&var_reprs); - throw default_exception("PDR does not support negated predicates in rule tails"); + char const* msg = "PDR does not supported negated predicates in rule tails"; + IF_VERBOSE(0, verbose_stream() << msg << "\n";); + throw default_exception(msg); } init_atom(pts, rule.get_tail(i), var_reprs, conj, i); } @@ -600,14 +601,14 @@ namespace pdr { flatten_and(tail); for (unsigned i = 0; i < tail.size(); ++i) { expr_ref tmp(m); - var_subst(m, false)(tail[i].get(), var_reprs.size(), (expr*const*)var_reprs.c_ptr(), tmp); + var_subst vs(m, false); + vs(tail[i].get(), var_reprs.size(), (expr*const*)var_reprs.c_ptr(), tmp); conj.push_back(tmp); TRACE("pdr", tout << mk_pp(tail[i].get(), m) << "\n" << mk_pp(tmp, m) << "\n";); if (!is_ground(tmp)) { std::stringstream msg; msg << "PDR cannot solve non-ground tails: " << tmp; IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";); - dealloc(&var_reprs); throw default_exception(msg.str()); } } @@ -631,7 +632,7 @@ namespace pdr { m_rule2transition.insert(&rule, fml.get()); rules.push_back(&rule); } - m_rule2inst.insert(&rule, &var_reprs); + m_rule2inst.insert(&rule, alloc(app_ref_vector, var_reprs)); m_rule2vars.insert(&rule, aux_vars); TRACE("pdr", tout << rule.get_decl()->get_name() << "\n"; @@ -1468,13 +1469,20 @@ namespace pdr { reset(); } - void context::reset() { - TRACE("pdr", tout << "\n";); - decl2rel::iterator it = m_rels.begin(), end = m_rels.end(); + void context::reset(decl2rel& rels) { + decl2rel::iterator it = rels.begin(), end = rels.end(); for (; it != end; ++it) { dealloc(it->m_value); } - m_rels.reset(); + rels.reset(); + } + + void context::reset(bool full) { + TRACE("pdr", tout << "reset\n";); + reset(m_rels); + if (full) { + reset(m_rels_tmp); + } m_search.reset(); m_query = 0; m_last_result = l_undef; @@ -1496,6 +1504,7 @@ namespace pdr { e->get_data().m_value->add_rule(pred_rules[i]); } } + TRACE("pdr", tout << "adding rules\n";); datalog::rule_set::iterator rit = rules.begin(), rend = rules.end(); for (; rit != rend; ++rit) { datalog::rule* r = *rit; @@ -1510,6 +1519,7 @@ namespace pdr { } } // Initialize use list dependencies + TRACE("pdr", tout << "initialize use list dependencies\n";); decl2rel::iterator it = rels.begin(), end = rels.end(); for (; it != end; ++it) { func_decl* pred = it->m_key; @@ -1523,9 +1533,11 @@ namespace pdr { } } + TRACE("pdr", tout << "initialize predicate transformers\n";); // Initialize the predicate transformers. it = rels.begin(), end = rels.end(); for (; it != end; ++it) { + SASSERT(it->m_value); pred_transformer& rel = *it->m_value; rel.initialize(rels); TRACE("pdr", rel.display(tout); ); @@ -1533,21 +1545,24 @@ namespace pdr { } void context::update_rules(datalog::rule_set& rules) { - decl2rel rels; + TRACE("pdr", tout << "update rules\n";); + reset(m_rels_tmp); init_core_generalizers(rules); - init_rules(rules, rels); - decl2rel::iterator it = rels.begin(), end = rels.end(); + init_rules(rules, m_rels_tmp); + decl2rel::iterator it = m_rels_tmp.begin(), end = m_rels_tmp.end(); for (; it != end; ++it) { pred_transformer* pt = 0; if (m_rels.find(it->m_key, pt)) { it->m_value->inherit_properties(*pt); } } - reset(); - it = rels.begin(), end = rels.end(); + reset(false); + it = m_rels_tmp.begin(), end = m_rels_tmp.end(); for (; it != end; ++it) { m_rels.insert(it->m_key, it->m_value); } + m_rels_tmp.reset(); + TRACE("pdr", tout << "done update rules\n";); } unsigned context::get_num_levels(func_decl* p) { @@ -1875,6 +1890,7 @@ namespace pdr { } lbool context::solve() { + TRACE("pdr", tout << "solve\n";); m_last_result = l_undef; try { solve_impl(); @@ -2090,6 +2106,7 @@ namespace pdr { } case l_undef: { TRACE("pdr", tout << "unknown state: " << mk_pp(m_pm.mk_and(cube), m) << "\n";); + IF_VERBOSE(1, verbose_stream() << "unknown state\n";); throw unknown_exception(); } } diff --git a/src/muz/pdr/pdr_context.h b/src/muz/pdr/pdr_context.h index c3567bdd8..a32a65c48 100644 --- a/src/muz/pdr/pdr_context.h +++ b/src/muz/pdr/pdr_context.h @@ -328,6 +328,7 @@ namespace pdr { datalog::context* m_context; manager m_pm; decl2rel m_rels; // Map from relation predicate to fp-operator. + decl2rel m_rels_tmp; func_decl_ref m_query_pred; pred_transformer* m_query; mutable model_search m_search; @@ -370,6 +371,8 @@ namespace pdr { void reset_core_generalizers(); + void reset(decl2rel& rels); + void validate(); void validate_proof(); void validate_search(); @@ -410,8 +413,7 @@ namespace pdr { lbool solve(); - - void reset(); + void reset(bool full = true); void set_query(func_decl* q) { m_query_pred = q; } diff --git a/src/muz/pdr/pdr_dl_interface.cpp b/src/muz/pdr/pdr_dl_interface.cpp index 761b730ce..5f4a200fc 100644 --- a/src/muz/pdr/pdr_dl_interface.cpp +++ b/src/muz/pdr/pdr_dl_interface.cpp @@ -19,12 +19,8 @@ Revision History: #include "dl_context.h" #include "dl_mk_coi_filter.h" -#include "dl_mk_interp_tail_simplifier.h" -#include "dl_mk_subsumption_checker.h" -#include "dl_mk_rule_inliner.h" #include "dl_rule.h" #include "dl_rule_transformer.h" -#include "smt2parser.h" #include "pdr_context.h" #include "pdr_dl_interface.h" #include "dl_rule_set.h" @@ -164,7 +160,7 @@ lbool dl_interface::query(expr * query) { m_context->set_proof_converter(m_ctx.get_proof_converter()); m_context->set_model_converter(m_ctx.get_model_converter()); m_context->set_query(query_pred); - m_context->set_axioms(bg_assertion); + m_context->set_axioms(bg_assertion); m_context->update_rules(m_pdr_rules); if (m_pdr_rules.get_rules().empty()) { diff --git a/src/smt/asserted_formulas.cpp b/src/smt/asserted_formulas.cpp index 3c67cadcf..26395f9ab 100644 --- a/src/smt/asserted_formulas.cpp +++ b/src/smt/asserted_formulas.cpp @@ -184,13 +184,13 @@ void asserted_formulas::get_assertions(ptr_vector & result) { } void asserted_formulas::push_scope() { - SASSERT(inconsistent() || m_asserted_qhead == m_asserted_formulas.size()); + SASSERT(inconsistent() || m_asserted_qhead == m_asserted_formulas.size() || m_manager.canceled()); TRACE("asserted_formulas_scopes", tout << "push:\n"; display(tout);); m_scopes.push_back(scope()); m_macro_manager.push_scope(); scope & s = m_scopes.back(); s.m_asserted_formulas_lim = m_asserted_formulas.size(); - SASSERT(inconsistent() || s.m_asserted_formulas_lim == m_asserted_qhead); + SASSERT(inconsistent() || s.m_asserted_formulas_lim == m_asserted_qhead || m_manager.canceled()); s.m_inconsistent_old = m_inconsistent; m_defined_names.push(); m_bv_sharing.push_scope(); From dc543a7ee727b112d0dec16cff05b446396cec13 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Sun, 15 Jan 2017 21:13:22 -0800 Subject: [PATCH 35/47] update macro_util logging to uniform format Signed-off-by: Nikolaj Bjorner --- src/api/api_datalog.cpp | 2 +- src/ast/macros/macro_util.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/api/api_datalog.cpp b/src/api/api_datalog.cpp index cc512c08e..8843256c6 100644 --- a/src/api/api_datalog.cpp +++ b/src/api/api_datalog.cpp @@ -290,8 +290,8 @@ extern "C" { r = to_fixedpoint_ref(d)->ctx().query(to_expr(q)); } catch (z3_exception& ex) { - mk_c(c)->handle_exception(ex); r = l_undef; + mk_c(c)->handle_exception(ex); } to_fixedpoint_ref(d)->ctx().cleanup(); } diff --git a/src/ast/macros/macro_util.cpp b/src/ast/macros/macro_util.cpp index 027cce09d..97b44d4cd 100644 --- a/src/ast/macros/macro_util.cpp +++ b/src/ast/macros/macro_util.cpp @@ -466,7 +466,7 @@ void macro_util::normalize_expr(app * head, expr * t, expr_ref & norm_t) const { if (v->get_idx() > max_var_idx) max_var_idx = v->get_idx(); } - TRACE("normalize_expr_bug", + TRACE("macro_util", tout << "head: " << mk_pp(head, m_manager) << "\n"; tout << "applying substitution to:\n" << mk_bounded_pp(t, m_manager) << "\n";); for (unsigned i = 0; i < num_args; i++) { @@ -489,7 +489,7 @@ void macro_util::normalize_expr(app * head, expr * t, expr_ref & norm_t) const { if (changed) { // REMARK: t may have nested quantifiers... So, I must use the std order for variable substitution. var_subst subst(m_manager, true); - TRACE("macro_util_bug", + TRACE("macro_util", tout << "head: " << mk_pp(head, m_manager) << "\n"; tout << "applying substitution to:\n" << mk_ll_pp(t, m_manager) << "\nsubstitution:\n"; for (unsigned i = 0; i < var_mapping.size(); i++) { @@ -604,12 +604,12 @@ void hint_to_macro_head(ast_manager & m, app * head, unsigned num_decls, app_ref is_hint_head(head, vars) must also return true */ bool macro_util::is_poly_hint(expr * n, app * head, expr * exception) { - TRACE("macro_util_hint", tout << "is_poly_hint n:\n" << mk_pp(n, m_manager) << "\nhead:\n" << mk_pp(head, m_manager) << "\nexception:\n"; + TRACE("macro_util", tout << "is_poly_hint n:\n" << mk_pp(n, m_manager) << "\nhead:\n" << mk_pp(head, m_manager) << "\nexception:\n"; if (exception) tout << mk_pp(exception, m_manager); else tout << ""; tout << "\n";); ptr_buffer vars; if (!is_hint_head(head, vars)) { - TRACE("macro_util_hint", tout << "failed because head is not hint head\n";); + TRACE("macro_util", tout << "failed because head is not hint head\n";); return false; } func_decl * f = head->get_decl(); @@ -626,11 +626,11 @@ bool macro_util::is_poly_hint(expr * n, app * head, expr * exception) { for (unsigned i = 0; i < num_args; i++) { expr * arg = args[i]; if (arg != exception && (occurs(f, arg) || !vars_of_is_subset(arg, vars))) { - TRACE("macro_util_hint", tout << "failed because of:\n" << mk_pp(arg, m_manager) << "\n";); + TRACE("macro_util", tout << "failed because of:\n" << mk_pp(arg, m_manager) << "\n";); return false; } } - TRACE("macro_util_hint", tout << "succeeded\n";); + TRACE("macro_util", tout << "succeeded\n";); return true; } @@ -831,7 +831,7 @@ void macro_util::collect_arith_macro_candidates(expr * lhs, expr * rhs, expr * a } void macro_util::collect_arith_macro_candidates(expr * atom, unsigned num_decls, macro_candidates & r) { - TRACE("macro_util_hint", tout << "collect_arith_macro_candidates:\n" << mk_pp(atom, m_manager) << "\n";); + TRACE("macro_util", tout << "collect_arith_macro_candidates:\n" << mk_pp(atom, m_manager) << "\n";); if (!m_manager.is_eq(atom) && !is_le_ge(atom)) return; expr * lhs = to_app(atom)->get_arg(0); From 24e4f19d76c17574bb6c9d1d64b22f6dd316978e Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 16 Jan 2017 14:08:21 +0000 Subject: [PATCH 36/47] build fix --- scripts/mk_win_dist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index 9d3abaf2c..0e7fab490 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -315,7 +315,7 @@ def main(): init_project_def() mk_dist_dirs() cp_licenses() - cp_vs_runtime() + cp_vs_runtimes() mk_zip() main() From 00a50eea7f439fad4ba8bb981eedf15e076bfb41 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 16 Jan 2017 15:05:58 +0000 Subject: [PATCH 37/47] Added (include ...) SMT2 command. --- src/shell/smtlib_frontend.cpp | 2 ++ src/smt/smt2_extra_cmds.cpp | 47 +++++++++++++++++++++++++++++++++++ src/smt/smt2_extra_cmds.h | 26 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 src/smt/smt2_extra_cmds.cpp create mode 100644 src/smt/smt2_extra_cmds.h diff --git a/src/shell/smtlib_frontend.cpp b/src/shell/smtlib_frontend.cpp index 31c964ae0..c9fa69221 100644 --- a/src/shell/smtlib_frontend.cpp +++ b/src/shell/smtlib_frontend.cpp @@ -29,6 +29,7 @@ Revision History: #include"opt_cmds.h" #include"polynomial_cmds.h" #include"subpaving_cmds.h" +#include"smt2_extra_cmds.h" #include"smt_strategic_solver.h" #include"smt_solver.h" @@ -113,6 +114,7 @@ unsigned read_smtlib2_commands(char const * file_name) { install_polynomial_cmds(ctx); install_subpaving_cmds(ctx); install_opt_cmds(ctx); + install_smt2_extra_cmds(ctx); g_cmd_context = &ctx; signal(SIGINT, on_ctrl_c); diff --git a/src/smt/smt2_extra_cmds.cpp b/src/smt/smt2_extra_cmds.cpp new file mode 100644 index 000000000..866a1178e --- /dev/null +++ b/src/smt/smt2_extra_cmds.cpp @@ -0,0 +1,47 @@ +/*++ +Copyright (c) 2011 Microsoft Corporation + +Module Name: + + smt2_extra_cmds.cpp + +Abstract: + + Additional SMT-specific commands. + +Author: + + Christoph (cwinter) 2017-01-16 + +Notes: + +--*/ +#include"cmd_context.h" +#include"smt2parser.h" +#include"smt2_extra_cmds.h" + +class include_cmd : public cmd { + char const * m_filename; +public: + include_cmd() : cmd("include"), m_filename(0) {} + virtual char const * get_usage() const { return ""; } + virtual char const * get_descr(cmd_context & ctx) const { return "include a file"; } + virtual unsigned get_arity() const { return 1; } + virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_STRING; } + virtual void set_next_arg(cmd_context & ctx, char const * val) { m_filename = val; } + virtual void failure_cleanup(cmd_context & ctx) {} + virtual void execute(cmd_context & ctx) { + std::ifstream is(m_filename); + if (is.bad() || is.fail()) + throw cmd_exception(std::string("failed to open file '") + m_filename + "'"); + parse_smt2_commands(ctx, is, false); + is.close(); + } + virtual void prepare(cmd_context & ctx) { reset(ctx); } + virtual void reset(cmd_context & ctx) { m_filename = 0; } + virtual void finalize(cmd_context & ctx) { reset(ctx); } +}; + +void install_smt2_extra_cmds(cmd_context & ctx) { + ctx.insert(alloc(include_cmd)); +} \ No newline at end of file diff --git a/src/smt/smt2_extra_cmds.h b/src/smt/smt2_extra_cmds.h new file mode 100644 index 000000000..947f5ed7a --- /dev/null +++ b/src/smt/smt2_extra_cmds.h @@ -0,0 +1,26 @@ +/*++ +Copyright (c) 2011 Microsoft Corporation + +Module Name: + + smt2_extra_cmds.h + +Abstract: + + Additional SMT-specific commands. + +Author: + + Christoph (cwinter) 2017-01-16 + +Notes: + +--*/ +#ifndef SMT2_EXTRA_CMDS_H_ +#define SMT2_EXTRA_CMDS_H_ + +class cmd_context; + +void install_smt2_extra_cmds(cmd_context & ctx); + +#endif /* SMT2_EXTRA_CMDS_H_ */ From 090a331d79648b7eb76a49ac1fd22c80a63a19a8 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 9 Jan 2017 14:51:01 +0000 Subject: [PATCH 38/47] Added filenames to error messages for when we have more than one file. --- src/parsers/smt2/smt2parser.cpp | 195 ++++++++++++++++---------------- src/parsers/smt2/smt2parser.h | 2 +- 2 files changed, 101 insertions(+), 96 deletions(-) diff --git a/src/parsers/smt2/smt2parser.cpp b/src/parsers/smt2/smt2parser.cpp index bb0c5bfb9..d2b55af1d 100644 --- a/src/parsers/smt2/smt2parser.cpp +++ b/src/parsers/smt2/smt2parser.cpp @@ -109,7 +109,6 @@ namespace smt2 { typedef std::pair named_expr; named_expr m_last_named_expr; - ast_manager & m() const { return m_ctx.m(); } pdecl_manager & pm() const { return m_ctx.pm(); } sexpr_manager & sm() const { return m_ctx.sm(); } @@ -117,7 +116,7 @@ namespace smt2 { bool m_ignore_user_patterns; bool m_ignore_bad_patterns; bool m_display_error_for_vs; - + bool ignore_user_patterns() const { return m_ignore_user_patterns; } bool ignore_bad_patterns() const { return m_ignore_bad_patterns; } bool use_vs_format() const { return m_display_error_for_vs; } @@ -129,7 +128,7 @@ namespace smt2 { m_decl(d), m_spos(spos) { } }; - + typedef psort_frame sort_frame; enum expr_frame_kind { EF_APP, EF_LET, EF_LET_DECL, EF_QUANT, EF_ATTR_EXPR, EF_PATTERN }; @@ -138,17 +137,17 @@ namespace smt2 { expr_frame_kind m_kind; expr_frame(expr_frame_kind k):m_kind(k) {} }; - + struct app_frame : public expr_frame { symbol m_f; unsigned m_expr_spos; unsigned m_param_spos; bool m_as_sort; app_frame(symbol const & f, unsigned expr_spos, unsigned param_spos, bool as_sort): - expr_frame(EF_APP), - m_f(f), - m_expr_spos(expr_spos), - m_param_spos(param_spos), + expr_frame(EF_APP), + m_f(f), + m_expr_spos(expr_spos), + m_param_spos(param_spos), m_as_sort(as_sort) {} }; @@ -163,8 +162,8 @@ namespace smt2 { unsigned m_sort_spos; unsigned m_expr_spos; quant_frame(bool forall, unsigned pat_spos, unsigned nopat_spos, unsigned sym_spos, unsigned sort_spos, unsigned expr_spos): - expr_frame(EF_QUANT), m_forall(forall), m_weight(1), - m_pat_spos(pat_spos), m_nopat_spos(nopat_spos), + expr_frame(EF_QUANT), m_forall(forall), m_weight(1), + m_pat_spos(pat_spos), m_nopat_spos(nopat_spos), m_sym_spos(sym_spos), m_sort_spos(sort_spos), m_expr_spos(expr_spos) {} }; @@ -175,7 +174,7 @@ namespace smt2 { unsigned m_expr_spos; let_frame(unsigned sym_spos, unsigned expr_spos):expr_frame(EF_LET), m_in_decls(true), m_sym_spos(sym_spos), m_expr_spos(expr_spos) {} }; - + struct let_decl_frame : public expr_frame { let_decl_frame():expr_frame(EF_LET_DECL) {} }; @@ -186,9 +185,9 @@ namespace smt2 { unsigned m_expr_spos; symbol m_last_symbol; attr_expr_frame(expr_frame * prev, unsigned sym_spos, unsigned expr_spos): - expr_frame(EF_ATTR_EXPR), - m_prev(prev), - m_sym_spos(sym_spos), + expr_frame(EF_ATTR_EXPR), + m_prev(prev), + m_sym_spos(sym_spos), m_expr_spos(expr_spos) {} }; @@ -228,12 +227,12 @@ namespace smt2 { m_expr_stack = alloc(expr_ref_vector, m()); return *(m_expr_stack.get()); } - + template static unsigned size(scoped_ptr & v) { return v.get() == 0 ? 0 : v->size(); } - + template static void shrink(scoped_ptr & v, unsigned old_sz) { if (v.get() == 0) { @@ -255,7 +254,7 @@ namespace smt2 { m_nopattern_stack = alloc(expr_ref_vector, m()); return *(m_nopattern_stack.get()); } - + svector & symbol_stack() { return m_symbol_stack; } @@ -328,7 +327,7 @@ namespace smt2 { bool sync_after_error() { while (true) { try { - while (curr_is_rparen()) + while (curr_is_rparen()) next(); if (m_num_open_paren < 0) m_num_open_paren = 0; @@ -337,7 +336,7 @@ namespace smt2 { SASSERT(m_num_open_paren >= 0); while (m_num_open_paren > 0 || !curr_is_lparen()) { TRACE("sync", tout << "sync(): curr: " << curr() << "\n"; - tout << "m_num_open_paren: " << m_num_open_paren << ", line: " << m_scanner.get_line() << ", pos: " + tout << "m_num_open_paren: " << m_num_open_paren << ", line: " << m_scanner.get_line() << ", pos: " << m_scanner.get_pos() << "\n";); if (curr() == scanner::EOF_TOKEN) { return false; @@ -365,7 +364,7 @@ namespace smt2 { } throw parser_exception(msg); } - + symbol const & curr_id() const { return m_scanner.get_id(); } rational curr_numeral() const { return m_scanner.get_number(); } @@ -402,15 +401,20 @@ namespace smt2 { void check_int_or_float(char const * msg) { if (!curr_is_int() && !curr_is_float()) throw parser_exception(msg); } void check_float(char const * msg) { if (!curr_is_float()) throw parser_exception(msg); } + char const * m_current_file; + void set_current_file(char const * s) { m_current_file = s; } + void error(unsigned line, unsigned pos, char const * msg) { m_ctx.set_cancel(false); if (use_vs_format()) { m_ctx.diagnostic_stream() << "Z3(" << line << ", " << pos << "): ERROR: " << msg; if (msg[strlen(msg)-1] != '\n') - m_ctx.diagnostic_stream() << std::endl; + m_ctx.diagnostic_stream() << std::endl; } else { - m_ctx.regular_stream() << "(error \"line " << line << " column " << pos << ": " << escaped(msg, true) << "\")" << std::endl; + m_ctx.regular_stream() << "(error \""; + if (m_current_file) m_ctx.regular_stream() << m_current_file << ": "; + m_ctx.regular_stream()<< "line " << line << " column " << pos << ": " << escaped(msg, true) << "\")" << std::endl; } if (m_ctx.exit_on_error()) { exit(1); @@ -431,7 +435,7 @@ namespace smt2 { m_ctx.regular_stream() << "(error : " << escaped(msg, true) << "\")" << std::endl; } } - + void unknown_sort(symbol id, char const* context = "") { std::string msg = context; if (context[0]) msg += ": "; @@ -444,10 +448,10 @@ namespace smt2 { unsigned num_parens = 0; do { switch (curr()) { - case scanner::LEFT_PAREN: - num_parens++; + case scanner::LEFT_PAREN: + num_parens++; break; - case scanner::RIGHT_PAREN: + case scanner::RIGHT_PAREN: if (num_parens == 0) throw parser_exception("invalid s-expression, unexpected ')'"); num_parens--; @@ -565,7 +569,7 @@ namespace smt2 { else { if (ignore_unknow_sort) return 0; - unknown_sort(id); + unknown_sort(id); UNREACHABLE(); return 0; } @@ -579,7 +583,7 @@ namespace smt2 { check_identifier("invalid indexed sort, symbol expected"); symbol id = curr_id(); psort_decl * d = m_ctx.find_psort_decl(id); - if (d == 0) + if (d == 0) unknown_sort(id); next(); sbuffer args; @@ -604,13 +608,13 @@ namespace smt2 { SASSERT(curr_is_identifier()); symbol id = curr_id(); psort_decl * d = m_ctx.find_psort_decl(id); - if (d == 0) + if (d == 0) unknown_sort(id); next(); void * mem = m_stack.allocate(sizeof(psort_frame)); new (mem) psort_frame(*this, d, psort_stack().size()); } - + void pop_psort_app_frame() { SASSERT(curr_is_rparen()); psort_frame * fr = static_cast(m_stack.top()); @@ -647,7 +651,7 @@ namespace smt2 { else { check_lparen_next("invalid sort, symbol, '_' or '(' expected"); if (!curr_is_identifier()) - throw parser_exception("invalid sort, symbol or '_' expected"); + throw parser_exception("invalid sort, symbol or '_' expected"); if (curr_id_is_underscore()) { psort_stack().push_back(pm().mk_psort_cnst(parse_indexed_sort())); } @@ -665,13 +669,13 @@ namespace smt2 { SASSERT(curr_is_identifier()); symbol id = curr_id(); psort_decl * d = m_ctx.find_psort_decl(id); - if (d == 0) + if (d == 0) unknown_sort(id); next(); void * mem = m_stack.allocate(sizeof(sort_frame)); new (mem) sort_frame(*this, d, sort_stack().size()); } - + void pop_sort_app_frame() { SASSERT(curr_is_rparen()); sort_frame * fr = static_cast(m_stack.top()); @@ -710,8 +714,8 @@ namespace smt2 { } else { check_lparen_next("invalid sort, symbol, '_' or '(' expected"); - if (!curr_is_identifier()) - throw parser_exception(std::string(context) + " invalid sort, symbol or '_' expected"); + if (!curr_is_identifier()) + throw parser_exception(std::string(context) + " invalid sort, symbol or '_' expected"); if (curr_id_is_underscore()) { sort_stack().push_back(parse_indexed_sort()); } @@ -726,7 +730,7 @@ namespace smt2 { } unsigned parse_sorts(char const* context) { - unsigned sz = 0; + unsigned sz = 0; check_lparen_next(context); while (!curr_is_rparen()) { parse_sort(context); @@ -949,7 +953,7 @@ namespace smt2 { } // parse expression state - enum pe_state { + enum pe_state { PES_EXPR, // expecting PES_DECL, // expecting ( ) PES_PATTERN, @@ -1015,7 +1019,7 @@ namespace smt2 { else { // just consume pattern next(); - consume_sexpr(); + consume_sexpr(); } } else if (id == m_nopattern) { @@ -1036,7 +1040,7 @@ namespace smt2 { str << "unknown attribute " << id; warning_msg("%s", str.str().c_str()); next(); - // just consume the + // just consume the consume_sexpr(); } if (curr_is_rparen()) @@ -1051,13 +1055,13 @@ namespace smt2 { switch (fr->m_kind) { case EF_LET: return static_cast(fr)->m_in_decls ? PES_DECL : PES_EXPR; - case EF_ATTR_EXPR: + case EF_ATTR_EXPR: return consume_attributes(static_cast(fr)); default: return PES_EXPR; } } - + void parse_numeral(bool is_int) { SASSERT(!is_int || curr_is_int()); SASSERT(is_int || curr_is_float()); @@ -1095,7 +1099,7 @@ namespace smt2 { expr_stack().push_back(0); // empty pattern return; } - + if (curr_is_lparen()) { // multi-pattern void * mem = m_stack.allocate(sizeof(pattern_frame)); @@ -1185,9 +1189,9 @@ namespace smt2 { SASSERT(curr_id_is_forall() || curr_id_is_exists()); SASSERT(!is_forall || curr_id_is_forall()); SASSERT(is_forall || curr_id_is_exists()); - next(); + next(); void * mem = m_stack.allocate(sizeof(quant_frame)); - new (mem) quant_frame(is_forall, pattern_stack().size(), nopattern_stack().size(), symbol_stack().size(), + new (mem) quant_frame(is_forall, pattern_stack().size(), nopattern_stack().size(), symbol_stack().size(), sort_stack().size(), expr_stack().size()); m_num_expr_frames++; unsigned num_vars = parse_sorted_vars(); @@ -1229,11 +1233,11 @@ namespace smt2 { next(); return r; } - check_lparen_next("invalid (indexed) identifier, '(_' or symbol expected"); + check_lparen_next("invalid (indexed) identifier, '(_' or symbol expected"); return parse_indexed_identifier_core(); } - // parse: + // parse: // 'as' ')' // '_' + ')' // 'as' (|)+ ')' ')' @@ -1255,7 +1259,7 @@ namespace smt2 { } } - // parse: + // parse: // // '(' 'as' ')' // '(' '_' + ')' @@ -1281,8 +1285,8 @@ namespace smt2 { throw parser_exception(msg.c_str()); } - rational m_last_bv_numeral; // for bv, bvbin, bvhex - + rational m_last_bv_numeral; // for bv, bvbin, bvhex + // return true if *s == [0-9]+ bool is_bv_decimal(char const * s) { TRACE("is_bv_num", tout << "is_bv_decimal: " << s << "\n";); @@ -1321,7 +1325,7 @@ namespace smt2 { return false; return true; } - + // return true if *s == hex[0-9,a-f,A-F]+ bool is_bv_hex(char const * s) { SASSERT(*s == 'h'); @@ -1329,7 +1333,7 @@ namespace smt2 { if (*s != 'e') return false; ++s; if (*s != 'x') return false; - ++s; + ++s; rational & n = m_last_bv_numeral; unsigned i = 0; n = rational(0); @@ -1340,7 +1344,7 @@ namespace smt2 { } else if ('a' <= *s && *s <= 'f') { n *= rational(16); - n += rational(10 + (*s - 'a')); + n += rational(10 + (*s - 'a')); } else if ('A' <= *s && *s <= 'F') { n *= rational(16); @@ -1357,11 +1361,11 @@ namespace smt2 { } } - // Return true if + // Return true if // n == bv[0-9]+ OR // n == bvhex[0-9,a-f,A-F]+ OR - // n == bvbin[0-1]+ - // It store the bit-vector value in m_last_bv_numeral + // n == bvbin[0-1]+ + // It store the bit-vector value in m_last_bv_numeral bool is_bv_num(symbol const & n) { char const * s = n.bare_str(); if (*s != 'b') return false; @@ -1405,7 +1409,7 @@ namespace smt2 { } next(); } - + // if has_as == true, then the sort of t must be equal to sort_stack().pop_back() // if that is the case, pop the top of sort_stack() void check_qualifier(expr * t, bool has_as) { @@ -1543,7 +1547,7 @@ namespace smt2 { unsigned num_args = expr_stack().size() - fr->m_expr_spos; unsigned num_indices = m_param_stack.size() - fr->m_param_spos; expr_ref t_ref(m()); - m_ctx.mk_app(fr->m_f, + m_ctx.mk_app(fr->m_f, num_args, expr_stack().c_ptr() + fr->m_expr_spos, num_indices, @@ -1627,7 +1631,7 @@ namespace smt2 { fr->m_qid = symbol(m_scanner.get_line()); if (!m().is_bool(expr_stack().back())) throw parser_exception("quantifier body must be a Boolean expression"); - quantifier * new_q = m().mk_quantifier(fr->m_forall, + quantifier * new_q = m().mk_quantifier(fr->m_forall, num_decls, sort_stack().c_ptr() + fr->m_sort_spos, symbol_stack().c_ptr() + fr->m_sym_spos, @@ -1688,7 +1692,7 @@ namespace smt2 { case EF_APP: pop_app_frame(static_cast(fr)); break; - case EF_LET: + case EF_LET: pop_let_frame(static_cast(fr)); break; case EF_LET_DECL: @@ -1714,7 +1718,7 @@ namespace smt2 { void parse_expr() { m_num_expr_frames = 0; do { - TRACE("parse_expr", tout << "curr(): " << curr() << ", m_num_expr_frames: " << m_num_expr_frames + TRACE("parse_expr", tout << "curr(): " << curr() << ", m_num_expr_frames: " << m_num_expr_frames << ", expr_stack().size(): " << expr_stack().size() << "\n";); if (curr_is_rparen()) { if (m_num_expr_frames == 0) @@ -1798,7 +1802,7 @@ namespace smt2 { SASSERT(curr_is_identifier()); SASSERT(curr_id() == m_declare_sort); next(); - + check_identifier("invalid sort declaration, symbol expected"); symbol id = curr_id(); if (m_ctx.find_psort_decl(id) != 0) @@ -1812,7 +1816,7 @@ namespace smt2 { check_int("invalid sort declaration, arity () or ')' expected"); rational n = curr_numeral(); if (!n.is_unsigned()) - throw parser_exception("invalid sort declaration, arity is too big to fit in an unsigned machine integer"); + throw parser_exception("invalid sort declaration, arity is too big to fit in an unsigned machine integer"); psort_decl * decl = pm().mk_psort_user_decl(n.get_unsigned(), id, 0); m_ctx.insert(decl); next(); @@ -1872,12 +1876,12 @@ namespace smt2 { } void parse_define_fun_rec() { - // ( define-fun-rec hfun_defi ) + // ( define-fun-rec hfun_defi ) SASSERT(curr_is_identifier()); SASSERT(curr_id() == m_define_fun_rec); SASSERT(m_num_bindings == 0); next(); - + expr_ref_vector binding(m()); svector ids; func_decl_ref f(m()); @@ -1890,7 +1894,7 @@ namespace smt2 { } void parse_define_funs_rec() { - // ( define-funs-rec ( hfun_decin+1 ) ( htermin+1 ) ) + // ( define-funs-rec ( hfun_decin+1 ) ( htermin+1 ) ) SASSERT(curr_is_identifier()); SASSERT(curr_id() == m_define_funs_rec); SASSERT(m_num_bindings == 0); @@ -1920,14 +1924,14 @@ namespace smt2 { check_lparen("invalid recursive function definition, '(' expected"); next(); - + parse_rec_fun_decl(f, binding, id); decls.push_back(f); bindings.push_back(binding); ids.push_back(id); check_rparen("invalid recursive function definition, ')' expected"); - next(); + next(); } next(); } @@ -1950,7 +1954,7 @@ namespace smt2 { sort_stack().shrink(sort_spos); expr_stack().shrink(expr_spos); m_env.end_scope(); - m_num_bindings = 0; + m_num_bindings = 0; } void parse_rec_fun_bodies(func_decl_ref_vector const& decls, vector const& bindings, vector >const & ids) { @@ -1963,10 +1967,10 @@ namespace smt2 { } if (i != decls.size()) { - throw parser_exception("the number of declarations does not match number of supplied definitions"); + throw parser_exception("the number of declarations does not match number of supplied definitions"); } check_rparen("invalid recursive function definition, ')' expected"); - next(); + next(); } void parse_rec_fun_body(func_decl* f, expr_ref_vector const& bindings, svector const& ids) { @@ -1980,19 +1984,19 @@ namespace smt2 { for (unsigned i = 0; i < num_vars; ++i) { m_env.insert(ids[i], local(bindings[i], num_vars)); } - parse_expr(); + parse_expr(); body = expr_stack().back(); expr_stack().pop_back(); symbol_stack().shrink(sym_spos); m_env.end_scope(); - m_num_bindings = 0; + m_num_bindings = 0; if (m().get_sort(body) != f->get_range()) { std::ostringstream buffer; buffer << "invalid function definition, sort mismatch. Expcected " - << mk_pp(f->get_range(), m()) << " but function body has sort " + << mk_pp(f->get_range(), m()) << " but function body has sort " << mk_pp(m().get_sort(body), m()); throw parser_exception(buffer.str().c_str()); - } + } m_ctx.insert_rec_fun(f, bindings, ids, body); } @@ -2185,7 +2189,7 @@ namespace smt2 { unsigned spos = expr_stack().size(); check_lparen_next("invalid check-sat-assuming command, '(', expected"); parse_assumptions(); - check_rparen_next("invalid check-sat-assuming command, ')', expected"); + check_rparen_next("invalid check-sat-assuming command, ')', expected"); m_ctx.check_sat(expr_stack().size() - spos, expr_stack().c_ptr() + spos); next(); expr_stack().shrink(spos); @@ -2201,7 +2205,7 @@ namespace smt2 { m_scanner.start_caching(); m_cache_end = 0; m_cached_strings.resize(0); - + check_lparen_next("invalid get-value command, '(' expected"); while (!curr_is_rparen()) { parse_expr(); @@ -2241,7 +2245,7 @@ namespace smt2 { SASSERT(curr_id() == m_reset); next(); check_rparen("invalid reset command, ')' expected"); - m_ctx.reset(); + m_ctx.reset(); reset(); m_ctx.print_success(); next(); @@ -2323,7 +2327,7 @@ namespace smt2 { } next(); } - + void parse_next_cmd_arg() { SASSERT(m_curr_cmd != 0); cmd_arg_kind k = m_curr_cmd->next_arg_kind(m_ctx); @@ -2332,7 +2336,7 @@ namespace smt2 { check_int("invalid command argument, unsigned integer expected"); rational n = curr_numeral(); if (!n.is_unsigned()) - throw parser_exception("invalid command argument, numeral is too big to fit in an unsigned machine integer"); + throw parser_exception("invalid command argument, numeral is too big to fit in an unsigned machine integer"); m_curr_cmd->set_next_arg(m_ctx, n.get_unsigned()); next(); break; @@ -2445,7 +2449,7 @@ namespace smt2 { m_curr_cmd = m_ctx.find_cmd(s); if (m_curr_cmd == 0) { parse_unknown_cmd(); - return; + return; } next(); unsigned arity = m_curr_cmd->get_arity(); @@ -2475,14 +2479,14 @@ namespace smt2 { return; } else { - if (arity != VAR_ARITY && i == arity) + if (arity != VAR_ARITY && i == arity) throw parser_exception("invalid command, too many arguments"); parse_next_cmd_arg(); } i++; } } - + void parse_cmd() { SASSERT(curr_is_lparen()); int line = m_scanner.get_line(); @@ -2531,7 +2535,7 @@ namespace smt2 { return; } if (s == m_declare_datatypes) { - parse_declare_datatypes(); + parse_declare_datatypes(); return; } if (s == m_get_value) { @@ -2558,8 +2562,8 @@ namespace smt2 { } public: - parser(cmd_context & ctx, std::istream & is, bool interactive, params_ref const & p): - m_ctx(ctx), + parser(cmd_context & ctx, std::istream & is, bool interactive, params_ref const & p, char const * filename=0): + m_ctx(ctx), m_params(p), m_scanner(ctx, is, interactive), m_curr(scanner::NULL_TOKEN), @@ -2597,14 +2601,15 @@ namespace smt2 { m_check_sat_assuming("check-sat-assuming"), m_define_fun_rec("define-fun-rec"), m_define_funs_rec("define-funs-rec"), - m_underscore("_"), - m_num_open_paren(0) { + m_underscore("_"), + m_num_open_paren(0), + m_current_file(filename) { // the following assertion does not hold if ctx was already attached to an AST manager before the parser object is created. // SASSERT(!m_ctx.has_manager()); - + updt_params(); } - + ~parser() { reset_stack(); } @@ -2615,7 +2620,7 @@ namespace smt2 { m_ignore_bad_patterns = p.ignore_bad_patterns(); m_display_error_for_vs = p.error_for_visual_studio(); } - + void reset() { reset_stack(); m_num_bindings = 0; @@ -2630,7 +2635,7 @@ namespace smt2 { m_env .reset(); m_sort_id2param_idx .reset(); m_dt_name2idx .reset(); - + m_bv_util = 0; m_arith_util = 0; m_seq_util = 0; @@ -2680,9 +2685,9 @@ namespace smt2 { return !found_errors; } catch (parser_exception & ex) { - if (ex.has_pos()) + if (ex.has_pos()) error(ex.line(), ex.pos(), ex.msg()); - else + else error(ex.msg()); } catch (ast_exception & ex) { @@ -2705,8 +2710,8 @@ namespace smt2 { }; }; -bool parse_smt2_commands(cmd_context & ctx, std::istream & is, bool interactive, params_ref const & ps) { - smt2::parser p(ctx, is, interactive, ps); +bool parse_smt2_commands(cmd_context & ctx, std::istream & is, bool interactive, params_ref const & ps, char const * filename) { + smt2::parser p(ctx, is, interactive, ps, filename); return p(); } diff --git a/src/parsers/smt2/smt2parser.h b/src/parsers/smt2/smt2parser.h index 5b4384917..77fd41d5d 100644 --- a/src/parsers/smt2/smt2parser.h +++ b/src/parsers/smt2/smt2parser.h @@ -21,6 +21,6 @@ Revision History: #include"cmd_context.h" -bool parse_smt2_commands(cmd_context & ctx, std::istream & is, bool interactive = false, params_ref const & p = params_ref()); +bool parse_smt2_commands(cmd_context & ctx, std::istream & is, bool interactive = false, params_ref const & p = params_ref(), char const * filename = 0); #endif From e472a8d4cfe36df6a68d0b4e285e9a3410d6ff8a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 16 Jan 2017 15:46:58 +0000 Subject: [PATCH 39/47] Enabled filenames in error messages during inclusion of files. --- src/smt/smt2_extra_cmds.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/smt/smt2_extra_cmds.cpp b/src/smt/smt2_extra_cmds.cpp index 866a1178e..901810442 100644 --- a/src/smt/smt2_extra_cmds.cpp +++ b/src/smt/smt2_extra_cmds.cpp @@ -34,7 +34,7 @@ public: std::ifstream is(m_filename); if (is.bad() || is.fail()) throw cmd_exception(std::string("failed to open file '") + m_filename + "'"); - parse_smt2_commands(ctx, is, false); + parse_smt2_commands(ctx, is, false, params_ref(), m_filename); is.close(); } virtual void prepare(cmd_context & ctx) { reset(ctx); } From 625681f82f3ac3e86c4fe6755c4939bf477af6f7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Mon, 16 Jan 2017 15:59:16 +0000 Subject: [PATCH 40/47] Updated cmake build --- contrib/cmake/src/smt/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/cmake/src/smt/CMakeLists.txt b/contrib/cmake/src/smt/CMakeLists.txt index 035ac07c9..bd8ad3f31 100644 --- a/contrib/cmake/src/smt/CMakeLists.txt +++ b/contrib/cmake/src/smt/CMakeLists.txt @@ -43,6 +43,7 @@ z3_add_component(smt smt_statistics.cpp smt_theory.cpp smt_value_sort.cpp + smt2_extra_cmds.cpp theory_arith.cpp theory_array_base.cpp theory_array.cpp From 0fae048e3e00f380bea70cb863625097f4854a46 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 17 Jan 2017 12:58:32 +0000 Subject: [PATCH 41/47] Windows build fix. --- scripts/mk_win_dist.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index eb9f707a2..11048650f 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -316,7 +316,7 @@ def main(): mk_dist_dirs() cp_licenses() cp_vs_runtimes() - mk_zip() + mk_zips() main() From 6d34899c463db50cf4248c6e4f2451e6003919e7 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Tue, 17 Jan 2017 15:44:03 +0000 Subject: [PATCH 42/47] Bugfix for macro finder. Fixes #832. --- src/ast/macros/macro_manager.cpp | 18 +++++------ src/ast/macros/macro_util.cpp | 51 ++++++++++++++++---------------- src/ast/macros/macro_util.h | 16 +++++----- 3 files changed, 42 insertions(+), 43 deletions(-) diff --git a/src/ast/macros/macro_manager.cpp b/src/ast/macros/macro_manager.cpp index 75b4e55f4..b17e1ce28 100644 --- a/src/ast/macros/macro_manager.cpp +++ b/src/ast/macros/macro_manager.cpp @@ -106,7 +106,7 @@ bool macro_manager::insert(func_decl * f, quantifier * m, proof * pr) { if (!m_deps.insert(f, s)) { return false; } - + // add macro m_decl2macro.insert(f, m); m_decls.push_back(f); @@ -117,8 +117,8 @@ bool macro_manager::insert(func_decl * f, quantifier * m, proof * pr) { } TRACE("macro_insert", tout << "A macro was successfully created for: " << f->get_name() << "\n";); - - // Nothing's forbidden anymore; if something's bad, we detected it earlier. + + // Nothing's forbidden anymore; if something's bad, we detected it earlier. // mark_forbidden(m->get_expr()); return true; } @@ -144,7 +144,7 @@ namespace macro_manager_ns { \brief Mark all func_decls used in exprs as forbidden. */ void macro_manager::mark_forbidden(unsigned n, expr * const * exprs) { - expr_mark visited; + expr_mark visited; macro_manager_ns::proc p(m_forbidden_set, m_forbidden); for (unsigned i = 0; i < n; i++) for_each_expr(p, visited, exprs[i]); @@ -187,9 +187,9 @@ func_decl * macro_manager::get_macro_interpretation(unsigned i, expr_ref & inter app * head; expr * def; get_head_def(q, f, head, def); - TRACE("macro_bug", + TRACE("macro_bug", tout << f->get_name() << "\n" << mk_pp(head, m_manager) << "\n" << mk_pp(q, m_manager) << "\n";); - m_util.mk_macro_interpretation(head, def, interp); + m_util.mk_macro_interpretation(head, q->get_num_decls(), def, interp); return f; } @@ -237,7 +237,7 @@ void macro_manager::macro_expander::reduce1_quantifier(quantifier * q) { erase_patterns = true; } for (unsigned i = 0; !erase_patterns && i < q->get_num_no_patterns(); i++) { - if (q->get_no_pattern(i) != new_q->get_no_pattern(i)) + if (q->get_no_pattern(i) != new_q->get_no_pattern(i)) erase_patterns = true; } } @@ -254,7 +254,7 @@ bool macro_manager::macro_expander::get_subst(expr * _n, expr_ref & r, proof_ref return false; app * n = to_app(_n); quantifier * q = 0; - func_decl * d = n->get_decl(); + func_decl * d = n->get_decl(); TRACE("macro_manager_bug", tout << "trying to expand:\n" << mk_pp(n, m) << "\nd:\n" << d->get_name() << "\n";); if (m_macro_manager.m_decl2macro.find(d, q)) { TRACE("macro_manager", tout << "expanding: " << mk_pp(n, m) << "\n";); @@ -308,7 +308,7 @@ void macro_manager::expand_macros(expr * n, proof * pr, expr_ref & r, proof_ref if (r.get() == old_n.get()) return; old_n = r; - old_pr = new_pr; + old_pr = new_pr; } } else { diff --git a/src/ast/macros/macro_util.cpp b/src/ast/macros/macro_util.cpp index 97b44d4cd..99732871c 100644 --- a/src/ast/macros/macro_util.cpp +++ b/src/ast/macros/macro_util.cpp @@ -405,7 +405,7 @@ bool macro_util::is_quasi_macro_head(expr * n, unsigned num_decls) const { \brief Convert a quasi-macro head into a macro head, and store the conditions under which it is valid in cond. */ -void macro_util::quasi_macro_head_to_macro_head(app * qhead, unsigned num_decls, app_ref & head, expr_ref & cond) const { +void macro_util::quasi_macro_head_to_macro_head(app * qhead, unsigned & num_decls, app_ref & head, expr_ref & cond) const { unsigned num_args = qhead->get_num_args(); sbuffer found_vars; found_vars.resize(num_decls, false); @@ -431,6 +431,7 @@ void macro_util::quasi_macro_head_to_macro_head(app * qhead, unsigned num_decls, } get_basic_simp()->mk_and(new_conds.size(), new_conds.c_ptr(), cond); head = m_manager.mk_app(qhead->get_decl(), new_args.size(), new_args.c_ptr()); + num_decls = next_var_idx; } /** @@ -440,10 +441,10 @@ void macro_util::quasi_macro_head_to_macro_head(app * qhead, unsigned num_decls, See normalize_expr */ -void macro_util::mk_macro_interpretation(app * head, expr * def, expr_ref & interp) const { +void macro_util::mk_macro_interpretation(app * head, unsigned num_decls, expr * def, expr_ref & interp) const { SASSERT(is_macro_head(head, head->get_num_args())); SASSERT(!occurs(head->get_decl(), def)); - normalize_expr(head, def, interp); + normalize_expr(head, num_decls, def, interp); } /** @@ -456,36 +457,27 @@ void macro_util::mk_macro_interpretation(app * head, expr * def, expr_ref & inte f(x_1, x_2) --> f(x_0, x_1) f(x_3, x_2) --> f(x_0, x_1) */ -void macro_util::normalize_expr(app * head, expr * t, expr_ref & norm_t) const { - expr_ref_buffer var_mapping(m_manager); +void macro_util::normalize_expr(app * head, unsigned num_decls, expr * t, expr_ref & norm_t) const { + expr_ref_buffer var_mapping(m_manager); + var_mapping.resize(num_decls); bool changed = false; unsigned num_args = head->get_num_args(); - unsigned max_var_idx = 0; - for (unsigned i = 0; i < num_args; i++) { - var const * v = to_var(head->get_arg(i)); - if (v->get_idx() > max_var_idx) - max_var_idx = v->get_idx(); - } TRACE("macro_util", tout << "head: " << mk_pp(head, m_manager) << "\n"; tout << "applying substitution to:\n" << mk_bounded_pp(t, m_manager) << "\n";); for (unsigned i = 0; i < num_args; i++) { var * v = to_var(head->get_arg(i)); - if (v->get_idx() != i) { + unsigned vi = v->get_idx(); + SASSERT(vi < num_decls); + if (vi != i) { changed = true; var_ref new_var(m_manager.mk_var(i, v->get_sort()), m_manager); - var_mapping.setx(max_var_idx - v->get_idx(), new_var); + var_mapping.setx(num_decls - vi - 1, new_var); } else - var_mapping.setx(max_var_idx - i, v); + var_mapping.setx(num_decls - i - 1, v); } - for (unsigned i = num_args; i <= max_var_idx; i++) - // CMW: Won't be used, but dictates a larger binding size, - // so that the indexes between here and in the rewriter match. - // It's possible that we don't see the true max idx of all vars here. - var_mapping.setx(max_var_idx - i, 0); - if (changed) { // REMARK: t may have nested quantifiers... So, I must use the std order for variable substitution. var_subst subst(m_manager, true); @@ -573,7 +565,7 @@ bool is_hint_atom(expr * lhs, expr * rhs) { return !occurs(to_app(lhs)->get_decl(), rhs) && vars_of_is_subset(rhs, vars); } -void hint_to_macro_head(ast_manager & m, app * head, unsigned num_decls, app_ref & new_head) { +void hint_to_macro_head(ast_manager & m, app * head, unsigned & num_decls, app_ref & new_head) { unsigned num_args = head->get_num_args(); ptr_buffer new_args; sbuffer found_vars; @@ -595,6 +587,7 @@ void hint_to_macro_head(ast_manager & m, app * head, unsigned num_decls, app_ref new_args.push_back(new_var); } new_head = m.mk_app(head->get_decl(), new_args.size(), new_args.c_ptr()); + num_decls = next_var_idx; } /** @@ -671,12 +664,12 @@ void macro_util::macro_candidates::insert(func_decl * f, expr * def, expr * cond // // ----------------------------- -void macro_util::insert_macro(app * head, expr * def, expr * cond, bool ineq, bool satisfy_atom, bool hint, macro_candidates & r) { +void macro_util::insert_macro(app * head, unsigned num_decls, expr * def, expr * cond, bool ineq, bool satisfy_atom, bool hint, macro_candidates & r) { expr_ref norm_def(m_manager); expr_ref norm_cond(m_manager); - normalize_expr(head, def, norm_def); + normalize_expr(head, num_decls, def, norm_def); if (cond != 0) - normalize_expr(head, cond, norm_cond); + normalize_expr(head, num_decls, cond, norm_cond); else if (!hint) norm_cond = m_manager.mk_true(); SASSERT(!hint || norm_cond.get() == 0); @@ -698,11 +691,14 @@ void macro_util::insert_quasi_macro(app * head, unsigned num_decls, expr * def, } else { hint_to_macro_head(m_manager, head, num_decls, new_head); + TRACE("macro_util", + tout << "hint macro head: " << mk_ismt2_pp(new_head, m_manager) << std::endl; + tout << "hint macro def: " << mk_ismt2_pp(def, m_manager) << std::endl; ); } - insert_macro(new_head, def, new_cond, ineq, satisfy_atom, hint, r); + insert_macro(new_head, num_decls, def, new_cond, ineq, satisfy_atom, hint, r); } else { - insert_macro(head, def, cond, ineq, satisfy_atom, hint, r); + insert_macro(head, num_decls, def, cond, ineq, satisfy_atom, hint, r); } } @@ -879,6 +875,9 @@ void macro_util::collect_arith_macro_candidates(expr * atom, unsigned num_decls, */ void macro_util::collect_macro_candidates_core(expr * atom, unsigned num_decls, macro_candidates & r) { expr* lhs, *rhs; + + TRACE("macro_util", tout << "Candidate check for: " << mk_ismt2_pp(atom, m_manager) << std::endl;); + if (m_manager.is_eq(atom, lhs, rhs) || m_manager.is_iff(atom, lhs, rhs)) { if (is_quasi_macro_head(lhs, num_decls) && !is_forbidden(to_app(lhs)->get_decl()) && diff --git a/src/ast/macros/macro_util.h b/src/ast/macros/macro_util.h index 18b00c1f7..033f6ecb4 100644 --- a/src/ast/macros/macro_util.h +++ b/src/ast/macros/macro_util.h @@ -74,9 +74,9 @@ private: void collect_arith_macros(expr * n, unsigned num_decls, unsigned max_macros, bool allow_cond_macros, macro_candidates & r); - void normalize_expr(app * head, expr * t, expr_ref & norm_t) const; - void insert_macro(app * head, expr * def, expr * cond, bool ineq, bool satisfy_atom, bool hint, macro_candidates & r); - void insert_quasi_macro(app * head, unsigned num_decls, expr * def, expr * cond, bool ineq, bool satisfy_atom, bool hint, + void normalize_expr(app * head, unsigned num_decls, expr * t, expr_ref & norm_t) const; + void insert_macro(app * head, unsigned num_decls, expr * def, expr * cond, bool ineq, bool satisfy_atom, bool hint, macro_candidates & r); + void insert_quasi_macro(app * head, unsigned num_decls, expr * def, expr * cond, bool ineq, bool satisfy_atom, bool hint, macro_candidates & r); expr * m_curr_clause; // auxiliary var used in collect_macro_candidates. @@ -105,7 +105,7 @@ public: bool is_left_simple_macro(expr * n, unsigned num_decls, app_ref & head, expr_ref & def) const; bool is_right_simple_macro(expr * n, unsigned num_decls, app_ref & head, expr_ref & def) const; bool is_simple_macro(expr * n, unsigned num_decls, app_ref& head, expr_ref & def) const { - return is_left_simple_macro(n, num_decls, head, def) || is_right_simple_macro(n, num_decls, head, def); + return is_left_simple_macro(n, num_decls, head, def) || is_right_simple_macro(n, num_decls, head, def); } bool is_arith_macro(expr * n, unsigned num_decls, app_ref & head, expr_ref & def, bool & inv) const; @@ -113,20 +113,20 @@ public: bool inv; return is_arith_macro(n, num_decls, head, def, inv); } - + bool is_pseudo_head(expr * n, unsigned num_decls, app_ref & head, app_ref & t); bool is_pseudo_predicate_macro(expr * n, app_ref & head, app_ref & t, expr_ref & def); bool is_quasi_macro_head(expr * n, unsigned num_decls) const; - void quasi_macro_head_to_macro_head(app * qhead, unsigned num_decls, app_ref & head, expr_ref & cond) const; + void quasi_macro_head_to_macro_head(app * qhead, unsigned & num_decls, app_ref & head, expr_ref & cond) const; - void mk_macro_interpretation(app * head, expr * def, expr_ref & interp) const; + void mk_macro_interpretation(app * head, unsigned num_decls, expr * def, expr_ref & interp) const; void collect_macro_candidates(expr * atom, unsigned num_decls, macro_candidates & r); void collect_macro_candidates(quantifier * q, macro_candidates & r); // - // Auxiliary goodness that allows us to manipulate BV and Arith polynomials. + // Auxiliary goodness that allows us to manipulate BV and Arith polynomials. // bool is_bv(expr * n) const; bool is_bv_sort(sort * s) const; From 873d975c77abeeb58fc170e8c8e03e671ff39bd4 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 17 Jan 2017 13:41:15 -0800 Subject: [PATCH 43/47] fix bug in consequence extraction: the order of bcp is not fixed between restarts, so the order of unit literals may not be preserved. This is relatively rare, so we optimize for the case where we assume bcp preserves order (and maybe miss some consequences) Signed-off-by: Nikolaj Bjorner --- src/sat/sat_solver.cpp | 28 +++++++++++++++++++++++----- src/sat/sat_solver.h | 6 ++++-- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp index eec94879a..37fb971fd 100644 --- a/src/sat/sat_solver.cpp +++ b/src/sat/sat_solver.cpp @@ -3227,20 +3227,32 @@ namespace sat { SASSERT(!inconsistent()); unsigned sz = m_trail.size(); for (unsigned i = start; i < sz && lvl(m_trail[i]) <= 1; ++i) { - extract_fixed_consequences(m_trail[i], assumptions, unfixed, conseq); + if (!extract_fixed_consequences(m_trail[i], assumptions, unfixed, conseq)) { + for (i = 0; i < sz && lvl(m_trail[i]) <= 1; ++i) { + VERIFY(extract_fixed_consequences(m_trail[i], assumptions, unfixed, conseq)); + } + break; + } } start = sz; } - void solver::extract_assumptions(literal lit, index_set& s) { + bool solver::check_domain(literal lit, literal lit2) { + return m_antecedents.contains(lit2.var()); + } + + bool solver::extract_assumptions(literal lit, index_set& s) { justification js = m_justification[lit.var()]; switch (js.get_kind()) { case justification::NONE: break; case justification::BINARY: + if (!check_domain(lit, js.get_literal())) return false; s |= m_antecedents.find(js.get_literal().var()); break; case justification::TERNARY: + if (!check_domain(lit, js.get_literal1())) return false; + if (!check_domain(lit, js.get_literal2())) return false; s |= m_antecedents.find(js.get_literal1().var()); s |= m_antecedents.find(js.get_literal2().var()); break; @@ -3248,6 +3260,7 @@ namespace sat { clause & c = *(m_cls_allocator.get_clause(js.get_clause_offset())); for (unsigned i = 0; i < c.size(); ++i) { if (c[i] != lit) { + if (!check_domain(lit, c[i])) return false; s |= m_antecedents.find(c[i].var()); } } @@ -3258,6 +3271,7 @@ namespace sat { literal_vector::iterator it = m_ext_antecedents.begin(); literal_vector::iterator end = m_ext_antecedents.end(); for (; it != end; ++it) { + if (!check_domain(lit, *it)) return false; s |= m_antecedents.find(it->var()); } break; @@ -3267,6 +3281,7 @@ namespace sat { break; } TRACE("sat", display_index_set(tout << lit << ": " , s) << "\n";); + return true; } std::ostream& solver::display_index_set(std::ostream& out, index_set const& s) const { @@ -3279,17 +3294,19 @@ namespace sat { } - void solver::extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector& conseq) { + bool solver::extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector& conseq) { index_set s; if (m_antecedents.contains(lit.var())) { - return; + return true; } if (assumptions.contains(lit)) { s.insert(lit.index()); } else { + if (!extract_assumptions(lit, s)) { + return false; + } add_assumption(lit); - extract_assumptions(lit, s); } m_antecedents.insert(lit.var(), s); if (unfixed.contains(lit.var())) { @@ -3302,6 +3319,7 @@ namespace sat { unfixed.remove(lit.var()); conseq.push_back(cons); } + return true; } void solver::asymmetric_branching() { diff --git a/src/sat/sat_solver.h b/src/sat/sat_solver.h index f28d0aa5b..dcf7e2acb 100644 --- a/src/sat/sat_solver.h +++ b/src/sat/sat_solver.h @@ -439,7 +439,9 @@ namespace sat { u_map m_antecedents; vector m_binary_clause_graph; - void extract_assumptions(literal lit, index_set& s); + bool extract_assumptions(literal lit, index_set& s); + + bool check_domain(literal lit, literal lit2); std::ostream& display_index_set(std::ostream& out, index_set const& s) const; @@ -451,7 +453,7 @@ namespace sat { void extract_fixed_consequences(unsigned& start, literal_set const& assumptions, bool_var_set& unfixed, vector& conseq); - void extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector& conseq); + bool extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector& conseq); void update_unfixed_literals(literal_set& unfixed_lits, bool_var_set& unfixed_vars); From 0aa912371b3ea5ca92aa10b34b7fb25bc6372536 Mon Sep 17 00:00:00 2001 From: Nikolaj Bjorner Date: Tue, 17 Jan 2017 14:19:24 -0800 Subject: [PATCH 44/47] Another fix for #847. Reset wmax theory solver state between lex calls, otherwise it uses stale constraints Signed-off-by: Nikolaj Bjorner --- src/opt/maxsmt.cpp | 15 +++++++++++---- src/opt/opt_solver.cpp | 7 +------ src/opt/opt_solver.h | 1 - src/opt/wmax.cpp | 1 + src/smt/smt_context.cpp | 1 + 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/opt/maxsmt.cpp b/src/opt/maxsmt.cpp index 97b6a5293..f93291599 100644 --- a/src/opt/maxsmt.cpp +++ b/src/opt/maxsmt.cpp @@ -55,15 +55,18 @@ namespace opt { void maxsmt_solver_base::commit_assignment() { expr_ref tmp(m); - rational k(0); + rational k(0), cost(0); for (unsigned i = 0; i < m_soft.size(); ++i) { if (get_assignment(i)) { k += m_weights[i]; } + else { + cost += m_weights[i]; + } } pb_util pb(m); tmp = pb.mk_ge(m_weights.size(), m_weights.c_ptr(), m_soft.c_ptr(), k); - TRACE("opt", tout << tmp << "\n";); + TRACE("opt", tout << "cost: " << cost << "\n" << tmp << "\n";); s().assert_expr(tmp); } @@ -140,7 +143,9 @@ namespace opt { m_wth = s.ensure_wmax_theory(); } maxsmt_solver_base::scoped_ensure_theory::~scoped_ensure_theory() { - //m_wth->reset_local(); + if (m_wth) { + m_wth->reset_local(); + } } smt::theory_wmaxsat& maxsmt_solver_base::scoped_ensure_theory::operator()() { return *m_wth; } @@ -226,7 +231,9 @@ namespace opt { m_msolver = 0; symbol const& maxsat_engine = m_c.maxsat_engine(); IF_VERBOSE(1, verbose_stream() << "(maxsmt)\n";); - TRACE("opt", tout << "maxsmt\n";); + TRACE("opt", tout << "maxsmt\n"; + s().display(tout); tout << "\n"; + ); if (m_soft_constraints.empty() || maxsat_engine == symbol("maxres") || maxsat_engine == symbol::null) { m_msolver = mk_maxres(m_c, m_index, m_weights, m_soft_constraints); } diff --git a/src/opt/opt_solver.cpp b/src/opt/opt_solver.cpp index 42129be70..351141a3f 100644 --- a/src/opt/opt_solver.cpp +++ b/src/opt/opt_solver.cpp @@ -327,12 +327,7 @@ namespace opt { SASSERT(idx < get_num_assertions()); return m_context.get_formulas()[idx]; } - - std::ostream& opt_solver::display(std::ostream & out) const { - m_context.display(out); - return out; - } - + smt::theory_var opt_solver::add_objective(app* term) { smt::theory_var v = get_optimizer().add_objective(term); m_objective_vars.push_back(v); diff --git a/src/opt/opt_solver.h b/src/opt/opt_solver.h index cdaad3cf2..27168e2ca 100644 --- a/src/opt/opt_solver.h +++ b/src/opt/opt_solver.h @@ -104,7 +104,6 @@ namespace opt { virtual void set_progress_callback(progress_callback * callback); virtual unsigned get_num_assertions() const; virtual expr * get_assertion(unsigned idx) const; - virtual std::ostream& display(std::ostream & out) const; virtual ast_manager& get_manager() const { return m; } virtual lbool find_mutexes(expr_ref_vector const& vars, vector& mutexes); virtual lbool preferred_sat(expr_ref_vector const& asms, vector& cores); diff --git a/src/opt/wmax.cpp b/src/opt/wmax.cpp index 690e2000b..9708bdc8f 100644 --- a/src/opt/wmax.cpp +++ b/src/opt/wmax.cpp @@ -64,6 +64,7 @@ namespace opt { bool was_sat = false; expr_ref_vector asms(m); vector cores; + obj_map::iterator it = soft.begin(), end = soft.end(); for (; it != end; ++it) { expr* c = assert_weighted(wth(), it->m_key, it->m_value); diff --git a/src/smt/smt_context.cpp b/src/smt/smt_context.cpp index ea97d1a64..c7aecca88 100644 --- a/src/smt/smt_context.cpp +++ b/src/smt/smt_context.cpp @@ -1795,6 +1795,7 @@ namespace smt { void context::set_conflict(b_justification js, literal not_l) { if (!inconsistent()) { + TRACE("set_conflict", display_literal_verbose(tout, not_l); display(tout, js); ); m_conflict = js; m_not_l = not_l; } From a334020f2cf2731ffa60e188e08d985038944f7a Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 18 Jan 2017 12:32:02 +0000 Subject: [PATCH 45/47] Added .NET 3.5 solution/project files --- examples/dotnet/Program.cs | 4 + .../Example/Properties/AssemblyInfo.cs | 36 ++ .../dotnet/dotnet35/Microsoft.Z3.NET35.csproj | 325 ++++++++++++++++++ .../dotnet/dotnet35/Microsoft.Z3.NET35.sln | 48 +++ .../dotnet35/Properties/AssemblyInfo.cs | 38 ++ .../dotnet35/Properties/AssemblyInfo.cs.in | 38 ++ src/api/dotnet/{ => dotnet35}/Readme.NET35 | 3 +- src/api/dotnet/dotnet35/packages.config | 4 + 8 files changed, 495 insertions(+), 1 deletion(-) create mode 100644 src/api/dotnet/dotnet35/Example/Properties/AssemblyInfo.cs create mode 100644 src/api/dotnet/dotnet35/Microsoft.Z3.NET35.csproj create mode 100644 src/api/dotnet/dotnet35/Microsoft.Z3.NET35.sln create mode 100644 src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs create mode 100644 src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs.in rename src/api/dotnet/{ => dotnet35}/Readme.NET35 (87%) create mode 100644 src/api/dotnet/dotnet35/packages.config diff --git a/examples/dotnet/Program.cs b/examples/dotnet/Program.cs index 5b10dadd0..20bb012b1 100644 --- a/examples/dotnet/Program.cs +++ b/examples/dotnet/Program.cs @@ -818,6 +818,7 @@ namespace test_mapi BigIntCheck(ctx, ctx.MkReal("234234333/2")); +#if !FRAMEWORK_LT_4 string bn = "1234567890987654321"; if (ctx.MkInt(bn).BigInteger.ToString() != bn) @@ -828,6 +829,7 @@ namespace test_mapi if (ctx.MkBV(bn, 32).BigInteger.ToString() == bn) throw new TestFailedException(); +#endif // Error handling test. try @@ -1094,8 +1096,10 @@ namespace test_mapi static void BigIntCheck(Context ctx, RatNum r) { +#if !FRAMEWORK_LT_4 Console.WriteLine("Num: " + r.BigIntNumerator); Console.WriteLine("Den: " + r.BigIntDenominator); +#endif } /// diff --git a/src/api/dotnet/dotnet35/Example/Properties/AssemblyInfo.cs b/src/api/dotnet/dotnet35/Example/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..ef95285e0 --- /dev/null +++ b/src/api/dotnet/dotnet35/Example/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Example")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Example")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7a55be70-b47a-42c0-bb06-a6c3c3102947")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.csproj b/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.csproj new file mode 100644 index 000000000..7eaf16fd4 --- /dev/null +++ b/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.csproj @@ -0,0 +1,325 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {EC3DB697-B734-42F7-9468-5B62821EEB5A} + Library + Properties + Microsoft.Z3 + Microsoft.Z3 + v3.5 + 512 + + + 0 + + + true + full + false + Debug\ + TRACE;DEBUG;FRAMEWORK_LT_4 + prompt + 4 + true + Debug\Microsoft.Z3.XML + False + False + True + False + False + True + False + True + True + False + False + False + True + False + False + False + True + False + False + True + True + True + False + False + + + + + + + True + Full + %28none%29 + 2 + + + pdbonly + true + Release\ + FRAMEWORK_LT_4 + prompt + 4 + true + Release\Microsoft.Z3.xml + x86 + + + true + + + + + + + false + + + + packages\Code.Contract.1.0.0\lib\net35\Microsoft.Contracts.dll + True + + + + + + + AlgebraicNum.cs + + + ApplyResult.cs + + + ArithExpr.cs + + + ArithSort.cs + + + ArrayExpr.cs + + + ArraySort.cs + + + AST.cs + + + ASTMap.cs + + + ASTVector.cs + + + BitVecExpr.cs + + + BitVecNum.cs + + + BitVecSort.cs + + + BoolExpr.cs + + + BoolSort.cs + + + Constructor.cs + + + ConstructorList.cs + + + Context.cs + + + DatatypeExpr.cs + + + DatatypeSort.cs + + + Deprecated.cs + + + Enumerations.cs + + + EnumSort.cs + + + Expr.cs + + + FiniteDomainExpr.cs + + + FiniteDomainNum.cs + + + FiniteDomainSort.cs + + + Fixedpoint.cs + + + FPExpr.cs + + + FPNum.cs + + + FPRMExpr.cs + + + FPRMNum.cs + + + FPRMSort.cs + + + FPSort.cs + + + FuncDecl.cs + + + FuncInterp.cs + + + Global.cs + + + Goal.cs + + + IDecRefQueue.cs + + + InterpolationContext.cs + + + IntExpr.cs + + + IntNum.cs + + + IntSort.cs + + + IntSymbol.cs + + + ListSort.cs + + + Log.cs + + + Model.cs + + + Native.cs + + + Optimize.cs + + + ParamDescrs.cs + + + Params.cs + + + Pattern.cs + + + Probe.cs + + + Quantifier.cs + + + RatNum.cs + + + RealExpr.cs + + + RealSort.cs + + + ReExpr.cs + + + RelationSort.cs + + + ReSort.cs + + + SeqExpr.cs + + + SeqSort.cs + + + SetSort.cs + + + Solver.cs + + + Sort.cs + + + Statistics.cs + + + Status.cs + + + StringSymbol.cs + + + Symbol.cs + + + Tactic.cs + + + TupleSort.cs + + + UninterpretedSort.cs + + + Version.cs + + + Z3Exception.cs + + + Z3Object.cs + + + + + + + + + + + \ No newline at end of file diff --git a/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.sln b/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.sln new file mode 100644 index 000000000..c71a920a2 --- /dev/null +++ b/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Z3.NET35", "Microsoft.Z3.NET35.csproj", "{EC3DB697-B734-42F7-9468-5B62821EEB5A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example.csproj", "{7A55BE70-B47A-42C0-BB06-A6C3C3102947}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x64.ActiveCfg = Debug|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x64.Build.0 = Debug|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x86.ActiveCfg = Debug|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x86.Build.0 = Debug|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|Any CPU.Build.0 = Release|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x64.ActiveCfg = Release|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x64.Build.0 = Release|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x86.ActiveCfg = Release|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x86.Build.0 = Release|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|x64.ActiveCfg = Debug|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|x64.Build.0 = Debug|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|x86.ActiveCfg = Debug|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|x86.Build.0 = Debug|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|Any CPU.Build.0 = Release|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|x64.ActiveCfg = Release|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|x64.Build.0 = Release|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|x86.ActiveCfg = Release|Any CPU + {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs b/src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..fb4319002 --- /dev/null +++ b/src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs @@ -0,0 +1,38 @@ +using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Permissions; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Z3 .NET Interface")] +[assembly: AssemblyDescription(".NET Interface to the Z3 Theorem Prover")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft Corporation")] +[assembly: AssemblyProduct("Z3")] +[assembly: AssemblyCopyright("Copyright (C) 2006-2015 Microsoft Corporation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4853ed71-2078-40f4-8117-bc46646bce0e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("4.2.0.0")] +[assembly: AssemblyVersion("4.5.1.6031")] +[assembly: AssemblyFileVersion("4.5.1.6031")] diff --git a/src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs.in b/src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs.in new file mode 100644 index 000000000..e5a85f16f --- /dev/null +++ b/src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs.in @@ -0,0 +1,38 @@ +using System; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Security.Permissions; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Z3 .NET Interface")] +[assembly: AssemblyDescription(".NET Interface to the Z3 Theorem Prover")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft Corporation")] +[assembly: AssemblyProduct("Z3")] +[assembly: AssemblyCopyright("Copyright (C) 2006-2015 Microsoft Corporation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("4853ed71-2078-40f4-8117-bc46646bce0e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("4.2.0.0")] +[assembly: AssemblyVersion("@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_REVISION@")] +[assembly: AssemblyFileVersion("@VER_MAJOR@.@VER_MINOR@.@VER_BUILD@.@VER_REVISION@")] diff --git a/src/api/dotnet/Readme.NET35 b/src/api/dotnet/dotnet35/Readme.NET35 similarity index 87% rename from src/api/dotnet/Readme.NET35 rename to src/api/dotnet/dotnet35/Readme.NET35 index 73743fd15..f8c2958ee 100644 --- a/src/api/dotnet/Readme.NET35 +++ b/src/api/dotnet/dotnet35/Readme.NET35 @@ -6,4 +6,5 @@ In the project properties of Microsoft.Z3.csproj: - Under 'Application': Change Target framework to .NET Framework 3.5 - Under 'Build': Add FRAMEWORK_LT_4 to the condidional compilation symbols - Remove the reference to System.Numerics -- Install the NuGet Package "Microsoft Code Contracts for Net3.5" +- Install the NuGet Package "Microsoft Code Contracts for Net3.5": + In the Package Manager Console enter Install-Package Code.Contract diff --git a/src/api/dotnet/dotnet35/packages.config b/src/api/dotnet/dotnet35/packages.config new file mode 100644 index 000000000..daa06aed7 --- /dev/null +++ b/src/api/dotnet/dotnet35/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 5c1ffe13d1de90ed04f142cfe10bc26634f37393 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Wed, 18 Jan 2017 13:06:28 +0000 Subject: [PATCH 46/47] x64 build fix for .NET 3.5 API --- src/api/dotnet/dotnet35/Example/App.config | 6 ++ .../dotnet/dotnet35/Example/Example.csproj | 78 +++++++++++++++++++ .../Example/Properties/AssemblyInfo.cs | 2 +- .../dotnet/dotnet35/Microsoft.Z3.NET35.csproj | 22 ++++++ .../dotnet/dotnet35/Microsoft.Z3.NET35.sln | 30 +++---- 5 files changed, 122 insertions(+), 16 deletions(-) create mode 100644 src/api/dotnet/dotnet35/Example/App.config create mode 100644 src/api/dotnet/dotnet35/Example/Example.csproj diff --git a/src/api/dotnet/dotnet35/Example/App.config b/src/api/dotnet/dotnet35/Example/App.config new file mode 100644 index 000000000..88fa4027b --- /dev/null +++ b/src/api/dotnet/dotnet35/Example/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/api/dotnet/dotnet35/Example/Example.csproj b/src/api/dotnet/dotnet35/Example/Example.csproj new file mode 100644 index 000000000..2b096ed40 --- /dev/null +++ b/src/api/dotnet/dotnet35/Example/Example.csproj @@ -0,0 +1,78 @@ + + + + + Debug + AnyCPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812} + Exe + Properties + Example + Example + v4.5.2 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + TRACE;DEBUG;FRAMEWORK_LT_4 + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE;FRAMEWORK_LT_4 + prompt + 4 + + + true + bin\x64\Debug\ + TRACE;DEBUG;FRAMEWORK_LT_4 + full + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + bin\x64\Release\ + TRACE;FRAMEWORK_LT_4 + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + true + + + + Program.cs + + + + + + + + + {ec3db697-b734-42f7-9468-5b62821eeb5a} + Microsoft.Z3.NET35 + + + + + \ No newline at end of file diff --git a/src/api/dotnet/dotnet35/Example/Properties/AssemblyInfo.cs b/src/api/dotnet/dotnet35/Example/Properties/AssemblyInfo.cs index ef95285e0..ed0d8454f 100644 --- a/src/api/dotnet/dotnet35/Example/Properties/AssemblyInfo.cs +++ b/src/api/dotnet/dotnet35/Example/Properties/AssemblyInfo.cs @@ -20,7 +20,7 @@ using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("7a55be70-b47a-42c0-bb06-a6c3c3102947")] +[assembly: Guid("2a8e577b-7b6d-4ca9-832a-ca2eec314812")] // Version information for an assembly consists of the following four values: // diff --git a/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.csproj b/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.csproj index 7eaf16fd4..d278b4f1d 100644 --- a/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.csproj +++ b/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.csproj @@ -82,6 +82,28 @@ false + + true + bin\x64\Debug\ + TRACE;DEBUG;FRAMEWORK_LT_4 + true + Debug\Microsoft.Z3.XML + full + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\Release\ + FRAMEWORK_LT_4 + true + Release\Microsoft.Z3.xml + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + packages\Code.Contract.1.0.0\lib\net35\Microsoft.Contracts.dll diff --git a/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.sln b/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.sln index c71a920a2..b6e252684 100644 --- a/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.sln +++ b/src/api/dotnet/dotnet35/Microsoft.Z3.NET35.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Z3.NET35", "Microsoft.Z3.NET35.csproj", "{EC3DB697-B734-42F7-9468-5B62821EEB5A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example.csproj", "{7A55BE70-B47A-42C0-BB06-A6C3C3102947}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example.csproj", "{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -25,22 +25,22 @@ Global {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Debug|x86.Build.0 = Debug|Any CPU {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|Any CPU.ActiveCfg = Release|Any CPU {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|Any CPU.Build.0 = Release|Any CPU - {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x64.ActiveCfg = Release|Any CPU - {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x64.Build.0 = Release|Any CPU + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x64.ActiveCfg = Release|x64 + {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x64.Build.0 = Release|x64 {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x86.ActiveCfg = Release|Any CPU {EC3DB697-B734-42F7-9468-5B62821EEB5A}.Release|x86.Build.0 = Release|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|x64.ActiveCfg = Debug|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|x64.Build.0 = Debug|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|x86.ActiveCfg = Debug|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Debug|x86.Build.0 = Debug|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|Any CPU.Build.0 = Release|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|x64.ActiveCfg = Release|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|x64.Build.0 = Release|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|x86.ActiveCfg = Release|Any CPU - {7A55BE70-B47A-42C0-BB06-A6C3C3102947}.Release|x86.Build.0 = Release|Any CPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x64.ActiveCfg = Debug|Any CPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x64.Build.0 = Debug|Any CPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x86.ActiveCfg = Debug|Any CPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Debug|x86.Build.0 = Debug|Any CPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|Any CPU.Build.0 = Release|Any CPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x64.ActiveCfg = Release|x64 + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x64.Build.0 = Release|x64 + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x86.ActiveCfg = Release|Any CPU + {2A8E577B-7B6D-4CA9-832A-CA2EEC314812}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 43d083bafb58aac211f3dad151c2ad7da91e1d30 Mon Sep 17 00:00:00 2001 From: "Christoph M. Wintersteiger" Date: Thu, 19 Jan 2017 11:19:29 +0000 Subject: [PATCH 47/47] Windows build fix. --- scripts/mk_win_dist.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/mk_win_dist.py b/scripts/mk_win_dist.py index 11048650f..66f44426f 100644 --- a/scripts/mk_win_dist.py +++ b/scripts/mk_win_dist.py @@ -241,8 +241,8 @@ def mk_zip(x64): # Create a zip file for each platform def mk_zips(): - mk_zip_core(False) - mk_zip_core(True) + mk_zip(False) + mk_zip(True) VS_RUNTIME_PATS = [re.compile('vcomp.*\.dll'),