3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 10:25:18 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-01-19 17:56:43 -08:00
commit 13099b1590
87 changed files with 2187 additions and 4479 deletions

View file

@ -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 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
[3]: #building-z3-using-cmake

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
}
/// <summary>

View file

@ -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')

View file

@ -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

View file

@ -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

View file

@ -2442,7 +2442,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'
@ -2493,7 +2493,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)
@ -2870,7 +2872,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():
@ -2924,172 +2927,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:
efile.write('(** %s *)\n' % name[3:])
efile.write('type %s =\n' % name[3:]) # strip Z3_
for k, i in decls.items():
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():
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():
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 decls.items():
# 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

View file

@ -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,9 +240,9 @@ def mk_zip_core(x64):
os.chdir(old)
# Create a zip file for each platform
def mk_zip():
mk_zip_core(False)
mk_zip_core(True)
def mk_zips():
mk_zip(False)
mk_zip(True)
VS_RUNTIME_PATS = [re.compile('vcomp.*\.dll'),
@ -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_runtimes()
mk_zips()
main()

View file

@ -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')
@ -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()
@ -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<iostream>\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')
@ -1666,7 +1667,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 +1743,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 +1771,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 +1786,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 +1802,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__':

View file

@ -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<iostream>
#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])) {

View file

@ -15,7 +15,6 @@ Author:
Revision History:
--*/
#include<iostream>
#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);
}

View file

@ -15,7 +15,6 @@ Author:
Revision History:
--*/
#include<iostream>
#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<sort> 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<Z3_sort>(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<Z3_sort>(to_sort(t)->get_parameter(1).get_ast());
RETURN_Z3(r);

View file

@ -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;
@ -1210,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;
}
}

View file

@ -15,7 +15,6 @@ Author:
Revision History:
--*/
#include<iostream>
#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 <tt>shl(1, N-1)</tt>
@ -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);
}
};

View file

@ -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();
}

View file

@ -15,7 +15,6 @@ Author:
Revision History:
--*/
#include<iostream>
#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<accessor_decl> 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<func_decl> 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<func_decl> 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<constructor_decl> 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<func_decl> 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<func_decl> const* cnstrs = data_util.get_datatype_constructors(s);
for (unsigned i = 0; i < num_constructors; ++i) {
constructor* cn = reinterpret_cast<constructor*>(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_list*>(constructor_lists[i]);
ptr_vector<func_decl> 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<func_decl> 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<func_decl> 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<func_decl> 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<func_decl> 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<func_decl> 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);

View file

@ -15,7 +15,6 @@
Revision History:
--*/
#include<iostream>
#include<sstream>
#include<vector>
#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){

View file

@ -15,7 +15,6 @@ Author:
Revision History:
--*/
#include<iostream>
#include<fstream>
#include"z3.h"
#include"api_log_macros.h"

View file

@ -15,7 +15,6 @@ Author:
Revision History:
--*/
#include<iostream>
#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,8 +37,21 @@ 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_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 Z3_API Z3_mk_pble(Z3_context c, unsigned num_args,
Z3_ast const args[], int _coeffs[],
int k) {
Z3_TRY;
@ -57,7 +69,25 @@ 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_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<rational> 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) {
Z3_TRY;

View file

@ -14,9 +14,8 @@ Author:
Leonardo de Moura (leonardo) 2012-12-08
Notes:
--*/
#include<iostream>
#include"z3.h"
#include"api_log_macros.h"
#include"api_context.h"
@ -35,7 +34,7 @@ namespace api {
pmanager::~pmanager() {
}
};
extern "C" {

View file

@ -15,7 +15,6 @@ Author:
Revision History:
--*/
#include<iostream>
#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<Z3_ast>(p));
}
};

View file

@ -16,7 +16,6 @@ Author:
Revision History:
--*/
#include<iostream>
#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);

View file

