Home Docs Download Mail FAQ Awards Status MSR

Z3 An Efficient SMT Solver

C API examples


Auxiliary Functions

void exitf (const char *message)
 exit gracefully in case of error.
void unreachable ()
 exit if unreachable code was reached.
void error_handler (Z3_error_code e)
 Simpler error handler.
void throw_z3_error (Z3_error_code c)
 Low tech exceptions.
Z3_context mk_context_custom (Z3_config cfg, Z3_error_handler err)
 Create a logical context.
Z3_context mk_context ()
 Create a logical context.
Z3_context mk_proof_context ()
 Create a logical context.
Z3_ast mk_var (Z3_context ctx, const char *name, Z3_sort ty)
 Create a variable using the given name and type.
Z3_ast mk_bool_var (Z3_context ctx, const char *name)
 Create a boolean variable using the given name.
Z3_ast mk_int_var (Z3_context ctx, const char *name)
 Create an integer variable using the given name.
Z3_ast mk_int (Z3_context ctx, int v)
 Create a Z3 integer node using a C int.
Z3_ast mk_real_var (Z3_context ctx, const char *name)
 Create a real variable using the given name.
Z3_ast mk_unary_app (Z3_context ctx, Z3_func_decl f, Z3_ast x)
 Create the unary function application: (f x).
Z3_ast mk_binary_app (Z3_context ctx, Z3_func_decl f, Z3_ast x, Z3_ast y)
 Create the binary function application: (f x y).
void check (Z3_context ctx, Z3_lbool expected_result)
 Check whether the logical context is satisfiable, and compare the result with the expected result. If the context is satisfiable, then display the model.
void prove (Z3_context ctx, Z3_ast f, Z3_bool is_valid)
 Prove that the constraints already asserted into the logical context implies the given formula. The result of the proof is displayed.
void assert_inj_axiom (Z3_context ctx, Z3_func_decl f, unsigned i)
 Assert the axiom: function f is injective in the i-th argument.
void assert_comm_axiom (Z3_context ctx, Z3_func_decl f)
 Assert the axiom: function f is commutative.
Z3_ast mk_tuple_update (Z3_context c, Z3_ast t, unsigned i, Z3_ast new_val)
 Z3 does not support explicitly tuple updates. They can be easily implemented as macros. The argument t must have tuple type. A tuple update is a new tuple where field i has value new_val, and all other fields have the value of the respective field of t.
void display_symbol (Z3_context c, FILE *out, Z3_symbol s)
 Display a symbol in the given output stream.
void display_sort (Z3_context c, FILE *out, Z3_sort ty)
 Display the given type.
void display_ast (Z3_context c, FILE *out, Z3_ast v)
 Custom ast pretty printer.
void display_function_interpretations (Z3_context c, FILE *out, Z3_model m)
 Custom function interpretations pretty printer.
void display_model (Z3_context c, FILE *out, Z3_model m)
 Custom model pretty printer.
void check2 (Z3_context ctx, Z3_lbool expected_result)
 Similar to check, but uses display_model instead of Z3_model_to_string.
void display_version ()
 Display Z3 version in the standard output.

Examples

void simple_example ()
 "Hello world" example: create a Z3 logical context, and delete it.
void demorgan ()
void find_model_example1 ()
 Find a model for x xor y.
void find_model_example2 ()
 Find a model for x < y + 1, x > 2. Then, assert not(x = y), and find another model.
void prove_example1 ()
 Prove x = y implies g(x) = g(y), and disprove x = y implies g(g(x)) = g(y).
void prove_example2 ()
 Prove not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < 0 . Then, show that z < -1 is not implied.
void push_pop_example1 ()
 Show how push & pop can be used to create "backtracking" points.
void quantifier_example1 ()
 Prove that f(x, y) = f(w, v) implies y = v when f is injective in the second argument.
void array_example1 ()
 Prove store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3)).
void array_example2 ()
 Show that distinct(a_0, ... , a_n) is unsatisfiable when a_i's are arrays from boolean to boolean and n > 4.
void array_example3 ()
 Simple array type construction/deconstruction example.
