| Home | • | Docs | • | Download | • | • | FAQ | • | Awards | • | Status | • | MSR |
|---|
An Efficient SMT Solver
00001 #include<stdio.h> 00002 #include<stdlib.h> 00003 #include<stdarg.h> 00004 #include<memory.h> 00005 #include<setjmp.h> 00006 #include<z3.h> 00007 00016 00020 void exitf(const char* message) 00021 { 00022 fprintf(stderr,"BUG: %s.\n", message); 00023 exit(1); 00024 } 00025 00029 void unreachable() 00030 { 00031 exitf("unreachable code was reached"); 00032 } 00033 00037 void error_handler(Z3_error_code e) 00038 { 00039 printf("Error code: %d\n", e); 00040 exitf("incorrect use of Z3"); 00041 } 00042 00043 static jmp_buf g_catch_buffer; 00049 void throw_z3_error(Z3_error_code c) 00050 { 00051 longjmp(g_catch_buffer, c); 00052 } 00053 00061 Z3_context mk_context_custom(Z3_config cfg, Z3_error_handler err) 00062 { 00063 Z3_context ctx; 00064 00065 Z3_set_param_value(cfg, "MODEL", "true"); 00066 ctx = Z3_mk_context(cfg); 00067 #ifdef TRACING 00068 Z3_trace_to_stderr(ctx); 00069 #endif 00070 Z3_set_error_handler(ctx, err); 00071 00072 return ctx; 00073 } 00074 00082 Z3_context mk_context() 00083 { 00084 Z3_config cfg; 00085 Z3_context ctx; 00086 cfg = Z3_mk_config(); 00087 ctx = mk_context_custom(cfg, error_handler); 00088 Z3_del_config(cfg); 00089 return ctx; 00090 } 00091 00100 Z3_context mk_proof_context() { 00101 Z3_config cfg = Z3_mk_config(); 00102 Z3_context ctx; 00103 Z3_set_param_value(cfg, "PROOF_MODE", "2"); 00104 ctx = mk_context_custom(cfg,throw_z3_error); 00105 Z3_del_config(cfg); 00106 return ctx; 00107 } 00108 00112 Z3_ast mk_var(Z3_context ctx, const char * name, Z3_sort ty) 00113 { 00114 Z3_symbol s = Z3_mk_string_symbol(ctx, name); 00115 return Z3_mk_const(ctx, s, ty); 00116 } 00117 00121 Z3_ast mk_bool_var(Z3_context ctx, const char * name) 00122 { 00123 Z3_sort ty = Z3_mk_bool_sort(ctx); 00124 return mk_var(ctx, name, ty); 00125 } 00126 00130 Z3_ast mk_int_var(Z3_context ctx, const char * name) 00131 { 00132 Z3_sort ty = Z3_mk_int_sort(ctx); 00133 return mk_var(ctx, name, ty); 00134 } 00135 00139 Z3_ast mk_int(Z3_context ctx, int v) 00140 { 00141 Z3_sort ty = Z3_mk_int_sort(ctx); 00142 return Z3_mk_int(ctx, v, ty); 00143 } 00144 00148 Z3_ast mk_real_var(Z3_context ctx, const char * name) 00149 { 00150 Z3_sort ty = Z3_mk_real_sort(ctx); 00151 return mk_var(ctx, name, ty); 00152 } 00153 00157 Z3_ast mk_unary_app(Z3_context ctx, Z3_func_decl f, Z3_ast x) 00158 { 00159 Z3_ast args[1] = {x}; 00160 return Z3_mk_app(ctx, f, 1, args); 00161 } 00162 00166 Z3_ast mk_binary_app(Z3_context ctx, Z3_func_decl f, Z3_ast x, Z3_ast y) 00167 { 00168 Z3_ast args[2] = {x, y}; 00169 return Z3_mk_app(ctx, f, 2, args); 00170 } 00171 00176 void check(Z3_context ctx, Z3_lbool expected_result) 00177 { 00178 Z3_model m = 0; 00179 Z3_lbool result = Z3_check_and_get_model(ctx, &m); 00180 switch (result) { 00181 case Z3_L_FALSE: 00182 printf("unsat\n"); 00183 break; 00184 case Z3_L_UNDEF: 00185 printf("unknown\n"); 00186 printf("potential model:\n%s\n", Z3_model_to_string(ctx, m)); 00187 break; 00188 case Z3_L_TRUE: 00189 printf("sat\n%s\n", Z3_model_to_string(ctx, m)); 00190 break; 00191 } 00192 if (m) { 00193 Z3_del_model(ctx, m); 00194 } 00195 if (result != expected_result) { 00196 exitf("unexpected result"); 00197 } 00198 } 00199 00210 void prove(Z3_context ctx, Z3_ast f, Z3_bool is_valid) 00211 { 00212 Z3_model m; 00213 Z3_ast not_f; 00214 00215 /* save the current state of the context */ 00216 Z3_push(ctx); 00217 00218 not_f = Z3_mk_not(ctx, f); 00219 Z3_assert_cnstr(ctx, not_f); 00220 00221 m = 0; 00222 00223 switch (Z3_check_and_get_model(ctx, &m)) { 00224 case Z3_L_FALSE: 00225 /* proved */ 00226 printf("valid\n"); 00227 if (!is_valid) { 00228 exitf("unexpected result"); 00229 } 00230 break; 00231 case Z3_L_UNDEF: 00232 /* Z3 failed to prove/disprove f. */ 00233 printf("unknown\n"); 00234 if (m != 0) { 00235 /* m should be viewed as a potential counterexample. */ 00236 printf("potential counterexample:\n%s\n", Z3_model_to_string(ctx, m)); 00237 } 00238 if (is_valid) { 00239 exitf("unexpected result"); 00240 } 00241 break; 00242 case Z3_L_TRUE: 00243 /* disproved */ 00244 printf("invalid\n"); 00245 if (m) { 00246 /* the model returned by Z3 is a counterexample */ 00247 printf("counterexample:\n%s\n", Z3_model_to_string(ctx, m)); 00248 } 00249 if (is_valid) { 00250 exitf("unexpected result"); 00251 } 00252 break; 00253 } 00254 00255 if (m) { 00256 Z3_del_model(ctx, m); 00257 } 00258 00259 /* restore context */ 00260 Z3_pop(ctx, 1); 00261 } 00262 00273 void assert_inj_axiom(Z3_context ctx, Z3_func_decl f, unsigned i) 00274 { 00275 unsigned sz, j; 00276 Z3_sort finv_domain, finv_range; 00277 Z3_func_decl finv; 00278 Z3_sort * types; /* types of the quantified variables */ 00279 Z3_symbol * names; /* names of the quantified variables */ 00280 Z3_ast * xs; /* arguments for the application f(x_0, ..., x_i, ..., x_{n-1}) */ 00281 Z3_ast x_i, fxs, finv_fxs, eq; 00282 Z3_pattern p; 00283 Z3_ast q; 00284 sz = Z3_get_domain_size(ctx, f); 00285 00286 if (i >= sz) { 00287 exitf("failed to create inj axiom"); 00288 } 00289 00290 /* declare the i-th inverse of f: finv */ 00291 finv_domain = Z3_get_range(ctx, f); 00292 finv_range = Z3_get_domain(ctx, f, i); 00293 finv = Z3_mk_fresh_func_decl(ctx, "inv", 1, &finv_domain, finv_range); 00294 00295 /* allocate temporary arrays */ 00296 types = (Z3_sort *) malloc(sizeof(Z3_sort) * sz); 00297 names = (Z3_symbol *) malloc(sizeof(Z3_symbol) * sz); 00298 xs = (Z3_ast *) malloc(sizeof(Z3_ast) * sz); 00299 00300 /* fill types, names and xs */ 00301 for (j = 0; j < sz; j++) { types[j] = Z3_get_domain(ctx, f, j); }; 00302 for (j = 0; j < sz; j++) { names[j] = Z3_mk_int_symbol(ctx, j); }; 00303 for (j = 0; j < sz; j++) { xs[j] = Z3_mk_bound(ctx, j, types[j]); }; 00304 00305 x_i = xs[i]; 00306 00307 /* create f(x_0, ..., x_i, ..., x_{n-1}) */ 00308 fxs = Z3_mk_app(ctx, f, sz, xs); 00309 00310 /* create f_inv(f(x_0, ..., x_i, ..., x_{n-1})) */ 00311 finv_fxs = mk_unary_app(ctx, finv, fxs); 00312 00313 /* create finv(f(x_0, ..., x_i, ..., x_{n-1})) = x_i */ 00314 eq = Z3_mk_eq(ctx, finv_fxs, x_i); 00315 00316 /* use f(x_0, ..., x_i, ..., x_{n-1}) as the pattern for the quantifier */ 00317 p = Z3_mk_pattern(ctx, 1, &fxs); 00318 printf("pattern: %s\n", Z3_pattern_to_string(ctx, p)); 00319 printf("\n"); 00320 00321 /* create & assert quantifier */ 00322 q = Z3_mk_forall(ctx, 00323 0, /* using default weight */ 00324 1, /* number of patterns */ 00325 &p, /* address of the "array" of patterns */ 00326 sz, /* number of quantified variables */ 00327 types, 00328 names, 00329 eq); 00330 printf("assert axiom:\n%s\n", Z3_ast_to_string(ctx, q)); 00331 Z3_assert_cnstr(ctx, q); 00332 00333 /* free temporary arrays */ 00334 free(types); 00335 free(names); 00336 free(xs); 00337 } 00338 00344 void assert_comm_axiom(Z3_context ctx, Z3_func_decl f) 00345 { 00346 Z3_sort t; 00347 Z3_symbol f_name, t_name; 00348 Z3_ast q; 00349 00350 t = Z3_get_range(ctx, f); 00351 00352 if (Z3_get_domain_size(ctx, f) != 2 || 00353 Z3_get_domain(ctx, f, 0) != t || 00354 Z3_get_domain(ctx, f, 1) != t) { 00355 exitf("function must be binary, and argument types must be equal to return type"); 00356 } 00357 00358 /* Inside the parser, function f will be referenced using the symbol 'f'. */ 00359 f_name = Z3_mk_string_symbol(ctx, "f"); 00360 00361 /* Inside the parser, type t will be referenced using the symbol 'T'. */ 00362 t_name = Z3_mk_string_symbol(ctx, "T"); 00363 00364 00365 Z3_parse_smtlib_string(ctx, 00366 "(benchmark comm :formula (forall (x T) (y T) (= (f x y) (f y x))))", 00367 1, &t_name, &t, 00368 1, &f_name, &f); 00369 q = Z3_get_smtlib_formula(ctx, 0); 00370 printf("assert axiom:\n%s\n", Z3_ast_to_string(ctx, q)); 00371 Z3_assert_cnstr(ctx, q); 00372 } 00373 00383 Z3_ast mk_tuple_update(Z3_context c, Z3_ast t, unsigned i, Z3_ast new_val) 00384 { 00385 Z3_sort ty; 00386 Z3_func_decl mk_tuple_decl; 00387 unsigned num_fields, j; 00388 Z3_ast * new_fields; 00389 Z3_ast result; 00390 00391 ty = Z3_get_sort(c, t); 00392 00393 if (Z3_get_sort_kind(c, ty) != Z3_DATATYPE_SORT) { 00394 exitf("argument must be a tuple"); 00395 } 00396 00397 num_fields = Z3_get_tuple_sort_num_fields(c, ty); 00398 00399 if (i >= num_fields) { 00400 exitf("invalid tuple update, index is too big"); 00401 } 00402 00403 new_fields = (Z3_ast*) malloc(sizeof(Z3_ast) * num_fields); 00404 for (j = 0; j < num_fields; j++) { 00405 if (i == j) { 00406 /* use new_val at position i */ 00407 new_fields[j] = new_val; 00408 } 00409 else { 00410 /* use field j of t */ 00411 Z3_func_decl proj_decl = Z3_get_tuple_sort_field_decl(c, ty, j); 00412 new_fields[j] = mk_unary_app(c, proj_decl, t); 00413 } 00414 } 00415 mk_tuple_decl = Z3_get_tuple_sort_mk_decl(c, ty); 00416 result = Z3_mk_app(c, mk_tuple_decl, num_fields, new_fields); 00417 free(new_fields); 00418 return result; 00419 } 00420 00424 void display_symbol(Z3_context c, FILE * out, Z3_symbol s) 00425 { 00426 switch (Z3_get_symbol_kind(c, s)) { 00427 case Z3_INT_SYMBOL: 00428 fprintf(out, "#%d", Z3_get_symbol_int(c, s)); 00429 break; 00430 case Z3_STRING_SYMBOL: 00431 fprintf(out, Z3_get_symbol_string(c, s)); 00432 break; 00433 default: 00434 unreachable(); 00435 } 00436 } 00437 00441 void display_sort(Z3_context c, FILE * out, Z3_sort ty) 00442 { 00443 switch (Z3_get_sort_kind(c, ty)) { 00444 case Z3_UNINTERPRETED_SORT: 00445 display_symbol(c, out, Z3_get_sort_name(c, ty)); 00446 break; 00447 case Z3_BOOL_SORT: 00448 fprintf(out, "bool"); 00449 break; 00450 case Z3_INT_SORT: 00451 fprintf(out, "int"); 00452 break; 00453 case Z3_REAL_SORT: 00454 fprintf(out, "real"); 00455 break; 00456 case Z3_BV_SORT: 00457 fprintf(out, "bv%d", Z3_get_bv_sort_size(c, ty)); 00458 break; 00459 case Z3_ARRAY_SORT: 00460 fprintf(out, "["); 00461 display_sort(c, out, Z3_get_array_sort_domain(c, ty)); 00462 fprintf(out, "->"); 00463 display_sort(c, out, Z3_get_array_sort_range(c, ty)); 00464 fprintf(out, "]"); 00465 break; 00466 case Z3_DATATYPE_SORT: 00467 if (Z3_get_datatype_sort_num_constructors(c, ty) != 1) 00468 { 00469 fprintf(out, "%s", Z3_sort_to_string(c,ty)); 00470 break; 00471 } 00472 { 00473 unsigned num_fields = Z3_get_tuple_sort_num_fields(c, ty); 00474 unsigned i; 00475 fprintf(out, "("); 00476 for (i = 0; i < num_fields; i++) { 00477 Z3_func_decl field = Z3_get_tuple_sort_field_decl(c, ty, i); 00478 if (i > 0) { 00479 fprintf(out, ", "); 00480 } 00481 display_sort(c, out, Z3_get_range(c, field)); 00482 } 00483 fprintf(out, ")"); 00484 break; 00485 } 00486 default: 00487 fprintf(out, "unknown["); 00488 display_symbol(c, out, Z3_get_sort_name(c, ty)); 00489 fprintf(out, "]"); 00490 break; 00491 } 00492 } 00493 00499 void display_ast(Z3_context c, FILE * out, Z3_ast v) 00500 { 00501 switch (Z3_get_ast_kind(c, v)) { 00502 case Z3_NUMERAL_AST: { 00503 Z3_sort t; 00504 fprintf(out, Z3_get_numeral_string(c, v)); 00505 t = Z3_get_sort(c, v); 00506 fprintf(out, ":"); 00507 display_sort(c, out, t); 00508 break; 00509 } 00510 case Z3_APP_AST: { 00511 unsigned i; 00512 Z3_app app = Z3_to_app(c, v); 00513 unsigned num_fields = Z3_get_app_num_args(c, app); 00514 Z3_func_decl d = Z3_get_app_decl(c, app); 00515 fprintf(out, Z3_func_decl_to_string(c, d)); 00516 if (num_fields > 0) { 00517 fprintf(out, "["); 00518 for (i = 0; i < num_fields; i++) { 00519 if (i > 0) { 00520 fprintf(out, ", "); 00521 } 00522 display_ast(c, out, Z3_get_app_arg(c, app, i)); 00523 } 00524 fprintf(out, "]"); 00525 } 00526 break; 00527 } 00528 case Z3_QUANTIFIER_AST: { 00529 fprintf(out, "quantifier"); 00530 ; 00531 } 00532 default: 00533 fprintf(out, "#unknown"); 00534 } 00535 } 00536 00540 void display_function_interpretations(Z3_context c, FILE * out, Z3_model m) 00541 { 00542 unsigned num_functions, i; 00543 00544 fprintf(out, "function interpretations:\n"); 00545 00546 num_functions = Z3_get_model_num_funcs(c, m); 00547 for (i = 0; i < num_functions; i++) { 00548 Z3_func_decl fdecl; 00549 Z3_symbol name; 00550 Z3_ast func_else; 00551 unsigned num_entries, j; 00552 00553 fdecl = Z3_get_model_func_decl(c, m, i); 00554 name = Z3_get_decl_name(c, fdecl); 00555 display_symbol(c, out, name); 00556 fprintf(out, " = {"); 00557 num_entries = Z3_get_model_func_num_entries(c, m, i); 00558 for (j = 0; j < num_entries; j++) { 00559 unsigned num_args, k; 00560 if (j > 0) { 00561 fprintf(out, ", "); 00562 } 00563 num_args = Z3_get_model_func_entry_num_args(c, m, i, j); 00564 fprintf(out, "("); 00565 for (k = 0; k < num_args; k++) { 00566 if (k > 0) { 00567 fprintf(out, ", "); 00568 } 00569 display_ast(c, out, Z3_get_model_func_entry_arg(c, m, i, j, k)); 00570 } 00571 fprintf(out, "|->"); 00572 display_ast(c, out, Z3_get_model_func_entry_value(c, m, i, j)); 00573 fprintf(out, ")"); 00574 } 00575 if (num_entries > 0) { 00576 fprintf(out, ", "); 00577 } 00578 fprintf(out, "(else|->"); 00579 func_else = Z3_get_model_func_else(c, m, i); 00580 display_ast(c, out, func_else); 00581 fprintf(out, ")}\n"); 00582 } 00583 } 00584 00588 void display_model(Z3_context c, FILE * out, Z3_model m) 00589 { 00590 unsigned num_constants; 00591 unsigned i; 00592 00593 num_constants = Z3_get_model_num_constants(c, m); 00594 for (i = 0; i < num_constants; i++) { 00595 Z3_symbol name; 00596 Z3_func_decl cnst = Z3_get_model_constant(c, m, i); 00597 Z3_ast a, v; 00598 Z3_bool ok; 00599 name = Z3_get_decl_name(c, cnst); 00600 display_symbol(c, out, name); 00601 fprintf(out, " = "); 00602 a = Z3_mk_app(c, cnst, 0, 0); 00603 v = a; 00604 ok = Z3_eval(c, m, a, &v); 00605 display_ast(c, out, v); 00606 fprintf(out, "\n"); 00607 } 00608 display_function_interpretations(c, out, m); 00609 } 00610 00614 void check2(Z3_context ctx, Z3_lbool expected_result) 00615 { 00616 Z3_model m = 0; 00617 Z3_lbool result = Z3_check_and_get_model(ctx, &m); 00618 switch (result) { 00619 case Z3_L_FALSE: 00620 printf("unsat\n"); 00621 break; 00622 case Z3_L_UNDEF: 00623 printf("unknown\n"); 00624 printf("potential model:\n"); 00625 display_model(ctx, stdout, m); 00626 break; 00627 case Z3_L_TRUE: 00628 printf("sat\n"); 00629 display_model(ctx, stdout, m); 00630 break; 00631 } 00632 if (m) { 00633 Z3_del_model(ctx, m); 00634 } 00635 if (result != expected_result) { 00636 exitf("unexpected result"); 00637 } 00638 } 00639 00643 void display_version() 00644 { 00645 unsigned major, minor, build, revision; 00646 Z3_get_version(&major, &minor, &build, &revision); 00647 printf("Z3 %d.%d.%d.%d\n", major, minor, build, revision); 00648 } 00658 void simple_example() 00659 { 00660 Z3_context ctx; 00661 00662 printf("\nsimple_example\n"); 00663 00664 ctx = mk_context(); 00665 00666 /* do something with the context */ 00667 printf("CONTEXT:\n%sEND OF CONTEXT\n", Z3_context_to_string(ctx)); 00668 00669 /* delete logical context */ 00670 Z3_del_context(ctx); 00671 } 00672 00677 void demorgan() 00678 { 00679 Z3_config cfg; 00680 Z3_context ctx; 00681 Z3_sort bool_sort; 00682 Z3_symbol symbol_x, symbol_y; 00683 Z3_ast x, y, not_x, not_y, x_and_y, ls, rs, conjecture, negated_conjecture; 00684 Z3_ast args[2]; 00685 00686 printf("\nDeMorgan\n"); 00687 00688 cfg = Z3_mk_config(); 00689 ctx = Z3_mk_context(cfg); 00690 Z3_del_config(cfg); 00691 #ifdef TRACING 00692 Z3_trace_to_stderr(ctx); 00693 #endif 00694 bool_sort = Z3_mk_bool_sort(ctx); 00695 symbol_x = Z3_mk_int_symbol(ctx, 0); 00696 symbol_y = Z3_mk_int_symbol(ctx, 1); 00697 x = Z3_mk_const(ctx, symbol_x, bool_sort); 00698 y = Z3_mk_const(ctx, symbol_y, bool_sort); 00699 00700 /* De Morgan - with a negation around */ 00701 /* !(!(x && y) <-> (!x || !y)) */ 00702 not_x = Z3_mk_not(ctx, x); 00703 not_y = Z3_mk_not(ctx, y); 00704 args[0] = x; 00705 args[1] = y; 00706 x_and_y = Z3_mk_and(ctx, 2, args); 00707 ls = Z3_mk_not(ctx, x_and_y); 00708 args[0] = not_x; 00709 args[1] = not_y; 00710 rs = Z3_mk_or(ctx, 2, args); 00711 conjecture = Z3_mk_iff(ctx, ls, rs); 00712 negated_conjecture = Z3_mk_not(ctx, conjecture); 00713 00714 Z3_assert_cnstr(ctx, negated_conjecture); 00715 switch (Z3_check(ctx)) { 00716 case Z3_L_FALSE: 00717 /* The negated conjecture was unsatisfiable, hence the conjecture is valid */ 00718 printf("DeMorgan is valid\n"); 00719 break; 00720 case Z3_L_UNDEF: 00721 /* Check returned undef */ 00722 printf("Undef\n"); 00723 break; 00724 case Z3_L_TRUE: 00725 /* The negated conjecture was satisfiable, hence the conjecture is not valid */ 00726 printf("DeMorgan is not valid\n"); 00727 break; 00728 } 00729 Z3_del_context(ctx); 00730 } 00731 00735 void find_model_example1() 00736 { 00737 Z3_context ctx; 00738 Z3_ast x, y, x_xor_y; 00739 00740 printf("\nfind_model_example1\n"); 00741 00742 ctx = mk_context(); 00743 00744 x = mk_bool_var(ctx, "x"); 00745 y = mk_bool_var(ctx, "y"); 00746 x_xor_y = Z3_mk_xor(ctx, x, y); 00747 00748 Z3_assert_cnstr(ctx, x_xor_y); 00749 00750 printf("model for: x xor y\n"); 00751 check(ctx, Z3_L_TRUE); 00752 00753 Z3_del_context(ctx); 00754 } 00755 00760 void find_model_example2() 00761 { 00762 Z3_context ctx; 00763 Z3_ast x, y, one, two, y_plus_one; 00764 Z3_ast x_eq_y; 00765 Z3_ast args[2]; 00766 Z3_ast c1, c2, c3; 00767 00768 printf("\nfind_model_example2\n"); 00769 00770 ctx = mk_context(); 00771 x = mk_int_var(ctx, "x"); 00772 y = mk_int_var(ctx, "y"); 00773 one = mk_int(ctx, 1); 00774 two = mk_int(ctx, 2); 00775 00776 args[0] = y; 00777 args[1] = one; 00778 y_plus_one = Z3_mk_add(ctx, 2, args); 00779 00780 c1 = Z3_mk_lt(ctx, x, y_plus_one); 00781 c2 = Z3_mk_gt(ctx, x, two); 00782 00783 Z3_assert_cnstr(ctx, c1); 00784 Z3_assert_cnstr(ctx, c2); 00785 00786 printf("model for: x < y + 1, x > 2\n"); 00787 check(ctx, Z3_L_TRUE); 00788 00789 /* assert not(x = y) */ 00790 x_eq_y = Z3_mk_eq(ctx, x, y); 00791 c3 = Z3_mk_not(ctx, x_eq_y); 00792 Z3_assert_cnstr(ctx, c3); 00793 00794 printf("model for: x < y + 1, x > 2, not(x = y)\n"); 00795 check(ctx, Z3_L_TRUE); 00796 00797 Z3_del_context(ctx); 00798 } 00799 00807 void prove_example1() 00808 { 00809 Z3_context ctx; 00810 Z3_symbol U_name, g_name, x_name, y_name; 00811 Z3_sort U; 00812 Z3_sort g_domain[1]; 00813 Z3_func_decl g; 00814 Z3_ast x, y, gx, ggx, gy; 00815 Z3_ast eq, f; 00816 00817 printf("\nprove_example1\n"); 00818 00819 ctx = mk_context(); 00820 00821 /* create uninterpreted type. */ 00822 U_name = Z3_mk_string_symbol(ctx, "U"); 00823 U = Z3_mk_uninterpreted_sort(ctx, U_name); 00824 00825 /* declare function g */ 00826 g_name = Z3_mk_string_symbol(ctx, "g"); 00827 g_domain[0] = U; 00828 g = Z3_mk_func_decl(ctx, g_name, 1, g_domain, U); 00829 00830 /* create x and y */ 00831 x_name = Z3_mk_string_symbol(ctx, "x"); 00832 y_name = Z3_mk_string_symbol(ctx, "y"); 00833 x = Z3_mk_const(ctx, x_name, U); 00834 y = Z3_mk_const(ctx, y_name, U); 00835 /* create g(x), g(y) */ 00836 gx = mk_unary_app(ctx, g, x); 00837 gy = mk_unary_app(ctx, g, y); 00838 00839 /* assert x = y */ 00840 eq = Z3_mk_eq(ctx, x, y); 00841 Z3_assert_cnstr(ctx, eq); 00842 00843 /* prove g(x) = g(y) */ 00844 f = Z3_mk_eq(ctx, gx, gy); 00845 printf("prove: x = y implies g(x) = g(y)\n"); 00846 prove(ctx, f, Z3_TRUE); 00847 00848 /* create g(g(x)) */ 00849 ggx = mk_unary_app(ctx, g, gx); 00850 00851 /* disprove g(g(x)) = g(y) */ 00852 f = Z3_mk_eq(ctx, ggx, gy); 00853 printf("disprove: x = y implies g(g(x)) = g(y)\n"); 00854 prove(ctx, f, Z3_FALSE); 00855 00856 Z3_del_context(ctx); 00857 } 00858 00865 void prove_example2() 00866 { 00867 Z3_context ctx; 00868 Z3_sort int_sort; 00869 Z3_symbol g_name; 00870 Z3_sort g_domain[1]; 00871 Z3_func_decl g; 00872 Z3_ast x, y, z, zero, minus_one, x_plus_z, gx, gy, gz, gx_gy, ggx_gy; 00873 Z3_ast args[2]; 00874 Z3_ast eq, c1, c2, c3, f; 00875 00876 printf("\nprove_example2\n"); 00877 00878 ctx = mk_context(); 00879 00880 /* declare function g */ 00881 int_sort = Z3_mk_int_sort(ctx); 00882 g_name = Z3_mk_string_symbol(ctx, "g"); 00883 g_domain[0] = int_sort; 00884 g = Z3_mk_func_decl(ctx, g_name, 1, g_domain, int_sort); 00885 00886 /* create x, y, and z */ 00887 x = mk_int_var(ctx, "x"); 00888 y = mk_int_var(ctx, "y"); 00889 z = mk_int_var(ctx, "z"); 00890 00891 /* create gx, gy, gz */ 00892 gx = mk_unary_app(ctx, g, x); 00893 gy = mk_unary_app(ctx, g, y); 00894 gz = mk_unary_app(ctx, g, z); 00895 00896 /* create zero */ 00897 zero = mk_int(ctx, 0); 00898 00899 /* assert not(g(g(x) - g(y)) = g(z)) */ 00900 args[0] = gx; 00901 args[1] = gy; 00902 gx_gy = Z3_mk_sub(ctx, 2, args); 00903 ggx_gy = mk_unary_app(ctx, g, gx_gy); 00904 eq = Z3_mk_eq(ctx, ggx_gy, gz); 00905 c1 = Z3_mk_not(ctx, eq); 00906 Z3_assert_cnstr(ctx, c1); 00907 00908 /* assert x + z <= y */ 00909 args[0] = x; 00910 args[1] = z; 00911 x_plus_z = Z3_mk_add(ctx, 2, args); 00912 c2 = Z3_mk_le(ctx, x_plus_z, y); 00913 Z3_assert_cnstr(ctx, c2); 00914 00915 /* assert y <= x */ 00916 c3 = Z3_mk_le(ctx, y, x); 00917 Z3_assert_cnstr(ctx, c3); 00918 00919 /* prove z < 0 */ 00920 f = Z3_mk_lt(ctx, z, zero); 00921 printf("prove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < 0\n"); 00922 prove(ctx, f, Z3_TRUE); 00923 00924 /* disprove z < -1 */ 00925 minus_one = mk_int(ctx, -1); 00926 f = Z3_mk_lt(ctx, z, minus_one); 00927 printf("disprove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < -1\n"); 00928 prove(ctx, f, Z3_FALSE); 00929 00930 Z3_del_context(ctx); 00931 } 00932 00939 void push_pop_example1() 00940 { 00941 Z3_context ctx; 00942 Z3_sort int_sort; 00943 Z3_symbol x_sym, y_sym; 00944 Z3_ast x, y, big_number, three; 00945 Z3_ast c1, c2, c3; 00946 00947 printf("\npush_pop_example1\n"); 00948 00949 ctx = mk_context(); 00950 00951 /* create a big number */ 00952 int_sort = Z3_mk_int_sort(ctx); 00953 big_number = Z3_mk_numeral(ctx, "1000000000000000000000000000000000000000000000000000000", int_sort); 00954 00955 /* create number 3 */ 00956 three = Z3_mk_numeral(ctx, "3", int_sort); 00957 00958 /* create x */ 00959 x_sym = Z3_mk_string_symbol(ctx, "x"); 00960 x = Z3_mk_const(ctx, x_sym, int_sort); 00961 00962 /* assert x >= "big number" */ 00963 c1 = Z3_mk_ge(ctx, x, big_number); 00964 printf("assert: x >= 'big number'\n"); 00965 Z3_assert_cnstr(ctx, c1); 00966 00967 /* create a backtracking point */ 00968 printf("push\n"); 00969 Z3_push(ctx); 00970 00971 /* assert x <= 3 */ 00972 c2 = Z3_mk_le(ctx, x, three); 00973 printf("assert: x <= 3\n"); 00974 Z3_assert_cnstr(ctx, c2); 00975 00976 /* context is inconsistent at this point */ 00977 check2(ctx, Z3_L_FALSE); 00978 00979 /* backtrack: the constraint x <= 3 will be removed, since it was 00980 asserted after the last Z3_push. */ 00981 printf("pop\n"); 00982 Z3_pop(ctx, 1); 00983 00984 /* the context is consistent again. */ 00985 check2(ctx, Z3_L_TRUE); 00986 00987 /* new constraints can be asserted... */ 00988 00989 /* create y */ 00990 y_sym = Z3_mk_string_symbol(ctx, "y"); 00991 y = Z3_mk_const(ctx, y_sym, int_sort); 00992 00993 /* assert y > x */ 00994 c3 = Z3_mk_gt(ctx, y, x); 00995 printf("assert: y > x\n"); 00996 Z3_assert_cnstr(ctx, c3); 00997 00998 /* the context is still consistent. */ 00999 check2(ctx, Z3_L_TRUE); 01000 01001 Z3_del_context(ctx); 01002 } 01003 01010 void quantifier_example1() 01011 { 01012 Z3_config cfg; 01013 Z3_context ctx; 01014 Z3_sort int_sort; 01015 Z3_symbol f_name; 01016 Z3_sort f_domain[2]; 01017 Z3_func_decl f; 01018 Z3_ast x, y, w, v, fxy, fwv; 01019 Z3_ast p1, p2, p3, not_p3; 01020 01021 printf("\nquantifier_example1\n"); 01022 01023 cfg = Z3_mk_config(); 01024 /* If quantified formulas are asserted in a logical context, then 01025 the model produced by Z3 should be viewed as a potential model. 01026 */ 01027 Z3_set_param_value(cfg, "MODEL", "true"); 01028 ctx = mk_context_custom(cfg, error_handler); 01029 Z3_del_config(cfg); 01030 01031 /* declare function f */ 01032 int_sort = Z3_mk_int_sort(ctx); 01033 f_name = Z3_mk_string_symbol(ctx, "f"); 01034 f_domain[0] = int_sort; 01035 f_domain[1] = int_sort; 01036 f = Z3_mk_func_decl(ctx, f_name, 2, f_domain, int_sort); 01037 01038 /* assert that f is injective in the second argument. */ 01039 assert_inj_axiom(ctx, f, 1); 01040 01041 /* create x, y, v, w, fxy, fwv */ 01042 x = mk_int_var(ctx, "x"); 01043 y = mk_int_var(ctx, "y"); 01044 v = mk_int_var(ctx, "v"); 01045 w = mk_int_var(ctx, "w"); 01046 fxy = mk_binary_app(ctx, f, x, y); 01047 fwv = mk_binary_app(ctx, f, w, v); 01048 01049 /* assert f(x, y) = f(w, v) */ 01050 p1 = Z3_mk_eq(ctx, fxy, fwv); 01051 Z3_assert_cnstr(ctx, p1); 01052 01053 /* prove f(x, y) = f(w, v) implies y = v */ 01054 p2 = Z3_mk_eq(ctx, y, v); 01055 printf("prove: f(x, y) = f(w, v) implies y = v\n"); 01056 prove(ctx, p2, Z3_TRUE); 01057 01058 /* disprove f(x, y) = f(w, v) implies x = w */ 01059 /* using check2 instead of prove */ 01060 p3 = Z3_mk_eq(ctx, x, w); 01061 not_p3 = Z3_mk_not(ctx, p3); 01062 Z3_assert_cnstr(ctx, not_p3); 01063 printf("disprove: f(x, y) = f(w, v) implies x = w\n"); 01064 printf("that is: not(f(x, y) = f(w, v) implies x = w) is satisfiable\n"); 01065 check2(ctx, Z3_L_UNDEF); 01066 printf("reason for last failure: %d (7 = quantifiers)\n", 01067 Z3_get_search_failure(ctx)); 01068 if (Z3_get_search_failure(ctx) != Z3_QUANTIFIERS) { 01069 exitf("unexpected result"); 01070 } 01071 01072 Z3_del_context(ctx); 01073 } 01074 01080 void array_example1() 01081 { 01082 Z3_context ctx; 01083 Z3_sort int_sort, array_sort; 01084 Z3_ast a1, a2, i1, v1, i2, v2, i3; 01085 Z3_ast st1, st2, sel1, sel2; 01086 Z3_ast antecedent, consequent; 01087 Z3_ast ds[3]; 01088 Z3_ast thm; 01089 01090 printf("\narray_example1\n"); 01091 01092 ctx = mk_context(); 01093 01094 int_sort = Z3_mk_int_sort(ctx); 01095 array_sort = Z3_mk_array_sort(ctx, int_sort, int_sort); 01096 01097 a1 = mk_var(ctx, "a1", array_sort); 01098 a2 = mk_var(ctx, "a2", array_sort); 01099 i1 = mk_var(ctx, "i1", int_sort); 01100 i2 = mk_var(ctx, "i2", int_sort); 01101 i3 = mk_var(ctx, "i3", int_sort); 01102 v1 = mk_var(ctx, "v1", int_sort); 01103 v2 = mk_var(ctx, "v2", int_sort); 01104 01105 st1 = Z3_mk_store(ctx, a1, i1, v1); 01106 st2 = Z3_mk_store(ctx, a2, i2, v2); 01107 01108 sel1 = Z3_mk_select(ctx, a1, i3); 01109 sel2 = Z3_mk_select(ctx, a2, i3); 01110 01111 /* create antecedent */ 01112 antecedent = Z3_mk_eq(ctx, st1, st2); 01113 01114 /* create consequent: i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3) */ 01115 ds[0] = Z3_mk_eq(ctx, i1, i3); 01116 ds[1] = Z3_mk_eq(ctx, i2, i3); 01117 ds[2] = Z3_mk_eq(ctx, sel1, sel2); 01118 consequent = Z3_mk_or(ctx, 3, ds); 01119 01120 /* prove store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3)) */ 01121 thm = Z3_mk_implies(ctx, antecedent, consequent); 01122 printf("prove: store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3))\n"); 01123 printf("%s\n", Z3_ast_to_string(ctx, thm)); 01124 prove(ctx, thm, Z3_TRUE); 01125 01126 Z3_del_context(ctx); 01127 } 01128 01136 void array_example2() 01137 { 01138 Z3_context ctx; 01139 Z3_sort bool_sort, array_sort; 01140 Z3_ast a[5]; 01141 Z3_ast d; 01142 unsigned i, n; 01143 01144 printf("\narray_example2\n"); 01145 01146 for (n = 2; n <= 5; n++) { 01147 printf("n = %d\n", n); 01148 ctx = mk_context(); 01149 01150 bool_sort = Z3_mk_bool_sort(ctx); 01151 array_sort = Z3_mk_array_sort(ctx, bool_sort, bool_sort); 01152 01153 /* create arrays */ 01154 for (i = 0; i < n; i++) { 01155 Z3_symbol s = Z3_mk_int_symbol(ctx, i); 01156 a[i] = Z3_mk_const(ctx, s, array_sort); 01157 } 01158 01159 /* assert distinct(a[0], ..., a[n]) */ 01160 d = Z3_mk_distinct(ctx, n, a); 01161 printf("%s\n", Z3_ast_to_string(ctx, d)); 01162 Z3_assert_cnstr(ctx, d); 01163 01164 /* context is satisfiable if n < 5 */ 01165 check2(ctx, n < 5 ? Z3_L_TRUE : Z3_L_FALSE); 01166 01167 Z3_del_context(ctx); 01168 } 01169 } 01170 01174 void array_example3() 01175 { 01176 Z3_context ctx; 01177 Z3_sort bool_sort, int_sort, array_sort; 01178 Z3_sort domain, range; 01179 printf("\narray_example3\n"); 01180 01181 ctx = mk_context(); 01182 01183 bool_sort = Z3_mk_bool_sort(ctx); 01184 int_sort = Z3_mk_int_sort(ctx); 01185 array_sort = Z3_mk_array_sort(ctx, int_sort, bool_sort); 01186 01187 if (Z3_get_sort_kind(ctx, array_sort) != Z3_ARRAY_SORT) { 01188 exitf("type must be an array type"); 01189 } 01190 01191 domain = Z3_get_array_sort_domain(ctx, array_sort); 01192 range = Z3_get_array_sort_range(ctx, array_sort); 01193 01194 printf("domain: "); 01195 display_sort(ctx, stdout, domain); 01196 printf("\n"); 01197 printf("range: "); 01198 display_sort(ctx, stdout, range); 01199 printf("\n"); 01200 01201 if (int_sort != domain || bool_sort != range) { 01202 exitf("invalid array type"); 01203 } 01204 01205 Z3_del_context(ctx); 01206 } 01207 01211 void tuple_example1() 01212 { 01213 Z3_context ctx; 01214 Z3_sort real_sort, pair_sort; 01215 Z3_symbol mk_tuple_name; 01216 Z3_func_decl mk_tuple_decl; 01217 Z3_symbol proj_names[2]; 01218 Z3_sort proj_sorts[2]; 01219 Z3_func_decl proj_decls[2]; 01220 Z3_func_decl get_x_decl, get_y_decl; 01221 01222 printf("\ntuple_example1\n"); 01223 01224 ctx = mk_context(); 01225 01226 Z3_open_log(ctx, "z3.log"); 01227 Z3_trace_to_file(ctx, "z3.trace"); 01228 01229 real_sort = Z3_mk_real_sort(ctx); 01230 01231 /* Create pair (tuple) type */ 01232 mk_tuple_name = Z3_mk_string_symbol(ctx, "mk_pair"); 01233 proj_names[0] = Z3_mk_string_symbol(ctx, "get_x"); 01234 proj_names[1] = Z3_mk_string_symbol(ctx, "get_y"); 01235 proj_sorts[0] = real_sort; 01236 proj_sorts[1] = real_sort; 01237 /* Z3_mk_tuple_sort will set mk_tuple_decl and proj_decls */ 01238 pair_sort = Z3_mk_tuple_sort(ctx, mk_tuple_name, 2, proj_names, proj_sorts, &mk_tuple_decl, proj_decls); 01239 get_x_decl = proj_decls[0]; /* function that extracts the first element of a tuple. */ 01240 get_y_decl = proj_decls[1]; /* function that extracts the second element of a tuple. */ 01241 01242 printf("tuple_sort: "); 01243 display_sort(ctx, stdout, pair_sort); 01244 printf("\n"); 01245 01246 { 01247 /* prove that get_x(mk_pair(x,y)) == 1 implies x = 1*/ 01248 Z3_ast app1, app2, x, y, one; 01249 Z3_ast eq1, eq2, eq3, thm; 01250 01251 x = mk_real_var(ctx, "x"); 01252 y = mk_real_var(ctx, "y"); 01253 app1 = mk_binary_app(ctx, mk_tuple_decl, x, y); 01254 app2 = mk_unary_app(ctx, get_x_decl, app1); 01255 one = Z3_mk_numeral(ctx, "1", real_sort); 01256 eq1 = Z3_mk_eq(ctx, app2, one); 01257 eq2 = Z3_mk_eq(ctx, x, one); 01258 thm = Z3_mk_implies(ctx, eq1, eq2); 01259 printf("prove: get_x(mk_pair(x, y)) = 1 implies x = 1\n"); 01260 prove(ctx, thm, Z3_TRUE); 01261 01262 /* disprove that get_x(mk_pair(x,y)) == 1 implies y = 1*/ 01263 eq3 = Z3_mk_eq(ctx, y, one); 01264 thm = Z3_mk_implies(ctx, eq1, eq3); 01265 printf("disprove: get_x(mk_pair(x, y)) = 1 implies y = 1\n"); 01266 prove(ctx, thm, Z3_FALSE); 01267 } 01268 01269 { 01270 /* prove that get_x(p1) = get_x(p2) and get_y(p1) = get_y(p2) implies p1 = p2 */ 01271 Z3_ast p1, p2, x1, x2, y1, y2; 01272 Z3_ast antecedents[2]; 01273 Z3_ast antecedent, consequent, thm; 01274 01275 p1 = mk_var(ctx, "p1", pair_sort); 01276 p2 = mk_var(ctx, "p2", pair_sort); 01277 x1 = mk_unary_app(ctx, get_x_decl, p1); 01278 y1 = mk_unary_app(ctx, get_y_decl, p1); 01279 x2 = mk_unary_app(ctx, get_x_decl, p2); 01280 y2 = mk_unary_app(ctx, get_y_decl, p2); 01281 antecedents[0] = Z3_mk_eq(ctx, x1, x2); 01282 antecedents[1] = Z3_mk_eq(ctx, y1, y2); 01283 antecedent = Z3_mk_and(ctx, 2, antecedents); 01284 consequent = Z3_mk_eq(ctx, p1, p2); 01285 thm = Z3_mk_implies(ctx, antecedent, consequent); 01286 printf("prove: get_x(p1) = get_x(p2) and get_y(p1) = get_y(p2) implies p1 = p2\n"); 01287 prove(ctx, thm, Z3_TRUE); 01288 01289 /* disprove that get_x(p1) = get_x(p2) implies p1 = p2 */ 01290 thm = Z3_mk_implies(ctx, antecedents[0], consequent); 01291 printf("disprove: get_x(p1) = get_x(p2) implies p1 = p2\n"); 01292 prove(ctx, thm, Z3_FALSE); 01293 } 01294 01295 { 01296 /* demonstrate how to use the mk_tuple_update function */ 01297 /* prove that p2 = update(p1, 0, 10) implies get_x(p2) = 10 */ 01298 Z3_ast p1, p2, one, ten, updt, x, y; 01299 Z3_ast antecedent, consequent, thm; 01300 01301 p1 = mk_var(ctx, "p1", pair_sort); 01302 p2 = mk_var(ctx, "p2", pair_sort); 01303 one = Z3_mk_numeral(ctx, "1", real_sort); 01304 ten = Z3_mk_numeral(ctx, "10", real_sort); 01305 updt = mk_tuple_update(ctx, p1, 0, ten); 01306 antecedent = Z3_mk_eq(ctx, p2, updt); 01307 x = mk_unary_app(ctx, get_x_decl, p2); 01308 consequent = Z3_mk_eq(ctx, x, ten); 01309 thm = Z3_mk_implies(ctx, antecedent, consequent); 01310 printf("prove: p2 = update(p1, 0, 10) implies get_x(p2) = 10\n"); 01311 prove(ctx, thm, Z3_TRUE); 01312 01313 /* disprove that p2 = update(p1, 0, 10) implies get_y(p2) = 10 */ 01314 y = mk_unary_app(ctx, get_y_decl, p2); 01315 consequent = Z3_mk_eq(ctx, y, ten); 01316 thm = Z3_mk_implies(ctx, antecedent, consequent); 01317 printf("disprove: p2 = update(p1, 0, 10) implies get_y(p2) = 10\n"); 01318 prove(ctx, thm, Z3_FALSE); 01319 } 01320 01321 Z3_del_context(ctx); 01322 } 01323 01327 void bitvector_example1() 01328 { 01329 Z3_context ctx; 01330 Z3_sort bv_sort; 01331 Z3_ast x, zero, ten, x_minus_ten, c1, c2, thm; 01332 01333 printf("\nbitvector_example1\n"); 01334 01335 ctx = mk_context(); 01336 01337 bv_sort = Z3_mk_bv_sort(ctx, 32); 01338 01339 x = mk_var(ctx, "x", bv_sort); 01340 zero = Z3_mk_numeral(ctx, "0", bv_sort); 01341 ten = Z3_mk_numeral(ctx, "10", bv_sort); 01342 x_minus_ten = Z3_mk_bvsub(ctx, x, ten); 01343 /* bvsle is signed less than or equal to */ 01344 c1 = Z3_mk_bvsle(ctx, x, ten); 01345 c2 = Z3_mk_bvsle(ctx, x_minus_ten, zero); 01346 thm = Z3_mk_iff(ctx, c1, c2); 01347 printf("disprove: x - 10 <= 0 IFF x <= 10 for (32-bit) machine integers\n"); 01348 prove(ctx, thm, Z3_FALSE); 01349 01350 Z3_del_context(ctx); 01351 } 01352 01356 void bitvector_example2() 01357 { 01358 Z3_context ctx = mk_context(); 01359 01360 /* construct x ^ y - 103 == x * y */ 01361 Z3_sort bv_sort = Z3_mk_bv_sort(ctx, 32); 01362 Z3_ast x = mk_var(ctx, "x", bv_sort); 01363 Z3_ast y = mk_var(ctx, "y", bv_sort); 01364 Z3_ast x_xor_y = Z3_mk_bvxor(ctx, x, y); 01365 Z3_ast c103 = Z3_mk_numeral(ctx, "103", bv_sort); 01366 Z3_ast lhs = Z3_mk_bvsub(ctx, x_xor_y, c103); 01367 Z3_ast rhs = Z3_mk_bvmul(ctx, x, y); 01368 Z3_ast ctr = Z3_mk_eq(ctx, lhs, rhs); 01369 01370 printf("\nbitvector_example2\n"); 01371 printf("find values of x and y, such that x ^ y - 103 == x * y\n"); 01372 01373 /* add the constraint <tt>x ^ y - 103 == x * y<\tt> to the logical context */ 01374 Z3_assert_cnstr(ctx, ctr); 01375 01376 /* find a model (i.e., values for x an y that satisfy the constraint */ 01377 check(ctx, Z3_L_TRUE); 01378 01379 Z3_del_context(ctx); 01380 } 01381 01385 void eval_example1() 01386 { 01387 Z3_context ctx; 01388 Z3_ast x, y, two; 01389 Z3_ast c1, c2; 01390 Z3_model m; 01391 01392 printf("\neval_example1\n"); 01393 01394 ctx = mk_context(); 01395 x = mk_int_var(ctx, "x"); 01396 y = mk_int_var(ctx, "y"); 01397 two = mk_int(ctx, 2); 01398 01399 /* assert x < y */ 01400 c1 = Z3_mk_lt(ctx, x, y); 01401 Z3_assert_cnstr(ctx, c1); 01402 01403 /* assert x > 2 */ 01404 c2 = Z3_mk_gt(ctx, x, two); 01405 Z3_assert_cnstr(ctx, c2); 01406 01407 /* find model for the constraints above */ 01408 if (Z3_check_and_get_model(ctx, &m) == Z3_L_TRUE) { 01409 Z3_ast x_plus_y; 01410 Z3_ast args[2] = {x, y}; 01411 Z3_ast v; 01412 printf("MODEL:\n%s", Z3_model_to_string(ctx, m)); 01413 x_plus_y = Z3_mk_add(ctx, 2, args); 01414 printf("\nevaluating x+y\n"); 01415 if (Z3_eval(ctx, m, x_plus_y, &v)) { 01416 printf("result = "); 01417 display_ast(ctx, stdout, v); 01418 printf("\n"); 01419 } 01420 else { 01421 exitf("failed to evaluate: x+y"); 01422 } 01423 Z3_del_model(ctx, m); 01424 } 01425 else { 01426 exitf("the constraints are satisfiable"); 01427 } 01428 01429 Z3_del_context(ctx); 01430 } 01431 01435 void two_contexts_example1() 01436 { 01437 Z3_context ctx1, ctx2; 01438 Z3_ast x1, x2; 01439 01440 printf("\ntwo_contexts_example1\n"); 01441 01442 /* using the same (default) configuration to initialized both logical contexts. */ 01443 ctx1 = mk_context(); 01444 ctx2 = mk_context(); 01445 01446 x1 = Z3_mk_const(ctx1, Z3_mk_int_symbol(ctx1,0), Z3_mk_bool_sort(ctx1)); 01447 x2 = Z3_mk_const(ctx2, Z3_mk_int_symbol(ctx2,0), Z3_mk_bool_sort(ctx2)); 01448 01449 Z3_del_context(ctx1); 01450 01451 /* ctx2 can still be used. */ 01452 printf("%s\n", Z3_ast_to_string(ctx2, x2)); 01453 01454 Z3_del_context(ctx2); 01455 } 01456 01460 void error_code_example1() 01461 { 01462 Z3_config cfg; 01463 Z3_context ctx; 01464 Z3_ast x; 01465 Z3_model m; 01466 Z3_ast v; 01467 Z3_func_decl x_decl; 01468 const char * str; 01469 01470 printf("\nerror_code_example1\n"); 01471 01472 /* Do not register an error handler, as we want to use Z3_get_error_code manually */ 01473 cfg = Z3_mk_config(); 01474 ctx = mk_context_custom(cfg, NULL); 01475 Z3_del_config(cfg); 01476 01477 x = mk_bool_var(ctx, "x"); 01478 x_decl = Z3_get_app_decl(ctx, Z3_to_app(ctx, x)); 01479 Z3_assert_cnstr(ctx, x); 01480 01481 if (Z3_check_and_get_model(ctx, &m) != Z3_L_TRUE) { 01482 exitf("unexpected result"); 01483 } 01484 01485 if (!Z3_eval_func_decl(ctx, m, x_decl, &v)) { 01486 exitf("did not obtain value for declaration.\n"); 01487 } 01488 if (Z3_get_error_code(ctx) == Z3_OK) { 01489 printf("last call succeeded.\n"); 01490 } 01491 /* The following call will fail since the value of x is a boolean */ 01492 str = Z3_get_numeral_string(ctx, v); 01493 if (Z3_get_error_code(ctx) != Z3_OK) { 01494 printf("last call failed.\n"); 01495 } 01496 Z3_del_model(ctx, m); 01497 Z3_del_context(ctx); 01498 } 01499 01503 void error_code_example2() 01504 { 01505 Z3_config cfg; 01506 Z3_context ctx = NULL; 01507 int r; 01508 01509 printf("\nerror_code_example2\n"); 01510 01511 /* low tech try&catch */ 01512 r = setjmp(g_catch_buffer); 01513 if (r == 0) { 01514 Z3_ast x, y, app; 01515 01516 cfg = Z3_mk_config(); 01517 ctx = mk_context_custom(cfg, throw_z3_error); 01518 Z3_del_config(cfg); 01519 01520 x = mk_int_var(ctx, "x"); 01521 y = mk_bool_var(ctx, "y"); 01522 printf("before Z3_mk_iff\n"); 01523 /* the next call will produce an error */ 01524 app = Z3_mk_iff(ctx, x, y); 01525 unreachable(); 01526 Z3_del_context(ctx); 01527 } 01528 else { 01529 printf("Z3 error: %s.\n", Z3_get_error_msg((Z3_error_code)r)); 01530 if (cfg != NULL) { 01531 Z3_del_context(ctx); 01532 } 01533 } 01534 } 01535 01539 void parser_example1() 01540 { 01541 Z3_context ctx; 01542 unsigned i, num_formulas; 01543 01544 printf("\nparser_example1\n"); 01545 01546 ctx = mk_context(); 01547 01548 Z3_parse_smtlib_string(ctx, 01549 "(benchmark tst :extrafuns ((x Int) (y Int)) :formula (> x y) :formula (> x 0))", 01550 0, 0, 0, 01551 0, 0, 0); 01552 num_formulas = Z3_get_smtlib_num_formulas(ctx); 01553 for (i = 0; i < num_formulas; i++) { 01554 Z3_ast f = Z3_get_smtlib_formula(ctx, i); 01555 printf("formula %d: %s\n", i, Z3_ast_to_string(ctx, f)); 01556 Z3_assert_cnstr(ctx, f); 01557 } 01558 01559 check(ctx, Z3_L_TRUE); 01560 01561 Z3_del_context(ctx); 01562 } 01563 01567 void parser_example2() 01568 { 01569 Z3_context ctx; 01570 Z3_ast x, y; 01571 Z3_symbol names[2]; 01572 Z3_func_decl decls[2]; 01573 Z3_ast f; 01574 01575 printf("\nparser_example2\n"); 01576 01577 ctx = mk_context(); 01578 01579 /* Z3_enable_arithmetic doesn't need to be invoked in this example 01580 because it will be implicitly invoked by mk_int_var. 01581 */ 01582 01583 x = mk_int_var(ctx, "x"); 01584 decls[0] = Z3_get_app_decl(ctx, Z3_to_app(ctx, x)); 01585 y = mk_int_var(ctx, "y"); 01586 decls[1] = Z3_get_app_decl(ctx, Z3_to_app(ctx, y)); 01587 01588 names[0] = Z3_mk_string_symbol(ctx, "a"); 01589 names[1] = Z3_mk_string_symbol(ctx, "b"); 01590 01591 Z3_parse_smtlib_string(ctx, 01592 "(benchmark tst :formula (> a b))", 01593 0, 0, 0, 01594 /* 'x' and 'y' declarations are inserted as 'a' and 'b' into the parser symbol table. */ 01595 2, names, decls); 01596 f = Z3_get_smtlib_formula(ctx, 0); 01597 printf("formula: %s\n", Z3_ast_to_string(ctx, f)); 01598 Z3_assert_cnstr(ctx, f); 01599 check(ctx, Z3_L_TRUE); 01600 01601 Z3_del_context(ctx); 01602 } 01603 01607 void parser_example3() 01608 { 01609 Z3_config cfg; 01610 Z3_context ctx; 01611 Z3_sort int_sort; 01612 Z3_symbol g_name; 01613 Z3_sort g_domain[2]; 01614 Z3_func_decl g; 01615 Z3_ast thm; 01616 01617 printf("\nparser_example3\n"); 01618 01619 cfg = Z3_mk_config(); 01620 /* See quantifer_example1 */ 01621 Z3_set_param_value(cfg, "MODEL", "true"); 01622 ctx = mk_context_custom(cfg, error_handler); 01623 Z3_del_config(cfg); 01624 01625 /* declare function g */ 01626 int_sort = Z3_mk_int_sort(ctx); 01627 g_name = Z3_mk_string_symbol(ctx, "g"); 01628 g_domain[0] = int_sort; 01629 g_domain[1] = int_sort; 01630 g = Z3_mk_func_decl(ctx, g_name, 2, g_domain, int_sort); 01631 01632 assert_comm_axiom(ctx, g); 01633 01634 Z3_parse_smtlib_string(ctx, 01635 "(benchmark tst :formula (forall (x Int) (y Int) (implies (= x y) (= (g x 0) (g 0 y)))))", 01636 0, 0, 0, 01637 1, &g_name, &g); 01638 thm = Z3_get_smtlib_formula(ctx, 0); 01639 printf("formula: %s\n", Z3_ast_to_string(ctx, thm)); 01640 prove(ctx, thm, Z3_TRUE); 01641 01642 Z3_del_context(ctx); 01643 } 01644 01648 void parser_example4() 01649 { 01650 Z3_context ctx; 01651 unsigned i, num_decls, num_assumptions, num_formulas; 01652 01653 printf("\nparser_example4\n"); 01654 01655 ctx = mk_context(); 01656 01657 Z3_parse_smtlib_string(ctx, 01658 "(benchmark tst :extrafuns ((x Int) (y Int)) :assumption (= x 20) :formula (> x y) :formula (> x 0))", 01659 0, 0, 0, 01660 0, 0, 0); 01661 num_decls = Z3_get_smtlib_num_decls(ctx); 01662 for (i = 0; i < num_decls; i++) { 01663 Z3_func_decl d = Z3_get_smtlib_decl(ctx, i); 01664 printf("declaration %d: %s\n", i, Z3_func_decl_to_string(ctx, d)); 01665 } 01666 num_assumptions = Z3_get_smtlib_num_assumptions(ctx); 01667 for (i = 0; i < num_assumptions; i++) { 01668 Z3_ast a = Z3_get_smtlib_assumption(ctx, i); 01669 printf("assumption %d: %s\n", i, Z3_ast_to_string(ctx, a)); 01670 } 01671 num_formulas = Z3_get_smtlib_num_formulas(ctx); 01672 for (i = 0; i < num_formulas; i++) { 01673 Z3_ast f = Z3_get_smtlib_formula(ctx, i); 01674 printf("formula %d: %s\n", i, Z3_ast_to_string(ctx, f)); 01675 } 01676 Z3_del_context(ctx); 01677 } 01678 01682 void parser_example5() 01683 { 01684 Z3_config cfg; 01685 Z3_context ctx = NULL; 01686 int r; 01687 01688 printf("\nparser_example5\n"); 01689 01690 r = setjmp(g_catch_buffer); 01691 if (r == 0) { 01692 cfg = Z3_mk_config(); 01693 ctx = mk_context_custom(cfg, throw_z3_error); 01694 Z3_del_config(cfg); 01695 01696 Z3_parse_smtlib_string(ctx, 01697 /* the following string has a parsing error: missing parenthesis */ 01698 "(benchmark tst :extrafuns ((x Int (y Int)) :formula (> x y) :formula (> x 0))", 01699 0, 0, 0, 01700 0, 0, 0); 01701 unreachable(); 01702 Z3_del_context(ctx); 01703 } 01704 else { 01705 printf("Z3 error: %s.\n", Z3_get_error_msg((Z3_error_code)r)); 01706 if (ctx != NULL) { 01707 printf("Error message: '%s'.\n",Z3_get_smtlib_error(ctx)); 01708 Z3_del_context(ctx); 01709 } 01710 } 01711 } 01712 01716 void ite_example() 01717 { 01718 Z3_context ctx; 01719 Z3_ast f, one, zero, ite; 01720 01721 printf("\nite_example\n"); 01722 01723 ctx = mk_context(); 01724 01725 f = Z3_mk_false(ctx); 01726 one = mk_int(ctx, 1); 01727 zero = mk_int(ctx, 0); 01728 ite = Z3_mk_ite(ctx, f, one, zero); 01729 01730 printf("term: %s\n", Z3_ast_to_string(ctx, ite)); 01731 01732 /* delete logical context */ 01733 Z3_del_context(ctx); 01734 } 01735 01739 void enum_example() { 01740 Z3_context ctx = mk_context(); 01741 Z3_sort fruit; 01742 Z3_symbol name = Z3_mk_string_symbol(ctx, "fruit"); 01743 Z3_symbol enum_names[3]; 01744 Z3_func_decl enum_consts[3]; 01745 Z3_func_decl enum_testers[3]; 01746 Z3_ast apple, orange, banana, fruity; 01747 Z3_ast ors[3]; 01748 01749 printf("\nenum_example\n"); 01750 01751 enum_names[0] = Z3_mk_string_symbol(ctx,"apple"); 01752 enum_names[1] = Z3_mk_string_symbol(ctx,"banana"); 01753 enum_names[2] = Z3_mk_string_symbol(ctx,"orange"); 01754 01755 fruit = Z3_mk_enumeration_sort(ctx, name, 3, enum_names, enum_consts, enum_testers); 01756 01757 printf("%s\n", Z3_func_decl_to_string(ctx, enum_consts[0])); 01758 printf("%s\n", Z3_func_decl_to_string(ctx, enum_consts[1])); 01759 printf("%s\n", Z3_func_decl_to_string(ctx, enum_consts[2])); 01760 01761 printf("%s\n", Z3_func_decl_to_string(ctx, enum_testers[0])); 01762 printf("%s\n", Z3_func_decl_to_string(ctx, enum_testers[1])); 01763 printf("%s\n", Z3_func_decl_to_string(ctx, enum_testers[2])); 01764 01765 apple = Z3_mk_app(ctx, enum_consts[0], 0, 0); 01766 banana = Z3_mk_app(ctx, enum_consts[1], 0, 0); 01767 orange = Z3_mk_app(ctx, enum_consts[2], 0, 0); 01768 01769 /* Apples are different from oranges */ 01770 prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, apple, orange)), Z3_TRUE); 01771 01772 /* Apples pass the apple test */ 01773 prove(ctx, Z3_mk_app(ctx, enum_testers[0], 1, &apple), Z3_TRUE); 01774 01775 /* Oranges fail the apple test */ 01776 prove(ctx, Z3_mk_app(ctx, enum_testers[0], 1, &orange), Z3_FALSE); 01777 prove(ctx, Z3_mk_not(ctx, Z3_mk_app(ctx, enum_testers[0], 1, &orange)), Z3_TRUE); 01778 01779 fruity = mk_var(ctx, "fruity", fruit); 01780 01781 /* If something is fruity, then it is an apple, banana, or orange */ 01782 ors[0] = Z3_mk_eq(ctx, fruity, apple); 01783 ors[1] = Z3_mk_eq(ctx, fruity, banana); 01784 ors[2] = Z3_mk_eq(ctx, fruity, orange); 01785 01786 prove(ctx, Z3_mk_or(ctx, 3, ors), Z3_TRUE); 01787 01788 /* delete logical context */ 01789 Z3_del_context(ctx); 01790 } 01791 01795 void list_example() { 01796 Z3_context ctx = mk_context(); 01797 Z3_sort int_ty, int_list; 01798 Z3_func_decl nil_decl, is_nil_decl, cons_decl, is_cons_decl, head_decl, tail_decl; 01799 Z3_ast nil, l1, l2, x, y, u, v, fml, fml1; 01800 Z3_ast ors[2]; 01801 01802 01803 printf("\nlist_example\n"); 01804 01805 int_ty = Z3_mk_int_sort(ctx); 01806 01807 int_list = Z3_mk_list_sort(ctx, Z3_mk_string_symbol(ctx, "int_list"), int_ty, 01808 &nil_decl, &is_nil_decl, &cons_decl, &is_cons_decl, &head_decl, &tail_decl); 01809 01810 nil = Z3_mk_app(ctx, nil_decl, 0, 0); 01811 l1 = mk_binary_app(ctx, cons_decl, mk_int(ctx, 1), nil); 01812 l2 = mk_binary_app(ctx, cons_decl, mk_int(ctx, 2), nil); 01813 01814 /* nil != cons(1, nil) */ 01815 prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil, l1)), Z3_TRUE); 01816 01817 /* cons(2,nil) != cons(1, nil) */ 01818 prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, l1, l2)), Z3_TRUE); 01819 01820 /* cons(x,nil) = cons(y, nil) => x = y */ 01821 x = mk_var(ctx, "x", int_ty); 01822 y = mk_var(ctx, "y", int_ty); 01823 l1 = mk_binary_app(ctx, cons_decl, x, nil); 01824 l2 = mk_binary_app(ctx, cons_decl, y, nil); 01825 prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE); 01826 01827 /* cons(x,u) = cons(x, v) => u = v */ 01828 u = mk_var(ctx, "u", int_list); 01829 v = mk_var(ctx, "v", int_list); 01830 l1 = mk_binary_app(ctx, cons_decl, x, u); 01831 l2 = mk_binary_app(ctx, cons_decl, y, v); 01832 prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, u, v)), Z3_TRUE); 01833 prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE); 01834 01835 /* is_nil(u) or is_cons(u) */ 01836 ors[0] = Z3_mk_app(ctx, is_nil_decl, 1, &u); 01837 ors[1] = Z3_mk_app(ctx, is_cons_decl, 1, &u); 01838 prove(ctx, Z3_mk_or(ctx, 2, ors), Z3_TRUE); 01839 01840 /* occurs check u != cons(x,u) */ 01841 prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, u, l1)), Z3_TRUE); 01842 01843 /* destructors: is_cons(u) => u = cons(head(u),tail(u)) */ 01844 fml1 = Z3_mk_eq(ctx, u, mk_binary_app(ctx, cons_decl, mk_unary_app(ctx, head_decl, u), mk_unary_app(ctx, tail_decl, u))); 01845 fml = Z3_mk_implies(ctx, Z3_mk_app(ctx, is_cons_decl, 1, &u), fml1); 01846 printf("Formula %s\n", Z3_ast_to_string(ctx, fml)); 01847 prove(ctx, fml, Z3_TRUE); 01848 01849 prove(ctx, fml1, Z3_FALSE); 01850 01851 /* delete logical context */ 01852 Z3_del_context(ctx); 01853 } 01854 01858 void tree_example() { 01859 Z3_context ctx = mk_context(); 01860 Z3_sort cell; 01861 Z3_func_decl nil_decl, is_nil_decl, cons_decl, is_cons_decl, car_decl, cdr_decl; 01862 Z3_ast nil, l1, l2, x, y, u, v, fml, fml1; 01863 Z3_symbol head_tail[2] = { Z3_mk_string_symbol(ctx, "car"), Z3_mk_string_symbol(ctx, "cdr") }; 01864 Z3_sort sorts[2] = { 0, 0 }; 01865 unsigned sort_refs[2] = { 0, 0 }; 01866 Z3_constructor nil_con, cons_con; 01867 Z3_constructor constructors[2]; 01868 Z3_func_decl cons_accessors[2]; 01869 Z3_ast ors[2]; 01870 01871 printf("\ntree_example\n"); 01872 01873 nil_con = Z3_mk_constructor(ctx, Z3_mk_string_symbol(ctx, "nil"), Z3_mk_string_symbol(ctx, "is_nil"), 0, 0, 0, 0); 01874 cons_con = Z3_mk_constructor(ctx, Z3_mk_string_symbol(ctx, "cons"), Z3_mk_string_symbol(ctx, "is_cons"), 2, head_tail, sorts, sort_refs); 01875 constructors[0] = nil_con; 01876 constructors[1] = cons_con; 01877 01878 cell = Z3_mk_datatype(ctx, Z3_mk_string_symbol(ctx, "cell"), 2, constructors); 01879 01880 Z3_query_constructor(ctx, nil_con, 0, &nil_decl, &is_nil_decl, 0); 01881 Z3_query_constructor(ctx, cons_con, 2, &cons_decl, &is_cons_decl, cons_accessors); 01882 car_decl = cons_accessors[0]; 01883 cdr_decl = cons_accessors[1]; 01884 01885 Z3_del_constructor(ctx,nil_con); 01886 Z3_del_constructor(ctx,cons_con); 01887 01888 01889 nil = Z3_mk_app(ctx, nil_decl, 0, 0); 01890 l1 = mk_binary_app(ctx, cons_decl, nil, nil); 01891 l2 = mk_binary_app(ctx, cons_decl, l1, nil); 01892 01893 /* nil != cons(nil, nil) */ 01894 prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil, l1)), Z3_TRUE); 01895 01896 /* cons(x,u) = cons(x, v) => u = v */ 01897 u = mk_var(ctx, "u", cell); 01898 v = mk_var(ctx, "v", cell); 01899 x = mk_var(ctx, "x", cell); 01900 y = mk_var(ctx, "y", cell); 01901 l1 = mk_binary_app(ctx, cons_decl, x, u); 01902 l2 = mk_binary_app(ctx, cons_decl, y, v); 01903 prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, u, v)), Z3_TRUE); 01904 prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE); 01905 01906 /* is_nil(u) or is_cons(u) */ 01907 ors[0] = Z3_mk_app(ctx, is_nil_decl, 1, &u); 01908 ors[1] = Z3_mk_app(ctx, is_cons_decl, 1, &u); 01909 prove(ctx, Z3_mk_or(ctx, 2, ors), Z3_TRUE); 01910 01911 /* occurs check u != cons(x,u) */ 01912 prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, u, l1)), Z3_TRUE); 01913 01914 /* destructors: is_cons(u) => u = cons(car(u),cdr(u)) */ 01915 fml1 = Z3_mk_eq(ctx, u, mk_binary_app(ctx, cons_decl, mk_unary_app(ctx, car_decl, u), mk_unary_app(ctx, cdr_decl, u))); 01916 fml = Z3_mk_implies(ctx, Z3_mk_app(ctx, is_cons_decl, 1, &u), fml1); 01917 printf("Formula %s\n", Z3_ast_to_string(ctx, fml)); 01918 prove(ctx, fml, Z3_TRUE); 01919 01920 prove(ctx, fml1, Z3_FALSE); 01921 01922 /* delete logical context */ 01923 Z3_del_context(ctx); 01924 01925 01926 } 01927 01935 void forest_example() { 01936 Z3_context ctx = mk_context(); 01937 Z3_sort tree, forest; 01938 Z3_func_decl nil1_decl, is_nil1_decl, cons1_decl, is_cons1_decl, car1_decl, cdr1_decl; 01939 Z3_func_decl nil2_decl, is_nil2_decl, cons2_decl, is_cons2_decl, car2_decl, cdr2_decl; 01940 Z3_ast nil1, nil2, t1, t2, t3, t4, f1, f2, f3, l1, l2, x, y, u, v; 01941 Z3_symbol head_tail[2] = { Z3_mk_string_symbol(ctx, "car"), Z3_mk_string_symbol(ctx, "cdr") }; 01942 Z3_sort sorts[2] = { 0, 0 }; 01943 unsigned sort_refs[2] = { 0, 0 }; 01944 Z3_constructor nil1_con, cons1_con, nil2_con, cons2_con; 01945 Z3_constructor constructors1[2], constructors2[2]; 01946 Z3_func_decl cons_accessors[2]; 01947 Z3_ast ors[2]; 01948 Z3_constructor_list clist1, clist2; 01949 Z3_constructor_list clists[2]; 01950 Z3_symbol sort_names[2] = { Z3_mk_string_symbol(ctx, "forest"), Z3_mk_string_symbol(ctx, "tree") }; 01951 01952 printf("\nforest_example\n"); 01953 01954 /* build a forest */ 01955 nil1_con = Z3_mk_constructor(ctx, Z3_mk_string_symbol(ctx, "nil1"), Z3_mk_string_symbol(ctx, "is_nil1"), 0, 0, 0, 0); 01956 sort_refs[0] = 1; /* the car of a forest is a tree */ 01957 sort_refs[1] = 0; 01958 cons1_con = Z3_mk_constructor(ctx, Z3_mk_string_symbol(ctx, "cons1"), Z3_mk_string_symbol(ctx, "is_cons1"), 2, head_tail, sorts, sort_refs); 01959 constructors1[0] = nil1_con; 01960 constructors1[1] = cons1_con; 01961 01962 /* build a tree */ 01963 nil2_con = Z3_mk_constructor(ctx, Z3_mk_string_symbol(ctx, "nil2"), Z3_mk_string_symbol(ctx, "is_nil2"),0, 0, 0, 0); 01964 sort_refs[0] = 0; /* both branches of a tree are forests */ 01965 sort_refs[1] = 0; 01966 cons2_con = Z3_mk_constructor(ctx, Z3_mk_string_symbol(ctx, "cons2"), Z3_mk_string_symbol(ctx, "is_cons2"),2, head_tail, sorts, sort_refs); 01967 constructors2[0] = nil2_con; 01968 constructors2[1] = cons2_con; 01969 01970 clist1 = Z3_mk_constructor_list(ctx, 2, constructors1); 01971 clist2 = Z3_mk_constructor_list(ctx, 2, constructors2); 01972 01973 clists[0] = clist1; 01974 clists[1] = clist2; 01975 01976 Z3_mk_datatypes(ctx, 2, sort_names, sorts, clists); 01977 forest = sorts[0]; 01978 tree = sorts[1]; 01979 01980 Z3_query_constructor(ctx, nil1_con, 0, &nil1_decl, &is_nil1_decl, 0); 01981 Z3_query_constructor(ctx, cons1_con, 2, &cons1_decl, &is_cons1_decl, cons_accessors); 01982 car1_decl = cons_accessors[0]; 01983 cdr1_decl = cons_accessors[1]; 01984 01985 Z3_query_constructor(ctx, nil2_con, 0, &nil2_decl, &is_nil2_decl, 0); 01986 Z3_query_constructor(ctx, cons2_con, 2, &cons2_decl, &is_cons2_decl, cons_accessors); 01987 car2_decl = cons_accessors[0]; 01988 cdr2_decl = cons_accessors[1]; 01989 01990 Z3_del_constructor_list(ctx, clist1); 01991 Z3_del_constructor_list(ctx, clist2); 01992 Z3_del_constructor(ctx,nil1_con); 01993 Z3_del_constructor(ctx,cons1_con); 01994 Z3_del_constructor(ctx,nil2_con); 01995 Z3_del_constructor(ctx,cons2_con); 01996 01997 nil1 = Z3_mk_app(ctx, nil1_decl, 0, 0); 01998 nil2 = Z3_mk_app(ctx, nil2_decl, 0, 0); 01999 f1 = mk_binary_app(ctx, cons1_decl, nil2, nil1); 02000 t1 = mk_binary_app(ctx, cons2_decl, nil1, nil1); 02001 t2 = mk_binary_app(ctx, cons2_decl, f1, nil1); 02002 t3 = mk_binary_app(ctx, cons2_decl, f1, f1); 02003 t4 = mk_binary_app(ctx, cons2_decl, nil1, f1); 02004 f2 = mk_binary_app(ctx, cons1_decl, t1, nil1); 02005 f3 = mk_binary_app(ctx, cons1_decl, t1, f1); 02006 02007 02008 /* nil != cons(nil,nil) */ 02009 prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil1, f1)), Z3_TRUE); 02010 prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil2, t1)), Z3_TRUE); 02011 02012 02013 /* cons(x,u) = cons(x, v) => u = v */ 02014 u = mk_var(ctx, "u", forest); 02015 v = mk_var(ctx, "v", forest); 02016 x = mk_var(ctx, "x", tree); 02017 y = mk_var(ctx, "y", tree); 02018 l1 = mk_binary_app(ctx, cons1_decl, x, u); 02019 l2 = mk_binary_app(ctx, cons1_decl, y, v); 02020 prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, u, v)), Z3_TRUE); 02021 prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE); 02022 02023 /* is_nil(u) or is_cons(u) */ 02024 ors[0] = Z3_mk_app(ctx, is_nil1_decl, 1, &u); 02025 ors[1] = Z3_mk_app(ctx, is_cons1_decl, 1, &u); 02026 prove(ctx, Z3_mk_or(ctx, 2, ors), Z3_TRUE); 02027 02028 /* occurs check u != cons(x,u) */ 02029 prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, u, l1)), Z3_TRUE); 02030 02031 /* delete logical context */ 02032 Z3_del_context(ctx); 02033 } 02034 02035 02036 02043 void unsat_core_and_proof_example() { 02044 Z3_context ctx = mk_proof_context(); 02045 Z3_ast pa = mk_bool_var(ctx, "PredA"); 02046 Z3_ast pb = mk_bool_var(ctx, "PredB"); 02047 Z3_ast pc = mk_bool_var(ctx, "PredC"); 02048 Z3_ast pd = mk_bool_var(ctx, "PredD"); 02049 Z3_ast p1 = mk_bool_var(ctx, "P1"); 02050 Z3_ast p2 = mk_bool_var(ctx, "P2"); 02051 Z3_ast p3 = mk_bool_var(ctx, "P3"); 02052 Z3_ast p4 = mk_bool_var(ctx, "P4"); 02053 Z3_ast assumptions[4] = { Z3_mk_not(ctx, p1), Z3_mk_not(ctx, p2), Z3_mk_not(ctx, p3), Z3_mk_not(ctx, p4) }; 02054 Z3_ast args1[3] = { pa, pb, pc }; 02055 Z3_ast f1 = Z3_mk_and(ctx, 3, args1); 02056 Z3_ast args2[3] = { pa, Z3_mk_not(ctx, pb), pc }; 02057 Z3_ast f2 = Z3_mk_and(ctx, 3, args2); 02058 Z3_ast args3[2] = { Z3_mk_not(ctx, pa), Z3_mk_not(ctx, pc) }; 02059 Z3_ast f3 = Z3_mk_or(ctx, 2, args3); 02060 Z3_ast f4 = pd; 02061 Z3_ast g1[2] = { f1, p1 }; 02062 Z3_ast g2[2] = { f2, p2 }; 02063 Z3_ast g3[2] = { f3, p3 }; 02064 Z3_ast g4[2] = { f4, p4 }; 02065 Z3_ast core[4] = { 0, 0, 0, 0 }; 02066 unsigned core_size = 4; 02067 Z3_ast proof; 02068 Z3_model m = 0; 02069 Z3_lbool result; 02070 unsigned i; 02071 02072 Z3_assert_cnstr(ctx, Z3_mk_or(ctx, 2, g1)); 02073 Z3_assert_cnstr(ctx, Z3_mk_or(ctx, 2, g2)); 02074 Z3_assert_cnstr(ctx, Z3_mk_or(ctx, 2, g3)); 02075 Z3_assert_cnstr(ctx, Z3_mk_or(ctx, 2, g4)); 02076 02077 result = Z3_check_assumptions(ctx, 4, assumptions, &m, &proof, &core_size, core); 02078 02079 switch (result) { 02080 case Z3_L_FALSE: 02081 printf("unsat\n"); 02082 printf("proof: %s\n", Z3_ast_to_string(ctx, proof)); 02083 02084 printf("\ncore:\n"); 02085 for (i = 0; i < core_size; ++i) { 02086 printf("%s\n", Z3_ast_to_string(ctx, core[i])); 02087 } 02088 printf("\n"); 02089 break; 02090 case Z3_L_UNDEF: 02091 printf("unknown\n"); 02092 printf("potential model:\n"); 02093 display_model(ctx, stdout, m); 02094 break; 02095 case Z3_L_TRUE: 02096 printf("sat\n"); 02097 display_model(ctx, stdout, m); 02098 break; 02099 } 02100 if (m) { 02101 Z3_del_model(ctx, m); 02102 } 02103 02104 /* delete logical context */ 02105 Z3_del_context(ctx); 02106 } 02107 02108 02115 void get_implied_equalities_example() { 02116 Z3_config cfg = Z3_mk_config(); 02117 Z3_context ctx; 02118 Z3_set_param_value(cfg, "ARITH_PROCESS_ALL_EQS", "true"); 02119 Z3_set_param_value(cfg, "ARITH_EQ_BOUNDS", "true"); 02120 ctx = Z3_mk_context(cfg); 02121 Z3_del_config(cfg); 02122 { 02123 Z3_sort int_ty = Z3_mk_int_sort(ctx); 02124 Z3_ast a = mk_int_var(ctx,"a"); 02125 Z3_ast b = mk_int_var(ctx,"b"); 02126 Z3_ast c = mk_int_var(ctx,"c"); 02127 Z3_ast d = mk_int_var(ctx,"d"); 02128 Z3_func_decl f = Z3_mk_func_decl(ctx, Z3_mk_string_symbol(ctx,"f"), 1, &int_ty, int_ty); 02129 Z3_ast fa = Z3_mk_app(ctx, f, 1, &a); 02130 Z3_ast fb = Z3_mk_app(ctx, f, 1, &b); 02131 Z3_ast fc = Z3_mk_app(ctx, f, 1, &c); 02132 unsigned const num_terms = 7; 02133 unsigned i; 02134 Z3_ast terms[7] = { a, b, c, d, fa, fb, fc }; 02135 unsigned class_ids[7] = { 0, 0, 0, 0, 0, 0, 0 }; 02136 02137 Z3_assert_cnstr(ctx, Z3_mk_eq(ctx, a, b)); 02138 Z3_assert_cnstr(ctx, Z3_mk_eq(ctx, b, c)); 02139 Z3_assert_cnstr(ctx, Z3_mk_le(ctx, fc, b)); 02140 Z3_assert_cnstr(ctx, Z3_mk_le(ctx, b, fa)); 02141 02142 Z3_get_implied_equalities(ctx, num_terms, terms, class_ids); 02143 for (i = 0; i < num_terms; ++i) { 02144 printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); 02145 } 02146 printf("asserting f(a) <= b\n"); 02147 Z3_assert_cnstr(ctx, Z3_mk_le(ctx, fa, b)); 02148 Z3_get_implied_equalities(ctx, num_terms, terms, class_ids); 02149 for (i = 0; i < num_terms; ++i) { 02150 printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]); 02151 } 02152 /* delete logical context */ 02153 Z3_del_context(ctx); 02154 } 02155 } 02156 02159 02160 int main() 02161 { 02162 02163 display_version(); 02164 simple_example(); 02165 demorgan(); 02166 find_model_example1(); 02167 find_model_example2(); 02168 prove_example1(); 02169 prove_example2(); 02170 push_pop_example1(); 02171 quantifier_example1(); 02172 array_example1(); 02173 array_example2(); 02174 array_example3(); 02175 tuple_example1(); 02176 bitvector_example1(); 02177 bitvector_example2(); 02178 eval_example1(); 02179 two_contexts_example1(); 02180 error_code_example1(); 02181 error_code_example2(); 02182 parser_example1(); 02183 parser_example2(); 02184 parser_example3(); 02185 parser_example4(); 02186 parser_example5(); 02187 ite_example(); 02188 list_example(); 02189 tree_example(); 02190 forest_example(); 02191 enum_example(); 02192 unsat_core_and_proof_example(); 02193 get_implied_equalities_example(); 02194 02195 return 0; 02196 }