@ -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.
*/
@ -330,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); }
@ -672,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;
int result = 0;
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;
@ -686,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;
unsigned result = 0;
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;
@ -706,8 +732,10 @@ namespace z3 {
*/
__int64 get_numeral_int64() const {
assert(is_numeral());
__int64 result;
__int64 result = 0;
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;
@ -721,8 +749,10 @@ namespace z3 {
*/
__uint64 get_numeral_uint64() const {
assert(is_numeral());
__uint64 result;
__uint64 result = 0;
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;
@ -1615,7 +1645,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);
}

View file

@ -2692,6 +2692,18 @@ namespace Microsoft.Z3
AST.ArrayToNative(args), k));
}
/// <summary>
/// Create an at-least-k constraint.
/// </summary>
public BoolExpr MkAtLeast(BoolExpr[] args, uint k)
{
Contract.Requires(args != null);
Contract.Requires(Contract.Result<BoolExpr[]>() != null);
CheckContextMatch<BoolExpr>(args);
return new BoolExpr(this, Native.Z3_mk_atleast(nCtx, (uint) args.Length,
AST.ArrayToNative(args), k));
}
/// <summary>
/// Create a pseudo-Boolean less-or-equal constraint.
/// </summary>
@ -2707,6 +2719,20 @@ namespace Microsoft.Z3
coeffs, k));
}
/// <summary>
/// Create a pseudo-Boolean greater-or-equal constraint.
/// </summary>
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<BoolExpr[]>() != null);
CheckContextMatch<BoolExpr>(args);
return new BoolExpr(this, Native.Z3_mk_pbge(nCtx, (uint) args.Length,
AST.ArrayToNative(args),
coeffs, k));
}
/// <summary>
/// Create a pseudo-Boolean equal constraint.
/// </summary>

View file

@ -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);
}
/// <summary>
/// Alias for Assert.
/// </summary>
public void Add(IEnumerable<BoolExpr> constraints)
{
Assert(constraints.ToArray());
}
/// <summary>
/// Assert multiple constraints into the solver, and track them (in the unsat) core
/// using the Boolean constants in ps.

View file

@ -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<Object, bool> p) { return true; }
public static bool ForAll(int from, int to, Predicate<int> p) { return true; }
[Conditional("false")]
public static void Invariant(bool b) { }
public static T[] Result<T>() { return new T[1]; }
[Conditional("false")]
public static void EndContractBlock() { }
public static T ValueAtReturn<T>(out T v) { T[] t = new T[1]; v = t[0]; return v; }
}

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

View file

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Example</RootNamespace>
<AssemblyName>Example</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FRAMEWORK_LT_4</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;FRAMEWORK_LT_4</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FRAMEWORK_LT_4</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;FRAMEWORK_LT_4</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\..\..\..\examples\dotnet\Program.cs">
<Link>Program.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Z3.NET35.csproj">
<Project>{ec3db697-b734-42f7-9468-5b62821eeb5a}</Project>
<Name>Microsoft.Z3.NET35</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -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("2a8e577b-7b6d-4ca9-832a-ca2eec314812")]
// 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")]

View file