void tuple_example1 ()
 Simple tuple type example. It creates a tuple that is a pair of real numbers.
void bitvector_example1 ()
 Simple bit-vector example. This example disproves that x - 10 <= 0 IFF x <= 10 for (32-bit) machine integers.
void bitvector_example2 ()
 Find x and y such that: x ^ y - 103 == x * y.
void eval_example1 ()
 Demonstrate how to use Z3_eval.
void two_contexts_example1 ()
 Several logical context can be used simultaneously.
void error_code_example1 ()
 Demonstrates how error codes can be read insted of registering an error handler.
void error_code_example2 ()
 Demonstrates how error handlers can be used.
void parser_example1 ()
 Demonstrates how to use the SMTLIB parser.
void parser_example2 ()
 Demonstrates how to initialize the parser symbol table.
void parser_example3 ()
 Demonstrates how to initialize the parser symbol table.
void parser_example4 ()
 Display the declarations, assumptions and formulas in a SMT-LIB string.
void parser_example5 ()
 Demonstrates how to handle parser errors using Z3 error handling support.
void ite_example ()
 Test ite-term (if-then-else terms).
void enum_example ()
 Create an enumeration data type.
void list_example ()
 Create a list datatype.
void tree_example ()
 Create a binary tree datatype.
void forest_example ()
 Create a forest of trees.
void unsat_core_and_proof_example ()
 Prove a theorem and extract, and print the proof.
void get_implied_equalities_example ()
 Extract classes of implied equalities.

Function Documentation

void array_example1 (  ) 

Prove store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3)).

This example demonstrates how to use the array theory.

Definition at line 1080 of file test_capi.c.

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 }

void array_example2 (  ) 

Show that distinct(a_0, ... , a_n) is unsatisfiable when a_i's are arrays from boolean to boolean and n > 4.

This example also shows how to use the distinct construct.

Definition at line 1136 of file test_capi.c.

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 }

void array_example3 (  ) 

Simple array type construction/deconstruction example.

Definition at line 1174 of file test_capi.c.

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 }

void assert_comm_axiom ( Z3_context  ctx,
Z3_func_decl  f 
)

Assert the axiom: function f is commutative.

This example uses the SMT-LIB parser to simplify the axiom construction.

Definition at line 344 of file test_capi.c.

Referenced by parser_example3().

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 }

void assert_inj_axiom ( Z3_context  ctx,
Z3_func_decl  f,
unsigned  i 
)

Assert the axiom: function f is injective in the i-th argument.

The following axiom is asserted into the logical context:

   forall (x_0, ..., x_n) finv(f(x_0, ..., x_i, ..., x_{n-1})) = x_i

Where, finv is a fresh function declaration.

Definition at line 273 of file test_capi.c.

Referenced by quantifier_example1().

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 }

void bitvector_example1 (  ) 

Simple bit-vector example. This example disproves that x - 10 <= 0 IFF x <= 10 for (32-bit) machine integers.

Definition at line 1327 of file test_capi.c.

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 }

void bitvector_example2 (  ) 

Find x and y such that: x ^ y - 103 == x * y.

Definition at line 1356 of file test_capi.c.

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 }

void check ( Z3_context  ctx,
Z3_lbool  expected_result 
)

Check whether the logical context is satisfiable, and compare the result with the expected result. If the context is satisfiable, then display the model.

Definition at line 176 of file test_capi.c.

Referenced by bitvector_example2(), find_model_example1(), find_model_example2(), parser_example1(), and parser_example2().

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 }

void check2 ( Z3_context  ctx,
Z3_lbool  expected_result 
)

Similar to check, but uses display_model instead of Z3_model_to_string.

Definition at line 614 of file test_capi.c.

Referenced by array_example2(), push_pop_example1(), and quantifier_example1().

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 }

void demorgan (  ) 

Demonstration of how Z3 can be used to prove validity of De Morgan's Duality Law: {e not(x and y) <-> (not x) or ( not y) }

Definition at line 677 of file test_capi.c.

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 }

