mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +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"z3++.h" | ||||
| 
 | ||||
| 
 | ||||
| using namespace z3; | ||||
| 
 | ||||
| /**
 | ||||
|  |  | |||
|  | @ -90,12 +90,12 @@ int main(int argc, const char **argv) { | |||
|    | ||||
|   /* Read an interpolation problem */ | ||||
| 
 | ||||
|   int num; | ||||
|   unsigned num; | ||||
|   Z3_ast *constraints; | ||||
|   int *parents = 0; | ||||
|   unsigned *parents = 0; | ||||
|   const char *error; | ||||
|   bool ok; | ||||
|   int num_theory; | ||||
|   unsigned num_theory; | ||||
|   Z3_ast *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){ | ||||
|     /* 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 { | ||||
| 
 | ||||
|  | @ -165,7 +165,7 @@ int main(int argc, const char **argv) { | |||
|     for(int i = 0; i < num; i++){ | ||||
|       asserted[i] = constraints[i]; | ||||
|       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){ | ||||
| 	for(unsigned j = 0; j < num-1; j++) | ||||
|           /* Since we want the interpolant formulas to survive a "pop", we
 | ||||
|  |  | |||
|  | @ -74,8 +74,12 @@ 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('smtparser', ['portfolio'], 'parsers/smt') | ||||
|     add_lib('opt', ['smt', 'smtlogic_tactics', 'sls_tactic'], 'opt') | ||||
|     API_files = ['z3_api.h', 'z3_algebraic.h', 'z3_polynomial.h', 'z3_rcf.h'] | ||||
|     add_lib('api', ['portfolio', 'user_plugin', 'smtparser', 'realclosure','interp','opt'], | ||||
| #    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'], | ||||
|             includes2install=['z3.h', 'z3_v1.h', 'z3_macros.h'] + API_files) | ||||
|     add_exe('shell', ['api', 'sat', 'extra_cmds','opt'], exe_name='z3') | ||||
|     add_exe('test', ['api', 'fuzzing', 'simplex'], exe_name='test-z3', install=False) | ||||
|  |  | |||
|  | @ -108,6 +108,7 @@ INOUT       = 2 | |||
| IN_ARRAY    = 3 | ||||
| OUT_ARRAY   = 4 | ||||
| INOUT_ARRAY = 5 | ||||
| OUT_MANAGED_ARRAY  = 6 | ||||
| 
 | ||||
| # Primitive Types | ||||
| 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', | ||||
|              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', | ||||
|                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', | ||||
|                PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint',  | ||||
|                PRINT_MODE : 'ctypes.c_uint', ERROR_CODE : 'ctypes.c_uint' | ||||
|                } | ||||
| 
 | ||||
| # Mapping to .NET types | ||||
|  | @ -148,11 +149,11 @@ Type2Dotnet = { VOID : 'void', VOID_PTR : 'IntPtr', INT : 'int', UINT : 'uint', | |||
| # Mapping to Java types | ||||
| Type2Java = { VOID : 'void', VOID_PTR : 'long', INT : 'int', UINT : 'int', INT64 : 'long', UINT64 : 'long', DOUBLE : 'double', | ||||
|               STRING : 'String', STRING_PTR : 'StringPtr',  | ||||
|               BOOL : 'boolean', SYMBOL : 'long', PRINT_MODE : 'int', ERROR_CODE : 'int' } | ||||
|               BOOL : 'boolean', SYMBOL : 'long', PRINT_MODE : 'int', ERROR_CODE : 'int'} | ||||
| 
 | ||||
| Type2JavaW = { VOID : 'void', VOID_PTR : 'jlong', INT : 'jint', UINT : 'jint', INT64 : 'jlong', UINT64 : 'jlong', DOUBLE : 'jdouble', | ||||
|                STRING : 'jstring', STRING_PTR : 'jobject', | ||||
|                BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint' } | ||||
|                BOOL : 'jboolean', SYMBOL : 'jlong', PRINT_MODE : 'jint', ERROR_CODE : 'jint'} | ||||
| 
 | ||||
| 
 | ||||
| next_type_id = FIRST_OBJ_ID | ||||
|  | @ -224,6 +225,10 @@ def _out_array2(cap, sz, ty): | |||
| def _inout_array(sz, ty): | ||||
|     return (INOUT_ARRAY, ty, sz, sz); | ||||
| 
 | ||||
| def _out_managed_array(sz,ty): | ||||
|     return (OUT_MANAGED_ARRAY, ty, 0, sz) | ||||
| 
 | ||||
| 
 | ||||
| def param_kind(p): | ||||
|     return p[0] | ||||
| 
 | ||||
|  | @ -254,12 +259,12 @@ def param2dotnet(p): | |||
|             return "out IntPtr" | ||||
|         else: | ||||
|             return "[In, Out] ref %s" % type2dotnet(param_type(p)) | ||||
|     if k == IN_ARRAY: | ||||
|     elif k == IN_ARRAY: | ||||
|         return "[In] %s[]" % type2dotnet(param_type(p)) | ||||
|     if k == INOUT_ARRAY: | ||||
|     elif k == INOUT_ARRAY: | ||||
|         return "[In, Out] %s[]" % type2dotnet(param_type(p)) | ||||
|     if k == OUT_ARRAY: | ||||
|         return "[Out] %s[]" % type2dotnet(param_type(p)) | ||||
|     elif k == OUT_ARRAY or k == OUT_MANAGED_ARRAY: | ||||
|         return "[Out] out %s[]" % type2dotnet(param_type(p)) | ||||
|     else: | ||||
|         return type2dotnet(param_type(p)) | ||||
| 
 | ||||
|  | @ -268,7 +273,7 @@ def param2java(p): | |||
|     if k == OUT: | ||||
|         if param_type(p) == INT or param_type(p) == UINT: | ||||
|             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" | ||||
|         elif param_type(p) == STRING: | ||||
|             return "StringPtr" | ||||
|  | @ -276,8 +281,13 @@ def param2java(p): | |||
|             print("ERROR: unreachable code") | ||||
|             assert(False) | ||||
|             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)) | ||||
|     elif k == OUT_MANAGED_ARRAY: | ||||
|         if param_type(p) == UINT: | ||||
|             return "UIntArrayPtr" | ||||
|         else: | ||||
|             return "ObjArrayPtr" | ||||
|     else: | ||||
|         return type2java(param_type(p)) | ||||
| 
 | ||||
|  | @ -466,6 +476,8 @@ def mk_dotnet_wrappers(): | |||
|                     dotnet.write('out '); | ||||
|                 else: | ||||
|                     dotnet.write('ref ') | ||||
|             elif param_kind(param) == OUT_ARRAY or param_kind(param) == OUT_MANAGED_ARRAY: | ||||
|                 dotnet.write('out '); | ||||
|             dotnet.write('a%d' % i) | ||||
|             i = i + 1 | ||||
|         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 LongPtr { public long 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') | ||||
|     if IS_WINDOWS or os.uname()[0]=="CYGWIN": | ||||
|         java_native.write('  static { System.loadLibrary("%s"); }\n' % get_component('java').dll_name) | ||||
|  | @ -676,9 +690,11 @@ def mk_java(): | |||
|                 if param_type(param) == INT or param_type(param) == UINT: | ||||
|                     java_wrapper.write('  jenv->GetIntArrayRegion(a%s, 0, (jsize)a%s, (jint*)_a%s);\n' % (i, param_array_capacity_pos(param), i)) | ||||
|                 else: | ||||
|                     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: | ||||
|                 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 | ||||
|         # invoke procedure | ||||
|         java_wrapper.write('  ') | ||||
|  | @ -697,6 +713,8 @@ def mk_java(): | |||
|                 java_wrapper.write('&_a%s' % i) | ||||
|             elif k == OUT_ARRAY or k == IN_ARRAY or k == INOUT_ARRAY: | ||||
|                 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: | ||||
|                 java_wrapper.write('_a%s' % i) | ||||
|             else: | ||||
|  | @ -732,6 +750,8 @@ def mk_java(): | |||
|                     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('  }\n') | ||||
|             elif k == OUT_MANAGED_ARRAY: | ||||
|                 java_wrapper.write('  *(jlong**)a%s = (jlong*)_a%s;\n' % (i, i)) | ||||
|             i = i + 1 | ||||
|         # return | ||||
|         if result == STRING: | ||||
|  | @ -932,6 +952,9 @@ def def_API(name, result, params): | |||
|             elif ty == INT64: | ||||
|                 log_c.write("  I(0);\n") | ||||
|                 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: | ||||
|                 error("unsupported parameter for %s, %s" % (name, p)) | ||||
|         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) | ||||
|                 exe_c.write("in.get_int_array(%s)" % i) | ||||
|             else: | ||||
|                 error ("unsupported parameter for %s, %s" % (name, p)) | ||||
|                 error ("unsupported parameter for %s, %s" % (ty, name, p)) | ||||
|         elif kind == OUT_ARRAY: | ||||
|             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): | ||||
|                 log_c.write("P(0);") | ||||
|                 log_c.write(" }\n") | ||||
|                 log_c.write("  Ap(a%s);\n" % sz) | ||||
|                 exe_c.write("reinterpret_cast<%s*>(in.get_obj_array(%s))" % (type2str(ty), i)) | ||||
|                 log_c.write("  Ap(%s);\n" % sz_e) | ||||
|                 exe_c.write("reinterpret_cast<%s*>(in.get_obj_array(%s))" % (tstr, i)) | ||||
|             elif ty == UINT: | ||||
|                 log_c.write("U(0);") | ||||
|                 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) | ||||
|             else: | ||||
|                 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: | ||||
|             error ("unsupported parameter for %s, %s" % (name, p)) | ||||
|         i = i + 1 | ||||
|  |  | |||
|  | @ -209,7 +209,7 @@ extern "C" { | |||
|     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_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) { | ||||
|         expr * result = mk_c(c)->m().mk_ite(to_expr(t1), to_expr(t2), to_expr(t3)); | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -40,6 +40,11 @@ extern "C" { | |||
|         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); | ||||
|         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); | ||||
|     } | ||||
| 
 | ||||
|  | @ -102,6 +107,7 @@ extern "C" { | |||
|         if (!initialized) | ||||
|             init_solver(c, s); | ||||
|         to_solver_ref(s)->collect_param_descrs(descrs); | ||||
|         context_params::collect_solver_param_descrs(descrs); | ||||
|         if (!initialized) | ||||
|             to_solver(s)->m_solver = 0; | ||||
|         descrs.display(buffer); | ||||
|  | @ -119,6 +125,7 @@ extern "C" { | |||
|         if (!initialized) | ||||
|             init_solver(c, s); | ||||
|         to_solver_ref(s)->collect_param_descrs(d->m_descrs); | ||||
|         context_params::collect_solver_param_descrs(d->m_descrs); | ||||
|         if (!initialized) | ||||
|             to_solver(s)->m_solver = 0; | ||||
|         Z3_param_descrs r = of_param_descrs(d); | ||||
|  | @ -130,11 +137,16 @@ extern "C" { | |||
|         Z3_TRY; | ||||
|         LOG_Z3_solver_set_params(c, s, p); | ||||
|         RESET_ERROR_CODE(); | ||||
| 
 | ||||
|         if (to_solver(s)->m_solver) { | ||||
|             bool old_model = to_solver(s)->m_params.get_bool("model", true); | ||||
|             bool new_model = to_param_ref(p).get_bool("model", true); | ||||
|             if (old_model != 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(s)->m_params = to_param_ref(p); | ||||
|  |  | |||
|  | @ -450,6 +450,9 @@ extern "C" { | |||
|         Z3_TRY; | ||||
|         LOG_Z3_tactic_apply_ex(c, t, g, p); | ||||
|         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)); | ||||
|         RETURN_Z3(r); | ||||
|         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; } | ||||
|     }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Z3 global configuration object. | ||||
|     */ | ||||
|  | @ -269,8 +271,9 @@ namespace z3 { | |||
|         object(object const & s):m_ctx(s.m_ctx) {} | ||||
|         context & ctx() const { return *m_ctx; } | ||||
|         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 { | ||||
|         Z3_symbol m_sym; | ||||
|  | @ -282,7 +285,7 @@ namespace z3 { | |||
|         Z3_symbol_kind kind() const { return Z3_get_symbol_kind(ctx(), m_sym); } | ||||
|         std::string str() const { assert(kind() == Z3_STRING_SYMBOL); return Z3_get_symbol_string(ctx(), m_sym); } | ||||
|         int to_int() const { assert(kind() == Z3_INT_SYMBOL); return Z3_get_symbol_int(ctx(), m_sym); } | ||||
|         friend std::ostream & operator<<(std::ostream & out, symbol const & s) {  | ||||
|         friend std::ostream & operator<<(std::ostream & out, symbol const & s) { | ||||
|             if (s.kind() == Z3_INT_SYMBOL) | ||||
|                 out << "k!" << s.to_int(); | ||||
|             else | ||||
|  | @ -291,6 +294,7 @@ namespace z3 { | |||
|         } | ||||
|     }; | ||||
| 
 | ||||
| 
 | ||||
|     class params : public object { | ||||
|         Z3_params m_params; | ||||
|     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, 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); } | ||||
|         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 { | ||||
|  | @ -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; } | ||||
|         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; } | ||||
|         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. | ||||
|         */ | ||||
|         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. | ||||
|     */ | ||||
|  | @ -570,6 +581,7 @@ namespace z3 { | |||
|             return expr(a.ctx(), r); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         /**
 | ||||
|            \brief Return an expression representing <tt>a and b</tt>. | ||||
| 
 | ||||
|  | @ -585,6 +597,7 @@ namespace z3 { | |||
|             return expr(a.ctx(), r); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         /**
 | ||||
|            \brief Return an expression representing <tt>a and b</tt>. | ||||
|            The C++ Boolean value \c b is automatically converted into a Z3 Boolean constant. | ||||
|  | @ -636,21 +649,10 @@ namespace z3 { | |||
|             a.check_error(); | ||||
|             return expr(a.ctx(), r); | ||||
|         } | ||||
|         friend expr implies(expr const & a, bool b) { return implies(a, a.ctx().bool_val(b)); } | ||||
|         friend expr implies(bool a, expr const & b) { return implies(b.ctx().bool_val(a), b); } | ||||
|         friend expr implies(expr const & a, bool b); | ||||
|         friend expr implies(bool a, expr const & b); | ||||
| 
 | ||||
|         /**
 | ||||
|            \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 ite(expr const & c, expr const & t, expr const & e); | ||||
| 
 | ||||
|         friend expr distinct(expr_vector const& args); | ||||
| 
 | ||||
|  | @ -716,15 +718,9 @@ namespace z3 { | |||
|         /**
 | ||||
|            \brief Power operator | ||||
|         */ | ||||
|         friend 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); | ||||
|         } | ||||
|         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 pw(expr const & a, expr const & b); | ||||
|         friend expr pw(expr const & a, int b); | ||||
|         friend expr pw(int a, expr const & b); | ||||
| 
 | ||||
|         friend expr operator/(expr const & a, expr const & b) { | ||||
|             check_context(a, b); | ||||
|  | @ -891,6 +887,38 @@ namespace z3 { | |||
|         expr substitute(expr_vector const& dst); | ||||
| 
 | ||||
|    }; | ||||
| 
 | ||||
|     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. | ||||
|  | @ -1404,22 +1432,28 @@ namespace z3 { | |||
|             t1.check_error(); | ||||
|             return tactic(t1.ctx(), r); | ||||
|         } | ||||
|         friend tactic repeat(tactic const & t, unsigned max=UINT_MAX) { | ||||
|             Z3_tactic r = Z3_tactic_repeat(t.ctx(), t, max); | ||||
|             t.check_error(); | ||||
|             return tactic(t.ctx(), r); | ||||
|         } | ||||
|         friend tactic with(tactic const & t, params const & p) { | ||||
|             Z3_tactic r = Z3_tactic_using_params(t.ctx(), t, p); | ||||
|             t.check_error(); | ||||
|             return tactic(t.ctx(), r); | ||||
|         } | ||||
|         friend tactic try_for(tactic const & t, unsigned ms) { | ||||
|             Z3_tactic r = Z3_tactic_try_for(t.ctx(), t, ms); | ||||
|             t.check_error(); | ||||
|             return tactic(t.ctx(), r); | ||||
|         } | ||||
|         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); | ||||
|         t.check_error(); | ||||
|         return tactic(t.ctx(), r); | ||||
|     } | ||||
| 
 | ||||
|     inline tactic with(tactic const & t, params const & p) { | ||||
|         Z3_tactic r = Z3_tactic_using_params(t.ctx(), t, p); | ||||
|         t.check_error(); | ||||
|         return tactic(t.ctx(), r); | ||||
|     } | ||||
|     inline tactic try_for(tactic const & t, unsigned ms) { | ||||
|         Z3_tactic r = Z3_tactic_try_for(t.ctx(), t, ms); | ||||
|         t.check_error(); | ||||
|         return tactic(t.ctx(), r); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     class probe : public object { | ||||
|         Z3_probe m_probe; | ||||
|  |  | |||
|  | @ -50,7 +50,7 @@ namespace Microsoft.Z3 | |||
|                 IntPtr constructor = IntPtr.Zero; | ||||
|                 IntPtr tester = IntPtr.Zero; | ||||
|                 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);                 | ||||
|             } | ||||
|         } | ||||
|  | @ -66,7 +66,7 @@ namespace Microsoft.Z3 | |||
|                 IntPtr constructor = IntPtr.Zero; | ||||
|                 IntPtr tester = IntPtr.Zero; | ||||
|                 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);                 | ||||
|             } | ||||
|         } | ||||
|  | @ -82,7 +82,7 @@ namespace Microsoft.Z3 | |||
|                 IntPtr constructor = IntPtr.Zero; | ||||
|                 IntPtr tester = IntPtr.Zero; | ||||
|                 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]; | ||||
|                 for (uint i = 0; i < n; i++) | ||||
|                     t[i] = new FuncDecl(Context, accessors[i]);  | ||||
|  |  | |||
|  | @ -424,7 +424,7 @@ namespace Microsoft.Z3 | |||
|                 n_constr[i] = cla[i].NativeObject; | ||||
|             } | ||||
|             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]; | ||||
|             for (uint i = 0; i < n; i++) | ||||
|                 res[i] = new DatatypeSort(this, n_res[i]); | ||||
|  |  | |||
|  | @ -78,7 +78,7 @@ namespace Microsoft.Z3 | |||
|                 IntPtr[] native_core = new IntPtr[assumptions.Length]; | ||||
|                 r = (Z3_lbool)Native.Z3_check_assumptions(ctx.nCtx,  | ||||
|                                    (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++) | ||||
|                     core.Add((BoolExpr)Expr.Create(ctx, native_core[i])); | ||||
|  |  | |||
|  | @ -88,7 +88,7 @@ namespace Microsoft.Z3 | |||
|             IntPtr[] n_constdecls = new IntPtr[n]; | ||||
|             IntPtr[] n_testers = new IntPtr[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 | ||||
|     }; | ||||
|  |  | |||
|  | @ -323,6 +323,14 @@ namespace Microsoft.Z3 | |||
| 
 | ||||
|         #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 | ||||
|         /// <summary> | ||||
|         /// Indicates whether the term is of integer sort. | ||||
|  | @ -791,7 +799,7 @@ namespace Microsoft.Z3 | |||
|         /// </summary> | ||||
|         /// <remarks>A label literal has a set of string parameters. It takes no arguments.</remarks> | ||||
|         public bool IsLabelLit { get { return IsApp && FuncDecl.DeclKind == Z3_decl_kind.Z3_OP_LABEL_LIT; } } | ||||
|         #endregion | ||||
|         #endregion         | ||||
| 
 | ||||
|         #region Proof Terms | ||||
|         /// <summary> | ||||
|  |  | |||
							
								
								
									
										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> | ||||
|     <DebugType>full</DebugType> | ||||
|     <Optimize>false</Optimize> | ||||
|     <OutputPath>..\Debug\</OutputPath> | ||||
|     <OutputPath>..\..\..\..\..\cwinter\bugs\z3bugs\Debug\</OutputPath> | ||||
|     <DefineConstants>DEBUG;TRACE</DefineConstants> | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||||
|     <DocumentationFile>..\Debug\Microsoft.Z3.XML</DocumentationFile> | ||||
|     <DocumentationFile>C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML</DocumentationFile> | ||||
|     <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking> | ||||
|     <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface> | ||||
|     <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure> | ||||
|  | @ -254,7 +254,7 @@ | |||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'"> | ||||
|     <DebugSymbols>true</DebugSymbols> | ||||
|     <OutputPath>bin\x86\Debug\</OutputPath> | ||||
|     <OutputPath>..\..\..\..\..\cwinter\bugs\z3bugs\Debug\</OutputPath> | ||||
|     <DefineConstants>DEBUG;TRACE</DefineConstants> | ||||
|     <AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||||
|     <DebugType>full</DebugType> | ||||
|  | @ -266,7 +266,7 @@ | |||
|     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> | ||||
|     <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> | ||||
|     <DocumentationFile>bin\x86\Debug\Microsoft.Z3.XML</DocumentationFile> | ||||
|     <DocumentationFile>C:\cwinter\bugs\z3bugs\Debug\Microsoft.Z3.XML</DocumentationFile> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'"> | ||||
|     <OutputPath>bin\x86\Release\</OutputPath> | ||||
|  | @ -352,6 +352,7 @@ | |||
|     <Compile Include="FuncDecl.cs" /> | ||||
|     <Compile Include="FuncInterp.cs" /> | ||||
|     <Compile Include="Goal.cs" /> | ||||
|     <Compile Include="InterpolationContext.cs" /> | ||||
|     <Compile Include="IntExpr.cs" /> | ||||
|     <Compile Include="IntNum.cs" /> | ||||
|     <Compile Include="IntSort.cs" /> | ||||
|  |  | |||
|  | @ -58,6 +58,16 @@ namespace Microsoft.Z3 | |||
|             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> | ||||
|         /// Adds a parameter setting. | ||||
|         /// </summary> | ||||
|  |  | |||
|  | @ -74,9 +74,10 @@ namespace Microsoft.Z3 | |||
|             Contract.Requires(name != null); | ||||
| 
 | ||||
|             IntPtr t = IntPtr.Zero; | ||||
|             IntPtr[] f; | ||||
|             NativeObject = Native.Z3_mk_tuple_sort(ctx.nCtx, name.NativeObject, numFields, | ||||
|                                                    Symbol.ArrayToNative(fieldNames), AST.ArrayToNative(fieldSorts), | ||||
|                                                    ref t, new IntPtr[numFields]); | ||||
|                                                    ref t, out f); | ||||
|         } | ||||
|         #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));      | ||||
|     } | ||||
| } | ||||
|  | @ -28,6 +28,17 @@ public class Params extends Z3Object | |||
|         Native.paramsSetDouble(getContext().nCtx(), getNativeObject(), | ||||
|                 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. | ||||
|  | @ -75,6 +86,17 @@ public class Params extends Z3Object | |||
|                 .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. | ||||
|      **/ | ||||
|  |  | |||
|  | @ -7426,19 +7426,19 @@ def parse_smt2_file(f, sorts={}, decls={}, ctx=None): | |||
|     dsz, dnames, ddecls = _dict2darray(decls, 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. | ||||
|      | ||||
|     The argument is an interpolation pattern (see tree_interpolant).  | ||||
| 
 | ||||
|     >>> x = Int('x') | ||||
|     >>> print Interp(x>0) | ||||
|     >>> print Interpolant(x>0) | ||||
|     interp(x > 0) | ||||
|     """ | ||||
|     ctx = _get_ctx(_ctx_from_ast_arg_list([a], ctx)) | ||||
|     s = BoolSort(ctx) | ||||
|     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): | ||||
|     """Compute interpolant for a tree of formulas. | ||||
|  | @ -7477,10 +7477,10 @@ def tree_interpolant(pat,p=None,ctx=None): | |||
| 
 | ||||
|     >>> x = Int('x') | ||||
|     >>> 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)] | ||||
| 
 | ||||
