Z3_solver solver = Z3_mk_solver(ctx);
Z3_solver_inc_ref(ctx, solver);
// Enable unsat core tracking
Z3_params params = Z3_mk_params(ctx);
Z3_params_inc_ref(ctx, params);
Z3_symbol unsat_core = Z3_mk_string_symbol(ctx, "unsat_core");
Z3_params_set_bool(ctx, params, unsat_core, true);
Z3_solver_set_params(ctx, solver, params);
Z3_params_dec_ref(ctx, params);
// Create tracking literals
Z3_ast track1 = Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, "track1"),
Z3_mk_bool_sort(ctx));
Z3_ast track2 = Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, "track2"),
Z3_mk_bool_sort(ctx));
Z3_ast track3 = Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, "track3"),
Z3_mk_bool_sort(ctx));
// Create constraints
Z3_ast x = Z3_mk_const(ctx, Z3_mk_string_symbol(ctx, "x"),
Z3_mk_int_sort(ctx));
Z3_ast zero = Z3_mk_int(ctx, 0, Z3_mk_int_sort(ctx));
Z3_ast c1 = Z3_mk_gt(ctx, x, zero);
Z3_ast c2 = Z3_mk_lt(ctx, x, zero);
Z3_ast c3 = Z3_mk_eq(ctx, x, zero);
// Assert with tracking literals
Z3_ast implies1 = Z3_mk_implies(ctx, track1, c1);
Z3_ast implies2 = Z3_mk_implies(ctx, track2, c2);
Z3_ast implies3 = Z3_mk_implies(ctx, track3, c3);
Z3_solver_assert(ctx, solver, implies1);
Z3_solver_assert(ctx, solver, implies2);
Z3_solver_assert(ctx, solver, implies3);
// Check with tracking assumptions
Z3_ast assumptions[3] = {track1, track2, track3};
Z3_lbool result = Z3_solver_check_assumptions(ctx, solver, 3, assumptions);
if (result == Z3_L_FALSE) {
Z3_ast_vector core = Z3_solver_get_unsat_core(ctx, solver);
Z3_ast_vector_inc_ref(ctx, core);
printf("Conflicting constraints:\n");
unsigned core_size = Z3_ast_vector_size(ctx, core);
for (unsigned i = 0; i < core_size; i++) {
Z3_ast elem = Z3_ast_vector_get(ctx, core, i);
Z3_symbol sym = Z3_get_symbol_int(ctx,
Z3_get_decl_name(ctx, Z3_get_app_decl(ctx, Z3_to_app(ctx, elem))));
printf(" %s\n", Z3_get_symbol_string(ctx, sym));
}
Z3_ast_vector_dec_ref(ctx, core);
}
Z3_solver_dec_ref(ctx, solver);