@ -0,0 +1,347 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{EC3DB697-B734-42F7-9468-5B62821EEB5A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.Z3</RootNamespace>
<AssemblyName>Microsoft.Z3</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FRAMEWORK_LT_4</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>Debug\Microsoft.Z3.XML</DocumentationFile>
<CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
<CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
<CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
<CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
<CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
<CodeContractsRunCodeAnalysis>True</CodeContractsRunCodeAnalysis>
<CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
<CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
<CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
<CodeContractsEnumObligations>False</CodeContractsEnumObligations>
<CodeContractsPointerObligations>False</CodeContractsPointerObligations>
<CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
<CodeContractsInferRequires>True</CodeContractsInferRequires>
<CodeContractsInferEnsures>False</CodeContractsInferEnsures>
<CodeContractsInferObjectInvariants>False</CodeContractsInferObjectInvariants>
<CodeContractsSuggestAssumptions>False</CodeContractsSuggestAssumptions>
<CodeContractsSuggestRequires>True</CodeContractsSuggestRequires>
<CodeContractsSuggestEnsures>False</CodeContractsSuggestEnsures>
<CodeContractsSuggestObjectInvariants>False</CodeContractsSuggestObjectInvariants>
<CodeContractsDisjunctiveRequires>True</CodeContractsDisjunctiveRequires>
<CodeContractsRunInBackground>True</CodeContractsRunInBackground>
<CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
<CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
<CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
<CodeContractsCustomRewriterAssembly />
<CodeContractsCustomRewriterClass />
<CodeContractsLibPaths />
<CodeContractsExtraRewriteOptions />
<CodeContractsExtraAnalysisOptions />
<CodeContractsBaseLineFile />
<CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
<CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
<CodeContractsReferenceAssembly>%28none%29</CodeContractsReferenceAssembly>
<CodeContractsAnalysisWarningLevel>2</CodeContractsAnalysisWarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>Release\</OutputPath>
<DefineConstants>FRAMEWORK_LT_4</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>Release\Microsoft.Z3.xml</DocumentationFile>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup>
<DelaySign>false</DelaySign>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;FRAMEWORK_LT_4</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>Debug\Microsoft.Z3.XML</DocumentationFile>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>FRAMEWORK_LT_4</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DocumentationFile>Release\Microsoft.Z3.xml</DocumentationFile>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=736440c9b414ea16, processorArchitecture=MSIL">
<HintPath>packages\Code.Contract.1.0.0\lib\net35\Microsoft.Contracts.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\AlgebraicNum.cs">
<Link>AlgebraicNum.cs</Link>
</Compile>
<Compile Include="..\ApplyResult.cs">
<Link>ApplyResult.cs</Link>
</Compile>
<Compile Include="..\ArithExpr.cs">
<Link>ArithExpr.cs</Link>
</Compile>
<Compile Include="..\ArithSort.cs">
<Link>ArithSort.cs</Link>
</Compile>
<Compile Include="..\ArrayExpr.cs">
<Link>ArrayExpr.cs</Link>
</Compile>
<Compile Include="..\ArraySort.cs">
<Link>ArraySort.cs</Link>
</Compile>
<Compile Include="..\AST.cs">
<Link>AST.cs</Link>
</Compile>
<Compile Include="..\ASTMap.cs">
<Link>ASTMap.cs</Link>
</Compile>
<Compile Include="..\ASTVector.cs">
<Link>ASTVector.cs</Link>
</Compile>
<Compile Include="..\BitVecExpr.cs">
<Link>BitVecExpr.cs</Link>
</Compile>
<Compile Include="..\BitVecNum.cs">
<Link>BitVecNum.cs</Link>
</Compile>
<Compile Include="..\BitVecSort.cs">
<Link>BitVecSort.cs</Link>
</Compile>
<Compile Include="..\BoolExpr.cs">
<Link>BoolExpr.cs</Link>
</Compile>
<Compile Include="..\BoolSort.cs">
<Link>BoolSort.cs</Link>
</Compile>
<Compile Include="..\Constructor.cs">
<Link>Constructor.cs</Link>
</Compile>
<Compile Include="..\ConstructorList.cs">
<Link>ConstructorList.cs</Link>
</Compile>
<Compile Include="..\Context.cs">
<Link>Context.cs</Link>
</Compile>
<Compile Include="..\DatatypeExpr.cs">
<Link>DatatypeExpr.cs</Link>
</Compile>
<Compile Include="..\DatatypeSort.cs">
<Link>DatatypeSort.cs</Link>
</Compile>
<Compile Include="..\Deprecated.cs">
<Link>Deprecated.cs</Link>
</Compile>
<Compile Include="..\Enumerations.cs">
<Link>Enumerations.cs</Link>
</Compile>
<Compile Include="..\EnumSort.cs">
<Link>EnumSort.cs</Link>
</Compile>
<Compile Include="..\Expr.cs">
<Link>Expr.cs</Link>
</Compile>
<Compile Include="..\FiniteDomainExpr.cs">
<Link>FiniteDomainExpr.cs</Link>
</Compile>
<Compile Include="..\FiniteDomainNum.cs">
<Link>FiniteDomainNum.cs</Link>
</Compile>
<Compile Include="..\FiniteDomainSort.cs">
<Link>FiniteDomainSort.cs</Link>
</Compile>
<Compile Include="..\Fixedpoint.cs">
<Link>Fixedpoint.cs</Link>
</Compile>
<Compile Include="..\FPExpr.cs">
<Link>FPExpr.cs</Link>
</Compile>
<Compile Include="..\FPNum.cs">
<Link>FPNum.cs</Link>
</Compile>
<Compile Include="..\FPRMExpr.cs">
<Link>FPRMExpr.cs</Link>
</Compile>
<Compile Include="..\FPRMNum.cs">
<Link>FPRMNum.cs</Link>
</Compile>
<Compile Include="..\FPRMSort.cs">
<Link>FPRMSort.cs</Link>
</Compile>
<Compile Include="..\FPSort.cs">
<Link>FPSort.cs</Link>
</Compile>
<Compile Include="..\FuncDecl.cs">
<Link>FuncDecl.cs</Link>
</Compile>
<Compile Include="..\FuncInterp.cs">
<Link>FuncInterp.cs</Link>
</Compile>
<Compile Include="..\Global.cs">
<Link>Global.cs</Link>
</Compile>
<Compile Include="..\Goal.cs">
<Link>Goal.cs</Link>
</Compile>
<Compile Include="..\IDecRefQueue.cs">
<Link>IDecRefQueue.cs</Link>
</Compile>
<Compile Include="..\InterpolationContext.cs">
<Link>InterpolationContext.cs</Link>
</Compile>
<Compile Include="..\IntExpr.cs">
<Link>IntExpr.cs</Link>
</Compile>
<Compile Include="..\IntNum.cs">
<Link>IntNum.cs</Link>
</Compile>
<Compile Include="..\IntSort.cs">
<Link>IntSort.cs</Link>
</Compile>
<Compile Include="..\IntSymbol.cs">
<Link>IntSymbol.cs</Link>
</Compile>
<Compile Include="..\ListSort.cs">
<Link>ListSort.cs</Link>
</Compile>
<Compile Include="..\Log.cs">
<Link>Log.cs</Link>
</Compile>
<Compile Include="..\Model.cs">
<Link>Model.cs</Link>
</Compile>
<Compile Include="..\Native.cs">
<Link>Native.cs</Link>
</Compile>
<Compile Include="..\Optimize.cs">
<Link>Optimize.cs</Link>
</Compile>
<Compile Include="..\ParamDescrs.cs">
<Link>ParamDescrs.cs</Link>
</Compile>
<Compile Include="..\Params.cs">
<Link>Params.cs</Link>
</Compile>
<Compile Include="..\Pattern.cs">
<Link>Pattern.cs</Link>
</Compile>
<Compile Include="..\Probe.cs">
<Link>Probe.cs</Link>
</Compile>
<Compile Include="..\Quantifier.cs">
<Link>Quantifier.cs</Link>
</Compile>
<Compile Include="..\RatNum.cs">
<Link>RatNum.cs</Link>
</Compile>
<Compile Include="..\RealExpr.cs">
<Link>RealExpr.cs</Link>
</Compile>
<Compile Include="..\RealSort.cs">
<Link>RealSort.cs</Link>
</Compile>
<Compile Include="..\ReExpr.cs">
<Link>ReExpr.cs</Link>
</Compile>
<Compile Include="..\RelationSort.cs">
<Link>RelationSort.cs</Link>
</Compile>
<Compile Include="..\ReSort.cs">
<Link>ReSort.cs</Link>
</Compile>
<Compile Include="..\SeqExpr.cs">
<Link>SeqExpr.cs</Link>
</Compile>
<Compile Include="..\SeqSort.cs">
<Link>SeqSort.cs</Link>
</Compile>
<Compile Include="..\SetSort.cs">
<Link>SetSort.cs</Link>
</Compile>
<Compile Include="..\Solver.cs">
<Link>Solver.cs</Link>
</Compile>
<Compile Include="..\Sort.cs">
<Link>Sort.cs</Link>
</Compile>
<Compile Include="..\Statistics.cs">
<Link>Statistics.cs</Link>
</Compile>
<Compile Include="..\Status.cs">
<Link>Status.cs</Link>
</Compile>
<Compile Include="..\StringSymbol.cs">
<Link>StringSymbol.cs</Link>
</Compile>
<Compile Include="..\Symbol.cs">
<Link>Symbol.cs</Link>
</Compile>
<Compile Include="..\Tactic.cs">
<Link>Tactic.cs</Link>
</Compile>
<Compile Include="..\TupleSort.cs">
<Link>TupleSort.cs</Link>
</Compile>
<Compile Include="..\UninterpretedSort.cs">
<Link>UninterpretedSort.cs</Link>
</Compile>
<Compile Include="..\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="..\Z3Exception.cs">
<Link>Z3Exception.cs</Link>
</Compile>
<Compile Include="..\Z3Object.cs">
<Link>Z3Object.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<WCFMetadata Include="Service References\" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -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", "{2A8E577B-7B6D-4CA9-832A-CA2EEC314812}"
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|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
{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
EndGlobalSection
EndGlobal

View file

@ -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")]

View file

@ -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@")]

View file

@ -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

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Code.Contract" version="1.0.0" targetFramework="net35" />
</packages>

View file

@ -7648,11 +7648,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")
@ -7660,10 +7655,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.
@ -7671,38 +7681,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)

View file

@ -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
@ -1060,6 +1063,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,
@ -1173,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,
@ -1948,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.
@ -3083,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
@ -3388,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);
/**
@ -3425,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);
/*@}*/
@ -3961,10 +3966,19 @@ 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.
Encode p1 + p2 + ... + pn >= k
def_API('Z3_mk_atleast', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in(UINT)))
*/
Z3_ast Z3_API Z3_mk_atleast(Z3_context c, unsigned num_args,
Z3_ast const args[], unsigned k);
/**
\brief Pseudo-Boolean relations.
@ -3972,11 +3986,21 @@ 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.
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_API Z3_mk_pbge(Z3_context c, unsigned num_args,
Z3_ast const args[], int coeffs[],
int k);
/**
\brief Pseudo-Boolean relations.
@ -3984,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);
@ -5199,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);
@ -5972,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,

View file

@ -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 {

View file

@ -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<bool> 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,40 +457,31 @@ 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("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++) {
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);
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++) {
@ -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<expr> new_args;
sbuffer<bool> 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;
}
/**
@ -604,12 +597,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 << "<null>";
tout << "\n";);
ptr_buffer<var> 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 +619,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;
}
@ -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);
}
}
@ -831,7 +827,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);
@ -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()) &&

View file

@ -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;

View file

@ -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;
}

View file

@ -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"

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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<app> 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();
}
}

View file

@ -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; }

View file

@ -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()) {

View file

@ -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<expr> 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());
}
@ -302,17 +301,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<rational> 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() {
@ -500,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) {
@ -540,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();
@ -617,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);
}
@ -668,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");
@ -690,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);
}
@ -749,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) {
@ -767,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) {
@ -790,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();
@ -868,7 +859,6 @@ public:
IF_VERBOSE(0, verbose_stream() << "assignment is infeasible\n";);
}
}
};
opt::maxsmt_solver_base* opt::mk_maxres(

View file

@ -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);
}

View file

@ -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);

View file

@ -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<expr_ref_vector>& mutexes);
virtual lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores);

View file

@ -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<expr, unsigned> m_decl2var; // map declarations to Boolean variables.
ptr_vector<expr> 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;

View file

@ -62,20 +62,22 @@ namespace opt {
}
m_upper = m_lower;
bool was_sat = false;
expr_ref_vector disj(m), asms(m);
expr_ref_vector asms(m);
vector<expr_ref_vector> cores;
obj_map<expr, rational>::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 +86,7 @@ namespace opt {
is_sat = l_undef;
}
if (is_sat == l_false) {
TRACE("opt", tout << "Unsat\n";);
break;
}
if (is_sat == l_true) {

View file

@ -109,7 +109,6 @@ namespace smt2 {
typedef std::pair<symbol, expr*> 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<typename T>
static unsigned size(scoped_ptr<T> & v) {
return v.get() == 0 ? 0 : v->size();
}
template<typename T>
static void shrink(scoped_ptr<T> & 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> & 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<unsigned> 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<psort_frame*>(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<sort_frame*>(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 <expr>
PES_DECL, // expecting (<id> <expr>)
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<let_frame*>(fr)->m_in_decls ? PES_DECL : PES_EXPR;
case EF_ATTR_EXPR:
case EF_ATTR_EXPR:
return consume_attributes(static_cast<attr_expr_frame*>(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' <identifier> <sort> ')'
// '_' <identifier> <num>+ ')'
// 'as' <identifier '(' '_' <identifier> (<num>|<func-decl-ref>)+ ')' <sort> ')'
@ -1255,7 +1259,7 @@ namespace smt2 {
}
}
// parse:
// parse:
// <identifier>
// '(' 'as' <identifier> <sort> ')'
// '(' '_' <identifier> <num>+ ')'
@ -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<app_frame*>(fr));
break;
case EF_LET:
case EF_LET:
pop_let_frame(static_cast<let_frame*>(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 (<numeral>) 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<symbol> 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<expr_ref_vector> const& bindings, vector<svector<symbol> >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<symbol> 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();
}

View file

@ -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

View file

@ -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<clause>& 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<clause*>& 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<clause*>& 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<uint64, unsigned, u64_hash, u64_eq> 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<bool> _disable_bcd(m_solver.m_config.m_bcd, false);
flet<bool> _disable_min(m_solver.m_config.m_core_minimize, false);
flet<bool> _disable_opt(m_solver.m_config.m_optimize_model, false);
flet<unsigned> _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();
}
};

View file

@ -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> clause_use_list;
class use_list {
vector<ptr_vector<clause> > 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<clause>& get(literal lit);
};
typedef std::pair<literal, literal> bin_clause;
typedef svector<bin_clause> bin_clauses;
solver & m_solver;
use_list* m_use_list;
use_list m_bce_use_list;
solver* m_s;
random_gen m_rand;
svector<clause*> m_clauses;
svector<clause*> m_L;
svector<clause*> m_R;
literal_vector m_L_blits;
literal_vector m_R_blits;
svector<clause*> m_bin_clauses;
svector<uint64> m_rbits;
svector<clause*> m_rstack; // stack of blocked clauses
literal_vector m_bstack; // stack of blocking literals
svector<bool> m_marked;
svector<bool> 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<clause>& uses, svector<clause*>& 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

View file

@ -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"),
@ -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();
}

View file

@ -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;

View file

@ -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<bool> _disable_min(s.m_config.m_core_minimize, false);
flet<bool> _disable_opt(s.m_config.m_optimize_model, false);
flet<bool> _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;
}
}
}
}

View file

@ -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();

View file

@ -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'),
@ -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')))

View file

@ -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<solver::bin_clause> 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<int>(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<int>(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";
}
}
};

View file

@ -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<clause const> m_clauses; // vector of all clauses.
index_set m_false; // clauses currently false
vector<unsigned_vector> m_use_list; // use lists for literals
unsigned_vector m_num_true; // per clause, count of # true literals
svector<literal> 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<bool> 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<int> m_hscore;
svector<double> m_sscore;
literal_vector m_soft;
svector<double> 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

View file

@ -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() {
@ -123,6 +120,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 +146,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);
@ -212,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++;
@ -235,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
@ -255,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]));
@ -277,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
@ -296,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()) {
@ -326,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);
}
/**
@ -711,7 +707,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);
@ -726,7 +722,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();
@ -766,7 +762,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;
}
@ -912,12 +908,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();
@ -941,16 +936,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()));
@ -960,109 +945,6 @@ namespace sat {
}
bool solver::init_weighted_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight) {
flet<bool> _min1(m_config.m_core_minimize, false);
m_weight = 0;
m_blocker.reset();
svector<lbool> 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<bool> _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();
@ -1112,6 +994,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";
}
});
}
}
@ -1139,11 +1028,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();
}
}
/**
@ -1235,9 +1119,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";);
@ -1664,10 +1545,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;
@ -3118,7 +2995,14 @@ namespace sat {
lbool solver::get_consequences(literal_vector const& asms, bool_var_vector const& vars, vector<literal_vector>& conseq) {
literal_vector lits;
lbool is_sat = check(asms.size(), asms.c_ptr());
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());
}
if (is_sat != l_true) {
return is_sat;
}
@ -3136,9 +3020,94 @@ namespace sat {
return is_sat;
}
lbool solver::get_consequences(literal_vector const& asms, literal_vector const& lits, vector<literal_vector>& conseq) {
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();
index_set::iterator it = s.begin(), end = s.end();
for (; it != end; ++it) {
m_core.push_back(to_literal(*it));
}
TRACE("sat", tout << m_core << "\n";);
}
lbool solver::get_bounded_consequences(literal_vector const& asms, bool_var_vector const& vars, vector<literal_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]);
}
TRACE("sat", tout << asms << "\n";);
m_antecedents.reset();
literal_set vars(lits), assumptions(asms);
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);
}
else {
init_assumptions(asms.size(), asms.c_ptr());
}
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<literal_vector>& conseq) {
TRACE("sat", tout << asms << "\n";);
m_antecedents.reset();
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;
@ -3148,20 +3117,24 @@ 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;
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) {
@ -3202,53 +3175,84 @@ 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 (!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<literal_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<literal_vector>& conseq) {
SASSERT(!inconsistent());
unsigned sz = m_trail.size();
for (unsigned i = start; i < sz; ++i) {
extract_fixed_consequences(m_trail[i], assumptions, unfixed, conseq);
for (unsigned i = start; i < sz && lvl(m_trail[i]) <= 1; ++i) {
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;
@ -3256,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());
}
}
@ -3266,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;
@ -3274,28 +3280,46 @@ namespace sat {
UNREACHABLE();
break;
}
TRACE("sat", display_index_set(tout << lit << ": " , s) << "\n";);
return true;
}
void solver::extract_fixed_consequences(literal lit, literal_set const& assumptions, literal_set& unfixed, vector<literal_vector>& conseq) {
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;
}
bool solver::extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq) {
index_set s;
if (m_antecedents.contains(lit.var())) {
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)) {
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);
}
return true;
}
void solver::asymmetric_branching() {

View file

@ -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);
@ -189,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;
@ -280,10 +273,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 +301,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();
@ -453,15 +439,25 @@ namespace sat {
u_map<index_set> m_antecedents;
vector<literal_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;
lbool get_consequences(literal_vector const& assms, literal_vector const& lits, vector<literal_vector>& conseq);
void delete_unfixed(literal_set& unfixed);
lbool get_bounded_consequences(literal_vector const& assms, bool_var_vector const& vars, vector<literal_vector>& conseq);
void extract_fixed_consequences(unsigned& start, literal_set const& assumptions, literal_set& unfixed, vector<literal_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<literal_vector>& conseq);
void extract_fixed_consequences(unsigned& start, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq);
bool extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq);
void update_unfixed_literals(literal_set& unfixed_lits, bool_var_set& unfixed_vars);
void fixup_consequence_core();
// -----------------------
//

View file

@ -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;
@ -252,12 +243,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_true) 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.
@ -670,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<inc_sat_solver&>(_s);
vector<double> 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<inc_sat_solver&>(_s);
vector<unsigned> weights;

View file

@ -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);

View file

@ -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);

View file

@ -184,13 +184,13 @@ void asserted_formulas::get_assertions(ptr_vector<expr> & 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();

View file

@ -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')
))

View file

@ -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 "<string>"; }
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, params_ref(), m_filename);
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));
}

26
src/smt/smt2_extra_cmds.h Normal file
View file

@ -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_ */