void display_ast ( Z3_context  c,
FILE *  out,
Z3_ast  v 
)

Custom ast pretty printer.

This function demonstrates how to use the API to navigate terms.

Definition at line 499 of file test_capi.c.

Referenced by display_function_interpretations(), display_model(), and eval_example1().

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 }

void display_function_interpretations ( Z3_context  c,
FILE *  out,
Z3_model  m 
)

Custom function interpretations pretty printer.

Definition at line 540 of file test_capi.c.

Referenced by display_model().

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 }

void display_model ( Z3_context  c,
FILE *  out,
Z3_model  m 
)

Custom model pretty printer.

Definition at line 588 of file test_capi.c.

Referenced by check2(), and unsat_core_and_proof_example().

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 }

void display_sort ( Z3_context  c,
FILE *  out,
Z3_sort  ty 
)

Display the given type.

Definition at line 441 of file test_capi.c.

Referenced by array_example3(), display_ast(), and tuple_example1().

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 }

void display_symbol ( Z3_context  c,
FILE *  out,
Z3_symbol  s 
)

Display a symbol in the given output stream.

Definition at line 424 of file test_capi.c.

Referenced by display_function_interpretations(), display_model(), and display_sort().

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 }

void display_version (  ) 

Display Z3 version in the standard output.

Definition at line 643 of file test_capi.c.

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 }

void enum_example (  ) 

Create an enumeration data type.

Definition at line 1739 of file test_capi.c.

01739                     {
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 }

void error_code_example1 (  ) 

Demonstrates how error codes can be read insted of registering an error handler.

Definition at line 1460 of file test_capi.c.

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 }

void error_code_example2 (  ) 

Demonstrates how error handlers can be used.

Definition at line 1503 of file test_capi.c.

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 }

void error_handler ( Z3_error_code  e  ) 

Simpler error handler.

Definition at line 37 of file test_capi.c.

Referenced by mk_context(), parser_example3(), and quantifier_example1().

00038 {
00039         printf("Error code: %d\n", e);
00040     exitf("incorrect use of Z3");
00041 }

void eval_example1 (  ) 

Demonstrate how to use Z3_eval.

Definition at line 1385 of file test_capi.c.

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 }

void exitf ( const char *  message  ) 

exit gracefully in case of error.

Definition at line 20 of file test_capi.c.

Referenced by array_example3(), assert_comm_axiom(), assert_inj_axiom(), check(), check2(), error_code_example1(), error_handler(), eval_example1(), mk_tuple_update(), prove(), quantifier_example1(), and unreachable().

00021 {
00022   fprintf(stderr,"BUG: %s.\n", message);
00023   exit(1);
00024 }

void find_model_example1 (  ) 

Find a model for x xor y.

Definition at line 735 of file test_capi.c.

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 }

void find_model_example2 (  ) 

Find a model for x < y + 1, x > 2. Then, assert not(x = y), and find another model.

Definition at line 760 of file test_capi.c.

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 }

void forest_example (  ) 

Create a forest of trees.

forest ::= nil | cons(tree, forest) tree ::= nil | cons(forest, forest)

Definition at line 1935 of file test_capi.c.

01935                       {
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 }

void get_implied_equalities_example (  ) 

Extract classes of implied equalities.

This example illustrates the use of Z3_get_implied_equalities.

Definition at line 2115 of file test_capi.c.

02115                                       {
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 }

void ite_example (  ) 

Test ite-term (if-then-else terms).

Definition at line 1716 of file test_capi.c.

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 }

void list_example (  ) 

Create a list datatype.

Definition at line 1795 of file test_capi.c.

01795                     {
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 }

Z3_ast mk_binary_app ( Z3_context  ctx,
Z3_func_decl  f,
Z3_ast  x,
Z3_ast  y 
)

Create the binary function application: (f x y).

Definition at line 166 of file test_capi.c.

Referenced by TestManaged::forest_example(), forest_example(), TestManaged::list_example(), list_example(), quantifier_example1(), TestManaged::tree_example(), tree_example(), and tuple_example1().

