mirror of
https://github.com/Z3Prover/z3
synced 2025-08-08 12:11:23 +00:00
merge
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
13099b1590
87 changed files with 2187 additions and 4479 deletions
|
@ -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.
|
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 |
|
||||||
|
| ----------- | ----------- | ---------- | ---------- | ---------- | --- |
|
||||||
|
 |  |  |  |  | 
|
||||||
|
|
||||||
[1]: #building-z3-on-windows-using-visual-studio-command-prompt
|
[1]: #building-z3-on-windows-using-visual-studio-command-prompt
|
||||||
[2]: #building-z3-using-make-and-gccclang
|
[2]: #building-z3-using-make-and-gccclang
|
||||||
[3]: #building-z3-using-cmake
|
[3]: #building-z3-using-cmake
|
||||||
|
|
|
@ -3,7 +3,6 @@ z3_add_component(polynomial
|
||||||
algebraic_numbers.cpp
|
algebraic_numbers.cpp
|
||||||
polynomial_cache.cpp
|
polynomial_cache.cpp
|
||||||
polynomial.cpp
|
polynomial.cpp
|
||||||
polynomial_factorization.cpp
|
|
||||||
rpolynomial.cpp
|
rpolynomial.cpp
|
||||||
sexpr2upolynomial.cpp
|
sexpr2upolynomial.cpp
|
||||||
upolynomial.cpp
|
upolynomial.cpp
|
||||||
|
|
|
@ -2,7 +2,6 @@ z3_add_component(sat
|
||||||
SOURCES
|
SOURCES
|
||||||
dimacs.cpp
|
dimacs.cpp
|
||||||
sat_asymm_branch.cpp
|
sat_asymm_branch.cpp
|
||||||
sat_bceq.cpp
|
|
||||||
sat_clause.cpp
|
sat_clause.cpp
|
||||||
sat_clause_set.cpp
|
sat_clause_set.cpp
|
||||||
sat_clause_use_list.cpp
|
sat_clause_use_list.cpp
|
||||||
|
@ -16,7 +15,6 @@ z3_add_component(sat
|
||||||
sat_probing.cpp
|
sat_probing.cpp
|
||||||
sat_scc.cpp
|
sat_scc.cpp
|
||||||
sat_simplifier.cpp
|
sat_simplifier.cpp
|
||||||
sat_sls.cpp
|
|
||||||
sat_solver.cpp
|
sat_solver.cpp
|
||||||
sat_watched.cpp
|
sat_watched.cpp
|
||||||
COMPONENT_DEPENDENCIES
|
COMPONENT_DEPENDENCIES
|
||||||
|
|
|
@ -43,6 +43,7 @@ z3_add_component(smt
|
||||||
smt_statistics.cpp
|
smt_statistics.cpp
|
||||||
smt_theory.cpp
|
smt_theory.cpp
|
||||||
smt_value_sort.cpp
|
smt_value_sort.cpp
|
||||||
|
smt2_extra_cmds.cpp
|
||||||
theory_arith.cpp
|
theory_arith.cpp
|
||||||
theory_array_base.cpp
|
theory_array_base.cpp
|
||||||
theory_array.cpp
|
theory_array.cpp
|
||||||
|
|
|
@ -82,7 +82,6 @@ add_executable(test-z3
|
||||||
pdr.cpp
|
pdr.cpp
|
||||||
permutation.cpp
|
permutation.cpp
|
||||||
polynomial.cpp
|
polynomial.cpp
|
||||||
polynomial_factorization.cpp
|
|
||||||
polynorm.cpp
|
polynorm.cpp
|
||||||
prime_generator.cpp
|
prime_generator.cpp
|
||||||
proof_checker.cpp
|
proof_checker.cpp
|
||||||
|
|
|
@ -818,6 +818,7 @@ namespace test_mapi
|
||||||
BigIntCheck(ctx, ctx.MkReal("234234333/2"));
|
BigIntCheck(ctx, ctx.MkReal("234234333/2"));
|
||||||
|
|
||||||
|
|
||||||
|
#if !FRAMEWORK_LT_4
|
||||||
string bn = "1234567890987654321";
|
string bn = "1234567890987654321";
|
||||||
|
|
||||||
if (ctx.MkInt(bn).BigInteger.ToString() != bn)
|
if (ctx.MkInt(bn).BigInteger.ToString() != bn)
|
||||||
|
@ -828,6 +829,7 @@ namespace test_mapi
|
||||||
|
|
||||||
if (ctx.MkBV(bn, 32).BigInteger.ToString() == bn)
|
if (ctx.MkBV(bn, 32).BigInteger.ToString() == bn)
|
||||||
throw new TestFailedException();
|
throw new TestFailedException();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Error handling test.
|
// Error handling test.
|
||||||
try
|
try
|
||||||
|
@ -1094,8 +1096,10 @@ namespace test_mapi
|
||||||
|
|
||||||
static void BigIntCheck(Context ctx, RatNum r)
|
static void BigIntCheck(Context ctx, RatNum r)
|
||||||
{
|
{
|
||||||
|
#if !FRAMEWORK_LT_4
|
||||||
Console.WriteLine("Num: " + r.BigIntNumerator);
|
Console.WriteLine("Num: " + r.BigIntNumerator);
|
||||||
Console.WriteLine("Den: " + r.BigIntDenominator);
|
Console.WriteLine("Den: " + r.BigIntDenominator);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -22,6 +22,7 @@ def main(args):
|
||||||
dest="java_package_name",
|
dest="java_package_name",
|
||||||
default=None,
|
default=None,
|
||||||
help="Name to give the Java package (e.g. ``com.microsoft.z3``).")
|
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)
|
pargs = parser.parse_args(args)
|
||||||
|
|
||||||
if not mk_genfile_common.check_files_exist(pargs.api_files):
|
if not mk_genfile_common.check_files_exist(pargs.api_files):
|
||||||
|
@ -60,6 +61,15 @@ def main(args):
|
||||||
logging.info('Generated "{}"'.format(generated_file))
|
logging.info('Generated "{}"'.format(generated_file))
|
||||||
count += 1
|
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:
|
if count == 0:
|
||||||
logging.info('No files generated. You need to specific an output directory'
|
logging.info('No files generated. You need to specific an output directory'
|
||||||
' for the relevant langauge bindings')
|
' for the relevant langauge bindings')
|
||||||
|
|
|
@ -376,6 +376,180 @@ def mk_z3consts_java_internal(api_files, package_name, output_dir):
|
||||||
api.close()
|
api.close()
|
||||||
return generated_enumeration_files
|
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
|
# Functions for generating a "module definition file" for MSVC
|
||||||
|
|
|
@ -27,6 +27,7 @@ DOTNET_KEY_FILE=None
|
||||||
JAVA_ENABLED=True
|
JAVA_ENABLED=True
|
||||||
GIT_HASH=False
|
GIT_HASH=False
|
||||||
PYTHON_ENABLED=True
|
PYTHON_ENABLED=True
|
||||||
|
MAKEJOBS=getenv("MAKEJOBS", '8')
|
||||||
|
|
||||||
def set_verbose(flag):
|
def set_verbose(flag):
|
||||||
global VERBOSE
|
global VERBOSE
|
||||||
|
@ -139,7 +140,7 @@ class cd:
|
||||||
def mk_z3():
|
def mk_z3():
|
||||||
with cd(BUILD_DIR):
|
with cd(BUILD_DIR):
|
||||||
try:
|
try:
|
||||||
return subprocess.call(['make', '-j', '8'])
|
return subprocess.call(['make', '-j', MAKEJOBS])
|
||||||
except:
|
except:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
|
|
@ -2442,7 +2442,7 @@ def mk_config():
|
||||||
CXXFLAGS = '%s -O3 -D _EXTERNAL_RELEASE -fomit-frame-pointer' % CXXFLAGS
|
CXXFLAGS = '%s -O3 -D _EXTERNAL_RELEASE -fomit-frame-pointer' % CXXFLAGS
|
||||||
if is_CXX_clangpp():
|
if is_CXX_clangpp():
|
||||||
CXXFLAGS = '%s -Wno-unknown-pragmas -Wno-overloaded-virtual -Wno-unused-value' % CXXFLAGS
|
CXXFLAGS = '%s -Wno-unknown-pragmas -Wno-overloaded-virtual -Wno-unused-value' % CXXFLAGS
|
||||||
sysname = os.uname()[0]
|
sysname, _, _, _, machine = os.uname()
|
||||||
if sysname == 'Darwin':
|
if sysname == 'Darwin':
|
||||||
SO_EXT = '.dylib'
|
SO_EXT = '.dylib'
|
||||||
SLIBFLAGS = '-dynamiclib'
|
SLIBFLAGS = '-dynamiclib'
|
||||||
|
@ -2493,6 +2493,8 @@ def mk_config():
|
||||||
# and to make it create an import library.
|
# and to make it create an import library.
|
||||||
SLIBEXTRAFLAGS = '%s -static-libgcc -static-libstdc++ -Wl,--out-implib,libz3.dll.a' % SLIBEXTRAFLAGS
|
SLIBEXTRAFLAGS = '%s -static-libgcc -static-libstdc++ -Wl,--out-implib,libz3.dll.a' % SLIBEXTRAFLAGS
|
||||||
LDFLAGS = '%s -static-libgcc -static-libstdc++' % LDFLAGS
|
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('PREFIX=%s\n' % PREFIX)
|
||||||
config.write('CC=%s\n' % CC)
|
config.write('CC=%s\n' % CC)
|
||||||
|
@ -2870,7 +2872,8 @@ def mk_bindings(api_files):
|
||||||
dotnet_output_dir=dotnet_output_dir,
|
dotnet_output_dir=dotnet_output_dir,
|
||||||
java_output_dir=java_output_dir,
|
java_output_dir=java_output_dir,
|
||||||
java_package_name=java_package_name,
|
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()
|
cp_z3py_to_build()
|
||||||
if is_ml_enabled():
|
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
|
# Extract enumeration types from z3_api.h, and add ML definitions
|
||||||
def mk_z3consts_ml(api_files):
|
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)
|
ml = get_component(ML_COMPONENT)
|
||||||
|
full_path_api_files = []
|
||||||
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')
|
|
||||||
for api_file in api_files:
|
for api_file in api_files:
|
||||||
api_file_c = ml.find_file(api_file, ml.name)
|
api_file_c = ml.find_file(api_file, ml.name)
|
||||||
api_file = os.path.join(api_file_c.src_dir, api_file)
|
api_file = os.path.join(api_file_c.src_dir, api_file)
|
||||||
|
full_path_api_files.append(api_file)
|
||||||
api = open(api_file, 'r')
|
generated_file = mk_genfile_common.mk_z3consts_ml_internal(
|
||||||
|
full_path_api_files,
|
||||||
SEARCHING = 0
|
ml.src_dir)
|
||||||
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()
|
|
||||||
if VERBOSE:
|
if VERBOSE:
|
||||||
print ('Generated "%s/z3enums.ml"' % ('%s' % gendir))
|
print ('Generated "%s"' % generated_file)
|
||||||
# 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))
|
|
||||||
|
|
||||||
def mk_gui_str(id):
|
def mk_gui_str(id):
|
||||||
return '4D2F40D8-E5F9-473B-B548-%012d' % id
|
return '4D2F40D8-E5F9-473B-B548-%012d' % id
|
||||||
|
|
|
@ -29,6 +29,9 @@ DOTNET_KEY_FILE=None
|
||||||
JAVA_ENABLED=True
|
JAVA_ENABLED=True
|
||||||
GIT_HASH=False
|
GIT_HASH=False
|
||||||
PYTHON_ENABLED=True
|
PYTHON_ENABLED=True
|
||||||
|
X86ONLY=False
|
||||||
|
X64ONLY=False
|
||||||
|
MAKEJOBS=getenv("MAKEJOBS", "24")
|
||||||
|
|
||||||
def set_verbose(flag):
|
def set_verbose(flag):
|
||||||
global VERBOSE
|
global VERBOSE
|
||||||
|
@ -63,11 +66,13 @@ def display_help():
|
||||||
print(" --nojava do not include Java bindings in the binary distribution files.")
|
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(" --nopython do not include Python bindings in the binary distribution files.")
|
||||||
print(" --githash include git hash in the Zip file.")
|
print(" --githash include git hash in the Zip file.")
|
||||||
|
print(" --x86-only x86 dist only.")
|
||||||
|
print(" --x64-only x64 dist only.")
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
# Parse configuration option for mk_make script
|
# Parse configuration option for mk_make script
|
||||||
def parse_options():
|
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
|
path = BUILD_DIR
|
||||||
options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:hsf', ['build=',
|
options, remainder = getopt.gnu_getopt(sys.argv[1:], 'b:hsf', ['build=',
|
||||||
'help',
|
'help',
|
||||||
|
@ -77,7 +82,9 @@ def parse_options():
|
||||||
'nodotnet',
|
'nodotnet',
|
||||||
'dotnet-key=',
|
'dotnet-key=',
|
||||||
'githash',
|
'githash',
|
||||||
'nopython'
|
'nopython',
|
||||||
|
'x86-only',
|
||||||
|
'x64-only'
|
||||||
])
|
])
|
||||||
for opt, arg in options:
|
for opt, arg in options:
|
||||||
if opt in ('-b', '--build'):
|
if opt in ('-b', '--build'):
|
||||||
|
@ -100,6 +107,10 @@ def parse_options():
|
||||||
JAVA_ENABLED = False
|
JAVA_ENABLED = False
|
||||||
elif opt == '--githash':
|
elif opt == '--githash':
|
||||||
GIT_HASH = True
|
GIT_HASH = True
|
||||||
|
elif opt == '--x86-only' and not X64ONLY:
|
||||||
|
X86ONLY = True
|
||||||
|
elif opt == '--x64-only' and not X86ONLY:
|
||||||
|
X64ONLY = True
|
||||||
else:
|
else:
|
||||||
raise MKException("Invalid command line option '%s'" % opt)
|
raise MKException("Invalid command line option '%s'" % opt)
|
||||||
set_build_dir(path)
|
set_build_dir(path)
|
||||||
|
@ -111,7 +122,8 @@ def check_build_dir(path):
|
||||||
# Create a build directory using mk_make.py
|
# Create a build directory using mk_make.py
|
||||||
def mk_build_dir(path, x64):
|
def mk_build_dir(path, x64):
|
||||||
if not check_build_dir(path) or FORCE_MK:
|
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:
|
if DOTNET_ENABLED:
|
||||||
opts.append('--dotnet')
|
opts.append('--dotnet')
|
||||||
if not DOTNET_KEY_FILE is None:
|
if not DOTNET_KEY_FILE is None:
|
||||||
|
@ -160,7 +172,7 @@ def exec_cmds(cmds):
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# Compile Z3 (if x64 == True, then it builds it in x64 mode).
|
# Compile Z3 (if x64 == True, then it builds it in x64 mode).
|
||||||
def mk_z3_core(x64):
|
def mk_z3(x64):
|
||||||
cmds = []
|
cmds = []
|
||||||
if x64:
|
if x64:
|
||||||
cmds.append('call "%VCINSTALLDIR%vcvarsall.bat" amd64')
|
cmds.append('call "%VCINSTALLDIR%vcvarsall.bat" amd64')
|
||||||
|
@ -172,9 +184,9 @@ def mk_z3_core(x64):
|
||||||
if exec_cmds(cmds) != 0:
|
if exec_cmds(cmds) != 0:
|
||||||
raise MKException("Failed to make z3, x64: %s" % x64)
|
raise MKException("Failed to make z3, x64: %s" % x64)
|
||||||
|
|
||||||
def mk_z3():
|
def mk_z3s():
|
||||||
mk_z3_core(False)
|
mk_z3(False)
|
||||||
mk_z3_core(True)
|
mk_z3(True)
|
||||||
|
|
||||||
def get_z3_name(x64):
|
def get_z3_name(x64):
|
||||||
major, minor, build, revision = get_version()
|
major, minor, build, revision = get_version()
|
||||||
|
@ -187,7 +199,7 @@ def get_z3_name(x64):
|
||||||
else:
|
else:
|
||||||
return 'z3-%s.%s.%s-%s-win' % (major, minor, build, platform)
|
return 'z3-%s.%s.%s-%s-win' % (major, minor, build, platform)
|
||||||
|
|
||||||
def mk_dist_dir_core(x64):
|
def mk_dist_dir(x64):
|
||||||
if x64:
|
if x64:
|
||||||
platform = "x64"
|
platform = "x64"
|
||||||
build_path = BUILD_X64_DIR
|
build_path = BUILD_X64_DIR
|
||||||
|
@ -204,14 +216,14 @@ def mk_dist_dir_core(x64):
|
||||||
if is_verbose():
|
if is_verbose():
|
||||||
print("Generated %s distribution folder at '%s'" % (platform, dist_path))
|
print("Generated %s distribution folder at '%s'" % (platform, dist_path))
|
||||||
|
|
||||||
def mk_dist_dir():
|
def mk_dist_dirs():
|
||||||
mk_dist_dir_core(False)
|
mk_dist_dir(False)
|
||||||
mk_dist_dir_core(True)
|
mk_dist_dir(True)
|
||||||
|
|
||||||
def get_dist_path(x64):
|
def get_dist_path(x64):
|
||||||
return get_z3_name(x64)
|
return get_z3_name(x64)
|
||||||
|
|
||||||
def mk_zip_core(x64):
|
def mk_zip(x64):
|
||||||
dist_path = get_dist_path(x64)
|
dist_path = get_dist_path(x64)
|
||||||
old = os.getcwd()
|
old = os.getcwd()
|
||||||
try:
|
try:
|
||||||
|
@ -228,9 +240,9 @@ def mk_zip_core(x64):
|
||||||
os.chdir(old)
|
os.chdir(old)
|
||||||
|
|
||||||
# Create a zip file for each platform
|
# Create a zip file for each platform
|
||||||
def mk_zip():
|
def mk_zips():
|
||||||
mk_zip_core(False)
|
mk_zip(False)
|
||||||
mk_zip_core(True)
|
mk_zip(True)
|
||||||
|
|
||||||
|
|
||||||
VS_RUNTIME_PATS = [re.compile('vcomp.*\.dll'),
|
VS_RUNTIME_PATS = [re.compile('vcomp.*\.dll'),
|
||||||
|
@ -238,7 +250,7 @@ VS_RUNTIME_PATS = [re.compile('vcomp.*\.dll'),
|
||||||
re.compile('msvcr.*\.dll')]
|
re.compile('msvcr.*\.dll')]
|
||||||
|
|
||||||
# Copy Visual Studio Runtime libraries
|
# Copy Visual Studio Runtime libraries
|
||||||
def cp_vs_runtime_core(x64):
|
def cp_vs_runtime(x64):
|
||||||
if x64:
|
if x64:
|
||||||
platform = "x64"
|
platform = "x64"
|
||||||
|
|
||||||
|
@ -262,27 +274,49 @@ def cp_vs_runtime_core(x64):
|
||||||
if is_verbose():
|
if is_verbose():
|
||||||
print("Copied '%s' to '%s'" % (f, bin_dist_path))
|
print("Copied '%s' to '%s'" % (f, bin_dist_path))
|
||||||
|
|
||||||
def cp_vs_runtime():
|
def cp_vs_runtimes():
|
||||||
cp_vs_runtime_core(True)
|
cp_vs_runtime(True)
|
||||||
cp_vs_runtime_core(False)
|
cp_vs_runtime(False)
|
||||||
|
|
||||||
def cp_license():
|
def cp_license(x64):
|
||||||
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(x64)))
|
||||||
shutil.copy("LICENSE.txt", os.path.join(DIST_DIR, get_dist_path(False)))
|
|
||||||
|
def cp_licenses():
|
||||||
|
cp_license(True)
|
||||||
|
cp_license(False)
|
||||||
|
|
||||||
# Entry point
|
# Entry point
|
||||||
def main():
|
def main():
|
||||||
if os.name != 'nt':
|
if os.name != 'nt':
|
||||||
raise MKException("This script is for Windows only")
|
raise MKException("This script is for Windows only")
|
||||||
|
|
||||||
parse_options()
|
parse_options()
|
||||||
check_vc_cmd_prompt()
|
check_vc_cmd_prompt()
|
||||||
mk_build_dirs()
|
|
||||||
mk_z3()
|
if X86ONLY:
|
||||||
init_project_def()
|
mk_build_dir(BUILD_X86_DIR, False)
|
||||||
mk_dist_dir()
|
mk_z3(False)
|
||||||
cp_license()
|
init_project_def()
|
||||||
cp_vs_runtime()
|
mk_dist_dir(False)
|
||||||
mk_zip()
|
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()
|
main()
|
||||||
|
|
||||||
|
|
|
@ -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 delegate void Z3_error_handler(Z3_context c, Z3_error_code e);\n\n')
|
||||||
dotnet.write(' public class LIB\n')
|
dotnet.write(' public class LIB\n')
|
||||||
dotnet.write(' {\n')
|
dotnet.write(' {\n')
|
||||||
dotnet.write(' const string Z3_DLL_NAME = \"libz3.dll\";\n'
|
dotnet.write(' const string Z3_DLL_NAME = \"libz3\";\n'
|
||||||
' \n')
|
' \n')
|
||||||
dotnet.write(' [DllImport(Z3_DLL_NAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\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')
|
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)
|
alloc_str = '%s = caml_alloc_custom(&%s, sizeof(%s), 0, 1); ' % (lhs, pops, pts)
|
||||||
return alloc_str + ml_set_wrap(t, lhs, rhs)
|
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
|
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 = open(ml_nativef, 'w')
|
||||||
ml_native.write('(* Automatically generated file *)\n\n')
|
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:
|
for s in ml_pref:
|
||||||
ml_native.write(s);
|
ml_native.write(s);
|
||||||
ml_pref.close()
|
ml_pref.close()
|
||||||
|
@ -1250,14 +1250,14 @@ def mk_ml(ml_dir):
|
||||||
if mk_util.is_verbose():
|
if mk_util.is_verbose():
|
||||||
print ('Generated "%s"' % ml_nativef)
|
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
|
def mk_z3native_stubs_c(ml_src_dir, ml_output_dir): # C interface
|
||||||
ml_wrapperf = os.path.join(ml_dir, 'z3native_stubs.c')
|
ml_wrapperf = os.path.join(ml_output_dir, 'z3native_stubs.c')
|
||||||
ml_wrapper = open(ml_wrapperf, 'w')
|
ml_wrapper = open(ml_wrapperf, 'w')
|
||||||
ml_wrapper.write('// Automatically generated file\n\n')
|
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:
|
for s in ml_pref:
|
||||||
ml_wrapper.write(s);
|
ml_wrapper.write(s);
|
||||||
ml_pref.close()
|
ml_pref.close()
|
||||||
|
@ -1574,6 +1574,7 @@ def write_log_h_preamble(log_h):
|
||||||
log_h.write('#define _Z3_UNUSED\n')
|
log_h.write('#define _Z3_UNUSED\n')
|
||||||
log_h.write('#endif\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 std::ostream * g_z3_log;\n')
|
||||||
log_h.write('extern bool g_z3_log_enabled;\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')
|
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,
|
dotnet_output_dir=None,
|
||||||
java_output_dir=None,
|
java_output_dir=None,
|
||||||
java_package_name=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
|
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``
|
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)
|
mk_java(java_output_dir, java_package_name)
|
||||||
|
|
||||||
if ml_output_dir:
|
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):
|
def main(args):
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
@ -1768,6 +1771,10 @@ def main(args):
|
||||||
dest="java_package_name",
|
dest="java_package_name",
|
||||||
default=None,
|
default=None,
|
||||||
help="Name to give the Java package (e.g. ``com.microsoft.z3``).")
|
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",
|
parser.add_argument("--ml-output-dir",
|
||||||
dest="ml_output_dir",
|
dest="ml_output_dir",
|
||||||
default=None,
|
default=None,
|
||||||
|
@ -1779,6 +1786,11 @@ def main(args):
|
||||||
logging.error('--java-package-name must be specified')
|
logging.error('--java-package-name must be specified')
|
||||||
return 1
|
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:
|
for api_file in pargs.api_files:
|
||||||
if not os.path.exists(api_file):
|
if not os.path.exists(api_file):
|
||||||
logging.error('"{}" does not exist'.format(api_file))
|
logging.error('"{}" does not exist'.format(api_file))
|
||||||
|
@ -1790,7 +1802,8 @@ def main(args):
|
||||||
dotnet_output_dir=pargs.dotnet_output_dir,
|
dotnet_output_dir=pargs.dotnet_output_dir,
|
||||||
java_output_dir=pargs.java_output_dir,
|
java_output_dir=pargs.java_output_dir,
|
||||||
java_package_name=pargs.java_package_name,
|
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
|
return 0
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -17,7 +17,6 @@ Author:
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
#include"api_context.h"
|
#include"api_context.h"
|
||||||
|
|
|
@ -15,7 +15,6 @@ Author:
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
#include"api_context.h"
|
#include"api_context.h"
|
||||||
|
|
|
@ -15,7 +15,6 @@ Author:
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
#include"api_context.h"
|
#include"api_context.h"
|
||||||
|
|
|
@ -1063,6 +1063,7 @@ extern "C" {
|
||||||
case OP_BV2INT: return Z3_OP_BV2INT;
|
case OP_BV2INT: return Z3_OP_BV2INT;
|
||||||
case OP_CARRY: return Z3_OP_CARRY;
|
case OP_CARRY: return Z3_OP_CARRY;
|
||||||
case OP_XOR3: return Z3_OP_XOR3;
|
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_BSMUL_NO_OVFL: return Z3_OP_BSMUL_NO_OVFL;
|
||||||
case OP_BUMUL_NO_OVFL: return Z3_OP_BUMUL_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;
|
||||||
|
@ -1210,7 +1211,9 @@ extern "C" {
|
||||||
switch(_d->get_decl_kind()) {
|
switch(_d->get_decl_kind()) {
|
||||||
case OP_PB_LE: return Z3_OP_PB_LE;
|
case OP_PB_LE: return Z3_OP_PB_LE;
|
||||||
case OP_PB_GE: return Z3_OP_PB_GE;
|
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_MOST_K: return Z3_OP_PB_AT_MOST;
|
||||||
|
case OP_AT_LEAST_K: return Z3_OP_PB_AT_LEAST;
|
||||||
default: return Z3_OP_INTERNAL;
|
default: return Z3_OP_INTERNAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ Author:
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
#include"api_context.h"
|
#include"api_context.h"
|
||||||
|
|
|
@ -290,8 +290,8 @@ extern "C" {
|
||||||
r = to_fixedpoint_ref(d)->ctx().query(to_expr(q));
|
r = to_fixedpoint_ref(d)->ctx().query(to_expr(q));
|
||||||
}
|
}
|
||||||
catch (z3_exception& ex) {
|
catch (z3_exception& ex) {
|
||||||
mk_c(c)->handle_exception(ex);
|
|
||||||
r = l_undef;
|
r = l_undef;
|
||||||
|
mk_c(c)->handle_exception(ex);
|
||||||
}
|
}
|
||||||
to_fixedpoint_ref(d)->ctx().cleanup();
|
to_fixedpoint_ref(d)->ctx().cleanup();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ Author:
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
#include"api_context.h"
|
#include"api_context.h"
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include<sstream>
|
#include<sstream>
|
||||||
#include<vector>
|
#include<vector>
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
|
|
|
@ -15,7 +15,6 @@ Author:
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include<fstream>
|
#include<fstream>
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
|
|
|
@ -15,7 +15,6 @@ Author:
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
#include"api_context.h"
|
#include"api_context.h"
|
||||||
|
@ -38,6 +37,19 @@ extern "C" {
|
||||||
Z3_CATCH_RETURN(0);
|
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[],
|
Z3_ast const args[], int _coeffs[],
|
||||||
|
@ -57,6 +69,24 @@ extern "C" {
|
||||||
Z3_CATCH_RETURN(0);
|
Z3_CATCH_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Z3_ast Z3_API Z3_mk_pbge(Z3_context c, unsigned num_args,
|
||||||
|
Z3_ast const args[], int _coeffs[],
|
||||||
|
int k) {
|
||||||
|
Z3_TRY;
|
||||||
|
LOG_Z3_mk_pble(c, num_args, args, _coeffs, k);
|
||||||
|
RESET_ERROR_CODE();
|
||||||
|
pb_util util(mk_c(c)->m());
|
||||||
|
vector<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 Z3_API Z3_mk_pbeq(Z3_context c, unsigned num_args,
|
||||||
Z3_ast const args[], int _coeffs[],
|
Z3_ast const args[], int _coeffs[],
|
||||||
int k) {
|
int k) {
|
||||||
|
|
|
@ -16,7 +16,6 @@ Author:
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
#include"api_context.h"
|
#include"api_context.h"
|
||||||
|
|
|
@ -15,7 +15,6 @@ Author:
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
#include"api_context.h"
|
#include"api_context.h"
|
||||||
|
|
|
@ -16,7 +16,6 @@ Author:
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
--*/
|
--*/
|
||||||
#include<iostream>
|
|
||||||
#include"z3.h"
|
#include"z3.h"
|
||||||
#include"api_log_macros.h"
|
#include"api_log_macros.h"
|
||||||
#include"api_context.h"
|
#include"api_context.h"
|
||||||
|
|
|
@ -132,16 +132,19 @@ namespace z3 {
|
||||||
\brief A Context manages all other Z3 objects, global configuration options, etc.
|
\brief A Context manages all other Z3 objects, global configuration options, etc.
|
||||||
*/
|
*/
|
||||||
class context {
|
class context {
|
||||||
|
bool m_enable_exceptions;
|
||||||
Z3_context m_ctx;
|
Z3_context m_ctx;
|
||||||
static void error_handler(Z3_context /*c*/, Z3_error_code /*e*/) { /* do nothing */ }
|
static void error_handler(Z3_context /*c*/, Z3_error_code /*e*/) { /* do nothing */ }
|
||||||
void init(config & c) {
|
void init(config & c) {
|
||||||
m_ctx = Z3_mk_context_rc(c);
|
m_ctx = Z3_mk_context_rc(c);
|
||||||
|
m_enable_exceptions = true;
|
||||||
Z3_set_error_handler(m_ctx, error_handler);
|
Z3_set_error_handler(m_ctx, error_handler);
|
||||||
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_interp(config & c) {
|
void init_interp(config & c) {
|
||||||
m_ctx = Z3_mk_interpolation_context(c);
|
m_ctx = Z3_mk_interpolation_context(c);
|
||||||
|
m_enable_exceptions = true;
|
||||||
Z3_set_error_handler(m_ctx, error_handler);
|
Z3_set_error_handler(m_ctx, error_handler);
|
||||||
Z3_set_ast_print_mode(m_ctx, Z3_PRINT_SMTLIB2_COMPLIANT);
|
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.
|
\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);
|
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));
|
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.
|
\brief Update global parameter \c param with string \c value.
|
||||||
*/
|
*/
|
||||||
|
@ -330,7 +345,7 @@ namespace z3 {
|
||||||
object(context & c):m_ctx(&c) {}
|
object(context & c):m_ctx(&c) {}
|
||||||
object(object const & s):m_ctx(s.m_ctx) {}
|
object(object const & s):m_ctx(s.m_ctx) {}
|
||||||
context & ctx() const { return *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);
|
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); }
|
inline void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); }
|
||||||
|
@ -673,11 +688,17 @@ namespace z3 {
|
||||||
\brief Return int value of numeral, throw if result cannot fit in
|
\brief Return int value of numeral, throw if result cannot fit in
|
||||||
machine int
|
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()
|
\pre is_numeral()
|
||||||
*/
|
*/
|
||||||
int get_numeral_int() const {
|
int get_numeral_int() const {
|
||||||
int result;
|
int result = 0;
|
||||||
if (!is_numeral_i(result)) {
|
if (!is_numeral_i(result)) {
|
||||||
|
assert(ctx().enable_exceptions());
|
||||||
|
if (!ctx().enable_exceptions()) return 0;
|
||||||
throw exception("numeral does not fit in machine int");
|
throw exception("numeral does not fit in machine int");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -687,12 +708,17 @@ namespace z3 {
|
||||||
\brief Return uint value of numeral, throw if result cannot fit in
|
\brief Return uint value of numeral, throw if result cannot fit in
|
||||||
machine uint
|
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()
|
\pre is_numeral()
|
||||||
*/
|
*/
|
||||||
unsigned get_numeral_uint() const {
|
unsigned get_numeral_uint() const {
|
||||||
assert(is_numeral());
|
assert(is_numeral());
|
||||||
unsigned result;
|
unsigned result = 0;
|
||||||
if (!is_numeral_u(result)) {
|
if (!is_numeral_u(result)) {
|
||||||
|
assert(ctx().enable_exceptions());
|
||||||
|
if (!ctx().enable_exceptions()) return 0;
|
||||||
throw exception("numeral does not fit in machine uint");
|
throw exception("numeral does not fit in machine uint");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -706,8 +732,10 @@ namespace z3 {
|
||||||
*/
|
*/
|
||||||
__int64 get_numeral_int64() const {
|
__int64 get_numeral_int64() const {
|
||||||
assert(is_numeral());
|
assert(is_numeral());
|
||||||
__int64 result;
|
__int64 result = 0;
|
||||||
if (!is_numeral_i64(result)) {
|
if (!is_numeral_i64(result)) {
|
||||||
|
assert(ctx().enable_exceptions());
|
||||||
|
if (!ctx().enable_exceptions()) return 0;
|
||||||
throw exception("numeral does not fit in machine __int64");
|
throw exception("numeral does not fit in machine __int64");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -721,8 +749,10 @@ namespace z3 {
|
||||||
*/
|
*/
|
||||||
__uint64 get_numeral_uint64() const {
|
__uint64 get_numeral_uint64() const {
|
||||||
assert(is_numeral());
|
assert(is_numeral());
|
||||||
__uint64 result;
|
__uint64 result = 0;
|
||||||
if (!is_numeral_u64(result)) {
|
if (!is_numeral_u64(result)) {
|
||||||
|
assert(ctx().enable_exceptions());
|
||||||
|
if (!ctx().enable_exceptions()) return 0;
|
||||||
throw exception("numeral does not fit in machine __uint64");
|
throw exception("numeral does not fit in machine __uint64");
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1615,7 +1645,7 @@ namespace z3 {
|
||||||
Z3_ast r = 0;
|
Z3_ast r = 0;
|
||||||
Z3_bool status = Z3_model_eval(ctx(), m_model, n, model_completion, &r);
|
Z3_bool status = Z3_model_eval(ctx(), m_model, n, model_completion, &r);
|
||||||
check_error();
|
check_error();
|
||||||
if (status == Z3_FALSE)
|
if (status == Z3_FALSE && ctx().enable_exceptions())
|
||||||
throw exception("failed to evaluate expression");
|
throw exception("failed to evaluate expression");
|
||||||
return expr(ctx(), r);
|
return expr(ctx(), r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2692,6 +2692,18 @@ namespace Microsoft.Z3
|
||||||
AST.ArrayToNative(args), k));
|
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>
|
/// <summary>
|
||||||
/// Create a pseudo-Boolean less-or-equal constraint.
|
/// Create a pseudo-Boolean less-or-equal constraint.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -2707,6 +2719,20 @@ namespace Microsoft.Z3
|
||||||
coeffs, k));
|
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>
|
/// <summary>
|
||||||
/// Create a pseudo-Boolean equal constraint.
|
/// Create a pseudo-Boolean equal constraint.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -18,6 +18,7 @@ Notes:
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
|
|
||||||
|
@ -126,6 +127,14 @@ namespace Microsoft.Z3
|
||||||
Assert(constraints);
|
Assert(constraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Alias for Assert.
|
||||||
|
/// </summary>
|
||||||
|
public void Add(IEnumerable<BoolExpr> constraints)
|
||||||
|
{
|
||||||
|
Assert(constraints.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Assert multiple constraints into the solver, and track them (in the unsat) core
|
/// Assert multiple constraints into the solver, and track them (in the unsat) core
|
||||||
/// using the Boolean constants in ps.
|
/// using the Boolean constants in ps.
|
||||||
|
|
|
@ -44,15 +44,21 @@ namespace System.Diagnostics.Contracts
|
||||||
|
|
||||||
public static class Contract
|
public static class Contract
|
||||||
{
|
{
|
||||||
|
[Conditional("false")]
|
||||||
public static void Ensures(bool b) { }
|
public static void Ensures(bool b) { }
|
||||||
|
[Conditional("false")]
|
||||||
public static void Requires(bool b) { }
|
public static void Requires(bool b) { }
|
||||||
|
[Conditional("false")]
|
||||||
public static void Assume(bool b, string msg) { }
|
public static void Assume(bool b, string msg) { }
|
||||||
|
[Conditional("false")]
|
||||||
public static void Assert(bool b) { }
|
public static void Assert(bool b) { }
|
||||||
public static bool ForAll(bool b) { return true; }
|
public static bool ForAll(bool b) { return true; }
|
||||||
public static bool ForAll(Object c, Func<Object, bool> p) { 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; }
|
public static bool ForAll(int from, int to, Predicate<int> p) { return true; }
|
||||||
|
[Conditional("false")]
|
||||||
public static void Invariant(bool b) { }
|
public static void Invariant(bool b) { }
|
||||||
public static T[] Result<T>() { return new T[1]; }
|
public static T[] Result<T>() { return new T[1]; }
|
||||||
|
[Conditional("false")]
|
||||||
public static void EndContractBlock() { }
|
public static void EndContractBlock() { }
|
||||||
public static T ValueAtReturn<T>(out T v) { T[] t = new T[1]; v = t[0]; return v; }
|
public static T ValueAtReturn<T>(out T v) { T[] t = new T[1]; v = t[0]; return v; }
|
||||||
}
|
}
|
||||||
|
|
6
src/api/dotnet/dotnet35/Example/App.config
Normal file
6
src/api/dotnet/dotnet35/Example/App.config
Normal 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>
|
78
src/api/dotnet/dotnet35/Example/Example.csproj
Normal file
78
src/api/dotnet/dotnet35/Example/Example.csproj
Normal 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>
|
36
src/api/dotnet/dotnet35/Example/Properties/AssemblyInfo.cs
Normal file
36
src/api/dotnet/dotnet35/Example/Properties/AssemblyInfo.cs
Normal 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")]
|
347
src/api/dotnet/dotnet35/Microsoft.Z3.NET35.csproj
Normal file
347
src/api/dotnet/dotnet35/Microsoft.Z3.NET35.csproj
Normal 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>
|
48
src/api/dotnet/dotnet35/Microsoft.Z3.NET35.sln
Normal file
48
src/api/dotnet/dotnet35/Microsoft.Z3.NET35.sln
Normal 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
|
38
src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs
Normal file
38
src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs
Normal 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")]
|
38
src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs.in
Normal file
38
src/api/dotnet/dotnet35/Properties/AssemblyInfo.cs.in
Normal 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@")]
|
|
@ -6,4 +6,5 @@ In the project properties of Microsoft.Z3.csproj:
|
||||||
- Under 'Application': Change Target framework to .NET Framework 3.5
|
- Under 'Application': Change Target framework to .NET Framework 3.5
|
||||||
- Under 'Build': Add FRAMEWORK_LT_4 to the condidional compilation symbols
|
- Under 'Build': Add FRAMEWORK_LT_4 to the condidional compilation symbols
|
||||||
- Remove the reference to System.Numerics
|
- 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
|
4
src/api/dotnet/dotnet35/packages.config
Normal file
4
src/api/dotnet/dotnet35/packages.config
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Code.Contract" version="1.0.0" targetFramework="net35" />
|
||||||
|
</packages>
|
|
@ -7648,11 +7648,6 @@ def AtLeast(*args):
|
||||||
>>> a, b, c = Bools('a b c')
|
>>> a, b, c = Bools('a b c')
|
||||||
>>> f = AtLeast(a, b, c, 2)
|
>>> 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)
|
args = _get_args(args)
|
||||||
if __debug__:
|
if __debug__:
|
||||||
_z3_assert(len(args) > 1, "Non empty list of arguments expected")
|
_z3_assert(len(args) > 1, "Non empty list of arguments expected")
|
||||||
|
@ -7660,10 +7655,25 @@ def AtLeast(*args):
|
||||||
if __debug__:
|
if __debug__:
|
||||||
_z3_assert(ctx is not None, "At least one of the arguments must be a Z3 expression")
|
_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 = _coerce_expr_list(args[:-1], ctx)
|
||||||
args1 = [ mk_not(a) for a in args1 ]
|
k = args[-1]
|
||||||
k = len(args1) - args[-1]
|
|
||||||
_args, sz = _to_ast_array(args1)
|
_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):
|
def PbLe(args, k):
|
||||||
"""Create a Pseudo-Boolean inequality k constraint.
|
"""Create a Pseudo-Boolean inequality k constraint.
|
||||||
|
@ -7671,38 +7681,25 @@ def PbLe(args, k):
|
||||||
>>> a, b, c = Bools('a b c')
|
>>> a, b, c = Bools('a b c')
|
||||||
>>> f = PbLe(((a,1),(b,3),(c,2)), 3)
|
>>> f = PbLe(((a,1),(b,3),(c,2)), 3)
|
||||||
"""
|
"""
|
||||||
args = _get_args(args)
|
ctx, sz, _args, _coeffs = _pb_args_coeffs(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 BoolRef(Z3_mk_pble(ctx.ref(), sz, _args, _coeffs, k), ctx)
|
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):
|
def PbEq(args, k):
|
||||||
"""Create a Pseudo-Boolean inequality k constraint.
|
"""Create a Pseudo-Boolean inequality k constraint.
|
||||||
|
|
||||||
>>> a, b, c = Bools('a b c')
|
>>> a, b, c = Bools('a b c')
|
||||||
>>> f = PbEq(((a,1),(b,3),(c,2)), 3)
|
>>> f = PbEq(((a,1),(b,3),(c,2)), 3)
|
||||||
"""
|
"""
|
||||||
args = _get_args(args)
|
ctx, sz, _args, _coeffs = _pb_args_coeffs(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 BoolRef(Z3_mk_pbeq(ctx.ref(), sz, _args, _coeffs, k), ctx)
|
return BoolRef(Z3_mk_pbeq(ctx.ref(), sz, _args, _coeffs, k), ctx)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -855,6 +855,9 @@ typedef enum
|
||||||
- Z3_OP_PB_AT_MOST: Cardinality constraint.
|
- Z3_OP_PB_AT_MOST: Cardinality constraint.
|
||||||
E.g., x + y + z <= 2
|
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.
|
- Z3_OP_PB_LE: Generalized Pseudo-Boolean cardinality constraint.
|
||||||
Example 2*x + 3*y <= 4
|
Example 2*x + 3*y <= 4
|
||||||
|
|
||||||
|
@ -1060,6 +1063,7 @@ typedef enum {
|
||||||
Z3_OP_EXT_ROTATE_LEFT,
|
Z3_OP_EXT_ROTATE_LEFT,
|
||||||
Z3_OP_EXT_ROTATE_RIGHT,
|
Z3_OP_EXT_ROTATE_RIGHT,
|
||||||
|
|
||||||
|
Z3_OP_BIT2BOOL,
|
||||||
Z3_OP_INT2BV,
|
Z3_OP_INT2BV,
|
||||||
Z3_OP_BV2INT,
|
Z3_OP_BV2INT,
|
||||||
Z3_OP_CARRY,
|
Z3_OP_CARRY,
|
||||||
|
@ -1173,6 +1177,7 @@ typedef enum {
|
||||||
|
|
||||||
// Pseudo Booleans
|
// Pseudo Booleans
|
||||||
Z3_OP_PB_AT_MOST=0x900,
|
Z3_OP_PB_AT_MOST=0x900,
|
||||||
|
Z3_OP_PB_AT_LEAST,
|
||||||
Z3_OP_PB_LE,
|
Z3_OP_PB_LE,
|
||||||
Z3_OP_PB_GE,
|
Z3_OP_PB_GE,
|
||||||
Z3_OP_PB_EQ,
|
Z3_OP_PB_EQ,
|
||||||
|
@ -1948,7 +1953,7 @@ extern "C" {
|
||||||
The datatype may be recursive. Return the datatype sort.
|
The datatype may be recursive. Return the datatype sort.
|
||||||
|
|
||||||
\param c logical context.
|
\param c logical context.
|
||||||
\param name name of datatype.
|
\param name name of datatype.
|
||||||
\param num_constructors number of constructors passed in.
|
\param num_constructors number of constructors passed in.
|
||||||
\param constructors array of constructor containers.
|
\param constructors array of constructor containers.
|
||||||
|
|
||||||
|
@ -3961,10 +3966,19 @@ extern "C" {
|
||||||
|
|
||||||
def_API('Z3_mk_atmost', AST, (_in(CONTEXT), _in(UINT), _in_array(1,AST), _in(UINT)))
|
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 Z3_API Z3_mk_atmost(Z3_context c, unsigned num_args,
|
||||||
Z3_ast const args[], unsigned k);
|
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.
|
\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)))
|
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 Z3_API Z3_mk_pble(Z3_context c, unsigned num_args,
|
||||||
Z3_ast const args[], int coeffs[],
|
Z3_ast const args[], int coeffs[],
|
||||||
int k);
|
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.
|
\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)))
|
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 Z3_API Z3_mk_pbeq(Z3_context c, unsigned num_args,
|
||||||
Z3_ast const args[], int coeffs[],
|
Z3_ast const args[], int coeffs[],
|
||||||
int k);
|
int k);
|
||||||
|
|
|
@ -189,7 +189,7 @@ func_decl * macro_manager::get_macro_interpretation(unsigned i, expr_ref & inter
|
||||||
get_head_def(q, f, head, 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";);
|
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;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
\brief Convert a quasi-macro head into a macro head, and store the conditions under
|
||||||
which it is valid in cond.
|
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();
|
unsigned num_args = qhead->get_num_args();
|
||||||
sbuffer<bool> found_vars;
|
sbuffer<bool> found_vars;
|
||||||
found_vars.resize(num_decls, false);
|
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);
|
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());
|
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
|
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(is_macro_head(head, head->get_num_args()));
|
||||||
SASSERT(!occurs(head->get_decl(), def));
|
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_1, x_2) --> f(x_0, x_1)
|
||||||
f(x_3, 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 {
|
void macro_util::normalize_expr(app * head, unsigned num_decls, expr * t, expr_ref & norm_t) const {
|
||||||
expr_ref_buffer var_mapping(m_manager);
|
expr_ref_buffer var_mapping(m_manager);
|
||||||
|
var_mapping.resize(num_decls);
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
unsigned num_args = head->get_num_args();
|
unsigned num_args = head->get_num_args();
|
||||||
unsigned max_var_idx = 0;
|
TRACE("macro_util",
|
||||||
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",
|
|
||||||
tout << "head: " << mk_pp(head, m_manager) << "\n";
|
tout << "head: " << mk_pp(head, m_manager) << "\n";
|
||||||
tout << "applying substitution to:\n" << mk_bounded_pp(t, m_manager) << "\n";);
|
tout << "applying substitution to:\n" << mk_bounded_pp(t, m_manager) << "\n";);
|
||||||
for (unsigned i = 0; i < num_args; i++) {
|
for (unsigned i = 0; i < num_args; i++) {
|
||||||
var * v = to_var(head->get_arg(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;
|
changed = true;
|
||||||
var_ref new_var(m_manager.mk_var(i, v->get_sort()), m_manager);
|
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
|
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) {
|
if (changed) {
|
||||||
// REMARK: t may have nested quantifiers... So, I must use the std order for variable substitution.
|
// REMARK: t may have nested quantifiers... So, I must use the std order for variable substitution.
|
||||||
var_subst subst(m_manager, true);
|
var_subst subst(m_manager, true);
|
||||||
TRACE("macro_util_bug",
|
TRACE("macro_util",
|
||||||
tout << "head: " << mk_pp(head, m_manager) << "\n";
|
tout << "head: " << mk_pp(head, m_manager) << "\n";
|
||||||
tout << "applying substitution to:\n" << mk_ll_pp(t, m_manager) << "\nsubstitution:\n";
|
tout << "applying substitution to:\n" << mk_ll_pp(t, m_manager) << "\nsubstitution:\n";
|
||||||
for (unsigned i = 0; i < var_mapping.size(); i++) {
|
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);
|
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();
|
unsigned num_args = head->get_num_args();
|
||||||
ptr_buffer<expr> new_args;
|
ptr_buffer<expr> new_args;
|
||||||
sbuffer<bool> found_vars;
|
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_args.push_back(new_var);
|
||||||
}
|
}
|
||||||
new_head = m.mk_app(head->get_decl(), new_args.size(), new_args.c_ptr());
|
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
|
is_hint_head(head, vars) must also return true
|
||||||
*/
|
*/
|
||||||
bool macro_util::is_poly_hint(expr * n, app * head, expr * exception) {
|
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>";
|
if (exception) tout << mk_pp(exception, m_manager); else tout << "<null>";
|
||||||
tout << "\n";);
|
tout << "\n";);
|
||||||
ptr_buffer<var> vars;
|
ptr_buffer<var> vars;
|
||||||
if (!is_hint_head(head, 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;
|
return false;
|
||||||
}
|
}
|
||||||
func_decl * f = head->get_decl();
|
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++) {
|
for (unsigned i = 0; i < num_args; i++) {
|
||||||
expr * arg = args[i];
|
expr * arg = args[i];
|
||||||
if (arg != exception && (occurs(f, arg) || !vars_of_is_subset(arg, vars))) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRACE("macro_util_hint", tout << "succeeded\n";);
|
TRACE("macro_util", tout << "succeeded\n";);
|
||||||
return true;
|
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_def(m_manager);
|
||||||
expr_ref norm_cond(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)
|
if (cond != 0)
|
||||||
normalize_expr(head, cond, norm_cond);
|
normalize_expr(head, num_decls, cond, norm_cond);
|
||||||
else if (!hint)
|
else if (!hint)
|
||||||
norm_cond = m_manager.mk_true();
|
norm_cond = m_manager.mk_true();
|
||||||
SASSERT(!hint || norm_cond.get() == 0);
|
SASSERT(!hint || norm_cond.get() == 0);
|
||||||
|
@ -698,11 +691,14 @@ void macro_util::insert_quasi_macro(app * head, unsigned num_decls, expr * def,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
hint_to_macro_head(m_manager, head, num_decls, new_head);
|
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 {
|
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) {
|
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))
|
if (!m_manager.is_eq(atom) && !is_le_ge(atom))
|
||||||
return;
|
return;
|
||||||
expr * lhs = to_app(atom)->get_arg(0);
|
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) {
|
void macro_util::collect_macro_candidates_core(expr * atom, unsigned num_decls, macro_candidates & r) {
|
||||||
expr* lhs, *rhs;
|
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 (m_manager.is_eq(atom, lhs, rhs) || m_manager.is_iff(atom, lhs, rhs)) {
|
||||||
if (is_quasi_macro_head(lhs, num_decls) &&
|
if (is_quasi_macro_head(lhs, num_decls) &&
|
||||||
!is_forbidden(to_app(lhs)->get_decl()) &&
|
!is_forbidden(to_app(lhs)->get_decl()) &&
|
||||||
|
|
|
@ -74,8 +74,8 @@ private:
|
||||||
void collect_arith_macros(expr * n, unsigned num_decls, unsigned max_macros, bool allow_cond_macros,
|
void collect_arith_macros(expr * n, unsigned num_decls, unsigned max_macros, bool allow_cond_macros,
|
||||||
macro_candidates & r);
|
macro_candidates & r);
|
||||||
|
|
||||||
void normalize_expr(app * head, expr * t, expr_ref & norm_t) const;
|
void normalize_expr(app * head, unsigned num_decls, 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_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,
|
void insert_quasi_macro(app * head, unsigned num_decls, expr * def, expr * cond, bool ineq, bool satisfy_atom, bool hint,
|
||||||
macro_candidates & r);
|
macro_candidates & r);
|
||||||
|
|
||||||
|
@ -118,9 +118,9 @@ public:
|
||||||
bool is_pseudo_predicate_macro(expr * n, app_ref & head, app_ref & t, expr_ref & def);
|
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;
|
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(expr * atom, unsigned num_decls, macro_candidates & r);
|
||||||
void collect_macro_candidates(quantifier * q, macro_candidates & r);
|
void collect_macro_candidates(quantifier * q, macro_candidates & r);
|
||||||
|
|
|
@ -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);
|
mk_implies(args[0], args[1], result);
|
||||||
return BR_DONE;
|
return BR_DONE;
|
||||||
case OP_XOR:
|
case OP_XOR:
|
||||||
SASSERT(num_args == 2);
|
switch (num_args) {
|
||||||
mk_xor(args[0], args[1], result);
|
case 0: return BR_FAILED;
|
||||||
return BR_DONE;
|
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:
|
default:
|
||||||
return BR_FAILED;
|
return BR_FAILED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ Notes:
|
||||||
#include"scoped_ptr_vector.h"
|
#include"scoped_ptr_vector.h"
|
||||||
#include"cooperate.h"
|
#include"cooperate.h"
|
||||||
#include"upolynomial_factorization.h"
|
#include"upolynomial_factorization.h"
|
||||||
#include"polynomial_factorization.h"
|
|
||||||
#include"polynomial_primes.h"
|
#include"polynomial_primes.h"
|
||||||
#include"permutation.h"
|
#include"permutation.h"
|
||||||
#include"algebraic_numbers.h"
|
#include"algebraic_numbers.h"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
|
|
@ -575,7 +575,7 @@ namespace pdr {
|
||||||
// Predicates that are variable representatives. Other predicates at
|
// Predicates that are variable representatives. Other predicates at
|
||||||
// positions the variables occur are made equivalent with these.
|
// positions the variables occur are made equivalent with these.
|
||||||
expr_ref_vector conj(m);
|
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;
|
ptr_vector<app> aux_vars;
|
||||||
|
|
||||||
unsigned ut_size = rule.get_uninterpreted_tail_size();
|
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);
|
init_atom(pts, rule.get_head(), var_reprs, conj, UINT_MAX);
|
||||||
for (unsigned i = 0; i < ut_size; ++i) {
|
for (unsigned i = 0; i < ut_size; ++i) {
|
||||||
if (rule.is_neg_tail(i)) {
|
if (rule.is_neg_tail(i)) {
|
||||||
dealloc(&var_reprs);
|
char const* msg = "PDR does not supported negated predicates in rule tails";
|
||||||
throw default_exception("PDR does not support 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);
|
init_atom(pts, rule.get_tail(i), var_reprs, conj, i);
|
||||||
}
|
}
|
||||||
|
@ -600,14 +601,14 @@ namespace pdr {
|
||||||
flatten_and(tail);
|
flatten_and(tail);
|
||||||
for (unsigned i = 0; i < tail.size(); ++i) {
|
for (unsigned i = 0; i < tail.size(); ++i) {
|
||||||
expr_ref tmp(m);
|
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);
|
conj.push_back(tmp);
|
||||||
TRACE("pdr", tout << mk_pp(tail[i].get(), m) << "\n" << mk_pp(tmp, m) << "\n";);
|
TRACE("pdr", tout << mk_pp(tail[i].get(), m) << "\n" << mk_pp(tmp, m) << "\n";);
|
||||||
if (!is_ground(tmp)) {
|
if (!is_ground(tmp)) {
|
||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
msg << "PDR cannot solve non-ground tails: " << tmp;
|
msg << "PDR cannot solve non-ground tails: " << tmp;
|
||||||
IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
|
IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
|
||||||
dealloc(&var_reprs);
|
|
||||||
throw default_exception(msg.str());
|
throw default_exception(msg.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -631,7 +632,7 @@ namespace pdr {
|
||||||
m_rule2transition.insert(&rule, fml.get());
|
m_rule2transition.insert(&rule, fml.get());
|
||||||
rules.push_back(&rule);
|
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);
|
m_rule2vars.insert(&rule, aux_vars);
|
||||||
TRACE("pdr",
|
TRACE("pdr",
|
||||||
tout << rule.get_decl()->get_name() << "\n";
|
tout << rule.get_decl()->get_name() << "\n";
|
||||||
|
@ -1468,13 +1469,20 @@ namespace pdr {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::reset() {
|
void context::reset(decl2rel& rels) {
|
||||||
TRACE("pdr", tout << "\n";);
|
decl2rel::iterator it = rels.begin(), end = rels.end();
|
||||||
decl2rel::iterator it = m_rels.begin(), end = m_rels.end();
|
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
dealloc(it->m_value);
|
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_search.reset();
|
||||||
m_query = 0;
|
m_query = 0;
|
||||||
m_last_result = l_undef;
|
m_last_result = l_undef;
|
||||||
|
@ -1496,6 +1504,7 @@ namespace pdr {
|
||||||
e->get_data().m_value->add_rule(pred_rules[i]);
|
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();
|
datalog::rule_set::iterator rit = rules.begin(), rend = rules.end();
|
||||||
for (; rit != rend; ++rit) {
|
for (; rit != rend; ++rit) {
|
||||||
datalog::rule* r = *rit;
|
datalog::rule* r = *rit;
|
||||||
|
@ -1510,6 +1519,7 @@ namespace pdr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Initialize use list dependencies
|
// Initialize use list dependencies
|
||||||
|
TRACE("pdr", tout << "initialize use list dependencies\n";);
|
||||||
decl2rel::iterator it = rels.begin(), end = rels.end();
|
decl2rel::iterator it = rels.begin(), end = rels.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
func_decl* pred = it->m_key;
|
func_decl* pred = it->m_key;
|
||||||
|
@ -1523,9 +1533,11 @@ namespace pdr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE("pdr", tout << "initialize predicate transformers\n";);
|
||||||
// Initialize the predicate transformers.
|
// Initialize the predicate transformers.
|
||||||
it = rels.begin(), end = rels.end();
|
it = rels.begin(), end = rels.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
|
SASSERT(it->m_value);
|
||||||
pred_transformer& rel = *it->m_value;
|
pred_transformer& rel = *it->m_value;
|
||||||
rel.initialize(rels);
|
rel.initialize(rels);
|
||||||
TRACE("pdr", rel.display(tout); );
|
TRACE("pdr", rel.display(tout); );
|
||||||
|
@ -1533,21 +1545,24 @@ namespace pdr {
|
||||||
}
|
}
|
||||||
|
|
||||||
void context::update_rules(datalog::rule_set& rules) {
|
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_core_generalizers(rules);
|
||||||
init_rules(rules, rels);
|
init_rules(rules, m_rels_tmp);
|
||||||
decl2rel::iterator it = rels.begin(), end = rels.end();
|
decl2rel::iterator it = m_rels_tmp.begin(), end = m_rels_tmp.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
pred_transformer* pt = 0;
|
pred_transformer* pt = 0;
|
||||||
if (m_rels.find(it->m_key, pt)) {
|
if (m_rels.find(it->m_key, pt)) {
|
||||||
it->m_value->inherit_properties(*pt);
|
it->m_value->inherit_properties(*pt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reset();
|
reset(false);
|
||||||
it = rels.begin(), end = rels.end();
|
it = m_rels_tmp.begin(), end = m_rels_tmp.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
m_rels.insert(it->m_key, it->m_value);
|
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) {
|
unsigned context::get_num_levels(func_decl* p) {
|
||||||
|
@ -1875,6 +1890,7 @@ namespace pdr {
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool context::solve() {
|
lbool context::solve() {
|
||||||
|
TRACE("pdr", tout << "solve\n";);
|
||||||
m_last_result = l_undef;
|
m_last_result = l_undef;
|
||||||
try {
|
try {
|
||||||
solve_impl();
|
solve_impl();
|
||||||
|
@ -2090,6 +2106,7 @@ namespace pdr {
|
||||||
}
|
}
|
||||||
case l_undef: {
|
case l_undef: {
|
||||||
TRACE("pdr", tout << "unknown state: " << mk_pp(m_pm.mk_and(cube), m) << "\n";);
|
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();
|
throw unknown_exception();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,6 +328,7 @@ namespace pdr {
|
||||||
datalog::context* m_context;
|
datalog::context* m_context;
|
||||||
manager m_pm;
|
manager m_pm;
|
||||||
decl2rel m_rels; // Map from relation predicate to fp-operator.
|
decl2rel m_rels; // Map from relation predicate to fp-operator.
|
||||||
|
decl2rel m_rels_tmp;
|
||||||
func_decl_ref m_query_pred;
|
func_decl_ref m_query_pred;
|
||||||
pred_transformer* m_query;
|
pred_transformer* m_query;
|
||||||
mutable model_search m_search;
|
mutable model_search m_search;
|
||||||
|
@ -370,6 +371,8 @@ namespace pdr {
|
||||||
|
|
||||||
void reset_core_generalizers();
|
void reset_core_generalizers();
|
||||||
|
|
||||||
|
void reset(decl2rel& rels);
|
||||||
|
|
||||||
void validate();
|
void validate();
|
||||||
void validate_proof();
|
void validate_proof();
|
||||||
void validate_search();
|
void validate_search();
|
||||||
|
@ -410,8 +413,7 @@ namespace pdr {
|
||||||
|
|
||||||
lbool solve();
|
lbool solve();
|
||||||
|
|
||||||
|
void reset(bool full = true);
|
||||||
void reset();
|
|
||||||
|
|
||||||
void set_query(func_decl* q) { m_query_pred = q; }
|
void set_query(func_decl* q) { m_query_pred = q; }
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,8 @@ Revision History:
|
||||||
|
|
||||||
#include "dl_context.h"
|
#include "dl_context.h"
|
||||||
#include "dl_mk_coi_filter.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.h"
|
||||||
#include "dl_rule_transformer.h"
|
#include "dl_rule_transformer.h"
|
||||||
#include "smt2parser.h"
|
|
||||||
#include "pdr_context.h"
|
#include "pdr_context.h"
|
||||||
#include "pdr_dl_interface.h"
|
#include "pdr_dl_interface.h"
|
||||||
#include "dl_rule_set.h"
|
#include "dl_rule_set.h"
|
||||||
|
|
|
@ -109,6 +109,7 @@ private:
|
||||||
bool m_pivot_on_cs; // prefer smaller correction set to core.
|
bool m_pivot_on_cs; // prefer smaller correction set to core.
|
||||||
bool m_dump_benchmarks; // display benchmarks (into wcnf format)
|
bool m_dump_benchmarks; // display benchmarks (into wcnf format)
|
||||||
|
|
||||||
|
|
||||||
std::string m_trace_id;
|
std::string m_trace_id;
|
||||||
typedef ptr_vector<expr> exprs;
|
typedef ptr_vector<expr> exprs;
|
||||||
|
|
||||||
|
@ -152,8 +153,6 @@ public:
|
||||||
(m.is_not(l, l) && is_uninterp_const(l));
|
(m.is_not(l, l) && is_uninterp_const(l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void add_soft(expr* e, rational const& w) {
|
void add_soft(expr* e, rational const& w) {
|
||||||
TRACE("opt", tout << mk_pp(e, m) << " |-> " << w << "\n";);
|
TRACE("opt", tout << mk_pp(e, m) << " |-> " << w << "\n";);
|
||||||
expr_ref asum(m), fml(m);
|
expr_ref asum(m), fml(m);
|
||||||
|
@ -290,7 +289,7 @@ public:
|
||||||
index = next_index(asms, index);
|
index = next_index(asms, index);
|
||||||
}
|
}
|
||||||
first = false;
|
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;
|
m_last_index = index;
|
||||||
is_sat = check_sat(index, asms.c_ptr());
|
is_sat = check_sat(index, asms.c_ptr());
|
||||||
}
|
}
|
||||||
|
@ -302,17 +301,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool check_sat(unsigned sz, expr* const* asms) {
|
lbool check_sat(unsigned sz, expr* const* asms) {
|
||||||
if (m_st == s_primal_dual && m_c.sat_enabled()) {
|
return s().check_sat(sz, asms);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void found_optimum() {
|
void found_optimum() {
|
||||||
|
@ -500,7 +489,7 @@ public:
|
||||||
TRACE("opt", display_vec(tout << "minimized core: ", core););
|
TRACE("opt", display_vec(tout << "minimized core: ", core););
|
||||||
IF_VERBOSE(10, display_vec(verbose_stream() << "core: ", core););
|
IF_VERBOSE(10, display_vec(verbose_stream() << "core: ", core););
|
||||||
max_resolve(core, w);
|
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);
|
s().assert_expr(fml);
|
||||||
m_lower += w;
|
m_lower += w;
|
||||||
if (m_st == s_primal_dual) {
|
if (m_st == s_primal_dual) {
|
||||||
|
@ -540,7 +529,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool minimize_core(exprs& core) {
|
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;
|
return l_true;
|
||||||
}
|
}
|
||||||
m_mus.reset();
|
m_mus.reset();
|
||||||
|
@ -617,8 +609,8 @@ public:
|
||||||
// Soundness of this rule can be established using MaxRes
|
// Soundness of this rule can be established using MaxRes
|
||||||
//
|
//
|
||||||
for (unsigned i = 1; i < core.size(); ++i) {
|
for (unsigned i = 1; i < core.size(); ++i) {
|
||||||
expr* b_i = m_B[i-1].get();
|
expr* b_i = core[i-1];
|
||||||
expr* b_i1 = m_B[i].get();
|
expr* b_i1 = core[i];
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
d = to_app(b_i);
|
d = to_app(b_i);
|
||||||
}
|
}
|
||||||
|
@ -668,8 +660,8 @@ public:
|
||||||
// d_i => d_{i-1} or b_{i-1}
|
// d_i => d_{i-1} or b_{i-1}
|
||||||
//
|
//
|
||||||
for (unsigned i = 1; i < cs.size(); ++i) {
|
for (unsigned i = 1; i < cs.size(); ++i) {
|
||||||
expr* b_i = m_B[i-1].get();
|
expr* b_i = cs[i - 1];
|
||||||
expr* b_i1 = m_B[i].get();
|
expr* b_i1 = cs[i];
|
||||||
cls = m.mk_or(b_i, d);
|
cls = m.mk_or(b_i, d);
|
||||||
if (i > 2) {
|
if (i > 2) {
|
||||||
d = mk_fresh_bool("d");
|
d = mk_fresh_bool("d");
|
||||||
|
@ -690,10 +682,11 @@ public:
|
||||||
s().assert_expr(fml);
|
s().assert_expr(fml);
|
||||||
m_defs.push_back(fml);
|
m_defs.push_back(fml);
|
||||||
new_assumption(asum, w);
|
new_assumption(asum, w);
|
||||||
|
|
||||||
fml = m.mk_and(b_i1, cls);
|
fml = m.mk_and(b_i1, cls);
|
||||||
update_model(asum, fml);
|
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);
|
s().assert_expr(fml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,10 +760,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_true(expr_ref_vector const& es) {
|
bool is_true(expr_ref_vector const& es) {
|
||||||
for (unsigned i = 0; i < es.size(); ++i) {
|
unsigned i = 0;
|
||||||
if (!is_true(es[i])) return false;
|
for (; i < es.size() && is_true(es[i]); ++i) { }
|
||||||
}
|
return i == es.size();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_soft(exprs const& core, expr_ref_vector& asms) {
|
void remove_soft(exprs const& core, expr_ref_vector& asms) {
|
||||||
|
@ -790,7 +782,6 @@ public:
|
||||||
virtual void updt_params(params_ref& p) {
|
virtual void updt_params(params_ref& p) {
|
||||||
maxsmt_solver_base::updt_params(p);
|
maxsmt_solver_base::updt_params(p);
|
||||||
opt_params _p(p);
|
opt_params _p(p);
|
||||||
|
|
||||||
m_hill_climb = _p.maxres_hill_climb();
|
m_hill_climb = _p.maxres_hill_climb();
|
||||||
m_add_upper_bound_block = _p.maxres_add_upper_bound_block();
|
m_add_upper_bound_block = _p.maxres_add_upper_bound_block();
|
||||||
m_max_num_cores = _p.maxres_max_num_cores();
|
m_max_num_cores = _p.maxres_max_num_cores();
|
||||||
|
@ -868,7 +859,6 @@ public:
|
||||||
IF_VERBOSE(0, verbose_stream() << "assignment is infeasible\n";);
|
IF_VERBOSE(0, verbose_stream() << "assignment is infeasible\n";);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
opt::maxsmt_solver_base* opt::mk_maxres(
|
opt::maxsmt_solver_base* opt::mk_maxres(
|
||||||
|
|
|
@ -55,15 +55,18 @@ namespace opt {
|
||||||
|
|
||||||
void maxsmt_solver_base::commit_assignment() {
|
void maxsmt_solver_base::commit_assignment() {
|
||||||
expr_ref tmp(m);
|
expr_ref tmp(m);
|
||||||
rational k(0);
|
rational k(0), cost(0);
|
||||||
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
||||||
if (get_assignment(i)) {
|
if (get_assignment(i)) {
|
||||||
k += m_weights[i];
|
k += m_weights[i];
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
cost += m_weights[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pb_util pb(m);
|
pb_util pb(m);
|
||||||
tmp = pb.mk_ge(m_weights.size(), m_weights.c_ptr(), m_soft.c_ptr(), k);
|
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);
|
s().assert_expr(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +143,9 @@ namespace opt {
|
||||||
m_wth = s.ensure_wmax_theory();
|
m_wth = s.ensure_wmax_theory();
|
||||||
}
|
}
|
||||||
maxsmt_solver_base::scoped_ensure_theory::~scoped_ensure_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; }
|
smt::theory_wmaxsat& maxsmt_solver_base::scoped_ensure_theory::operator()() { return *m_wth; }
|
||||||
|
|
||||||
|
@ -226,7 +231,9 @@ namespace opt {
|
||||||
m_msolver = 0;
|
m_msolver = 0;
|
||||||
symbol const& maxsat_engine = m_c.maxsat_engine();
|
symbol const& maxsat_engine = m_c.maxsat_engine();
|
||||||
IF_VERBOSE(1, verbose_stream() << "(maxsmt)\n";);
|
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) {
|
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);
|
m_msolver = mk_maxres(m_c, m_index, m_weights, m_soft_constraints);
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,11 +328,6 @@ namespace opt {
|
||||||
return m_context.get_formulas()[idx];
|
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 opt_solver::add_objective(app* term) {
|
||||||
smt::theory_var v = get_optimizer().add_objective(term);
|
smt::theory_var v = get_optimizer().add_objective(term);
|
||||||
m_objective_vars.push_back(v);
|
m_objective_vars.push_back(v);
|
||||||
|
|
|
@ -104,7 +104,6 @@ namespace opt {
|
||||||
virtual void set_progress_callback(progress_callback * callback);
|
virtual void set_progress_callback(progress_callback * callback);
|
||||||
virtual unsigned get_num_assertions() const;
|
virtual unsigned get_num_assertions() const;
|
||||||
virtual expr * get_assertion(unsigned idx) 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 ast_manager& get_manager() const { return m; }
|
||||||
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes);
|
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);
|
virtual lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores);
|
||||||
|
|
|
@ -20,9 +20,49 @@ Notes:
|
||||||
#include "smt_literal.h"
|
#include "smt_literal.h"
|
||||||
#include "ast_pp.h"
|
#include "ast_pp.h"
|
||||||
#include "th_rewriter.h"
|
#include "th_rewriter.h"
|
||||||
#include "sat_sls.h"
|
#include "sat_types.h"
|
||||||
|
|
||||||
namespace smt {
|
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 pb_sls::imp {
|
||||||
|
|
||||||
struct clause {
|
struct clause {
|
||||||
|
@ -73,8 +113,8 @@ namespace smt {
|
||||||
expr_ref_vector m_trail;
|
expr_ref_vector m_trail;
|
||||||
obj_map<expr, unsigned> m_decl2var; // map declarations to Boolean variables.
|
obj_map<expr, unsigned> m_decl2var; // map declarations to Boolean variables.
|
||||||
ptr_vector<expr> m_var2decl; // reverse map
|
ptr_vector<expr> m_var2decl; // reverse map
|
||||||
sat::index_set m_hard_false; // list of hard clauses that are false.
|
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_soft_false; // list of soft clauses that are false.
|
||||||
unsigned m_max_flips; // maximal number of flips
|
unsigned m_max_flips; // maximal number of flips
|
||||||
unsigned m_non_greedy_percent; // percent of moves to do non-greedy style
|
unsigned m_non_greedy_percent; // percent of moves to do non-greedy style
|
||||||
random_gen m_rng;
|
random_gen m_rng;
|
||||||
|
|
|
@ -62,20 +62,22 @@ namespace opt {
|
||||||
}
|
}
|
||||||
m_upper = m_lower;
|
m_upper = m_lower;
|
||||||
bool was_sat = false;
|
bool was_sat = false;
|
||||||
expr_ref_vector disj(m), asms(m);
|
expr_ref_vector asms(m);
|
||||||
vector<expr_ref_vector> cores;
|
vector<expr_ref_vector> cores;
|
||||||
|
|
||||||
obj_map<expr, rational>::iterator it = soft.begin(), end = soft.end();
|
obj_map<expr, rational>::iterator it = soft.begin(), end = soft.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
expr* c = assert_weighted(wth(), it->m_key, it->m_value);
|
expr* c = assert_weighted(wth(), it->m_key, it->m_value);
|
||||||
if (!is_true(it->m_key)) {
|
if (!is_true(it->m_key)) {
|
||||||
disj.push_back(m.mk_not(c));
|
|
||||||
m_upper += it->m_value;
|
m_upper += it->m_value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wth().init_min_cost(m_upper - m_lower);
|
wth().init_min_cost(m_upper - m_lower);
|
||||||
s().assert_expr(mk_or(disj));
|
|
||||||
trace_bounds("wmax");
|
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) {
|
while (!m.canceled() && m_lower < m_upper) {
|
||||||
//mk_assumptions(asms);
|
//mk_assumptions(asms);
|
||||||
//is_sat = s().preferred_sat(asms, cores);
|
//is_sat = s().preferred_sat(asms, cores);
|
||||||
|
@ -84,6 +86,7 @@ namespace opt {
|
||||||
is_sat = l_undef;
|
is_sat = l_undef;
|
||||||
}
|
}
|
||||||
if (is_sat == l_false) {
|
if (is_sat == l_false) {
|
||||||
|
TRACE("opt", tout << "Unsat\n";);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (is_sat == l_true) {
|
if (is_sat == l_true) {
|
||||||
|
|
|
@ -109,7 +109,6 @@ namespace smt2 {
|
||||||
typedef std::pair<symbol, expr*> named_expr;
|
typedef std::pair<symbol, expr*> named_expr;
|
||||||
named_expr m_last_named_expr;
|
named_expr m_last_named_expr;
|
||||||
|
|
||||||
|
|
||||||
ast_manager & m() const { return m_ctx.m(); }
|
ast_manager & m() const { return m_ctx.m(); }
|
||||||
pdecl_manager & pm() const { return m_ctx.pm(); }
|
pdecl_manager & pm() const { return m_ctx.pm(); }
|
||||||
sexpr_manager & sm() const { return m_ctx.sm(); }
|
sexpr_manager & sm() const { return m_ctx.sm(); }
|
||||||
|
@ -402,6 +401,9 @@ namespace smt2 {
|
||||||
void check_int_or_float(char const * msg) { if (!curr_is_int() && !curr_is_float()) throw parser_exception(msg); }
|
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); }
|
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) {
|
void error(unsigned line, unsigned pos, char const * msg) {
|
||||||
m_ctx.set_cancel(false);
|
m_ctx.set_cancel(false);
|
||||||
if (use_vs_format()) {
|
if (use_vs_format()) {
|
||||||
|
@ -410,7 +412,9 @@ namespace smt2 {
|
||||||
m_ctx.diagnostic_stream() << std::endl;
|
m_ctx.diagnostic_stream() << std::endl;
|
||||||
}
|
}
|
||||||
else {
|
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()) {
|
if (m_ctx.exit_on_error()) {
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -2558,7 +2562,7 @@ namespace smt2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
parser(cmd_context & ctx, std::istream & is, bool interactive, params_ref const & p):
|
parser(cmd_context & ctx, std::istream & is, bool interactive, params_ref const & p, char const * filename=0):
|
||||||
m_ctx(ctx),
|
m_ctx(ctx),
|
||||||
m_params(p),
|
m_params(p),
|
||||||
m_scanner(ctx, is, interactive),
|
m_scanner(ctx, is, interactive),
|
||||||
|
@ -2598,7 +2602,8 @@ namespace smt2 {
|
||||||
m_define_fun_rec("define-fun-rec"),
|
m_define_fun_rec("define-fun-rec"),
|
||||||
m_define_funs_rec("define-funs-rec"),
|
m_define_funs_rec("define-funs-rec"),
|
||||||
m_underscore("_"),
|
m_underscore("_"),
|
||||||
m_num_open_paren(0) {
|
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.
|
// 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());
|
// SASSERT(!m_ctx.has_manager());
|
||||||
|
|
||||||
|
@ -2705,8 +2710,8 @@ namespace smt2 {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
bool parse_smt2_commands(cmd_context & ctx, std::istream & is, bool interactive, params_ref const & 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);
|
smt2::parser p(ctx, is, interactive, ps, filename);
|
||||||
return p();
|
return p();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,6 @@ Revision History:
|
||||||
|
|
||||||
#include"cmd_context.h"
|
#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
|
#endif
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -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
|
|
|
@ -23,10 +23,10 @@ Revision History:
|
||||||
namespace sat {
|
namespace sat {
|
||||||
|
|
||||||
config::config(params_ref const & p):
|
config::config(params_ref const & p):
|
||||||
|
m_restart_max(0),
|
||||||
m_always_true("always_true"),
|
m_always_true("always_true"),
|
||||||
m_always_false("always_false"),
|
m_always_false("always_false"),
|
||||||
m_caching("caching"),
|
m_caching("caching"),
|
||||||
m_restart_max(0),
|
|
||||||
m_random("random"),
|
m_random("random"),
|
||||||
m_geometric("geometric"),
|
m_geometric("geometric"),
|
||||||
m_luby("luby"),
|
m_luby("luby"),
|
||||||
|
@ -111,8 +111,6 @@ namespace sat {
|
||||||
m_minimize_lemmas = p.minimize_lemmas();
|
m_minimize_lemmas = p.minimize_lemmas();
|
||||||
m_core_minimize = p.core_minimize();
|
m_core_minimize = p.core_minimize();
|
||||||
m_core_minimize_partial = p.core_minimize_partial();
|
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();
|
m_dyn_sub_res = p.dyn_sub_res();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,6 @@ namespace sat {
|
||||||
bool m_dyn_sub_res;
|
bool m_dyn_sub_res;
|
||||||
bool m_core_minimize;
|
bool m_core_minimize;
|
||||||
bool m_core_minimize_partial;
|
bool m_core_minimize_partial;
|
||||||
bool m_optimize_model;
|
|
||||||
bool m_bcd;
|
|
||||||
|
|
||||||
|
|
||||||
symbol m_always_true;
|
symbol m_always_true;
|
||||||
|
|
|
@ -20,11 +20,10 @@ Notes:
|
||||||
|
|
||||||
#include "sat_solver.h"
|
#include "sat_solver.h"
|
||||||
#include "sat_mus.h"
|
#include "sat_mus.h"
|
||||||
#include "sat_sls.h"
|
|
||||||
|
|
||||||
namespace sat {
|
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() {}
|
mus::~mus() {}
|
||||||
|
|
||||||
|
@ -32,7 +31,6 @@ namespace sat {
|
||||||
m_core.reset();
|
m_core.reset();
|
||||||
m_mus.reset();
|
m_mus.reset();
|
||||||
m_model.reset();
|
m_model.reset();
|
||||||
m_best_value = 0;
|
|
||||||
m_max_restarts = (s.m_stats.m_restart - m_restart) + 10;
|
m_max_restarts = (s.m_stats.m_restart - m_restart) + 10;
|
||||||
m_restart = s.m_stats.m_restart;
|
m_restart = s.m_stats.m_restart;
|
||||||
}
|
}
|
||||||
|
@ -45,21 +43,13 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void mus::update_model() {
|
void mus::update_model() {
|
||||||
double new_value = s.m_wsls.evaluate_model(s.m_model);
|
|
||||||
if (m_model.empty()) {
|
if (m_model.empty()) {
|
||||||
m_model.append(s.m_model);
|
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()() {
|
lbool mus::operator()() {
|
||||||
flet<bool> _disable_min(s.m_config.m_core_minimize, false);
|
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);
|
flet<bool> _is_active(m_is_active, true);
|
||||||
IF_VERBOSE(3, verbose_stream() << "(sat.mus " << s.get_core() << ")\n";);
|
IF_VERBOSE(3, verbose_stream() << "(sat.mus " << s.get_core() << ")\n";);
|
||||||
reset();
|
reset();
|
||||||
|
@ -120,9 +110,6 @@ namespace sat {
|
||||||
SASSERT(value_at(lit, s.get_model()) == l_false);
|
SASSERT(value_at(lit, s.get_model()) == l_false);
|
||||||
mus.push_back(lit);
|
mus.push_back(lit);
|
||||||
update_model();
|
update_model();
|
||||||
if (!core.empty()) {
|
|
||||||
// mr(); // TBD: measure
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case l_false:
|
case l_false:
|
||||||
|
@ -262,27 +249,5 @@ namespace sat {
|
||||||
IF_VERBOSE(3, verbose_stream() << "core verification: " << is_sat << " " << core << "\n";);
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ namespace sat {
|
||||||
literal_vector m_mus;
|
literal_vector m_mus;
|
||||||
bool m_is_active;
|
bool m_is_active;
|
||||||
model m_model; // model obtained during minimal unsat core
|
model m_model; // model obtained during minimal unsat core
|
||||||
double m_best_value;
|
|
||||||
unsigned m_restart;
|
unsigned m_restart;
|
||||||
unsigned m_max_restarts;
|
unsigned m_max_restarts;
|
||||||
|
|
||||||
|
@ -41,7 +40,6 @@ namespace sat {
|
||||||
lbool mus1();
|
lbool mus1();
|
||||||
lbool mus2();
|
lbool mus2();
|
||||||
lbool qx(literal_set& assignment, literal_set& support, bool has_support);
|
lbool qx(literal_set& assignment, literal_set& support, bool has_support);
|
||||||
void mr();
|
|
||||||
void reset();
|
void reset();
|
||||||
void set_core();
|
void set_core();
|
||||||
void update_model();
|
void update_model();
|
||||||
|
|
|
@ -7,7 +7,7 @@ def_module_params('sat',
|
||||||
('phase.caching.off', UINT, 100, 'phase caching off period (in number of conflicts)'),
|
('phase.caching.off', UINT, 100, 'phase caching off period (in number of conflicts)'),
|
||||||
('restart', SYMBOL, 'luby', 'restart strategy: luby or geometric'),
|
('restart', SYMBOL, 'luby', 'restart strategy: luby or geometric'),
|
||||||
('restart.initial', UINT, 100, 'initial restart (number of conflicts)'),
|
('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'),
|
('restart.factor', DOUBLE, 1.5, 'restart increment factor for geometric strategy'),
|
||||||
('random_freq', DOUBLE, 0.01, 'frequency of random case splits'),
|
('random_freq', DOUBLE, 0.01, 'frequency of random case splits'),
|
||||||
('random_seed', UINT, 0, 'random seed'),
|
('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'),
|
('dyn_sub_res', BOOL, True, 'dynamic subsumption resolution for minimizing learned clauses'),
|
||||||
('core.minimize', BOOL, False, 'minimize computed core'),
|
('core.minimize', BOOL, False, 'minimize computed core'),
|
||||||
('core.minimize_partial', BOOL, False, 'apply partial (cheap) core minimization'),
|
('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')))
|
('dimacs.core', BOOL, False, 'extract core from DIMACS benchmarks')))
|
||||||
|
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
|
@ -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
|
|
|
@ -20,7 +20,6 @@ Revision History:
|
||||||
#include"sat_integrity_checker.h"
|
#include"sat_integrity_checker.h"
|
||||||
#include"luby.h"
|
#include"luby.h"
|
||||||
#include"trace.h"
|
#include"trace.h"
|
||||||
#include"sat_bceq.h"
|
|
||||||
#include"max_cliques.h"
|
#include"max_cliques.h"
|
||||||
|
|
||||||
// define to update glue during propagation
|
// define to update glue during propagation
|
||||||
|
@ -42,7 +41,6 @@ namespace sat {
|
||||||
m_asymm_branch(*this, p),
|
m_asymm_branch(*this, p),
|
||||||
m_probing(*this, p),
|
m_probing(*this, p),
|
||||||
m_mus(*this),
|
m_mus(*this),
|
||||||
m_wsls(*this),
|
|
||||||
m_inconsistent(false),
|
m_inconsistent(false),
|
||||||
m_num_frozen(0),
|
m_num_frozen(0),
|
||||||
m_activity_inc(128),
|
m_activity_inc(128),
|
||||||
|
@ -55,7 +53,6 @@ namespace sat {
|
||||||
m_conflicts = 0;
|
m_conflicts = 0;
|
||||||
m_next_simplify = 0;
|
m_next_simplify = 0;
|
||||||
m_num_checkpoints = 0;
|
m_num_checkpoints = 0;
|
||||||
m_initializing_preferred = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
solver::~solver() {
|
solver::~solver() {
|
||||||
|
@ -123,6 +120,7 @@ namespace sat {
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
|
||||||
bool_var solver::mk_var(bool ext, bool dvar) {
|
bool_var solver::mk_var(bool ext, bool dvar) {
|
||||||
|
m_model_is_current = false;
|
||||||
m_stats.m_mk_var++;
|
m_stats.m_mk_var++;
|
||||||
bool_var v = m_level.size();
|
bool_var v = m_level.size();
|
||||||
m_watches.push_back(watch_list());
|
m_watches.push_back(watch_list());
|
||||||
|
@ -148,6 +146,7 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::mk_clause(unsigned num_lits, literal * lits) {
|
void solver::mk_clause(unsigned num_lits, literal * lits) {
|
||||||
|
m_model_is_current = false;
|
||||||
DEBUG_CODE({
|
DEBUG_CODE({
|
||||||
for (unsigned i = 0; i < num_lits; i++)
|
for (unsigned i = 0; i < num_lits; i++)
|
||||||
SASSERT(m_eliminated[lits[i].var()] == false);
|
SASSERT(m_eliminated[lits[i].var()] == false);
|
||||||
|
@ -235,19 +234,18 @@ namespace sat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::push_reinit_stack(clause & c) {
|
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));
|
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) {
|
clause * solver::mk_ter_clause(literal * lits, bool learned) {
|
||||||
m_stats.m_mk_ter_clause++;
|
m_stats.m_mk_ter_clause++;
|
||||||
clause * r = m_cls_allocator.mk_clause(3, lits, learned);
|
clause * r = m_cls_allocator.mk_clause(3, lits, learned);
|
||||||
bool reinit;
|
bool reinit = attach_ter_clause(*r);
|
||||||
attach_ter_clause(*r, reinit);
|
if (reinit && !learned) push_reinit_stack(*r);
|
||||||
if (!learned && reinit) {
|
|
||||||
TRACE("sat_reinit", tout << "adding to reinit stack: " << *r << "\n";);
|
|
||||||
push_reinit_stack(*r);
|
|
||||||
}
|
|
||||||
if (learned)
|
if (learned)
|
||||||
m_learned.push_back(r);
|
m_learned.push_back(r);
|
||||||
else
|
else
|
||||||
|
@ -255,8 +253,8 @@ namespace sat {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::attach_ter_clause(clause & c, bool & reinit) {
|
bool solver::attach_ter_clause(clause & c) {
|
||||||
reinit = false;
|
bool reinit = false;
|
||||||
m_watches[(~c[0]).index()].push_back(watched(c[1], c[2]));
|
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[1]).index()].push_back(watched(c[0], c[2]));
|
||||||
m_watches[(~c[2]).index()].push_back(watched(c[0], c[1]));
|
m_watches[(~c[2]).index()].push_back(watched(c[0], c[1]));
|
||||||
|
@ -277,18 +275,15 @@ namespace sat {
|
||||||
reinit = true;
|
reinit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return reinit;
|
||||||
}
|
}
|
||||||
|
|
||||||
clause * solver::mk_nary_clause(unsigned num_lits, literal * lits, bool learned) {
|
clause * solver::mk_nary_clause(unsigned num_lits, literal * lits, bool learned) {
|
||||||
m_stats.m_mk_clause++;
|
m_stats.m_mk_clause++;
|
||||||
clause * r = m_cls_allocator.mk_clause(num_lits, lits, learned);
|
clause * r = m_cls_allocator.mk_clause(num_lits, lits, learned);
|
||||||
SASSERT(!learned || r->is_learned());
|
SASSERT(!learned || r->is_learned());
|
||||||
bool reinit;
|
bool reinit = attach_nary_clause(*r);
|
||||||
attach_nary_clause(*r, reinit);
|
if (reinit && !learned) push_reinit_stack(*r);
|
||||||
if (!learned && reinit) {
|
|
||||||
TRACE("sat_reinit", tout << "adding to reinit stack: " << *r << "\n";);
|
|
||||||
push_reinit_stack(*r);
|
|
||||||
}
|
|
||||||
if (learned)
|
if (learned)
|
||||||
m_learned.push_back(r);
|
m_learned.push_back(r);
|
||||||
else
|
else
|
||||||
|
@ -296,8 +291,8 @@ namespace sat {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::attach_nary_clause(clause & c, bool & reinit) {
|
bool solver::attach_nary_clause(clause & c) {
|
||||||
reinit = false;
|
bool reinit = false;
|
||||||
clause_offset cls_off = m_cls_allocator.get_offset(&c);
|
clause_offset cls_off = m_cls_allocator.get_offset(&c);
|
||||||
if (scope_lvl() > 0) {
|
if (scope_lvl() > 0) {
|
||||||
if (c.is_learned()) {
|
if (c.is_learned()) {
|
||||||
|
@ -326,15 +321,16 @@ namespace sat {
|
||||||
literal block_lit = c[some_idx];
|
literal block_lit = c[some_idx];
|
||||||
m_watches[(~c[0]).index()].push_back(watched(block_lit, cls_off));
|
m_watches[(~c[0]).index()].push_back(watched(block_lit, cls_off));
|
||||||
m_watches[(~c[1]).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) {
|
void solver::attach_clause(clause & c, bool & reinit) {
|
||||||
SASSERT(c.size() > 2);
|
SASSERT(c.size() > 2);
|
||||||
reinit = false;
|
reinit = false;
|
||||||
if (c.size() == 3)
|
if (c.size() == 3)
|
||||||
attach_ter_clause(c, reinit);
|
reinit = attach_ter_clause(c);
|
||||||
else
|
else
|
||||||
attach_nary_clause(c, reinit);
|
reinit = attach_nary_clause(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -711,7 +707,7 @@ namespace sat {
|
||||||
// Search
|
// 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();
|
pop_to_base_level();
|
||||||
IF_VERBOSE(2, verbose_stream() << "(sat.sat-solver)\n";);
|
IF_VERBOSE(2, verbose_stream() << "(sat.sat-solver)\n";);
|
||||||
SASSERT(scope_lvl() == 0);
|
SASSERT(scope_lvl() == 0);
|
||||||
|
@ -726,7 +722,7 @@ namespace sat {
|
||||||
init_search();
|
init_search();
|
||||||
propagate(false);
|
propagate(false);
|
||||||
if (inconsistent()) return l_false;
|
if (inconsistent()) return l_false;
|
||||||
init_assumptions(num_lits, lits, weights, max_weight);
|
init_assumptions(num_lits, lits);
|
||||||
propagate(false);
|
propagate(false);
|
||||||
if (check_inconsistent()) return l_false;
|
if (check_inconsistent()) return l_false;
|
||||||
cleanup();
|
cleanup();
|
||||||
|
@ -766,7 +762,7 @@ namespace sat {
|
||||||
if (check_inconsistent()) return l_false;
|
if (check_inconsistent()) return l_false;
|
||||||
gc();
|
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";);
|
IF_VERBOSE(SAT_VB_LVL, verbose_stream() << "(sat \"abort: max-restarts\")\n";);
|
||||||
return l_undef;
|
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()) {
|
if (num_lits == 0 && m_user_scope_literals.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
retry_init_assumptions:
|
|
||||||
reset_assumptions();
|
reset_assumptions();
|
||||||
push();
|
push();
|
||||||
|
|
||||||
|
@ -941,16 +936,6 @@ namespace sat {
|
||||||
assign(nlit, justification());
|
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) {
|
for (unsigned i = 0; !inconsistent() && i < num_lits; ++i) {
|
||||||
literal lit = lits[i];
|
literal lit = lits[i];
|
||||||
SASSERT(is_external(lit.var()));
|
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() {
|
void solver::update_min_core() {
|
||||||
if (!m_min_core_valid || m_core.size() < m_min_core.size()) {
|
if (!m_min_core_valid || m_core.size() < m_min_core.size()) {
|
||||||
m_min_core.reset();
|
m_min_core.reset();
|
||||||
|
@ -1112,6 +994,13 @@ namespace sat {
|
||||||
for (unsigned i = 0; !inconsistent() && i < m_assumptions.size(); ++i) {
|
for (unsigned i = 0; !inconsistent() && i < m_assumptions.size(); ++i) {
|
||||||
assign(m_assumptions[i], justification());
|
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_valid = false;
|
||||||
m_min_core.reset();
|
m_min_core.reset();
|
||||||
TRACE("sat", display(tout););
|
TRACE("sat", display(tout););
|
||||||
|
|
||||||
if (m_config.m_bcd) {
|
|
||||||
bceq bc(*this);
|
|
||||||
bc();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1235,9 +1119,6 @@ namespace sat {
|
||||||
m_model[v] = value(v);
|
m_model[v] = value(v);
|
||||||
}
|
}
|
||||||
TRACE("sat_mc_bug", m_mc.display(tout););
|
TRACE("sat_mc_bug", m_mc.display(tout););
|
||||||
if (m_config.m_optimize_model) {
|
|
||||||
m_wsls.opt(0, 0, false);
|
|
||||||
}
|
|
||||||
m_mc(m_model);
|
m_mc(m_model);
|
||||||
TRACE("sat", for (bool_var v = 0; v < num; v++) tout << v << ": " << m_model[v] << "\n";);
|
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";
|
if (m_not_l == literal()) tout << "null literal\n";
|
||||||
else tout << m_not_l << "\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()) {
|
if (m_conflict_lvl <= 1 && tracking_assumptions()) {
|
||||||
resolve_conflict_for_unsat_core();
|
resolve_conflict_for_unsat_core();
|
||||||
return false;
|
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) {
|
lbool solver::get_consequences(literal_vector const& asms, bool_var_vector const& vars, vector<literal_vector>& conseq) {
|
||||||
literal_vector lits;
|
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) {
|
if (is_sat != l_true) {
|
||||||
return is_sat;
|
return is_sat;
|
||||||
}
|
}
|
||||||
|
@ -3136,9 +3020,94 @@ namespace sat {
|
||||||
return is_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();
|
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();
|
pop_to_base_level();
|
||||||
if (inconsistent()) return l_false;
|
if (inconsistent()) return l_false;
|
||||||
|
@ -3148,20 +3117,24 @@ namespace sat {
|
||||||
if (asms.empty()) {
|
if (asms.empty()) {
|
||||||
bool_var v = mk_var(true, false);
|
bool_var v = mk_var(true, false);
|
||||||
literal lit(v, false);
|
literal lit(v, false);
|
||||||
init_assumptions(1, &lit, 0, 0);
|
init_assumptions(1, &lit);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
init_assumptions(asms.size(), asms.c_ptr(), 0, 0);
|
init_assumptions(asms.size(), asms.c_ptr());
|
||||||
}
|
}
|
||||||
propagate(false);
|
propagate(false);
|
||||||
if (check_inconsistent()) return l_false;
|
if (check_inconsistent()) return l_false;
|
||||||
|
|
||||||
unsigned num_units = 0, num_iterations = 0;
|
unsigned num_units = 0, num_iterations = 0;
|
||||||
extract_fixed_consequences(num_units, assumptions, vars, conseq);
|
extract_fixed_consequences(num_units, assumptions, unfixed_vars, conseq);
|
||||||
while (!vars.empty()) {
|
update_unfixed_literals(unfixed_lits, unfixed_vars);
|
||||||
|
while (!unfixed_lits.empty()) {
|
||||||
|
if (scope_lvl() > 1) {
|
||||||
|
pop(scope_lvl() - 1);
|
||||||
|
}
|
||||||
++num_iterations;
|
++num_iterations;
|
||||||
checkpoint();
|
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;
|
unsigned num_resolves = 0;
|
||||||
lbool is_sat = l_true;
|
lbool is_sat = l_true;
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
|
@ -3202,53 +3175,84 @@ namespace sat {
|
||||||
m_inconsistent = false;
|
m_inconsistent = false;
|
||||||
}
|
}
|
||||||
if (is_sat == l_true) {
|
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"
|
IF_VERBOSE(1, verbose_stream() << "(sat.get-consequences"
|
||||||
<< " iterations: " << num_iterations
|
<< " iterations: " << num_iterations
|
||||||
<< " variables: " << vars.size()
|
<< " variables: " << unfixed_lits.size()
|
||||||
<< " fixed: " << conseq.size()
|
<< " fixed: " << conseq.size()
|
||||||
<< " unfixed: " << lits.size() - conseq.size() - vars.size()
|
<< " unfixed: " << lits.size() - conseq.size() - unfixed_lits.size()
|
||||||
<< ")\n";);
|
<< ")\n";);
|
||||||
|
|
||||||
|
if (!unfixed_lits.empty() && m_config.m_restart_max <= num_iterations) {
|
||||||
|
return l_undef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return l_true;
|
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 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) {
|
for (; it != end; ++it) {
|
||||||
literal lit = *it;
|
literal lit = *it;
|
||||||
if (value(lit) == l_true) {
|
if (value(lit) == l_true) {
|
||||||
to_keep.insert(lit);
|
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) {
|
void solver::update_unfixed_literals(literal_set& unfixed_lits, bool_var_set& unfixed_vars) {
|
||||||
if (scope_lvl() > 1) {
|
literal_vector to_delete;
|
||||||
pop(scope_lvl() - 1);
|
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());
|
SASSERT(!inconsistent());
|
||||||
unsigned sz = m_trail.size();
|
unsigned sz = m_trail.size();
|
||||||
for (unsigned i = start; i < sz; ++i) {
|
for (unsigned i = start; i < sz && lvl(m_trail[i]) <= 1; ++i) {
|
||||||
extract_fixed_consequences(m_trail[i], assumptions, unfixed, conseq);
|
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;
|
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()];
|
justification js = m_justification[lit.var()];
|
||||||
switch (js.get_kind()) {
|
switch (js.get_kind()) {
|
||||||
case justification::NONE:
|
case justification::NONE:
|
||||||
break;
|
break;
|
||||||
case justification::BINARY:
|
case justification::BINARY:
|
||||||
|
if (!check_domain(lit, js.get_literal())) return false;
|
||||||
s |= m_antecedents.find(js.get_literal().var());
|
s |= m_antecedents.find(js.get_literal().var());
|
||||||
break;
|
break;
|
||||||
case justification::TERNARY:
|
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_literal1().var());
|
||||||
s |= m_antecedents.find(js.get_literal2().var());
|
s |= m_antecedents.find(js.get_literal2().var());
|
||||||
break;
|
break;
|
||||||
|
@ -3256,6 +3260,7 @@ namespace sat {
|
||||||
clause & c = *(m_cls_allocator.get_clause(js.get_clause_offset()));
|
clause & c = *(m_cls_allocator.get_clause(js.get_clause_offset()));
|
||||||
for (unsigned i = 0; i < c.size(); ++i) {
|
for (unsigned i = 0; i < c.size(); ++i) {
|
||||||
if (c[i] != lit) {
|
if (c[i] != lit) {
|
||||||
|
if (!check_domain(lit, c[i])) return false;
|
||||||
s |= m_antecedents.find(c[i].var());
|
s |= m_antecedents.find(c[i].var());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3266,6 +3271,7 @@ namespace sat {
|
||||||
literal_vector::iterator it = m_ext_antecedents.begin();
|
literal_vector::iterator it = m_ext_antecedents.begin();
|
||||||
literal_vector::iterator end = m_ext_antecedents.end();
|
literal_vector::iterator end = m_ext_antecedents.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
|
if (!check_domain(lit, *it)) return false;
|
||||||
s |= m_antecedents.find(it->var());
|
s |= m_antecedents.find(it->var());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -3274,28 +3280,46 @@ namespace sat {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
break;
|
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;
|
index_set s;
|
||||||
|
if (m_antecedents.contains(lit.var())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (assumptions.contains(lit)) {
|
if (assumptions.contains(lit)) {
|
||||||
s.insert(lit.index());
|
s.insert(lit.index());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (!extract_assumptions(lit, s)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
add_assumption(lit);
|
add_assumption(lit);
|
||||||
extract_assumptions(lit, s);
|
|
||||||
}
|
}
|
||||||
m_antecedents.insert(lit.var(), s);
|
m_antecedents.insert(lit.var(), s);
|
||||||
if (unfixed.contains(lit)) {
|
if (unfixed.contains(lit.var())) {
|
||||||
literal_vector cons;
|
literal_vector cons;
|
||||||
cons.push_back(lit);
|
cons.push_back(lit);
|
||||||
index_set::iterator it = s.begin(), end = s.end();
|
index_set::iterator it = s.begin(), end = s.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
cons.push_back(to_literal(*it));
|
cons.push_back(to_literal(*it));
|
||||||
}
|
}
|
||||||
unfixed.remove(lit);
|
unfixed.remove(lit.var());
|
||||||
conseq.push_back(cons);
|
conseq.push_back(cons);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::asymmetric_branching() {
|
void solver::asymmetric_branching() {
|
||||||
|
|
|
@ -33,7 +33,6 @@ Revision History:
|
||||||
#include"sat_iff3_finder.h"
|
#include"sat_iff3_finder.h"
|
||||||
#include"sat_probing.h"
|
#include"sat_probing.h"
|
||||||
#include"sat_mus.h"
|
#include"sat_mus.h"
|
||||||
#include"sat_sls.h"
|
|
||||||
#include"params.h"
|
#include"params.h"
|
||||||
#include"statistics.h"
|
#include"statistics.h"
|
||||||
#include"stopwatch.h"
|
#include"stopwatch.h"
|
||||||
|
@ -86,7 +85,6 @@ namespace sat {
|
||||||
asymm_branch m_asymm_branch;
|
asymm_branch m_asymm_branch;
|
||||||
probing m_probing;
|
probing m_probing;
|
||||||
mus m_mus; // MUS for minimal core extraction
|
mus m_mus; // MUS for minimal core extraction
|
||||||
wsls m_wsls; // SLS facility for MaxSAT use
|
|
||||||
bool m_inconsistent;
|
bool m_inconsistent;
|
||||||
// A conflict is usually a single justification. That is, a justification
|
// 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
|
// 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 probing;
|
||||||
friend class iff3_finder;
|
friend class iff3_finder;
|
||||||
friend class mus;
|
friend class mus;
|
||||||
friend class sls;
|
|
||||||
friend class wsls;
|
|
||||||
friend class bceq;
|
|
||||||
friend struct mk_stat;
|
friend struct mk_stat;
|
||||||
public:
|
public:
|
||||||
solver(params_ref const & p, reslimit& l, extension * ext);
|
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);
|
void mk_bin_clause(literal l1, literal l2, bool learned);
|
||||||
bool propagate_bin_clause(literal l1, literal l2);
|
bool propagate_bin_clause(literal l1, literal l2);
|
||||||
clause * mk_ter_clause(literal * lits, bool learned);
|
clause * mk_ter_clause(literal * lits, bool learned);
|
||||||
void attach_ter_clause(clause & c, bool & reinit);
|
bool attach_ter_clause(clause & c);
|
||||||
void attach_ter_clause(clause & c) { bool reinit; attach_ter_clause(c, reinit); }
|
|
||||||
clause * mk_nary_clause(unsigned num_lits, literal * lits, bool learned);
|
clause * mk_nary_clause(unsigned num_lits, literal * lits, bool learned);
|
||||||
void attach_nary_clause(clause & c, bool & reinit);
|
bool attach_nary_clause(clause & c);
|
||||||
void attach_nary_clause(clause & c) { bool reinit; attach_nary_clause(c, reinit); }
|
|
||||||
void attach_clause(clause & c, bool & reinit);
|
void attach_clause(clause & c, bool & reinit);
|
||||||
void attach_clause(clause & c) { bool reinit; attach_clause(c, reinit); }
|
void attach_clause(clause & c) { bool reinit; attach_clause(c, reinit); }
|
||||||
unsigned select_watch_lit(clause const & cls, unsigned starting_at) const;
|
unsigned select_watch_lit(clause const & cls, unsigned starting_at) const;
|
||||||
|
@ -280,10 +273,7 @@ namespace sat {
|
||||||
//
|
//
|
||||||
// -----------------------
|
// -----------------------
|
||||||
public:
|
public:
|
||||||
lbool check(unsigned num_lits = 0, literal const* lits = 0) {
|
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);
|
|
||||||
|
|
||||||
model const & get_model() const { return m_model; }
|
model const & get_model() const { return m_model; }
|
||||||
bool model_is_current() const { return m_model_is_current; }
|
bool model_is_current() const { return m_model_is_current; }
|
||||||
|
@ -311,11 +301,7 @@ namespace sat {
|
||||||
|
|
||||||
literal_vector m_min_core;
|
literal_vector m_min_core;
|
||||||
bool m_min_core_valid;
|
bool m_min_core_valid;
|
||||||
literal_vector m_blocker;
|
void init_assumptions(unsigned num_lits, literal const* lits);
|
||||||
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 reassert_min_core();
|
void reassert_min_core();
|
||||||
void update_min_core();
|
void update_min_core();
|
||||||
void resolve_weighted();
|
void resolve_weighted();
|
||||||
|
@ -453,15 +439,25 @@ namespace sat {
|
||||||
u_map<index_set> m_antecedents;
|
u_map<index_set> m_antecedents;
|
||||||
vector<literal_vector> m_binary_clause_graph;
|
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);
|
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();
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
//
|
//
|
||||||
|
|
|
@ -105,13 +105,8 @@ public:
|
||||||
|
|
||||||
virtual void set_progress_callback(progress_callback * callback) {}
|
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) {
|
void display_weighted(std::ostream& out, unsigned sz, expr * const * assumptions, unsigned const* weights) {
|
||||||
m_weights.reset();
|
|
||||||
if (weights != 0) {
|
if (weights != 0) {
|
||||||
for (unsigned i = 0; i < sz; ++i) m_weights.push_back(weights[i]);
|
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) {
|
for (unsigned i = 0; i < m_asms.size(); ++i) {
|
||||||
nweights.push_back((unsigned) m_weights[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());
|
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) {
|
virtual lbool check_sat(unsigned sz, expr * const * assumptions) {
|
||||||
m_weights.reset();
|
|
||||||
if (weights != 0) {
|
|
||||||
m_weights.append(sz, weights);
|
|
||||||
}
|
|
||||||
SASSERT(m_weights.empty() == (m_weights.c_ptr() == 0));
|
|
||||||
m_solver.pop_to_base_level();
|
m_solver.pop_to_base_level();
|
||||||
dep2asm_t dep2asm;
|
dep2asm_t dep2asm;
|
||||||
m_model = 0;
|
m_model = 0;
|
||||||
|
@ -148,10 +139,10 @@ public:
|
||||||
r = internalize_assumptions(sz, assumptions, dep2asm);
|
r = internalize_assumptions(sz, assumptions, dep2asm);
|
||||||
if (r != l_true) return r;
|
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) {
|
switch (r) {
|
||||||
case l_true:
|
case l_true:
|
||||||
if (sz > 0 && !weights) {
|
if (sz > 0) {
|
||||||
check_assumptions(dep2asm);
|
check_assumptions(dep2asm);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -252,12 +243,17 @@ public:
|
||||||
m_solver.pop_to_base_level();
|
m_solver.pop_to_base_level();
|
||||||
lbool r = internalize_formulas();
|
lbool r = internalize_formulas();
|
||||||
if (r != l_true) return r;
|
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);
|
r = internalize_assumptions(assumptions.size(), assumptions.c_ptr(), dep2asm);
|
||||||
if (r != l_true) return r;
|
if (r != l_true) return r;
|
||||||
r = internalize_vars(vars, bvars);
|
|
||||||
|
|
||||||
r = m_solver.get_consequences(m_asms, bvars, lconseq);
|
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
|
// build map from bound variables to
|
||||||
// the consequences that cover them.
|
// 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) {
|
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);
|
inc_sat_solver& s = dynamic_cast<inc_sat_solver&>(_s);
|
||||||
vector<unsigned> weights;
|
vector<unsigned> weights;
|
||||||
|
|
|
@ -24,7 +24,6 @@ Notes:
|
||||||
|
|
||||||
solver* mk_inc_sat_solver(ast_manager& m, params_ref const& p);
|
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);
|
void inc_sat_display(std::ostream& out, solver& s, unsigned sz, expr*const* soft, rational const* _weights);
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ Revision History:
|
||||||
#include"opt_cmds.h"
|
#include"opt_cmds.h"
|
||||||
#include"polynomial_cmds.h"
|
#include"polynomial_cmds.h"
|
||||||
#include"subpaving_cmds.h"
|
#include"subpaving_cmds.h"
|
||||||
|
#include"smt2_extra_cmds.h"
|
||||||
#include"smt_strategic_solver.h"
|
#include"smt_strategic_solver.h"
|
||||||
#include"smt_solver.h"
|
#include"smt_solver.h"
|
||||||
|
|
||||||
|
@ -113,6 +114,7 @@ unsigned read_smtlib2_commands(char const * file_name) {
|
||||||
install_polynomial_cmds(ctx);
|
install_polynomial_cmds(ctx);
|
||||||
install_subpaving_cmds(ctx);
|
install_subpaving_cmds(ctx);
|
||||||
install_opt_cmds(ctx);
|
install_opt_cmds(ctx);
|
||||||
|
install_smt2_extra_cmds(ctx);
|
||||||
|
|
||||||
g_cmd_context = &ctx;
|
g_cmd_context = &ctx;
|
||||||
signal(SIGINT, on_ctrl_c);
|
signal(SIGINT, on_ctrl_c);
|
||||||
|
|
|
@ -184,13 +184,13 @@ void asserted_formulas::get_assertions(ptr_vector<expr> & result) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void asserted_formulas::push_scope() {
|
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););
|
TRACE("asserted_formulas_scopes", tout << "push:\n"; display(tout););
|
||||||
m_scopes.push_back(scope());
|
m_scopes.push_back(scope());
|
||||||
m_macro_manager.push_scope();
|
m_macro_manager.push_scope();
|
||||||
scope & s = m_scopes.back();
|
scope & s = m_scopes.back();
|
||||||
s.m_asserted_formulas_lim = m_asserted_formulas.size();
|
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;
|
s.m_inconsistent_old = m_inconsistent;
|
||||||
m_defined_names.push();
|
m_defined_names.push();
|
||||||
m_bv_sharing.push_scope();
|
m_bv_sharing.push_scope();
|
||||||
|
|
|
@ -17,7 +17,7 @@ def_module_params(module_name='smt',
|
||||||
('pull_nested_quantifiers', BOOL, False, 'pull nested quantifiers'),
|
('pull_nested_quantifiers', BOOL, False, 'pull nested quantifiers'),
|
||||||
('refine_inj_axioms', BOOL, True, 'refine injectivity axioms'),
|
('refine_inj_axioms', BOOL, True, 'refine injectivity axioms'),
|
||||||
('timeout', UINT, UINT_MAX, 'timeout (in milliseconds) (UINT_MAX and 0 mean no timeout)'),
|
('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.'),
|
('max_conflicts', UINT, UINT_MAX, 'maximum number of conflicts before giving up.'),
|
||||||
('mbqi', BOOL, True, 'model based quantifier instantiation (MBQI)'),
|
('mbqi', BOOL, True, 'model based quantifier instantiation (MBQI)'),
|
||||||
('mbqi.max_cexs', UINT, 1, 'initial maximal number of counterexamples used in MBQI, each counterexample generates a quantifier instantiation'),
|
('mbqi.max_cexs', 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.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'),
|
('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.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')
|
||||||
))
|
))
|
||||||
|
|
47
src/smt/smt2_extra_cmds.cpp
Normal file
47
src/smt/smt2_extra_cmds.cpp
Normal 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
26
src/smt/smt2_extra_cmds.h
Normal 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_ */
|
|
@ -24,7 +24,9 @@ Revision History:
|
||||||
namespace smt {
|
namespace smt {
|
||||||
|
|
||||||
struct bool_var_data {
|
struct bool_var_data {
|
||||||
|
private:
|
||||||
b_justification m_justification;
|
b_justification m_justification;
|
||||||
|
public:
|
||||||
unsigned m_scope_lvl:24; //!< scope level of when the variable was assigned.
|
unsigned m_scope_lvl:24; //!< scope level of when the variable was assigned.
|
||||||
unsigned m_mark:1;
|
unsigned m_mark:1;
|
||||||
unsigned m_assumption:1;
|
unsigned m_assumption:1;
|
||||||
|
@ -46,6 +48,14 @@ namespace smt {
|
||||||
|
|
||||||
unsigned get_intern_level() const { return m_iscope_lvl; }
|
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; }
|
bool is_atom() const { return m_atom; }
|
||||||
|
|
||||||
theory_id get_theory() const {
|
theory_id get_theory() const {
|
||||||
|
|
|
@ -496,13 +496,15 @@ namespace smt {
|
||||||
|
|
||||||
unsigned idx = skip_literals_above_conflict_level();
|
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
|
// save space for first uip
|
||||||
m_lemma.push_back(null_literal);
|
m_lemma.push_back(null_literal);
|
||||||
m_lemma_atoms.push_back(0);
|
m_lemma_atoms.push_back(0);
|
||||||
|
|
||||||
unsigned num_marks = 0;
|
unsigned num_marks = 0;
|
||||||
if (not_l != null_literal) {
|
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);
|
process_antecedent(not_l, num_marks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,7 +516,7 @@ namespace smt {
|
||||||
get_manager().trace_stream() << "\n";
|
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";);
|
tout << "num_marks: " << num_marks << ", js kind: " << js.get_kind() << "\n";);
|
||||||
SASSERT(js != null_b_justification);
|
SASSERT(js != null_b_justification);
|
||||||
switch (js.get_kind()) {
|
switch (js.get_kind()) {
|
||||||
|
@ -1076,6 +1078,7 @@ namespace smt {
|
||||||
return true;
|
return true;
|
||||||
SASSERT(js.get_kind() != b_justification::BIN_CLAUSE);
|
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););
|
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)
|
if (js.get_kind() == b_justification::AXIOM)
|
||||||
return true;
|
return true;
|
||||||
SASSERT(js.get_kind() != b_justification::AXIOM);
|
SASSERT(js.get_kind() != b_justification::AXIOM);
|
||||||
|
@ -1089,14 +1092,17 @@ namespace smt {
|
||||||
i = 1;
|
i = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
SASSERT(cls->get_literal(1) == l);
|
||||||
if (get_proof(~cls->get_literal(0)) == 0)
|
if (get_proof(~cls->get_literal(0)) == 0)
|
||||||
visited = false;
|
visited = false;
|
||||||
i = 2;
|
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)
|
if (get_proof(~cls->get_literal(i)) == 0)
|
||||||
visited = false;
|
visited = false;
|
||||||
|
}
|
||||||
return visited;
|
return visited;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1251,14 +1257,19 @@ namespace smt {
|
||||||
}
|
}
|
||||||
tout << "\n";);
|
tout << "\n";);
|
||||||
init_mk_proof();
|
init_mk_proof();
|
||||||
literal consequent = false_literal;
|
literal consequent;
|
||||||
if (not_l != null_literal)
|
if (not_l == null_literal) {
|
||||||
consequent = ~not_l;
|
consequent = false_literal;
|
||||||
visit_b_justification(consequent, conflict);
|
}
|
||||||
if (not_l != null_literal)
|
else {
|
||||||
|
consequent = ~not_l;
|
||||||
m_todo_pr.push_back(tp_elem(not_l));
|
m_todo_pr.push_back(tp_elem(not_l));
|
||||||
|
}
|
||||||
|
visit_b_justification(consequent, conflict);
|
||||||
|
|
||||||
while (!m_todo_pr.empty()) {
|
while (!m_todo_pr.empty()) {
|
||||||
tp_elem & elem = m_todo_pr.back();
|
tp_elem & elem = m_todo_pr.back();
|
||||||
|
|
||||||
switch (elem.m_kind) {
|
switch (elem.m_kind) {
|
||||||
case tp_elem::EQUALITY: {
|
case tp_elem::EQUALITY: {
|
||||||
enode * lhs = elem.m_lhs;
|
enode * lhs = elem.m_lhs;
|
||||||
|
|
|
@ -261,10 +261,11 @@ namespace smt {
|
||||||
m_assignment[false_literal.index()] = l_false;
|
m_assignment[false_literal.index()] = l_false;
|
||||||
if (m_manager.proofs_enabled()) {
|
if (m_manager.proofs_enabled()) {
|
||||||
proof * pr = m_manager.mk_true_proof();
|
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 {
|
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);
|
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.
|
// internalizer is marking enodes as interpreted whenever the associated ast is a value and a constant.
|
||||||
|
@ -293,6 +294,12 @@ namespace smt {
|
||||||
return m_manager.mk_eq(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) {
|
void context::assign_core(literal l, b_justification j, bool decision) {
|
||||||
TRACE("assign_core", tout << (decision?"decision: ":"propagating: ") << l << " ";
|
TRACE("assign_core", tout << (decision?"decision: ":"propagating: ") << l << " ";
|
||||||
display_literal_verbose(tout, l); tout << " level: " << m_scope_lvl << "\n";
|
display_literal_verbose(tout, l); tout << " level: " << m_scope_lvl << "\n";
|
||||||
|
@ -302,7 +309,7 @@ namespace smt {
|
||||||
m_assignment[l.index()] = l_true;
|
m_assignment[l.index()] = l_true;
|
||||||
m_assignment[(~l).index()] = l_false;
|
m_assignment[(~l).index()] = l_false;
|
||||||
bool_var_data & d = get_bdata(l.var());
|
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;
|
d.m_scope_lvl = m_scope_lvl;
|
||||||
if (m_fparams.m_restart_adaptive && d.m_phase_available) {
|
if (m_fparams.m_restart_adaptive && d.m_phase_available) {
|
||||||
m_agility *= m_fparams.m_agility_factor;
|
m_agility *= m_fparams.m_agility_factor;
|
||||||
|
@ -1406,7 +1413,8 @@ namespace smt {
|
||||||
else {
|
else {
|
||||||
TRACE("add_diseq", display_eq_detail(tout, bool_var2enode(v)););
|
TRACE("add_diseq", display_eq_detail(tout, bool_var2enode(v)););
|
||||||
if (!add_diseq(get_enode(lhs), get_enode(rhs)) && !inconsistent()) {
|
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) {
|
void context::set_conflict(b_justification js, literal not_l) {
|
||||||
if (!inconsistent()) {
|
if (!inconsistent()) {
|
||||||
|
TRACE("set_conflict", display_literal_verbose(tout, not_l); display(tout, js); );
|
||||||
m_conflict = js;
|
m_conflict = js;
|
||||||
m_not_l = not_l;
|
m_not_l = not_l;
|
||||||
}
|
}
|
||||||
|
@ -2042,7 +2051,7 @@ namespace smt {
|
||||||
m_assignment[(~l).index()] = l_undef;
|
m_assignment[(~l).index()] = l_undef;
|
||||||
bool_var v = l.var();
|
bool_var v = l.var();
|
||||||
bool_var_data & d = get_bdata(v);
|
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);
|
m_case_split_queue->unassign_var_eh(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2593,10 +2602,10 @@ namespace smt {
|
||||||
cls->set_justification(0);
|
cls->set_justification(0);
|
||||||
m_justifications.push_back(js);
|
m_justifications.push_back(js);
|
||||||
}
|
}
|
||||||
m_bdata[v0].m_justification = b_justification(js);
|
set_justification(v0, m_bdata[v0], b_justification(js));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_bdata[v0].m_justification = b_justification::mk_axiom();
|
m_bdata[v0].set_axiom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
del_clause(cls);
|
del_clause(cls);
|
||||||
|
|
|
@ -220,10 +220,10 @@ namespace smt {
|
||||||
// Unsat core extraction
|
// Unsat core extraction
|
||||||
//
|
//
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
typedef u_map<expr *> literal2assumption;
|
typedef u_map<expr *> literal2assumption;
|
||||||
literal_vector m_assumptions;
|
literal_vector m_assumptions;
|
||||||
literal2assumption m_literal2assumption; // maps an expression associated with a literal to the original assumption
|
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;
|
||||||
|
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
//
|
//
|
||||||
|
@ -363,9 +363,11 @@ namespace smt {
|
||||||
void get_assignments(expr_ref_vector& assignments);
|
void get_assignments(expr_ref_vector& assignments);
|
||||||
|
|
||||||
b_justification get_justification(bool_var v) const {
|
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 {
|
bool has_th_justification(bool_var v, theory_id th_id) const {
|
||||||
b_justification js = get_justification(v);
|
b_justification js = get_justification(v);
|
||||||
return js.get_kind() == b_justification::JUSTIFICATION && js.get_justification()->get_from_theory() == th_id;
|
return js.get_kind() == b_justification::JUSTIFICATION && js.get_justification()->get_from_theory() == th_id;
|
||||||
|
@ -1381,6 +1383,8 @@ namespace smt {
|
||||||
void validate_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars,
|
void validate_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars,
|
||||||
expr_ref_vector const& conseq, expr_ref_vector const& unfixed);
|
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 justify(literal lit, index_set& s);
|
||||||
|
|
||||||
void extract_cores(expr_ref_vector const& asms, vector<expr_ref_vector>& cores, unsigned& min_core_size);
|
void extract_cores(expr_ref_vector const& asms, vector<expr_ref_vector>& cores, unsigned& min_core_size);
|
||||||
|
|
|
@ -402,6 +402,20 @@ namespace smt {
|
||||||
|
|
||||||
#endif
|
#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() {
|
bool context::validate_model() {
|
||||||
if (!m_proto_model) {
|
if (!m_proto_model) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -27,6 +27,8 @@ namespace smt {
|
||||||
out << "true";
|
out << "true";
|
||||||
else if (*this == false_literal)
|
else if (*this == false_literal)
|
||||||
out << "false";
|
out << "false";
|
||||||
|
else if (*this == null_literal)
|
||||||
|
out << "null";
|
||||||
else if (sign())
|
else if (sign())
|
||||||
out << "(not " << mk_pp(bool_var2expr_map[var()], m) << ")";
|
out << "(not " << mk_pp(bool_var2expr_map[var()], m) << ")";
|
||||||
else
|
else
|
||||||
|
|
|
@ -22,42 +22,62 @@ Notes:
|
||||||
#include"smt_params.h"
|
#include"smt_params.h"
|
||||||
#include"smt_params_helper.hpp"
|
#include"smt_params_helper.hpp"
|
||||||
#include"mus.h"
|
#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 {
|
namespace smt {
|
||||||
|
|
||||||
class solver : public solver_na2as {
|
class solver : public solver_na2as {
|
||||||
smt_params m_smt_params;
|
smt_params m_smt_params;
|
||||||
params_ref m_params;
|
params_ref m_params;
|
||||||
smt::kernel m_context;
|
smt::kernel m_context;
|
||||||
progress_callback * m_callback;
|
progress_callback * m_callback;
|
||||||
symbol m_logic;
|
symbol m_logic;
|
||||||
bool m_minimizing_core;
|
bool m_minimizing_core;
|
||||||
|
bool m_core_extend_patterns;
|
||||||
|
obj_map<expr, expr*> m_name2assertion;
|
||||||
|
|
||||||
public:
|
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),
|
solver_na2as(m),
|
||||||
m_smt_params(p),
|
m_smt_params(p),
|
||||||
m_params(p),
|
m_params(p),
|
||||||
m_context(m, m_smt_params),
|
m_context(m, m_smt_params),
|
||||||
m_minimizing_core(false) {
|
m_minimizing_core(false),
|
||||||
|
m_core_extend_patterns(false) {
|
||||||
m_logic = l;
|
m_logic = l;
|
||||||
if (m_logic != symbol::null)
|
if (m_logic != symbol::null)
|
||||||
m_context.set_logic(m_logic);
|
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) {
|
virtual solver * translate(ast_manager & m, params_ref const & p) {
|
||||||
solver* result = alloc(solver, m, p, m_logic);
|
solver * result = alloc(solver, m, p, m_logic);
|
||||||
smt::kernel::copy(m_context, result->m_context);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~solver() {
|
virtual ~solver() {
|
||||||
|
dec_ref_values(get_manager(), m_name2assertion);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updt_params(params_ref const & p) {
|
virtual void updt_params(params_ref const & p) {
|
||||||
m_smt_params.updt_params(p);
|
m_smt_params.updt_params(p);
|
||||||
m_params.copy(p);
|
m_params.copy(p);
|
||||||
m_context.updt_params(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) {
|
virtual void collect_param_descrs(param_descrs & r) {
|
||||||
|
@ -81,11 +101,32 @@ namespace smt {
|
||||||
m_context.assert_expr(t);
|
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() {
|
virtual void push_core() {
|
||||||
m_context.push();
|
m_context.push();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void pop_core(unsigned n) {
|
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);
|
m_context.pop(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +138,7 @@ namespace smt {
|
||||||
struct scoped_minimize_core {
|
struct scoped_minimize_core {
|
||||||
solver& s;
|
solver& s;
|
||||||
expr_ref_vector m_assumptions;
|
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_minimizing_core = true;
|
||||||
s.m_assumptions.reset();
|
s.m_assumptions.reset();
|
||||||
}
|
}
|
||||||
|
@ -114,17 +155,19 @@ namespace smt {
|
||||||
r.push_back(m_context.get_unsat_core_expr(i));
|
r.push_back(m_context.get_unsat_core_expr(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_minimizing_core || smt_params_helper(m_params).core_minimize() == false) {
|
if (m_minimizing_core && smt_params_helper(m_params).core_minimize()) {
|
||||||
return;
|
scoped_minimize_core scm(*this);
|
||||||
}
|
mus mus(*this);
|
||||||
scoped_minimize_core scm(*this);
|
mus.add_soft(r.size(), r.c_ptr());
|
||||||
mus mus(*this);
|
ptr_vector<expr> r2;
|
||||||
mus.add_soft(r.size(), r.c_ptr());
|
if (l_true == mus.get_mus(r2)) {
|
||||||
ptr_vector<expr> r2;
|
r.reset();
|
||||||
if (l_true == mus.get_mus(r2)) {
|
r.append(r2);
|
||||||
r.reset();
|
}
|
||||||
r.append(r2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_core_extend_patterns)
|
||||||
|
add_pattern_literals_to_core(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void get_model(model_ref & m) {
|
virtual void get_model(model_ref & m) {
|
||||||
|
@ -149,7 +192,7 @@ namespace smt {
|
||||||
r.append(tmp.size(), tmp.c_ptr());
|
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) {
|
virtual void set_progress_callback(progress_callback * callback) {
|
||||||
m_callback = callback;
|
m_callback = callback;
|
||||||
|
@ -165,6 +208,109 @@ namespace smt {
|
||||||
return m_context.get_formulas()[idx];
|
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());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ namespace smt {
|
||||||
|
|
||||||
final_check_status theory_wmaxsat::final_check_eh() {
|
final_check_status theory_wmaxsat::final_check_eh() {
|
||||||
if (m_normalize) normalize();
|
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;
|
return FC_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,6 @@ int main(int argc, char ** argv) {
|
||||||
TST(polynomial);
|
TST(polynomial);
|
||||||
TST(upolynomial);
|
TST(upolynomial);
|
||||||
TST(algebraic);
|
TST(algebraic);
|
||||||
TST(polynomial_factorization);
|
|
||||||
TST(prime_generator);
|
TST(prime_generator);
|
||||||
TST(permutation);
|
TST(permutation);
|
||||||
TST(nlsat);
|
TST(nlsat);
|
||||||
|
|
|
@ -18,7 +18,6 @@ Notes:
|
||||||
--*/
|
--*/
|
||||||
#if !defined(__clang__)
|
#if !defined(__clang__)
|
||||||
#include"polynomial.h"
|
#include"polynomial.h"
|
||||||
#include"polynomial_factorization.h"
|
|
||||||
#include"polynomial_var2value.h"
|
#include"polynomial_var2value.h"
|
||||||
#include"polynomial_cache.h"
|
#include"polynomial_cache.h"
|
||||||
#include"linear_eq_solver.h"
|
#include"linear_eq_solver.h"
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue