Home Docs Download Mail FAQ Awards Status MSR

Z3 An Efficient SMT Solver

test_capi/test_capi.c

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 }
Last modified Thu Nov 12 16:35:56 2009