00167 {
00168     Z3_ast args[2] = {x, y};
00169     return Z3_mk_app(ctx, f, 2, args);
00170 }

Z3_ast mk_bool_var ( Z3_context  ctx,
const char *  name 
)

Create a boolean variable using the given name.

Definition at line 121 of file test_capi.c.

Referenced by error_code_example1(), error_code_example2(), find_model_example1(), TestManaged::unsat_core_and_proof_example(), and unsat_core_and_proof_example().

00122 {
00123     Z3_sort ty = Z3_mk_bool_sort(ctx);
00124     return mk_var(ctx, name, ty);
00125 }

Z3_context mk_context (  ) 

Z3_context mk_context_custom ( Z3_config  cfg,
Z3_error_handler  err 
)

Create a logical context.

Enable model construction. Other configuration parameters can be passed in the cfg variable.

Also enable tracing to stderr and register custom error handler.

Definition at line 61 of file test_capi.c.

Referenced by error_code_example1(), error_code_example2(), mk_context(), mk_proof_context(), parser_example3(), parser_example5(), and quantifier_example1().

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 }

Z3_ast mk_int ( Z3_context  ctx,
int  v 
)

Create a Z3 integer node using a C int.

Definition at line 139 of file test_capi.c.

Referenced by TestManaged::eval_example1(), eval_example1(), find_model_example2(), ite_example(), TestManaged::list_example(), list_example(), and prove_example2().

00140 {
00141     Z3_sort ty = Z3_mk_int_sort(ctx);
00142     return Z3_mk_int(ctx, v, ty);
00143 }

Z3_ast mk_int_var ( Z3_context  ctx,
const char *  name 
)

Create an integer variable using the given name.

Definition at line 130 of file test_capi.c.

Referenced by error_code_example2(), TestManaged::eval_example1(), eval_example1(), find_model_example2(), TestManaged::get_implied_equalities_example(), get_implied_equalities_example(), parser_example2(), prove_example2(), quantifier_example1(), and TestManaged::simplifier_example().

00131 {
00132     Z3_sort ty = Z3_mk_int_sort(ctx);
00133     return mk_var(ctx, name, ty);
00134 }

Z3_context mk_proof_context (  ) 

Create a logical context.

Enable fine-grained proof construction. Enable model construction.

Also enable tracing to stderr and register standard error handler.

Definition at line 100 of file test_capi.c.

Referenced by unsat_core_and_proof_example().

00100                               {
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 }

Z3_ast mk_real_var ( Z3_context  ctx,
const char *  name 
)

Create a real variable using the given name.

Definition at line 148 of file test_capi.c.

Referenced by tuple_example1().

00149 {
00150     Z3_sort ty = Z3_mk_real_sort(ctx);
00151     return mk_var(ctx, name, ty);
00152 }

Z3_ast mk_tuple_update ( Z3_context  c,
Z3_ast  t,
unsigned  i,
Z3_ast  new_val 
)

Z3 does not support explicitly tuple updates. They can be easily implemented as macros. The argument t must have tuple type. A tuple update is a new tuple where field i has value new_val, and all other fields have the value of the respective field of t.

update(t, i, new_val) is equivalent to mk_tuple(proj_0(t), ..., new_val, ..., proj_n(t))

Definition at line 383 of file test_capi.c.

Referenced by tuple_example1().

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 }

Z3_ast mk_unary_app ( Z3_context  ctx,
Z3_func_decl  f,
Z3_ast  x 
)

Create the unary function application: (f x).

Definition at line 157 of file test_capi.c.

Referenced by assert_inj_axiom(), TestManaged::list_example(), list_example(), mk_tuple_update(), prove_example1(), prove_example2(), TestManaged::tree_example(), tree_example(), and tuple_example1().

00158 {
00159     Z3_ast args[1] = {x};
00160     return Z3_mk_app(ctx, f, 1, args);
00161 }

Z3_ast mk_var ( Z3_context  ctx,
const char *  name,
Z3_sort  ty 
)

Create a variable using the given name and type.

Definition at line 112 of file test_capi.c.

Referenced by array_example1(), bitvector_example1(), bitvector_example2(), enum_example(), TestManaged::forest_example(), forest_example(), TestManaged::list_example(), list_example(), mk_bool_var(), mk_int_var(), mk_real_var(), TestManaged::tree_example(), tree_example(), and tuple_example1().

00113 {
00114     Z3_symbol   s  = Z3_mk_string_symbol(ctx, name);
00115     return Z3_mk_const(ctx, s, ty);
00116 }

void parser_example1 (  ) 

Demonstrates how to use the SMTLIB parser.

Definition at line 1539 of file test_capi.c.

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 }

void parser_example2 (  ) 

Demonstrates how to initialize the parser symbol table.

Definition at line 1567 of file test_capi.c.

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 }

void parser_example3 (  ) 

Demonstrates how to initialize the parser symbol table.

Definition at line 1607 of file test_capi.c.

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 }

void parser_example4 (  ) 

Display the declarations, assumptions and formulas in a SMT-LIB string.

Definition at line 1648 of file test_capi.c.

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 }

void parser_example5 (  ) 

Demonstrates how to handle parser errors using Z3 error handling support.

Definition at line 1682 of file test_capi.c.

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 }

void prove ( Z3_context  ctx,
Z3_ast  f,
Z3_bool  is_valid 
)

Prove that the constraints already asserted into the logical context implies the given formula. The result of the proof is displayed.

Z3 is a satisfiability checker. So, one can prove f by showing that (not f) is unsatisfiable.

The context ctx is not modified by this function.

Definition at line 210 of file test_capi.c.

Referenced by array_example1(), bitvector_example1(), enum_example(), forest_example(), list_example(), parser_example3(), prove_example1(), prove_example2(), quantifier_example1(), tree_example(), and tuple_example1().

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 }

void prove_example1 (  ) 

Prove x = y implies g(x) = g(y), and disprove x = y implies g(g(x)) = g(y).

This function demonstrates how to create uninterpreted types and functions.

Definition at line 807 of file test_capi.c.

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 }

void prove_example2 (  ) 

Prove not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < 0 . Then, show that z < -1 is not implied.

This example demonstrates how to combine uninterpreted functions and arithmetic.

Definition at line 865 of file test_capi.c.

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 }

void push_pop_example1 (  ) 

Show how push & pop can be used to create "backtracking" points.

This example also demonstrates how big numbers can be created in Z3.

Definition at line 939 of file test_capi.c.

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 }

void quantifier_example1 (  ) 

Prove that f(x, y) = f(w, v) implies y = v when f is injective in the second argument.

See also:
assert_inj_axiom.

Definition at line 1010 of file test_capi.c.

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 }

void simple_example (  ) 

"Hello world" example: create a Z3 logical context, and delete it.

Definition at line 658 of file test_capi.c.

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 }

void throw_z3_error ( Z3_error_code  c  ) 

Low tech exceptions.

In high-level programming languages, an error handler can throw an exception.

Definition at line 49 of file test_capi.c.

Referenced by error_code_example2(), mk_proof_context(), and parser_example5().

00050 {
00051     longjmp(g_catch_buffer, c);
00052 }

void tree_example (  ) 

Create a binary tree datatype.

Definition at line 1858 of file test_capi.c.

01858                     {
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 }

void tuple_example1 (  ) 

Simple tuple type example. It creates a tuple that is a pair of real numbers.

Definition at line 1211 of file test_capi.c.

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 }

void two_contexts_example1 (  ) 

Several logical context can be used simultaneously.

Definition at line 1435 of file test_capi.c.

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 }

void unreachable (  ) 

exit if unreachable code was reached.

Definition at line 29 of file test_capi.c.

Referenced by display_symbol(), error_code_example2(), and parser_example5().

00030 {
00031     exitf("unreachable code was reached");
00032 }

void unsat_core_and_proof_example (  ) 

Prove a theorem and extract, and print the proof.

This example illustrates the use of Z3_check_assumptions.

Definition at line 2043 of file test_capi.c.

02043                                     {
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 }

Last modified Thu Nov 12 16:35:57 2009