|     >>> g = And(Interp(x<0),x<2) | ||||
|     >>> g = And(Interpolant(x<0),x<2) | ||||
|     >>> try: | ||||
|     ...     print tree_interpolant(g).sexpr() | ||||
|     ... except ModelRef as m: | ||||
|  | @ -7519,7 +7519,7 @@ def binary_interpolant(a,b,p=None,ctx=None): | |||
|     print binary_interpolant(x<0,x>2) | ||||
|     Not(x >= 0) | ||||
|     """ | ||||
|     f = And(Interp(a),b) | ||||
|     f = And(Interpolant(a),b) | ||||
|     return tree_interpolant(f,p,ctx)[0] | ||||
| 
 | ||||
| def sequence_interpolant(v,p=None,ctx=None): | ||||
|  | @ -7548,6 +7548,6 @@ def sequence_interpolant(v,p=None,ctx=None): | |||
|     """ | ||||
|     f = v[0] | ||||
|     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) | ||||
| 
 | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ Notes: | |||
| #include"z3_algebraic.h" | ||||
| #include"z3_polynomial.h" | ||||
| #include"z3_rcf.h" | ||||
| #include"z3_interp.h" | ||||
| 
 | ||||
| #undef __in | ||||
| #undef __out | ||||
|  |  | |||
							
								
								
									
										336
									
								
								src/api/z3_api.h
									
										
									
									
									
								
							
							
						
						
									
										336
									
								
								src/api/z3_api.h
									
										
									
									
									
								
							|  | @ -1796,7 +1796,7 @@ extern "C" { | |||
|     Z3_sort Z3_API Z3_mk_tuple_sort(__in Z3_context c,  | ||||
|                                         __in Z3_symbol mk_tuple_name,  | ||||
|                                         __in unsigned num_fields,  | ||||
|                                         __in_ecount(num_fields) Z3_symbol   const field_names[], | ||||
|                                         __in_ecount(num_fields) Z3_symbol const field_names[], | ||||
|                                         __in_ecount(num_fields) Z3_sort const field_sorts[], | ||||
|                                         __out Z3_func_decl * mk_tuple_decl, | ||||
|                                         __out_ecount(num_fields)  Z3_func_decl proj_decl[]); | ||||
|  | @ -2133,17 +2133,7 @@ END_MLAPI_EXCLUDE | |||
|         def_API('Z3_mk_not', AST, (_in(CONTEXT), _in(AST))) | ||||
|     */ | ||||
|     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  | ||||
|        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 unsigned num_decls, | ||||
|                                           __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. | ||||
|  | @ -4967,13 +4956,12 @@ END_MLAPI_EXCLUDE | |||
|     */ | ||||
|     Z3_ast Z3_API Z3_parse_smtlib2_file(__in Z3_context c,  | ||||
|                                         __in Z3_string file_name, | ||||
|                                           __in unsigned num_sorts, | ||||
|                                           __in_ecount(num_sorts) Z3_symbol const sort_names[], | ||||
|                                           __in_ecount(num_sorts) Z3_sort const sorts[], | ||||
|                                           __in unsigned num_decls, | ||||
|                                           __in_ecount(num_decls) Z3_symbol const decl_names[], | ||||
|                                           __in_ecount(num_decls) Z3_func_decl const decls[]     | ||||
|                                         ); | ||||
|                                         __in unsigned num_sorts, | ||||
|                                         __in_ecount(num_sorts) Z3_symbol const sort_names[], | ||||
|                                         __in_ecount(num_sorts) Z3_sort const sorts[], | ||||
|                                         __in unsigned num_decls, | ||||
|                                         __in_ecount(num_decls) Z3_symbol const decl_names[], | ||||
|                                         __in_ecount(num_decls) Z3_func_decl const decls[]); | ||||
| 
 | ||||
