mirror of
https://github.com/Z3Prover/z3
synced 2025-06-12 17:06:14 +00:00
fix box
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
ce18421a7a
51 changed files with 1663 additions and 1117 deletions
|
@ -1,5 +1,7 @@
|
||||||
#include<vector>
|
#include<vector>
|
||||||
#include"z3++.h"
|
#include"z3++.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace z3;
|
using namespace z3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,12 +90,12 @@ int main(int argc, const char **argv) {
|
||||||
|
|
||||||
/* Read an interpolation problem */
|
/* Read an interpolation problem */
|
||||||
|
|
||||||
int num;
|
unsigned num;
|
||||||
Z3_ast *constraints;
|
Z3_ast *constraints;
|
||||||
int *parents = 0;
|
unsigned *parents = 0;
|
||||||
const char *error;
|
const char *error;
|
||||||
bool ok;
|
bool ok;
|
||||||
int num_theory;
|
unsigned num_theory;
|
||||||
Z3_ast *theory;
|
Z3_ast *theory;
|
||||||
|
|
||||||
ok = Z3_read_interpolation_problem(ctx, &num, &constraints, tree_mode ? &parents : 0, filename, &error, &num_theory, &theory);
|
ok = Z3_read_interpolation_problem(ctx, &num, &constraints, tree_mode ? &parents : 0, filename, &error, &num_theory, &theory);
|
||||||
|
@ -144,7 +144,7 @@ int main(int argc, const char **argv) {
|
||||||
|
|
||||||
if(!incremental_mode){
|
if(!incremental_mode){
|
||||||
/* In non-incremental mode, we just pass the constraints. */
|
/* In non-incremental mode, we just pass the constraints. */
|
||||||
result = Z3_interpolate(ctx, num, constraints, (unsigned int *)parents, options, interpolants, &model, 0, false, num_theory, theory);
|
result = Z3_L_UNDEF; // FIXME: Z3_interpolate(ctx, num, constraints, parents, options, interpolants, &model, 0, false, num_theory, theory);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ int main(int argc, const char **argv) {
|
||||||
for(int i = 0; i < num; i++){
|
for(int i = 0; i < num; i++){
|
||||||
asserted[i] = constraints[i];
|
asserted[i] = constraints[i];
|
||||||
Z3_assert_cnstr(ctx,constraints[i]); // assert one constraint
|
Z3_assert_cnstr(ctx,constraints[i]); // assert one constraint
|
||||||
result = Z3_interpolate(ctx, num, &asserted[0], (unsigned int *)parents, options, interpolants, &model, 0, true, 0, 0);
|
result = Z3_L_UNDEF; // FIXME: Z3_interpolate(ctx, num, &asserted[0], parents, options, interpolants, &model, 0, true, 0, 0);
|
||||||
if(result == Z3_L_FALSE){
|
if(result == Z3_L_FALSE){
|
||||||
for(unsigned j = 0; j < num-1; j++)
|
for(unsigned j = 0; j < num-1; j++)
|
||||||
/* Since we want the interpolant formulas to survive a "pop", we
|
/* Since we want the interpolant formulas to survive a "pop", we
|
||||||
|
|
|
@ -74,7 +74,11 @@ def init_project_def():
|
||||||
add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa_tactics', 'aig_tactic', 'fp', 'qe','sls_tactic', 'subpaving_tactic'], 'tactic/portfolio')
|
add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa_tactics', 'aig_tactic', 'fp', 'qe','sls_tactic', 'subpaving_tactic'], 'tactic/portfolio')
|
||||||
add_lib('smtparser', ['portfolio'], 'parsers/smt')
|
add_lib('smtparser', ['portfolio'], 'parsers/smt')
|
||||||
add_lib('opt', ['smt', 'smtlogic_tactics', 'sls_tactic'], 'opt')
|
add_lib('opt', ['smt', 'smtlogic_tactics', 'sls_tactic'], 'opt')
|
||||||
API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h']
|
# add_dll('foci2', ['util'], 'interp/foci2stub',
|
||||||
|
# dll_name='foci2',
|
||||||
|
# export_files=['foci2stub.cpp'])
|
||||||
|
# add_lib('interp', ['solver','foci2'])
|
||||||
|
API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h', 'z3_interp.h']
|
||||||
add_lib('api', ['portfolio', 'user_plugin', 'smtparser', 'realclosure', 'interp', 'opt'],
|
add_lib('api', ['portfolio', 'user_plugin', 'smtparser', 'realclosure', 'interp', 'opt'],
|
||||||
includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files)
|
includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files)
|
||||||
add_exe('shell', ['api', 'sat', 'extra_cmds','opt'], exe_name='z3')
|
add_exe('shell', ['api', 'sat', 'extra_cmds','opt'], exe_name='z3')
|
||||||
|
|
|
@ -108,6 +108,7 @@ INOUT = 2
|
||||||
IN_ARRAY = 3
|
IN_ARRAY = 3
|
||||||
OUT_ARRAY = 4
|
OUT_ARRAY = 4
|
||||||
INOUT_ARRAY = 5
|
INOUT_ARRAY = 5
|
||||||
|
OUT_MANAGED_ARRAY = 6
|
||||||
|
|
||||||
# Primitive Types
|
# Primitive Types
|
||||||
VOID = 0
|
VOID = 0
|
||||||
|
@ -131,13 +132,13 @@ def is_obj(ty):
|
||||||
|
|
||||||
Type2Str = { VOID : 'void', VOID_PTR : 'void*', INT : 'int', UINT : 'unsigned', INT64 : '__int64', UINT64 : '__uint64', DOUBLE : 'double',
|
Type2Str = { VOID : 'void', VOID_PTR : 'void*', INT : 'int', UINT : 'unsigned', INT64 : '__int64', UINT64 : '__uint64', DOUBLE : 'double',
|
||||||
STRING : 'Z3_string', STRING_PTR : 'Z3_string_ptr', BOOL : 'Z3_bool', SYMBOL : 'Z3_symbol',
|
STRING : 'Z3_string', STRING_PTR : 'Z3_string_ptr', BOOL : 'Z3_bool', SYMBOL : 'Z3_symbol',
|
||||||
PRINT_MODE : 'Z3_ast_print_mode', ERROR_CODE : 'Z3_error_code',
|
PRINT_MODE : 'Z3_ast_print_mode', ERROR_CODE : 'Z3_error_code'
|
||||||
}
|
}
|
||||||
|
|
||||||
Type2PyStr = { VOID_PTR : 'ctypes.c_void_p', INT : 'ctypes.c_int', UINT : 'ctypes.c_uint', INT64 : 'ctypes.c_longlong',
|
Type2PyStr = { VOID_PTR : 'ctypes.c_void_p', INT : 'ctypes.c_int', UINT : 'ctypes.c_uint', INT64 : 'ctypes.c_longlong',
|
||||||
UINT64 : 'ctypes.c_ulonglong', DOUBLE : 'ctypes.c_double',
|
UINT64 : 'ctypes.c_ulonglong', DOUBLE : 'ctypes.c_double',
|
||||||
STRING : 'ctypes.c_char_p', STRING_PTR : 'ctypes.POINTER(ctypes.c_char_p)', BOOL : 'ctypes.c_bool', SYMBOL : 'Symbol',
|
STRING : 'ctypes.c_char_p', STRING_PTR : 'ctypes.POINTER(ctypes.c_char_p)', BOOL : 'ctypes.c_bool', SYMBOL : 'Symbol',
|
||||||
PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint',
|
PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Mapping to .NET types
|
# Mapping to .NET types
|
||||||
|
@ -224,6 +225,10 @@ def _out_array2(cap, sz, ty):
|
||||||
def _inout_array(sz, ty):
|
def _inout_array(sz, ty):
|
||||||
return (INOUT_ARRAY, ty, sz, sz);
|
return (INOUT_ARRAY, ty, sz, sz);
|
||||||
|
|
||||||
|
def _out_managed_array(sz,ty):
|
||||||
|
return (OUT_MANAGED_ARRAY, ty, 0, sz)
|
||||||
|
|
||||||
|
|
||||||
def param_kind(p):
|
def param_kind(p):
|
||||||
return p[0]
|
return p[0]
|
||||||
|
|
||||||
|
@ -254,12 +259,12 @@ def param2dotnet(p):
|
||||||
return "out IntPtr"
|
return "out IntPtr"
|
||||||
else:
|
else:
|
||||||
return "[In, Out] ref %s" % type2dotnet(param_type(p))
|
return "[In, Out] ref %s" % type2dotnet(param_type(p))
|
||||||
if k == IN_ARRAY:
|
elif k == IN_ARRAY:
|
||||||
return "[In] %s[]" % type2dotnet(param_type(p))
|
return "[In] %s[]" % type2dotnet(param_type(p))
|
||||||
if k == INOUT_ARRAY:
|
elif k == INOUT_ARRAY:
|
||||||
return "[In, Out] %s[]" % type2dotnet(param_type(p))
|
return "[In, Out] %s[]" % type2dotnet(param_type(p))
|
||||||
if k == OUT_ARRAY:
|
elif k == OUT_ARRAY or k == OUT_MANAGED_ARRAY:
|
||||||
return "[Out] %s[]" % type2dotnet(param_type(p))
|
return "[Out] out %s[]" % type2dotnet(param_type(p))
|
||||||
else:
|
else:
|
||||||
return type2dotnet(param_type(p))
|
return type2dotnet(param_type(p))
|
||||||
|
|
||||||
|
@ -268,7 +273,7 @@ def param2java(p):
|
||||||
if k == OUT:
|
if k == OUT:
|
||||||
if param_type(p) == INT or param_type(p) == UINT:
|
if param_type(p) == INT or param_type(p) == UINT:
|
||||||
return "IntPtr"
|
return "IntPtr"
|
||||||
elif param_type(p) == INT64 or param_type(p) == UINT64 or param_type(p) >= FIRST_OBJ_ID:
|
elif param_type(p) == INT64 or param_type(p) == UINT64 or param_type(p) == VOID_PTR or param_type(p) >= FIRST_OBJ_ID:
|
||||||
return "LongPtr"
|
return "LongPtr"
|
||||||
elif param_type(p) == STRING:
|
elif param_type(p) == STRING:
|
||||||
return "StringPtr"
|
return "StringPtr"
|
||||||
|
@ -276,8 +281,13 @@ def param2java(p):
|
||||||
print("ERROR: unreachable code")
|
print("ERROR: unreachable code")
|
||||||
assert(False)
|
assert(False)
|
||||||
exit(1)
|
exit(1)
|
||||||
if k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY:
|
elif k == IN_ARRAY or k == INOUT_ARRAY or k == OUT_ARRAY:
|
||||||
return "%s[]" % type2java(param_type(p))
|
return "%s[]" % type2java(param_type(p))
|
||||||
|
elif k == OUT_MANAGED_ARRAY:
|
||||||
|
if param_type(p) == UINT:
|
||||||
|
return "UIntArrayPtr"
|
||||||
|
else:
|
||||||
|
return "ObjArrayPtr"
|
||||||
else:
|
else:
|
||||||
return type2java(param_type(p))
|
return type2java(param_type(p))
|
||||||
|
|
||||||
|
@ -466,6 +476,8 @@ def mk_dotnet_wrappers():
|
||||||
dotnet.write('out ');
|
dotnet.write('out ');
|
||||||
else:
|
else:
|
||||||
dotnet.write('ref ')
|
dotnet.write('ref ')
|
||||||
|
elif param_kind(param) == OUT_ARRAY or param_kind(param) == OUT_MANAGED_ARRAY:
|
||||||
|
dotnet.write('out ');
|
||||||
dotnet.write('a%d' % i)
|
dotnet.write('a%d' % i)
|
||||||
i = i + 1
|
i = i + 1
|
||||||
dotnet.write(');\n');
|
dotnet.write(');\n');
|
||||||
|
@ -522,6 +534,8 @@ def mk_java():
|
||||||
java_native.write(' public static class IntPtr { public int value; }\n')
|
java_native.write(' public static class IntPtr { public int value; }\n')
|
||||||
java_native.write(' public static class LongPtr { public long value; }\n')
|
java_native.write(' public static class LongPtr { public long value; }\n')
|
||||||
java_native.write(' public static class StringPtr { public String value; }\n')
|
java_native.write(' public static class StringPtr { public String value; }\n')
|
||||||
|
java_native.write(' public static class ObjArrayPtr { public long[] value; }\n')
|
||||||
|
java_native.write(' public static class UIntArrayPtr { public int[] value; }\n')
|
||||||
java_native.write(' public static native void setInternalErrorHandler(long ctx);\n\n')
|
java_native.write(' public static native void setInternalErrorHandler(long ctx);\n\n')
|
||||||
if IS_WINDOWS or os.uname()[0]=="CYGWIN":
|
if IS_WINDOWS or os.uname()[0]=="CYGWIN":
|
||||||
java_native.write(' static { System.loadLibrary("%s"); }\n' % get_component('java').dll_name)
|
java_native.write(' static { System.loadLibrary("%s"); }\n' % get_component('java').dll_name)
|
||||||
|
@ -679,6 +693,8 @@ def mk_java():
|
||||||
java_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i))
|
java_wrapper.write(' GETLONGAREGION(%s, a%s, 0, a%s, _a%s);\n' % (type2str(param_type(param)), i, param_array_capacity_pos(param), i))
|
||||||
elif k == IN and param_type(param) == STRING:
|
elif k == IN and param_type(param) == STRING:
|
||||||
java_wrapper.write(' Z3_string _a%s = (Z3_string) jenv->GetStringUTFChars(a%s, NULL);\n' % (i, i))
|
java_wrapper.write(' Z3_string _a%s = (Z3_string) jenv->GetStringUTFChars(a%s, NULL);\n' % (i, i))
|
||||||
|
elif k == OUT_MANAGED_ARRAY:
|
||||||
|
java_wrapper.write(' %s * _a%s = 0;\n' % (type2str(param_type(param)), i))
|
||||||
i = i + 1
|
i = i + 1
|
||||||
# invoke procedure
|
# invoke procedure
|
||||||
java_wrapper.write(' ')
|
java_wrapper.write(' ')
|
||||||
|
@ -697,6 +713,8 @@ def mk_java():
|
||||||
java_wrapper.write('&_a%s' % i)
|
java_wrapper.write('&_a%s' % i)
|
||||||
elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY:
|
elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY:
|
||||||
java_wrapper.write('_a%s' % i)
|
java_wrapper.write('_a%s' % i)
|
||||||
|
elif k == OUT_MANAGED_ARRAY:
|
||||||
|
java_wrapper.write('&_a%s' % i)
|
||||||
elif k == IN and param_type(param) == STRING:
|
elif k == IN and param_type(param) == STRING:
|
||||||
java_wrapper.write('_a%s' % i)
|
java_wrapper.write('_a%s' % i)
|
||||||
else:
|
else:
|
||||||
|
@ -732,6 +750,8 @@ def mk_java():
|
||||||
java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n')
|
java_wrapper.write(' jfieldID fid = jenv->GetFieldID(mc, "value", "J");\n')
|
||||||
java_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i))
|
java_wrapper.write(' jenv->SetLongField(a%s, fid, (jlong) _a%s);\n' % (i, i))
|
||||||
java_wrapper.write(' }\n')
|
java_wrapper.write(' }\n')
|
||||||
|
elif k == OUT_MANAGED_ARRAY:
|
||||||
|
java_wrapper.write(' *(jlong**)a%s = (jlong*)_a%s;\n' % (i, i))
|
||||||
i = i + 1
|
i = i + 1
|
||||||
# return
|
# return
|
||||||
if result == STRING:
|
if result == STRING:
|
||||||
|
@ -932,6 +952,9 @@ def def_API(name, result, params):
|
||||||
elif ty == INT64:
|
elif ty == INT64:
|
||||||
log_c.write(" I(0);\n")
|
log_c.write(" I(0);\n")
|
||||||
exe_c.write("in.get_int64_addr(%s)" % i)
|
exe_c.write("in.get_int64_addr(%s)" % i)
|
||||||
|
elif ty == VOID_PTR:
|
||||||
|
log_c.write(" P(0);\n")
|
||||||
|
exe_c.write("in.get_obj_addr(%s)" % i)
|
||||||
else:
|
else:
|
||||||
error("unsupported parameter for %s, %s" % (name, p))
|
error("unsupported parameter for %s, %s" % (name, p))
|
||||||
elif kind == IN_ARRAY or kind == INOUT_ARRAY:
|
elif kind == IN_ARRAY or kind == INOUT_ARRAY:
|
||||||
|
@ -958,22 +981,43 @@ def def_API(name, result, params):
|
||||||
log_c.write(" Au(a%s);\n" % sz)
|
log_c.write(" Au(a%s);\n" % sz)
|
||||||
exe_c.write("in.get_int_array(%s)" % i)
|
exe_c.write("in.get_int_array(%s)" % i)
|
||||||
else:
|
else:
|
||||||
error ("unsupported parameter for %s, %s" % (name, p))
|
error ("unsupported parameter for %s, %s" % (ty, name, p))
|
||||||
elif kind == OUT_ARRAY:
|
elif kind == OUT_ARRAY:
|
||||||
sz = param_array_capacity_pos(p)
|
sz = param_array_capacity_pos(p)
|
||||||
log_c.write(" for (unsigned i = 0; i < a%s; i++) { " % sz)
|
sz_p = params[sz]
|
||||||
|
sz_p_k = param_kind(sz_p)
|
||||||
|
tstr = type2str(ty)
|
||||||
|
if sz_p_k == OUT or sz_p_k == INOUT:
|
||||||
|
sz_e = ("(*a%s)" % sz)
|
||||||
|
else:
|
||||||
|
sz_e = ("a%s" % sz)
|
||||||
|
log_c.write(" for (unsigned i = 0; i < %s; i++) { " % sz_e)
|
||||||
if is_obj(ty):
|
if is_obj(ty):
|
||||||
log_c.write("P(0);")
|
log_c.write("P(0);")
|
||||||
log_c.write(" }\n")
|
log_c.write(" }\n")
|
||||||
log_c.write(" Ap(a%s);\n" % sz)
|
log_c.write(" Ap(%s);\n" % sz_e)
|
||||||
exe_c.write("reinterpret_cast<%s*>(in.get_obj_array(%s))" % (type2str(ty), i))
|
exe_c.write("reinterpret_cast<%s*>(in.get_obj_array(%s))" % (tstr, i))
|
||||||
elif ty == UINT:
|
elif ty == UINT:
|
||||||
log_c.write("U(0);")
|
log_c.write("U(0);")
|
||||||
log_c.write(" }\n")
|
log_c.write(" }\n")
|
||||||
log_c.write(" Au(a%s);\n" % sz)
|
log_c.write(" Au(%s);\n" % sz_e)
|
||||||
exe_c.write("in.get_uint_array(%s)" % i)
|
exe_c.write("in.get_uint_array(%s)" % i)
|
||||||
else:
|
else:
|
||||||
error ("unsupported parameter for %s, %s" % (name, p))
|
error ("unsupported parameter for %s, %s" % (name, p))
|
||||||
|
elif kind == OUT_MANAGED_ARRAY:
|
||||||
|
sz = param_array_size_pos(p)
|
||||||
|
sz_p = params[sz]
|
||||||
|
sz_p_k = param_kind(sz_p)
|
||||||
|
tstr = type2str(ty)
|
||||||
|
if sz_p_k == OUT or sz_p_k == INOUT:
|
||||||
|
sz_e = ("(*a%s)" % sz)
|
||||||
|
else:
|
||||||
|
sz_e = ("a%s" % sz)
|
||||||
|
log_c.write(" for (unsigned i = 0; i < %s; i++) { " % sz_e)
|
||||||
|
log_c.write("P(0);")
|
||||||
|
log_c.write(" }\n")
|
||||||
|
log_c.write(" Ap(%s);\n" % sz_e)
|
||||||
|
exe_c.write("reinterpret_cast<%s**>(in.get_obj_array(%s))" % (tstr, i))
|
||||||
else:
|
else:
|
||||||
error ("unsupported parameter for %s, %s" % (name, p))
|
error ("unsupported parameter for %s, %s" % (name, p))
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
|
|
@ -209,7 +209,7 @@ extern "C" {
|
||||||
MK_BINARY(Z3_mk_xor, mk_c(c)->get_basic_fid(), OP_XOR, SKIP);
|
MK_BINARY(Z3_mk_xor, mk_c(c)->get_basic_fid(), OP_XOR, SKIP);
|
||||||
MK_NARY(Z3_mk_and, mk_c(c)->get_basic_fid(), OP_AND, SKIP);
|
MK_NARY(Z3_mk_and, mk_c(c)->get_basic_fid(), OP_AND, SKIP);
|
||||||
MK_NARY(Z3_mk_or, mk_c(c)->get_basic_fid(), OP_OR, SKIP);
|
MK_NARY(Z3_mk_or, mk_c(c)->get_basic_fid(), OP_OR, SKIP);
|
||||||
MK_UNARY(Z3_mk_interp, mk_c(c)->get_basic_fid(), OP_INTERP, SKIP);
|
MK_UNARY(Z3_mk_interpolant, mk_c(c)->get_basic_fid(), OP_INTERP, SKIP);
|
||||||
|
|
||||||
Z3_ast mk_ite_core(Z3_context c, Z3_ast t1, Z3_ast t2, Z3_ast t3) {
|
Z3_ast mk_ite_core(Z3_context c, Z3_ast t1, Z3_ast t2, Z3_ast t3) {
|
||||||
expr * result = mk_c(c)->m().mk_ite(to_expr(t1), to_expr(t2), to_expr(t3));
|
expr * result = mk_c(c)->m().mk_ite(to_expr(t1), to_expr(t2), to_expr(t3));
|
||||||
|
|
|
@ -78,8 +78,8 @@ extern "C" {
|
||||||
Z3_params options,
|
Z3_params options,
|
||||||
Z3_ast *interps,
|
Z3_ast *interps,
|
||||||
int num_theory,
|
int num_theory,
|
||||||
Z3_ast *theory
|
Z3_ast *theory)
|
||||||
){
|
{
|
||||||
|
|
||||||
if (num > 1){ // if we have interpolants to compute
|
if (num > 1){ // if we have interpolants to compute
|
||||||
|
|
||||||
|
@ -123,98 +123,15 @@ extern "C" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Z3_lbool Z3_interpolate(Z3_context ctx,
|
|
||||||
int num,
|
|
||||||
Z3_ast *cnsts,
|
|
||||||
unsigned *parents,
|
|
||||||
Z3_params options,
|
|
||||||
Z3_ast *interps,
|
|
||||||
Z3_model *model,
|
|
||||||
Z3_literals *labels,
|
|
||||||
int incremental,
|
|
||||||
int num_theory,
|
|
||||||
Z3_ast *theory
|
|
||||||
){
|
|
||||||
|
|
||||||
|
|
||||||
profiling::timer_start("Solve");
|
|
||||||
|
|
||||||
if(!incremental){
|
|
||||||
|
|
||||||
profiling::timer_start("Z3 assert");
|
|
||||||
|
|
||||||
Z3_push(ctx); // so we can rewind later
|
|
||||||
|
|
||||||
for(int i = 0; i < num; i++)
|
|
||||||
Z3_assert_cnstr(ctx,cnsts[i]); // assert all the constraints
|
|
||||||
|
|
||||||
if(theory){
|
|
||||||
for(int i = 0; i < num_theory; i++)
|
|
||||||
Z3_assert_cnstr(ctx,theory[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
profiling::timer_stop("Z3 assert");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Get a proof of unsat
|
|
||||||
|
|
||||||
Z3_ast proof;
|
|
||||||
Z3_lbool result;
|
|
||||||
|
|
||||||
profiling::timer_start("Z3 solving");
|
|
||||||
result = Z3_check_assumptions(ctx, 0, 0, model, &proof, 0, 0);
|
|
||||||
profiling::timer_stop("Z3 solving");
|
|
||||||
|
|
||||||
switch (result) {
|
|
||||||
case Z3_L_FALSE:
|
|
||||||
|
|
||||||
Z3_interpolate_proof(ctx,
|
|
||||||
proof,
|
|
||||||
num,
|
|
||||||
cnsts,
|
|
||||||
parents,
|
|
||||||
options,
|
|
||||||
interps,
|
|
||||||
num_theory,
|
|
||||||
theory);
|
|
||||||
|
|
||||||
if(!incremental)
|
|
||||||
for(int i = 0; i < num-1; i++)
|
|
||||||
Z3_persist_ast(ctx,interps[i],1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Z3_L_UNDEF:
|
|
||||||
if(labels)
|
|
||||||
*labels = Z3_get_relevant_labels(ctx);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Z3_L_TRUE:
|
|
||||||
if(labels)
|
|
||||||
*labels = Z3_get_relevant_labels(ctx);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
profiling::timer_start("Z3 pop");
|
|
||||||
if(!incremental)
|
|
||||||
Z3_pop(ctx,1);
|
|
||||||
profiling::timer_stop("Z3 pop");
|
|
||||||
|
|
||||||
profiling::timer_stop("Solve");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::ostringstream itp_err;
|
static std::ostringstream itp_err;
|
||||||
|
|
||||||
int Z3_check_interpolant(Z3_context ctx,
|
int Z3_check_interpolant(Z3_context ctx,
|
||||||
int num,
|
unsigned num,
|
||||||
Z3_ast *cnsts,
|
Z3_ast *cnsts,
|
||||||
int *parents,
|
unsigned *parents,
|
||||||
Z3_ast *itp,
|
Z3_ast *itp,
|
||||||
const char **error,
|
Z3_string *error,
|
||||||
int num_theory,
|
unsigned num_theory,
|
||||||
Z3_ast *theory){
|
Z3_ast *theory){
|
||||||
|
|
||||||
ast_manager &_m = mk_c(ctx)->m();
|
ast_manager &_m = mk_c(ctx)->m();
|
||||||
|
@ -226,13 +143,13 @@ extern "C" {
|
||||||
scoped_ptr<solver> sp((*(sf))(_m, p, false, true, false, symbol("AUFLIA")));
|
scoped_ptr<solver> sp((*(sf))(_m, p, false, true, false, symbol("AUFLIA")));
|
||||||
|
|
||||||
ptr_vector<ast> cnsts_vec(num); // get constraints in a vector
|
ptr_vector<ast> cnsts_vec(num); // get constraints in a vector
|
||||||
for(int i = 0; i < num; i++){
|
for (unsigned i = 0; i < num; i++){
|
||||||
ast *a = to_ast(cnsts[i]);
|
ast *a = to_ast(cnsts[i]);
|
||||||
cnsts_vec[i] = a;
|
cnsts_vec[i] = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr_vector<ast> itp_vec(num); // get interpolants in a vector
|
ptr_vector<ast> itp_vec(num); // get interpolants in a vector
|
||||||
for(int i = 0; i < num-1; i++){
|
for (unsigned i = 0; i < num - 1; i++){
|
||||||
ast *a = to_ast(itp[i]);
|
ast *a = to_ast(itp[i]);
|
||||||
itp_vec[i] = a;
|
itp_vec[i] = a;
|
||||||
}
|
}
|
||||||
|
@ -240,14 +157,14 @@ extern "C" {
|
||||||
::vector<int> parents_vec; // get parents in a vector
|
::vector<int> parents_vec; // get parents in a vector
|
||||||
if (parents){
|
if (parents){
|
||||||
parents_vec.resize(num);
|
parents_vec.resize(num);
|
||||||
for(int i = 0; i < num; i++)
|
for (unsigned i = 0; i < num; i++)
|
||||||
parents_vec[i] = parents[i];
|
parents_vec[i] = parents[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr_vector<ast> theory_vec; // get background theory in a vector
|
ptr_vector<ast> theory_vec; // get background theory in a vector
|
||||||
if (theory){
|
if (theory){
|
||||||
theory_vec.resize(num_theory);
|
theory_vec.resize(num_theory);
|
||||||
for(int i = 0; i < num_theory; i++)
|
for (unsigned i = 0; i < num_theory; i++)
|
||||||
theory_vec[i] = to_ast(theory[i]);
|
theory_vec[i] = to_ast(theory[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,7 +358,7 @@ extern "C" {
|
||||||
f.close();
|
f.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Z3_write_interpolation_problem(Z3_context ctx, int num, Z3_ast *cnsts, int *parents, const char *filename, int num_theory, Z3_ast *theory){
|
void Z3_write_interpolation_problem(Z3_context ctx, int num, Z3_ast *cnsts, unsigned *parents, const char *filename, int num_theory, Z3_ast *theory){
|
||||||
if(!parents){
|
if(!parents){
|
||||||
iZ3_write_seq(ctx,num,cnsts,filename,num_theory,theory);
|
iZ3_write_seq(ctx,num,cnsts,filename,num_theory,theory);
|
||||||
return;
|
return;
|
||||||
|
@ -472,13 +389,13 @@ extern "C" {
|
||||||
return (c.size() > 1) ? Z3_mk_and(ctx, c.size(), &c[0]) : c[0];
|
return (c.size() > 1) ? Z3_mk_and(ctx, c.size(), &c[0]) : c[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Z3_ast parents_vector_to_tree(Z3_context ctx, int num, Z3_ast *cnsts, int *parents){
|
static Z3_ast parents_vector_to_tree(Z3_context ctx, int num, Z3_ast *cnsts, unsigned *parents){
|
||||||
Z3_ast res;
|
Z3_ast res;
|
||||||
if (!parents){
|
if (!parents){
|
||||||
res = Z3_mk_interp(ctx,cnsts[0]);
|
res = Z3_mk_interpolant(ctx, cnsts[0]);
|
||||||
for (int i = 1; i < num - 1; i++){
|
for (int i = 1; i < num - 1; i++){
|
||||||
Z3_ast bar[2] = { res, cnsts[i] };
|
Z3_ast bar[2] = { res, cnsts[i] };
|
||||||
res = Z3_mk_interp(ctx,Z3_mk_and(ctx,2,bar));
|
res = Z3_mk_interpolant(ctx, Z3_mk_and(ctx, 2, bar));
|
||||||
}
|
}
|
||||||
if (num > 1){
|
if (num > 1){
|
||||||
Z3_ast bar[2] = { res, cnsts[num - 1] };
|
Z3_ast bar[2] = { res, cnsts[num - 1] };
|
||||||
|
@ -490,7 +407,7 @@ extern "C" {
|
||||||
for (int i = 0; i < num - 1; i++){
|
for (int i = 0; i < num - 1; i++){
|
||||||
svector<Z3_ast> &c = chs[i];
|
svector<Z3_ast> &c = chs[i];
|
||||||
c.push_back(cnsts[i]);
|
c.push_back(cnsts[i]);
|
||||||
Z3_ast foo = Z3_mk_interp(ctx,and_vec(ctx,c));
|
Z3_ast foo = Z3_mk_interpolant(ctx, and_vec(ctx, c));
|
||||||
chs[parents[i]].push_back(foo);
|
chs[parents[i]].push_back(foo);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -503,19 +420,25 @@ extern "C" {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Z3_write_interpolation_problem(Z3_context ctx, int num, Z3_ast *cnsts, int *parents, const char *filename, int num_theory, Z3_ast *theory){
|
void Z3_write_interpolation_problem(Z3_context ctx, unsigned num, Z3_ast *cnsts, unsigned *parents, const char *filename, unsigned num_theory, Z3_ast *theory){
|
||||||
std::ofstream f(filename);
|
std::ofstream f(filename);
|
||||||
if (num > 0){
|
if (num > 0){
|
||||||
|
#if 0
|
||||||
|
// Suggested shorthand:
|
||||||
|
ptr_vector<expr> cnsts_vec;
|
||||||
|
cnsts_vec.append(num, to_exprs(cnsts));
|
||||||
|
cnsts_vec.append(num_theory, to_exprs(theory));
|
||||||
|
#endif
|
||||||
ptr_vector<expr> cnsts_vec(num); // get constraints in a vector
|
ptr_vector<expr> cnsts_vec(num); // get constraints in a vector
|
||||||
for(int i = 0; i < num; i++){
|
for (unsigned i = 0; i < num; i++){
|
||||||
expr *a = to_expr(cnsts[i]);
|
expr *a = to_expr(cnsts[i]);
|
||||||
cnsts_vec[i] = a;
|
cnsts_vec[i] = a;
|
||||||
}
|
}
|
||||||
Z3_ast tree = parents_vector_to_tree(ctx,num,cnsts,parents);
|
for (unsigned i = 0; i < num_theory; i++){
|
||||||
for(int i = 0; i < num_theory; i++){
|
|
||||||
expr *a = to_expr(theory[i]);
|
expr *a = to_expr(theory[i]);
|
||||||
cnsts_vec.push_back(a);
|
cnsts_vec.push_back(a);
|
||||||
}
|
}
|
||||||
|
Z3_ast tree = parents_vector_to_tree(ctx, num, cnsts, parents);
|
||||||
iz3pp(mk_c(ctx)->m(), cnsts_vec, to_expr(tree), f);
|
iz3pp(mk_c(ctx)->m(), cnsts_vec, to_expr(tree), f);
|
||||||
Z3_dec_ref(ctx, tree);
|
Z3_dec_ref(ctx, tree);
|
||||||
}
|
}
|
||||||
|
@ -554,7 +477,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static std::vector<Z3_ast> read_cnsts;
|
static std::vector<Z3_ast> read_cnsts;
|
||||||
static std::vector<int> read_parents;
|
static std::vector<unsigned> read_parents;
|
||||||
static std::ostringstream read_error;
|
static std::ostringstream read_error;
|
||||||
static std::string read_msg;
|
static std::string read_msg;
|
||||||
static std::vector<Z3_ast> read_theory;
|
static std::vector<Z3_ast> read_theory;
|
||||||
|
@ -597,7 +520,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Z3_read_interpolation_problem(Z3_context ctx, int *_num, Z3_ast **cnsts, int **parents, const char *filename, const char **error, int *ret_num_theory, Z3_ast **theory ){
|
int Z3_read_interpolation_problem(Z3_context ctx, unsigned *_num, Z3_ast *cnsts[], unsigned *parents[], const char *filename, Z3_string_ptr error, unsigned *ret_num_theory, Z3_ast *theory[]){
|
||||||
|
|
||||||
hash_map<std::string, std::string> file_params;
|
hash_map<std::string, std::string> file_params;
|
||||||
get_file_params(filename, file_params);
|
get_file_params(filename, file_params);
|
||||||
|
@ -711,3 +634,87 @@ extern "C" {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/** Constant reprepresenting a root of a formula tree for tree interpolation */
|
||||||
|
#define IZ3_ROOT SHRT_MAX
|
||||||
|
|
||||||
|
/** This function uses Z3 to determine satisfiability of a set of
|
||||||
|
constraints. If UNSAT, an interpolant is returned, based on the
|
||||||
|
refutation generated by Z3. If SAT, a model is returned.
|
||||||
|
|
||||||
|
If "parents" is non-null, computes a tree interpolant. The tree is
|
||||||
|
defined by the array "parents". This array maps each formula in
|
||||||
|
the tree to its parent, where formulas are indicated by their
|
||||||
|
integer index in "cnsts". The parent of formula n must have index
|
||||||
|
greater than n. The last formula is the root of the tree. Its
|
||||||
|
parent entry should be the constant IZ3_ROOT.
|
||||||
|
|
||||||
|
If "parents" is null, computes a sequence interpolant.
|
||||||
|
|
||||||
|
\param ctx The Z3 context. Must be generated by iz3_mk_context
|
||||||
|
\param num The number of constraints in the sequence
|
||||||
|
\param cnsts Array of constraints (AST's in context ctx)
|
||||||
|
\param parents The parents vector defining the tree structure
|
||||||
|
\param options Interpolation options (may be NULL)
|
||||||
|
\param interps Array to return interpolants (size at least num-1, may be NULL)
|
||||||
|
\param model Returns a Z3 model if constraints SAT (may be NULL)
|
||||||
|
\param labels Returns relevant labels if SAT (may be NULL)
|
||||||
|
\param incremental
|
||||||
|
|
||||||
|
VERY IMPORTANT: All the Z3 formulas in cnsts must be in Z3
|
||||||
|
context ctx. The model and interpolants returned are also
|
||||||
|
in this context.
|
||||||
|
|
||||||
|
The return code is as in Z3_check_assumptions, that is,
|
||||||
|
|
||||||
|
Z3_L_FALSE = constraints UNSAT (interpolants returned)
|
||||||
|
Z3_L_TRUE = constraints SAT (model returned)
|
||||||
|
Z3_L_UNDEF = Z3 produced no result, or interpolation not possible
|
||||||
|
|
||||||
|
Currently, this function supports integer and boolean variables,
|
||||||
|
as well as arrays over these types, with linear arithmetic,
|
||||||
|
uninterpreted functions and quantifiers over integers (that is
|
||||||
|
AUFLIA). Interpolants are produced in AULIA. However, some
|
||||||
|
uses of array operations may cause quantifiers to appear in the
|
||||||
|
interpolants even when there are no quantifiers in the input formulas.
|
||||||
|
Although quantifiers may appear in the input formulas, Z3 may give up in
|
||||||
|
this case, returning Z3_L_UNDEF.
|
||||||
|
|
||||||
|
If "incremental" is true, cnsts must contain exactly the set of
|
||||||
|
formulas that are currently asserted in the context. If false,
|
||||||
|
there must be no formulas currently asserted in the context.
|
||||||
|
Setting "incremental" to true makes it posisble to incrementally
|
||||||
|
add and remove constraints from the context until the context
|
||||||
|
becomes UNSAT, at which point an interpolant is computed. Caution
|
||||||
|
must be used, however. Before popping the context, if you wish to
|
||||||
|
keep the interolant formulas, you *must* preserve them by using
|
||||||
|
Z3_persist_ast. Also, if you want to simplify the interpolant
|
||||||
|
formulas using Z3_simplify, you must first pop all of the
|
||||||
|
assertions in the context (or use a different context). Otherwise,
|
||||||
|
the formulas will be simplified *relative* to these constraints,
|
||||||
|
which is almost certainly not what you want.
|
||||||
|
|
||||||
|
|
||||||
|
Current limitations on tree interpolants. In a tree interpolation
|
||||||
|
problem, each constant (0-ary function symbol) must occur only
|
||||||
|
along one path from root to leaf. Function symbols (of arity > 0)
|
||||||
|
are considered to have global scope (i.e., may appear in any
|
||||||
|
interpolant formula).
|
||||||
|
|
||||||
|
def_API('Z3_interpolate', BOOL, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in(PARAMS), _out_array(1, AST), _out(MODEL), _out(LITERALS), _in(UINT), _in(UINT), _in_array(9, AST)))
|
||||||
|
*/
|
||||||
|
|
||||||
|
Z3_lbool Z3_API Z3_interpolate(__in Z3_context ctx,
|
||||||
|
__in unsigned num,
|
||||||
|
__in_ecount(num) Z3_ast *cnsts,
|
||||||
|
__in_ecount(num) unsigned *parents,
|
||||||
|
__in Z3_params options,
|
||||||
|
__out_ecount(num - 1) Z3_ast *interps,
|
||||||
|
__out Z3_model *model,
|
||||||
|
__out Z3_literals *labels,
|
||||||
|
__in unsigned incremental,
|
||||||
|
__in unsigned num_theory,
|
||||||
|
__in_ecount(num_theory) Z3_ast *theory);
|
||||||
|
#endif
|
|
@ -40,6 +40,11 @@ extern "C" {
|
||||||
params_ref p = s->m_params;
|
params_ref p = s->m_params;
|
||||||
mk_c(c)->params().get_solver_params(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled);
|
mk_c(c)->params().get_solver_params(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled);
|
||||||
s->m_solver = (*(s->m_solver_factory))(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled, s->m_logic);
|
s->m_solver = (*(s->m_solver_factory))(mk_c(c)->m(), p, proofs_enabled, models_enabled, unsat_core_enabled, s->m_logic);
|
||||||
|
|
||||||
|
param_descrs r;
|
||||||
|
s->m_solver->collect_param_descrs(r);
|
||||||
|
context_params::collect_solver_param_descrs(r);
|
||||||
|
p.validate(r);
|
||||||
s->m_solver->updt_params(p);
|
s->m_solver->updt_params(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +107,7 @@ extern "C" {
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
init_solver(c, s);
|
init_solver(c, s);
|
||||||
to_solver_ref(s)->collect_param_descrs(descrs);
|
to_solver_ref(s)->collect_param_descrs(descrs);
|
||||||
|
context_params::collect_solver_param_descrs(descrs);
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
to_solver(s)->m_solver = 0;
|
to_solver(s)->m_solver = 0;
|
||||||
descrs.display(buffer);
|
descrs.display(buffer);
|
||||||
|
@ -119,6 +125,7 @@ extern "C" {
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
init_solver(c, s);
|
init_solver(c, s);
|
||||||
to_solver_ref(s)->collect_param_descrs(d->m_descrs);
|
to_solver_ref(s)->collect_param_descrs(d->m_descrs);
|
||||||
|
context_params::collect_solver_param_descrs(d->m_descrs);
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
to_solver(s)->m_solver = 0;
|
to_solver(s)->m_solver = 0;
|
||||||
Z3_param_descrs r = of_param_descrs(d);
|
Z3_param_descrs r = of_param_descrs(d);
|
||||||
|
@ -130,11 +137,16 @@ extern "C" {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_solver_set_params(c, s, p);
|
LOG_Z3_solver_set_params(c, s, p);
|
||||||
RESET_ERROR_CODE();
|
RESET_ERROR_CODE();
|
||||||
|
|
||||||
if (to_solver(s)->m_solver) {
|
if (to_solver(s)->m_solver) {
|
||||||
bool old_model = to_solver(s)->m_params.get_bool("model", true);
|
bool old_model = to_solver(s)->m_params.get_bool("model", true);
|
||||||
bool new_model = to_param_ref(p).get_bool("model", true);
|
bool new_model = to_param_ref(p).get_bool("model", true);
|
||||||
if (old_model != new_model)
|
if (old_model != new_model)
|
||||||
to_solver_ref(s)->set_produce_models(new_model);
|
to_solver_ref(s)->set_produce_models(new_model);
|
||||||
|
param_descrs r;
|
||||||
|
to_solver_ref(s)->collect_param_descrs(r);
|
||||||
|
context_params::collect_solver_param_descrs(r);
|
||||||
|
to_param_ref(p).validate(r);
|
||||||
to_solver_ref(s)->updt_params(to_param_ref(p));
|
to_solver_ref(s)->updt_params(to_param_ref(p));
|
||||||
}
|
}
|
||||||
to_solver(s)->m_params = to_param_ref(p);
|
to_solver(s)->m_params = to_param_ref(p);
|
||||||
|
|
|
@ -450,6 +450,9 @@ extern "C" {
|
||||||
Z3_TRY;
|
Z3_TRY;
|
||||||
LOG_Z3_tactic_apply_ex(c, t, g, p);
|
LOG_Z3_tactic_apply_ex(c, t, g, p);
|
||||||
RESET_ERROR_CODE();
|
RESET_ERROR_CODE();
|
||||||
|
param_descrs pd;
|
||||||
|
to_tactic_ref(t)->collect_param_descrs(pd);
|
||||||
|
to_param_ref(p).validate(pd);
|
||||||
Z3_apply_result r = _tactic_apply(c, t, g, to_param_ref(p));
|
Z3_apply_result r = _tactic_apply(c, t, g, to_param_ref(p));
|
||||||
RETURN_Z3(r);
|
RETURN_Z3(r);
|
||||||
Z3_CATCH_RETURN(0);
|
Z3_CATCH_RETURN(0);
|
||||||
|
|
|
@ -85,6 +85,8 @@ namespace z3 {
|
||||||
friend std::ostream & operator<<(std::ostream & out, exception const & e) { out << e.msg(); return out; }
|
friend std::ostream & operator<<(std::ostream & out, exception const & e) { out << e.msg(); return out; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Z3 global configuration object.
|
\brief Z3 global configuration object.
|
||||||
*/
|
*/
|
||||||
|
@ -269,8 +271,9 @@ namespace z3 {
|
||||||
object(object const & s):m_ctx(s.m_ctx) {}
|
object(object const & s):m_ctx(s.m_ctx) {}
|
||||||
context & ctx() const { return *m_ctx; }
|
context & ctx() const { return *m_ctx; }
|
||||||
void check_error() const { m_ctx->check_error(); }
|
void check_error() const { m_ctx->check_error(); }
|
||||||
friend void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); }
|
friend void check_context(object const & a, object const & b);
|
||||||
};
|
};
|
||||||
|
inline void check_context(object const & a, object const & b) { assert(a.m_ctx == b.m_ctx); }
|
||||||
|
|
||||||
class symbol : public object {
|
class symbol : public object {
|
||||||
Z3_symbol m_sym;
|
Z3_symbol m_sym;
|
||||||
|
@ -291,6 +294,7 @@ namespace z3 {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class params : public object {
|
class params : public object {
|
||||||
Z3_params m_params;
|
Z3_params m_params;
|
||||||
public:
|
public:
|
||||||
|
@ -309,7 +313,9 @@ namespace z3 {
|
||||||
void set(char const * k, unsigned n) { Z3_params_set_uint(ctx(), m_params, ctx().str_symbol(k), n); }
|
void set(char const * k, unsigned n) { Z3_params_set_uint(ctx(), m_params, ctx().str_symbol(k), n); }
|
||||||
void set(char const * k, double n) { Z3_params_set_double(ctx(), m_params, ctx().str_symbol(k), n); }
|
void set(char const * k, double n) { Z3_params_set_double(ctx(), m_params, ctx().str_symbol(k), n); }
|
||||||
void set(char const * k, symbol const & s) { Z3_params_set_symbol(ctx(), m_params, ctx().str_symbol(k), s); }
|
void set(char const * k, symbol const & s) { Z3_params_set_symbol(ctx(), m_params, ctx().str_symbol(k), s); }
|
||||||
friend std::ostream & operator<<(std::ostream & out, params const & p) { out << Z3_params_to_string(p.ctx(), p); return out; }
|
friend std::ostream & operator<<(std::ostream & out, params const & p) {
|
||||||
|
out << Z3_params_to_string(p.ctx(), p); return out;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ast : public object {
|
class ast : public object {
|
||||||
|
@ -325,14 +331,19 @@ namespace z3 {
|
||||||
ast & operator=(ast const & s) { Z3_inc_ref(s.ctx(), s.m_ast); if (m_ast) Z3_dec_ref(ctx(), m_ast); m_ctx = s.m_ctx; m_ast = s.m_ast; return *this; }
|
ast & operator=(ast const & s) { Z3_inc_ref(s.ctx(), s.m_ast); if (m_ast) Z3_dec_ref(ctx(), m_ast); m_ctx = s.m_ctx; m_ast = s.m_ast; return *this; }
|
||||||
Z3_ast_kind kind() const { Z3_ast_kind r = Z3_get_ast_kind(ctx(), m_ast); check_error(); return r; }
|
Z3_ast_kind kind() const { Z3_ast_kind r = Z3_get_ast_kind(ctx(), m_ast); check_error(); return r; }
|
||||||
unsigned hash() const { unsigned r = Z3_get_ast_hash(ctx(), m_ast); check_error(); return r; }
|
unsigned hash() const { unsigned r = Z3_get_ast_hash(ctx(), m_ast); check_error(); return r; }
|
||||||
friend std::ostream & operator<<(std::ostream & out, ast const & n) { out << Z3_ast_to_string(n.ctx(), n.m_ast); return out; }
|
friend std::ostream & operator<<(std::ostream & out, ast const & n) {
|
||||||
|
out << Z3_ast_to_string(n.ctx(), n.m_ast); return out;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return true if the ASTs are structurally identical.
|
\brief Return true if the ASTs are structurally identical.
|
||||||
*/
|
*/
|
||||||
friend bool eq(ast const & a, ast const & b) { return Z3_is_eq_ast(a.ctx(), a, b) != 0; }
|
friend bool eq(ast const & a, ast const & b);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool eq(ast const & a, ast const & b) { return Z3_is_eq_ast(a.ctx(), a, b) != 0; }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief A Z3 sort (aka type). Every expression (i.e., formula or term) in Z3 has a sort.
|
\brief A Z3 sort (aka type). Every expression (i.e., formula or term) in Z3 has a sort.
|
||||||
*/
|
*/
|
||||||
|
@ -570,6 +581,7 @@ namespace z3 {
|
||||||
return expr(a.ctx(), r);
|
return expr(a.ctx(), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return an expression representing <tt>a and b</tt>.
|
\brief Return an expression representing <tt>a and b</tt>.
|
||||||
|
|
||||||
|
@ -585,6 +597,7 @@ namespace z3 {
|
||||||
return expr(a.ctx(), r);
|
return expr(a.ctx(), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Return an expression representing <tt>a and b</tt>.
|
\brief Return an expression representing <tt>a and b</tt>.
|
||||||
The C++ Boolean value \c b is automatically converted into a Z3 Boolean constant.
|
The C++ Boolean value \c b is automatically converted into a Z3 Boolean constant.
|
||||||
|
@ -636,21 +649,10 @@ namespace z3 {
|
||||||
a.check_error();
|
a.check_error();
|
||||||
return expr(a.ctx(), r);
|
return expr(a.ctx(), r);
|
||||||
}
|
}
|
||||||
friend expr implies(expr const & a, bool b) { return implies(a, a.ctx().bool_val(b)); }
|
friend expr implies(expr const & a, bool b);
|
||||||
friend expr implies(bool a, expr const & b) { return implies(b.ctx().bool_val(a), b); }
|
friend expr implies(bool a, expr const & b);
|
||||||
|
|
||||||
/**
|
friend expr ite(expr const & c, expr const & t, expr const & e);
|
||||||
\brief Create the if-then-else expression <tt>ite(c, t, e)</tt>
|
|
||||||
|
|
||||||
\pre c.is_bool()
|
|
||||||
*/
|
|
||||||
friend expr ite(expr const & c, expr const & t, expr const & e) {
|
|
||||||
check_context(c, t); check_context(c, e);
|
|
||||||
assert(c.is_bool());
|
|
||||||
Z3_ast r = Z3_mk_ite(c.ctx(), c, t, e);
|
|
||||||
c.check_error();
|
|
||||||
return expr(c.ctx(), r);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend expr distinct(expr_vector const& args);
|
friend expr distinct(expr_vector const& args);
|
||||||
|
|
||||||
|
@ -716,15 +718,9 @@ namespace z3 {
|
||||||
/**
|
/**
|
||||||
\brief Power operator
|
\brief Power operator
|
||||||
*/
|
*/
|
||||||
friend expr pw(expr const & a, expr const & b) {
|
friend expr pw(expr const & a, expr const & b);
|
||||||
assert(a.is_arith() && b.is_arith());
|
friend expr pw(expr const & a, int b);
|
||||||
check_context(a, b);
|
friend expr pw(int a, expr const & b);
|
||||||
Z3_ast r = Z3_mk_power(a.ctx(), a, b);
|
|
||||||
a.check_error();
|
|
||||||
return expr(a.ctx(), r);
|
|
||||||
}
|
|
||||||
friend expr pw(expr const & a, int b) { return pw(a, a.ctx().num_val(b, a.get_sort())); }
|
|
||||||
friend expr pw(int a, expr const & b) { return pw(b.ctx().num_val(a, b.get_sort()), b); }
|
|
||||||
|
|
||||||
friend expr operator/(expr const & a, expr const & b) {
|
friend expr operator/(expr const & a, expr const & b) {
|
||||||
check_context(a, b);
|
check_context(a, b);
|
||||||
|
@ -892,6 +888,38 @@ namespace z3 {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline expr implies(expr const & a, bool b) { return implies(a, a.ctx().bool_val(b)); }
|
||||||
|
inline expr implies(bool a, expr const & b) { return implies(b.ctx().bool_val(a), b); }
|
||||||
|
|
||||||
|
inline expr pw(expr const & a, expr const & b) {
|
||||||
|
assert(a.is_arith() && b.is_arith());
|
||||||
|
check_context(a, b);
|
||||||
|
Z3_ast r = Z3_mk_power(a.ctx(), a, b);
|
||||||
|
a.check_error();
|
||||||
|
return expr(a.ctx(), r);
|
||||||
|
}
|
||||||
|
inline expr pw(expr const & a, int b) { return pw(a, a.ctx().num_val(b, a.get_sort())); }
|
||||||
|
inline expr pw(int a, expr const & b) { return pw(b.ctx().num_val(a, b.get_sort()), b); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Create the if-then-else expression <tt>ite(c, t, e)</tt>
|
||||||
|
|
||||||
|
\pre c.is_bool()
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline expr ite(expr const & c, expr const & t, expr const & e) {
|
||||||
|
check_context(c, t); check_context(c, e);
|
||||||
|
assert(c.is_bool());
|
||||||
|
Z3_ast r = Z3_mk_ite(c.ctx(), c, t, e);
|
||||||
|
c.check_error();
|
||||||
|
return expr(c.ctx(), r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Wraps a Z3_ast as an expr object. It also checks for errors.
|
\brief Wraps a Z3_ast as an expr object. It also checks for errors.
|
||||||
This function allows the user to use the whole C API with the C++ layer defined in this file.
|
This function allows the user to use the whole C API with the C++ layer defined in this file.
|
||||||
|
@ -1404,22 +1432,28 @@ namespace z3 {
|
||||||
t1.check_error();
|
t1.check_error();
|
||||||
return tactic(t1.ctx(), r);
|
return tactic(t1.ctx(), r);
|
||||||
}
|
}
|
||||||
friend tactic repeat(tactic const & t, unsigned max=UINT_MAX) {
|
friend tactic repeat(tactic const & t, unsigned max);
|
||||||
|
friend tactic with(tactic const & t, params const & p);
|
||||||
|
friend tactic try_for(tactic const & t, unsigned ms);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline tactic repeat(tactic const & t, unsigned max=UINT_MAX) {
|
||||||
Z3_tactic r = Z3_tactic_repeat(t.ctx(), t, max);
|
Z3_tactic r = Z3_tactic_repeat(t.ctx(), t, max);
|
||||||
t.check_error();
|
t.check_error();
|
||||||
return tactic(t.ctx(), r);
|
return tactic(t.ctx(), r);
|
||||||
}
|
}
|
||||||
friend tactic with(tactic const & t, params const & p) {
|
|
||||||
|
inline tactic with(tactic const & t, params const & p) {
|
||||||
Z3_tactic r = Z3_tactic_using_params(t.ctx(), t, p);
|
Z3_tactic r = Z3_tactic_using_params(t.ctx(), t, p);
|
||||||
t.check_error();
|
t.check_error();
|
||||||
return tactic(t.ctx(), r);
|
return tactic(t.ctx(), r);
|
||||||
}
|
}
|
||||||
friend tactic try_for(tactic const & t, unsigned ms) {
|
inline tactic try_for(tactic const & t, unsigned ms) {
|
||||||
Z3_tactic r = Z3_tactic_try_for(t.ctx(), t, ms);
|
Z3_tactic r = Z3_tactic_try_for(t.ctx(), t, ms);
|
||||||
t.check_error();
|
t.check_error();
|
||||||
return tactic(t.ctx(), r);
|
return tactic(t.ctx(), r);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
class probe : public object {
|
class probe : public object {
|
||||||
Z3_probe m_probe;
|
Z3_probe m_probe;
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace Microsoft.Z3
|
||||||
IntPtr constructor = IntPtr.Zero;
|
IntPtr constructor = IntPtr.Zero;
|
||||||
IntPtr tester = IntPtr.Zero;
|
IntPtr tester = IntPtr.Zero;
|
||||||
IntPtr[] accessors = new IntPtr[n];
|
IntPtr[] accessors = new IntPtr[n];
|
||||||
Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors);
|
Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, out accessors);
|
||||||
return new FuncDecl(Context, constructor);
|
return new FuncDecl(Context, constructor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ namespace Microsoft.Z3
|
||||||
IntPtr constructor = IntPtr.Zero;
|
IntPtr constructor = IntPtr.Zero;
|
||||||
IntPtr tester = IntPtr.Zero;
|
IntPtr tester = IntPtr.Zero;
|
||||||
IntPtr[] accessors = new IntPtr[n];
|
IntPtr[] accessors = new IntPtr[n];
|
||||||
Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors);
|
Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, out accessors);
|
||||||
return new FuncDecl(Context, tester);
|
return new FuncDecl(Context, tester);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ namespace Microsoft.Z3
|
||||||
IntPtr constructor = IntPtr.Zero;
|
IntPtr constructor = IntPtr.Zero;
|
||||||
IntPtr tester = IntPtr.Zero;
|
IntPtr tester = IntPtr.Zero;
|
||||||
IntPtr[] accessors = new IntPtr[n];
|
IntPtr[] accessors = new IntPtr[n];
|
||||||
Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, accessors);
|
Native.Z3_query_constructor(Context.nCtx, NativeObject, n, ref constructor, ref tester, out accessors);
|
||||||
FuncDecl[] t = new FuncDecl[n];
|
FuncDecl[] t = new FuncDecl[n];
|
||||||
for (uint i = 0; i < n; i++)
|
for (uint i = 0; i < n; i++)
|
||||||
t[i] = new FuncDecl(Context, accessors[i]);
|
t[i] = new FuncDecl(Context, accessors[i]);
|
||||||
|
|
|
@ -424,7 +424,7 @@ namespace Microsoft.Z3
|
||||||
n_constr[i] = cla[i].NativeObject;
|
n_constr[i] = cla[i].NativeObject;
|
||||||
}
|
}
|
||||||
IntPtr[] n_res = new IntPtr[n];
|
IntPtr[] n_res = new IntPtr[n];
|
||||||
Native.Z3_mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), n_res, n_constr);
|
Native.Z3_mk_datatypes(nCtx, n, Symbol.ArrayToNative(names), out n_res, n_constr);
|
||||||
DatatypeSort[] res = new DatatypeSort[n];
|
DatatypeSort[] res = new DatatypeSort[n];
|
||||||
for (uint i = 0; i < n; i++)
|
for (uint i = 0; i < n; i++)
|
||||||
res[i] = new DatatypeSort(this, n_res[i]);
|
res[i] = new DatatypeSort(this, n_res[i]);
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace Microsoft.Z3
|
||||||
IntPtr[] native_core = new IntPtr[assumptions.Length];
|
IntPtr[] native_core = new IntPtr[assumptions.Length];
|
||||||
r = (Z3_lbool)Native.Z3_check_assumptions(ctx.nCtx,
|
r = (Z3_lbool)Native.Z3_check_assumptions(ctx.nCtx,
|
||||||
(uint)assumptions.Length, AST.ArrayToNative(assumptions),
|
(uint)assumptions.Length, AST.ArrayToNative(assumptions),
|
||||||
ref mdl, ref prf, ref core_size, native_core);
|
ref mdl, ref prf, ref core_size, out native_core);
|
||||||
|
|
||||||
for (uint i = 0; i < core_size; i++)
|
for (uint i = 0; i < core_size; i++)
|
||||||
core.Add((BoolExpr)Expr.Create(ctx, native_core[i]));
|
core.Add((BoolExpr)Expr.Create(ctx, native_core[i]));
|
||||||
|
|
|
@ -88,7 +88,7 @@ namespace Microsoft.Z3
|
||||||
IntPtr[] n_constdecls = new IntPtr[n];
|
IntPtr[] n_constdecls = new IntPtr[n];
|
||||||
IntPtr[] n_testers = new IntPtr[n];
|
IntPtr[] n_testers = new IntPtr[n];
|
||||||
NativeObject = Native.Z3_mk_enumeration_sort(ctx.nCtx, name.NativeObject, (uint)n,
|
NativeObject = Native.Z3_mk_enumeration_sort(ctx.nCtx, name.NativeObject, (uint)n,
|
||||||
Symbol.ArrayToNative(enumNames), n_constdecls, n_testers);
|
Symbol.ArrayToNative(enumNames), out n_constdecls, out n_testers);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
};
|
};
|
||||||
|
|
|
@ -323,6 +323,14 @@ namespace Microsoft.Z3
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Interpolation
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the term is marked for interpolation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks></remarks>
|
||||||
|
public bool IsInterpolant { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_INTERP; } }
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Arithmetic Terms
|
#region Arithmetic Terms
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates whether the term is of integer sort.
|
/// Indicates whether the term is of integer sort.
|
||||||
|
|
162
src/api/dotnet/InterpolationContext.cs
Normal file
162
src/api/dotnet/InterpolationContext.cs
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Diagnostics.Contracts;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Microsoft.Z3
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The InterpolationContext is suitable for generation of interpolants.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the C/C++ API, which is well documented.</remarks>
|
||||||
|
[ContractVerification(true)]
|
||||||
|
class InterpolationContext : Context
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
public InterpolationContext() : base() { }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks><seealso cref="Context.Context(Dictionary<string, string>)"/></remarks>
|
||||||
|
public InterpolationContext(Dictionary<string, string> settings) : base(settings) { }
|
||||||
|
|
||||||
|
#region Terms
|
||||||
|
/// <summary>
|
||||||
|
/// Create an expression that marks a formula position for interpolation.
|
||||||
|
/// </summary>
|
||||||
|
public BoolExpr MkInterpolant(BoolExpr a)
|
||||||
|
{
|
||||||
|
Contract.Requires(a != null);
|
||||||
|
Contract.Ensures(Contract.Result<BoolExpr>() != null);
|
||||||
|
|
||||||
|
CheckContextMatch(a);
|
||||||
|
return new BoolExpr(this, Native.Z3_mk_interpolant(nCtx, a.NativeObject));
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes an interpolant.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the function Z3_get_interpolant in the C/C++ API, which is
|
||||||
|
/// well documented.</remarks>
|
||||||
|
Expr[] GetInterpolant(Expr pf, Expr pat, Params p)
|
||||||
|
{
|
||||||
|
Contract.Requires(pf != null);
|
||||||
|
Contract.Requires(pat != null);
|
||||||
|
Contract.Requires(p != null);
|
||||||
|
Contract.Ensures(Contract.Result<Expr>() != null);
|
||||||
|
|
||||||
|
CheckContextMatch(pf);
|
||||||
|
CheckContextMatch(pat);
|
||||||
|
CheckContextMatch(p);
|
||||||
|
|
||||||
|
ASTVector seq = new ASTVector(this, Native.Z3_get_interpolant(nCtx, pf.NativeObject, pat.NativeObject, p.NativeObject));
|
||||||
|
uint n = seq.Size;
|
||||||
|
Expr[] res = new Expr[n];
|
||||||
|
for (uint i = 0; i < n; i++)
|
||||||
|
res[i] = Expr.Create(this, seq[i].NativeObject);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes an interpolant.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the function Z3_compute_interpolant in the C/C++ API, which is
|
||||||
|
/// well documented.</remarks>
|
||||||
|
Z3_lbool ComputeInterpolant(Expr pat, Params p, out ASTVector interp, out Model model)
|
||||||
|
{
|
||||||
|
Contract.Requires(pat != null);
|
||||||
|
Contract.Requires(p != null);
|
||||||
|
Contract.Ensures(Contract.ValueAtReturn(out interp) != null);
|
||||||
|
Contract.Ensures(Contract.ValueAtReturn(out model) != null);
|
||||||
|
|
||||||
|
CheckContextMatch(pat);
|
||||||
|
CheckContextMatch(p);
|
||||||
|
|
||||||
|
IntPtr i = IntPtr.Zero, m = IntPtr.Zero;
|
||||||
|
int r = Native.Z3_compute_interpolant(nCtx, pat.NativeObject, p.NativeObject, ref i, ref m);
|
||||||
|
interp = new ASTVector(this, i);
|
||||||
|
model = new Model(this, m);
|
||||||
|
return (Z3_lbool)r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return a string summarizing cumulative time used for interpolation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the function Z3_interpolation_profile in the C/C++ API, which is
|
||||||
|
/// well documented.</remarks>
|
||||||
|
public string InterpolationProfile()
|
||||||
|
{
|
||||||
|
return Native.Z3_interpolation_profile(nCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks the correctness of an interpolant.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the function Z3_check_interpolant in the C/C++ API, which is
|
||||||
|
/// well documented.</remarks>
|
||||||
|
public int CheckInterpolant(Expr[] cnsts, uint[] parents, Expr[] interps, out string error, Expr[] theory)
|
||||||
|
{
|
||||||
|
Contract.Requires(cnsts.Length == parents.Length);
|
||||||
|
Contract.Requires(cnsts.Length == interps.Length + 1);
|
||||||
|
IntPtr n_err_str;
|
||||||
|
int r = Native.Z3_check_interpolant(nCtx,
|
||||||
|
(uint)cnsts.Length,
|
||||||
|
Expr.ArrayToNative(cnsts),
|
||||||
|
parents,
|
||||||
|
Expr.ArrayToNative(interps),
|
||||||
|
out n_err_str,
|
||||||
|
(uint)theory.Length,
|
||||||
|
Expr.ArrayToNative(theory));
|
||||||
|
error = Marshal.PtrToStringAnsi(n_err_str);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads an interpolation problem from a file.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the function Z3_read_interpolation_problem in the C/C++ API, which is
|
||||||
|
/// well documented.</remarks>
|
||||||
|
public int ReadInterpolationProblem(string filename, out Expr[] cnsts, out uint[] parents, out string error, out Expr[] theory)
|
||||||
|
{
|
||||||
|
uint num = 0, num_theory = 0;
|
||||||
|
IntPtr[] n_cnsts;
|
||||||
|
IntPtr[] n_theory;
|
||||||
|
IntPtr n_err_str;
|
||||||
|
int r = Native.Z3_read_interpolation_problem(nCtx, ref num, out n_cnsts, out parents, filename, out n_err_str, ref num_theory, out n_theory);
|
||||||
|
error = Marshal.PtrToStringAnsi(n_err_str);
|
||||||
|
cnsts = new Expr[num];
|
||||||
|
parents = new uint[num];
|
||||||
|
theory = new Expr[num_theory];
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
cnsts[i] = Expr.Create(this, n_cnsts[i]);
|
||||||
|
for (int i = 0; i < num_theory; i++)
|
||||||
|
theory[i] = Expr.Create(this, n_theory[i]);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes an interpolation problem to a file.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the function Z3_write_interpolation_problem in the C/C++ API, which is
|
||||||
|
/// well documented.</remarks>
|
||||||
|
public void WriteInterpolationProblem(string filename, Expr[] cnsts, uint[] parents, Expr[] theory)
|
||||||
|
{
|
||||||
|
Contract.Requires(cnsts.Length == parents.Length);
|
||||||
|
Native.Z3_write_interpolation_problem(nCtx, (uint)cnsts.Length, Expr.ArrayToNative(cnsts), parents, filename, (uint)theory.Length, Expr.ArrayToNative(theory));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,12 +19,12 @@
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
<Optimize>false</Optimize>
|
<Optimize>false</Optimize>
|
||||||
<OutputPath>..\Debug\</OutputPath>
|
<OutputPath>..\..\..\..\..\cwinter\bugs\z3bugs\Debug\</OutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<DocumentationFile>..\Debug\Microsoft.Z3.XML</DocumentationFile>
|
<DocumentationFile>C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML</DocumentationFile>
|
||||||
<CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
|
<CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
|
||||||
<CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
|
<CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
|
||||||
<CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
|
<CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
|
||||||
|
@ -254,7 +254,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
<OutputPath>..\..\..\..\..\cwinter\bugs\z3bugs\Debug\</OutputPath>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<DebugType>full</DebugType>
|
<DebugType>full</DebugType>
|
||||||
|
@ -266,7 +266,7 @@
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
|
<CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
|
||||||
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
|
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
|
||||||
<DocumentationFile>bin\x86\Debug\Microsoft.Z3.XML</DocumentationFile>
|
<DocumentationFile>C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML</DocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
<OutputPath>bin\x86\Release\</OutputPath>
|
||||||
|
@ -352,6 +352,7 @@
|
||||||
<Compile Include="FuncDecl.cs" />
|
<Compile Include="FuncDecl.cs" />
|
||||||
<Compile Include="FuncInterp.cs" />
|
<Compile Include="FuncInterp.cs" />
|
||||||
<Compile Include="Goal.cs" />
|
<Compile Include="Goal.cs" />
|
||||||
|
<Compile Include="InterpolationContext.cs" />
|
||||||
<Compile Include="IntExpr.cs" />
|
<Compile Include="IntExpr.cs" />
|
||||||
<Compile Include="IntNum.cs" />
|
<Compile Include="IntNum.cs" />
|
||||||
<Compile Include="IntSort.cs" />
|
<Compile Include="IntSort.cs" />
|
||||||
|
|
|
@ -58,6 +58,16 @@ namespace Microsoft.Z3
|
||||||
Native.Z3_params_set_double(Context.nCtx, NativeObject, name.NativeObject, value);
|
Native.Z3_params_set_double(Context.nCtx, NativeObject, name.NativeObject, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a parameter setting.
|
||||||
|
/// </summary>
|
||||||
|
public void Add(Symbol name, string value)
|
||||||
|
{
|
||||||
|
Contract.Requires(value != null);
|
||||||
|
|
||||||
|
Native.Z3_params_set_symbol(Context.nCtx, NativeObject, name.NativeObject, Context.MkSymbol(value).NativeObject);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a parameter setting.
|
/// Adds a parameter setting.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -74,9 +74,10 @@ namespace Microsoft.Z3
|
||||||
Contract.Requires(name != null);
|
Contract.Requires(name != null);
|
||||||
|
|
||||||
IntPtr t = IntPtr.Zero;
|
IntPtr t = IntPtr.Zero;
|
||||||
|
IntPtr[] f;
|
||||||
NativeObject = Native.Z3_mk_tuple_sort(ctx.nCtx, name.NativeObject, numFields,
|
NativeObject = Native.Z3_mk_tuple_sort(ctx.nCtx, name.NativeObject, numFields,
|
||||||
Symbol.ArrayToNative(fieldNames), AST.ArrayToNative(fieldSorts),
|
Symbol.ArrayToNative(fieldNames), AST.ArrayToNative(fieldSorts),
|
||||||
ref t, new IntPtr[numFields]);
|
ref t, out f);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
};
|
};
|
||||||
|
|
169
src/api/java/InterpolationContext.java
Normal file
169
src/api/java/InterpolationContext.java
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package com.microsoft.z3;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.lang.String;
|
||||||
|
|
||||||
|
import com.microsoft.z3.Native.IntPtr;
|
||||||
|
import com.microsoft.z3.Native.UIntArrayPtr;
|
||||||
|
import com.microsoft.z3.enumerations.Z3_lbool;
|
||||||
|
|
||||||
|
/** <summary>
|
||||||
|
* The InterpolationContext is suitable for generation of interpolants.
|
||||||
|
* </summary>
|
||||||
|
* <remarks>For more information on interpolation please refer
|
||||||
|
* too the C/C++ API, which is well documented.</remarks>
|
||||||
|
**/
|
||||||
|
public class InterpolationContext extends Context
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
**/
|
||||||
|
public InterpolationContext() throws Z3Exception
|
||||||
|
{
|
||||||
|
m_ctx = Native.mkInterpolationContext(0);
|
||||||
|
initContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* <remarks><seealso cref="Context.Context(Dictionary<string, string>)"/></remarks>
|
||||||
|
**/
|
||||||
|
public InterpolationContext(Map<String, String> settings) throws Z3Exception
|
||||||
|
{
|
||||||
|
long cfg = Native.mkConfig();
|
||||||
|
for (Map.Entry<String, String> kv : settings.entrySet())
|
||||||
|
Native.setParamValue(cfg, kv.getKey(), kv.getValue());
|
||||||
|
m_ctx = Native.mkInterpolationContext(cfg);
|
||||||
|
Native.delConfig(cfg);
|
||||||
|
initContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an expression that marks a formula position for interpolation.
|
||||||
|
* @throws Z3Exception
|
||||||
|
**/
|
||||||
|
public BoolExpr MkInterpolant(BoolExpr a) throws Z3Exception
|
||||||
|
{
|
||||||
|
checkContextMatch(a);
|
||||||
|
return new BoolExpr(this, Native.mkInterpolant(nCtx(), a.getNativeObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes an interpolant.
|
||||||
|
* <remarks>For more information on interpolation please refer
|
||||||
|
* too the function Z3_get_interpolant in the C/C++ API, which is
|
||||||
|
* well documented.</remarks>
|
||||||
|
* @throws Z3Exception
|
||||||
|
**/
|
||||||
|
Expr[] GetInterpolant(Expr pf, Expr pat, Params p) throws Z3Exception
|
||||||
|
{
|
||||||
|
checkContextMatch(pf);
|
||||||
|
checkContextMatch(pat);
|
||||||
|
checkContextMatch(p);
|
||||||
|
|
||||||
|
ASTVector seq = new ASTVector(this, Native.getInterpolant(nCtx(), pf.getNativeObject(), pat.getNativeObject(), p.getNativeObject()));
|
||||||
|
int n = seq.size();
|
||||||
|
Expr[] res = new Expr[n];
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
res[i] = Expr.create(this, seq.get(i).getNativeObject());
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes an interpolant.
|
||||||
|
* <remarks>For more information on interpolation please refer
|
||||||
|
* too the function Z3_compute_interpolant in the C/C++ API, which is
|
||||||
|
* well documented.</remarks>
|
||||||
|
* @throws Z3Exception
|
||||||
|
**/
|
||||||
|
Z3_lbool ComputeInterpolant(Expr pat, Params p, ASTVector interp, Model model) throws Z3Exception
|
||||||
|
{
|
||||||
|
checkContextMatch(pat);
|
||||||
|
checkContextMatch(p);
|
||||||
|
|
||||||
|
Native.LongPtr n_i = new Native.LongPtr();
|
||||||
|
Native.LongPtr n_m = new Native.LongPtr();
|
||||||
|
int r = Native.computeInterpolant(nCtx(), pat.getNativeObject(), p.getNativeObject(), n_i, n_m);
|
||||||
|
interp = new ASTVector(this, n_i.value);
|
||||||
|
model = new Model(this, n_m.value);
|
||||||
|
return Z3_lbool.fromInt(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return a string summarizing cumulative time used for interpolation.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the function Z3_interpolation_profile in the C/C++ API, which is
|
||||||
|
/// well documented.</remarks>
|
||||||
|
public String InterpolationProfile() throws Z3Exception
|
||||||
|
{
|
||||||
|
return Native.interpolationProfile(nCtx());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks the correctness of an interpolant.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the function Z3_check_interpolant in the C/C++ API, which is
|
||||||
|
/// well documented.</remarks>
|
||||||
|
public int CheckInterpolant(Expr[] cnsts, int[] parents, Expr[] interps, String error, Expr[] theory) throws Z3Exception
|
||||||
|
{
|
||||||
|
Native.StringPtr n_err_str = new Native.StringPtr();
|
||||||
|
int r = Native.checkInterpolant(nCtx(),
|
||||||
|
cnsts.length,
|
||||||
|
Expr.arrayToNative(cnsts),
|
||||||
|
parents,
|
||||||
|
Expr.arrayToNative(interps),
|
||||||
|
n_err_str,
|
||||||
|
theory.length,
|
||||||
|
Expr.arrayToNative(theory));
|
||||||
|
error = n_err_str.value;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads an interpolation problem from a file.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the function Z3_read_interpolation_problem in the C/C++ API, which is
|
||||||
|
/// well documented.</remarks>
|
||||||
|
public int ReadInterpolationProblem(String filename, Expr[] cnsts, int[] parents, String error, Expr[] theory) throws Z3Exception
|
||||||
|
{
|
||||||
|
Native.IntPtr n_num = new Native.IntPtr();
|
||||||
|
Native.IntPtr n_num_theory = new Native.IntPtr();
|
||||||
|
Native.ObjArrayPtr n_cnsts = new Native.ObjArrayPtr();
|
||||||
|
Native.UIntArrayPtr n_parents = new Native.UIntArrayPtr();
|
||||||
|
Native.ObjArrayPtr n_theory = new Native.ObjArrayPtr();
|
||||||
|
Native.StringPtr n_err_str = new Native.StringPtr();
|
||||||
|
int r = Native.readInterpolationProblem(nCtx(), n_num, n_cnsts, n_parents, filename, n_err_str, n_num_theory, n_theory);
|
||||||
|
int num = n_num.value;
|
||||||
|
int num_theory = n_num_theory.value;
|
||||||
|
error = n_err_str.value;
|
||||||
|
cnsts = new Expr[num];
|
||||||
|
parents = new int[num];
|
||||||
|
theory = new Expr[num_theory];
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
|
{
|
||||||
|
cnsts[i] = Expr.create(this, n_cnsts.value[i]);
|
||||||
|
parents[i] = n_parents.value[i];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < num_theory; i++)
|
||||||
|
theory[i] = Expr.create(this, n_theory.value[i]);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes an interpolation problem to a file.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>For more information on interpolation please refer
|
||||||
|
/// too the function Z3_write_interpolation_problem in the C/C++ API, which is
|
||||||
|
/// well documented.</remarks>
|
||||||
|
public void WriteInterpolationProblem(String filename, Expr[] cnsts, int[] parents, String error, Expr[] theory) throws Z3Exception
|
||||||
|
{
|
||||||
|
Native.writeInterpolationProblem(nCtx(), cnsts.length, Expr.arrayToNative(cnsts), parents, filename, theory.length, Expr.arrayToNative(theory));
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,6 +29,17 @@ public class Params extends Z3Object
|
||||||
name.getNativeObject(), value);
|
name.getNativeObject(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a parameter setting.
|
||||||
|
**/
|
||||||
|
public void add(Symbol name, String value) throws Z3Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
Native.paramsSetSymbol(getContext().nCtx(), getNativeObject(),
|
||||||
|
name.getNativeObject(),
|
||||||
|
getContext().mkSymbol(value).getNativeObject());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a parameter setting.
|
* Adds a parameter setting.
|
||||||
**/
|
**/
|
||||||
|
@ -75,6 +86,17 @@ public class Params extends Z3Object
|
||||||
.mkSymbol(name).getNativeObject(), value.getNativeObject());
|
.mkSymbol(name).getNativeObject(), value.getNativeObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a parameter setting.
|
||||||
|
**/
|
||||||
|
public void add(String name, String value) throws Z3Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
Native.paramsSetSymbol(getContext().nCtx(), getNativeObject(),
|
||||||
|
getContext().mkSymbol(name).getNativeObject(),
|
||||||
|
getContext().mkSymbol(value).getNativeObject());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A string representation of the parameter set.
|
* A string representation of the parameter set.
|
||||||
**/
|
**/
|
||||||
|
|
|
@ -7426,19 +7426,19 @@ def parse_smt2_file(f, sorts={}, decls={}, ctx=None):
|
||||||
dsz, dnames, ddecls = _dict2darray(decls, ctx)
|
dsz, dnames, ddecls = _dict2darray(decls, ctx)
|
||||||
return _to_expr_ref(Z3_parse_smtlib2_file(ctx.ref(), f, ssz, snames, ssorts, dsz, dnames, ddecls), ctx)
|
return _to_expr_ref(Z3_parse_smtlib2_file(ctx.ref(), f, ssz, snames, ssorts, dsz, dnames, ddecls), ctx)
|
||||||
|
|
||||||
def Interp(a,ctx=None):
|
def Interpolant(a,ctx=None):
|
||||||
"""Create an interpolation operator.
|
"""Create an interpolation operator.
|
||||||
|
|
||||||
The argument is an interpolation pattern (see tree_interpolant).
|
The argument is an interpolation pattern (see tree_interpolant).
|
||||||
|
|
||||||
>>> x = Int('x')
|
>>> x = Int('x')
|
||||||
>>> print Interp(x>0)
|
>>> print Interpolant(x>0)
|
||||||
interp(x > 0)
|
interp(x > 0)
|
||||||
"""
|
"""
|
||||||
ctx = _get_ctx(_ctx_from_ast_arg_list([a], ctx))
|
ctx = _get_ctx(_ctx_from_ast_arg_list([a], ctx))
|
||||||
s = BoolSort(ctx)
|
s = BoolSort(ctx)
|
||||||
a = s.cast(a)
|
a = s.cast(a)
|
||||||
return BoolRef(Z3_mk_interp(ctx.ref(), a.as_ast()), ctx)
|
return BoolRef(Z3_mk_interpolant(ctx.ref(), a.as_ast()), ctx)
|
||||||
|
|
||||||
def tree_interpolant(pat,p=None,ctx=None):
|
def tree_interpolant(pat,p=None,ctx=None):
|
||||||
"""Compute interpolant for a tree of formulas.
|
"""Compute interpolant for a tree of formulas.
|
||||||
|
@ -7477,10 +7477,10 @@ def tree_interpolant(pat,p=None,ctx=None):
|
||||||
|
|
||||||
>>> x = Int('x')
|
>>> x = Int('x')
|
||||||
>>> y = Int('y')
|
>>> y = Int('y')
|
||||||
>>> print tree_interpolant(And(Interp(x < 0), Interp(y > 2), x == y))
|
>>> print tree_interpolant(And(Interpolant(x < 0), Interpolant(y > 2), x == y))
|
||||||
[Not(x >= 0), Not(y <= 2)]
|
[Not(x >= 0), Not(y <= 2)]
|
||||||
|
|
||||||
>>> g = And(Interp(x<0),x<2)
|
>>> g = And(Interpolant(x<0),x<2)
|
||||||
>>> try:
|
>>> try:
|
||||||
... print tree_interpolant(g).sexpr()
|
... print tree_interpolant(g).sexpr()
|
||||||
... except ModelRef as m:
|
... except ModelRef as m:
|
||||||
|
@ -7519,7 +7519,7 @@ def binary_interpolant(a,b,p=None,ctx=None):
|
||||||
print binary_interpolant(x<0,x>2)
|
print binary_interpolant(x<0,x>2)
|
||||||
Not(x >= 0)
|
Not(x >= 0)
|
||||||
"""
|
"""
|
||||||
f = And(Interp(a),b)
|
f = And(Interpolant(a),b)
|
||||||
return tree_interpolant(f,p,ctx)[0]
|
return tree_interpolant(f,p,ctx)[0]
|
||||||
|
|
||||||
def sequence_interpolant(v,p=None,ctx=None):
|
def sequence_interpolant(v,p=None,ctx=None):
|
||||||
|
@ -7548,6 +7548,6 @@ def sequence_interpolant(v,p=None,ctx=None):
|
||||||
"""
|
"""
|
||||||
f = v[0]
|
f = v[0]
|
||||||
for i in range(1,len(v)):
|
for i in range(1,len(v)):
|
||||||
f = And(Interp(f),v[i])
|
f = And(Interpolant(f),v[i])
|
||||||
return tree_interpolant(f,p,ctx)
|
return tree_interpolant(f,p,ctx)
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ Notes:
|
||||||
#include"z3_algebraic.h"
|
#include"z3_algebraic.h"
|
||||||
#include"z3_polynomial.h"
|
#include"z3_polynomial.h"
|
||||||
#include"z3_rcf.h"
|
#include"z3_rcf.h"
|
||||||
|
#include"z3_interp.h"
|
||||||
|
|
||||||
#undef __in
|
#undef __in
|
||||||
#undef __out
|
#undef __out
|
||||||
|
|
324
src/api/z3_api.h
324
src/api/z3_api.h
|
@ -2134,16 +2134,6 @@ END_MLAPI_EXCLUDE
|
||||||
*/
|
*/
|
||||||
Z3_ast Z3_API Z3_mk_not(__in Z3_context c, __in Z3_ast a);
|
Z3_ast Z3_API Z3_mk_not(__in Z3_context c, __in Z3_ast a);
|
||||||
|
|
||||||
/**
|
|
||||||
\brief \mlh mk_interp c a \endmlh
|
|
||||||
Create an AST node marking a formula position for interpolation.
|
|
||||||
|
|
||||||
The node \c a must have Boolean sort.
|
|
||||||
|
|
||||||
def_API('Z3_mk_interp', AST, (_in(CONTEXT), _in(AST)))
|
|
||||||
*/
|
|
||||||
Z3_ast Z3_API Z3_mk_interp(__in Z3_context c, __in Z3_ast a);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief \mlh mk_ite c t1 t2 t2 \endmlh
|
\brief \mlh mk_ite c t1 t2 t2 \endmlh
|
||||||
Create an AST node representing an if-then-else: <tt>ite(t1, t2,
|
Create an AST node representing an if-then-else: <tt>ite(t1, t2,
|
||||||
|
@ -4957,8 +4947,7 @@ END_MLAPI_EXCLUDE
|
||||||
__in_ecount(num_sorts) Z3_sort const sorts[],
|
__in_ecount(num_sorts) Z3_sort const sorts[],
|
||||||
__in unsigned num_decls,
|
__in unsigned num_decls,
|
||||||
__in_ecount(num_decls) Z3_symbol const decl_names[],
|
__in_ecount(num_decls) Z3_symbol const decl_names[],
|
||||||
__in_ecount(num_decls) Z3_func_decl const decls[]
|
__in_ecount(num_decls) Z3_func_decl const decls[]);
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Similar to #Z3_parse_smtlib2_string, but reads the benchmark from a file.
|
\brief Similar to #Z3_parse_smtlib2_string, but reads the benchmark from a file.
|
||||||
|
@ -4972,8 +4961,7 @@ END_MLAPI_EXCLUDE
|
||||||
__in_ecount(num_sorts) Z3_sort const sorts[],
|
__in_ecount(num_sorts) Z3_sort const sorts[],
|
||||||
__in unsigned num_decls,
|
__in unsigned num_decls,
|
||||||
__in_ecount(num_decls) Z3_symbol const decl_names[],
|
__in_ecount(num_decls) Z3_symbol const decl_names[],
|
||||||
__in_ecount(num_decls) Z3_func_decl const decls[]
|
__in_ecount(num_decls) Z3_func_decl const decls[]);
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef ML4only
|
#ifdef ML4only
|
||||||
#include <mlx_parse_smtlib.idl>
|
#include <mlx_parse_smtlib.idl>
|
||||||
|
@ -7931,314 +7919,6 @@ END_MLAPI_EXCLUDE
|
||||||
Z3_ast Z3_API Z3_get_context_assignment(__in Z3_context c);
|
Z3_ast Z3_API Z3_get_context_assignment(__in Z3_context c);
|
||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
/**
|
|
||||||
@name Interpolation
|
|
||||||
*/
|
|
||||||
/*@{*/
|
|
||||||
|
|
||||||
/** \brief This function generates a Z3 context suitable for generation of
|
|
||||||
interpolants. Formulas can be generated as abstract syntx trees in
|
|
||||||
this context using the Z3 C API.
|
|
||||||
|
|
||||||
Interpolants are also generated as AST's in this context.
|
|
||||||
|
|
||||||
If cfg is non-null, it will be used as the base configuration
|
|
||||||
for the Z3 context. This makes it possible to set Z3 options
|
|
||||||
to be used during interpolation. This feature should be used
|
|
||||||
with some caution however, as it may be that certain Z3 options
|
|
||||||
are incompatible with interpolation.
|
|
||||||
|
|
||||||
def_API('Z3_mk_interpolation_context', CONTEXT, (_in(CONFIG),))
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
Z3_context Z3_API Z3_mk_interpolation_context(__in Z3_config cfg);
|
|
||||||
|
|
||||||
/** Compute an interpolant from a refutation. This takes a proof of
|
|
||||||
"false" from a set of formulas C, and an interpolation
|
|
||||||
pattern. The pattern pat is a formula combining the formulas in C
|
|
||||||
using logical conjunction and the "interp" operator (see
|
|
||||||
#Z3_mk_interp). This interp operator is logically the identity
|
|
||||||
operator. It marks the sub-formulas of the pattern for which interpolants should
|
|
||||||
be computed. The interpolant is a map sigma from marked subformulas to
|
|
||||||
formulas, such that, for each marked subformula phi of pat (where phi sigma
|
|
||||||
is phi with sigma(psi) substituted for each subformula psi of phi such that
|
|
||||||
psi in dom(sigma)):
|
|
||||||
|
|
||||||
1) phi sigma implies sigma(phi), and
|
|
||||||
|
|
||||||
2) sigma(phi) is in the common uninterpreted vocabulary between
|
|
||||||
the formulas of C occurring in phi and those not occurring in
|
|
||||||
phi
|
|
||||||
|
|
||||||
and moreover pat sigma implies false. In the simplest case
|
|
||||||
an interpolant for the pattern "(and (interp A) B)" maps A
|
|
||||||
to an interpolant for A /\ B.
|
|
||||||
|
|
||||||
The return value is a vector of formulas representing sigma. The
|
|
||||||
vector contains sigma(phi) for each marked subformula of pat, in
|
|
||||||
pre-order traversal. This means that subformulas of phi occur before phi
|
|
||||||
in the vector. Also, subformulas that occur multiply in pat will
|
|
||||||
occur multiply in the result vector.
|
|
||||||
|
|
||||||
In particular, calling Z3_get_interpolant on a pattern of the
|
|
||||||
form (interp ... (interp (and (interp A_1) A_2)) ... A_N) will
|
|
||||||
result in a sequence interpolant for A_1, A_2,... A_N.
|
|
||||||
|
|
||||||
Neglecting interp markers, the pattern must be a conjunction of
|
|
||||||
formulas in C, the set of premises of the proof. Otherwise an
|
|
||||||
error is flagged.
|
|
||||||
|
|
||||||
Any premises of the proof not present in the pattern are
|
|
||||||
treated as "background theory". Predicate and function symbols
|
|
||||||
occurring in the background theory are treated as interpreted and
|
|
||||||
thus always allowed in the interpolant.
|
|
||||||
|
|
||||||
Interpolant may not necessarily be computable from all
|
|
||||||
proofs. To be sure an interpolant can be computed, the proof
|
|
||||||
must be generated by an SMT solver for which interpoaltion is
|
|
||||||
supported, and the premises must be expressed using only
|
|
||||||
theories and operators for which interpolation is supported.
|
|
||||||
|
|
||||||
Currently, the only SMT solver that is supported is the legacy
|
|
||||||
SMT solver. Such a solver is available as the default solver in
|
|
||||||
#Z3_context objects produced by #Z3_mk_interpolation_context.
|
|
||||||
Currently, the theories supported are equality with
|
|
||||||
uninterpreted functions, linear integer arithmetic, and the
|
|
||||||
theory of arrays (in SMT-LIB terms, this is AUFLIA).
|
|
||||||
Quantifiers are allowed. Use of any other operators (including
|
|
||||||
"labels") may result in failure to compute an interpolant from a
|
|
||||||
proof.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
|
|
||||||
\param c logical context.
|
|
||||||
\param pf a refutation from premises (assertions) C
|
|
||||||
\param pat an interpolation pattern over C
|
|
||||||
\param p parameters
|
|
||||||
|
|
||||||
def_API('Z3_get_interpolant', AST_VECTOR, (_in(CONTEXT), _in(AST), _in(AST), _in(PARAMS)))
|
|
||||||
*/
|
|
||||||
|
|
||||||
Z3_ast_vector Z3_API Z3_get_interpolant(__in Z3_context c, __in Z3_ast pf, __in Z3_ast pat, __in Z3_params p);
|
|
||||||
|
|
||||||
/* Compute an interpolant for an unsatisfiable conjunction of formulas.
|
|
||||||
|
|
||||||
This takes as an argument an interpolation pattern as in
|
|
||||||
#Z3_get_interpolant. This is a conjunction, some subformulas of
|
|
||||||
which are marked with the "interp" operator (see #Z3_mk_interp).
|
|
||||||
|
|
||||||
The conjunction is first checked for unsatisfiability. The result
|
|
||||||
of this check is returned in the out parameter "status". If the result
|
|
||||||
is unsat, an interpolant is computed from the refutation as in #Z3_get_interpolant
|
|
||||||
and returned as a vector of formulas. Otherwise the return value is
|
|
||||||
an empty formula.
|
|
||||||
|
|
||||||
See #Z3_get_interpolant for a discussion of supported theories.
|
|
||||||
|
|
||||||
The advantage of this function over #Z3_get_interpolant is that
|
|
||||||
it is not necessary to create a suitable SMT solver and generate
|
|
||||||
a proof. The disadvantage is that it is not possible to use the
|
|
||||||
solver incrementally.
|
|
||||||
|
|
||||||
Parameters:
|
|
||||||
|
|
||||||
\param c logical context.
|
|
||||||
\param pat an interpolation pattern
|
|
||||||
\param p parameters for solver creation
|
|
||||||
\param status returns the status of the sat check
|
|
||||||
\param model returns model if satisfiable
|
|
||||||
|
|
||||||
Return value: status of SAT check
|
|
||||||
|
|
||||||
def_API('Z3_compute_interpolant', INT, (_in(CONTEXT), _in(AST), _in(PARAMS), _out(AST_VECTOR), _out(MODEL)))
|
|
||||||
*/
|
|
||||||
|
|
||||||
Z3_lbool Z3_API Z3_compute_interpolant(__in Z3_context c, __in Z3_ast pat, __in Z3_params p, __out Z3_ast_vector *interp, __out Z3_model *model);
|
|
||||||
|
|
||||||
|
|
||||||
/** Constant reprepresenting a root of a formula tree for tree interpolation */
|
|
||||||
#define IZ3_ROOT SHRT_MAX
|
|
||||||
|
|
||||||
/** This function uses Z3 to determine satisfiability of a set of
|
|
||||||
constraints. If UNSAT, an interpolant is returned, based on the
|
|
||||||
refutation generated by Z3. If SAT, a model is returned.
|
|
||||||
|
|
||||||
If "parents" is non-null, computes a tree interpolant. The tree is
|
|
||||||
defined by the array "parents". This array maps each formula in
|
|
||||||
the tree to its parent, where formulas are indicated by their
|
|
||||||
integer index in "cnsts". The parent of formula n must have index
|
|
||||||
greater than n. The last formula is the root of the tree. Its
|
|
||||||
parent entry should be the constant IZ3_ROOT.
|
|
||||||
|
|
||||||
If "parents" is null, computes a sequence interpolant.
|
|
||||||
|
|
||||||
\param ctx The Z3 context. Must be generated by iz3_mk_context
|
|
||||||
\param num The number of constraints in the sequence
|
|
||||||
\param cnsts Array of constraints (AST's in context ctx)
|
|
||||||
\param parents The parents vector defining the tree structure
|
|
||||||
\param options Interpolation options (may be NULL)
|
|
||||||
\param interps Array to return interpolants (size at least num-1, may be NULL)
|
|
||||||
\param model Returns a Z3 model if constraints SAT (may be NULL)
|
|
||||||
\param labels Returns relevant labels if SAT (may be NULL)
|
|
||||||
\param incremental
|
|
||||||
|
|
||||||
VERY IMPORTANT: All the Z3 formulas in cnsts must be in Z3
|
|
||||||
context ctx. The model and interpolants returned are also
|
|
||||||
in this context.
|
|
||||||
|
|
||||||
The return code is as in Z3_check_assumptions, that is,
|
|
||||||
|
|
||||||
Z3_L_FALSE = constraints UNSAT (interpolants returned)
|
|
||||||
Z3_L_TRUE = constraints SAT (model returned)
|
|
||||||
Z3_L_UNDEF = Z3 produced no result, or interpolation not possible
|
|
||||||
|
|
||||||
Currently, this function supports integer and boolean variables,
|
|
||||||
as well as arrays over these types, with linear arithmetic,
|
|
||||||
uninterpreted functions and quantifiers over integers (that is
|
|
||||||
AUFLIA). Interpolants are produced in AUFLIA. However, some
|
|
||||||
uses of array operations may cause quantifiers to appear in the
|
|
||||||
interpolants even when there are no quantifiers in the input formulas.
|
|
||||||
Although quantifiers may appear in the input formulas, Z3 may give up in
|
|
||||||
this case, returning Z3_L_UNDEF.
|
|
||||||
|
|
||||||
If "incremental" is true, cnsts must contain exactly the set of
|
|
||||||
formulas that are currently asserted in the context. If false,
|
|
||||||
there must be no formulas currently asserted in the context.
|
|
||||||
Setting "incremental" to true makes it posisble to incrementally
|
|
||||||
add and remove constraints from the context until the context
|
|
||||||
becomes UNSAT, at which point an interpolant is computed. Caution
|
|
||||||
must be used, however. Before popping the context, if you wish to
|
|
||||||
keep the interolant formulas, you *must* preserve them by using
|
|
||||||
Z3_persist_ast. Also, if you want to simplify the interpolant
|
|
||||||
formulas using Z3_simplify, you must first pop all of the
|
|
||||||
assertions in the context (or use a different context). Otherwise,
|
|
||||||
the formulas will be simplified *relative* to these constraints,
|
|
||||||
which is almost certainly not what you want.
|
|
||||||
|
|
||||||
|
|
||||||
Current limitations on tree interpolants. In a tree interpolation
|
|
||||||
problem, each constant (0-ary function symbol) must occur only
|
|
||||||
along one path from root to leaf. Function symbols (of arity > 0)
|
|
||||||
are considered to have global scope (i.e., may appear in any
|
|
||||||
interpolant formula).
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
Z3_lbool Z3_API Z3_interpolate(__in Z3_context ctx,
|
|
||||||
__in int num,
|
|
||||||
__in_ecount(num) Z3_ast *cnsts,
|
|
||||||
__in_ecount(num) unsigned *parents,
|
|
||||||
__in Z3_params options,
|
|
||||||
__out_ecount(num-1) Z3_ast *interps,
|
|
||||||
__out Z3_model *model,
|
|
||||||
__out Z3_literals *labels,
|
|
||||||
__in int incremental,
|
|
||||||
__in int num_theory,
|
|
||||||
__in_ecount(num_theory) Z3_ast *theory);
|
|
||||||
|
|
||||||
/** Return a string summarizing cumulative time used for
|
|
||||||
interpolation. This string is purely for entertainment purposes
|
|
||||||
and has no semantics.
|
|
||||||
|
|
||||||
\param ctx The context (currently ignored)
|
|
||||||
|
|
||||||
def_API('Z3_interpolation_profile', STRING, (_in(CONTEXT),))
|
|
||||||
*/
|
|
||||||
|
|
||||||
Z3_string Z3_API Z3_interpolation_profile(__in Z3_context ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
\brief Read an interpolation problem from file.
|
|
||||||
|
|
||||||
\param ctx The Z3 context. This resets the error handler of ctx.
|
|
||||||
\param filename The file name to read.
|
|
||||||
\param num Returns length of sequence.
|
|
||||||
\param cnsts Returns sequence of formulas (do not free)
|
|
||||||
\param parents Returns the parents vector (or NULL for sequence)
|
|
||||||
\param error Returns an error message in case of failure (do not free the string)
|
|
||||||
|
|
||||||
Returns true on success.
|
|
||||||
|
|
||||||
File formats: Currently two formats are supported, based on
|
|
||||||
SMT-LIB2. For sequence interpolants, the sequence of constraints is
|
|
||||||
represented by the sequence of "assert" commands in the file.
|
|
||||||
|
|
||||||
For tree interpolants, one symbol of type bool is associated to
|
|
||||||
each vertex of the tree. For each vertex v there is an "assert"
|
|
||||||
of the form:
|
|
||||||
|
|
||||||
(implies (and c1 ... cn f) v)
|
|
||||||
|
|
||||||
where c1 .. cn are the children of v (which must precede v in the file)
|
|
||||||
and f is the formula assiciated to node v. The last formula in the
|
|
||||||
file is the root vertex, and is represented by the predicate "false".
|
|
||||||
|
|
||||||
A solution to a tree interpolation problem can be thought of as a
|
|
||||||
valuation of the vertices that makes all the implications true
|
|
||||||
where each value is represented using the common symbols between
|
|
||||||
the formulas in the subtree and the remainder of the formulas.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
int Z3_API Z3_read_interpolation_problem(__in Z3_context ctx,
|
|
||||||
__out int *num,
|
|
||||||
__out_ecount(*num) Z3_ast **cnsts,
|
|
||||||
__out_ecount(*num) int **parents,
|
|
||||||
__in const char *filename,
|
|
||||||
__out const char **error,
|
|
||||||
__out int *num_theory,
|
|
||||||
__out_ecount(*num_theory) Z3_ast **theory);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** Check the correctness of an interpolant. The Z3 context must
|
|
||||||
have no constraints asserted when this call is made. That means
|
|
||||||
that after interpolating, you must first fully pop the Z3
|
|
||||||
context before calling this. See Z3_interpolate for meaning of parameters.
|
|
||||||
|
|
||||||
\param ctx The Z3 context. Must be generated by Z3_mk_interpolation_context
|
|
||||||
\param num The number of constraints in the sequence
|
|
||||||
\param cnsts Array of constraints (AST's in context ctx)
|
|
||||||
\param parents The parents vector (or NULL for sequence)
|
|
||||||
\param interps The interpolant to check
|
|
||||||
\param error Returns an error message if interpolant incorrect (do not free the string)
|
|
||||||
|
|
||||||
Return value is Z3_L_TRUE if interpolant is verified, Z3_L_FALSE if
|
|
||||||
incorrect, and Z3_L_UNDEF if unknown.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
int Z3_API Z3_check_interpolant(Z3_context ctx, int num, Z3_ast *cnsts, int *parents, Z3_ast *interps, const char **error,
|
|
||||||
int num_theory, Z3_ast *theory);
|
|
||||||
|
|
||||||
/** Write an interpolation problem to file suitable for reading with
|
|
||||||
Z3_read_interpolation_problem. The output file is a sequence
|
|
||||||
of SMT-LIB2 format commands, suitable for reading with command-line Z3
|
|
||||||
or other interpolating solvers.
|
|
||||||
|
|
||||||
\param ctx The Z3 context. Must be generated by z3_mk_interpolation_context
|
|
||||||
\param num The number of constraints in the sequence
|
|
||||||
\param cnsts Array of constraints
|
|
||||||
\param parents The parents vector (or NULL for sequence)
|
|
||||||
\param filename The file name to write
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
void Z3_API Z3_write_interpolation_problem(Z3_context ctx,
|
|
||||||
int num,
|
|
||||||
Z3_ast *cnsts,
|
|
||||||
int *parents,
|
|
||||||
const char *filename,
|
|
||||||
int num_theory,
|
|
||||||
Z3_ast *theory);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
277
src/api/z3_interp.h
Normal file
277
src/api/z3_interp.h
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2014 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
z3_interp.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
API for interpolation
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Kenneth McMillan (kenmcmil)
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#ifndef _Z3_INTERPOLATION_H_
|
||||||
|
#define _Z3_INTERPOLATION_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
/**
|
||||||
|
@name Interpolation
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief \mlh mk_interp c a \endmlh
|
||||||
|
Create an AST node marking a formula position for interpolation.
|
||||||
|
|
||||||
|
The node \c a must have Boolean sort.
|
||||||
|
|
||||||
|
def_API('Z3_mk_interpolant', AST, (_in(CONTEXT), _in(AST)))
|
||||||
|
*/
|
||||||
|
Z3_ast Z3_API Z3_mk_interpolant(__in Z3_context c, __in Z3_ast a);
|
||||||
|
|
||||||
|
|
||||||
|
/** \brief This function generates a Z3 context suitable for generation of
|
||||||
|
interpolants. Formulas can be generated as abstract syntax trees in
|
||||||
|
this context using the Z3 C API.
|
||||||
|
|
||||||
|
Interpolants are also generated as AST's in this context.
|
||||||
|
|
||||||
|
If cfg is non-null, it will be used as the base configuration
|
||||||
|
for the Z3 context. This makes it possible to set Z3 options
|
||||||
|
to be used during interpolation. This feature should be used
|
||||||
|
with some caution however, as it may be that certain Z3 options
|
||||||
|
are incompatible with interpolation.
|
||||||
|
|
||||||
|
def_API('Z3_mk_interpolation_context', CONTEXT, (_in(CONFIG),))
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
Z3_context Z3_API Z3_mk_interpolation_context(__in Z3_config cfg);
|
||||||
|
|
||||||
|
/** Compute an interpolant from a refutation. This takes a proof of
|
||||||
|
"false" from a set of formulas C, and an interpolation
|
||||||
|
pattern. The pattern pat is a formula combining the formulas in C
|
||||||
|
using logical conjunction and the "interp" operator (see
|
||||||
|
#Z3_mk_interpolant). This interp operator is logically the identity
|
||||||
|
operator. It marks the sub-formulas of the pattern for which interpolants should
|
||||||
|
be computed. The interpolant is a map sigma from marked subformulas to
|
||||||
|
formulas, such that, for each marked subformula phi of pat (where phi sigma
|
||||||
|
is phi with sigma(psi) substituted for each subformula psi of phi such that
|
||||||
|
psi in dom(sigma)):
|
||||||
|
|
||||||
|
1) phi sigma implies sigma(phi), and
|
||||||
|
|
||||||
|
2) sigma(phi) is in the common uninterpreted vocabulary between
|
||||||
|
the formulas of C occurring in phi and those not occurring in
|
||||||
|
phi
|
||||||
|
|
||||||
|
and moreover pat sigma implies false. In the simplest case
|
||||||
|
an interpolant for the pattern "(and (interp A) B)" maps A
|
||||||
|
to an interpolant for A /\ B.
|
||||||
|
|
||||||
|
The return value is a vector of formulas representing sigma. The
|
||||||
|
vector contains sigma(phi) for each marked subformula of pat, in
|
||||||
|
pre-order traversal. This means that subformulas of phi occur before phi
|
||||||
|
in the vector. Also, subformulas that occur multiply in pat will
|
||||||
|
occur multiply in the result vector.
|
||||||
|
|
||||||
|
In particular, calling Z3_get_interpolant on a pattern of the
|
||||||
|
form (interp ... (interp (and (interp A_1) A_2)) ... A_N) will
|
||||||
|
result in a sequence interpolant for A_1, A_2,... A_N.
|
||||||
|
|
||||||
|
Neglecting interp markers, the pattern must be a conjunction of
|
||||||
|
formulas in C, the set of premises of the proof. Otherwise an
|
||||||
|
error is flagged.
|
||||||
|
|
||||||
|
Any premises of the proof not present in the pattern are
|
||||||
|
treated as "background theory". Predicate and function symbols
|
||||||
|
occurring in the background theory are treated as interpreted and
|
||||||
|
thus always allowed in the interpolant.
|
||||||
|
|
||||||
|
Interpolant may not necessarily be computable from all
|
||||||
|
proofs. To be sure an interpolant can be computed, the proof
|
||||||
|
must be generated by an SMT solver for which interpoaltion is
|
||||||
|
supported, and the premises must be expressed using only
|
||||||
|
theories and operators for which interpolation is supported.
|
||||||
|
|
||||||
|
Currently, the only SMT solver that is supported is the legacy
|
||||||
|
SMT solver. Such a solver is available as the default solver in
|
||||||
|
#Z3_context objects produced by #Z3_mk_interpolation_context.
|
||||||
|
Currently, the theories supported are equality with
|
||||||
|
uninterpreted functions, linear integer arithmetic, and the
|
||||||
|
theory of arrays (in SMT-LIB terms, this is AUFLIA).
|
||||||
|
Quantifiers are allowed. Use of any other operators (including
|
||||||
|
"labels") may result in failure to compute an interpolant from a
|
||||||
|
proof.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
\param c logical context.
|
||||||
|
\param pf a refutation from premises (assertions) C
|
||||||
|
\param pat an interpolation pattern over C
|
||||||
|
\param p parameters
|
||||||
|
|
||||||
|
def_API('Z3_get_interpolant', AST_VECTOR, (_in(CONTEXT), _in(AST), _in(AST), _in(PARAMS)))
|
||||||
|
*/
|
||||||
|
|
||||||
|
Z3_ast_vector Z3_API Z3_get_interpolant(__in Z3_context c, __in Z3_ast pf, __in Z3_ast pat, __in Z3_params p);
|
||||||
|
|
||||||
|
/* Compute an interpolant for an unsatisfiable conjunction of formulas.
|
||||||
|
|
||||||
|
This takes as an argument an interpolation pattern as in
|
||||||
|
#Z3_get_interpolant. This is a conjunction, some subformulas of
|
||||||
|
which are marked with the "interp" operator (see #Z3_mk_interpolant).
|
||||||
|
|
||||||
|
The conjunction is first checked for unsatisfiability. The result
|
||||||
|
of this check is returned in the out parameter "status". If the result
|
||||||
|
is unsat, an interpolant is computed from the refutation as in #Z3_get_interpolant
|
||||||
|
and returned as a vector of formulas. Otherwise the return value is
|
||||||
|
an empty formula.
|
||||||
|
|
||||||
|
See #Z3_get_interpolant for a discussion of supported theories.
|
||||||
|
|
||||||
|
The advantage of this function over #Z3_get_interpolant is that
|
||||||
|
it is not necessary to create a suitable SMT solver and generate
|
||||||
|
a proof. The disadvantage is that it is not possible to use the
|
||||||
|
solver incrementally.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
|
||||||
|
\param c logical context.
|
||||||
|
\param pat an interpolation pattern
|
||||||
|
\param p parameters for solver creation
|
||||||
|
\param status returns the status of the sat check
|
||||||
|
\param model returns model if satisfiable
|
||||||
|
|
||||||
|
Return value: status of SAT check
|
||||||
|
|
||||||
|
def_API('Z3_compute_interpolant', INT, (_in(CONTEXT), _in(AST), _in(PARAMS), _out(AST_VECTOR), _out(MODEL)))
|
||||||
|
*/
|
||||||
|
|
||||||
|
Z3_lbool Z3_API Z3_compute_interpolant(__in Z3_context c,
|
||||||
|
__in Z3_ast pat,
|
||||||
|
__in Z3_params p,
|
||||||
|
__out Z3_ast_vector *interp,
|
||||||
|
__out Z3_model *model);
|
||||||
|
|
||||||
|
/** Return a string summarizing cumulative time used for
|
||||||
|
interpolation. This string is purely for entertainment purposes
|
||||||
|
and has no semantics.
|
||||||
|
|
||||||
|
\param ctx The context (currently ignored)
|
||||||
|
|
||||||
|
|
||||||
|
def_API('Z3_interpolation_profile', STRING, (_in(CONTEXT),))
|
||||||
|
*/
|
||||||
|
|
||||||
|
Z3_string Z3_API Z3_interpolation_profile(__in Z3_context ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Read an interpolation problem from file.
|
||||||
|
|
||||||
|
\param ctx The Z3 context. This resets the error handler of ctx.
|
||||||
|
\param filename The file name to read.
|
||||||
|
\param num Returns length of sequence.
|
||||||
|
\param cnsts Returns sequence of formulas (do not free)
|
||||||
|
\param parents Returns the parents vector (or NULL for sequence)
|
||||||
|
\param error Returns an error message in case of failure (do not free the string)
|
||||||
|
|
||||||
|
Returns true on success.
|
||||||
|
|
||||||
|
File formats: Currently two formats are supported, based on
|
||||||
|
SMT-LIB2. For sequence interpolants, the sequence of constraints is
|
||||||
|
represented by the sequence of "assert" commands in the file.
|
||||||
|
|
||||||
|
For tree interpolants, one symbol of type bool is associated to
|
||||||
|
each vertex of the tree. For each vertex v there is an "assert"
|
||||||
|
of the form:
|
||||||
|
|
||||||
|
(implies (and c1 ... cn f) v)
|
||||||
|
|
||||||
|
where c1 .. cn are the children of v (which must precede v in the file)
|
||||||
|
and f is the formula assiciated to node v. The last formula in the
|
||||||
|
file is the root vertex, and is represented by the predicate "false".
|
||||||
|
|
||||||
|
A solution to a tree interpolation problem can be thought of as a
|
||||||
|
valuation of the vertices that makes all the implications true
|
||||||
|
where each value is represented using the common symbols between
|
||||||
|
the formulas in the subtree and the remainder of the formulas.
|
||||||
|
|
||||||
|
def_API('Z3_read_interpolation_problem', INT, (_in(CONTEXT), _out(UINT), _out_managed_array(1, AST), _out_managed_array(1, UINT), _in(STRING), _out(STRING), _out(UINT), _out_managed_array(6, AST)))
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Z3_API Z3_read_interpolation_problem(__in Z3_context ctx,
|
||||||
|
__out unsigned *num,
|
||||||
|
__out Z3_ast *cnsts[],
|
||||||
|
__out unsigned *parents[],
|
||||||
|
__in Z3_string filename,
|
||||||
|
__out_opt Z3_string_ptr error,
|
||||||
|
__out unsigned *num_theory,
|
||||||
|
__out Z3_ast *theory[]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Check the correctness of an interpolant. The Z3 context must
|
||||||
|
have no constraints asserted when this call is made. That means
|
||||||
|
that after interpolating, you must first fully pop the Z3
|
||||||
|
context before calling this. See Z3_interpolate for meaning of parameters.
|
||||||
|
|
||||||
|
\param ctx The Z3 context. Must be generated by Z3_mk_interpolation_context
|
||||||
|
\param num The number of constraints in the sequence
|
||||||
|
\param cnsts Array of constraints (AST's in context ctx)
|
||||||
|
\param parents The parents vector (or NULL for sequence)
|
||||||
|
\param interps The interpolant to check
|
||||||
|
\param error Returns an error message if interpolant incorrect (do not free the string)
|
||||||
|
|
||||||
|
Return value is Z3_L_TRUE if interpolant is verified, Z3_L_FALSE if
|
||||||
|
incorrect, and Z3_L_UNDEF if unknown.
|
||||||
|
|
||||||
|
def_API('Z3_check_interpolant', INT, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in_array(1, AST), _out(STRING), _in(UINT), _in_array(6, AST)))
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Z3_API Z3_check_interpolant(__in Z3_context ctx,
|
||||||
|
__in unsigned num,
|
||||||
|
__in_ecount(num) Z3_ast cnsts[],
|
||||||
|
__in_ecount(num) unsigned parents[],
|
||||||
|
__in_ecount(num - 1) Z3_ast *interps,
|
||||||
|
__out_opt Z3_string_ptr error,
|
||||||
|
__in unsigned num_theory,
|
||||||
|
__in_ecount(num_theory) Z3_ast theory[]);
|
||||||
|
|
||||||
|
/** Write an interpolation problem to file suitable for reading with
|
||||||
|
Z3_read_interpolation_problem. The output file is a sequence
|
||||||
|
of SMT-LIB2 format commands, suitable for reading with command-line Z3
|
||||||
|
or other interpolating solvers.
|
||||||
|
|
||||||
|
\param ctx The Z3 context. Must be generated by z3_mk_interpolation_context
|
||||||
|
\param num The number of constraints in the sequence
|
||||||
|
\param cnsts Array of constraints
|
||||||
|
\param parents The parents vector (or NULL for sequence)
|
||||||
|
\param filename The file name to write
|
||||||
|
|
||||||
|
def_API('Z3_write_interpolation_problem', VOID, (_in(CONTEXT), _in(UINT), _in_array(1, AST), _in_array(1, UINT), _in(STRING), _in(UINT), _in_array(5, AST)))
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Z3_API Z3_write_interpolation_problem(__in Z3_context ctx,
|
||||||
|
__in unsigned num,
|
||||||
|
__in_ecount(num) Z3_ast cnsts[],
|
||||||
|
__in_ecount(num) unsigned parents[],
|
||||||
|
__in Z3_string filename,
|
||||||
|
__in unsigned num_theory,
|
||||||
|
__in_ecount(num_theory) Z3_ast theory[]);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
|
@ -75,6 +75,7 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
|
||||||
m_a_rw.updt_params(p);
|
m_a_rw.updt_params(p);
|
||||||
m_bv_rw.updt_params(p);
|
m_bv_rw.updt_params(p);
|
||||||
m_ar_rw.updt_params(p);
|
m_ar_rw.updt_params(p);
|
||||||
|
m_f_rw.updt_params(p);
|
||||||
updt_local_params(p);
|
updt_local_params(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,15 +114,19 @@ void context_params::collect_param_descrs(param_descrs & d) {
|
||||||
d.insert("well_sorted_check", CPK_BOOL, "type checker", "true");
|
d.insert("well_sorted_check", CPK_BOOL, "type checker", "true");
|
||||||
d.insert("type_check", CPK_BOOL, "type checker (alias for well_sorted_check)", "true");
|
d.insert("type_check", CPK_BOOL, "type checker (alias for well_sorted_check)", "true");
|
||||||
d.insert("auto_config", CPK_BOOL, "use heuristics to automatically select solver and configure it", "true");
|
d.insert("auto_config", CPK_BOOL, "use heuristics to automatically select solver and configure it", "true");
|
||||||
d.insert("proof", CPK_BOOL, "proof generation, it must be enabled when the Z3 context is created", "false");
|
|
||||||
d.insert("check_interpolants", CPK_BOOL, "check correctness of interpolants", "false");
|
d.insert("check_interpolants", CPK_BOOL, "check correctness of interpolants", "false");
|
||||||
d.insert("model", CPK_BOOL, "model generation for solvers, this parameter can be overwritten when creating a solver", "true");
|
|
||||||
d.insert("model_validate", CPK_BOOL, "validate models produced by solvers", "false");
|
d.insert("model_validate", CPK_BOOL, "validate models produced by solvers", "false");
|
||||||
d.insert("trace", CPK_BOOL, "trace generation for VCC", "false");
|
d.insert("trace", CPK_BOOL, "trace generation for VCC", "false");
|
||||||
d.insert("trace_file_name", CPK_STRING, "trace out file name (see option 'trace')", "z3.log");
|
d.insert("trace_file_name", CPK_STRING, "trace out file name (see option 'trace')", "z3.log");
|
||||||
d.insert("unsat_core", CPK_BOOL, "unsat-core generation for solvers, this parameter can be overwritten when creating a solver, not every solver in Z3 supports unsat core generation", "false");
|
|
||||||
d.insert("debug_ref_count", CPK_BOOL, "debug support for AST reference counting", "false");
|
d.insert("debug_ref_count", CPK_BOOL, "debug support for AST reference counting", "false");
|
||||||
d.insert("smtlib2_compliant", CPK_BOOL, "enable/disable SMT-LIB 2.0 compliance", "false");
|
d.insert("smtlib2_compliant", CPK_BOOL, "enable/disable SMT-LIB 2.0 compliance", "false");
|
||||||
|
collect_solver_param_descrs(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void context_params::collect_solver_param_descrs(param_descrs & d) {
|
||||||
|
d.insert("proof", CPK_BOOL, "proof generation, it must be enabled when the Z3 context is created", "false");
|
||||||
|
d.insert("model", CPK_BOOL, "model generation for solvers, this parameter can be overwritten when creating a solver", "true");
|
||||||
|
d.insert("unsat_core", CPK_BOOL, "unsat-core generation for solvers, this parameter can be overwritten when creating a solver, not every solver in Z3 supports unsat core generation", "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
params_ref context_params::merge_default_params(params_ref const & p) {
|
params_ref context_params::merge_default_params(params_ref const & p) {
|
||||||
|
|
|
@ -55,6 +55,8 @@ public:
|
||||||
*/
|
*/
|
||||||
void get_solver_params(ast_manager const & m, params_ref & p, bool & proofs_enabled, bool & models_enabled, bool & unsat_core_enabled);
|
void get_solver_params(ast_manager const & m, params_ref & p, bool & proofs_enabled, bool & models_enabled, bool & unsat_core_enabled);
|
||||||
|
|
||||||
|
static void collect_solver_param_descrs(param_descrs & d);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief Include in p parameters derived from this context_params.
|
\brief Include in p parameters derived from this context_params.
|
||||||
These are parameters that are meaningful for tactics and solvers.
|
These are parameters that are meaningful for tactics and solvers.
|
||||||
|
|
|
@ -500,7 +500,7 @@ static tactic * mk_using_params(cmd_context & ctx, sexpr * n) {
|
||||||
symbol param_name = symbol(norm_param_name(c->get_symbol()).c_str());
|
symbol param_name = symbol(norm_param_name(c->get_symbol()).c_str());
|
||||||
c = n->get_child(i);
|
c = n->get_child(i);
|
||||||
i++;
|
i++;
|
||||||
switch (descrs.get_kind(param_name)) {
|
switch (descrs.get_kind_in_module(param_name)) {
|
||||||
case CPK_INVALID:
|
case CPK_INVALID:
|
||||||
throw cmd_exception("invalid using-params combinator, unknown parameter ", param_name, c->get_line(), c->get_pos());
|
throw cmd_exception("invalid using-params combinator, unknown parameter ", param_name, c->get_line(), c->get_pos());
|
||||||
case CPK_BOOL:
|
case CPK_BOOL:
|
||||||
|
|
|
@ -161,17 +161,27 @@ namespace opt {
|
||||||
|
|
||||||
void opt_solver::maximize_objectives(expr_ref_vector& blockers) {
|
void opt_solver::maximize_objectives(expr_ref_vector& blockers) {
|
||||||
expr_ref blocker(m);
|
expr_ref blocker(m);
|
||||||
|
vector<inf_eps> values;
|
||||||
|
for (unsigned i = 0; i < m_objective_vars.size(); ++i) {
|
||||||
|
values.push_back(current_objective_value(i));
|
||||||
|
}
|
||||||
for (unsigned i = 0; i < m_objective_vars.size(); ++i) {
|
for (unsigned i = 0; i < m_objective_vars.size(); ++i) {
|
||||||
maximize_objective(i, blocker);
|
maximize_objective(i, blocker);
|
||||||
blockers.push_back(blocker);
|
blockers.push_back(blocker);
|
||||||
|
if (values[i] > m_objective_values[i]) {
|
||||||
|
std::cout << "local optimization produced a worse result\n";
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void opt_solver::maximize_objective(unsigned i, expr_ref& blocker) {
|
void opt_solver::maximize_objective(unsigned i, expr_ref& blocker) {
|
||||||
smt::theory_var v = m_objective_vars[i];
|
smt::theory_var v = m_objective_vars[i];
|
||||||
m_objective_values[i] = get_optimizer().maximize(v, blocker);
|
m_objective_values[i] = get_optimizer().maximize(v, blocker);
|
||||||
m_context.get_context().update_model();
|
m_context.get_context().update_model();
|
||||||
TRACE("opt", { model_ref mdl; get_model(mdl); model_smt2_pp(tout << "update model: ", m, *mdl, 0); });
|
TRACE("opt", { model_ref mdl; tout << m_objective_values[i] << "\n";
|
||||||
|
get_model(mdl); model_smt2_pp(tout << "update model: ", m, *mdl, 0); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void opt_solver::get_unsat_core(ptr_vector<expr> & r) {
|
void opt_solver::get_unsat_core(ptr_vector<expr> & r) {
|
||||||
|
@ -232,10 +242,16 @@ namespace opt {
|
||||||
return m_objective_values;
|
return m_objective_values;
|
||||||
}
|
}
|
||||||
|
|
||||||
inf_eps const& opt_solver::get_objective_value(unsigned i) {
|
inf_eps const& opt_solver::saved_objective_value(unsigned i) {
|
||||||
return m_objective_values[i];
|
return m_objective_values[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inf_eps opt_solver::current_objective_value(unsigned i) {
|
||||||
|
smt::theory_var v = m_objective_vars[i];
|
||||||
|
return get_optimizer().value(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
expr_ref opt_solver::mk_ge(unsigned var, inf_eps const& val) {
|
expr_ref opt_solver::mk_ge(unsigned var, inf_eps const& val) {
|
||||||
smt::theory_opt& opt = get_optimizer();
|
smt::theory_opt& opt = get_optimizer();
|
||||||
smt::theory_var v = m_objective_vars[var];
|
smt::theory_var v = m_objective_vars[var];
|
||||||
|
|
|
@ -107,9 +107,10 @@ namespace opt {
|
||||||
void reset_objectives();
|
void reset_objectives();
|
||||||
void maximize_objective(unsigned i, expr_ref& blocker);
|
void maximize_objective(unsigned i, expr_ref& blocker);
|
||||||
void maximize_objectives(expr_ref_vector& blockers);
|
void maximize_objectives(expr_ref_vector& blockers);
|
||||||
|
inf_eps const & saved_objective_value(unsigned obj_index);
|
||||||
|
inf_eps current_objective_value(unsigned obj_index);
|
||||||
|
|
||||||
vector<inf_eps> const& get_objective_values();
|
vector<inf_eps> const& get_objective_values();
|
||||||
inf_eps const & get_objective_value(unsigned obj_index);
|
|
||||||
expr_ref mk_ge(unsigned obj_index, inf_eps const& val);
|
expr_ref mk_ge(unsigned obj_index, inf_eps const& val);
|
||||||
|
|
||||||
static opt_solver& to_opt(solver& s);
|
static opt_solver& to_opt(solver& s);
|
||||||
|
|
|
@ -46,12 +46,21 @@ namespace opt {
|
||||||
m_cancel = f;
|
m_cancel = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void optsmt::set_max(vector<inf_eps>& dst, vector<inf_eps> const& src) {
|
void optsmt::set_max(vector<inf_eps>& dst, vector<inf_eps> const& src, expr_ref_vector& fmls) {
|
||||||
for (unsigned i = 0; i < src.size(); ++i) {
|
for (unsigned i = 0; i < src.size(); ++i) {
|
||||||
if (src[i] > dst[i]) {
|
if (src[i] > dst[i]) {
|
||||||
dst[i] = src[i];
|
dst[i] = src[i];
|
||||||
|
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();
|
||||||
|
fmls[i] = m.mk_false();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (src[i] < dst[i] && !m.is_true(m_lower_fmls[i].get())) {
|
||||||
|
fmls[i] = m_lower_fmls[i].get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -131,20 +140,17 @@ namespace opt {
|
||||||
disj.reset();
|
disj.reset();
|
||||||
m_s->maximize_objectives(disj);
|
m_s->maximize_objectives(disj);
|
||||||
m_s->get_model(m_model);
|
m_s->get_model(m_model);
|
||||||
set_max(m_lower, m_s->get_objective_values());
|
|
||||||
for (unsigned i = 0; i < ors.size(); ++i) {
|
for (unsigned i = 0; i < ors.size(); ++i) {
|
||||||
expr_ref tmp(m);
|
expr_ref tmp(m);
|
||||||
m_model->eval(ors[i].get(), tmp);
|
m_model->eval(ors[i].get(), tmp);
|
||||||
if (m.is_true(tmp)) {
|
if (m.is_true(tmp)) {
|
||||||
m_lower[i] = m_upper[i];
|
m_lower[i] = m_upper[i];
|
||||||
ors[i] = m.mk_false();
|
ors[i] = m.mk_false();
|
||||||
}
|
|
||||||
if (m.is_false(ors[i].get())) {
|
|
||||||
disj[i] = m.mk_false();
|
disj[i] = m.mk_false();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
set_max(m_lower, m_s->get_objective_values(), disj);
|
||||||
or = m.mk_or(ors.size(), ors.c_ptr());
|
or = m.mk_or(ors.size(), ors.c_ptr());
|
||||||
bound = m.mk_or(disj.size(), disj.c_ptr());
|
|
||||||
m_s->assert_expr(or);
|
m_s->assert_expr(or);
|
||||||
}
|
}
|
||||||
else if (is_sat == l_undef) {
|
else if (is_sat == l_undef) {
|
||||||
|
@ -155,6 +161,7 @@ namespace opt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bound = m.mk_or(m_lower_fmls.size(), m_lower_fmls.c_ptr());
|
||||||
m_s->assert_expr(bound);
|
m_s->assert_expr(bound);
|
||||||
|
|
||||||
if (m_cancel) {
|
if (m_cancel) {
|
||||||
|
@ -177,9 +184,9 @@ namespace opt {
|
||||||
|
|
||||||
void optsmt::update_lower() {
|
void optsmt::update_lower() {
|
||||||
expr_ref_vector disj(m);
|
expr_ref_vector disj(m);
|
||||||
m_s->maximize_objectives(disj);
|
|
||||||
m_s->get_model(m_model);
|
m_s->get_model(m_model);
|
||||||
set_max(m_lower, m_s->get_objective_values());
|
m_s->maximize_objectives(disj);
|
||||||
|
set_max(m_lower, m_s->get_objective_values(), disj);
|
||||||
TRACE("opt",
|
TRACE("opt",
|
||||||
for (unsigned i = 0; i < m_lower.size(); ++i) {
|
for (unsigned i = 0; i < m_lower.size(); ++i) {
|
||||||
tout << m_lower[i] << " ";
|
tout << m_lower[i] << " ";
|
||||||
|
@ -192,11 +199,8 @@ namespace opt {
|
||||||
verbose_stream() << m_lower[i] << " ";
|
verbose_stream() << m_lower[i] << " ";
|
||||||
}
|
}
|
||||||
verbose_stream() << ")\n";);
|
verbose_stream() << ")\n";);
|
||||||
for (unsigned i = 0; i < m_lower.size(); ++i) {
|
IF_VERBOSE(3, verbose_stream() << disj << "\n";);
|
||||||
if (m_lower[i].is_pos() && !m_lower[i].is_finite()) {
|
IF_VERBOSE(3, model_pp(verbose_stream(), *m_model););
|
||||||
disj[i] = m.mk_false();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
expr_ref constraint(m);
|
expr_ref constraint(m);
|
||||||
constraint = m.mk_or(disj.size(), disj.c_ptr());
|
constraint = m.mk_or(disj.size(), disj.c_ptr());
|
||||||
|
@ -309,7 +313,7 @@ namespace opt {
|
||||||
|
|
||||||
m_s->maximize_objective(obj_index, block);
|
m_s->maximize_objective(obj_index, block);
|
||||||
m_s->get_model(m_model);
|
m_s->get_model(m_model);
|
||||||
inf_eps obj = m_s->get_objective_value(obj_index);
|
inf_eps obj = m_s->saved_objective_value(obj_index);
|
||||||
if (obj > m_lower[obj_index]) {
|
if (obj > m_lower[obj_index]) {
|
||||||
m_lower[obj_index] = obj;
|
m_lower[obj_index] = obj;
|
||||||
IF_VERBOSE(1,
|
IF_VERBOSE(1,
|
||||||
|
@ -320,7 +324,7 @@ namespace opt {
|
||||||
);
|
);
|
||||||
for (unsigned i = obj_index+1; i < m_vars.size(); ++i) {
|
for (unsigned i = obj_index+1; i < m_vars.size(); ++i) {
|
||||||
m_s->maximize_objective(i, tmp);
|
m_s->maximize_objective(i, tmp);
|
||||||
m_lower[i] = m_s->get_objective_value(i);
|
m_lower[i] = m_s->saved_objective_value(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_s->assert_expr(block);
|
m_s->assert_expr(block);
|
||||||
|
@ -401,6 +405,7 @@ namespace opt {
|
||||||
m_objs.push_back(to_app(t2));
|
m_objs.push_back(to_app(t2));
|
||||||
m_lower.push_back(inf_eps(rational(-1),inf_rational(0)));
|
m_lower.push_back(inf_eps(rational(-1),inf_rational(0)));
|
||||||
m_upper.push_back(inf_eps(rational(1), inf_rational(0)));
|
m_upper.push_back(inf_eps(rational(1), inf_rational(0)));
|
||||||
|
m_lower_fmls.push_back(m.mk_true());
|
||||||
return m_objs.size()-1;
|
return m_objs.size()-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,6 +420,7 @@ namespace opt {
|
||||||
m_objs.reset();
|
m_objs.reset();
|
||||||
m_vars.reset();
|
m_vars.reset();
|
||||||
m_model.reset();
|
m_model.reset();
|
||||||
|
m_lower_fmls.reset();
|
||||||
m_s = 0;
|
m_s = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,13 @@ namespace opt {
|
||||||
vector<inf_eps> m_lower;
|
vector<inf_eps> m_lower;
|
||||||
vector<inf_eps> m_upper;
|
vector<inf_eps> m_upper;
|
||||||
app_ref_vector m_objs;
|
app_ref_vector m_objs;
|
||||||
|
expr_ref_vector m_lower_fmls;
|
||||||
svector<smt::theory_var> m_vars;
|
svector<smt::theory_var> m_vars;
|
||||||
symbol m_optsmt_engine;
|
symbol m_optsmt_engine;
|
||||||
model_ref m_model;
|
model_ref m_model;
|
||||||
public:
|
public:
|
||||||
optsmt(ast_manager& m): m(m), m_s(0), m_cancel(false), m_objs(m) {}
|
optsmt(ast_manager& m):
|
||||||
|
m(m), m_s(0), m_cancel(false), m_objs(m), m_lower_fmls(m) {}
|
||||||
|
|
||||||
void setup(opt_solver& solver);
|
void setup(opt_solver& solver);
|
||||||
|
|
||||||
|
@ -73,7 +75,7 @@ namespace opt {
|
||||||
|
|
||||||
lbool farkas_opt();
|
lbool farkas_opt();
|
||||||
|
|
||||||
void set_max(vector<inf_eps>& dst, vector<inf_eps> const& src);
|
void set_max(vector<inf_eps>& dst, vector<inf_eps> const& src, expr_ref_vector& fmls);
|
||||||
|
|
||||||
void update_lower();
|
void update_lower();
|
||||||
|
|
||||||
|
|
|
@ -2238,8 +2238,7 @@ namespace qe {
|
||||||
m_params(p),
|
m_params(p),
|
||||||
m_trail(m),
|
m_trail(m),
|
||||||
m_qe(0),
|
m_qe(0),
|
||||||
m_assumption(m.mk_true()),
|
m_assumption(m.mk_true())
|
||||||
m_use_new_qe(true)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2261,12 +2260,6 @@ namespace qe {
|
||||||
}
|
}
|
||||||
|
|
||||||
void expr_quant_elim::updt_params(params_ref const& p) {
|
void expr_quant_elim::updt_params(params_ref const& p) {
|
||||||
bool r = p.get_bool("use_neq_qe", m_use_new_qe);
|
|
||||||
if (r != m_use_new_qe) {
|
|
||||||
dealloc(m_qe);
|
|
||||||
m_qe = 0;
|
|
||||||
m_use_new_qe = r;
|
|
||||||
}
|
|
||||||
init_qe();
|
init_qe();
|
||||||
m_qe->updt_params(p);
|
m_qe->updt_params(p);
|
||||||
}
|
}
|
||||||
|
@ -2274,7 +2267,6 @@ namespace qe {
|
||||||
void expr_quant_elim::collect_param_descrs(param_descrs& r) {
|
void expr_quant_elim::collect_param_descrs(param_descrs& r) {
|
||||||
r.insert("eliminate_variables_as_block", CPK_BOOL,
|
r.insert("eliminate_variables_as_block", CPK_BOOL,
|
||||||
"(default: true) eliminate variables as a block (true) or one at a time (false)");
|
"(default: true) eliminate variables as a block (true) or one at a time (false)");
|
||||||
// r.insert("use_new_qe", CPK_BOOL, "(default: true) invoke quantifier engine based on abstracted solver");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void expr_quant_elim::init_qe() {
|
void expr_quant_elim::init_qe() {
|
||||||
|
@ -2517,6 +2509,10 @@ namespace qe {
|
||||||
add_plugin(mk_arith_plugin(*this, false, m_fparams));
|
add_plugin(mk_arith_plugin(*this, false, m_fparams));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updt_params(params_ref const& p) {
|
||||||
|
m_fparams.updt_params(p);
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~simplify_solver_context() { reset(); }
|
virtual ~simplify_solver_context() { reset(); }
|
||||||
|
|
||||||
void solve(expr_ref& fml, app_ref_vector& vars) {
|
void solve(expr_ref& fml, app_ref_vector& vars) {
|
||||||
|
@ -2607,6 +2603,10 @@ namespace qe {
|
||||||
public:
|
public:
|
||||||
impl(ast_manager& m) : m(m), m_ctx(m) {}
|
impl(ast_manager& m) : m(m), m_ctx(m) {}
|
||||||
|
|
||||||
|
void updt_params(params_ref const& p) {
|
||||||
|
m_ctx.updt_params(p);
|
||||||
|
}
|
||||||
|
|
||||||
bool reduce_quantifier(
|
bool reduce_quantifier(
|
||||||
quantifier * old_q,
|
quantifier * old_q,
|
||||||
expr * new_body,
|
expr * new_body,
|
||||||
|
@ -2670,6 +2670,10 @@ namespace qe {
|
||||||
return imp->reduce_quantifier(old_q, new_body, new_patterns, new_no_patterns, result, result_pr);
|
return imp->reduce_quantifier(old_q, new_body, new_patterns, new_no_patterns, result, result_pr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void simplify_rewriter_cfg::updt_params(params_ref const& p) {
|
||||||
|
imp->updt_params(p);
|
||||||
|
}
|
||||||
|
|
||||||
bool simplify_rewriter_cfg::pre_visit(expr* e) {
|
bool simplify_rewriter_cfg::pre_visit(expr* e) {
|
||||||
if (!is_quantifier(e)) return true;
|
if (!is_quantifier(e)) return true;
|
||||||
quantifier * q = to_quantifier(e);
|
quantifier * q = to_quantifier(e);
|
||||||
|
@ -2677,7 +2681,6 @@ namespace qe {
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplify_exists(app_ref_vector& vars, expr_ref& fml) {
|
void simplify_exists(app_ref_vector& vars, expr_ref& fml) {
|
||||||
smt_params params;
|
|
||||||
ast_manager& m = fml.get_manager();
|
ast_manager& m = fml.get_manager();
|
||||||
simplify_solver_context ctx(m);
|
simplify_solver_context ctx(m);
|
||||||
ctx.solve(fml, vars);
|
ctx.solve(fml, vars);
|
||||||
|
|
|
@ -281,7 +281,6 @@ namespace qe {
|
||||||
obj_map<expr,expr*> m_visited;
|
obj_map<expr,expr*> m_visited;
|
||||||
quant_elim* m_qe;
|
quant_elim* m_qe;
|
||||||
expr* m_assumption;
|
expr* m_assumption;
|
||||||
bool m_use_new_qe;
|
|
||||||
public:
|
public:
|
||||||
expr_quant_elim(ast_manager& m, smt_params const& fp, params_ref const& p = params_ref());
|
expr_quant_elim(ast_manager& m, smt_params const& fp, params_ref const& p = params_ref());
|
||||||
~expr_quant_elim();
|
~expr_quant_elim();
|
||||||
|
@ -372,6 +371,8 @@ namespace qe {
|
||||||
|
|
||||||
bool pre_visit(expr* e);
|
bool pre_visit(expr* e);
|
||||||
|
|
||||||
|
void updt_params(params_ref const& p);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class simplify_rewriter_star : public rewriter_tpl<simplify_rewriter_cfg> {
|
class simplify_rewriter_star : public rewriter_tpl<simplify_rewriter_cfg> {
|
||||||
|
@ -380,6 +381,8 @@ namespace qe {
|
||||||
simplify_rewriter_star(ast_manager& m):
|
simplify_rewriter_star(ast_manager& m):
|
||||||
rewriter_tpl<simplify_rewriter_cfg>(m, false, m_cfg),
|
rewriter_tpl<simplify_rewriter_cfg>(m, false, m_cfg),
|
||||||
m_cfg(m) {}
|
m_cfg(m) {}
|
||||||
|
|
||||||
|
void updt_params(params_ref const& p) { m_cfg.updt_params(p); }
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -74,6 +74,7 @@ namespace qe {
|
||||||
is_relevant_default m_is_relevant;
|
is_relevant_default m_is_relevant;
|
||||||
mk_atom_default m_mk_atom;
|
mk_atom_default m_mk_atom;
|
||||||
th_rewriter m_rewriter;
|
th_rewriter m_rewriter;
|
||||||
|
simplify_rewriter_star m_qe_rw;
|
||||||
expr_strong_context_simplifier m_ctx_rewriter;
|
expr_strong_context_simplifier m_ctx_rewriter;
|
||||||
|
|
||||||
class solver_context : public i_solver_context {
|
class solver_context : public i_solver_context {
|
||||||
|
@ -218,6 +219,7 @@ namespace qe {
|
||||||
m_Ms(m),
|
m_Ms(m),
|
||||||
m_assignments(m),
|
m_assignments(m),
|
||||||
m_rewriter(m),
|
m_rewriter(m),
|
||||||
|
m_qe_rw(m),
|
||||||
m_ctx_rewriter(m_fparams, m) {
|
m_ctx_rewriter(m_fparams, m) {
|
||||||
m_fparams.m_model = true;
|
m_fparams.m_model = true;
|
||||||
}
|
}
|
||||||
|
@ -257,9 +259,8 @@ namespace qe {
|
||||||
goal->get_formulas(fmls);
|
goal->get_formulas(fmls);
|
||||||
m_fml = m.mk_and(fmls.size(), fmls.c_ptr());
|
m_fml = m.mk_and(fmls.size(), fmls.c_ptr());
|
||||||
TRACE("qe", tout << "input: " << mk_pp(m_fml,m) << "\n";);
|
TRACE("qe", tout << "input: " << mk_pp(m_fml,m) << "\n";);
|
||||||
simplify_rewriter_star rw(m);
|
|
||||||
expr_ref tmp(m);
|
expr_ref tmp(m);
|
||||||
rw(m_fml, tmp);
|
m_qe_rw(m_fml, tmp);
|
||||||
m_fml = tmp;
|
m_fml = tmp;
|
||||||
TRACE("qe", tout << "reduced: " << mk_pp(m_fml,m) << "\n";);
|
TRACE("qe", tout << "reduced: " << mk_pp(m_fml,m) << "\n";);
|
||||||
skolemize_existential_prefix();
|
skolemize_existential_prefix();
|
||||||
|
@ -305,6 +306,8 @@ namespace qe {
|
||||||
m_projection_mode_param = p.get_bool("projection_mode", m_projection_mode_param);
|
m_projection_mode_param = p.get_bool("projection_mode", m_projection_mode_param);
|
||||||
m_strong_context_simplify_param = p.get_bool("strong_context_simplify", m_strong_context_simplify_param);
|
m_strong_context_simplify_param = p.get_bool("strong_context_simplify", m_strong_context_simplify_param);
|
||||||
m_ctx_simplify_local_param = p.get_bool("strong_context_simplify_local", m_ctx_simplify_local_param);
|
m_ctx_simplify_local_param = p.get_bool("strong_context_simplify_local", m_ctx_simplify_local_param);
|
||||||
|
m_fparams.updt_params(p);
|
||||||
|
m_qe_rw.updt_params(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void collect_param_descrs(param_descrs & r) {
|
virtual void collect_param_descrs(param_descrs & r) {
|
||||||
|
|
|
@ -36,6 +36,7 @@ class qe_tactic : public tactic {
|
||||||
}
|
}
|
||||||
|
|
||||||
void updt_params(params_ref const & p) {
|
void updt_params(params_ref const & p) {
|
||||||
|
m_fparams.updt_params(p);
|
||||||
m_fparams.m_nlquant_elim = p.get_bool("qe_nonlinear", false);
|
m_fparams.m_nlquant_elim = p.get_bool("qe_nonlinear", false);
|
||||||
m_qe.updt_params(p);
|
m_qe.updt_params(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1426,7 +1426,6 @@ namespace sat {
|
||||||
|
|
||||||
void simplifier::elim_vars() {
|
void simplifier::elim_vars() {
|
||||||
if (!m_elim_vars) return;
|
if (!m_elim_vars) return;
|
||||||
|
|
||||||
elim_var_report rpt(*this);
|
elim_var_report rpt(*this);
|
||||||
bool_var_vector vars;
|
bool_var_vector vars;
|
||||||
order_vars_for_elim(vars);
|
order_vars_for_elim(vars);
|
||||||
|
|
|
@ -19,10 +19,11 @@ Revision History:
|
||||||
#include"smt_params.h"
|
#include"smt_params.h"
|
||||||
#include"smt_params_helper.hpp"
|
#include"smt_params_helper.hpp"
|
||||||
#include"model_params.hpp"
|
#include"model_params.hpp"
|
||||||
|
#include"gparams.h"
|
||||||
|
|
||||||
void smt_params::updt_local_params(params_ref const & _p) {
|
void smt_params::updt_local_params(params_ref const & _p) {
|
||||||
smt_params_helper p(_p);
|
smt_params_helper p(_p);
|
||||||
m_auto_config = p.auto_config();
|
m_auto_config = p.auto_config() && gparams::get_value("auto_config") == "true"; // auto-config is not scoped by smt in gparams.
|
||||||
m_random_seed = p.random_seed();
|
m_random_seed = p.random_seed();
|
||||||
m_relevancy_lvl = p.relevancy();
|
m_relevancy_lvl = p.relevancy();
|
||||||
m_ematching = p.ematching();
|
m_ematching = p.ematching();
|
||||||
|
|
|
@ -1017,6 +1017,7 @@ namespace smt {
|
||||||
//
|
//
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
virtual inf_eps_rational<inf_rational> maximize(theory_var v, expr_ref& blocker);
|
virtual inf_eps_rational<inf_rational> maximize(theory_var v, expr_ref& blocker);
|
||||||
|
virtual inf_eps_rational<inf_rational> value(theory_var v);
|
||||||
virtual theory_var add_objective(app* term);
|
virtual theory_var add_objective(app* term);
|
||||||
virtual expr* mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val);
|
virtual expr* mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val);
|
||||||
void enable_record_conflict(expr* bound);
|
void enable_record_conflict(expr* bound);
|
||||||
|
|
|
@ -1059,7 +1059,6 @@ namespace smt {
|
||||||
theory_var theory_arith<Ext>::add_objective(app* term) {
|
theory_var theory_arith<Ext>::add_objective(app* term) {
|
||||||
theory_var v = internalize_term_core(term);
|
theory_var v = internalize_term_core(term);
|
||||||
TRACE("opt", tout << mk_pp(term, get_manager()) << " |-> v" << v << "\n";);
|
TRACE("opt", tout << mk_pp(term, get_manager()) << " |-> v" << v << "\n";);
|
||||||
TRACE("opt", tout << "data-size: " << m_data.size() << "\n";);
|
|
||||||
SASSERT(!is_quasi_base(v));
|
SASSERT(!is_quasi_base(v));
|
||||||
if (!is_linear(get_manager(), term)) {
|
if (!is_linear(get_manager(), term)) {
|
||||||
v = null_theory_var;
|
v = null_theory_var;
|
||||||
|
@ -1067,6 +1066,11 @@ namespace smt {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
inf_eps_rational<inf_rational> theory_arith<Ext>::value(theory_var v) {
|
||||||
|
return inf_eps_rational<inf_rational>(get_value(v));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
inf_eps_rational<inf_rational> theory_arith<Ext>::maximize(theory_var v, expr_ref& blocker) {
|
inf_eps_rational<inf_rational> theory_arith<Ext>::maximize(theory_var v, expr_ref& blocker) {
|
||||||
TRACE("bound_bug", display_var(tout, v); display(tout););
|
TRACE("bound_bug", display_var(tout, v); display(tout););
|
||||||
|
@ -1533,12 +1537,14 @@ namespace smt {
|
||||||
*/
|
*/
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
typename theory_arith<Ext>::max_min_t theory_arith<Ext>::max_min(theory_var v, bool max) {
|
typename theory_arith<Ext>::max_min_t theory_arith<Ext>::max_min(theory_var v, bool max) {
|
||||||
TRACE("opt", tout << (max ? "maximizing" : "minimizing") << " v" << v << "...\n";);
|
expr* e = get_enode(v)->get_owner();
|
||||||
SASSERT(valid_row_assignment());
|
SASSERT(valid_row_assignment());
|
||||||
SASSERT(satisfy_bounds());
|
SASSERT(satisfy_bounds());
|
||||||
SASSERT(!is_quasi_base(v));
|
SASSERT(!is_quasi_base(v));
|
||||||
if ((max && at_upper(v)) || (!max && at_lower(v)))
|
if ((max && at_upper(v)) || (!max && at_lower(v))) {
|
||||||
|
TRACE("opt", tout << "At bound: " << mk_pp(e, get_manager()) << "...\n";);
|
||||||
return AT_BOUND; // nothing to be done...
|
return AT_BOUND; // nothing to be done...
|
||||||
|
}
|
||||||
m_tmp_row.reset();
|
m_tmp_row.reset();
|
||||||
if (is_non_base(v)) {
|
if (is_non_base(v)) {
|
||||||
add_tmp_row_entry<false>(m_tmp_row, numeral(1), v);
|
add_tmp_row_entry<false>(m_tmp_row, numeral(1), v);
|
||||||
|
@ -1554,11 +1560,16 @@ namespace smt {
|
||||||
}
|
}
|
||||||
max_min_t r = max_min(m_tmp_row, max);
|
max_min_t r = max_min(m_tmp_row, max);
|
||||||
if (r == OPTIMIZED) {
|
if (r == OPTIMIZED) {
|
||||||
TRACE("opt", tout << "v" << v << " " << (max ? "max" : "min") << " value is: " << get_value(v) << "\n";
|
TRACE("opt", tout << mk_pp(e, get_manager()) << " " << (max ? "max" : "min") << " value is: " << get_value(v) << "\n";
|
||||||
display_row(tout, m_tmp_row, true); display_row_info(tout, m_tmp_row););
|
display_row(tout, m_tmp_row, true); display_row_info(tout, m_tmp_row););
|
||||||
|
|
||||||
mk_bound_from_row(v, get_value(v), max ? B_UPPER : B_LOWER, m_tmp_row);
|
mk_bound_from_row(v, get_value(v), max ? B_UPPER : B_LOWER, m_tmp_row);
|
||||||
|
}
|
||||||
|
else if (r == UNBOUNDED) {
|
||||||
|
TRACE("opt", tout << "unbounded: " << mk_pp(e, get_manager()) << "...\n";);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE("opt", tout << "not optimized: " << mk_pp(e, get_manager()) << "...\n";);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ namespace smt {
|
||||||
unsigned bv_size = get_bv_size(n);
|
unsigned bv_size = get_bv_size(n);
|
||||||
context & ctx = get_context();
|
context & ctx = get_context();
|
||||||
literal_vector & bits = m_bits[v];
|
literal_vector & bits = m_bits[v];
|
||||||
|
bits.reset();
|
||||||
for (unsigned i = 0; i < bv_size; i++) {
|
for (unsigned i = 0; i < bv_size; i++) {
|
||||||
app * bit = mk_bit2bool(owner, i);
|
app * bit = mk_bit2bool(owner, i);
|
||||||
ctx.internalize(bit, true);
|
ctx.internalize(bit, true);
|
||||||
|
@ -75,12 +76,14 @@ namespace smt {
|
||||||
void theory_bv::mk_bit2bool(app * n) {
|
void theory_bv::mk_bit2bool(app * n) {
|
||||||
context & ctx = get_context();
|
context & ctx = get_context();
|
||||||
SASSERT(!ctx.b_internalized(n));
|
SASSERT(!ctx.b_internalized(n));
|
||||||
if (!ctx.e_internalized(n->get_arg(0))) {
|
|
||||||
|
expr* first_arg = n->get_arg(0);
|
||||||
|
|
||||||
|
if (!ctx.e_internalized(first_arg)) {
|
||||||
// This may happen if bit2bool(x) is in a conflict
|
// This may happen if bit2bool(x) is in a conflict
|
||||||
// clause that is being reinitialized, and x was not reinitialized
|
// clause that is being reinitialized, and x was not reinitialized
|
||||||
// yet.
|
// yet.
|
||||||
// So, we internalize x (i.e., n->get_arg(0))
|
// So, we internalize x (i.e., arg)
|
||||||
expr * first_arg = n->get_arg(0);
|
|
||||||
ctx.internalize(first_arg, false);
|
ctx.internalize(first_arg, false);
|
||||||
SASSERT(ctx.e_internalized(first_arg));
|
SASSERT(ctx.e_internalized(first_arg));
|
||||||
// In most cases, when x is internalized, its bits are created.
|
// In most cases, when x is internalized, its bits are created.
|
||||||
|
@ -91,10 +94,27 @@ namespace smt {
|
||||||
// This will also force the creation of all bits for x.
|
// This will also force the creation of all bits for x.
|
||||||
enode * first_arg_enode = ctx.get_enode(first_arg);
|
enode * first_arg_enode = ctx.get_enode(first_arg);
|
||||||
get_var(first_arg_enode);
|
get_var(first_arg_enode);
|
||||||
SASSERT(ctx.b_internalized(n));
|
// numerals are not blasted into bit2bool, so we do this directly.
|
||||||
|
if (!ctx.b_internalized(n)) {
|
||||||
|
rational val;
|
||||||
|
unsigned sz;
|
||||||
|
VERIFY(m_util.is_numeral(first_arg, val, sz));
|
||||||
|
theory_var v = first_arg_enode->get_th_var(get_id());
|
||||||
|
app* owner = first_arg_enode->get_owner();
|
||||||
|
for (unsigned i = 0; i < sz; ++i) {
|
||||||
|
ctx.internalize(mk_bit2bool(owner, i), true);
|
||||||
|
}
|
||||||
|
m_bits[v].reset();
|
||||||
|
rational bit;
|
||||||
|
for (unsigned i = 0; i < sz; ++i) {
|
||||||
|
div(val, rational::power_of_two(i), bit);
|
||||||
|
mod(bit, rational(2), bit);
|
||||||
|
m_bits[v].push_back(bit.is_zero()?false_literal:true_literal);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
enode * arg = ctx.get_enode(n->get_arg(0));
|
enode * arg = ctx.get_enode(first_arg);
|
||||||
// The argument was already internalized, but it may not have a theory variable associated with it.
|
// The argument was already internalized, but it may not have a theory variable associated with it.
|
||||||
// For example, for ite-terms the method apply_sort_cnstr is not invoked.
|
// For example, for ite-terms the method apply_sort_cnstr is not invoked.
|
||||||
// See comment in the then-branch.
|
// See comment in the then-branch.
|
||||||
|
@ -1041,6 +1061,7 @@ namespace smt {
|
||||||
|
|
||||||
void theory_bv::new_diseq_eh(theory_var v1, theory_var v2) {
|
void theory_bv::new_diseq_eh(theory_var v1, theory_var v2) {
|
||||||
if (is_bv(v1)) {
|
if (is_bv(v1)) {
|
||||||
|
SASSERT(m_bits[v1].size() == m_bits[v2].size());
|
||||||
expand_diseq(v1, v2);
|
expand_diseq(v1, v2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1381,6 +1402,7 @@ namespace smt {
|
||||||
if (v1 != null_theory_var) {
|
if (v1 != null_theory_var) {
|
||||||
// conflict was detected ... v1 and v2 have complementary bits
|
// conflict was detected ... v1 and v2 have complementary bits
|
||||||
SASSERT(m_bits[v1][it->m_idx] == ~(m_bits[v2][it->m_idx]));
|
SASSERT(m_bits[v1][it->m_idx] == ~(m_bits[v2][it->m_idx]));
|
||||||
|
SASSERT(m_bits[v1].size() == m_bits[v2].size());
|
||||||
mk_new_diseq_axiom(v1, v2, it->m_idx);
|
mk_new_diseq_axiom(v1, v2, it->m_idx);
|
||||||
RESET_MERGET_AUX();
|
RESET_MERGET_AUX();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -267,6 +267,7 @@ namespace smt {
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
|
|
||||||
virtual inf_eps_rational<inf_rational> maximize(theory_var v, expr_ref& blocker);
|
virtual inf_eps_rational<inf_rational> maximize(theory_var v, expr_ref& blocker);
|
||||||
|
virtual inf_eps_rational<inf_rational> value(theory_var v);
|
||||||
virtual theory_var add_objective(app* term);
|
virtual theory_var add_objective(app* term);
|
||||||
virtual expr_ref mk_gt(theory_var v, inf_rational const& val);
|
virtual expr_ref mk_gt(theory_var v, inf_rational const& val);
|
||||||
virtual expr* mk_ge(theory_var v, inf_rational const& val) { return 0; }
|
virtual expr* mk_ge(theory_var v, inf_rational const& val) { return 0; }
|
||||||
|
|
|
@ -875,6 +875,19 @@ namespace smt {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
inf_eps_rational<inf_rational> theory_dense_diff_logic<Ext>::value(theory_var v) {
|
||||||
|
objective_term const& objective = m_objectives[v];
|
||||||
|
inf_eps r = inf_eps(m_objective_consts[v]);
|
||||||
|
for (unsigned i = 0; i < objective.size(); ++i) {
|
||||||
|
numeral n = m_assignment[v];
|
||||||
|
rational r1 = n.get_rational().to_rational();
|
||||||
|
rational r2 = n.get_infinitesimal().to_rational();
|
||||||
|
r += objective[i].second * inf_eps(rational(0), inf_rational(r1, r2));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
inf_eps_rational<inf_rational> theory_dense_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker) {
|
inf_eps_rational<inf_rational> theory_dense_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker) {
|
||||||
typedef simplex::simplex<simplex::mpq_ext> Simplex;
|
typedef simplex::simplex<simplex::mpq_ext> Simplex;
|
||||||
|
|
|
@ -65,6 +65,7 @@ namespace smt {
|
||||||
|
|
||||||
typedef typename Ext::numeral numeral;
|
typedef typename Ext::numeral numeral;
|
||||||
typedef simplex::simplex<simplex::mpq_ext> Simplex;
|
typedef simplex::simplex<simplex::mpq_ext> Simplex;
|
||||||
|
typedef inf_eps_rational<inf_rational> inf_eps;
|
||||||
|
|
||||||
class atom {
|
class atom {
|
||||||
bool_var m_bvar;
|
bool_var m_bvar;
|
||||||
|
@ -319,7 +320,8 @@ namespace smt {
|
||||||
//
|
//
|
||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
|
|
||||||
virtual inf_eps_rational<inf_rational> maximize(theory_var v, expr_ref& blocker);
|
virtual inf_eps maximize(theory_var v, expr_ref& blocker);
|
||||||
|
virtual inf_eps value(theory_var v);
|
||||||
virtual theory_var add_objective(app* term);
|
virtual theory_var add_objective(app* term);
|
||||||
virtual expr_ref mk_gt(theory_var v, inf_rational const& val);
|
virtual expr_ref mk_gt(theory_var v, inf_rational const& val);
|
||||||
virtual expr* mk_ge(theory_var v, inf_rational const& val) { return 0; }
|
virtual expr* mk_ge(theory_var v, inf_rational const& val) { return 0; }
|
||||||
|
|
|
@ -1078,43 +1078,32 @@ void theory_diff_logic<Ext>::get_implied_bound_antecedents(edge_id bridge_edge,
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
unsigned theory_diff_logic<Ext>::node2simplex(unsigned v) {
|
unsigned theory_diff_logic<Ext>::node2simplex(unsigned v) {
|
||||||
//return v;
|
|
||||||
return m_objectives.size() + 2*v + 1;
|
return m_objectives.size() + 2*v + 1;
|
||||||
}
|
}
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
unsigned theory_diff_logic<Ext>::edge2simplex(unsigned e) {
|
unsigned theory_diff_logic<Ext>::edge2simplex(unsigned e) {
|
||||||
//return m_graph.get_num_nodes() + e;
|
|
||||||
return m_objectives.size() + 2*e;
|
return m_objectives.size() + 2*e;
|
||||||
}
|
}
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
unsigned theory_diff_logic<Ext>::obj2simplex(unsigned e) {
|
unsigned theory_diff_logic<Ext>::obj2simplex(unsigned e) {
|
||||||
//return m_graph.get_num_nodes() + m_graph.get_num_edges() + e;
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
unsigned theory_diff_logic<Ext>::num_simplex_vars() {
|
unsigned theory_diff_logic<Ext>::num_simplex_vars() {
|
||||||
//return m_graph.get_num_nodes() + m_graph.get_num_edges() + m_objectives.size();
|
|
||||||
return m_objectives.size() + std::max(2*m_graph.get_num_edges(),2*m_graph.get_num_nodes()+1);
|
return m_objectives.size() + std::max(2*m_graph.get_num_edges(),2*m_graph.get_num_nodes()+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
bool theory_diff_logic<Ext>::is_simplex_edge(unsigned e) {
|
bool theory_diff_logic<Ext>::is_simplex_edge(unsigned e) {
|
||||||
#if 0
|
|
||||||
return
|
|
||||||
m_graph.get_num_nodes() <= e &&
|
|
||||||
e < m_graph.get_num_nodes() + m_graph.get_num_edges();
|
|
||||||
#else
|
|
||||||
if (e < m_objectives.size()) return false;
|
if (e < m_objectives.size()) return false;
|
||||||
e -= m_objectives.size();
|
e -= m_objectives.size();
|
||||||
return (0 == (e & 0x1));
|
return (0 == (e & 0x1));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
unsigned theory_diff_logic<Ext>::simplex2edge(unsigned e) {
|
unsigned theory_diff_logic<Ext>::simplex2edge(unsigned e) {
|
||||||
SASSERT(is_simplex_edge(e));
|
SASSERT(is_simplex_edge(e));
|
||||||
//return e - m_graph.get_num_nodes();
|
|
||||||
return (e - m_objectives.size())/2;
|
return (e - m_objectives.size())/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1184,7 +1173,21 @@ void theory_diff_logic<Ext>::update_simplex(Simplex& S) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
inf_eps_rational<inf_rational> theory_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker) {
|
typename theory_diff_logic<Ext>::inf_eps theory_diff_logic<Ext>::value(theory_var v) {
|
||||||
|
objective_term const& objective = m_objectives[v];
|
||||||
|
inf_eps r = inf_eps(m_objective_consts[v]);
|
||||||
|
for (unsigned i = 0; i < objective.size(); ++i) {
|
||||||
|
numeral n = m_graph.get_assignment(v);
|
||||||
|
rational r1 = n.get_rational().to_rational();
|
||||||
|
rational r2 = n.get_infinitesimal().to_rational();
|
||||||
|
r += objective[i].second * inf_eps(rational(0), inf_rational(r1, r2));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
typename theory_diff_logic<Ext>::inf_eps
|
||||||
|
theory_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker) {
|
||||||
|
|
||||||
Simplex& S = m_S;
|
Simplex& S = m_S;
|
||||||
ast_manager& m = get_manager();
|
ast_manager& m = get_manager();
|
||||||
|
@ -1206,7 +1209,7 @@ inf_eps_rational<inf_rational> theory_diff_logic<Ext>::maximize(theory_var v, ex
|
||||||
lbool is_sat = S.make_feasible();
|
lbool is_sat = S.make_feasible();
|
||||||
if (is_sat == l_undef) {
|
if (is_sat == l_undef) {
|
||||||
blocker = m.mk_false();
|
blocker = m.mk_false();
|
||||||
return inf_eps_rational<inf_rational>::infinity();
|
return inf_eps::infinity();
|
||||||
}
|
}
|
||||||
TRACE("opt", S.display(tout); );
|
TRACE("opt", S.display(tout); );
|
||||||
SASSERT(is_sat != l_false);
|
SASSERT(is_sat != l_false);
|
||||||
|
@ -1233,12 +1236,12 @@ inf_eps_rational<inf_rational> theory_diff_logic<Ext>::maximize(theory_var v, ex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
blocker = mk_gt(v, r);
|
blocker = mk_gt(v, r);
|
||||||
return inf_eps_rational<inf_rational>(rational(0), r);
|
return inf_eps(rational(0), r);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
TRACE("opt", tout << "unbounded\n"; );
|
TRACE("opt", tout << "unbounded\n"; );
|
||||||
blocker = m.mk_false();
|
blocker = m.mk_false();
|
||||||
return inf_eps_rational<inf_rational>::infinity();
|
return inf_eps::infinity();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace smt {
|
||||||
class theory_opt {
|
class theory_opt {
|
||||||
public:
|
public:
|
||||||
typedef inf_eps_rational<inf_rational> inf_eps;
|
typedef inf_eps_rational<inf_rational> inf_eps;
|
||||||
|
virtual inf_eps value(theory_var) = 0;
|
||||||
virtual inf_eps maximize(theory_var v, expr_ref& blocker) = 0;
|
virtual inf_eps maximize(theory_var v, expr_ref& blocker) = 0;
|
||||||
virtual theory_var add_objective(app* term) = 0;
|
virtual theory_var add_objective(app* term) = 0;
|
||||||
virtual expr* mk_ge(filter_model_converter& fm, theory_var v, inf_eps const& val) { UNREACHABLE(); return 0; }
|
virtual expr* mk_ge(filter_model_converter& fm, theory_var v, inf_eps const& val) { UNREACHABLE(); return 0; }
|
||||||
|
|
|
@ -97,6 +97,35 @@ struct param_descrs::imp {
|
||||||
return CPK_INVALID;
|
return CPK_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool split_name(symbol const& name, symbol & prefix, symbol & suffix) const {
|
||||||
|
if (name.is_numerical()) return false;
|
||||||
|
char const* str = name.bare_str();
|
||||||
|
char const* period = strchr(str,'.');
|
||||||
|
if (!period) return false;
|
||||||
|
svector<char> prefix_((unsigned)(period-str), str);
|
||||||
|
prefix_.push_back(0);
|
||||||
|
prefix = symbol(prefix_.c_ptr());
|
||||||
|
suffix = symbol(period + 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
param_kind get_kind_in_module(symbol & name) const {
|
||||||
|
param_kind k = get_kind(name);
|
||||||
|
symbol prefix, suffix;
|
||||||
|
if (k == CPK_INVALID && split_name(name, prefix, suffix)) {
|
||||||
|
k = get_kind(suffix);
|
||||||
|
if (k != CPK_INVALID) {
|
||||||
|
if (symbol(get_module(suffix)) == prefix) {
|
||||||
|
name = suffix;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
k = CPK_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
char const* get_module(symbol const& name) const {
|
char const* get_module(symbol const& name) const {
|
||||||
info i;
|
info i;
|
||||||
if (m_info.find(name, i))
|
if (m_info.find(name, i))
|
||||||
|
@ -230,6 +259,10 @@ void param_descrs::erase(char const * name) {
|
||||||
erase(symbol(name));
|
erase(symbol(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
param_kind param_descrs::get_kind_in_module(symbol & name) const {
|
||||||
|
return m_imp->get_kind_in_module(name);
|
||||||
|
}
|
||||||
|
|
||||||
param_kind param_descrs::get_kind(symbol const & name) const {
|
param_kind param_descrs::get_kind(symbol const & name) const {
|
||||||
return m_imp->get_kind(name);
|
return m_imp->get_kind(name);
|
||||||
}
|
}
|
||||||
|
@ -311,35 +344,13 @@ public:
|
||||||
void reset(symbol const & k);
|
void reset(symbol const & k);
|
||||||
void reset(char const * k);
|
void reset(char const * k);
|
||||||
|
|
||||||
bool split_name(symbol const& name, symbol & prefix, symbol & suffix) {
|
|
||||||
if (name.is_numerical()) return false;
|
|
||||||
char const* str = name.bare_str();
|
|
||||||
char const* period = strchr(str,'.');
|
|
||||||
if (!period) return false;
|
|
||||||
svector<char> prefix_((unsigned)(period-str), str);
|
|
||||||
prefix_.push_back(0);
|
|
||||||
prefix = symbol(prefix_.c_ptr());
|
|
||||||
suffix = symbol(period + 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void validate(param_descrs const & p) {
|
void validate(param_descrs const & p) {
|
||||||
svector<params::entry>::iterator it = m_entries.begin();
|
svector<params::entry>::iterator it = m_entries.begin();
|
||||||
svector<params::entry>::iterator end = m_entries.end();
|
svector<params::entry>::iterator end = m_entries.end();
|
||||||
symbol suffix, prefix;
|
symbol suffix, prefix;
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
param_kind expected = p.get_kind(it->first);
|
param_kind expected = p.get_kind_in_module(it->first);
|
||||||
if (expected == CPK_INVALID && split_name(it->first, prefix, suffix)) {
|
|
||||||
expected = p.get_kind(suffix);
|
|
||||||
if (expected != CPK_INVALID) {
|
|
||||||
if (symbol(p.get_module(suffix)) == prefix) {
|
|
||||||
it->first = suffix;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
expected = CPK_INVALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (expected == CPK_INVALID) {
|
if (expected == CPK_INVALID) {
|
||||||
std::stringstream strm;
|
std::stringstream strm;
|
||||||
strm << "unknown parameter '" << it->first.str() << "'\n";
|
strm << "unknown parameter '" << it->first.str() << "'\n";
|
||||||
|
|
|
@ -123,6 +123,7 @@ public:
|
||||||
void erase(symbol const & name);
|
void erase(symbol const & name);
|
||||||
param_kind get_kind(char const * name) const;
|
param_kind get_kind(char const * name) const;
|
||||||
param_kind get_kind(symbol const & name) const;
|
param_kind get_kind(symbol const & name) const;
|
||||||
|
param_kind get_kind_in_module(symbol & name) const;
|
||||||
char const * get_descr(char const * name) const;
|
char const * get_descr(char const * name) const;
|
||||||
char const * get_descr(symbol const & name) const;
|
char const * get_descr(symbol const & name) const;
|
||||||
char const * get_default(char const * name) const;
|
char const * get_default(char const * name) const;
|
||||||
|
|
|
@ -129,7 +129,7 @@ struct scoped_timer::imp {
|
||||||
WT_EXECUTEINTIMERTHREAD);
|
WT_EXECUTEINTIMERTHREAD);
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
// Mac OS X
|
// Mac OS X
|
||||||
m_interval = ms;
|
m_interval = ms?ms:0xFFFFFFFF;
|
||||||
if (pthread_attr_init(&m_attributes) != 0)
|
if (pthread_attr_init(&m_attributes) != 0)
|
||||||
throw default_exception("failed to initialize timer thread attributes");
|
throw default_exception("failed to initialize timer thread attributes");
|
||||||
if (pthread_cond_init(&m_condition_var, NULL) != 0)
|
if (pthread_cond_init(&m_condition_var, NULL) != 0)
|
||||||
|
|
|
@ -147,7 +147,7 @@ public:
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
if (!m_running) {
|
if (!m_running) {
|
||||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &m_start);
|
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &m_start);
|
||||||
m_running = true;
|
m_running = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,8 +155,9 @@ public:
|
||||||
void stop() {
|
void stop() {
|
||||||
if (m_running) {
|
if (m_running) {
|
||||||
struct timespec _stop;
|
struct timespec _stop;
|
||||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &_stop);
|
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &_stop);
|
||||||
m_time += (_stop.tv_sec - m_start.tv_sec) * 1000000000ull;
|
m_time += (_stop.tv_sec - m_start.tv_sec) * 1000000000ull;
|
||||||
|
if (m_time != 0 || _stop.tv_nsec >= m_start.tv_nsec)
|
||||||
m_time += (_stop.tv_nsec - m_start.tv_nsec);
|
m_time += (_stop.tv_nsec - m_start.tv_nsec);
|
||||||
m_running = false;
|
m_running = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue