mirror of
https://github.com/Z3Prover/z3
synced 2025-04-10 19:27:06 +00:00
Merge branch 'master' of https://github.com/Z3Prover/z3
This commit is contained in:
commit
56c56e277b
|
@ -1,458 +0,0 @@
|
|||
|
||||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
--*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "z3.h"
|
||||
|
||||
|
||||
|
||||
int usage(const char **argv){
|
||||
std::cerr << "usage: " << argv[0] << " [options] file.smt" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "options:" << std::endl;
|
||||
std::cerr << " -t,--tree tree interpolation" << std::endl;
|
||||
std::cerr << " -c,--check check result" << std::endl;
|
||||
std::cerr << " -p,--profile profile execution" << std::endl;
|
||||
std::cerr << " -w,--weak weak interpolants" << std::endl;
|
||||
std::cerr << " -f,--flat ouput flat formulas" << std::endl;
|
||||
std::cerr << " -o <file> ouput to SMT-LIB file" << std::endl;
|
||||
std::cerr << " -a,--anon anonymize" << std::endl;
|
||||
std::cerr << " -s,--simple simple proof mode" << std::endl;
|
||||
std::cerr << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
|
||||
bool tree_mode = false;
|
||||
bool check_mode = false;
|
||||
bool profile_mode = false;
|
||||
bool incremental_mode = false;
|
||||
std::string output_file;
|
||||
bool flat_mode = false;
|
||||
bool anonymize = false;
|
||||
bool write = false;
|
||||
|
||||
Z3_config cfg = Z3_mk_config();
|
||||
// Z3_interpolation_options options = Z3_mk_interpolation_options();
|
||||
// Z3_params options = 0;
|
||||
|
||||
/* Parse the command line */
|
||||
int argn = 1;
|
||||
while(argn < argc-1){
|
||||
std::string flag = argv[argn];
|
||||
if(flag[0] == '-'){
|
||||
if(flag == "-t" || flag == "--tree")
|
||||
tree_mode = true;
|
||||
else if(flag == "-c" || flag == "--check")
|
||||
check_mode = true;
|
||||
else if(flag == "-p" || flag == "--profile")
|
||||
profile_mode = true;
|
||||
#if 0
|
||||
else if(flag == "-w" || flag == "--weak")
|
||||
Z3_set_interpolation_option(options,"weak","1");
|
||||
else if(flag == "--secondary")
|
||||
Z3_set_interpolation_option(options,"secondary","1");
|
||||
#endif
|
||||
else if(flag == "-i" || flag == "--incremental")
|
||||
incremental_mode = true;
|
||||
else if(flag == "-o"){
|
||||
argn++;
|
||||
if(argn >= argc) return usage(argv);
|
||||
output_file = argv[argn];
|
||||
}
|
||||
else if(flag == "-f" || flag == "--flat")
|
||||
flat_mode = true;
|
||||
else if(flag == "-a" || flag == "--anon")
|
||||
anonymize = true;
|
||||
else if(flag == "-w" || flag == "--write")
|
||||
write = true;
|
||||
else if(flag == "-s" || flag == "--simple")
|
||||
Z3_set_param_value(cfg,"PREPROCESS","false");
|
||||
else
|
||||
return usage(argv);
|
||||
}
|
||||
argn++;
|
||||
}
|
||||
if(argn != argc-1)
|
||||
return usage(argv);
|
||||
const char *filename = argv[argn];
|
||||
|
||||
|
||||
/* Create a Z3 context to contain formulas */
|
||||
Z3_context ctx = Z3_mk_interpolation_context(cfg);
|
||||
|
||||
if(write || anonymize)
|
||||
Z3_set_ast_print_mode(ctx,Z3_PRINT_SMTLIB2_COMPLIANT);
|
||||
else if(!flat_mode)
|
||||
Z3_set_ast_print_mode(ctx,Z3_PRINT_SMTLIB_COMPLIANT);
|
||||
|
||||
/* Read an interpolation problem */
|
||||
|
||||
unsigned num;
|
||||
Z3_ast *constraints;
|
||||
unsigned *parents = 0;
|
||||
const char *error;
|
||||
bool ok;
|
||||
unsigned num_theory;
|
||||
Z3_ast *theory;
|
||||
|
||||
ok = Z3_read_interpolation_problem(ctx, &num, &constraints, tree_mode ? &parents : 0, filename, &error, &num_theory, &theory) != 0;
|
||||
|
||||
/* If parse failed, print the error message */
|
||||
|
||||
if(!ok){
|
||||
std::cerr << error << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* if we get only one formula, and it is a conjunction, split it into conjuncts. */
|
||||
if(!tree_mode && num == 1){
|
||||
Z3_app app = Z3_to_app(ctx,constraints[0]);
|
||||
Z3_func_decl func = Z3_get_app_decl(ctx,app);
|
||||
Z3_decl_kind dk = Z3_get_decl_kind(ctx,func);
|
||||
if(dk == Z3_OP_AND){
|
||||
int nconjs = Z3_get_app_num_args(ctx,app);
|
||||
if(nconjs > 1){
|
||||
std::cout << "Splitting formula into " << nconjs << " conjuncts...\n";
|
||||
num = nconjs;
|
||||
constraints = new Z3_ast[num];
|
||||
for(unsigned k = 0; k < num; k++)
|
||||
constraints[k] = Z3_get_app_arg(ctx,app,k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out anonymized version. */
|
||||
|
||||
if(write || anonymize){
|
||||
#if 0
|
||||
Z3_anonymize_ast_vector(ctx,num,constraints);
|
||||
#endif
|
||||
std::string ofn = output_file.empty() ? "iz3out.smt2" : output_file;
|
||||
Z3_write_interpolation_problem(ctx, num, constraints, parents, ofn.c_str(), num_theory, theory);
|
||||
std::cout << "anonymized problem written to " << ofn << "\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Compute an interpolant, or get a model. */
|
||||
|
||||
Z3_ast *interpolants = (Z3_ast *)malloc((num-1) * sizeof(Z3_ast));
|
||||
Z3_model model = 0;
|
||||
Z3_lbool result;
|
||||
|
||||
if(!incremental_mode){
|
||||
/* In non-incremental mode, we just pass the constraints. */
|
||||
result = Z3_L_UNDEF; // FIXME: Z3_interpolate(ctx, num, constraints, parents, options, interpolants, &model, 0, false, num_theory, theory);
|
||||
}
|
||||
else {
|
||||
|
||||
/* This is a somewhat useless demonstration of incremental mode.
|
||||
Here, we assert the constraints in the context, then pass them to
|
||||
iZ3 in an array, so iZ3 knows the sequence. Note it's safe to pass
|
||||
"true", even though we haven't techically asserted if. */
|
||||
|
||||
Z3_push(ctx);
|
||||
std::vector<Z3_ast> asserted(num);
|
||||
|
||||
/* We start with nothing asserted. */
|
||||
for(unsigned i = 0; i < num; i++)
|
||||
asserted[i] = Z3_mk_true(ctx);
|
||||
|
||||
/* Now we assert the constrints one at a time until UNSAT. */
|
||||
|
||||
for(unsigned i = 0; i < num; i++){
|
||||
asserted[i] = constraints[i];
|
||||
Z3_assert_cnstr(ctx,constraints[i]); // assert one constraint
|
||||
result = Z3_L_UNDEF; // FIXME: Z3_interpolate(ctx, num, &asserted[0], parents, options, interpolants, &model, 0, true, 0, 0);
|
||||
if(result == Z3_L_FALSE){
|
||||
for(unsigned j = 0; j < num-1; j++)
|
||||
/* Since we want the interpolant formulas to survive a "pop", we
|
||||
"persist" them here. */
|
||||
Z3_persist_ast(ctx,interpolants[j],1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Z3_pop(ctx,1);
|
||||
}
|
||||
|
||||
switch (result) {
|
||||
|
||||
/* If UNSAT, print the interpolants */
|
||||
case Z3_L_FALSE:
|
||||
printf("unsat\n");
|
||||
if(output_file.empty()){
|
||||
printf("interpolant:\n");
|
||||
for(unsigned i = 0; i < num-1; i++)
|
||||
printf("%s\n", Z3_ast_to_string(ctx, interpolants[i]));
|
||||
}
|
||||
else {
|
||||
#if 0
|
||||
Z3_write_interpolation_problem(ctx,num-1,interpolants,0,output_file.c_str());
|
||||
printf("interpolant written to %s\n",output_file.c_str());
|
||||
#endif
|
||||
}
|
||||
#if 1
|
||||
if(check_mode){
|
||||
std::cout << "Checking interpolant...\n";
|
||||
bool chk;
|
||||
chk = Z3_check_interpolant(ctx,num,constraints,parents,interpolants,&error,num_theory,theory) != 0;
|
||||
if(chk)
|
||||
std::cout << "Interpolant is correct\n";
|
||||
else {
|
||||
std::cout << "Interpolant is incorrect\n";
|
||||
std::cout << error;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case Z3_L_UNDEF:
|
||||
printf("fail\n");
|
||||
break;
|
||||
case Z3_L_TRUE:
|
||||
printf("sat\n");
|
||||
printf("model:\n%s\n", Z3_model_to_string(ctx, model));
|
||||
break;
|
||||
}
|
||||
|
||||
if(profile_mode)
|
||||
std::cout << Z3_interpolation_profile(ctx);
|
||||
|
||||
/* Delete the model if there is one */
|
||||
|
||||
if (model)
|
||||
Z3_del_model(ctx, model);
|
||||
|
||||
/* Delete logical context. */
|
||||
|
||||
Z3_del_context(ctx);
|
||||
free(interpolants);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
|
||||
|
||||
int test(){
|
||||
int i;
|
||||
|
||||
/* Create a Z3 context to contain formulas */
|
||||
|
||||
Z3_config cfg = Z3_mk_config();
|
||||
Z3_context ctx = iz3_mk_context(cfg);
|
||||
|
||||
int num = 2;
|
||||
|
||||
Z3_ast *constraints = (Z3_ast *)malloc(num * sizeof(Z3_ast));
|
||||
|
||||
#if 1
|
||||
Z3_sort arr = Z3_mk_array_sort(ctx,Z3_mk_int_sort(ctx),Z3_mk_bool_sort(ctx));
|
||||
Z3_symbol as = Z3_mk_string_symbol(ctx, "a");
|
||||
Z3_symbol bs = Z3_mk_string_symbol(ctx, "b");
|
||||
Z3_symbol xs = Z3_mk_string_symbol(ctx, "x");
|
||||
|
||||
Z3_ast a = Z3_mk_const(ctx,as,arr);
|
||||
Z3_ast b = Z3_mk_const(ctx,bs,arr);
|
||||
Z3_ast x = Z3_mk_const(ctx,xs,Z3_mk_int_sort(ctx));
|
||||
|
||||
Z3_ast c1 = Z3_mk_eq(ctx,a,Z3_mk_store(ctx,b,x,Z3_mk_true(ctx)));
|
||||
Z3_ast c2 = Z3_mk_not(ctx,Z3_mk_select(ctx,a,x));
|
||||
#else
|
||||
Z3_symbol xs = Z3_mk_string_symbol(ctx, "x");
|
||||
Z3_ast x = Z3_mk_const(ctx,xs,Z3_mk_bool_sort(ctx));
|
||||
Z3_ast c1 = Z3_mk_eq(ctx,x,Z3_mk_true(ctx));
|
||||
Z3_ast c2 = Z3_mk_eq(ctx,x,Z3_mk_false(ctx));
|
||||
|
||||
#endif
|
||||
|
||||
constraints[0] = c1;
|
||||
constraints[1] = c2;
|
||||
|
||||
/* print out the result for grins. */
|
||||
|
||||
// Z3_string smtout = Z3_benchmark_to_smtlib_string (ctx, "foo", "QFLIA", "sat", "", num, constraints, Z3_mk_true(ctx));
|
||||
|
||||
// Z3_string smtout = Z3_ast_to_string(ctx,constraints[0]);
|
||||
// Z3_string smtout = Z3_context_to_string(ctx);
|
||||
// puts(smtout);
|
||||
|
||||
iz3_print(ctx,num,constraints,"iZ3temp.smt");
|
||||
|
||||
/* Make room for interpolants. */
|
||||
|
||||
Z3_ast *interpolants = (Z3_ast *)malloc((num-1) * sizeof(Z3_ast));
|
||||
|
||||
/* Make room for the model. */
|
||||
|
||||
Z3_model model = 0;
|
||||
|
||||
/* Call the prover */
|
||||
|
||||
Z3_lbool result = iz3_interpolate(ctx, num, constraints, interpolants, &model);
|
||||
|
||||
switch (result) {
|
||||
|
||||
/* If UNSAT, print the interpolants */
|
||||
case Z3_L_FALSE:
|
||||
printf("unsat, interpolants:\n");
|
||||
for(i = 0; i < num-1; i++)
|
||||
printf("%s\n", Z3_ast_to_string(ctx, interpolants[i]));
|
||||
break;
|
||||
case Z3_L_UNDEF:
|
||||
printf("fail\n");
|
||||
break;
|
||||
case Z3_L_TRUE:
|
||||
printf("sat\n");
|
||||
printf("model:\n%s\n", Z3_model_to_string(ctx, model));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Delete the model if there is one */
|
||||
|
||||
if (model)
|
||||
Z3_del_model(ctx, model);
|
||||
|
||||
/* Delete logical context (note, we call iz3_del_context, not
|
||||
Z3_del_context */
|
||||
|
||||
iz3_del_context(ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct z3_error {
|
||||
Z3_error_code c;
|
||||
z3_error(Z3_error_code _c) : c(_c) {}
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
static void throw_z3_error(Z3_error_code c){
|
||||
throw z3_error(c);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
|
||||
/* Create a Z3 context to contain formulas */
|
||||
|
||||
Z3_config cfg = Z3_mk_config();
|
||||
Z3_context ctx = iz3_mk_context(cfg);
|
||||
Z3_set_error_handler(ctx, throw_z3_error);
|
||||
|
||||
/* Make some constraints, by parsing an smtlib formatted file given as arg 1 */
|
||||
|
||||
try {
|
||||
Z3_parse_smtlib_file(ctx, argv[1], 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
catch(const z3_error &err){
|
||||
std::cerr << "Z3 error: " << Z3_get_error_msg(err.c) << "\n";
|
||||
std::cerr << Z3_get_smtlib_error(ctx) << "\n";
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Get the constraints from the parser. */
|
||||
|
||||
int num = Z3_get_smtlib_num_formulas(ctx);
|
||||
|
||||
if(num == 0){
|
||||
std::cerr << "iZ3 error: File contains no formulas.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Z3_ast *constraints = (Z3_ast *)malloc(num * sizeof(Z3_ast));
|
||||
|
||||
int i;
|
||||
for (i = 0; i < num; i++)
|
||||
constraints[i] = Z3_get_smtlib_formula(ctx, i);
|
||||
|
||||
/* if we get only one formula, and it is a conjunction, split it into conjuncts. */
|
||||
if(num == 1){
|
||||
Z3_app app = Z3_to_app(ctx,constraints[0]);
|
||||
Z3_func_decl func = Z3_get_app_decl(ctx,app);
|
||||
Z3_decl_kind dk = Z3_get_decl_kind(ctx,func);
|
||||
if(dk == Z3_OP_AND){
|
||||
int nconjs = Z3_get_app_num_args(ctx,app);
|
||||
if(nconjs > 1){
|
||||
std::cout << "Splitting formula into " << nconjs << " conjuncts...\n";
|
||||
num = nconjs;
|
||||
constraints = new Z3_ast[num];
|
||||
for(int k = 0; k < num; k++)
|
||||
constraints[k] = Z3_get_app_arg(ctx,app,k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* print out the result for grins. */
|
||||
|
||||
// Z3_string smtout = Z3_benchmark_to_smtlib_string (ctx, "foo", "QFLIA", "sat", "", num, constraints, Z3_mk_true(ctx));
|
||||
|
||||
// Z3_string smtout = Z3_ast_to_string(ctx,constraints[0]);
|
||||
// Z3_string smtout = Z3_context_to_string(ctx);
|
||||
// puts(smtout);
|
||||
|
||||
// iz3_print(ctx,num,constraints,"iZ3temp.smt");
|
||||
|
||||
/* Make room for interpolants. */
|
||||
|
||||
Z3_ast *interpolants = (Z3_ast *)malloc((num-1) * sizeof(Z3_ast));
|
||||
|
||||
/* Make room for the model. */
|
||||
|
||||
Z3_model model = 0;
|
||||
|
||||
/* Call the prover */
|
||||
|
||||
Z3_lbool result = iz3_interpolate(ctx, num, constraints, interpolants, &model);
|
||||
|
||||
switch (result) {
|
||||
|
||||
/* If UNSAT, print the interpolants */
|
||||
case Z3_L_FALSE:
|
||||
printf("unsat, interpolants:\n");
|
||||
for(i = 0; i < num-1; i++)
|
||||
printf("%s\n", Z3_ast_to_string(ctx, interpolants[i]));
|
||||
std::cout << "Checking interpolants...\n";
|
||||
const char *error;
|
||||
if(iZ3_check_interpolant(ctx, num, constraints, 0, interpolants, &error))
|
||||
std::cout << "Interpolant is correct\n";
|
||||
else {
|
||||
std::cout << "Interpolant is incorrect\n";
|
||||
std::cout << error << "\n";
|
||||
}
|
||||
break;
|
||||
case Z3_L_UNDEF:
|
||||
printf("fail\n");
|
||||
break;
|
||||
case Z3_L_TRUE:
|
||||
printf("sat\n");
|
||||
printf("model:\n%s\n", Z3_model_to_string(ctx, model));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Delete the model if there is one */
|
||||
|
||||
if (model)
|
||||
Z3_del_model(ctx, model);
|
||||
|
||||
/* Delete logical context (note, we call iz3_del_context, not
|
||||
Z3_del_context */
|
||||
|
||||
iz3_del_context(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -94,7 +94,6 @@ def init_project_def():
|
|||
set_z3py_dir('api/python')
|
||||
# Examples
|
||||
add_cpp_example('cpp_example', 'c++')
|
||||
add_cpp_example('iz3', 'interp')
|
||||
add_cpp_example('z3_tptp', 'tptp')
|
||||
add_c_example('c_example', 'c')
|
||||
add_c_example('maxsat')
|
||||
|
|
|
@ -90,7 +90,13 @@ FPMATH="Default"
|
|||
FPMATH_FLAGS="-mfpmath=sse -msse -msse2"
|
||||
|
||||
def check_output(cmd):
|
||||
return (subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]).decode("utf-8").rstrip('\r\n')
|
||||
out = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
|
||||
if out != None:
|
||||
enc = sys.stdout.encoding
|
||||
if enc != None: return out.decode(enc).rstrip('\r\n')
|
||||
else: return out.rstrip('\r\n')
|
||||
else:
|
||||
return ""
|
||||
|
||||
def git_hash():
|
||||
try:
|
||||
|
@ -2586,7 +2592,7 @@ def mk_z3consts_py(api_files):
|
|||
if Z3PY_SRC_DIR is None:
|
||||
raise MKException("You must invoke set_z3py_dir(path):")
|
||||
|
||||
blank_pat = re.compile("^ *$")
|
||||
blank_pat = re.compile("^ *\r?$")
|
||||
comment_pat = re.compile("^ *//.*$")
|
||||
typedef_pat = re.compile("typedef enum *")
|
||||
typedef2_pat = re.compile("typedef enum { *")
|
||||
|
@ -2647,6 +2653,8 @@ def mk_z3consts_py(api_files):
|
|||
z3consts.write('%s = %s\n' % (k, i))
|
||||
z3consts.write('\n')
|
||||
mode = SEARCHING
|
||||
elif len(words) <= 2:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
if words[2] != '':
|
||||
if len(words[2]) > 1 and words[2][1] == 'x':
|
||||
|
@ -2664,7 +2672,7 @@ def mk_z3consts_py(api_files):
|
|||
|
||||
# Extract enumeration types from z3_api.h, and add .Net definitions
|
||||
def mk_z3consts_dotnet(api_files):
|
||||
blank_pat = re.compile("^ *$")
|
||||
blank_pat = re.compile("^ *\r?$")
|
||||
comment_pat = re.compile("^ *//.*$")
|
||||
typedef_pat = re.compile("typedef enum *")
|
||||
typedef2_pat = re.compile("typedef enum { *")
|
||||
|
@ -2734,6 +2742,8 @@ def mk_z3consts_dotnet(api_files):
|
|||
z3consts.write(' %s = %s,\n' % (k, i))
|
||||
z3consts.write(' }\n\n')
|
||||
mode = SEARCHING
|
||||
elif len(words) <= 2:
|
||||
assert False, "Invalid %s, line: %s" % (api_file, linenum)
|
||||
else:
|
||||
if words[2] != '':
|
||||
if len(words[2]) > 1 and words[2][1] == 'x':
|
||||
|
|
|
@ -96,7 +96,12 @@ if sys.version < '3':
|
|||
return s
|
||||
else:
|
||||
def _to_pystr(s):
|
||||
return s.decode('utf-8')
|
||||
if s != None:
|
||||
enc = sys.stdout.encoding
|
||||
if enc != None: return s.decode(enc)
|
||||
else: return s.decode('ascii')
|
||||
else:
|
||||
return ""
|
||||
|
||||
def init(PATH):
|
||||
global _lib
|
||||
|
|
|
@ -187,7 +187,8 @@ extern "C" {
|
|||
MK_BINARY(Z3_mk_set_difference, mk_c(c)->get_array_fid(), OP_SET_DIFFERENCE, SKIP);
|
||||
MK_UNARY(Z3_mk_set_complement, mk_c(c)->get_array_fid(), OP_SET_COMPLEMENT, SKIP);
|
||||
MK_BINARY(Z3_mk_set_subset, mk_c(c)->get_array_fid(), OP_SET_SUBSET, SKIP);
|
||||
|
||||
MK_BINARY(Z3_mk_array_ext, mk_c(c)->get_array_fid(), OP_ARRAY_EXT, SKIP);
|
||||
|
||||
Z3_ast Z3_mk_set_member(Z3_context c, Z3_ast elem, Z3_ast set) {
|
||||
return Z3_mk_select(c, set, elem);
|
||||
}
|
||||
|
|
|
@ -1012,6 +1012,7 @@ extern "C" {
|
|||
case OP_SET_COMPLEMENT: return Z3_OP_SET_COMPLEMENT;
|
||||
case OP_SET_SUBSET: return Z3_OP_SET_SUBSET;
|
||||
case OP_AS_ARRAY: return Z3_OP_AS_ARRAY;
|
||||
case OP_ARRAY_EXT: return Z3_OP_ARRAY_EXT;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Z3_OP_UNINTERPRETED;
|
||||
|
|
|
@ -103,9 +103,7 @@ namespace api {
|
|||
|
||||
m_smtlib_parser = 0;
|
||||
m_smtlib_parser_has_decls = false;
|
||||
|
||||
z3_bound_num_procs();
|
||||
|
||||
|
||||
m_error_handler = &default_error_handler;
|
||||
|
||||
m_basic_fid = m().get_basic_family_id();
|
||||
|
|
|
@ -97,6 +97,20 @@ extern "C" {
|
|||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_solver Z3_API Z3_solver_translate(Z3_context c, Z3_solver s, Z3_context target) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_translate(c, s, target);
|
||||
RESET_ERROR_CODE();
|
||||
params_ref const& p = to_solver(s)->m_params;
|
||||
Z3_solver_ref * sr = alloc(Z3_solver_ref, 0);
|
||||
init_solver(c, s);
|
||||
sr->m_solver = to_solver(s)->m_solver->translate(mk_c(target)->m(), p);
|
||||
mk_c(target)->save_object(sr);
|
||||
Z3_solver r = of_solver(sr);
|
||||
RETURN_Z3(r);
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
Z3_string Z3_API Z3_solver_get_help(Z3_context c, Z3_solver s) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_solver_get_help(c, s);
|
||||
|
|
|
@ -23,6 +23,8 @@ Revision History:
|
|||
#include"api_context.h"
|
||||
#include"api_model.h"
|
||||
#include"cancel_eh.h"
|
||||
#include"scoped_timer.h"
|
||||
#include"rlimit.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
@ -34,7 +36,7 @@ extern "C" {
|
|||
mk_c(c)->push();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
|
||||
void Z3_API Z3_pop(Z3_context c, unsigned num_scopes) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_pop(c, num_scopes);
|
||||
|
@ -62,7 +64,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_assert_cnstr(c, a);
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_FORMULA(a,);
|
||||
CHECK_FORMULA(a,);
|
||||
mk_c(c)->assert_cnstr(to_expr(a));
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
@ -75,17 +77,22 @@ extern "C" {
|
|||
cancel_eh<smt::kernel> eh(mk_c(c)->get_smt_kernel());
|
||||
api::context::set_interruptable si(*(mk_c(c)), eh);
|
||||
flet<bool> _model(mk_c(c)->fparams().m_model, true);
|
||||
unsigned timeout = mk_c(c)->params().m_timeout;
|
||||
unsigned rlimit = mk_c(c)->params().m_rlimit;
|
||||
lbool result;
|
||||
try {
|
||||
scoped_timer timer(timeout, &eh);
|
||||
scoped_rlimit _rlimit(mk_c(c)->m().limit(), rlimit);
|
||||
|
||||
model_ref _m;
|
||||
result = mk_c(c)->check(_m);
|
||||
if (m) {
|
||||
if (_m) {
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
m_ref->m_model = _m;
|
||||
// Must bump reference counter for backward compatibility reasons.
|
||||
// Don't need to invoke save_object, since the counter was bumped
|
||||
m_ref->inc_ref();
|
||||
m_ref->inc_ref();
|
||||
*m = of_model(m_ref);
|
||||
}
|
||||
else {
|
||||
|
@ -100,21 +107,21 @@ extern "C" {
|
|||
RETURN_Z3_check_and_get_model static_cast<Z3_lbool>(result);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
|
||||
Z3_lbool Z3_API Z3_check(Z3_context c) {
|
||||
Z3_TRY;
|
||||
// This is just syntax sugar...
|
||||
RESET_ERROR_CODE();
|
||||
// This is just syntax sugar...
|
||||
RESET_ERROR_CODE();
|
||||
CHECK_SEARCHING(c);
|
||||
Z3_lbool r = Z3_check_and_get_model(c, 0);
|
||||
return r;
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
|
||||
Z3_lbool Z3_API Z3_check_assumptions(Z3_context c,
|
||||
unsigned num_assumptions, Z3_ast const assumptions[],
|
||||
Z3_model * m, Z3_ast* proof,
|
||||
|
||||
Z3_lbool Z3_API Z3_check_assumptions(Z3_context c,
|
||||
unsigned num_assumptions, Z3_ast const assumptions[],
|
||||
Z3_model * m, Z3_ast* proof,
|
||||
unsigned* core_size, Z3_ast core[]) {
|
||||
Z3_TRY;
|
||||
LOG_Z3_check_assumptions(c, num_assumptions, assumptions, m, proof, core_size, core);
|
||||
|
@ -130,11 +137,11 @@ extern "C" {
|
|||
model_ref _m;
|
||||
mk_c(c)->get_smt_kernel().get_model(_m);
|
||||
if (_m) {
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
Z3_model_ref * m_ref = alloc(Z3_model_ref);
|
||||
m_ref->m_model = _m;
|
||||
// Must bump reference counter for backward compatibility reasons.
|
||||
// Don't need to invoke save_object, since the counter was bumped
|
||||
m_ref->inc_ref();
|
||||
m_ref->inc_ref();
|
||||
*m = of_model(m_ref);
|
||||
}
|
||||
else {
|
||||
|
@ -159,7 +166,7 @@ extern "C" {
|
|||
else if (proof) {
|
||||
*proof = 0; // breaks abstraction.
|
||||
}
|
||||
RETURN_Z3_check_assumptions static_cast<Z3_lbool>(result);
|
||||
RETURN_Z3_check_assumptions static_cast<Z3_lbool>(result);
|
||||
Z3_CATCH_RETURN(Z3_L_UNDEF);
|
||||
}
|
||||
|
||||
|
@ -185,7 +192,7 @@ extern "C" {
|
|||
symbol const& get_label() const { return m_label; }
|
||||
expr* get_literal() { return m_literal.get(); }
|
||||
};
|
||||
|
||||
|
||||
typedef vector<labeled_literal> labels;
|
||||
|
||||
Z3_literals Z3_API Z3_get_relevant_labels(Z3_context c) {
|
||||
|
@ -196,7 +203,7 @@ extern "C" {
|
|||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
mk_c(c)->get_smt_kernel().get_relevant_labels(0, labl_syms);
|
||||
mk_c(c)->get_smt_kernel().get_relevant_labeled_literals(mk_c(c)->fparams().m_at_labels_cex, lits);
|
||||
mk_c(c)->get_smt_kernel().get_relevant_labeled_literals(mk_c(c)->fparams().m_at_labels_cex, lits);
|
||||
labels* lbls = alloc(labels);
|
||||
SASSERT(labl_syms.size() == lits.size());
|
||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||
|
@ -212,12 +219,12 @@ extern "C" {
|
|||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
mk_c(c)->get_smt_kernel().get_relevant_literals(lits);
|
||||
mk_c(c)->get_smt_kernel().get_relevant_literals(lits);
|
||||
labels* lbls = alloc(labels);
|
||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||
lbls->push_back(labeled_literal(m,lits[i].get()));
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_literals>(lbls));
|
||||
RETURN_Z3(reinterpret_cast<Z3_literals>(lbls));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -227,12 +234,12 @@ extern "C" {
|
|||
RESET_ERROR_CODE();
|
||||
ast_manager& m = mk_c(c)->m();
|
||||
expr_ref_vector lits(m);
|
||||
mk_c(c)->get_smt_kernel().get_guessed_literals(lits);
|
||||
mk_c(c)->get_smt_kernel().get_guessed_literals(lits);
|
||||
labels* lbls = alloc(labels);
|
||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||
lbls->push_back(labeled_literal(m,lits[i].get()));
|
||||
}
|
||||
RETURN_Z3(reinterpret_cast<Z3_literals>(lbls));
|
||||
RETURN_Z3(reinterpret_cast<Z3_literals>(lbls));
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -248,7 +255,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_num_literals(c, lbls);
|
||||
RESET_ERROR_CODE();
|
||||
return reinterpret_cast<labels*>(lbls)->size();
|
||||
return reinterpret_cast<labels*>(lbls)->size();
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -256,7 +263,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_get_label_symbol(c, lbls, idx);
|
||||
RESET_ERROR_CODE();
|
||||
return of_symbol((*reinterpret_cast<labels*>(lbls))[idx].get_label());
|
||||
return of_symbol((*reinterpret_cast<labels*>(lbls))[idx].get_label());
|
||||
Z3_CATCH_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -274,7 +281,7 @@ extern "C" {
|
|||
Z3_TRY;
|
||||
LOG_Z3_disable_literal(c, lbls, idx);
|
||||
RESET_ERROR_CODE();
|
||||
(*reinterpret_cast<labels*>(lbls))[idx].disable();
|
||||
(*reinterpret_cast<labels*>(lbls))[idx].disable();
|
||||
Z3_CATCH;
|
||||
}
|
||||
|
||||
|
@ -348,4 +355,4 @@ void Z3_display_statistics(Z3_context c, std::ostream& s) {
|
|||
void Z3_display_istatistics(Z3_context c, std::ostream& s) {
|
||||
mk_c(c)->get_smt_kernel().display_istatistics(s);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1359,9 +1359,13 @@ namespace z3 {
|
|||
Z3_solver_inc_ref(ctx(), s);
|
||||
}
|
||||
public:
|
||||
struct simple {};
|
||||
struct translate {};
|
||||
solver(context & c):object(c) { init(Z3_mk_solver(c)); }
|
||||
solver(context & c, simple):object(c) { init(Z3_mk_simple_solver(c)); }
|
||||
solver(context & c, Z3_solver s):object(c) { init(s); }
|
||||
solver(context & c, char const * logic):object(c) { init(Z3_mk_solver_for_logic(c, c.str_symbol(logic))); }
|
||||
solver(context & c, solver const& src, translate): object(c) { init(Z3_solver_translate(src.ctx(), src, c)); }
|
||||
solver(solver const & s):object(s) { init(s.m_solver); }
|
||||
~solver() { Z3_solver_dec_ref(ctx(), m_solver); }
|
||||
operator Z3_solver() const { return m_solver; }
|
||||
|
|
|
@ -2122,6 +2122,21 @@ namespace Microsoft.Z3
|
|||
CheckContextMatch(array);
|
||||
return Expr.Create(this, Native.Z3_mk_array_default(nCtx, array.NativeObject));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create Extentionality index. Two arrays are equal if and only if they are equal on the index returned by MkArrayExt.
|
||||
/// </summary>
|
||||
public Expr MkArrayExt(ArrayExpr arg1, ArrayExpr arg2)
|
||||
{
|
||||
Contract.Requires(arg1 != null);
|
||||
Contract.Requires(arg2 != null);
|
||||
Contract.Ensures(Contract.Result<Expr>() != null);
|
||||
|
||||
CheckContextMatch(arg1);
|
||||
CheckContextMatch(arg2);
|
||||
return Expr.Create(this, Native.Z3_mk_array_ext(nCtx, arg1.NativeObject, arg2.NativeObject));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sets
|
||||
|
@ -2268,6 +2283,7 @@ namespace Microsoft.Z3
|
|||
CheckContextMatch(arg2);
|
||||
return (BoolExpr) Expr.Create(this, Native.Z3_mk_set_subset(nCtx, arg1.NativeObject, arg2.NativeObject));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Pseudo-Boolean constraints
|
||||
|
@ -2597,8 +2613,13 @@ namespace Microsoft.Z3
|
|||
/// <paramref name="patterns"/> is an array of patterns, <paramref name="sorts"/> is an array
|
||||
/// with the sorts of the bound variables, <paramref name="names"/> is an array with the
|
||||
/// 'names' of the bound variables, and <paramref name="body"/> is the body of the
|
||||
/// quantifier. Quantifiers are associated with weights indicating
|
||||
/// the importance of using the quantifier during instantiation.
|
||||
/// quantifier. Quantifiers are associated with weights indicating the importance of
|
||||
/// using the quantifier during instantiation.
|
||||
/// Note that the bound variables are de-Bruijn indices created using <see cref="MkBound"/>.
|
||||
/// Z3 applies the convention that the last element in <paramref name="names"/> and
|
||||
/// <paramref name="sorts"/> refers to the variable with index 0, the second to last element
|
||||
/// of <paramref name="names"/> and <paramref name="sorts"/> refers to the variable
|
||||
/// with index 1, etc.
|
||||
/// </remarks>
|
||||
/// <param name="sorts">the sorts of the bound variables.</param>
|
||||
/// <param name="names">names of the bound variables</param>
|
||||
|
@ -2628,6 +2649,11 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create a universal Quantifier.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates a universal quantifier using a list of constants that will
|
||||
/// form the set of bound variables.
|
||||
/// <seealso cref="MkForall(Sort[], Symbol[], Expr, uint, Pattern[], Expr[], Symbol, Symbol)"/>
|
||||
/// </remarks>
|
||||
public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
|
||||
{
|
||||
Contract.Requires(body != null);
|
||||
|
@ -2643,7 +2669,10 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create an existential Quantifier.
|
||||
/// </summary>
|
||||
/// <seealso cref="MkForall(Sort[],Symbol[],Expr,uint,Pattern[],Expr[],Symbol,Symbol)"/>
|
||||
/// <remarks>
|
||||
/// Creates an existential quantifier using de-Brujin indexed variables.
|
||||
/// (<see cref="MkForall(Sort[], Symbol[], Expr, uint, Pattern[], Expr[], Symbol, Symbol)"/>).
|
||||
/// </remarks>
|
||||
public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
|
||||
{
|
||||
Contract.Requires(sorts != null);
|
||||
|
@ -2662,6 +2691,11 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create an existential Quantifier.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Creates an existential quantifier using a list of constants that will
|
||||
/// form the set of bound variables.
|
||||
/// <seealso cref="MkForall(Sort[], Symbol[], Expr, uint, Pattern[], Expr[], Symbol, Symbol)"/>
|
||||
/// </remarks>
|
||||
public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
|
||||
{
|
||||
Contract.Requires(body != null);
|
||||
|
@ -2677,6 +2711,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create a Quantifier.
|
||||
/// </summary>
|
||||
/// <see cref="MkForall(Sort[], Symbol[], Expr, uint, Pattern[], Expr[], Symbol, Symbol)"/>
|
||||
public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
|
||||
{
|
||||
Contract.Requires(body != null);
|
||||
|
@ -2700,6 +2735,7 @@ namespace Microsoft.Z3
|
|||
/// <summary>
|
||||
/// Create a Quantifier.
|
||||
/// </summary>
|
||||
/// <see cref="MkForall(Sort[], Symbol[], Expr, uint, Pattern[], Expr[], Symbol, Symbol)"/>
|
||||
public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
|
||||
{
|
||||
Contract.Requires(body != null);
|
||||
|
|
|
@ -290,6 +290,17 @@ namespace Microsoft.Z3
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a clone of the current solver with respect to <c>ctx</c>.
|
||||
/// </summary>
|
||||
public Solver Translate(Context ctx)
|
||||
{
|
||||
Contract.Requires(ctx != null);
|
||||
Contract.Ensures(Contract.Result<Solver>() != null);
|
||||
return new Solver(ctx, Native.Z3_solver_translate(Context.nCtx, NativeObject, ctx.nCtx));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Solver statistics.
|
||||
/// </summary>
|
||||
|
|
|
@ -433,8 +433,8 @@ public class Context extends IDisposable
|
|||
/**
|
||||
* Creates a fresh function declaration with a name prefixed with
|
||||
* {@code prefix}.
|
||||
* @see mkFuncDecl(String,Sort,Sort)
|
||||
* @see mkFuncDecl(String,Sort[],Sort)
|
||||
* @see #mkFuncDecl(String,Sort,Sort)
|
||||
* @see #mkFuncDecl(String,Sort[],Sort)
|
||||
**/
|
||||
public FuncDecl mkFreshFuncDecl(String prefix, Sort[] domain, Sort range)
|
||||
|
||||
|
@ -1717,6 +1717,17 @@ public class Context extends IDisposable
|
|||
Native.mkArrayDefault(nCtx(), array.getNativeObject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Extentionality index. Two arrays are equal if and only if they are equal on the index returned by MkArrayExt.
|
||||
**/
|
||||
public Expr mkArrayExt(ArrayExpr arg1, ArrayExpr arg2)
|
||||
{
|
||||
checkContextMatch(arg1);
|
||||
checkContextMatch(arg2);
|
||||
return Expr.create(this, Native.mkArrayExt(nCtx(), arg1.getNativeObject(), arg2.getNativeObject()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a set type.
|
||||
**/
|
||||
|
@ -2014,6 +2025,7 @@ public class Context extends IDisposable
|
|||
|
||||
/**
|
||||
* Create a universal Quantifier.
|
||||
*
|
||||
* @param sorts the sorts of the bound variables.
|
||||
* @param names names of the bound variables
|
||||
* @param body the body of the quantifier.
|
||||
|
@ -2023,17 +2035,22 @@ public class Context extends IDisposable
|
|||
* @param quantifierID optional symbol to track quantifier.
|
||||
* @param skolemID optional symbol to track skolem constants.
|
||||
*
|
||||
* Remarks: Creates a forall formula, where
|
||||
* {@code weight"/> is the weight, <paramref name="patterns} is
|
||||
* @return Creates a forall formula, where
|
||||
* {@code weight} is the weight, {@code patterns} is
|
||||
* an array of patterns, {@code sorts} is an array with the sorts
|
||||
* of the bound variables, {@code names} is an array with the
|
||||
* 'names' of the bound variables, and {@code body} is the body
|
||||
* of the quantifier. Quantifiers are associated with weights indicating the
|
||||
* importance of using the quantifier during instantiation.
|
||||
* Note that the bound variables are de-Bruijn indices created using {@link mkBound}.
|
||||
* Z3 applies the convention that the last element in {@code names} and
|
||||
* {@code sorts} refers to the variable with index 0, the second to last element
|
||||
* of {@code names} and {@code sorts} refers to the variable
|
||||
* with index 1, etc.
|
||||
**/
|
||||
public Quantifier mkForall(Sort[] sorts, Symbol[] names, Expr body,
|
||||
int weight, Pattern[] patterns, Expr[] noPatterns,
|
||||
Symbol quantifierID, Symbol skolemID)
|
||||
int weight, Pattern[] patterns, Expr[] noPatterns,
|
||||
Symbol quantifierID, Symbol skolemID)
|
||||
{
|
||||
|
||||
return new Quantifier(this, true, sorts, names, body, weight, patterns,
|
||||
|
@ -2041,11 +2058,12 @@ public class Context extends IDisposable
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a universal Quantifier.
|
||||
* Creates a universal quantifier using a list of constants that will form the set of bound variables.
|
||||
* @see #mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol)
|
||||
**/
|
||||
public Quantifier mkForall(Expr[] boundConstants, Expr body, int weight,
|
||||
Pattern[] patterns, Expr[] noPatterns, Symbol quantifierID,
|
||||
Symbol skolemID)
|
||||
Pattern[] patterns, Expr[] noPatterns, Symbol quantifierID,
|
||||
Symbol skolemID)
|
||||
{
|
||||
|
||||
return new Quantifier(this, true, boundConstants, body, weight,
|
||||
|
@ -2053,12 +2071,12 @@ public class Context extends IDisposable
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an existential Quantifier.
|
||||
* Creates an existential quantifier using de-Brujin indexed variables.
|
||||
* @see mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol)
|
||||
**/
|
||||
public Quantifier mkExists(Sort[] sorts, Symbol[] names, Expr body,
|
||||
int weight, Pattern[] patterns, Expr[] noPatterns,
|
||||
Symbol quantifierID, Symbol skolemID)
|
||||
int weight, Pattern[] patterns, Expr[] noPatterns,
|
||||
Symbol quantifierID, Symbol skolemID)
|
||||
{
|
||||
|
||||
return new Quantifier(this, false, sorts, names, body, weight,
|
||||
|
@ -2066,11 +2084,12 @@ public class Context extends IDisposable
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an existential Quantifier.
|
||||
* Creates an existential quantifier using a list of constants that will form the set of bound variables.
|
||||
* @see #mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol)
|
||||
**/
|
||||
public Quantifier mkExists(Expr[] boundConstants, Expr body, int weight,
|
||||
Pattern[] patterns, Expr[] noPatterns, Symbol quantifierID,
|
||||
Symbol skolemID)
|
||||
Pattern[] patterns, Expr[] noPatterns, Symbol quantifierID,
|
||||
Symbol skolemID)
|
||||
{
|
||||
|
||||
return new Quantifier(this, false, boundConstants, body, weight,
|
||||
|
@ -2079,11 +2098,12 @@ public class Context extends IDisposable
|
|||
|
||||
/**
|
||||
* Create a Quantifier.
|
||||
* @see #mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol)
|
||||
**/
|
||||
public Quantifier mkQuantifier(boolean universal, Sort[] sorts,
|
||||
Symbol[] names, Expr body, int weight, Pattern[] patterns,
|
||||
Expr[] noPatterns, Symbol quantifierID, Symbol skolemID)
|
||||
|
||||
Symbol[] names, Expr body, int weight, Pattern[] patterns,
|
||||
Expr[] noPatterns, Symbol quantifierID, Symbol skolemID)
|
||||
|
||||
{
|
||||
|
||||
if (universal)
|
||||
|
@ -2095,11 +2115,12 @@ public class Context extends IDisposable
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a Quantifier.
|
||||
* Create a Quantifier
|
||||
* @see #mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol)
|
||||
**/
|
||||
public Quantifier mkQuantifier(boolean universal, Expr[] boundConstants,
|
||||
Expr body, int weight, Pattern[] patterns, Expr[] noPatterns,
|
||||
Symbol quantifierID, Symbol skolemID)
|
||||
Expr body, int weight, Pattern[] patterns, Expr[] noPatterns,
|
||||
Symbol quantifierID, Symbol skolemID)
|
||||
{
|
||||
|
||||
if (universal)
|
||||
|
|
|
@ -293,6 +293,14 @@ public class Solver extends Z3Object
|
|||
getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a clone of the current solver with respect to <c>ctx</c>.
|
||||
*/
|
||||
public Solver translate(Context ctx)
|
||||
{
|
||||
return new Solver(ctx, Native.solverTranslate(getContext().nCtx(), getNativeObject(), ctx.nCtx()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Solver statistics.
|
||||
*
|
||||
|
|
|
@ -1217,6 +1217,9 @@ struct
|
|||
|
||||
let mk_term_array ( ctx : context ) ( arg : expr ) =
|
||||
expr_of_ptr ctx (Z3native.mk_array_default (context_gno ctx) (Expr.gno arg))
|
||||
|
||||
let mk_array_ext ( ctx : context) ( arg1 : expr ) ( arg2 : expr ) =
|
||||
expr_of_ptr ctx (Z3native.mk_array_ext (context_gno ctx) (Expr.gno arg1) (Expr.gno arg2))
|
||||
end
|
||||
|
||||
|
||||
|
@ -2740,10 +2743,13 @@ struct
|
|||
mk_solver ctx (Some (Symbol.mk_string ctx logic))
|
||||
|
||||
let mk_simple_solver ( ctx : context ) =
|
||||
(create ctx (Z3native.mk_simple_solver (context_gno ctx)))
|
||||
create ctx (Z3native.mk_simple_solver (context_gno ctx))
|
||||
|
||||
let mk_solver_t ( ctx : context ) ( t : Tactic.tactic ) =
|
||||
(create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t)))
|
||||
create ctx (Z3native.mk_solver_from_tactic (context_gno ctx) (z3obj_gno t))
|
||||
|
||||
let translate ( x : solver ) ( to_ctx : context ) =
|
||||
create to_ctx (Z3native.solver_translate (z3obj_gnc x) (z3obj_gno x) (context_gno to_ctx))
|
||||
|
||||
let to_string ( x : solver ) = Z3native.solver_to_string (z3obj_gnc x) (z3obj_gno x)
|
||||
end
|
||||
|
|
|
@ -864,8 +864,15 @@ sig
|
|||
(** Access the array default value.
|
||||
|
||||
Produces the default range value, for arrays that can be represented as
|
||||
finite maps with a default range value. *)
|
||||
finite maps with a default range value. *)
|
||||
val mk_term_array : context -> Expr.expr -> Expr.expr
|
||||
|
||||
(** Create array extensionality index given two arrays with the same sort.
|
||||
|
||||
The meaning is given by the axiom:
|
||||
(=> (= (select A (array-ext A B)) (select B (array-ext A B))) (= A B)) *)
|
||||
val mk_array_ext : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
end
|
||||
|
||||
(** Functions to manipulate Set expressions *)
|
||||
|
@ -1185,36 +1192,36 @@ sig
|
|||
val mk_const_s : context -> string -> Expr.expr
|
||||
|
||||
(** Create an expression representing [t1 mod t2].
|
||||
The arguments must have int type. *)
|
||||
The arguments must have int type. *)
|
||||
val mk_mod : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
(** Create an expression representing [t1 rem t2].
|
||||
The arguments must have int type. *)
|
||||
The arguments must have int type. *)
|
||||
val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
(** Create an integer numeral. *)
|
||||
val mk_numeral_s : context -> string -> Expr.expr
|
||||
|
||||
(** Create an integer numeral.
|
||||
@return A Term with the given value and sort Integer *)
|
||||
@return A Term with the given value and sort Integer *)
|
||||
val mk_numeral_i : context -> int -> Expr.expr
|
||||
|
||||
(** Coerce an integer to a real.
|
||||
|
||||
There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard.
|
||||
|
||||
You can take the floor of a real by creating an auxiliary integer Term [k] and
|
||||
and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1].
|
||||
The argument must be of integer sort. *)
|
||||
(** Coerce an integer to a real.
|
||||
|
||||
There is also a converse operation exposed. It follows the semantics prescribed by the SMT-LIB standard.
|
||||
|
||||
You can take the floor of a real by creating an auxiliary integer Term [k] and
|
||||
and asserting [MakeInt2Real(k) <= t1 < MkInt2Real(k)+1].
|
||||
The argument must be of integer sort. *)
|
||||
val mk_int2real : context -> Expr.expr -> Expr.expr
|
||||
|
||||
(** Create an n-bit bit-vector from an integer argument.
|
||||
|
||||
NB. This function is essentially treated as uninterpreted.
|
||||
So you cannot expect Z3 to precisely reflect the semantics of this function
|
||||
when solving constraints with this function.
|
||||
|
||||
The argument must be of integer sort. *)
|
||||
|
||||
NB. This function is essentially treated as uninterpreted.
|
||||
So you cannot expect Z3 to precisely reflect the semantics of this function
|
||||
when solving constraints with this function.
|
||||
|
||||
The argument must be of integer sort. *)
|
||||
val mk_int2bv : context -> int -> Expr.expr -> Expr.expr
|
||||
end
|
||||
|
||||
|
@ -1234,7 +1241,7 @@ sig
|
|||
val get_ratio : Expr.expr -> Ratio.ratio
|
||||
|
||||
(** Returns a string representation in decimal notation.
|
||||
The result has at most as many decimal places as indicated by the int argument.*)
|
||||
The result has at most as many decimal places as indicated by the int argument.*)
|
||||
val to_decimal_string : Expr.expr-> int -> string
|
||||
|
||||
(** Returns a string representation of a numeral. *)
|
||||
|
@ -1247,16 +1254,16 @@ sig
|
|||
val mk_const_s : context -> string -> Expr.expr
|
||||
|
||||
(** Create a real numeral from a fraction.
|
||||
@return A Term with rational value and sort Real
|
||||
{!mk_numeral_s} *)
|
||||
@return A Term with rational value and sort Real
|
||||
{!mk_numeral_s} *)
|
||||
val mk_numeral_nd : context -> int -> int -> Expr.expr
|
||||
|
||||
(** Create a real numeral.
|
||||
@return A Term with the given value and sort Real *)
|
||||
@return A Term with the given value and sort Real *)
|
||||
val mk_numeral_s : context -> string -> Expr.expr
|
||||
|
||||
(** Create a real numeral.
|
||||
@return A Term with the given value and sort Real *)
|
||||
@return A Term with the given value and sort Real *)
|
||||
val mk_numeral_i : context -> int -> Expr.expr
|
||||
|
||||
(** Creates an expression that checks whether a real number is an integer. *)
|
||||
|
@ -1264,29 +1271,29 @@ sig
|
|||
|
||||
(** Coerce a real to an integer.
|
||||
|
||||
The semantics of this function follows the SMT-LIB standard for the function to_int.
|
||||
The argument must be of real sort. *)
|
||||
The semantics of this function follows the SMT-LIB standard for the function to_int.
|
||||
The argument must be of real sort. *)
|
||||
val mk_real2int : context -> Expr.expr -> Expr.expr
|
||||
|
||||
(** Algebraic Numbers *)
|
||||
module AlgebraicNumber :
|
||||
sig
|
||||
(** Return a upper bound for a given real algebraic number.
|
||||
The interval isolating the number is smaller than 1/10^precision.
|
||||
{!is_algebraic_number}
|
||||
@return A numeral Expr of sort Real *)
|
||||
The interval isolating the number is smaller than 1/10^precision.
|
||||
{!is_algebraic_number}
|
||||
@return A numeral Expr of sort Real *)
|
||||
val to_upper : Expr.expr -> int -> Expr.expr
|
||||
|
||||
|
||||
(** Return a lower bound for the given real algebraic number.
|
||||
The interval isolating the number is smaller than 1/10^precision.
|
||||
{!is_algebraic_number}
|
||||
@return A numeral Expr of sort Real *)
|
||||
The interval isolating the number is smaller than 1/10^precision.
|
||||
{!is_algebraic_number}
|
||||
@return A numeral Expr of sort Real *)
|
||||
val to_lower : Expr.expr -> int -> Expr.expr
|
||||
|
||||
|
||||
(** Returns a string representation in decimal notation.
|
||||
The result has at most as many decimal places as the int argument provided.*)
|
||||
The result has at most as many decimal places as the int argument provided.*)
|
||||
val to_decimal_string : Expr.expr -> int -> string
|
||||
|
||||
|
||||
(** Returns a string representation of a numeral. *)
|
||||
val numeral_to_string : Expr.expr -> string
|
||||
end
|
||||
|
@ -1846,52 +1853,52 @@ end
|
|||
module FloatingPoint :
|
||||
sig
|
||||
|
||||
(** Rounding Modes *)
|
||||
(** Rounding Modes *)
|
||||
module RoundingMode :
|
||||
sig
|
||||
(** Create the RoundingMode sort. *)
|
||||
(** Create the RoundingMode sort. *)
|
||||
val mk_sort : context -> Sort.sort
|
||||
|
||||
(** Indicates whether the terms is of floating-point rounding mode sort. *)
|
||||
(** Indicates whether the terms is of floating-point rounding mode sort. *)
|
||||
val is_fprm : Expr.expr -> bool
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. *)
|
||||
(** Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. *)
|
||||
val mk_round_nearest_ties_to_even : context -> Expr.expr
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. *)
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the NearestTiesToEven rounding mode. *)
|
||||
val mk_rne : context -> Expr.expr
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. *)
|
||||
(** Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. *)
|
||||
val mk_round_nearest_ties_to_away : context -> Expr.expr
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. *)
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the NearestTiesToAway rounding mode. *)
|
||||
val mk_rna : context -> Expr.expr
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. *)
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. *)
|
||||
val mk_round_toward_positive : context -> Expr.expr
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. *)
|
||||
val mk_rtp : context -> Expr.expr
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. *)
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardPositive rounding mode. *)
|
||||
val mk_rtp : context -> Expr.expr
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. *)
|
||||
val mk_round_toward_negative : context -> Expr.expr
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. *)
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardNegative rounding mode. *)
|
||||
val mk_rtn : context -> Expr.expr
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. *)
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. *)
|
||||
val mk_round_toward_zero : context -> Expr.expr
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. *)
|
||||
|
||||
(** Create a numeral of RoundingMode sort which represents the TowardZero rounding mode. *)
|
||||
val mk_rtz : context -> Expr.expr
|
||||
end
|
||||
|
||||
(** Create a FloatingPoint sort. *)
|
||||
val mk_sort : context -> int -> int -> Sort.sort
|
||||
|
||||
|
||||
(** Create the half-precision (16-bit) FloatingPoint sort.*)
|
||||
val mk_sort_half : context -> Sort.sort
|
||||
|
||||
|
||||
(** Create the half-precision (16-bit) FloatingPoint sort. *)
|
||||
val mk_sort_16 : context -> Sort.sort
|
||||
|
||||
|
@ -1906,7 +1913,7 @@ sig
|
|||
|
||||
(** Create the double-precision (64-bit) FloatingPoint sort. *)
|
||||
val mk_sort_64 : context -> Sort.sort
|
||||
|
||||
|
||||
(** Create the quadruple-precision (128-bit) FloatingPoint sort. *)
|
||||
val mk_sort_quadruple : context -> Sort.sort
|
||||
|
||||
|
@ -1924,7 +1931,7 @@ sig
|
|||
|
||||
(** Create an expression of FloatingPoint sort from three bit-vector expressions.
|
||||
|
||||
This is the operator named `fp' in the SMT FP theory definition.
|
||||
This is the operator named `fp' in the SMT FP theory definition.
|
||||
Note that \c sign is required to be a bit-vector of size 1. Significand and exponent
|
||||
are required to be greater than 1 and 2 respectively. The FloatingPoint sort
|
||||
of the resulting expression is automatically determined from the bit-vector sizes
|
||||
|
@ -1939,16 +1946,16 @@ sig
|
|||
|
||||
(** Create a numeral of FloatingPoint sort from a signed integer. *)
|
||||
val mk_numeral_i : context -> int -> Sort.sort -> Expr.expr
|
||||
|
||||
|
||||
(** Create a numeral of FloatingPoint sort from a sign bit and two integers. *)
|
||||
val mk_numeral_i_u : context -> bool -> int -> int -> Sort.sort -> Expr.expr
|
||||
|
||||
(** Create a numeral of FloatingPoint sort from a string *)
|
||||
val mk_numeral_s : context -> string -> Sort.sort -> Expr.expr
|
||||
|
||||
|
||||
(** Indicates whether the terms is of floating-point sort. *)
|
||||
val is_fp : Expr.expr -> bool
|
||||
|
||||
|
||||
|
||||
(** Indicates whether an expression is a floating-point abs expression *)
|
||||
val is_abs : Expr.expr -> bool
|
||||
|
@ -1958,7 +1965,7 @@ sig
|
|||
|
||||
(** Indicates whether an expression is a floating-point add expression *)
|
||||
val is_add : Expr.expr -> bool
|
||||
|
||||
|
||||
(** Indicates whether an expression is a floating-point sub expression *)
|
||||
val is_sub : Expr.expr -> bool
|
||||
|
||||
|
@ -2015,7 +2022,7 @@ sig
|
|||
|
||||
(** Indicates whether an expression is a floating-point is_nan expression *)
|
||||
val is_is_nan : Expr.expr -> bool
|
||||
|
||||
|
||||
(** Indicates whether an expression is a floating-point is_negative expression *)
|
||||
val is_is_negative : Expr.expr -> bool
|
||||
|
||||
|
@ -2070,17 +2077,17 @@ sig
|
|||
|
||||
(** Floating-point fused multiply-add. *)
|
||||
val mk_fma : context -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
|
||||
(** Floating-point square root *)
|
||||
val mk_sqrt : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
(** Floating-point remainder *)
|
||||
val mk_rem : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
|
||||
(** Floating-point roundToIntegral.
|
||||
|
||||
Rounds a floating-point number to the closest integer,
|
||||
again represented as a floating-point number. *)
|
||||
Rounds a floating-point number to the closest integer,
|
||||
again represented as a floating-point number. *)
|
||||
val mk_round_to_integral : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
(** Minimum of floating-point numbers. *)
|
||||
|
@ -2088,16 +2095,16 @@ sig
|
|||
|
||||
(** Maximum of floating-point numbers. *)
|
||||
val mk_max : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
|
||||
(** Floating-point less than or equal. *)
|
||||
val mk_leq : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
|
||||
(** Floating-point less than. *)
|
||||
val mk_lt : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
(** Floating-point greater than or equal. *)
|
||||
val mk_geq : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
|
||||
(** Floating-point greater than. *)
|
||||
val mk_gt : context -> Expr.expr -> Expr.expr -> Expr.expr
|
||||
|
||||
|
@ -2142,19 +2149,19 @@ sig
|
|||
|
||||
(** C1onversion of a floating-point term into an unsigned bit-vector. *)
|
||||
val mk_to_ubv : context -> Expr.expr -> Expr.expr -> int -> Expr.expr
|
||||
|
||||
|
||||
(** Conversion of a floating-point term into a signed bit-vector. *)
|
||||
val mk_to_sbv : context -> Expr.expr -> Expr.expr -> int -> Expr.expr
|
||||
|
||||
(** Conversion of a floating-point term into a real-numbered term. *)
|
||||
val mk_to_real : context -> Expr.expr -> Expr.expr
|
||||
|
||||
|
||||
(** Retrieves the number of bits reserved for the exponent in a FloatingPoint sort. *)
|
||||
val get_ebits : context -> Sort.sort -> int
|
||||
|
||||
(** Retrieves the number of bits reserved for the significand in a FloatingPoint sort. *)
|
||||
val get_sbits : context -> Sort.sort -> int
|
||||
|
||||
|
||||
(** Retrieves the sign of a floating-point literal. *)
|
||||
val get_numeral_sign : context -> Expr.expr -> bool * int
|
||||
|
||||
|
@ -2162,7 +2169,7 @@ sig
|
|||
val get_numeral_significand_string : context -> Expr.expr -> string
|
||||
|
||||
(** Return the significand value of a floating-point numeral as a uint64.
|
||||
Remark: This function extracts the significand bits, without the
|
||||
Remark: This function extracts the significand bits, without the
|
||||
hidden bit or normalization. Throws an exception if the
|
||||
significand does not fit into a uint64. *)
|
||||
val get_numeral_significand_uint : context -> Expr.expr -> bool * int
|
||||
|
@ -2172,7 +2179,7 @@ sig
|
|||
|
||||
(** Return the exponent value of a floating-point numeral as a signed integer *)
|
||||
val get_numeral_exponent_int : context -> Expr.expr -> bool * int
|
||||
|
||||
|
||||
(** Conversion of a floating-point term into a bit-vector term in IEEE 754-2008 format. *)
|
||||
val mk_to_ieee_bv : context -> Expr.expr -> Expr.expr
|
||||
|
||||
|
@ -2675,13 +2682,13 @@ sig
|
|||
|
||||
(** Function interpretations entries
|
||||
|
||||
An Entry object represents an element in the finite map used to a function interpretation. *)
|
||||
An Entry object represents an element in the finite map used to a function interpretation. *)
|
||||
module FuncEntry :
|
||||
sig
|
||||
type func_entry
|
||||
|
||||
(** Return the (symbolic) value of this entry.
|
||||
*)
|
||||
*)
|
||||
val get_value : func_entry -> Expr.expr
|
||||
|
||||
(** The number of arguments of the entry.
|
||||
|
@ -2865,8 +2872,8 @@ sig
|
|||
val get_subgoal : apply_result -> int -> Goal.goal
|
||||
|
||||
(** Convert a model for a subgoal into a model for the original
|
||||
goal [g], that the ApplyResult was obtained from.
|
||||
#return A model for [g] *)
|
||||
goal [g], that the ApplyResult was obtained from.
|
||||
#return A model for [g] *)
|
||||
val convert_model : apply_result -> int -> Model.model -> Model.model
|
||||
|
||||
(** A string representation of the ApplyResult. *)
|
||||
|
@ -2957,31 +2964,31 @@ end
|
|||
module Statistics :
|
||||
sig
|
||||
type statistics
|
||||
|
||||
|
||||
(** Statistical data is organized into pairs of \[Key, Entry\], where every
|
||||
Entry is either a floating point or integer value. *)
|
||||
Entry is either a floating point or integer value. *)
|
||||
module Entry :
|
||||
sig
|
||||
type statistics_entry
|
||||
|
||||
|
||||
(** The key of the entry. *)
|
||||
val get_key : statistics_entry -> string
|
||||
|
||||
|
||||
(** The int-value of the entry. *)
|
||||
val get_int : statistics_entry -> int
|
||||
|
||||
|
||||
(** The float-value of the entry. *)
|
||||
val get_float : statistics_entry -> float
|
||||
|
||||
|
||||
(** True if the entry is uint-valued. *)
|
||||
val is_int : statistics_entry -> bool
|
||||
|
||||
|
||||
(** True if the entry is float-valued. *)
|
||||
val is_float : statistics_entry -> bool
|
||||
|
||||
|
||||
(** The string representation of the the entry's value. *)
|
||||
val to_string_value : statistics_entry -> string
|
||||
|
||||
|
||||
(** The string representation of the entry (key and value) *)
|
||||
val to_string : statistics_entry -> string
|
||||
end
|
||||
|
@ -3122,6 +3129,9 @@ sig
|
|||
The solver supports the commands [Push] and [Pop], but it
|
||||
will always solve each check from scratch. *)
|
||||
val mk_solver_t : context -> Tactic.tactic -> solver
|
||||
|
||||
(** Create a clone of the current solver with respect to a context. *)
|
||||
val translate : solver -> context -> solver
|
||||
|
||||
(** A string representation of the solver. *)
|
||||
val to_string : solver -> string
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
############################################
|
||||
# Copyright (c) 2012 Microsoft Corporation
|
||||
#
|
||||
|
@ -4143,6 +4144,13 @@ def K(dom, v):
|
|||
v = _py2expr(v, ctx)
|
||||
return ArrayRef(Z3_mk_const_array(ctx.ref(), dom.ast, v.as_ast()), ctx)
|
||||
|
||||
def Ext(a, b):
|
||||
"""Return extensionality index for arrays.
|
||||
"""
|
||||
if __debug__:
|
||||
_z3_assert(is_array(a) and is_array(b))
|
||||
return _to_expr_ref(Z3_mk_array_ext(ctx.ref(), a.as_ast(), b.as_ast()));
|
||||
|
||||
def is_select(a):
|
||||
"""Return `True` if `a` is a Z3 array select application.
|
||||
|
||||
|
@ -4854,7 +4862,7 @@ class Goal(Z3PPObject):
|
|||
elif sz == 1:
|
||||
return self.get(0)
|
||||
else:
|
||||
return And([ self.get(i) for i in range(len(self)) ])
|
||||
return And([ self.get(i) for i in range(len(self)) ], self.ctx)
|
||||
|
||||
#########################################
|
||||
#
|
||||
|
@ -6084,6 +6092,19 @@ class Solver(Z3PPObject):
|
|||
"""Return a formatted string with all added constraints."""
|
||||
return obj_to_string(self)
|
||||
|
||||
def translate(self, target):
|
||||
"""Translate `self` to the context `target`. That is, return a copy of `self` in the context `target`.
|
||||
|
||||
>>> c1 = Context()
|
||||
>>> c2 = Context()
|
||||
>>> s1 = Solver(ctx=c1)
|
||||
>>> s2 = s1.translate(c2)
|
||||
"""
|
||||
if __debug__:
|
||||
_z3_assert(isinstance(target, Context), "argument must be a Z3 context")
|
||||
solver = Z3_solver_translate(self.ctx.ref(), self.solver, target.ref())
|
||||
return Solver(solver, target)
|
||||
|
||||
def sexpr(self):
|
||||
"""Return a formatted string (in Lisp-like format) with all added constraints. We say the string is in s-expression format.
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ _z3_op_to_str = {
|
|||
Z3_OP_BASHR : '>>', Z3_OP_BSHL : '<<', Z3_OP_BLSHR : 'LShR',
|
||||
Z3_OP_CONCAT : 'Concat', Z3_OP_EXTRACT : 'Extract', Z3_OP_BV2INT : 'BV2Int',
|
||||
Z3_OP_ARRAY_MAP : 'Map', Z3_OP_SELECT : 'Select', Z3_OP_STORE : 'Store',
|
||||
Z3_OP_CONST_ARRAY : 'K',
|
||||
Z3_OP_CONST_ARRAY : 'K', Z3_OP_ARRAY_EXT : 'Ext',
|
||||
Z3_OP_PB_AT_MOST : 'AtMost', Z3_OP_PB_LE : 'PbLe', Z3_OP_PB_GE : 'PbGe'
|
||||
}
|
||||
|
||||
|
@ -1157,7 +1157,13 @@ def set_pp_option(k, v):
|
|||
def obj_to_string(a):
|
||||
out = io.StringIO()
|
||||
_PP(out, _Formatter(a))
|
||||
return out.getvalue()
|
||||
r = out.getvalue()
|
||||
if sys.version < '3':
|
||||
return r
|
||||
else:
|
||||
enc = sys.stdout.encoding
|
||||
if enc != None: return r.decode(enc)
|
||||
return r
|
||||
|
||||
_html_out = None
|
||||
|
||||
|
|
|
@ -322,6 +322,9 @@ typedef enum
|
|||
- Z3_OP_AS_ARRAY An array value that behaves as the function graph of the
|
||||
function passed as parameter.
|
||||
|
||||
- Z3_OP_ARRAY_EXT Array extensionality function. It takes two arrays as arguments and produces an index, such that the arrays
|
||||
are different if they are different on the index.
|
||||
|
||||
- Z3_OP_BNUM Bit-vector numeral.
|
||||
|
||||
- Z3_OP_BIT1 One bit bit-vector.
|
||||
|
@ -1033,6 +1036,7 @@ typedef enum {
|
|||
Z3_OP_SET_COMPLEMENT,
|
||||
Z3_OP_SET_SUBSET,
|
||||
Z3_OP_AS_ARRAY,
|
||||
Z3_OP_ARRAY_EXT,
|
||||
|
||||
// Bit-vectors
|
||||
Z3_OP_BNUM = 0x400,
|
||||
|
@ -3260,6 +3264,17 @@ END_MLAPI_EXCLUDE
|
|||
Z3_ast Z3_API Z3_mk_set_subset(Z3_context c, Z3_ast arg1, Z3_ast arg2);
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
\brief Create array extensionality index given two arrays with the same sort.
|
||||
The meaning is given by the axiom:
|
||||
(=> (= (select A (array-ext A B)) (select B (array-ext A B))) (= A B))
|
||||
|
||||
def_API('Z3_mk_array_ext', AST, (_in(CONTEXT), _in(AST), _in(AST)))
|
||||
*/
|
||||
|
||||
Z3_ast Z3_API Z3_mk_array_ext(Z3_context c, Z3_ast arg1, Z3_ast arg2);
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
@name Numerals
|
||||
*/
|
||||
|
@ -7062,6 +7077,14 @@ END_MLAPI_EXCLUDE
|
|||
*/
|
||||
Z3_solver Z3_API Z3_mk_solver_from_tactic(Z3_context c, Z3_tactic t);
|
||||
|
||||
/**
|
||||
\brief Copy a solver \c s from the context \c source to a the context \c target.
|
||||
|
||||
def_API('Z3_solver_translate', SOLVER, (_in(CONTEXT), _in(SOLVER), _in(CONTEXT)))
|
||||
*/
|
||||
Z3_solver Z3_API Z3_solver_translate(Z3_context source, Z3_solver s, Z3_context target);
|
||||
|
||||
|
||||
/**
|
||||
\brief Return a string describing all solver available parameters.
|
||||
|
||||
|
|
|
@ -293,7 +293,7 @@ func_decl * array_decl_plugin::mk_store(unsigned arity, sort * const * domain) {
|
|||
func_decl_info(m_family_id, OP_STORE));
|
||||
}
|
||||
|
||||
func_decl * array_decl_plugin::mk_array_ext_skolem(unsigned arity, sort * const * domain, unsigned i) {
|
||||
func_decl * array_decl_plugin::mk_array_ext(unsigned arity, sort * const * domain, unsigned i) {
|
||||
if (arity != 2 || domain[0] != domain[1]) {
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
|
@ -306,7 +306,7 @@ func_decl * array_decl_plugin::mk_array_ext_skolem(unsigned arity, sort * const
|
|||
}
|
||||
sort * r = to_sort(s->get_parameter(i).get_ast());
|
||||
parameter param(s);
|
||||
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, func_decl_info(m_family_id, OP_ARRAY_EXT_SKOLEM, 1, ¶m));
|
||||
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, func_decl_info(m_family_id, OP_ARRAY_EXT, 1, ¶m));
|
||||
}
|
||||
|
||||
|
||||
|
@ -463,12 +463,15 @@ func_decl * array_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
|
|||
func_decl * f = to_func_decl(parameters[0].get_ast());
|
||||
return mk_map(f, arity, domain);
|
||||
}
|
||||
case OP_ARRAY_EXT_SKOLEM:
|
||||
case OP_ARRAY_EXT:
|
||||
if (num_parameters == 0) {
|
||||
return mk_array_ext(arity, domain, 0);
|
||||
}
|
||||
if (num_parameters != 1 || !parameters[0].is_int()) {
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
return mk_array_ext_skolem(arity, domain, parameters[0].get_int());
|
||||
return mk_array_ext(arity, domain, parameters[0].get_int());
|
||||
case OP_ARRAY_DEFAULT:
|
||||
return mk_default(arity, domain);
|
||||
case OP_SET_UNION:
|
||||
|
@ -519,6 +522,7 @@ void array_decl_plugin::get_op_names(svector<builtin_name>& op_names, symbol con
|
|||
op_names.push_back(builtin_name("complement",OP_SET_COMPLEMENT));
|
||||
op_names.push_back(builtin_name("subset",OP_SET_SUBSET));
|
||||
op_names.push_back(builtin_name("as-array", OP_AS_ARRAY));
|
||||
op_names.push_back(builtin_name("array-ext", OP_ARRAY_EXT));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ Revision History:
|
|||
#include"ast.h"
|
||||
|
||||
|
||||
inline sort* get_array_range(sort const * s) {
|
||||
inline sort* get_array_range(sort const * s) {
|
||||
return to_sort(s->get_parameter(s->get_num_parameters() - 1).get_ast());
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ enum array_op_kind {
|
|||
OP_STORE,
|
||||
OP_SELECT,
|
||||
OP_CONST_ARRAY,
|
||||
OP_ARRAY_EXT_SKOLEM,
|
||||
OP_ARRAY_EXT,
|
||||
OP_ARRAY_DEFAULT,
|
||||
OP_ARRAY_MAP,
|
||||
OP_SET_UNION,
|
||||
|
@ -80,7 +80,7 @@ class array_decl_plugin : public decl_plugin {
|
|||
|
||||
func_decl * mk_store(unsigned arity, sort * const * domain);
|
||||
|
||||
func_decl * mk_array_ext_skolem(unsigned arity, sort * const * domain, unsigned i);
|
||||
func_decl * mk_array_ext(unsigned arity, sort * const * domain, unsigned i);
|
||||
|
||||
func_decl * mk_set_union(unsigned arity, sort * const * domain);
|
||||
|
||||
|
@ -104,20 +104,20 @@ class array_decl_plugin : public decl_plugin {
|
|||
}
|
||||
|
||||
//
|
||||
// Contract for sort:
|
||||
// parameters[0] - 1st dimension
|
||||
// Contract for sort:
|
||||
// parameters[0] - 1st dimension
|
||||
// ...
|
||||
// parameters[n-1] - nth dimension
|
||||
// parameters[n] - range
|
||||
//
|
||||
virtual sort * mk_sort(decl_kind k, unsigned num_parameters, parameter const * parameters);
|
||||
|
||||
|
||||
//
|
||||
// Contract for func_decl:
|
||||
// parameters[0] - array sort
|
||||
// Contract for others:
|
||||
// no parameters
|
||||
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
|
||||
virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
|
||||
|
@ -184,6 +184,11 @@ public:
|
|||
sort * mk_array_sort(sort* dom, sort* range) { return mk_array_sort(1, &dom, range); }
|
||||
|
||||
sort * mk_array_sort(unsigned arity, sort* const* domain, sort* range);
|
||||
|
||||
app * mk_as_array(sort * s, func_decl * f) {
|
||||
parameter param(f);
|
||||
return m_manager.mk_app(m_fid, OP_AS_ARRAY, 1, ¶m, 0, 0, s);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -184,6 +184,7 @@ void ast_translation::mk_func_decl(func_decl * f, frame & fr) {
|
|||
}
|
||||
|
||||
ast * ast_translation::process(ast const * _n) {
|
||||
if (!_n) return 0;
|
||||
SASSERT(m_result_stack.empty());
|
||||
SASSERT(m_frame_stack.empty());
|
||||
SASSERT(m_extra_children_stack.empty());
|
||||
|
|
|
@ -58,9 +58,9 @@ public:
|
|||
|
||||
template<typename T>
|
||||
T * operator()(T const * n) {
|
||||
SASSERT(from().contains(const_cast<T*>(n)));
|
||||
SASSERT(!n || from().contains(const_cast<T*>(n)));
|
||||
ast * r = process(n);
|
||||
SASSERT(to().contains(const_cast<ast*>(r)));
|
||||
SASSERT((!n && !r) || to().contains(const_cast<ast*>(r)));
|
||||
return static_cast<T*>(r);
|
||||
}
|
||||
|
||||
|
|
|
@ -166,6 +166,11 @@ expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args) {
|
|||
return m.mk_and(num_args, args);
|
||||
}
|
||||
|
||||
app* mk_and(ast_manager & m, unsigned num_args, app * const * args) {
|
||||
return to_app(mk_and(m, num_args, (expr* const*) args));
|
||||
}
|
||||
|
||||
|
||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args) {
|
||||
if (num_args == 0)
|
||||
return m.mk_false();
|
||||
|
@ -175,6 +180,10 @@ expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args) {
|
|||
return m.mk_or(num_args, args);
|
||||
}
|
||||
|
||||
app* mk_or(ast_manager & m, unsigned num_args, app * const * args) {
|
||||
return to_app(mk_or(m, num_args, (expr* const*) args));
|
||||
}
|
||||
|
||||
expr * mk_not(ast_manager & m, expr * arg) {
|
||||
expr * atom;
|
||||
if (m.is_not(arg, atom))
|
||||
|
|
|
@ -107,6 +107,9 @@ expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx);
|
|||
Return true if num_args == 0
|
||||
*/
|
||||
expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
app * mk_and(ast_manager & m, unsigned num_args, app * const * args);
|
||||
inline app_ref mk_and(app_ref_vector const& args) { return app_ref(mk_and(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
|
||||
inline expr_ref mk_and(expr_ref_vector const& args) { return expr_ref(mk_and(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
|
||||
|
||||
/**
|
||||
Return (or args[0] ... args[num_args-1]) if num_args >= 2
|
||||
|
@ -114,6 +117,10 @@ expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args);
|
|||
Return false if num_args == 0
|
||||
*/
|
||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args);
|
||||
app * mk_or(ast_manager & m, unsigned num_args, app * const * args);
|
||||
inline app_ref mk_or(app_ref_vector const& args) { return app_ref(mk_or(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
|
||||
inline expr_ref mk_or(expr_ref_vector const& args) { return expr_ref(mk_or(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
|
||||
|
||||
|
||||
/**
|
||||
Return a if arg = (not a)
|
||||
|
|
|
@ -2648,9 +2648,8 @@ void fpa2bv_converter::mk_to_fp_signed(func_decl * f, unsigned num, expr * const
|
|||
|
||||
SASSERT(num == 2);
|
||||
SASSERT(m_util.is_float(f->get_range()));
|
||||
SASSERT(m_bv_util.is_bv(args[0]));
|
||||
SASSERT(m_bv_util.is_bv(args[1]));
|
||||
SASSERT(is_app_of(args[0], m_util.get_family_id(), OP_FPA_INTERNAL_RM));
|
||||
SASSERT(m_bv_util.is_bv(args[1]));
|
||||
|
||||
expr_ref bv_rm(m), x(m);
|
||||
bv_rm = to_app(args[0])->get_arg(0);
|
||||
|
|
|
@ -84,7 +84,7 @@ br_status bool_rewriter::mk_nflat_and_core(unsigned num_args, expr * const * arg
|
|||
ptr_buffer<expr> buffer;
|
||||
expr_fast_mark1 neg_lits;
|
||||
expr_fast_mark2 pos_lits;
|
||||
|
||||
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
expr * arg = args[i];
|
||||
if (m().is_true(arg)) {
|
||||
|
@ -120,9 +120,9 @@ br_status bool_rewriter::mk_nflat_and_core(unsigned num_args, expr * const * arg
|
|||
}
|
||||
buffer.push_back(arg);
|
||||
}
|
||||
|
||||
|
||||
unsigned sz = buffer.size();
|
||||
|
||||
|
||||
switch(sz) {
|
||||
case 0:
|
||||
result = m().mk_true();
|
||||
|
@ -208,9 +208,9 @@ br_status bool_rewriter::mk_nflat_or_core(unsigned num_args, expr * const * args
|
|||
}
|
||||
buffer.push_back(arg);
|
||||
}
|
||||
|
||||
|
||||
unsigned sz = buffer.size();
|
||||
|
||||
|
||||
switch(sz) {
|
||||
case 0:
|
||||
result = m().mk_false();
|
||||
|
@ -222,7 +222,7 @@ br_status bool_rewriter::mk_nflat_or_core(unsigned num_args, expr * const * args
|
|||
if (m_local_ctx && m_local_ctx_cost <= m_local_ctx_limit) {
|
||||
neg_lits.reset();
|
||||
pos_lits.reset();
|
||||
if (local_ctx_simp(sz, buffer.c_ptr(), result))
|
||||
if (local_ctx_simp(sz, buffer.c_ptr(), result))
|
||||
return BR_DONE;
|
||||
}
|
||||
if (s) {
|
||||
|
@ -273,11 +273,11 @@ expr * bool_rewriter::mk_or_app(unsigned num_args, expr * const * args) {
|
|||
|
||||
/**
|
||||
\brief Auxiliary method for local_ctx_simp.
|
||||
|
||||
|
||||
Replace args[i] by true if marked in neg_lits.
|
||||
Replace args[i] by false if marked in pos_lits.
|
||||
*/
|
||||
bool bool_rewriter::simp_nested_not_or(unsigned num_args, expr * const * args,
|
||||
bool bool_rewriter::simp_nested_not_or(unsigned num_args, expr * const * args,
|
||||
expr_fast_mark1 & neg_lits, expr_fast_mark2 & pos_lits, expr_ref & result) {
|
||||
ptr_buffer<expr> new_args;
|
||||
bool simp = false;
|
||||
|
@ -307,13 +307,13 @@ bool bool_rewriter::simp_nested_not_or(unsigned num_args, expr * const * args,
|
|||
}
|
||||
if (simp) {
|
||||
switch(new_args.size()) {
|
||||
case 0:
|
||||
result = m().mk_true();
|
||||
case 0:
|
||||
result = m().mk_true();
|
||||
return true;
|
||||
case 1:
|
||||
mk_not(new_args[0], result);
|
||||
case 1:
|
||||
mk_not(new_args[0], result);
|
||||
return true;
|
||||
default:
|
||||
default:
|
||||
result = m().mk_not(m().mk_or(new_args.size(), new_args.c_ptr()));
|
||||
return true;
|
||||
}
|
||||
|
@ -358,7 +358,7 @@ void bool_rewriter::mk_nested_ite(expr * c, expr * t, expr * e, expr_ref & resul
|
|||
result = t;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (m().is_false(c)) {
|
||||
result = e;
|
||||
return;
|
||||
|
@ -368,7 +368,7 @@ void bool_rewriter::mk_nested_ite(expr * c, expr * t, expr * e, expr_ref & resul
|
|||
result = t;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (m().is_bool(t)) {
|
||||
if (m().is_true(t)) {
|
||||
if (m().is_false(e)) {
|
||||
|
@ -384,13 +384,13 @@ void bool_rewriter::mk_nested_ite(expr * c, expr * t, expr * e, expr_ref & resul
|
|||
return;
|
||||
}
|
||||
expr_ref tmp(m());
|
||||
mk_not(e, tmp);
|
||||
mk_not(e, tmp);
|
||||
result = m().mk_not(m().mk_or(c, tmp));
|
||||
return;
|
||||
}
|
||||
if (m().is_true(e)) {
|
||||
expr_ref tmp(m());
|
||||
mk_not(c, tmp);
|
||||
mk_not(c, tmp);
|
||||
result = m().mk_or(tmp, t);
|
||||
return;
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ void bool_rewriter::mk_nested_ite(expr * c, expr * t, expr * e, expr_ref & resul
|
|||
result = m().mk_or(c, e);
|
||||
return;
|
||||
}
|
||||
if (m().is_complement_core(t, e)) { // t = not(e)
|
||||
if (m().is_complement_core(t, e)) { // t = not(e)
|
||||
mk_eq(c, t, result);
|
||||
return;
|
||||
}
|
||||
|
@ -443,8 +443,8 @@ bool bool_rewriter::simp_nested_eq_ite(expr * t, expr_fast_mark1 & neg_lits, exp
|
|||
expr * new_e = simp_arg(to_app(t)->get_arg(2), neg_lits, pos_lits, modified);
|
||||
if (!modified)
|
||||
return false;
|
||||
// It is not safe to invoke mk_ite here, since it can recursively call
|
||||
// local_ctx_simp by
|
||||
// It is not safe to invoke mk_ite here, since it can recursively call
|
||||
// local_ctx_simp by
|
||||
// - transforming the ITE into an OR
|
||||
// - and invoked mk_or, that will invoke local_ctx_simp
|
||||
// mk_ite(new_c, new_t, new_e, result);
|
||||
|
@ -522,7 +522,7 @@ bool bool_rewriter::local_ctx_simp(unsigned num_args, expr * const * args, expr_
|
|||
PUSH_NEW_ARG(arg); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
m_local_ctx_cost += 2*num_args;
|
||||
#if 0
|
||||
static unsigned counter = 0;
|
||||
|
@ -567,9 +567,9 @@ bool bool_rewriter::local_ctx_simp(unsigned num_args, expr * const * args, expr_
|
|||
|
||||
/**
|
||||
\brief Apply simplification if ite is an if-then-else tree where every leaf is a value.
|
||||
|
||||
This is an efficient way to
|
||||
|
||||
|
||||
This is an efficient way to
|
||||
|
||||
*/
|
||||
br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result) {
|
||||
SASSERT(m().is_ite(ite));
|
||||
|
@ -585,7 +585,7 @@ br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result)
|
|||
tout << t << " " << e << " " << val << "\n";);
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (t == val && e == val) {
|
||||
result = m().mk_true();
|
||||
|
@ -598,7 +598,7 @@ br_status bool_rewriter::try_ite_value(app * ite, app * val, expr_ref & result)
|
|||
}
|
||||
|
||||
SASSERT(e == val);
|
||||
|
||||
|
||||
mk_not(ite->get_arg(0), result);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -642,14 +642,14 @@ static bool is_ite_value_tree_neq_value(ast_manager & m, app * ite, app * val) {
|
|||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
br_status bool_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
|
||||
if (lhs == rhs) {
|
||||
result = m().mk_true();
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
||||
if (m().are_distinct(lhs, rhs)) {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
|
@ -662,7 +662,7 @@ br_status bool_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
|
|||
// return BR_DONE;
|
||||
// }
|
||||
r = try_ite_value(to_app(lhs), to_app(rhs), result);
|
||||
CTRACE("try_ite_value", r != BR_FAILED,
|
||||
CTRACE("try_ite_value", r != BR_FAILED,
|
||||
tout << mk_ismt2_pp(lhs, m()) << "\n" << mk_ismt2_pp(rhs, m()) << "\n--->\n" << mk_ismt2_pp(result, m()) << "\n";);
|
||||
}
|
||||
else if (m().is_ite(rhs) && m().is_value(lhs)) {
|
||||
|
@ -671,7 +671,7 @@ br_status bool_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
|
|||
// return BR_DONE;
|
||||
// }
|
||||
r = try_ite_value(to_app(rhs), to_app(lhs), result);
|
||||
CTRACE("try_ite_value", r != BR_FAILED,
|
||||
CTRACE("try_ite_value", r != BR_FAILED,
|
||||
tout << mk_ismt2_pp(lhs, m()) << "\n" << mk_ismt2_pp(rhs, m()) << "\n--->\n" << mk_ismt2_pp(result, m()) << "\n";);
|
||||
}
|
||||
if (r != BR_FAILED)
|
||||
|
@ -708,6 +708,19 @@ br_status bool_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
|
|||
result = m().mk_eq(lhs, rhs);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
expr *la, *lb, *ra, *rb;
|
||||
// fold (iff (iff a b) (iff (not a) b)) to false
|
||||
if (m().is_iff(lhs, la, lb) && m().is_iff(rhs, ra, rb)) {
|
||||
expr *n;
|
||||
if ((la == ra && ((m().is_not(rb, n) && n == lb) ||
|
||||
(m().is_not(lb, n) && n == rb))) ||
|
||||
(lb == rb && ((m().is_not(ra, n) && n == la) ||
|
||||
(m().is_not(la, n) && n == ra)))) {
|
||||
result = m().mk_false();
|
||||
return BR_DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
@ -756,13 +769,13 @@ br_status bool_rewriter::mk_distinct_core(unsigned num_args, expr * const * args
|
|||
result = m().mk_and(new_diseqs.size(), new_diseqs.c_ptr());
|
||||
return BR_REWRITE3;
|
||||
}
|
||||
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & result) {
|
||||
bool s = false;
|
||||
|
||||
|
||||
// (ite (not c) a b) ==> (ite c b a)
|
||||
if (m().is_not(c)) {
|
||||
c = to_app(c)->get_arg(0);
|
||||
|
@ -788,7 +801,7 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
result = t;
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
||||
if (m().is_false(c)) {
|
||||
result = e;
|
||||
return BR_DONE;
|
||||
|
@ -814,18 +827,18 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
return BR_DONE;
|
||||
}
|
||||
expr_ref tmp(m());
|
||||
mk_not(c, tmp);
|
||||
mk_not(c, tmp);
|
||||
mk_and(tmp, e, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m().is_true(e)) {
|
||||
expr_ref tmp(m());
|
||||
mk_not(c, tmp);
|
||||
mk_not(c, tmp);
|
||||
mk_or(tmp, t, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m().is_false(e)) {
|
||||
mk_and(c, t, result);
|
||||
mk_and(c, t, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (c == e) {
|
||||
|
@ -833,10 +846,10 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
return BR_DONE;
|
||||
}
|
||||
if (c == t) {
|
||||
mk_or(c, e, result);
|
||||
mk_or(c, e, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
if (m().is_complement_core(t, e)) { // t = not(e)
|
||||
if (m().is_complement_core(t, e)) { // t = not(e)
|
||||
mk_eq(c, t, result);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
@ -863,10 +876,10 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
result = m().mk_ite(new_c, to_app(t)->get_arg(1), e);
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
|
||||
|
||||
if (m().is_ite(e)) {
|
||||
// (ite c1 (ite c2 t1 t2) (ite c3 t1 t2)) ==> (ite (or (and c1 c2) (and (not c1) c3)) t1 t2)
|
||||
if (to_app(t)->get_arg(1) == to_app(e)->get_arg(1) &&
|
||||
if (to_app(t)->get_arg(1) == to_app(e)->get_arg(1) &&
|
||||
to_app(t)->get_arg(2) == to_app(e)->get_arg(2)) {
|
||||
expr_ref and1(m());
|
||||
expr_ref and2(m());
|
||||
|
@ -879,9 +892,9 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
result = m().mk_ite(new_c, to_app(t)->get_arg(1), to_app(t)->get_arg(2));
|
||||
return BR_REWRITE1;
|
||||
}
|
||||
|
||||
|
||||
// (ite c1 (ite c2 t1 t2) (ite c3 t2 t1)) ==> (ite (or (and c1 c2) (and (not c1) (not c3))) t1 t2)
|
||||
if (to_app(t)->get_arg(1) == to_app(e)->get_arg(2) &&
|
||||
if (to_app(t)->get_arg(1) == to_app(e)->get_arg(2) &&
|
||||
to_app(t)->get_arg(2) == to_app(e)->get_arg(1)) {
|
||||
expr_ref and1(m());
|
||||
expr_ref and2(m());
|
||||
|
@ -922,10 +935,10 @@ br_status bool_rewriter::mk_ite_core(expr * c, expr * t, expr * e, expr_ref & re
|
|||
result = m().mk_ite(c, t, e);
|
||||
return BR_DONE;
|
||||
}
|
||||
|
||||
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
|
||||
br_status bool_rewriter::mk_not_core(expr * t, expr_ref & result) {
|
||||
if (m().is_not(t)) {
|
||||
result = to_app(t)->get_arg(0);
|
||||
|
|
|
@ -27,7 +27,7 @@ void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, exp
|
|||
SASSERT(is_well_sorted(result.m(), n));
|
||||
m_reducer.reset();
|
||||
if (m_std_order)
|
||||
m_reducer.set_inv_bindings(num_args, args);
|
||||
m_reducer.set_inv_bindings(num_args, args);
|
||||
else
|
||||
m_reducer.set_bindings(num_args, args);
|
||||
m_reducer(n, result);
|
||||
|
@ -66,7 +66,7 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
return;
|
||||
}
|
||||
|
||||
ptr_buffer<sort> used_decl_sorts;
|
||||
ptr_buffer<sort> used_decl_sorts;
|
||||
buffer<symbol> used_decl_names;
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
if (m_used.contains(num_decls - i - 1)) {
|
||||
|
@ -74,7 +74,7 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
used_decl_names.push_back(q->get_decl_name(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned num_removed = 0;
|
||||
expr_ref_buffer var_mapping(m);
|
||||
int next_idx = 0;
|
||||
|
@ -100,18 +100,18 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
else
|
||||
var_mapping.push_back(0);
|
||||
}
|
||||
|
||||
|
||||
// Remark:
|
||||
|
||||
|
||||
// Remark:
|
||||
// (VAR 0) should be in the last position of var_mapping.
|
||||
// ...
|
||||
// (VAR (var_mapping.size() - 1)) should be in the first position.
|
||||
std::reverse(var_mapping.c_ptr(), var_mapping.c_ptr() + var_mapping.size());
|
||||
|
||||
expr_ref new_expr(m);
|
||||
|
||||
|
||||
m_subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr(), new_expr);
|
||||
|
||||
|
||||
if (num_removed == num_decls) {
|
||||
result = new_expr;
|
||||
return;
|
||||
|
@ -120,7 +120,7 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
expr_ref tmp(m);
|
||||
expr_ref_buffer new_patterns(m);
|
||||
expr_ref_buffer new_no_patterns(m);
|
||||
|
||||
|
||||
for (unsigned i = 0; i < num_patterns; i++) {
|
||||
m_subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
new_patterns.push_back(tmp);
|
||||
|
@ -129,7 +129,7 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
m_subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
|
||||
new_no_patterns.push_back(tmp);
|
||||
}
|
||||
|
||||
|
||||
result = m.mk_quantifier(q->is_forall(),
|
||||
used_decl_sorts.size(),
|
||||
used_decl_sorts.c_ptr(),
|
||||
|
@ -143,7 +143,7 @@ void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
|
|||
num_no_patterns,
|
||||
new_no_patterns.c_ptr());
|
||||
to_quantifier(result)->set_no_unused_vars();
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
SASSERT(is_well_sorted(m, result));
|
||||
}
|
||||
|
||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
|
||||
|
|
|
@ -1401,9 +1401,10 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
|
|||
unsigned rlimit = m_params.m_rlimit;
|
||||
scoped_watch sw(*this);
|
||||
lbool r;
|
||||
bool was_pareto = false, was_opt = false;
|
||||
|
||||
if (m_opt && !m_opt->empty()) {
|
||||
bool was_pareto = false;
|
||||
was_opt = true;
|
||||
m_check_sat_result = get_opt();
|
||||
cancel_eh<opt_wrapper> eh(*get_opt());
|
||||
scoped_ctrl_c ctrlc(eh);
|
||||
|
@ -1436,9 +1437,6 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
|
|||
r = l_true;
|
||||
}
|
||||
get_opt()->set_status(r);
|
||||
if (r != l_false && !was_pareto) {
|
||||
get_opt()->display_assignment(regular_stream());
|
||||
}
|
||||
}
|
||||
else if (m_solver) {
|
||||
m_check_sat_result = m_solver.get(); // solver itself stores the result.
|
||||
|
@ -1465,6 +1463,10 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
|
|||
}
|
||||
display_sat_result(r);
|
||||
validate_check_sat_result(r);
|
||||
if (was_opt && r != l_false && !was_pareto) {
|
||||
get_opt()->display_assignment(regular_stream());
|
||||
}
|
||||
|
||||
if (r == l_true) {
|
||||
validate_model();
|
||||
if (m_params.m_dump_models) {
|
||||
|
|
|
@ -48,7 +48,26 @@ void context_params::set_bool(bool & opt, char const * param, char const * value
|
|||
}
|
||||
else {
|
||||
std::stringstream strm;
|
||||
strm << "invalid value '" << value << "' for Boolean parameter '" << param;
|
||||
strm << "invalid value '" << value << "' for Boolean parameter '" << param << "'";
|
||||
throw default_exception(strm.str());
|
||||
}
|
||||
}
|
||||
|
||||
void context_params::set_uint(unsigned & opt, char const * param, char const * value) {
|
||||
bool is_uint = true;
|
||||
size_t sz = strlen(value);
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
if (!(value[i] >= '0' && value[i] <= '9'))
|
||||
is_uint = false;
|
||||
}
|
||||
|
||||
if (is_uint) {
|
||||
long val = strtol(value, 0, 10);
|
||||
opt = static_cast<unsigned>(val);
|
||||
}
|
||||
else {
|
||||
std::stringstream strm;
|
||||
strm << "invalid value '" << value << "' for unsigned int parameter '" << param << "'";
|
||||
throw default_exception(strm.str());
|
||||
}
|
||||
}
|
||||
|
@ -63,12 +82,10 @@ void context_params::set(char const * param, char const * value) {
|
|||
p[i] = '_';
|
||||
}
|
||||
if (p == "timeout") {
|
||||
long val = strtol(value, 0, 10);
|
||||
m_timeout = static_cast<unsigned>(val);
|
||||
set_uint(m_timeout, param, value);
|
||||
}
|
||||
else if (p == "rlimit") {
|
||||
long val = strtol(value, 0, 10);
|
||||
m_rlimit = static_cast<unsigned>(val);
|
||||
set_uint(m_rlimit, param, value);
|
||||
}
|
||||
else if (p == "type_check" || p == "well_sorted_check") {
|
||||
set_bool(m_well_sorted_check, param, value);
|
||||
|
@ -110,7 +127,7 @@ void context_params::set(char const * param, char const * value) {
|
|||
strm << "unknown parameter '" << p << "'\n";
|
||||
strm << "Legal parameters are:\n";
|
||||
d.display(strm, 2, false, false);
|
||||
throw default_exception(strm.str());
|
||||
throw default_exception(strm.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,8 +191,8 @@ void context_params::get_solver_params(ast_manager const & m, params_ref & p, bo
|
|||
}
|
||||
|
||||
ast_manager * context_params::mk_ast_manager() {
|
||||
ast_manager * r = alloc(ast_manager,
|
||||
m_proof ? PGM_FINE : PGM_DISABLED,
|
||||
ast_manager * r = alloc(ast_manager,
|
||||
m_proof ? PGM_FINE : PGM_DISABLED,
|
||||
m_trace ? m_trace_file_name.c_str() : 0);
|
||||
if (m_smtlib2_compliant)
|
||||
r->enable_int_real_coercions(false);
|
||||
|
|
|
@ -25,7 +25,8 @@ class ast_manager;
|
|||
|
||||
class context_params {
|
||||
void set_bool(bool & opt, char const * param, char const * value);
|
||||
|
||||
void set_uint(unsigned & opt, char const * param, char const * value);
|
||||
|
||||
public:
|
||||
bool m_auto_config;
|
||||
bool m_proof;
|
||||
|
@ -50,7 +51,7 @@ public:
|
|||
/*
|
||||
REG_PARAMS('context_params::collect_param_descrs')
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
\brief Goodies for extracting parameters for creating a solver object.
|
||||
*/
|
||||
|
@ -64,7 +65,7 @@ public:
|
|||
Example: auto_config
|
||||
*/
|
||||
params_ref merge_default_params(params_ref const & p);
|
||||
|
||||
|
||||
/**
|
||||
\brief Create an AST manager using this configuration.
|
||||
*/
|
||||
|
|
|
@ -87,6 +87,7 @@ namespace datalog {
|
|||
for (func_decl_set::iterator I = output_preds.begin(),
|
||||
E = output_preds.end(); I != E; ++I) {
|
||||
func_decl* sym = *I;
|
||||
TRACE("dl", tout << sym->get_name() << "\n";);
|
||||
const rule_vector& output_rules = m_rules.get_predicate_rules(sym);
|
||||
for (unsigned i = 0; i < output_rules.size(); ++i) {
|
||||
m_facts.insert_if_not_there2(sym, Fact())->get_data().m_value.init_down(m_context, output_rules[i]);
|
||||
|
|
|
@ -50,6 +50,7 @@ Notes:
|
|||
#include "blast_term_ite_tactic.h"
|
||||
#include "model_implicant.h"
|
||||
#include "expr_safe_replace.h"
|
||||
#include "ast_util.h"
|
||||
|
||||
namespace pdr {
|
||||
|
||||
|
@ -448,6 +449,7 @@ namespace pdr {
|
|||
else if (is_sat == l_false) {
|
||||
uses_level = m_solver.assumes_level();
|
||||
}
|
||||
m_solver.set_model(0);
|
||||
return is_sat;
|
||||
}
|
||||
|
||||
|
@ -481,6 +483,7 @@ namespace pdr {
|
|||
prop_solver::scoped_level _sl(m_solver, level);
|
||||
m_solver.set_core(&core);
|
||||
m_solver.set_subset_based_core(true);
|
||||
m_solver.set_model(0);
|
||||
lbool res = m_solver.check_assumptions_and_formula(lits, fml);
|
||||
if (res == l_false) {
|
||||
lits.reset();
|
||||
|
@ -738,6 +741,7 @@ namespace pdr {
|
|||
// model_node
|
||||
|
||||
void model_node::set_closed() {
|
||||
TRACE("pdr", tout << state() << "\n";);
|
||||
pt().close(state());
|
||||
m_closed = true;
|
||||
}
|
||||
|
@ -774,6 +778,13 @@ namespace pdr {
|
|||
}
|
||||
// only initial states are not set by the PDR search.
|
||||
SASSERT(m_model.get());
|
||||
if (!m_model.get()) {
|
||||
std::stringstream msg;
|
||||
msg << "no model for node " << state();
|
||||
IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
|
||||
throw default_exception(msg.str());
|
||||
}
|
||||
|
||||
datalog::rule const& rl1 = pt().find_rule(*m_model);
|
||||
if (is_ini(rl1)) {
|
||||
set_rule(&rl1);
|
||||
|
@ -792,15 +803,23 @@ namespace pdr {
|
|||
}
|
||||
}
|
||||
SASSERT(!tags.empty());
|
||||
ini_tags = m.mk_or(tags.size(), tags.c_ptr());
|
||||
ini_tags = ::mk_or(tags);
|
||||
ini_state = m.mk_and(ini_tags, pt().initial_state(), state());
|
||||
model_ref mdl;
|
||||
pt().get_solver().set_model(&mdl);
|
||||
TRACE("pdr", tout << mk_pp(ini_state, m) << "\n";);
|
||||
VERIFY(l_true == pt().get_solver().check_conjunction_as_assumptions(ini_state));
|
||||
TRACE("pdr", tout << ini_state << "\n";);
|
||||
if (l_true != pt().get_solver().check_conjunction_as_assumptions(ini_state)) {
|
||||
std::stringstream msg;
|
||||
msg << "Unsatisfiable initial state: " << ini_state << "\n";
|
||||
display(msg, 2);
|
||||
IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
|
||||
throw default_exception(msg.str());
|
||||
}
|
||||
SASSERT(mdl.get());
|
||||
datalog::rule const& rl2 = pt().find_rule(*mdl);
|
||||
SASSERT(is_ini(rl2));
|
||||
set_rule(&rl2);
|
||||
pt().get_solver().set_model(0);
|
||||
return const_cast<datalog::rule*>(m_rule);
|
||||
}
|
||||
|
||||
|
@ -829,7 +848,7 @@ namespace pdr {
|
|||
}
|
||||
r0 = get_rule();
|
||||
app_ref_vector& inst = pt().get_inst(r0);
|
||||
TRACE("pdr", tout << mk_pp(state(), m) << " instance: " << inst.size() << "\n";);
|
||||
TRACE("pdr", tout << state() << " instance: " << inst.size() << "\n";);
|
||||
for (unsigned i = 0; i < inst.size(); ++i) {
|
||||
expr* v;
|
||||
if (model.find(inst[i].get(), v)) {
|
||||
|
@ -851,7 +870,7 @@ namespace pdr {
|
|||
for (unsigned i = 0; i < indent; ++i) out << " ";
|
||||
out << m_level << " " << m_pt.head()->get_name() << " " << (m_closed?"closed":"open") << "\n";
|
||||
for (unsigned i = 0; i < indent; ++i) out << " ";
|
||||
out << " " << mk_pp(m_state, m_state.get_manager(), indent) << "\n";
|
||||
out << " " << mk_pp(m_state, m_state.get_manager(), indent) << " " << m_state->get_id() << "\n";
|
||||
for (unsigned i = 0; i < children().size(); ++i) {
|
||||
children()[i]->display(out, indent + 1);
|
||||
}
|
||||
|
@ -924,17 +943,6 @@ namespace pdr {
|
|||
}
|
||||
}
|
||||
|
||||
bool model_search::is_repeated(model_node& n) const {
|
||||
model_node* p = n.parent();
|
||||
while (p) {
|
||||
if (p->state() == n.state()) {
|
||||
TRACE("pdr", tout << "repeated\n";);
|
||||
return true;
|
||||
}
|
||||
p = p->parent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void model_search::add_leaf(model_node& n) {
|
||||
SASSERT(n.children().empty());
|
||||
|
@ -1011,13 +1019,18 @@ namespace pdr {
|
|||
nodes.erase(&n);
|
||||
bool is_goal = n.is_goal();
|
||||
remove_goal(n);
|
||||
if (!nodes.empty() && is_goal && backtrack) {
|
||||
// TBD: siblings would also fail if n is not a goal.
|
||||
if (!nodes.empty() && backtrack && nodes[0]->children().empty() && nodes[0]->is_closed()) {
|
||||
TRACE("pdr_verbose", for (unsigned i = 0; i < nodes.size(); ++i) n.display(tout << &n << "\n", 2););
|
||||
model_node* n1 = nodes[0];
|
||||
n1->set_open();
|
||||
SASSERT(n1->children().empty());
|
||||
n1->set_open();
|
||||
enqueue_leaf(n1);
|
||||
}
|
||||
|
||||
if (!nodes.empty() && n.get_model_ptr() && backtrack) {
|
||||
model_ref mr(n.get_model_ptr());
|
||||
nodes[0]->set_model(mr);
|
||||
}
|
||||
if (nodes.empty()) {
|
||||
cache(n).remove(n.state());
|
||||
}
|
||||
|
@ -1149,17 +1162,21 @@ namespace pdr {
|
|||
ast_manager& m = n->pt().get_manager();
|
||||
if (!n->get_model_ptr()) {
|
||||
if (models.find(n->state(), md)) {
|
||||
TRACE("pdr", tout << mk_pp(n->state(), m) << "\n";);
|
||||
TRACE("pdr", tout << n->state() << "\n";);
|
||||
model_ref mr(md);
|
||||
n->set_model(mr);
|
||||
datalog::rule const* rule = rules.find(n->state());
|
||||
n->set_rule(rule);
|
||||
}
|
||||
else {
|
||||
TRACE("pdr", tout << "no model for " << n->state() << "\n";);
|
||||
IF_VERBOSE(1, n->display(verbose_stream() << "no model:\n", 0);
|
||||
verbose_stream() << mk_pp(n->state(), m) << "\n";);
|
||||
verbose_stream() << n->state() << "\n";);
|
||||
}
|
||||
}
|
||||
else {
|
||||
TRACE("pdr", tout << n->state() << "\n";);
|
||||
}
|
||||
todo.pop_back();
|
||||
todo.append(n->children().size(), n->children().c_ptr());
|
||||
}
|
||||
|
@ -1692,7 +1709,15 @@ namespace pdr {
|
|||
|
||||
void context::validate_search() {
|
||||
expr_ref tr = m_search.get_trace(*this);
|
||||
// TBD: tr << "\n";
|
||||
smt::kernel solver(m, get_fparams());
|
||||
solver.assert_expr(tr);
|
||||
lbool res = solver.check();
|
||||
if (res != l_true) {
|
||||
std::stringstream msg;
|
||||
msg << "rule validation failed when checking: " << tr;
|
||||
IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
|
||||
throw default_exception(msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
void context::validate_model() {
|
||||
|
@ -1928,11 +1953,11 @@ namespace pdr {
|
|||
proof_ref proof(m);
|
||||
SASSERT(m_last_result == l_true);
|
||||
proof = m_search.get_proof_trace(*this);
|
||||
TRACE("pdr", tout << "PDR trace: " << mk_pp(proof, m) << "\n";);
|
||||
TRACE("pdr", tout << "PDR trace: " << proof << "\n";);
|
||||
apply(m, m_pc.get(), proof);
|
||||
TRACE("pdr", tout << "PDR trace: " << mk_pp(proof, m) << "\n";);
|
||||
TRACE("pdr", tout << "PDR trace: " << proof << "\n";);
|
||||
// proof_utils::push_instantiations_up(proof);
|
||||
// TRACE("pdr", tout << "PDR up: " << mk_pp(proof, m) << "\n";);
|
||||
// TRACE("pdr", tout << "PDR up: " << proof << "\n";);
|
||||
return proof;
|
||||
}
|
||||
|
||||
|
@ -2027,11 +2052,11 @@ namespace pdr {
|
|||
switch (expand_state(n, cube, uses_level)) {
|
||||
case l_true:
|
||||
if (n.level() == 0) {
|
||||
TRACE("pdr", tout << "reachable at level 0\n";);
|
||||
TRACE("pdr", n.display(tout << "reachable at level 0\n", 0););
|
||||
close_node(n);
|
||||
}
|
||||
else {
|
||||
TRACE("pdr", tout << "node: " << &n << "\n";);
|
||||
TRACE("pdr", n.display(tout, 0););
|
||||
create_children(n);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -240,7 +240,7 @@ namespace pdr {
|
|||
void check_pre_closed();
|
||||
void set_closed();
|
||||
void set_open();
|
||||
void set_pre_closed() { m_closed = true; }
|
||||
void set_pre_closed() { TRACE("pdr", tout << state() << "\n";); m_closed = true; }
|
||||
void reset() { m_children.reset(); }
|
||||
|
||||
void set_rule(datalog::rule const* r) { m_rule = r; }
|
||||
|
@ -268,7 +268,6 @@ namespace pdr {
|
|||
void enqueue_leaf(model_node* n); // add leaf to priority queue.
|
||||
void update_models();
|
||||
void set_leaf(model_node& n); // Set node as leaf, remove children.
|
||||
bool is_repeated(model_node& n) const;
|
||||
unsigned num_goals() const;
|
||||
|
||||
public:
|
||||
|
|
|
@ -41,6 +41,9 @@ namespace datalog {
|
|||
bool new_tail = false;
|
||||
bool contained = true;
|
||||
for (unsigned i = 0; i < r->get_uninterpreted_tail_size(); ++i) {
|
||||
if (m_context.has_facts(r->get_decl(i))) {
|
||||
return 0;
|
||||
}
|
||||
if (r->is_neg_tail(i)) {
|
||||
if (!engine.get_fact(r->get_decl(i)).is_reachable()) {
|
||||
if (!new_tail) {
|
||||
|
|
|
@ -154,7 +154,7 @@ namespace opt {
|
|||
m_soft_constraints(m), m_answer(m) {}
|
||||
|
||||
lbool maxsmt::operator()() {
|
||||
lbool is_sat;
|
||||
lbool is_sat = l_undef;
|
||||
m_msolver = 0;
|
||||
symbol const& maxsat_engine = m_c.maxsat_engine();
|
||||
IF_VERBOSE(1, verbose_stream() << "(maxsmt)\n";);
|
||||
|
@ -191,7 +191,7 @@ namespace opt {
|
|||
m_msolver->set_adjust_value(m_adjust_value);
|
||||
is_sat = (*m_msolver)();
|
||||
if (is_sat != l_false) {
|
||||
m_msolver->get_model(m_model);
|
||||
m_msolver->get_model(m_model, m_labels);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,8 +247,9 @@ namespace opt {
|
|||
m_upper = r;
|
||||
}
|
||||
|
||||
void maxsmt::get_model(model_ref& mdl) {
|
||||
void maxsmt::get_model(model_ref& mdl, svector<symbol>& labels) {
|
||||
mdl = m_model.get();
|
||||
labels = m_labels;
|
||||
}
|
||||
|
||||
void maxsmt::commit_assignment() {
|
||||
|
|
|
@ -46,7 +46,7 @@ namespace opt {
|
|||
virtual bool get_assignment(unsigned index) const = 0;
|
||||
virtual void set_cancel(bool f) = 0;
|
||||
virtual void collect_statistics(statistics& st) const = 0;
|
||||
virtual void get_model(model_ref& mdl) = 0;
|
||||
virtual void get_model(model_ref& mdl, svector<symbol>& labels) = 0;
|
||||
virtual void updt_params(params_ref& p) = 0;
|
||||
void set_adjust_value(adjust_value& adj) { m_adjust_value = adj; }
|
||||
|
||||
|
@ -67,6 +67,7 @@ namespace opt {
|
|||
rational m_lower;
|
||||
rational m_upper;
|
||||
model_ref m_model;
|
||||
svector<symbol> m_labels;
|
||||
svector<bool> m_assignment; // truth assignment to soft constraints
|
||||
params_ref m_params; // config
|
||||
|
||||
|
@ -79,9 +80,9 @@ namespace opt {
|
|||
virtual bool get_assignment(unsigned index) const { return m_assignment[index]; }
|
||||
virtual void set_cancel(bool f) { m_cancel = f; if (f) s().cancel(); else s().reset_cancel(); }
|
||||
virtual void collect_statistics(statistics& st) const { }
|
||||
virtual void get_model(model_ref& mdl) { mdl = m_model.get(); }
|
||||
virtual void get_model(model_ref& mdl, svector<symbol>& labels) { mdl = m_model.get(); labels = m_labels;}
|
||||
virtual void commit_assignment();
|
||||
void set_model() { s().get_model(m_model); }
|
||||
void set_model() { s().get_model(m_model); s().get_labels(m_labels); }
|
||||
virtual void updt_params(params_ref& p);
|
||||
solver& s();
|
||||
void init();
|
||||
|
@ -122,6 +123,7 @@ namespace opt {
|
|||
rational m_upper;
|
||||
adjust_value m_adjust_value;
|
||||
model_ref m_model;
|
||||
svector<symbol> m_labels;
|
||||
params_ref m_params;
|
||||
public:
|
||||
maxsmt(maxsat_context& c);
|
||||
|
@ -139,7 +141,7 @@ namespace opt {
|
|||
rational get_upper() const;
|
||||
void update_lower(rational const& r);
|
||||
void update_upper(rational const& r);
|
||||
void get_model(model_ref& mdl);
|
||||
void get_model(model_ref& mdl, svector<symbol>& labels);
|
||||
bool get_assignment(unsigned index) const;
|
||||
void display_answer(std::ostream& out) const;
|
||||
void collect_statistics(statistics& st) const;
|
||||
|
|
|
@ -167,6 +167,10 @@ namespace opt {
|
|||
m_hard_constraints.reset();
|
||||
}
|
||||
|
||||
void context::get_labels(svector<symbol> & r) {
|
||||
r.append(m_labels);
|
||||
}
|
||||
|
||||
void context::set_hard_constraints(ptr_vector<expr>& fmls) {
|
||||
if (m_scoped_state.set(fmls)) {
|
||||
clear_state();
|
||||
|
@ -228,6 +232,7 @@ namespace opt {
|
|||
TRACE("opt", tout << "initial search result: " << is_sat << "\n";);
|
||||
if (is_sat != l_false) {
|
||||
s.get_model(m_model);
|
||||
s.get_labels(m_labels);
|
||||
}
|
||||
if (is_sat != l_true) {
|
||||
return is_sat;
|
||||
|
@ -276,11 +281,6 @@ namespace opt {
|
|||
}
|
||||
}
|
||||
|
||||
void context::set_model(model_ref& mdl) {
|
||||
m_model = mdl;
|
||||
fix_model(mdl);
|
||||
}
|
||||
|
||||
void context::get_model(model_ref& mdl) {
|
||||
mdl = m_model;
|
||||
fix_model(mdl);
|
||||
|
@ -289,7 +289,7 @@ namespace opt {
|
|||
lbool context::execute_min_max(unsigned index, bool committed, bool scoped, bool is_max) {
|
||||
if (scoped) get_solver().push();
|
||||
lbool result = m_optsmt.lex(index, is_max);
|
||||
if (result == l_true) m_optsmt.get_model(m_model);
|
||||
if (result == l_true) m_optsmt.get_model(m_model, m_labels);
|
||||
if (scoped) get_solver().pop(1);
|
||||
if (result == l_true && committed) m_optsmt.commit_assignment(index);
|
||||
return result;
|
||||
|
@ -300,7 +300,7 @@ namespace opt {
|
|||
maxsmt& ms = *m_maxsmts.find(id);
|
||||
if (scoped) get_solver().push();
|
||||
lbool result = ms();
|
||||
if (result != l_false && (ms.get_model(tmp), tmp.get())) ms.get_model(m_model);
|
||||
if (result != l_false && (ms.get_model(tmp, m_labels), tmp.get())) ms.get_model(m_model, m_labels);
|
||||
if (scoped) get_solver().pop(1);
|
||||
if (result == l_true && committed) ms.commit_assignment();
|
||||
return result;
|
||||
|
@ -453,7 +453,7 @@ namespace opt {
|
|||
}
|
||||
|
||||
void context::yield() {
|
||||
m_pareto->get_model(m_model);
|
||||
m_pareto->get_model(m_model, m_labels);
|
||||
update_bound(true);
|
||||
update_bound(false);
|
||||
}
|
||||
|
@ -770,7 +770,7 @@ namespace opt {
|
|||
tout << "offset: " << offset << "\n";
|
||||
);
|
||||
std::ostringstream out;
|
||||
out << mk_pp(orig_term, m);
|
||||
out << mk_pp(orig_term, m) << ":" << index;
|
||||
id = symbol(out.str().c_str());
|
||||
return true;
|
||||
}
|
||||
|
@ -793,7 +793,7 @@ namespace opt {
|
|||
}
|
||||
neg = true;
|
||||
std::ostringstream out;
|
||||
out << mk_pp(orig_term, m);
|
||||
out << mk_pp(orig_term, m) << ":" << index;
|
||||
id = symbol(out.str().c_str());
|
||||
return true;
|
||||
}
|
||||
|
@ -812,7 +812,7 @@ namespace opt {
|
|||
}
|
||||
neg = is_max;
|
||||
std::ostringstream out;
|
||||
out << mk_pp(orig_term, m);
|
||||
out << mk_pp(orig_term, m) << ":" << index;
|
||||
id = symbol(out.str().c_str());
|
||||
return true;
|
||||
}
|
||||
|
@ -902,6 +902,21 @@ namespace opt {
|
|||
m_hard_constraints.push_back(fml);
|
||||
}
|
||||
}
|
||||
// fix types of objectives:
|
||||
for (unsigned i = 0; i < m_objectives.size(); ++i) {
|
||||
objective & obj = m_objectives[i];
|
||||
expr* t = obj.m_term;
|
||||
switch(obj.m_type) {
|
||||
case O_MINIMIZE:
|
||||
case O_MAXIMIZE:
|
||||
if (!m_arith.is_int(t) && !m_arith.is_real(t)) {
|
||||
obj.m_term = m_arith.mk_numeral(rational(0), true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void context::purify(app_ref& term) {
|
||||
|
@ -1000,7 +1015,10 @@ namespace opt {
|
|||
switch(obj.m_type) {
|
||||
case O_MINIMIZE: {
|
||||
app_ref tmp(m);
|
||||
tmp = m_arith.mk_uminus(obj.m_term);
|
||||
tmp = obj.m_term;
|
||||
if (m_arith.is_int(tmp) || m_arith.is_real(tmp)) {
|
||||
tmp = m_arith.mk_uminus(obj.m_term);
|
||||
}
|
||||
obj.m_index = m_optsmt.add(tmp);
|
||||
break;
|
||||
}
|
||||
|
@ -1103,16 +1121,20 @@ namespace opt {
|
|||
}
|
||||
|
||||
void context::display_assignment(std::ostream& out) {
|
||||
out << "(objectives\n";
|
||||
for (unsigned i = 0; i < m_scoped_state.m_objectives.size(); ++i) {
|
||||
objective const& obj = m_scoped_state.m_objectives[i];
|
||||
out << " (";
|
||||
display_objective(out, obj);
|
||||
if (get_lower_as_num(i) != get_upper_as_num(i)) {
|
||||
out << " |-> [" << get_lower(i) << ":" << get_upper(i) << "]\n";
|
||||
out << " (" << get_lower(i) << " " << get_upper(i) << ")";
|
||||
}
|
||||
else {
|
||||
out << " |-> " << get_lower(i) << "\n";
|
||||
out << " " << get_lower(i);
|
||||
}
|
||||
out << ")\n";
|
||||
}
|
||||
out << ")\n";
|
||||
}
|
||||
|
||||
void context::display_objective(std::ostream& out, objective const& obj) const {
|
||||
|
|
|
@ -162,6 +162,7 @@ namespace opt {
|
|||
bool m_pp_neat;
|
||||
symbol m_maxsat_engine;
|
||||
symbol m_logic;
|
||||
svector<symbol> m_labels;
|
||||
public:
|
||||
context(ast_manager& m);
|
||||
virtual ~context();
|
||||
|
@ -180,11 +181,10 @@ namespace opt {
|
|||
virtual lbool optimize();
|
||||
virtual bool print_model() const;
|
||||
virtual void get_model(model_ref& _m);
|
||||
virtual void set_model(model_ref& _m);
|
||||
virtual void fix_model(model_ref& _m);
|
||||
virtual void collect_statistics(statistics& stats) const;
|
||||
virtual proof* get_proof() { return 0; }
|
||||
virtual void get_labels(svector<symbol> & r) {}
|
||||
virtual void get_labels(svector<symbol> & r);
|
||||
virtual void get_unsat_core(ptr_vector<expr> & r) {}
|
||||
virtual std::string reason_unknown() const;
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace opt {
|
|||
return l_undef;
|
||||
}
|
||||
m_solver->get_model(m_model);
|
||||
m_solver->get_labels(m_labels);
|
||||
IF_VERBOSE(1,
|
||||
model_ref mdl(m_model);
|
||||
cb.fix_model(mdl);
|
||||
|
@ -96,6 +97,7 @@ namespace opt {
|
|||
}
|
||||
if (is_sat == l_true) {
|
||||
m_solver->get_model(m_model);
|
||||
m_solver->get_labels(m_labels);
|
||||
mk_not_dominated_by();
|
||||
}
|
||||
return is_sat;
|
||||
|
|
|
@ -31,7 +31,6 @@ namespace opt {
|
|||
virtual expr_ref mk_gt(unsigned i, model_ref& model) = 0;
|
||||
virtual expr_ref mk_ge(unsigned i, model_ref& model) = 0;
|
||||
virtual expr_ref mk_le(unsigned i, model_ref& model) = 0;
|
||||
virtual void set_model(model_ref& m) = 0;
|
||||
virtual void fix_model(model_ref& m) = 0;
|
||||
};
|
||||
class pareto_base {
|
||||
|
@ -42,6 +41,7 @@ namespace opt {
|
|||
ref<solver> m_solver;
|
||||
params_ref m_params;
|
||||
model_ref m_model;
|
||||
svector<symbol> m_labels;
|
||||
public:
|
||||
pareto_base(
|
||||
ast_manager & m,
|
||||
|
@ -77,8 +77,9 @@ namespace opt {
|
|||
}
|
||||
virtual lbool operator()() = 0;
|
||||
|
||||
virtual void get_model(model_ref& mdl) {
|
||||
virtual void get_model(model_ref& mdl, svector<symbol>& labels) {
|
||||
mdl = m_model;
|
||||
labels = m_labels;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -63,6 +63,11 @@ namespace opt {
|
|||
m_context.updt_params(_p);
|
||||
}
|
||||
|
||||
solver* opt_solver::translate(ast_manager& m, params_ref const& p) {
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void opt_solver::collect_param_descrs(param_descrs & r) {
|
||||
m_context.collect_param_descrs(r);
|
||||
}
|
||||
|
@ -277,6 +282,7 @@ namespace opt {
|
|||
}
|
||||
|
||||
void opt_solver::get_labels(svector<symbol> & r) {
|
||||
r.reset();
|
||||
buffer<symbol> tmp;
|
||||
m_context.get_relevant_labels(0, tmp);
|
||||
r.append(tmp.size(), tmp.c_ptr());
|
||||
|
|
|
@ -86,6 +86,7 @@ namespace opt {
|
|||
opt_solver(ast_manager & m, params_ref const & p, filter_model_converter& fm);
|
||||
virtual ~opt_solver();
|
||||
|
||||
virtual solver* translate(ast_manager& m, params_ref const& p);
|
||||
virtual void updt_params(params_ref & p);
|
||||
virtual void collect_param_descrs(param_descrs & r);
|
||||
virtual void collect_statistics(statistics & st) const;
|
||||
|
|
|
@ -51,6 +51,7 @@ namespace opt {
|
|||
if (src[i] >= dst[i]) {
|
||||
dst[i] = src[i];
|
||||
m_models.set(i, m_s->get_model(i));
|
||||
m_s->get_labels(m_labels);
|
||||
m_lower_fmls[i] = fmls[i].get();
|
||||
if (dst[i].is_pos() && !dst[i].is_finite()) { // review: likely done already.
|
||||
m_lower_fmls[i] = m.mk_false();
|
||||
|
@ -156,7 +157,8 @@ namespace opt {
|
|||
if (is_sat == l_true) {
|
||||
disj.reset();
|
||||
m_s->maximize_objectives(disj);
|
||||
m_s->get_model(m_model);
|
||||
m_s->get_model(m_model);
|
||||
m_s->get_labels(m_labels);
|
||||
for (unsigned i = 0; i < ors.size(); ++i) {
|
||||
expr_ref tmp(m);
|
||||
m_model->eval(ors[i].get(), tmp);
|
||||
|
@ -203,6 +205,7 @@ namespace opt {
|
|||
expr_ref optsmt::update_lower() {
|
||||
expr_ref_vector disj(m);
|
||||
m_s->get_model(m_model);
|
||||
m_s->get_labels(m_labels);
|
||||
m_s->maximize_objectives(disj);
|
||||
set_max(m_lower, m_s->get_objective_values(), disj);
|
||||
TRACE("opt",
|
||||
|
@ -331,6 +334,7 @@ namespace opt {
|
|||
|
||||
m_s->maximize_objective(obj_index, block);
|
||||
m_s->get_model(m_model);
|
||||
m_s->get_labels(m_labels);
|
||||
inf_eps obj = m_s->saved_objective_value(obj_index);
|
||||
if (obj > m_lower[obj_index]) {
|
||||
m_lower[obj_index] = obj;
|
||||
|
@ -405,8 +409,9 @@ namespace opt {
|
|||
return m_upper[i];
|
||||
}
|
||||
|
||||
void optsmt::get_model(model_ref& mdl) {
|
||||
void optsmt::get_model(model_ref& mdl, svector<symbol> & labels) {
|
||||
mdl = m_model.get();
|
||||
labels = m_labels;
|
||||
}
|
||||
|
||||
// force lower_bound(i) <= objective_value(i)
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace opt {
|
|||
svector<smt::theory_var> m_vars;
|
||||
symbol m_optsmt_engine;
|
||||
model_ref m_model;
|
||||
svector<symbol> m_labels;
|
||||
sref_vector<model> m_models;
|
||||
public:
|
||||
optsmt(ast_manager& m):
|
||||
|
@ -60,7 +61,7 @@ namespace opt {
|
|||
inf_eps get_lower(unsigned index) const;
|
||||
inf_eps get_upper(unsigned index) const;
|
||||
bool objective_is_model_valid(unsigned index) const;
|
||||
void get_model(model_ref& mdl);
|
||||
void get_model(model_ref& mdl, svector<symbol>& labels);
|
||||
model* get_model(unsigned index) const { return m_models[index]; }
|
||||
|
||||
void update_lower(unsigned idx, inf_eps const& r);
|
||||
|
|
|
@ -88,7 +88,7 @@ bool pattern_validator::process(uint_set & found_vars, unsigned num_bindings, un
|
|||
if (!f.m_result)
|
||||
return false;
|
||||
if (!f.m_found_a_var) {
|
||||
warning_msg("pattern does contain any variable.");
|
||||
warning_msg("pattern does not contain any variable.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -32,6 +32,7 @@ Notes:
|
|||
#include "model_smt2_pp.h"
|
||||
#include "filter_model_converter.h"
|
||||
#include "bit_blaster_model_converter.h"
|
||||
#include "ast_translation.h"
|
||||
|
||||
// incremental SAT solver.
|
||||
class inc_sat_solver : public solver {
|
||||
|
@ -93,7 +94,25 @@ public:
|
|||
}
|
||||
|
||||
virtual ~inc_sat_solver() {}
|
||||
|
||||
|
||||
virtual solver* translate(ast_manager& dst_m, params_ref const& p) {
|
||||
ast_translation tr(m, dst_m);
|
||||
if (m_num_scopes > 0) {
|
||||
throw default_exception("Cannot translate sat solver at non-base level");
|
||||
}
|
||||
inc_sat_solver* result = alloc(inc_sat_solver, dst_m, p);
|
||||
expr_ref fml(dst_m);
|
||||
for (unsigned i = 0; i < m_fmls.size(); ++i) {
|
||||
fml = tr(m_fmls[i].get());
|
||||
result->m_fmls.push_back(fml);
|
||||
}
|
||||
for (unsigned i = 0; i < m_asmsf.size(); ++i) {
|
||||
fml = tr(m_asmsf[i].get());
|
||||
result->m_asmsf.push_back(fml);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual void set_progress_callback(progress_callback * callback) {}
|
||||
|
||||
virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) {
|
||||
|
@ -231,7 +250,6 @@ public:
|
|||
return "no reason given";
|
||||
}
|
||||
virtual void get_labels(svector<symbol> & r) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
virtual unsigned get_num_assertions() const {
|
||||
return m_fmls.size();
|
||||
|
|
|
@ -3646,6 +3646,9 @@ namespace smt {
|
|||
approx_set::iterator it1 = plbls1.begin();
|
||||
approx_set::iterator end1 = plbls1.end();
|
||||
for (; it1 != end1; ++it1) {
|
||||
if (m_context.get_cancel_flag()) {
|
||||
break;
|
||||
}
|
||||
unsigned plbl1 = *it1;
|
||||
SASSERT(plbls1.may_contain(plbl1));
|
||||
approx_set::iterator it2 = plbls2.begin();
|
||||
|
@ -3687,6 +3690,9 @@ namespace smt {
|
|||
approx_set::iterator it1 = plbls.begin();
|
||||
approx_set::iterator end1 = plbls.end();
|
||||
for (; it1 != end1; ++it1) {
|
||||
if (m_context.get_cancel_flag()) {
|
||||
break;
|
||||
}
|
||||
unsigned plbl1 = *it1;
|
||||
SASSERT(plbls.may_contain(plbl1));
|
||||
approx_set::iterator it2 = clbls.begin();
|
||||
|
@ -3706,6 +3712,9 @@ namespace smt {
|
|||
svector<qp_pair>::iterator it1 = m_new_patterns.begin();
|
||||
svector<qp_pair>::iterator end1 = m_new_patterns.end();
|
||||
for (; it1 != end1; ++it1) {
|
||||
if (m_context.get_cancel_flag()) {
|
||||
break;
|
||||
}
|
||||
quantifier * qa = it1->first;
|
||||
app * mp = it1->second;
|
||||
SASSERT(m_ast_manager.is_pattern(mp));
|
||||
|
|
|
@ -33,7 +33,7 @@ def_module_params(module_name='smt',
|
|||
('qi.cost', STRING, '(+ weight generation)', 'expression specifying what is the cost of a given quantifier instantiation'),
|
||||
('qi.max_multi_patterns', UINT, 0, 'specify the number of extra multi patterns'),
|
||||
('bv.reflect', BOOL, True, 'create enode for every bit-vector term'),
|
||||
('bv.enable_int2bv', BOOL, False, 'enable support for int2bv and bv2int operators'),
|
||||
('bv.enable_int2bv', BOOL, True, 'enable support for int2bv and bv2int operators'),
|
||||
('arith.random_initial_value', BOOL, False, 'use random initial values in the simplex-based procedure for linear arithmetic'),
|
||||
('arith.solver', UINT, 2, 'arithmetic solver: 0 - no solver, 1 - bellman-ford based solver (diff. logic only), 2 - simplex based solver, 3 - floyd-warshall based solver (diff. logic only) and no theory combination'),
|
||||
('arith.nl', BOOL, True, '(incomplete) nonlinear arithmetic support based on Groebner basis and interval propagation'),
|
||||
|
|
|
@ -39,7 +39,7 @@ struct theory_bv_params {
|
|||
m_bv_lazy_le(false),
|
||||
m_bv_cc(false),
|
||||
m_bv_blast_max_size(INT_MAX),
|
||||
m_bv_enable_int2bv2int(false) {
|
||||
m_bv_enable_int2bv2int(true) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ Revision History:
|
|||
#include"smt_model_finder.h"
|
||||
#include"model_pp.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
#include"ast_translation.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
|
@ -98,38 +99,159 @@ namespace smt {
|
|||
m_model_generator->set_context(this);
|
||||
}
|
||||
|
||||
literal context::translate_literal(
|
||||
literal lit, context& src_ctx, context& dst_ctx,
|
||||
vector<bool_var> b2v, ast_translation& tr) {
|
||||
ast_manager& dst_m = dst_ctx.get_manager();
|
||||
ast_manager& src_m = src_ctx.get_manager();
|
||||
expr_ref dst_f(dst_m);
|
||||
|
||||
SASSERT(lit != false_literal && lit != true_literal);
|
||||
bool_var v = b2v.get(lit.var(), null_bool_var);
|
||||
if (v == null_bool_var) {
|
||||
expr* e = src_ctx.m_bool_var2expr.get(lit.var(), 0);
|
||||
SASSERT(e);
|
||||
dst_f = tr(e);
|
||||
v = dst_ctx.get_bool_var_of_id_option(dst_f->get_id());
|
||||
if (v != null_bool_var) {
|
||||
}
|
||||
else if (src_m.is_not(e) || src_m.is_and(e) || src_m.is_or(e) ||
|
||||
src_m.is_iff(e) || src_m.is_ite(e)) {
|
||||
v = dst_ctx.mk_bool_var(dst_f);
|
||||
}
|
||||
else {
|
||||
dst_ctx.internalize_formula(dst_f, false);
|
||||
v = dst_ctx.get_bool_var(dst_f);
|
||||
}
|
||||
b2v.setx(lit.var(), v, null_bool_var);
|
||||
}
|
||||
return literal(v, lit.sign());
|
||||
}
|
||||
|
||||
|
||||
void context::copy(context& src_ctx, context& dst_ctx) {
|
||||
ast_manager& dst_m = dst_ctx.get_manager();
|
||||
ast_manager& src_m = src_ctx.get_manager();
|
||||
src_ctx.pop_to_base_lvl();
|
||||
|
||||
if (src_ctx.m_base_lvl > 0) {
|
||||
throw default_exception("Cloning contexts within a user-scope is not allowed");
|
||||
}
|
||||
SASSERT(src_ctx.m_base_lvl == 0);
|
||||
|
||||
ast_translation tr(src_m, dst_m, false);
|
||||
|
||||
dst_ctx.set_logic(src_ctx.m_setup.get_logic());
|
||||
dst_ctx.copy_plugins(src_ctx, dst_ctx);
|
||||
|
||||
asserted_formulas& src_af = src_ctx.m_asserted_formulas;
|
||||
asserted_formulas& dst_af = dst_ctx.m_asserted_formulas;
|
||||
|
||||
// Copy asserted formulas.
|
||||
for (unsigned i = 0; i < src_af.get_num_formulas(); ++i) {
|
||||
expr_ref fml(dst_m);
|
||||
proof_ref pr(dst_m);
|
||||
proof* pr_src = src_af.get_formula_proof(i);
|
||||
fml = tr(src_af.get_formula(i));
|
||||
if (pr_src) {
|
||||
pr = tr(pr_src);
|
||||
}
|
||||
dst_af.assert_expr(fml, pr);
|
||||
}
|
||||
|
||||
if (!src_ctx.m_setup.already_configured()) {
|
||||
return;
|
||||
}
|
||||
dst_ctx.setup_context(dst_ctx.m_fparams.m_auto_config);
|
||||
dst_ctx.internalize_assertions();
|
||||
|
||||
vector<bool_var> b2v;
|
||||
|
||||
#define TRANSLATE(_lit) translate_literal(_lit, src_ctx, dst_ctx, b2v, tr)
|
||||
|
||||
for (unsigned i = 0; i < src_ctx.m_assigned_literals.size(); ++i) {
|
||||
literal lit;
|
||||
lit = TRANSLATE(src_ctx.m_assigned_literals[i]);
|
||||
dst_ctx.mk_clause(1, &lit, 0, CLS_AUX, 0);
|
||||
}
|
||||
#if 0
|
||||
literal_vector lits;
|
||||
expr_ref_vector cls(src_m);
|
||||
for (unsigned i = 0; i < src_ctx.m_lemmas.size(); ++i) {
|
||||
lits.reset();
|
||||
cls.reset();
|
||||
clause& src_cls = *src_ctx.m_lemmas[i];
|
||||
unsigned sz = src_cls.get_num_literals();
|
||||
for (unsigned j = 0; j < sz; ++j) {
|
||||
literal lit = TRANSLATE(src_cls.get_literal(j));
|
||||
lits.push_back(lit);
|
||||
}
|
||||
dst_ctx.mk_clause(lits.size(), lits.c_ptr(), 0, src_cls.get_kind(), 0);
|
||||
}
|
||||
vector<watch_list>::const_iterator it = src_ctx.m_watches.begin();
|
||||
vector<watch_list>::const_iterator end = src_ctx.m_watches.end();
|
||||
literal ls[2];
|
||||
for (unsigned l_idx = 0; it != end; ++it, ++l_idx) {
|
||||
literal l1 = to_literal(l_idx);
|
||||
literal neg_l1 = ~l1;
|
||||
watch_list const & wl = *it;
|
||||
literal const * it2 = wl.begin_literals();
|
||||
literal const * end2 = wl.end_literals();
|
||||
for (; it2 != end2; ++it2) {
|
||||
literal l2 = *it2;
|
||||
if (l1.index() < l2.index()) {
|
||||
ls[0] = TRANSLATE(neg_l1);
|
||||
ls[1] = TRANSLATE(l2);
|
||||
dst_ctx.mk_clause(2, ls, 0, CLS_AUX, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TRACE("smt_context",
|
||||
src_ctx.display(tout);
|
||||
dst_ctx.display(tout););
|
||||
}
|
||||
|
||||
|
||||
context::~context() {
|
||||
flush();
|
||||
}
|
||||
|
||||
void context::copy_plugins(context& src, context& dst) {
|
||||
|
||||
// copy missing simplifier_plugins
|
||||
// remark: some simplifier_plugins are automatically created by the asserted_formulas class.
|
||||
simplifier & src_s = src.get_simplifier();
|
||||
simplifier & dst_s = dst.get_simplifier();
|
||||
ptr_vector<simplifier_plugin>::const_iterator it1 = src_s.begin_plugins();
|
||||
ptr_vector<simplifier_plugin>::const_iterator end1 = src_s.end_plugins();
|
||||
for (; it1 != end1; ++it1) {
|
||||
simplifier_plugin * p = *it1;
|
||||
if (dst_s.get_plugin(p->get_family_id()) == 0) {
|
||||
dst.register_plugin(p->mk_fresh());
|
||||
}
|
||||
SASSERT(dst_s.get_plugin(p->get_family_id()) != 0);
|
||||
}
|
||||
|
||||
// copy theory plugins
|
||||
ptr_vector<theory>::iterator it2 = src.m_theory_set.begin();
|
||||
ptr_vector<theory>::iterator end2 = src.m_theory_set.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
theory * new_th = (*it2)->mk_fresh(&dst);
|
||||
dst.register_plugin(new_th);
|
||||
}
|
||||
}
|
||||
|
||||
context * context::mk_fresh(symbol const * l, smt_params * p) {
|
||||
context * new_ctx = alloc(context, m_manager, p == 0 ? m_fparams : *p);
|
||||
new_ctx->set_logic(l == 0 ? m_setup.get_logic() : *l);
|
||||
// copy missing simplifier_plugins
|
||||
// remark: some simplifier_plugins are automatically created by the asserted_formulas class.
|
||||
simplifier & s = get_simplifier();
|
||||
simplifier & new_s = new_ctx->get_simplifier();
|
||||
ptr_vector<simplifier_plugin>::const_iterator it1 = s.begin_plugins();
|
||||
ptr_vector<simplifier_plugin>::const_iterator end1 = s.end_plugins();
|
||||
for (; it1 != end1; ++it1) {
|
||||
simplifier_plugin * p = *it1;
|
||||
if (new_s.get_plugin(p->get_family_id()) == 0) {
|
||||
new_ctx->register_plugin(p->mk_fresh());
|
||||
}
|
||||
SASSERT(new_s.get_plugin(p->get_family_id()) != 0);
|
||||
}
|
||||
|
||||
// copy theory plugins
|
||||
ptr_vector<theory>::iterator it2 = m_theory_set.begin();
|
||||
ptr_vector<theory>::iterator end2 = m_theory_set.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
theory * new_th = (*it2)->mk_fresh(new_ctx);
|
||||
new_ctx->register_plugin(new_th);
|
||||
}
|
||||
new_ctx->m_setup.mark_already_configured();
|
||||
copy_plugins(*this, *new_ctx);
|
||||
return new_ctx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void context::init() {
|
||||
app * t = m_manager.mk_true();
|
||||
mk_bool_var(t);
|
||||
|
|
|
@ -1326,9 +1326,18 @@ namespace smt {
|
|||
// -----------------------------------
|
||||
void assert_expr_core(expr * e, proof * pr);
|
||||
|
||||
// copy plugins into a fresh context.
|
||||
void copy_plugins(context& src, context& dst);
|
||||
|
||||
static literal translate_literal(
|
||||
literal lit, context& src_ctx, context& dst_ctx,
|
||||
vector<bool_var> b2v, ast_translation& tr);
|
||||
|
||||
|
||||
public:
|
||||
context(ast_manager & m, smt_params & fp, params_ref const & p = params_ref());
|
||||
|
||||
|
||||
virtual ~context();
|
||||
|
||||
/**
|
||||
|
@ -1340,6 +1349,12 @@ namespace smt {
|
|||
*/
|
||||
context * mk_fresh(symbol const * l = 0, smt_params * p = 0);
|
||||
|
||||
static void copy(context& src, context& dst);
|
||||
|
||||
/**
|
||||
\brief Translate context to use new manager m.
|
||||
*/
|
||||
|
||||
app * mk_eq_atom(expr * lhs, expr * rhs);
|
||||
|
||||
bool set_logic(symbol logic) { return m_setup.set_logic(logic); }
|
||||
|
|
|
@ -32,6 +32,10 @@ namespace smt {
|
|||
m_params(p) {
|
||||
}
|
||||
|
||||
static void copy(imp& src, imp& dst) {
|
||||
context::copy(src.m_kernel, dst.m_kernel);
|
||||
}
|
||||
|
||||
smt_params & fparams() {
|
||||
return m_kernel.get_fparams();
|
||||
}
|
||||
|
@ -193,6 +197,11 @@ namespace smt {
|
|||
return m_imp->m();
|
||||
}
|
||||
|
||||
void kernel::copy(kernel& src, kernel& dst) {
|
||||
imp::copy(*src.m_imp, *dst.m_imp);
|
||||
}
|
||||
|
||||
|
||||
bool kernel::set_logic(symbol logic) {
|
||||
return m_imp->set_logic(logic);
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ namespace smt {
|
|||
|
||||
~kernel();
|
||||
|
||||
static void copy(kernel& src, kernel& dst);
|
||||
|
||||
ast_manager & m() const;
|
||||
|
||||
/**
|
||||
|
|
|
@ -721,8 +721,8 @@ namespace smt {
|
|||
IF_VERBOSE(100, verbose_stream() << "(smt.collecting-features)\n";);
|
||||
st.collect(m_context.get_num_asserted_formulas(), m_context.get_asserted_formulas());
|
||||
IF_VERBOSE(1000, st.display_primitive(verbose_stream()););
|
||||
bool fixnum = st.arith_k_sum_is_small();
|
||||
bool int_only = !st.m_has_rational && !st.m_has_real;
|
||||
bool fixnum = st.arith_k_sum_is_small() && m_params.m_arith_fixnum;
|
||||
bool int_only = !st.m_has_rational && !st.m_has_real && m_params.m_arith_int_only;
|
||||
switch(m_params.m_arith_mode) {
|
||||
case AS_NO_ARITH:
|
||||
m_context.register_plugin(alloc(smt::theory_dummy, m_manager.mk_family_id("arith"), "no arithmetic"));
|
||||
|
|
|
@ -37,6 +37,12 @@ namespace smt {
|
|||
if (m_logic != symbol::null)
|
||||
m_context.set_logic(m_logic);
|
||||
}
|
||||
|
||||
virtual solver* translate(ast_manager& m, params_ref const& p) {
|
||||
solver* result = alloc(solver, m, p, m_logic);
|
||||
smt::kernel::copy(m_context, result->m_context);
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual ~solver() {
|
||||
}
|
||||
|
|
|
@ -1029,7 +1029,7 @@ namespace smt {
|
|||
theory_arith(ast_manager & m, theory_arith_params & params);
|
||||
virtual ~theory_arith();
|
||||
|
||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_arith, get_manager(), m_params); }
|
||||
virtual theory * mk_fresh(context * new_ctx);
|
||||
|
||||
virtual void setup();
|
||||
|
||||
|
|
|
@ -1538,6 +1538,11 @@ namespace smt {
|
|||
theory_arith<Ext>::~theory_arith() {
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
theory* theory_arith<Ext>::mk_fresh(context* new_ctx) {
|
||||
return alloc(theory_arith<Ext>, new_ctx->get_manager(), m_params);
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
void theory_arith<Ext>::setup() {
|
||||
m_random.set_seed(m_params.m_arith_random_seed);
|
||||
|
|
|
@ -210,7 +210,7 @@ namespace smt {
|
|||
TRACE("arith_int", tout << mk_bounded_pp(bound, get_manager()) << "\n";);
|
||||
context & ctx = get_context();
|
||||
ctx.internalize(bound, true);
|
||||
ctx.mark_as_relevant(bound);
|
||||
ctx.mark_as_relevant(bound.get());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ namespace smt {
|
|||
theory_array(ast_manager & m, theory_array_params & params);
|
||||
virtual ~theory_array();
|
||||
|
||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_array, get_manager(), m_params); }
|
||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_array, new_ctx->get_manager(), m_params); }
|
||||
|
||||
virtual char const * get_name() const { return "array"; }
|
||||
|
||||
|
|
|
@ -220,7 +220,7 @@ namespace smt {
|
|||
for (unsigned i = 0; i < dimension; ++i) {
|
||||
sort * ext_sk_domain[2] = { s_array, s_array };
|
||||
parameter p(i);
|
||||
func_decl * ext_sk_decl = m.mk_func_decl(get_id(), OP_ARRAY_EXT_SKOLEM, 1, &p, 2, ext_sk_domain);
|
||||
func_decl * ext_sk_decl = m.mk_func_decl(get_id(), OP_ARRAY_EXT, 1, &p, 2, ext_sk_domain);
|
||||
ext_skolems->push_back(ext_sk_decl);
|
||||
}
|
||||
m_sort2skolem.insert(s_array, ext_skolems);
|
||||
|
@ -310,10 +310,7 @@ namespace smt {
|
|||
func_decl_ref_vector * funcs = 0;
|
||||
sort * s = m.get_sort(e1);
|
||||
|
||||
if (!m_sort2skolem.find(s, funcs)) {
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
VERIFY(m_sort2skolem.find(s, funcs));
|
||||
|
||||
unsigned dimension = funcs->size();
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace smt {
|
|||
bool is_select(app const* n) const { return n->is_app_of(get_id(), OP_SELECT); }
|
||||
bool is_default(app const* n) const { return n->is_app_of(get_id(), OP_ARRAY_DEFAULT); }
|
||||
bool is_const(app const* n) const { return n->is_app_of(get_id(), OP_CONST_ARRAY); }
|
||||
bool is_array_ext(app const * n) const { return n->is_app_of(get_id(), OP_ARRAY_EXT_SKOLEM); }
|
||||
bool is_array_ext(app const * n) const { return n->is_app_of(get_id(), OP_ARRAY_EXT); }
|
||||
bool is_as_array(app const * n) const { return n->is_app_of(get_id(), OP_AS_ARRAY); }
|
||||
bool is_array_sort(sort const* s) const { return s->is_sort_of(get_id(), ARRAY_SORT); }
|
||||
bool is_array_sort(app const* n) const { return is_array_sort(get_manager().get_sort(n)); }
|
||||
|
|
|
@ -35,6 +35,10 @@ namespace smt {
|
|||
m_var_data_full.reset();
|
||||
}
|
||||
|
||||
theory* theory_array_full::mk_fresh(context* new_ctx) {
|
||||
return alloc(theory_array_full, new_ctx->get_manager(), m_params);
|
||||
}
|
||||
|
||||
void theory_array_full::add_map(theory_var v, enode* s) {
|
||||
if (m_params.m_array_cg && !s->is_cgr()) {
|
||||
return;
|
||||
|
@ -269,7 +273,7 @@ namespace smt {
|
|||
}
|
||||
context & ctx = get_context();
|
||||
|
||||
if (is_map(n)) {
|
||||
if (is_map(n) || is_array_ext(n)) {
|
||||
for (unsigned i = 0; i < n->get_num_args(); ++i) {
|
||||
enode* arg = ctx.get_enode(n->get_arg(i));
|
||||
if (!is_attached_to_var(arg)) {
|
||||
|
@ -316,6 +320,10 @@ namespace smt {
|
|||
found_unsupported_op(n);
|
||||
instantiate_default_as_array_axiom(node);
|
||||
}
|
||||
else if (is_array_ext(n)) {
|
||||
SASSERT(n->get_num_args() == 2);
|
||||
instantiate_extensionality(ctx.get_enode(n->get_arg(0)), ctx.get_enode(n->get_arg(1)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace smt {
|
|||
theory_array_full(ast_manager & m, theory_array_params & params);
|
||||
virtual ~theory_array_full();
|
||||
|
||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_array_full, get_manager(), m_params); }
|
||||
virtual theory * mk_fresh(context * new_ctx);
|
||||
|
||||
virtual void merge_eh(theory_var v1, theory_var v2, theory_var, theory_var);
|
||||
virtual void display_var(std::ostream & out, theory_var v) const;
|
||||
|
|
|
@ -1312,6 +1312,11 @@ namespace smt {
|
|||
|
||||
theory_bv::~theory_bv() {
|
||||
}
|
||||
|
||||
theory* theory_bv::mk_fresh(context* new_ctx) {
|
||||
return alloc(theory_bv, new_ctx->get_manager(), m_params, m_bb.get_params());
|
||||
}
|
||||
|
||||
|
||||
void theory_bv::merge_eh(theory_var r1, theory_var r2, theory_var v1, theory_var v2) {
|
||||
TRACE("bv", tout << "merging: #" << get_enode(v1)->get_owner_id() << " #" << get_enode(v2)->get_owner_id() << "\n";);
|
||||
|
|
|
@ -253,7 +253,7 @@ namespace smt {
|
|||
theory_bv(ast_manager & m, theory_bv_params const & params, bit_blaster_params const & bb_params);
|
||||
virtual ~theory_bv();
|
||||
|
||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_bv, get_manager(), m_params, m_bb.get_params()); }
|
||||
virtual theory * mk_fresh(context * new_ctx);
|
||||
|
||||
virtual char const * get_name() const { return "bit-vector"; }
|
||||
|
||||
|
|
|
@ -36,6 +36,11 @@ namespace smt {
|
|||
virtual theory_id get_from_theory() const { return null_theory_id; }
|
||||
};
|
||||
|
||||
|
||||
theory* theory_datatype::mk_fresh(context* new_ctx) {
|
||||
return alloc(theory_datatype, new_ctx->get_manager(), m_params);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Assert the axiom (antecedent => lhs = rhs)
|
||||
antecedent may be null_literal
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace smt {
|
|||
public:
|
||||
theory_datatype(ast_manager & m, theory_datatype_params & p);
|
||||
virtual ~theory_datatype();
|
||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_datatype, get_manager(), m_params); }
|
||||
virtual theory * mk_fresh(context * new_ctx);
|
||||
virtual void display(std::ostream & out) const;
|
||||
virtual void collect_statistics(::statistics & st) const;
|
||||
virtual void init_model(model_generator & m);
|
||||
|
|
|
@ -282,7 +282,7 @@ namespace smt {
|
|||
theory_dense_diff_logic(ast_manager & m, theory_arith_params & p);
|
||||
virtual ~theory_dense_diff_logic() { reset_eh(); }
|
||||
|
||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_dense_diff_logic, get_manager(), m_params); }
|
||||
virtual theory * mk_fresh(context * new_ctx);
|
||||
|
||||
virtual char const * get_name() const { return "difference-logic"; }
|
||||
|
||||
|
|
|
@ -39,6 +39,11 @@ namespace smt {
|
|||
m_edges.push_back(edge());
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
theory* theory_dense_diff_logic<Ext>::mk_fresh(context * new_ctx) {
|
||||
return alloc(theory_dense_diff_logic<Ext>, new_ctx->get_manager(), m_params);
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
inline app * theory_dense_diff_logic<Ext>::mk_zero_for(expr * n) {
|
||||
return m_autil.mk_numeral(rational(0), get_manager().get_sort(n));
|
||||
|
|
|
@ -243,7 +243,7 @@ namespace smt {
|
|||
reset_eh();
|
||||
}
|
||||
|
||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_diff_logic, get_manager(), m_params); }
|
||||
virtual theory * mk_fresh(context * new_ctx);
|
||||
|
||||
virtual char const * get_name() const { return "difference-logic"; }
|
||||
|
||||
|
|
|
@ -1384,5 +1384,11 @@ bool theory_diff_logic<Ext>::internalize_objective(expr * n, rational const& m,
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
theory* theory_diff_logic<Ext>::mk_fresh(context* new_ctx) {
|
||||
return alloc(theory_diff_logic<Ext>, new_ctx->get_manager(), m_params);
|
||||
}
|
||||
|
||||
|
||||
#endif /* THEORY_DIFF_LOGIC_DEF_H_ */
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
virtual theory * mk_fresh(context * new_ctx) {
|
||||
return alloc(theory_dl, get_manager());
|
||||
return alloc(theory_dl, new_ctx->get_manager());
|
||||
}
|
||||
|
||||
virtual void init_model(smt::model_generator & m) {
|
||||
|
|
|
@ -142,7 +142,8 @@ namespace smt {
|
|||
m_trail_stack(*this),
|
||||
m_fpa_util(m_converter.fu()),
|
||||
m_bv_util(m_converter.bu()),
|
||||
m_arith_util(m_converter.au())
|
||||
m_arith_util(m_converter.au()),
|
||||
m_is_initialized(false)
|
||||
{
|
||||
params_ref p;
|
||||
p.set_bool("arith_lhs", true);
|
||||
|
@ -151,10 +152,24 @@ namespace smt {
|
|||
|
||||
theory_fpa::~theory_fpa()
|
||||
{
|
||||
ast_manager & m = get_manager();
|
||||
dec_ref_map_values(m, m_conversions);
|
||||
dec_ref_map_values(m, m_wraps);
|
||||
dec_ref_map_values(m, m_unwraps);
|
||||
if (m_is_initialized) {
|
||||
ast_manager & m = get_manager();
|
||||
dec_ref_map_values(m, m_conversions);
|
||||
dec_ref_map_values(m, m_wraps);
|
||||
dec_ref_map_values(m, m_unwraps);
|
||||
}
|
||||
else {
|
||||
SASSERT(m_conversions.empty());
|
||||
SASSERT(m_wraps.empty());
|
||||
SASSERT(m_unwraps.empty());
|
||||
}
|
||||
|
||||
m_is_initialized = false;
|
||||
}
|
||||
|
||||
void theory_fpa::init(context * ctx) {
|
||||
smt::theory::init(ctx);
|
||||
m_is_initialized = true;
|
||||
}
|
||||
|
||||
app * theory_fpa::fpa_value_proc::mk_value(model_generator & mg, ptr_vector<expr> & values) {
|
||||
|
@ -716,6 +731,10 @@ namespace smt {
|
|||
return;
|
||||
}
|
||||
|
||||
theory* theory_fpa::mk_fresh(context* new_ctx) {
|
||||
return alloc(theory_fpa, new_ctx->get_manager());
|
||||
}
|
||||
|
||||
void theory_fpa::push_scope_eh() {
|
||||
theory::push_scope_eh();
|
||||
m_trail_stack.push_scope();
|
||||
|
@ -859,6 +878,16 @@ namespace smt {
|
|||
mk_ismt2_pp(a2, m) << " eq. cls. #" << get_enode(a2)->get_root()->get_owner()->get_id() << std::endl;);
|
||||
res = vp;
|
||||
}
|
||||
else if (is_app_of(owner, get_family_id(), OP_FPA_INTERNAL_RM)) {
|
||||
SASSERT(to_app(owner)->get_num_args() == 1);
|
||||
app_ref a0(m);
|
||||
a0 = to_app(owner->get_arg(0));
|
||||
fpa_rm_value_proc * vp = alloc(fpa_rm_value_proc, this);
|
||||
vp->add_dependency(ctx.get_enode(a0));
|
||||
TRACE("t_fpa_detail", tout << "Depends on: " <<
|
||||
mk_ismt2_pp(a0, m) << " eq. cls. #" << get_enode(a0)->get_root()->get_owner()->get_id() << std::endl;);
|
||||
res = vp;
|
||||
}
|
||||
else if (ctx.e_internalized(wrapped)) {
|
||||
if (m_fpa_util.is_rm(owner)) {
|
||||
fpa_rm_value_proc * vp = alloc(fpa_rm_value_proc, this);
|
||||
|
|
|
@ -148,6 +148,7 @@ namespace smt {
|
|||
obj_map<sort, func_decl*> m_wraps;
|
||||
obj_map<sort, func_decl*> m_unwraps;
|
||||
obj_map<expr, expr*> m_conversions;
|
||||
bool m_is_initialized;
|
||||
|
||||
virtual final_check_status final_check_eh();
|
||||
virtual bool internalize_atom(app * atom, bool gate_ctx);
|
||||
|
@ -158,7 +159,7 @@ namespace smt {
|
|||
virtual void push_scope_eh();
|
||||
virtual void pop_scope_eh(unsigned num_scopes);
|
||||
virtual void reset_eh();
|
||||
virtual theory* mk_fresh(context*) { return alloc(theory_fpa, get_manager()); }
|
||||
virtual theory* mk_fresh(context* new_ctx);
|
||||
virtual char const * get_name() const { return "fpa"; }
|
||||
|
||||
virtual model_value_proc * mk_value(enode * n, model_generator & mg);
|
||||
|
@ -169,9 +170,11 @@ namespace smt {
|
|||
virtual void finalize_model(model_generator & mg);
|
||||
|
||||
public:
|
||||
theory_fpa(ast_manager& m);
|
||||
theory_fpa(ast_manager & m);
|
||||
virtual ~theory_fpa();
|
||||
|
||||
virtual void init(context * ctx);
|
||||
|
||||
virtual void display(std::ostream & out) const;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace smt {
|
|||
virtual bool internalize_term(app*) { return internalize_atom(0,false); }
|
||||
virtual void new_eq_eh(theory_var, theory_var) { }
|
||||
virtual void new_diseq_eh(theory_var, theory_var) {}
|
||||
virtual theory* mk_fresh(context*) { return alloc(theory_seq_empty, get_manager()); }
|
||||
virtual theory* mk_fresh(context* new_ctx) { return alloc(theory_seq_empty, new_ctx->get_manager()); }
|
||||
virtual char const * get_name() const { return "seq-empty"; }
|
||||
public:
|
||||
theory_seq_empty(ast_manager& m):theory(m.mk_family_id("seq")), m_used(false) {}
|
||||
|
|
|
@ -156,5 +156,5 @@ namespace smt {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ namespace smt {
|
|||
|
||||
virtual ~theory_utvpi();
|
||||
|
||||
virtual theory * mk_fresh(context * new_ctx) { return alloc(theory_utvpi, get_manager()); }
|
||||
virtual theory * mk_fresh(context * new_ctx);
|
||||
|
||||
virtual char const * get_name() const { return "utvpi-logic"; }
|
||||
|
||||
|
|
|
@ -942,6 +942,10 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
theory* theory_utvpi<Ext>::mk_fresh(context* new_ctx) {
|
||||
return alloc(theory_utvpi<Ext>, new_ctx->get_manager());
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
|
|
@ -127,6 +127,17 @@ public:
|
|||
m_use_solver1_results = true;
|
||||
}
|
||||
|
||||
solver* translate(ast_manager& m, params_ref const& p) {
|
||||
solver* s1 = m_solver1->translate(m, p);
|
||||
solver* s2 = m_solver2->translate(m, p);
|
||||
combined_solver* r = alloc(combined_solver, s1, s2, p);
|
||||
r->m_solver2_initialized = m_solver2_initialized;
|
||||
r->m_inc_mode = m_inc_mode;
|
||||
r->m_check_sat_executed = m_check_sat_executed;
|
||||
r->m_use_solver1_results = m_use_solver1_results;
|
||||
return r;
|
||||
}
|
||||
|
||||
virtual void updt_params(params_ref const & p) {
|
||||
m_solver1->updt_params(p);
|
||||
m_solver2->updt_params(p);
|
||||
|
|
|
@ -46,6 +46,12 @@ public:
|
|||
class solver : public check_sat_result {
|
||||
public:
|
||||
virtual ~solver() {}
|
||||
|
||||
/**
|
||||
\brief Creates a clone of the solver.
|
||||
*/
|
||||
virtual solver* translate(ast_manager& m, params_ref const& p) = 0;
|
||||
|
||||
/**
|
||||
\brief Update the solver internal settings.
|
||||
*/
|
||||
|
@ -135,6 +141,8 @@ public:
|
|||
*/
|
||||
virtual expr * get_assumption(unsigned idx) const = 0;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief Display the content of this solver.
|
||||
*/
|
||||
|
|
|
@ -22,6 +22,7 @@ Notes:
|
|||
#include"solver_na2as.h"
|
||||
#include"tactic.h"
|
||||
#include"ast_pp_util.h"
|
||||
#include"ast_translation.h"
|
||||
|
||||
/**
|
||||
\brief Simulates the incremental solver interface using a tactic.
|
||||
|
@ -45,6 +46,8 @@ public:
|
|||
tactic2solver(ast_manager & m, tactic * t, params_ref const & p, bool produce_proofs, bool produce_models, bool produce_unsat_cores, symbol const & logic);
|
||||
virtual ~tactic2solver();
|
||||
|
||||
virtual solver* translate(ast_manager& m, params_ref const& p);
|
||||
|
||||
virtual void updt_params(params_ref const & p);
|
||||
virtual void collect_param_descrs(param_descrs & r);
|
||||
|
||||
|
@ -183,6 +186,22 @@ void tactic2solver::set_cancel(bool f) {
|
|||
}
|
||||
}
|
||||
|
||||
solver* tactic2solver::translate(ast_manager& m, params_ref const& p) {
|
||||
tactic* t = m_tactic->translate(m);
|
||||
tactic2solver* r = alloc(tactic2solver, m, t, p, m_produce_proofs, m_produce_models, m_produce_unsat_cores, m_logic);
|
||||
r->m_result = 0;
|
||||
if (!m_scopes.empty()) {
|
||||
throw default_exception("translation of contexts is only supported at base level");
|
||||
}
|
||||
ast_translation tr(m_assertions.get_manager(), m, false);
|
||||
|
||||
for (unsigned i = 0; i < get_num_assertions(); ++i) {
|
||||
r->m_assertions.push_back(tr(get_assertion(i)));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void tactic2solver::collect_statistics(statistics & st) const {
|
||||
st.copy(m_stats);
|
||||
//SASSERT(m_stats.size() > 0);
|
||||
|
|
|
@ -305,14 +305,16 @@ public:
|
|||
m_nonfd.mark(f, true);
|
||||
expr* e1, *e2;
|
||||
if (m.is_eq(f, e1, e2)) {
|
||||
if (is_fd(e1, e2)) {
|
||||
if (is_fd(e1, e2) || is_fd(e2, e1)) {
|
||||
continue;
|
||||
}
|
||||
if (is_fd(e2, e1)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_todo.append(to_app(f)->get_num_args(), to_app(f)->get_args());
|
||||
if (is_app(f)) {
|
||||
m_todo.append(to_app(f)->get_num_args(), to_app(f)->get_args());
|
||||
}
|
||||
else if (is_quantifier(f)) {
|
||||
m_todo.push_back(to_quantifier(f)->get_expr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
377
src/tactic/bv/bvarray2uf_rewriter.cpp
Normal file
377
src/tactic/bv/bvarray2uf_rewriter.cpp
Normal file
|
@ -0,0 +1,377 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
bvarray2uf_rewriter.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Rewriter that rewrites bit-vector arrays into bit-vector
|
||||
(uninterpreted) functions.
|
||||
|
||||
Author:
|
||||
|
||||
Christoph (cwinter) 2015-11-04
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
|
||||
#include"cooperate.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"array_decl_plugin.h"
|
||||
#include"params.h"
|
||||
#include"ast_pp.h"
|
||||
#include"bvarray2uf_rewriter.h"
|
||||
|
||||
// [1] C. M. Wintersteiger, Y. Hamadi, and L. de Moura: Efficiently Solving
|
||||
// Quantified Bit-Vector Formulas, in Formal Methods in System Design,
|
||||
// vol. 42, no. 1, pp. 3-23, Springer, 2013.
|
||||
|
||||
bvarray2uf_rewriter_cfg::bvarray2uf_rewriter_cfg(ast_manager & m, params_ref const & p) :
|
||||
m_manager(m),
|
||||
m_out(m),
|
||||
m_bindings(m),
|
||||
m_bv_util(m),
|
||||
m_array_util(m),
|
||||
m_emc(0),
|
||||
m_fmc(0),
|
||||
extra_assertions(m) {
|
||||
updt_params(p);
|
||||
// We need to make sure that the mananger has the BV and array plugins loaded.
|
||||
symbol s_bv("bv");
|
||||
if (!m_manager.has_plugin(s_bv))
|
||||
m_manager.register_plugin(s_bv, alloc(bv_decl_plugin));
|
||||
symbol s_array("array");
|
||||
if (!m_manager.has_plugin(s_array))
|
||||
m_manager.register_plugin(s_array, alloc(array_decl_plugin));
|
||||
}
|
||||
|
||||
bvarray2uf_rewriter_cfg::~bvarray2uf_rewriter_cfg() {
|
||||
for (obj_map<expr, func_decl*>::iterator it = m_arrays_fs.begin();
|
||||
it != m_arrays_fs.end();
|
||||
it++)
|
||||
m_manager.dec_ref(it->m_value);
|
||||
}
|
||||
|
||||
void bvarray2uf_rewriter_cfg::reset() {}
|
||||
|
||||
sort * bvarray2uf_rewriter_cfg::get_index_sort(expr * e) {
|
||||
return get_index_sort(m_manager.get_sort(e));
|
||||
}
|
||||
|
||||
sort * bvarray2uf_rewriter_cfg::get_index_sort(sort * s) {
|
||||
SASSERT(s->get_num_parameters() >= 2);
|
||||
unsigned total_width = 0;
|
||||
for (unsigned i = 0; i < s->get_num_parameters() - 1; i++) {
|
||||
parameter const & p = s->get_parameter(i);
|
||||
SASSERT(p.is_ast() && is_sort(to_sort(p.get_ast())));
|
||||
SASSERT(m_bv_util.is_bv_sort(to_sort(p.get_ast())));
|
||||
total_width += m_bv_util.get_bv_size(to_sort(p.get_ast()));
|
||||
}
|
||||
return m_bv_util.mk_sort(total_width);
|
||||
}
|
||||
|
||||
sort * bvarray2uf_rewriter_cfg::get_value_sort(expr * e) {
|
||||
return get_value_sort(m_manager.get_sort(e));
|
||||
}
|
||||
|
||||
sort * bvarray2uf_rewriter_cfg::get_value_sort(sort * s) {
|
||||
SASSERT(s->get_num_parameters() >= 2);
|
||||
parameter const & p = s->get_parameter(s->get_num_parameters() - 1);
|
||||
SASSERT(p.is_ast() && is_sort(to_sort(p.get_ast())));
|
||||
return to_sort(p.get_ast());
|
||||
}
|
||||
|
||||
bool bvarray2uf_rewriter_cfg::is_bv_array(expr * e) {
|
||||
return is_bv_array(m_manager.get_sort(e));
|
||||
}
|
||||
|
||||
bool bvarray2uf_rewriter_cfg::is_bv_array(sort * s) {
|
||||
if (!m_array_util.is_array(s))
|
||||
return false;
|
||||
|
||||
SASSERT(s->get_num_parameters() >= 2);
|
||||
for (unsigned i = 0; i < s->get_num_parameters(); i++) {
|
||||
parameter const & p = s->get_parameter(i);
|
||||
if (!p.is_ast() || !is_sort(to_sort(p.get_ast())) ||
|
||||
!m_bv_util.is_bv_sort(to_sort(p.get_ast())))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
func_decl_ref bvarray2uf_rewriter_cfg::mk_uf_for_array(expr * e) {
|
||||
SASSERT(is_bv_array(e));
|
||||
|
||||
if (m_array_util.is_as_array(e))
|
||||
return func_decl_ref(static_cast<func_decl*>(to_app(e)->get_decl()->get_parameter(0).get_ast()), m_manager);
|
||||
else {
|
||||
app * a = to_app(e);
|
||||
func_decl * bv_f = 0;
|
||||
if (!m_arrays_fs.find(e, bv_f)) {
|
||||
sort * domain = get_index_sort(a);
|
||||
sort * range = get_value_sort(a);
|
||||
bv_f = m_manager.mk_fresh_func_decl("f_t", "", 1, &domain, range);
|
||||
if (is_uninterp_const(e)) {
|
||||
if (m_emc)
|
||||
m_emc->insert(to_app(e)->get_decl(),
|
||||
m_array_util.mk_as_array(m_manager.get_sort(e), bv_f));
|
||||
}
|
||||
else if (m_fmc)
|
||||
m_fmc->insert(bv_f);
|
||||
m_arrays_fs.insert(e, bv_f);
|
||||
m_manager.inc_ref(bv_f);
|
||||
}
|
||||
|
||||
return func_decl_ref(bv_f, m_manager);
|
||||
}
|
||||
}
|
||||
|
||||
br_status bvarray2uf_rewriter_cfg::reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
br_status res = BR_FAILED;
|
||||
|
||||
if (m_manager.is_eq(f) && is_bv_array(f->get_domain()[0])) {
|
||||
SASSERT(num == 2);
|
||||
// From [1]: Finally, we replace equations of the form t = s,
|
||||
// where t and s are arrays, with \forall x . f_t(x) = f_s(x).
|
||||
func_decl_ref f_t(mk_uf_for_array(args[0]), m_manager);
|
||||
func_decl_ref f_s(mk_uf_for_array(args[1]), m_manager);
|
||||
|
||||
sort * sorts[1] = { get_index_sort(m_manager.get_sort(args[0])) };
|
||||
symbol names[1] = { symbol("x") };
|
||||
var_ref x(m_manager.mk_var(0, sorts[0]), m_manager);
|
||||
|
||||
expr_ref body(m_manager);
|
||||
body = m_manager.mk_eq(m_manager.mk_app(f_t, x.get()), m_manager.mk_app(f_s, x.get()));
|
||||
|
||||
result = m_manager.mk_forall(1, sorts, names, body);
|
||||
res = BR_DONE;
|
||||
}
|
||||
else if (m_manager.is_distinct(f) && is_bv_array(f->get_domain()[0])) {
|
||||
result = m_manager.mk_distinct_expanded(num, args);
|
||||
res = BR_REWRITE1;
|
||||
}
|
||||
else if (f->get_family_id() == null_family_id) {
|
||||
TRACE("bvarray2uf_rw", tout << "UF APP: " << f->get_name() << std::endl; );
|
||||
|
||||
bool has_bv_arrays = false;
|
||||
func_decl_ref f_t(m_manager);
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
if (is_bv_array(args[i])) {
|
||||
SASSERT(m_array_util.is_as_array(args[i]));
|
||||
has_bv_arrays = true;
|
||||
}
|
||||
}
|
||||
|
||||
expr_ref t(m_manager);
|
||||
t = m_manager.mk_app(f, num, args);
|
||||
|
||||
if (is_bv_array(t)) {
|
||||
// From [1]: For every array term t we create a fresh uninterpreted function f_t.
|
||||
f_t = mk_uf_for_array(t);
|
||||
result = m_array_util.mk_as_array(m_manager.get_sort(t), f_t);
|
||||
res = BR_DONE;
|
||||
}
|
||||
else if (has_bv_arrays) {
|
||||
result = t;
|
||||
res = BR_DONE;
|
||||
}
|
||||
else
|
||||
res = BR_FAILED;
|
||||
}
|
||||
else if (m_array_util.get_family_id() == f->get_family_id()) {
|
||||
TRACE("bvarray2uf_rw", tout << "APP: " << f->get_name() << std::endl; );
|
||||
|
||||
if (m_array_util.is_select(f)) {
|
||||
SASSERT(num == 2);
|
||||
expr * t = args[0];
|
||||
expr * i = args[1];
|
||||
TRACE("bvarray2uf_rw", tout <<
|
||||
"select; array: " << mk_ismt2_pp(t, m()) <<
|
||||
" index: " << mk_ismt2_pp(i, m()) << std::endl;);
|
||||
|
||||
if (!is_bv_array(t))
|
||||
res = BR_FAILED;
|
||||
else {
|
||||
// From [1]: Then, we replace terms of the form select(t, i) with f_t(i).
|
||||
func_decl_ref f_t(mk_uf_for_array(t), m_manager);
|
||||
result = m_manager.mk_app(f_t, i);
|
||||
res = BR_DONE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!is_bv_array(f->get_range()))
|
||||
res = BR_FAILED;
|
||||
else {
|
||||
if (m_array_util.is_const(f)) {
|
||||
SASSERT(num == 1);
|
||||
expr_ref t(m_manager.mk_app(f, num, args), m_manager);
|
||||
expr * v = args[0];
|
||||
func_decl_ref f_t(mk_uf_for_array(t), m_manager);
|
||||
|
||||
result = m_array_util.mk_as_array(f->get_range(), f_t);
|
||||
res = BR_DONE;
|
||||
|
||||
// Add \forall x . f_t(x) = v
|
||||
sort * sorts[1] = { get_index_sort(f->get_range()) };
|
||||
symbol names[1] = { symbol("x") };
|
||||
var_ref x(m_manager.mk_var(0, sorts[0]), m_manager);
|
||||
|
||||
expr_ref body(m_manager);
|
||||
body = m_manager.mk_eq(m_manager.mk_app(f_t, x.get()), v);
|
||||
|
||||
expr_ref frllx(m_manager.mk_forall(1, sorts, names, body), m_manager);
|
||||
extra_assertions.push_back(frllx);
|
||||
}
|
||||
else if (m_array_util.is_as_array(f)) {
|
||||
res = BR_FAILED;
|
||||
}
|
||||
else if (m_array_util.is_map(f)) {
|
||||
SASSERT(f->get_num_parameters() == 1);
|
||||
SASSERT(f->get_parameter(0).is_ast());
|
||||
expr_ref t(m_manager.mk_app(f, num, args), m_manager);
|
||||
func_decl_ref f_t(mk_uf_for_array(t), m_manager);
|
||||
func_decl_ref map_f(to_func_decl(f->get_parameter(0).get_ast()), m_manager);
|
||||
|
||||
func_decl_ref_vector ss(m_manager);
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
SASSERT(m_array_util.is_array(args[i]));
|
||||
func_decl_ref fd(mk_uf_for_array(args[i]), m_manager);
|
||||
ss.push_back(fd);
|
||||
}
|
||||
|
||||
// Add \forall x . f_t(x) = map_f(a[x], b[x], ...)
|
||||
sort * sorts[1] = { get_index_sort(f->get_range()) };
|
||||
symbol names[1] = { symbol("x") };
|
||||
var_ref x(m_manager.mk_var(0, sorts[0]), m_manager);
|
||||
|
||||
expr_ref_vector new_args(m_manager);
|
||||
for (unsigned i = 0; i < num; i++)
|
||||
new_args.push_back(m_manager.mk_app(ss[i].get(), x.get()));
|
||||
|
||||
expr_ref body(m_manager);
|
||||
body = m_manager.mk_eq(m_manager.mk_app(f_t, x.get()),
|
||||
m_manager.mk_app(map_f, num, new_args.c_ptr()));
|
||||
|
||||
expr_ref frllx(m_manager.mk_forall(1, sorts, names, body), m_manager);
|
||||
extra_assertions.push_back(frllx);
|
||||
|
||||
result = m_array_util.mk_as_array(f->get_range(), f_t);
|
||||
res = BR_DONE;
|
||||
}
|
||||
else if (m_array_util.is_store(f)) {
|
||||
SASSERT(num == 3);
|
||||
expr * s = args[0];
|
||||
expr * i = args[1];
|
||||
expr * v = args[2];
|
||||
TRACE("bvarray2uf_rw", tout <<
|
||||
"store; array: " << mk_ismt2_pp(s, m()) <<
|
||||
" index: " << mk_ismt2_pp(i, m()) <<
|
||||
" value: " << mk_ismt2_pp(v, m()) << std::endl;);
|
||||
if (!is_bv_array(s))
|
||||
res = BR_FAILED;
|
||||
else {
|
||||
expr_ref t(m_manager.mk_app(f, num, args), m_manager);
|
||||
// From [1]: For every term t of the form store(s, i, v), we add the universal
|
||||
// formula \forall x . x = i \vee f_t(x) = f_s(x), and the ground atom f_t(i) = v.
|
||||
func_decl_ref f_s(mk_uf_for_array(s), m_manager);
|
||||
func_decl_ref f_t(mk_uf_for_array(t), m_manager);
|
||||
|
||||
result = m_array_util.mk_as_array(f->get_range(), f_t);
|
||||
res = BR_DONE;
|
||||
|
||||
sort * sorts[1] = { get_index_sort(f->get_range()) };
|
||||
symbol names[1] = { symbol("x") };
|
||||
var_ref x(m_manager.mk_var(0, sorts[0]), m_manager);
|
||||
|
||||
expr_ref body(m_manager);
|
||||
body = m_manager.mk_or(m_manager.mk_eq(x, i),
|
||||
m_manager.mk_eq(m_manager.mk_app(f_t, x.get()),
|
||||
m_manager.mk_app(f_s, x.get())));
|
||||
|
||||
expr_ref frllx(m_manager.mk_forall(1, sorts, names, body), m_manager);
|
||||
extra_assertions.push_back(frllx);
|
||||
|
||||
expr_ref ground_atom(m_manager);
|
||||
ground_atom = m_manager.mk_eq(m_manager.mk_app(f_t, i), v);
|
||||
extra_assertions.push_back(ground_atom);
|
||||
TRACE("bvarray2uf_rw", tout << "ground atom: " << mk_ismt2_pp(ground_atom, m()) << std::endl; );
|
||||
}
|
||||
}
|
||||
else {
|
||||
NOT_IMPLEMENTED_YET();
|
||||
res = BR_FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTRACE("bvarray2uf_rw", res==BR_DONE, tout << "result: " << mk_ismt2_pp(result, m()) << std::endl; );
|
||||
return res;
|
||||
}
|
||||
|
||||
bool bvarray2uf_rewriter_cfg::pre_visit(expr * t)
|
||||
{
|
||||
TRACE("bvarray2uf_rw_q", tout << "pre_visit: " << mk_ismt2_pp(t, m()) << std::endl;);
|
||||
|
||||
if (is_quantifier(t)) {
|
||||
quantifier * q = to_quantifier(t);
|
||||
TRACE("bvarray2uf_rw_q", tout << "pre_visit quantifier [" << q->get_id() << "]: " << mk_ismt2_pp(q->get_expr(), m()) << std::endl;);
|
||||
sort_ref_vector new_bindings(m_manager);
|
||||
for (unsigned i = 0; i < q->get_num_decls(); i++)
|
||||
new_bindings.push_back(q->get_decl_sort(i));
|
||||
SASSERT(new_bindings.size() == q->get_num_decls());
|
||||
m_bindings.append(new_bindings);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bvarray2uf_rewriter_cfg::reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
unsigned curr_sz = m_bindings.size();
|
||||
SASSERT(old_q->get_num_decls() <= curr_sz);
|
||||
unsigned num_decls = old_q->get_num_decls();
|
||||
unsigned old_sz = curr_sz - num_decls;
|
||||
string_buffer<> name_buffer;
|
||||
ptr_buffer<sort> new_decl_sorts;
|
||||
sbuffer<symbol> new_decl_names;
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
symbol const & n = old_q->get_decl_name(i);
|
||||
sort * s = old_q->get_decl_sort(i);
|
||||
|
||||
NOT_IMPLEMENTED_YET();
|
||||
|
||||
}
|
||||
result = m().mk_quantifier(old_q->is_forall(), new_decl_sorts.size(), new_decl_sorts.c_ptr(), new_decl_names.c_ptr(),
|
||||
new_body, old_q->get_weight(), old_q->get_qid(), old_q->get_skid(),
|
||||
old_q->get_num_patterns(), new_patterns, old_q->get_num_no_patterns(), new_no_patterns);
|
||||
result_pr = 0;
|
||||
m_bindings.shrink(old_sz);
|
||||
TRACE("bvarray2uf_rw_q", tout << "reduce_quantifier[" << old_q->get_depth() << "]: " <<
|
||||
mk_ismt2_pp(old_q->get_expr(), m()) << std::endl <<
|
||||
" new body: " << mk_ismt2_pp(new_body, m()) << std::endl;
|
||||
tout << "result = " << mk_ismt2_pp(result, m()) << std::endl;);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bvarray2uf_rewriter_cfg::reduce_var(var * t, expr_ref & result, proof_ref & result_pr) {
|
||||
if (t->get_idx() >= m_bindings.size())
|
||||
return false;
|
||||
|
||||
expr_ref new_exp(m());
|
||||
sort * s = t->get_sort();
|
||||
|
||||
NOT_IMPLEMENTED_YET();
|
||||
|
||||
result = new_exp;
|
||||
result_pr = 0;
|
||||
TRACE("bvarray2uf_rw_q", tout << "reduce_var: " << mk_ismt2_pp(t, m()) << " -> " << mk_ismt2_pp(result, m()) << std::endl;);
|
||||
return true;
|
||||
}
|
87
src/tactic/bv/bvarray2uf_rewriter.h
Normal file
87
src/tactic/bv/bvarray2uf_rewriter.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
/*++
|
||||
Copyright (c) 2012 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
bvarray2uf_rewriter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Rewriter that rewrites bit-vector arrays into bit-vector
|
||||
(uninterpreted) functions.
|
||||
|
||||
Author:
|
||||
|
||||
Christoph (cwinter) 2015-11-04
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef BVARRAY2UF_REWRITER_H_
|
||||
#define BVARRAY2UF_REWRITER_H_
|
||||
|
||||
#include"rewriter_def.h"
|
||||
#include"extension_model_converter.h"
|
||||
#include"filter_model_converter.h"
|
||||
|
||||
class bvarray2uf_rewriter_cfg : public default_rewriter_cfg {
|
||||
ast_manager & m_manager;
|
||||
expr_ref_vector m_out;
|
||||
sort_ref_vector m_bindings;
|
||||
bv_util m_bv_util;
|
||||
array_util m_array_util;
|
||||
extension_model_converter * m_emc;
|
||||
filter_model_converter * m_fmc;
|
||||
|
||||
obj_map<expr, func_decl*> m_arrays_fs;
|
||||
|
||||
public:
|
||||
bvarray2uf_rewriter_cfg(ast_manager & m, params_ref const & p);
|
||||
~bvarray2uf_rewriter_cfg();
|
||||
|
||||
ast_manager & m() const { return m_manager; }
|
||||
void updt_params(params_ref const & p) {}
|
||||
|
||||
void reset();
|
||||
|
||||
bool pre_visit(expr * t);
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr);
|
||||
|
||||
bool reduce_quantifier(quantifier * old_q,
|
||||
expr * new_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr);
|
||||
|
||||
bool reduce_var(var * t, expr_ref & result, proof_ref & result_pr);
|
||||
|
||||
expr_ref_vector extra_assertions;
|
||||
|
||||
void set_mcs(extension_model_converter * emc, filter_model_converter * fmc) { m_emc = emc; m_fmc = fmc; }
|
||||
|
||||
protected:
|
||||
sort * get_index_sort(expr * e);
|
||||
sort * get_index_sort(sort * s);
|
||||
sort * get_value_sort(expr * e);
|
||||
sort * get_value_sort(sort * s);
|
||||
bool is_bv_array(expr * e);
|
||||
bool is_bv_array(sort * e);
|
||||
func_decl_ref mk_uf_for_array(expr * e);
|
||||
};
|
||||
|
||||
template class rewriter_tpl<bvarray2uf_rewriter_cfg>;
|
||||
|
||||
struct bvarray2uf_rewriter : public rewriter_tpl<bvarray2uf_rewriter_cfg> {
|
||||
bvarray2uf_rewriter_cfg m_cfg;
|
||||
bvarray2uf_rewriter(ast_manager & m, params_ref const & p) :
|
||||
rewriter_tpl<bvarray2uf_rewriter_cfg>(m, m.proofs_enabled(), m_cfg),
|
||||
m_cfg(m, p) {
|
||||
}
|
||||
|
||||
void set_mcs(extension_model_converter * emc, filter_model_converter * fmc) { m_cfg.set_mcs(emc, fmc); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
168
src/tactic/bv/bvarray2uf_tactic.cpp
Normal file
168
src/tactic/bv/bvarray2uf_tactic.cpp
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
bvarray2uf_tactic.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic that rewrites bit-vector arrays into bit-vector
|
||||
(uninterpreted) functions.
|
||||
|
||||
Author:
|
||||
|
||||
Christoph (cwinter) 2015-11-04
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#include"tactical.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"expr_replacer.h"
|
||||
#include"extension_model_converter.h"
|
||||
#include"filter_model_converter.h"
|
||||
#include"ast_smt2_pp.h"
|
||||
|
||||
#include"bvarray2uf_tactic.h"
|
||||
#include"bvarray2uf_rewriter.h"
|
||||
|
||||
class bvarray2uf_tactic : public tactic {
|
||||
|
||||
struct imp {
|
||||
ast_manager & m_manager;
|
||||
bool m_produce_models;
|
||||
bool m_produce_proofs;
|
||||
bool m_produce_cores;
|
||||
volatile bool m_cancel;
|
||||
bvarray2uf_rewriter m_rw;
|
||||
|
||||
ast_manager & m() { return m_manager; }
|
||||
|
||||
imp(ast_manager & m, params_ref const & p) :
|
||||
m_manager(m),
|
||||
m_produce_models(false),
|
||||
m_cancel(false),
|
||||
m_produce_proofs(false),
|
||||
m_produce_cores(false),
|
||||
m_rw(m, p) {
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
void set_cancel(bool f) {
|
||||
m_cancel = f;
|
||||
}
|
||||
|
||||
void checkpoint() {
|
||||
if (m_cancel)
|
||||
throw tactic_exception(TACTIC_CANCELED_MSG);
|
||||
}
|
||||
|
||||
void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core)
|
||||
{
|
||||
SASSERT(g->is_well_sorted());
|
||||
tactic_report report("bvarray2uf", *g);
|
||||
mc = 0; pc = 0; core = 0; result.reset();
|
||||
fail_if_proof_generation("bvarray2uf", g);
|
||||
fail_if_unsat_core_generation("bvarray2uf", g);
|
||||
|
||||
TRACE("bvarray2uf", tout << "Before: " << std::endl; g->display(tout); );
|
||||
m_produce_models = g->models_enabled();
|
||||
|
||||
if (m_produce_models) {
|
||||
extension_model_converter * emc = alloc(extension_model_converter, m_manager);
|
||||
filter_model_converter * fmc = alloc(filter_model_converter, m_manager);
|
||||
mc = concat(emc, fmc);
|
||||
m_rw.set_mcs(emc, fmc);
|
||||
|
||||
}
|
||||
|
||||
|
||||
m_rw.reset();
|
||||
expr_ref new_curr(m_manager);
|
||||
proof_ref new_pr(m_manager);
|
||||
unsigned size = g->size();
|
||||
for (unsigned idx = 0; idx < size; idx++) {
|
||||
if (g->inconsistent())
|
||||
break;
|
||||
expr * curr = g->form(idx);
|
||||
m_rw(curr, new_curr, new_pr);
|
||||
//if (m_produce_proofs) {
|
||||
// proof * pr = g->pr(idx);
|
||||
// new_pr = m.mk_modus_ponens(pr, new_pr);
|
||||
//}
|
||||
g->update(idx, new_curr, new_pr, g->dep(idx));
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < m_rw.m_cfg.extra_assertions.size(); i++)
|
||||
g->assert_expr(m_rw.m_cfg.extra_assertions[i].get());
|
||||
|
||||
g->inc_depth();
|
||||
result.push_back(g.get());
|
||||
TRACE("bvarray2uf", tout << "After: " << std::endl; g->display(tout););
|
||||
SASSERT(g->is_well_sorted());
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
}
|
||||
};
|
||||
|
||||
imp * m_imp;
|
||||
params_ref m_params;
|
||||
|
||||
public:
|
||||
bvarray2uf_tactic(ast_manager & m, params_ref const & p) :
|
||||
m_params(p) {
|
||||
m_imp = alloc(imp, m, p);
|
||||
}
|
||||
|
||||
virtual tactic * translate(ast_manager & m) {
|
||||
return alloc(bvarray2uf_tactic, m, m_params);
|
||||
}
|
||||
|
||||
virtual ~bvarray2uf_tactic() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
virtual void updt_params(params_ref const & p) {
|
||||
m_params = p;
|
||||
m_imp->updt_params(p);
|
||||
}
|
||||
|
||||
virtual void collect_param_descrs(param_descrs & r) {
|
||||
insert_produce_models(r);
|
||||
}
|
||||
|
||||
virtual void operator()(goal_ref const & in,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
(*m_imp)(in, result, mc, pc, core);
|
||||
}
|
||||
|
||||
virtual void cleanup() {
|
||||
ast_manager & m = m_imp->m();
|
||||
imp * d = alloc(imp, m, m_params);
|
||||
#pragma omp critical (tactic_cancel)
|
||||
{
|
||||
std::swap(d, m_imp);
|
||||
}
|
||||
dealloc(d);
|
||||
}
|
||||
|
||||
virtual void set_cancel(bool f) {
|
||||
if (m_imp)
|
||||
m_imp->set_cancel(f);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
tactic * mk_bvarray2uf_tactic(ast_manager & m, params_ref const & p) {
|
||||
return clean(alloc(bvarray2uf_tactic, m, p));
|
||||
}
|
33
src/tactic/bv/bvarray2uf_tactic.h
Normal file
33
src/tactic/bv/bvarray2uf_tactic.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
bvarray2ufbvarray2uf_tactic.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic that rewrites bit-vector arrays into bit-vector
|
||||
(uninterpreted) functions.
|
||||
|
||||
Author:
|
||||
|
||||
Christoph (cwinter) 2015-11-04
|
||||
|
||||
Notes:
|
||||
|
||||
--*/
|
||||
#ifndef BV_ARRAY2UF_TACTIC_H_
|
||||
#define BV_ARRAY2UF_TACTIC_H_
|
||||
|
||||
#include"params.h"
|
||||
class ast_manager;
|
||||
class tactic;
|
||||
|
||||
tactic * mk_bvarray2uf_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||
/*
|
||||
ADD_TACTIC("bvarray2uf", "Rewrite bit-vector arrays into bit-vector (uninterpreted) functions.", "mk_bvarray2uf_tactic(m, p)")
|
||||
*/
|
||||
|
||||
|
||||
#endif
|
332
src/tactic/bv/elim_small_bv_tactic.cpp
Normal file
332
src/tactic/bv/elim_small_bv_tactic.cpp
Normal file
|
@ -0,0 +1,332 @@
|
|||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
elim_small_bv.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic that eliminates small, quantified bit-vectors.
|
||||
|
||||
Author:
|
||||
|
||||
Christoph (cwinter) 2015-11-09
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include"tactical.h"
|
||||
#include"rewriter_def.h"
|
||||
#include"filter_model_converter.h"
|
||||
#include"cooperate.h"
|
||||
#include"bv_decl_plugin.h"
|
||||
#include"used_vars.h"
|
||||
#include"well_sorted.h"
|
||||
#include"var_subst.h"
|
||||
#include"simplifier.h"
|
||||
#include"basic_simplifier_plugin.h"
|
||||
#include"bv_simplifier_plugin.h"
|
||||
|
||||
#include"elim_small_bv_tactic.h"
|
||||
|
||||
class elim_small_bv_tactic : public tactic {
|
||||
|
||||
struct rw_cfg : public default_rewriter_cfg {
|
||||
ast_manager & m;
|
||||
bv_util m_util;
|
||||
simplifier m_simp;
|
||||
ref<filter_model_converter> m_mc;
|
||||
goal * m_goal;
|
||||
unsigned m_max_bits;
|
||||
unsigned long long m_max_steps;
|
||||
unsigned long long m_max_memory; // in bytes
|
||||
bool m_produce_models;
|
||||
sort_ref_vector m_bindings;
|
||||
unsigned long m_num_eliminated;
|
||||
|
||||
rw_cfg(ast_manager & _m, params_ref const & p) :
|
||||
m(_m),
|
||||
m_util(_m),
|
||||
m_simp(_m),
|
||||
m_bindings(_m),
|
||||
m_num_eliminated(0) {
|
||||
updt_params(p);
|
||||
m_goal = 0;
|
||||
m_max_steps = UINT_MAX;
|
||||
|
||||
basic_simplifier_plugin * bsimp = alloc(basic_simplifier_plugin, m);
|
||||
// bsimp->set_eliminate_and(true);
|
||||
m_simp.register_plugin(bsimp);
|
||||
|
||||
bv_simplifier_params bv_params;
|
||||
bv_simplifier_plugin * bvsimp = alloc(bv_simplifier_plugin, m, *bsimp, bv_params);
|
||||
m_simp.register_plugin(bvsimp);
|
||||
}
|
||||
|
||||
bool max_steps_exceeded(unsigned long long num_steps) const {
|
||||
cooperate("elim-small-bv");
|
||||
if (num_steps > m_max_steps)
|
||||
return true;
|
||||
if (memory::get_allocation_size() > m_max_memory)
|
||||
throw tactic_exception(TACTIC_MAX_MEMORY_MSG);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_small_bv(sort * s) {
|
||||
return m_util.is_bv_sort(s) && m_util.get_bv_size(s) <= m_max_bits;
|
||||
}
|
||||
|
||||
expr_ref replace_var(used_vars & uv,
|
||||
unsigned num_decls, unsigned max_var_idx_p1,
|
||||
unsigned idx, sort * s, expr * e, expr * replacement) {
|
||||
TRACE("elim_small_bv", tout << "replace idx " << idx << " with " << mk_ismt2_pp(replacement, m) <<
|
||||
" in " << mk_ismt2_pp(e, m) << std::endl;);
|
||||
expr_ref res(m);
|
||||
expr_ref_vector substitution(m);
|
||||
|
||||
substitution.resize(num_decls, 0);
|
||||
substitution[num_decls - idx - 1] = replacement;
|
||||
|
||||
// (VAR 0) is in the first position of substitution; (VAR num_decls-1) is in the last position.
|
||||
|
||||
for (unsigned i = 0; i < max_var_idx_p1; i++) {
|
||||
sort * s = uv.get(i);
|
||||
substitution.push_back(0);
|
||||
}
|
||||
|
||||
// (VAR num_decls) ... (VAR num_decls+sz-1); are in positions num_decls .. num_decls+sz-1
|
||||
|
||||
std::reverse(substitution.c_ptr(), substitution.c_ptr() + substitution.size());
|
||||
|
||||
// (VAR 0) should be in the last position of substitution.
|
||||
|
||||
TRACE("elim_small_bv", tout << "substitution: " << std::endl;
|
||||
for (unsigned k = 0; k < substitution.size(); k++) {
|
||||
expr * se = substitution[k].get();
|
||||
tout << k << " = ";
|
||||
if (se == 0) tout << "0";
|
||||
else tout << mk_ismt2_pp(se, m);
|
||||
tout << std::endl;
|
||||
});
|
||||
|
||||
var_subst vsbst(m);
|
||||
vsbst(e, substitution.size(), substitution.c_ptr(), res);
|
||||
SASSERT(is_well_sorted(m, res));
|
||||
|
||||
proof_ref pr(m);
|
||||
m_simp(res, res, pr);
|
||||
TRACE("elim_small_bv", tout << "replace done: " << mk_ismt2_pp(res, m) << std::endl;);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
br_status reduce_app(func_decl * f, unsigned num, expr * const * args, expr_ref & result, proof_ref & result_pr) {
|
||||
result = m.mk_app(f, num, args);
|
||||
TRACE("elim_small_bv_app", tout << "reduce " << mk_ismt2_pp(result, m) << std::endl; );
|
||||
return BR_FAILED;
|
||||
}
|
||||
|
||||
bool reduce_quantifier(
|
||||
quantifier * q,
|
||||
expr * old_body,
|
||||
expr * const * new_patterns,
|
||||
expr * const * new_no_patterns,
|
||||
expr_ref & result,
|
||||
proof_ref & result_pr) {
|
||||
TRACE("elim_small_bv", tout << "reduce_quantifier " << mk_ismt2_pp(q, m) << std::endl; );
|
||||
unsigned long long num_steps = 0;
|
||||
unsigned curr_sz = m_bindings.size();
|
||||
SASSERT(q->get_num_decls() <= curr_sz);
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
unsigned old_sz = curr_sz - num_decls;
|
||||
|
||||
used_vars uv;
|
||||
uv(q);
|
||||
SASSERT(is_well_sorted(m, q));
|
||||
unsigned max_var_idx_p1 = uv.get_max_found_var_idx_plus_1();
|
||||
|
||||
expr_ref body(old_body, m);
|
||||
for (unsigned i = num_decls-1; i != ((unsigned)-1) && !max_steps_exceeded(num_steps); i--) {
|
||||
sort * s = q->get_decl_sort(i);
|
||||
symbol const & name = q->get_decl_name(i);
|
||||
unsigned bv_sz = m_util.get_bv_size(s);
|
||||
|
||||
if (is_small_bv(s) && !max_steps_exceeded(num_steps)) {
|
||||
TRACE("elim_small_bv", tout << "eliminating " << name <<
|
||||
"; sort = " << mk_ismt2_pp(s, m) <<
|
||||
"; body = " << mk_ismt2_pp(body, m) << std::endl;);
|
||||
|
||||
expr_ref_vector new_bodies(m);
|
||||
for (unsigned j = 0; j < bv_sz && !max_steps_exceeded(num_steps); j ++) {
|
||||
expr_ref n(m_util.mk_numeral(j, bv_sz), m);
|
||||
expr_ref nb(m);
|
||||
nb = replace_var(uv, num_decls, max_var_idx_p1, i, s, body, n);
|
||||
new_bodies.push_back(nb);
|
||||
num_steps++;
|
||||
}
|
||||
|
||||
TRACE("elim_small_bv", tout << "new bodies: " << std::endl;
|
||||
for (unsigned k = 0; k < new_bodies.size(); k++)
|
||||
tout << mk_ismt2_pp(new_bodies[k].get(), m) << std::endl; );
|
||||
|
||||
body = q->is_forall() ? m.mk_and(new_bodies.size(), new_bodies.c_ptr()) :
|
||||
m.mk_or(new_bodies.size(), new_bodies.c_ptr());
|
||||
SASSERT(is_well_sorted(m, body));
|
||||
|
||||
proof_ref pr(m);
|
||||
m_simp(body, body, pr);
|
||||
m_num_eliminated++;
|
||||
}
|
||||
}
|
||||
|
||||
quantifier_ref new_q(m);
|
||||
new_q = m.update_quantifier(q, body);
|
||||
unused_vars_eliminator el(m);
|
||||
el(new_q, result);
|
||||
|
||||
TRACE("elim_small_bv", tout << "elimination result: " << mk_ismt2_pp(result, m) << std::endl; );
|
||||
|
||||
result_pr = 0; // proofs NIY
|
||||
m_bindings.shrink(old_sz);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pre_visit(expr * t) {
|
||||
TRACE("elim_small_bv_pre", tout << "pre_visit: " << mk_ismt2_pp(t, m) << std::endl;);
|
||||
if (is_quantifier(t)) {
|
||||
quantifier * q = to_quantifier(t);
|
||||
TRACE("elim_small_bv", tout << "pre_visit quantifier [" << q->get_id() << "]: " << mk_ismt2_pp(q->get_expr(), m) << std::endl;);
|
||||
sort_ref_vector new_bindings(m);
|
||||
for (unsigned i = 0; i < q->get_num_decls(); i++)
|
||||
new_bindings.push_back(q->get_decl_sort(i));
|
||||
SASSERT(new_bindings.size() == q->get_num_decls());
|
||||
m_bindings.append(new_bindings);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_max_memory = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
|
||||
m_max_steps = p.get_uint("max_steps", UINT_MAX);
|
||||
m_max_bits = p.get_uint("max_bits", 4);
|
||||
}
|
||||
};
|
||||
|
||||
struct rw : public rewriter_tpl<rw_cfg> {
|
||||
rw_cfg m_cfg;
|
||||
|
||||
rw(ast_manager & m, params_ref const & p) :
|
||||
rewriter_tpl<rw_cfg>(m, m.proofs_enabled(), m_cfg),
|
||||
m_cfg(m, p) {
|
||||
}
|
||||
};
|
||||
|
||||
struct imp {
|
||||
ast_manager & m;
|
||||
rw m_rw;
|
||||
|
||||
imp(ast_manager & _m, params_ref const & p) :
|
||||
m(_m),
|
||||
m_rw(m, p) {
|
||||
}
|
||||
|
||||
void set_cancel(bool f) {
|
||||
m_rw.set_cancel(f);
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
m_rw.cfg().updt_params(p);
|
||||
}
|
||||
|
||||
void operator()(goal_ref const & g,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
SASSERT(g->is_well_sorted());
|
||||
mc = 0; pc = 0; core = 0;
|
||||
tactic_report report("elim-small-bv", *g);
|
||||
bool produce_proofs = g->proofs_enabled();
|
||||
fail_if_proof_generation("elim-small-bv", g);
|
||||
fail_if_unsat_core_generation("elim-small-bv", g);
|
||||
m_rw.cfg().m_produce_models = g->models_enabled();
|
||||
|
||||
m_rw.m_cfg.m_goal = g.get();
|
||||
expr_ref new_curr(m);
|
||||
proof_ref new_pr(m);
|
||||
unsigned size = g->size();
|
||||
for (unsigned idx = 0; idx < size; idx++) {
|
||||
expr * curr = g->form(idx);
|
||||
m_rw(curr, new_curr, new_pr);
|
||||
if (produce_proofs) {
|
||||
proof * pr = g->pr(idx);
|
||||
new_pr = m.mk_modus_ponens(pr, new_pr);
|
||||
}
|
||||
g->update(idx, new_curr, new_pr, g->dep(idx));
|
||||
}
|
||||
mc = m_rw.m_cfg.m_mc.get();
|
||||
|
||||
report_tactic_progress(":elim-small-bv-num-eliminated", m_rw.m_cfg.m_num_eliminated);
|
||||
g->inc_depth();
|
||||
result.push_back(g.get());
|
||||
TRACE("elim-small-bv", g->display(tout););
|
||||
SASSERT(g->is_well_sorted());
|
||||
}
|
||||
};
|
||||
|
||||
imp * m_imp;
|
||||
params_ref m_params;
|
||||
public:
|
||||
elim_small_bv_tactic(ast_manager & m, params_ref const & p) :
|
||||
m_params(p) {
|
||||
m_imp = alloc(imp, m, p);
|
||||
}
|
||||
|
||||
virtual tactic * translate(ast_manager & m) {
|
||||
return alloc(elim_small_bv_tactic, m, m_params);
|
||||
}
|
||||
|
||||
virtual ~elim_small_bv_tactic() {
|
||||
dealloc(m_imp);
|
||||
}
|
||||
|
||||
virtual void updt_params(params_ref const & p) {
|
||||
m_params = p;
|
||||
m_imp->m_rw.cfg().updt_params(p);
|
||||
}
|
||||
|
||||
virtual void collect_param_descrs(param_descrs & r) {
|
||||
insert_max_memory(r);
|
||||
insert_max_steps(r);
|
||||
r.insert("max_bits", CPK_UINT, "(default: 4) maximum bit-vector size of quantified bit-vectors to be eliminated.");
|
||||
}
|
||||
|
||||
virtual void operator()(goal_ref const & in,
|
||||
goal_ref_buffer & result,
|
||||
model_converter_ref & mc,
|
||||
proof_converter_ref & pc,
|
||||
expr_dependency_ref & core) {
|
||||
(*m_imp)(in, result, mc, pc, core);
|
||||
}
|
||||
|
||||
virtual void cleanup() {
|
||||
ast_manager & m = m_imp->m;
|
||||
imp * d = alloc(imp, m, m_params);
|
||||
#pragma omp critical (tactic_cancel)
|
||||
{
|
||||
std::swap(d, m_imp);
|
||||
}
|
||||
dealloc(d);
|
||||
}
|
||||
|
||||
virtual void set_cancel(bool f) {
|
||||
if (m_imp)
|
||||
m_imp->set_cancel(f);
|
||||
}
|
||||
};
|
||||
|
||||
tactic * mk_elim_small_bv_tactic(ast_manager & m, params_ref const & p) {
|
||||
return clean(alloc(elim_small_bv_tactic, m, p));
|
||||
}
|
||||
|
32
src/tactic/bv/elim_small_bv_tactic.h
Normal file
32
src/tactic/bv/elim_small_bv_tactic.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*++
|
||||
Copyright (c) 2015 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
elim_small_bv.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Tactic that eliminates small, quantified bit-vectors.
|
||||
|
||||
Author:
|
||||
|
||||
Christoph (cwinter) 2015-11-09
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef ELIM_SMALL_BV_H_
|
||||
#define ELIM_SMALL_BV_H_
|
||||
|
||||
#include"params.h"
|
||||
class ast_manager;
|
||||
class tactic;
|
||||
|
||||
tactic * mk_elim_small_bv_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||
|
||||
/*
|
||||
ADD_TACTIC("elim-small-bv", "eliminate small, quantified bit-vectors by expansion.", "mk_elim_small_bv_tactic(m, p)")
|
||||
*/
|
||||
|
||||
#endif
|
|
@ -177,7 +177,6 @@ expr_ref fpa2bv_model_converter::convert_bv2rm(expr * eval_v) const {
|
|||
rational bv_val(0);
|
||||
unsigned sz = 0;
|
||||
|
||||
|
||||
if (bu.is_numeral(eval_v, bv_val, sz)) {
|
||||
SASSERT(bv_val.is_uint64());
|
||||
switch (bv_val.get_uint64()) {
|
||||
|
@ -309,9 +308,9 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) {
|
|||
expr * bvval = to_app(val)->get_arg(0);
|
||||
expr_ref fv(m);
|
||||
fv = convert_bv2rm(bv_mdl, var, bvval);
|
||||
TRACE("fpa2bv_mc", tout << var->get_name() << " == " << mk_ismt2_pp(fv, m) << std::endl;);
|
||||
TRACE("fpa2bv_mc", tout << var->get_name() << " == " << mk_ismt2_pp(fv, m) << ")" << std::endl;);
|
||||
float_mdl->register_decl(var, fv);
|
||||
seen.insert(to_app(val)->get_decl());
|
||||
seen.insert(to_app(bvval)->get_decl());
|
||||
}
|
||||
|
||||
for (obj_map<func_decl, func_decl*>::iterator it = m_uf2bvuf.begin();
|
||||
|
|
|
@ -25,6 +25,7 @@ Notes:
|
|||
#include"max_bv_sharing_tactic.h"
|
||||
#include"bv_size_reduction_tactic.h"
|
||||
#include"reduce_args_tactic.h"
|
||||
#include"qfbv_tactic.h"
|
||||
|
||||
tactic * mk_qfufbv_tactic(ast_manager & m, params_ref const & p) {
|
||||
params_ref main_p;
|
||||
|
@ -41,13 +42,11 @@ tactic * mk_qfufbv_tactic(ast_manager & m, params_ref const & p) {
|
|||
);
|
||||
|
||||
tactic * st = using_params(and_then(preamble_st,
|
||||
mk_smt_tactic()),
|
||||
cond(mk_is_qfbv_probe(),
|
||||
mk_qfbv_tactic(m),
|
||||
mk_smt_tactic())),
|
||||
main_p);
|
||||
|
||||
//cond(is_qfbv(),
|
||||
// and_then(mk_bit_blaster(m),
|
||||
// mk_sat_solver(m)),
|
||||
// mk_smt_solver())
|
||||
st->updt_params(p);
|
||||
return st;
|
||||
}
|
||||
|
|
|
@ -151,24 +151,3 @@ void escaped::display(std::ostream & out) const {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#ifdef ARRAYSIZE
|
||||
#undef ARRAYSIZE
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
void z3_bound_num_procs() {
|
||||
|
||||
#ifdef _Z3_COMMERCIAL
|
||||
#define Z3_COMMERCIAL_MAX_CORES 4
|
||||
#ifdef _WINDOWS
|
||||
DWORD_PTR numProcs = (1 << Z3_COMMERCIAL_MAX_CORES) - 1;
|
||||
SetProcessAffinityMask(GetCurrentProcess(), numProcs);
|
||||
#endif
|
||||
#else
|
||||
// Not bounded: Research evaluations are
|
||||
// not reasonable if run with artificial
|
||||
// or hidden throttles.
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -400,7 +400,6 @@ inline size_t megabytes_to_bytes(unsigned mb) {
|
|||
return r;
|
||||
}
|
||||
|
||||
void z3_bound_num_procs();
|
||||
|
||||
#endif /* UTIL_H_ */
|
||||
|
||||
|
|
Loading…
Reference in a new issue