| #ifdef ML4only | ||||
| #include <mlx_parse_smtlib.idl> | ||||
|  | @ -7931,314 +7919,6 @@ END_MLAPI_EXCLUDE | |||
|     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 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										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_bv_rw.updt_params(p); | ||||
|         m_ar_rw.updt_params(p); | ||||
|         m_f_rw.updt_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("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("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("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("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("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("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) { | ||||
|  |  | |||
|  | @ -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); | ||||
| 
 | ||||
|     static void collect_solver_param_descrs(param_descrs & d); | ||||
| 
 | ||||
|     /**
 | ||||
|        \brief Include in p parameters derived from this context_params. | ||||
|        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()); | ||||
|         c = n->get_child(i); | ||||
|         i++; | ||||
|         switch (descrs.get_kind(param_name)) { | ||||
|         switch (descrs.get_kind_in_module(param_name)) { | ||||
|         case CPK_INVALID: | ||||
|             throw cmd_exception("invalid using-params combinator, unknown parameter ", param_name, c->get_line(), c->get_pos()); | ||||
|         case CPK_BOOL: | ||||
|  |  | |||
|  | @ -257,7 +257,7 @@ namespace pdr { | |||
|         void enqueue_leaf(model_node& n); // add leaf to priority queue.
 | ||||
|         void update_models(); | ||||
|     public: | ||||
|         model_search(bool bfs):  m_bfs(bfs), m_root(0) {} | ||||
|         model_search(bool bfs): m_bfs(bfs), m_root(0) {} | ||||
|         ~model_search(); | ||||
| 
 | ||||
|         void reset(); | ||||
|  |  | |||
|  | @ -161,17 +161,27 @@ namespace opt { | |||
| 
 | ||||
|     void opt_solver::maximize_objectives(expr_ref_vector& blockers) { | ||||
|         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) { | ||||
|             maximize_objective(i, 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) { | ||||
|         smt::theory_var v = m_objective_vars[i]; | ||||
|         m_objective_values[i] = get_optimizer().maximize(v, blocker); | ||||
|         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) { | ||||
|  | @ -232,10 +242,16 @@ namespace opt { | |||
|         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]; | ||||
|     } | ||||
| 
 | ||||
|     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) { | ||||
|         smt::theory_opt& opt = get_optimizer(); | ||||
|         smt::theory_var v = m_objective_vars[var]; | ||||
|  |  | |||
|  | @ -107,9 +107,10 @@ namespace opt { | |||
|         void reset_objectives(); | ||||
|         void maximize_objective(unsigned i, expr_ref& blocker); | ||||
|         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(); | ||||
|         inf_eps const & get_objective_value(unsigned obj_index); | ||||
|         expr_ref mk_ge(unsigned obj_index, inf_eps const& val); | ||||
| 
 | ||||
|         static opt_solver& to_opt(solver& s); | ||||
|  |  | |||
|  | @ -46,12 +46,21 @@ namespace opt { | |||
|         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) { | ||||
|             if (src[i] > dst[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(); | ||||
|                     m_s->maximize_objectives(disj); | ||||
|                     m_s->get_model(m_model);                    | ||||
|                     set_max(m_lower, m_s->get_objective_values());  | ||||
|                     for (unsigned i = 0; i < ors.size(); ++i) { | ||||
|                         expr_ref tmp(m); | ||||
|                         m_model->eval(ors[i].get(), tmp); | ||||
|                         if (m.is_true(tmp)) { | ||||
|                             m_lower[i] = m_upper[i]; | ||||
|                             ors[i] = m.mk_false(); | ||||
|                         } | ||||
|                         if (m.is_false(ors[i].get())) { | ||||
|                             ors[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()); | ||||
|                     bound = m.mk_or(disj.size(), disj.c_ptr()); | ||||
|                     m_s->assert_expr(or); | ||||
|                 } | ||||
|                 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); | ||||
|          | ||||
|         if (m_cancel) { | ||||
|  | @ -177,9 +184,9 @@ namespace opt { | |||
| 
 | ||||
|     void optsmt::update_lower() { | ||||
|         expr_ref_vector disj(m); | ||||
|         m_s->maximize_objectives(disj); | ||||
|         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", | ||||
|               for (unsigned i = 0; i < m_lower.size(); ++i) { | ||||
|                   tout << m_lower[i] << " "; | ||||
|  | @ -192,11 +199,8 @@ namespace opt { | |||
|                        verbose_stream() << m_lower[i] << " "; | ||||
|                    } | ||||
|                    verbose_stream() << ")\n";); | ||||
|         for (unsigned i = 0; i < m_lower.size(); ++i) { | ||||
|             if (m_lower[i].is_pos() && !m_lower[i].is_finite()) { | ||||
|                 disj[i] = m.mk_false(); | ||||
|             } | ||||
|         } | ||||
|         IF_VERBOSE(3, verbose_stream() << disj << "\n";); | ||||
|         IF_VERBOSE(3, model_pp(verbose_stream(), *m_model);); | ||||
| 
 | ||||
|         expr_ref constraint(m);         | ||||
|         constraint = m.mk_or(disj.size(), disj.c_ptr()); | ||||
|  | @ -309,7 +313,7 @@ namespace opt { | |||
|              | ||||
|             m_s->maximize_objective(obj_index, block); | ||||
|             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]) { | ||||
|                 m_lower[obj_index] = obj;                 | ||||
|                 IF_VERBOSE(1,  | ||||
|  | @ -320,7 +324,7 @@ namespace opt { | |||
|                            ); | ||||
|                 for (unsigned i = obj_index+1; i < m_vars.size(); ++i) { | ||||
|                     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); | ||||
|  | @ -401,6 +405,7 @@ namespace opt { | |||
|         m_objs.push_back(to_app(t2)); | ||||
|         m_lower.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; | ||||
|     } | ||||
| 
 | ||||
|  | @ -415,6 +420,7 @@ namespace opt { | |||
|         m_objs.reset(); | ||||
|         m_vars.reset(); | ||||
|         m_model.reset(); | ||||
|         m_lower_fmls.reset(); | ||||
|         m_s = 0; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -34,11 +34,13 @@ namespace opt { | |||
|         vector<inf_eps>  m_lower; | ||||
|         vector<inf_eps>  m_upper; | ||||
|         app_ref_vector   m_objs; | ||||
|         expr_ref_vector  m_lower_fmls; | ||||
|         svector<smt::theory_var> m_vars; | ||||
|         symbol           m_optsmt_engine; | ||||
|         model_ref        m_model; | ||||
|     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); | ||||
| 
 | ||||
|  | @ -73,7 +75,7 @@ namespace 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(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -2238,8 +2238,7 @@ namespace qe { | |||
|         m_params(p), | ||||
|         m_trail(m), | ||||
|         m_qe(0), | ||||
|         m_assumption(m.mk_true()), | ||||
|         m_use_new_qe(true) | ||||
|         m_assumption(m.mk_true()) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|  | @ -2261,12 +2260,6 @@ namespace qe { | |||
|     } | ||||
| 
 | ||||
|     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(); | ||||
|         m_qe->updt_params(p); | ||||
|     } | ||||
|  | @ -2274,7 +2267,6 @@ namespace qe { | |||
|     void expr_quant_elim::collect_param_descrs(param_descrs& r) { | ||||
|         r.insert("eliminate_variables_as_block", CPK_BOOL,  | ||||
|                  "(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() { | ||||
|  | @ -2517,6 +2509,10 @@ namespace qe { | |||
|             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(); }     | ||||
|          | ||||
|         void solve(expr_ref& fml, app_ref_vector& vars) { | ||||
|  | @ -2607,6 +2603,10 @@ namespace qe { | |||
|     public: | ||||
|         impl(ast_manager& m) : m(m), m_ctx(m) {} | ||||
| 
 | ||||
|         void updt_params(params_ref const& p) { | ||||
|             m_ctx.updt_params(p); | ||||
|         } | ||||
| 
 | ||||
|         bool reduce_quantifier( | ||||
|             quantifier * old_q,  | ||||
|             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); | ||||
|     } | ||||
| 
 | ||||
|     void simplify_rewriter_cfg::updt_params(params_ref const& p) { | ||||
|         imp->updt_params(p); | ||||
|     } | ||||
| 
 | ||||
|     bool simplify_rewriter_cfg::pre_visit(expr* e) { | ||||
|         if (!is_quantifier(e)) return true; | ||||
|         quantifier * q = to_quantifier(e); | ||||
|  | @ -2677,7 +2681,6 @@ namespace qe { | |||
|     } | ||||
|      | ||||
|     void simplify_exists(app_ref_vector& vars, expr_ref& fml) { | ||||
|         smt_params params; | ||||
|         ast_manager& m = fml.get_manager(); | ||||
|         simplify_solver_context ctx(m); | ||||
|         ctx.solve(fml, vars);        | ||||
|  |  | |||
|  | @ -275,13 +275,12 @@ namespace qe { | |||
| 
 | ||||
|     class expr_quant_elim { | ||||
|         ast_manager&            m; | ||||
|         smt_params const& m_fparams; | ||||
|         smt_params const&       m_fparams; | ||||
|         params_ref              m_params; | ||||
|         expr_ref_vector         m_trail; | ||||
|         obj_map<expr,expr*>     m_visited; | ||||
|         quant_elim*             m_qe; | ||||
|         expr*                   m_assumption; | ||||
|         bool                    m_use_new_qe; | ||||
|     public: | ||||
|         expr_quant_elim(ast_manager& m, smt_params const& fp, params_ref const& p = params_ref()); | ||||
|         ~expr_quant_elim();  | ||||
|  | @ -372,6 +371,8 @@ namespace qe { | |||
|          | ||||
|         bool pre_visit(expr* e); | ||||
| 
 | ||||
|         void updt_params(params_ref const& p); | ||||
| 
 | ||||
|     }; | ||||
|      | ||||
|     class simplify_rewriter_star : public rewriter_tpl<simplify_rewriter_cfg> { | ||||
|  | @ -380,6 +381,8 @@ namespace qe { | |||
|         simplify_rewriter_star(ast_manager& m): | ||||
|             rewriter_tpl<simplify_rewriter_cfg>(m, false, m_cfg), | ||||
|             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; | ||||
|         mk_atom_default         m_mk_atom; | ||||
|         th_rewriter             m_rewriter; | ||||
|         simplify_rewriter_star  m_qe_rw; | ||||
|         expr_strong_context_simplifier m_ctx_rewriter; | ||||
| 
 | ||||
|         class solver_context : public i_solver_context { | ||||
|  | @ -218,6 +219,7 @@ namespace qe { | |||
|             m_Ms(m), | ||||
|             m_assignments(m), | ||||
|             m_rewriter(m), | ||||
|             m_qe_rw(m), | ||||
|             m_ctx_rewriter(m_fparams, m) {             | ||||
|             m_fparams.m_model = true; | ||||
|         } | ||||
|  | @ -256,10 +258,9 @@ namespace qe { | |||
|                 ptr_vector<expr> fmls; | ||||
|                 goal->get_formulas(fmls); | ||||
|                 m_fml = m.mk_and(fmls.size(), fmls.c_ptr()); | ||||
|                 TRACE("qe", tout << "input: " << mk_pp(m_fml,m) << "\n";); | ||||
|                 simplify_rewriter_star rw(m); | ||||
|                 TRACE("qe", tout << "input: " << mk_pp(m_fml,m) << "\n";);                | ||||
|                 expr_ref tmp(m); | ||||
|                 rw(m_fml, tmp); | ||||
|                 m_qe_rw(m_fml, tmp); | ||||
|                 m_fml = tmp; | ||||
|                 TRACE("qe", tout << "reduced: " << mk_pp(m_fml,m) << "\n";); | ||||
|                 skolemize_existential_prefix(); | ||||
|  | @ -305,6 +306,8 @@ namespace qe { | |||
|             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_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) { | ||||
|  |  | |||
|  | @ -36,6 +36,7 @@ class qe_tactic : public tactic { | |||
|         } | ||||
| 
 | ||||
|         void updt_params(params_ref const & p) { | ||||
|             m_fparams.updt_params(p); | ||||
|             m_fparams.m_nlquant_elim = p.get_bool("qe_nonlinear", false); | ||||
|             m_qe.updt_params(p); | ||||
|         } | ||||
|  |  | |||
|  | @ -1426,7 +1426,6 @@ namespace sat { | |||
| 
 | ||||
|     void simplifier::elim_vars() { | ||||
|         if (!m_elim_vars) return; | ||||
|          | ||||
|         elim_var_report rpt(*this); | ||||
|         bool_var_vector vars; | ||||
|         order_vars_for_elim(vars); | ||||
|  |  | |||
|  | @ -19,10 +19,11 @@ Revision History: | |||
| #include"smt_params.h" | ||||
| #include"smt_params_helper.hpp" | ||||
| #include"model_params.hpp" | ||||
| #include"gparams.h" | ||||
| 
 | ||||
| void smt_params::updt_local_params(params_ref const & _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_relevancy_lvl = p.relevancy(); | ||||
|     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> value(theory_var v); | ||||
|         virtual theory_var add_objective(app* term); | ||||
|         virtual expr* mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val); | ||||
|         void enable_record_conflict(expr* bound); | ||||
|  |  | |||
|  | @ -1059,7 +1059,6 @@ namespace smt { | |||
|     theory_var theory_arith<Ext>::add_objective(app* term) { | ||||
|         theory_var v = internalize_term_core(term); | ||||
|         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)); | ||||
|         if (!is_linear(get_manager(), term)) { | ||||
|             v = null_theory_var; | ||||
|  | @ -1067,6 +1066,11 @@ namespace smt { | |||
|         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> | ||||
|     inf_eps_rational<inf_rational> theory_arith<Ext>::maximize(theory_var v, expr_ref& blocker) { | ||||
|         TRACE("bound_bug", display_var(tout, v); display(tout);); | ||||
|  | @ -1533,12 +1537,14 @@ namespace smt { | |||
|     */ | ||||
|     template<typename Ext> | ||||
|     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(satisfy_bounds()); | ||||
|         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...
 | ||||
|         } | ||||
|         m_tmp_row.reset(); | ||||
|         if (is_non_base(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); | ||||
|         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);); | ||||
|              | ||||
|             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; | ||||
|     } | ||||
|  |  | |||
|  | @ -53,6 +53,7 @@ namespace smt { | |||
|         unsigned bv_size      = get_bv_size(n); | ||||
|         context & ctx         = get_context(); | ||||
|         literal_vector & bits = m_bits[v]; | ||||
|         bits.reset(); | ||||
|         for (unsigned i = 0; i < bv_size; i++) { | ||||
|             app * bit  = mk_bit2bool(owner, i); | ||||
|             ctx.internalize(bit, true); | ||||
|  | @ -75,12 +76,14 @@ namespace smt { | |||
|     void theory_bv::mk_bit2bool(app * n) { | ||||
|         context & ctx    = get_context(); | ||||
|         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
 | ||||
|             // clause that is being reinitialized, and x was not reinitialized
 | ||||
|             // yet.
 | ||||
|             // So, we internalize x (i.e., n->get_arg(0))
 | ||||
|             expr * first_arg = n->get_arg(0); | ||||
|             // So, we internalize x (i.e., arg)
 | ||||
|             ctx.internalize(first_arg, false); | ||||
|             SASSERT(ctx.e_internalized(first_arg)); | ||||
|             // 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.
 | ||||
|             enode * first_arg_enode = ctx.get_enode(first_arg); | ||||
|             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 { | ||||
|             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.
 | ||||
|             // For example, for ite-terms the method apply_sort_cnstr is not invoked.
 | ||||
|             // See comment in the then-branch.
 | ||||
|  | @ -1041,6 +1061,7 @@ namespace smt { | |||
| 
 | ||||
|     void theory_bv::new_diseq_eh(theory_var v1, theory_var v2) { | ||||
|         if (is_bv(v1)) { | ||||
|             SASSERT(m_bits[v1].size() == m_bits[v2].size()); | ||||
|             expand_diseq(v1, v2); | ||||
|         } | ||||
|     } | ||||
|  | @ -1381,6 +1402,7 @@ namespace smt { | |||
|             if (v1 != null_theory_var) { | ||||
|                 // 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].size() == m_bits[v2].size()); | ||||
|                 mk_new_diseq_axiom(v1, v2, it->m_idx); | ||||
|                 RESET_MERGET_AUX(); | ||||
|                 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> value(theory_var v); | ||||
|         virtual theory_var add_objective(app* term); | ||||
|         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; } | ||||
|  |  | |||
|  | @ -875,6 +875,19 @@ namespace smt { | |||
|         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> | ||||
|     inf_eps_rational<inf_rational> theory_dense_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker) { | ||||
|         typedef simplex::simplex<simplex::mpq_ext> Simplex; | ||||
|  |  | |||
|  | @ -65,6 +65,7 @@ namespace smt { | |||
|          | ||||
|         typedef typename Ext::numeral numeral; | ||||
|         typedef simplex::simplex<simplex::mpq_ext> Simplex; | ||||
|         typedef inf_eps_rational<inf_rational> inf_eps; | ||||
| 
 | ||||
|         class atom { | ||||
|             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 expr_ref mk_gt(theory_var v, inf_rational const& val); | ||||
|         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> | ||||
| unsigned theory_diff_logic<Ext>::node2simplex(unsigned v) { | ||||
|     //return v;
 | ||||
|     return m_objectives.size() + 2*v + 1; | ||||
| } | ||||
| template<typename Ext> | ||||
| unsigned theory_diff_logic<Ext>::edge2simplex(unsigned e) { | ||||
|     //return m_graph.get_num_nodes() + e;
 | ||||
|     return m_objectives.size() + 2*e; | ||||
| } | ||||
| template<typename Ext> | ||||
| unsigned theory_diff_logic<Ext>::obj2simplex(unsigned e) { | ||||
|     //return m_graph.get_num_nodes() + m_graph.get_num_edges() + e;
 | ||||
|     return e; | ||||
| } | ||||
| 
 | ||||
| template<typename Ext> | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| template<typename Ext> | ||||
| 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; | ||||
|     e -= m_objectives.size(); | ||||
|     return (0 == (e & 0x1)); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| template<typename Ext>  | ||||
| unsigned theory_diff_logic<Ext>::simplex2edge(unsigned e) { | ||||
|     SASSERT(is_simplex_edge(e)); | ||||
|     //return e - m_graph.get_num_nodes();
 | ||||
|     return (e - m_objectives.size())/2; | ||||
| } | ||||
| 
 | ||||
|  | @ -1184,7 +1173,21 @@ void theory_diff_logic<Ext>::update_simplex(Simplex& S) { | |||
| } | ||||
| 
 | ||||
| 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; | ||||
|     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(); | ||||
|     if (is_sat == l_undef) { | ||||
|         blocker = m.mk_false(); | ||||
|         return inf_eps_rational<inf_rational>::infinity();         | ||||
|         return inf_eps::infinity();         | ||||
|     } | ||||
|     TRACE("opt", S.display(tout); );     | ||||
|     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); | ||||
|         return inf_eps_rational<inf_rational>(rational(0), r); | ||||
|         return inf_eps(rational(0), r); | ||||
|     } | ||||
|     default: | ||||
|         TRACE("opt", tout << "unbounded\n"; );         | ||||
|         blocker = m.mk_false(); | ||||
|         return inf_eps_rational<inf_rational>::infinity();         | ||||
|         return inf_eps::infinity();         | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ namespace smt { | |||
|     class theory_opt { | ||||
|     public: | ||||
|         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 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; } | ||||
|  |  | |||
|  | @ -97,6 +97,35 @@ struct param_descrs::imp { | |||
|         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 { | ||||
|         info i; | ||||
|         if (m_info.find(name, i))  | ||||
|  | @ -230,6 +259,10 @@ void param_descrs::erase(char const * 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 { | ||||
|     return m_imp->get_kind(name); | ||||
| } | ||||
|  | @ -311,35 +344,13 @@ public: | |||
|     void reset(symbol 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) { | ||||
|         svector<params::entry>::iterator it  = m_entries.begin();   | ||||
|         svector<params::entry>::iterator end = m_entries.end(); | ||||
|         symbol suffix, prefix; | ||||
|         for (; it != end; ++it) {                                 | ||||
|             param_kind expected = p.get_kind(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; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             param_kind expected = p.get_kind_in_module(it->first); | ||||
|             if (expected == CPK_INVALID) { | ||||
|                 std::stringstream strm; | ||||
|                 strm << "unknown parameter '" << it->first.str() << "'\n";     | ||||
|  |  | |||
|  | @ -123,6 +123,7 @@ public: | |||
|     void erase(symbol const & name); | ||||
|     param_kind get_kind(char 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(symbol const & name) const; | ||||
|     char const * get_default(char const * name) const; | ||||
|  |  | |||
|  | @ -129,7 +129,7 @@ struct scoped_timer::imp { | |||
|                               WT_EXECUTEINTIMERTHREAD);	 | ||||
| #elif defined(__APPLE__) && defined(__MACH__) | ||||
|         // Mac OS X
 | ||||
|         m_interval = ms; | ||||
|         m_interval = ms?ms:0xFFFFFFFF; | ||||
|         if (pthread_attr_init(&m_attributes) != 0) | ||||
|             throw default_exception("failed to initialize timer thread attributes"); | ||||
|         if (pthread_cond_init(&m_condition_var, NULL) != 0) | ||||
|  |  | |||
|  | @ -91,7 +91,7 @@ public: | |||
|     ~stopwatch() {} | ||||
|      | ||||
|     void reset() { | ||||
| 	m_time = 0ull; | ||||
|         m_time = 0ull; | ||||
|     } | ||||
|      | ||||
|     void start() { | ||||
|  | @ -102,11 +102,11 @@ public: | |||
|     } | ||||
| 
 | ||||
|     void stop() { | ||||
| 	if (m_running) { | ||||
|         if (m_running) { | ||||
|             mach_timespec_t _stop; | ||||
|             clock_get_time(m_host_clock, &_stop); | ||||
|             m_time += (_stop.tv_sec - m_start.tv_sec) * 1000000000ull; | ||||
|             m_time += (_stop.tv_nsec - m_start.tv_nsec); | ||||
| 	    m_time += (_stop.tv_nsec - m_start.tv_nsec); | ||||
|             m_running = false; | ||||
|         } | ||||
|     } | ||||
|  | @ -121,7 +121,7 @@ public: | |||
|     } | ||||
| 
 | ||||
|     double get_current_seconds() const {  | ||||
| 	return get_seconds();  | ||||
|         return get_seconds();  | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  | @ -142,22 +142,23 @@ public: | |||
|     ~stopwatch() {} | ||||
|      | ||||
|     void reset() { | ||||
| 	m_time = 0ull; | ||||
|         m_time = 0ull; | ||||
|     } | ||||
|      | ||||
|     void start() { | ||||
|         if (!m_running) { | ||||
|             clock_gettime(CLOCK_THREAD_CPUTIME_ID, &m_start); | ||||
|             clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &m_start); | ||||
|             m_running = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void stop() { | ||||
| 	if (m_running) { | ||||
|     if (m_running) { | ||||
|             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_nsec - m_start.tv_nsec); | ||||
| 	    if (m_time != 0 || _stop.tv_nsec >= m_start.tv_nsec) | ||||
| 	      m_time += (_stop.tv_nsec - m_start.tv_nsec); | ||||
|             m_running = false; | ||||
|         } | ||||
|     } | ||||
|  | @ -172,7 +173,7 @@ public: | |||
|     } | ||||
| 
 | ||||
|     double get_current_seconds() const {  | ||||
| 	return get_seconds();  | ||||
|     return get_seconds();  | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue