| Home | • | Docs | • | Download | • | • | FAQ | • | Awards | • | Status | • | MSR |
|---|
An Efficient SMT Solver
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. | |
| 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().
| 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 | ( | ) |
Create a logical context.
Enable model construction only.
Also enable tracing to stderr and register standard error handler.
Definition at line 82 of file test_capi.c.
Referenced by array_example1(), array_example2(), array_example3(), bitvector_example1(), bitvector_example2(), enum_example(), TestManaged::eval_example1(), eval_example1(), TestManaged::eval_example2(), find_model_example1(), find_model_example2(), TestManaged::find_small_model_example(), TestManaged::forest_example(), forest_example(), ite_example(), TestManaged::list_example(), list_example(), parser_example1(), parser_example2(), parser_example4(), prove_example1(), prove_example2(), push_pop_example1(), simple_example(), TestManaged::simplifier_example(), TestManaged::tree_example(), tree_example(), tuple_example1(), and two_contexts_example1().
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 }
| 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.
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().
| 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 }