View file

@ -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; }

View file

@ -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;

View file

@ -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 n_eq = literal(l.var(), true);
set_conflict(b_justification(mk_justification(eq_propagation_justification(get_enode(lhs), get_enode(rhs)))), n_eq);
}
}
}
@ -1787,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;
}
@ -2042,7 +2051,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 +2602,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);

View file

@ -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<justification> m_justifications;
@ -116,7 +116,7 @@ namespace smt {
plugin_manager<theory> m_theories; // mapping from theory_id -> theory
ptr_vector<theory> m_theory_set; // set of theories for fast traversal
vector<enode_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<new_th_eq> m_propagated_th_eqs;
svector<new_th_eq> m_propagated_th_diseqs;
svector<enode_pair> 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<watch_list> m_watches; //!< per literal
vector<clause_set> m_lit_occs; //!< index for backward subsumption
svector<bool_var_data> m_bdata; //!< mapping bool_var -> data
svector<double> m_activity;
clause_vector m_aux_clauses;
svector<double> m_activity;
clause_vector m_aux_clauses;
clause_vector m_lemmas;
vector<clause_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<expr *> literal2assumption;
typedef u_map<expr *> 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<lbool>(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;
@ -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;
@ -423,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.
*/
@ -434,7 +436,7 @@ namespace smt {
theory * get_theory(theory_id th_id) const {
return m_theories.get_plugin(th_id);
}
ptr_vector<theory>::const_iterator begin_theories() const {
return m_theories.begin();
}
@ -448,7 +450,7 @@ namespace smt {
}
unsigned get_base_level() const {
return m_base_lvl;
return m_base_lvl;
}
bool at_base_level() const {
@ -468,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();
@ -499,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;
@ -589,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);
@ -615,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);
@ -630,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));
}
@ -646,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();
}
@ -654,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();
}
@ -691,9 +693,9 @@ namespace smt {
void ts_visit_child(expr * n, bool gate_ctx, svector<int> & tcolors, svector<int> & fcolors, svector<expr_bool_pair> & todo, bool & visited);
bool ts_visit_children(expr * n, bool gate_ctx, svector<int> & tcolors, svector<int> & fcolors, svector<expr_bool_pair> & todo);
void top_sort_expr(expr * n, svector<expr_bool_pair> & sorted_exprs);
void assert_default(expr * n, proof * pr);
void assert_distinct(app * n, proof * pr);
@ -721,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);
@ -752,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;
@ -784,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);
@ -796,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);
@ -819,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);
@ -828,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;
}
@ -849,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;
@ -878,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);
@ -899,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<enode> & used_enodes);
void set_global_generation(unsigned generation) { m_generation = generation; }
@ -958,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);
@ -997,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);
}
@ -1031,7 +1033,7 @@ namespace smt {
}
return false;
}
bool can_delete(clause * cls) const {
if (cls->in_reinit_stack())
return false;
@ -1053,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();
@ -1073,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();
@ -1102,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);
@ -1126,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<typename Eh>
relevancy_eh * mk_relevancy_eh(Eh const & eh) {
return m_relevancy_propagator->mk_relevancy_eh(eh);
@ -1149,9 +1151,9 @@ namespace smt {
void propagate_th_eqs();
void propagate_th_diseqs();
bool can_theories_propagate() const;
bool propagate();
public:
@ -1167,7 +1169,7 @@ namespace smt {
// -----------------------------------
//
// Pretty Printing
// Pretty Printing
//
// -----------------------------------
protected:
@ -1215,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;
@ -1235,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;
@ -1289,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;
@ -1357,7 +1359,7 @@ namespace smt {
static literal translate_literal(
literal lit, context& src_ctx, context& dst_ctx,
vector<bool_var> b2v, ast_translation& tr);
/*
\brief Utilities for consequence finding.
*/
@ -1366,7 +1368,7 @@ namespace smt {
u_map<index_set> m_antecedents;
void extract_fixed_consequences(literal lit, obj_map<expr, expr*>& var2val, index_set const& assumptions, expr_ref_vector& conseq);
void extract_fixed_consequences(unsigned& idx, obj_map<expr, expr*>& 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<expr, expr*>& var2val, expr_ref_vector& unfixed);
@ -1378,9 +1380,11 @@ 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);
void justify(literal lit, index_set& s);
void extract_cores(expr_ref_vector const& asms, vector<expr_ref_vector>& cores, unsigned& min_core_size);
@ -1426,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<expr_ref_vector>& mutexes);
lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_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();
@ -1462,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);
@ -1478,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<expr> & result);
@ -1500,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;

View file

@ -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;

View file

@ -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

View file

@ -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<expr, expr*> 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<expr, expr*>::iterator it = m_name2assertion.begin();
obj_map<expr, expr*>::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,11 +101,32 @@ namespace smt {
m_context.assert_expr(t);
}
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);
}
virtual void push_core() {
m_context.push();
}
virtual void pop_core(unsigned n) {
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);
}
@ -97,7 +138,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 +155,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<expr> 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<expr> 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 +192,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 +202,115 @@ 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<expr> & core, vector<func_decl_set> & assrtn_fds) {
assrtn_fds.resize(m_name2assertion.size());
obj_map<expr, expr*>::iterator ait = m_name2assertion.begin();
obj_map<expr, expr*>::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<expr> & core) {
ast_manager & m = get_manager();
expr_ref_vector new_core_literals(m);
func_decl_set pattern_fds;
vector<func_decl_set> assrtn_fds;
do {
new_core_literals.reset();
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);
}
if (!pattern_fds.empty()) {
if (assrtn_fds.empty())
compute_assrtn_fds(core, assrtn_fds);
obj_map<expr, expr*>::iterator ait = m_name2assertion.begin();
obj_map<expr, expr*>::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());
}
};
};

View file

@ -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;
}

View file

@ -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);

View file

@ -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"

View file

@ -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<polynomial_ref> 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<polynomial_ref> 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<polynomial_ref> 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.<x> = 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<polynomial_ref> 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<polynomial_ref> roots;
vector<polynomial::var> vars;
unsigned n = std::min(max, static_cast<unsigned>(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);
}