/** \brief Small test for the at-most-one constraint. */ void tst_at_most_one() { Z3_context ctx = mk_context(); Z3_solver s = mk_solver(ctx); Z3_ast k1 = mk_bool_var(ctx, "k1"); Z3_ast k2 = mk_bool_var(ctx, "k2"); Z3_ast k3 = mk_bool_var(ctx, "k3"); Z3_ast k4 = mk_bool_var(ctx, "k4"); Z3_ast k5 = mk_bool_var(ctx, "k5"); Z3_ast k6 = mk_bool_var(ctx, "k6"); Z3_ast args1[5] = { k1, k2, k3, k4, k5 }; Z3_ast args2[3] = { k4, k5, k6 }; Z3_model m = 0; Z3_lbool result; printf("testing at-most-one constraint\n"); assert_at_most_one(ctx, s, 5, args1); assert_at_most_one(ctx, s, 3, args2); printf("it must be sat...\n"); result = Z3_solver_check(ctx, s); if (result != Z3_L_TRUE) error("BUG"); m = Z3_solver_get_model(ctx, s); Z3_model_inc_ref(ctx, m); printf("model:\n%s\n", Z3_model_to_string(ctx, m)); Z3_model_dec_ref(ctx, m); Z3_solver_assert(ctx, s, mk_binary_or(ctx, k2, k3)); Z3_solver_assert(ctx, s, mk_binary_or(ctx, k1, k6)); printf("it must be sat...\n"); result = Z3_solver_check(ctx, s); if (result != Z3_L_TRUE) error("BUG"); m = Z3_solver_get_model(ctx, s); Z3_model_inc_ref(ctx, m); printf("model:\n%s\n", Z3_model_to_string(ctx, m)); Z3_solver_assert(ctx, s, mk_binary_or(ctx, k4, k5)); printf("it must be unsat...\n"); result = Z3_solver_check(ctx, s); if (result != Z3_L_FALSE) error("BUG"); Z3_model_dec_ref(ctx, m); Z3_solver_dec_ref(ctx, s); Z3_del_context(ctx); }
int unsat_core(/*in*/ SOLVER_CONTEXT ctx, SOLVER_TERM * cs, unsigned cs_size, /*out*/ unsigned** bitvector_core){ /* Suppose the formula x=0 and y=2 and x>2. Then, we add a positive literal {p1,p2,p3} to each clause as follows: (x=0 or p1) and (y=2 or p2) and (x>2 or p3) but assuming that p1=0, p2=0, and p3=0 to keep unchanged the formula. Then, we run the solver. In this case, the conflict arises due to either: a) x=0 is true and x>2 is false or b) x=0 is false and x>2 is true How we can extract this information? Case a) T F T F F T (x=0 or p1) and (y=2 or p2) and (x>2 or p3) The conflict literal is p3 because p3=F Case b) F T T F T F (x=0 or p1) and (y=2 or p2) and (x>2 or p3) The conflict literal is p1 because p1=F Then, the solver will add the clause p1 or p3 which means that the unsatisfiable core is the 1st and 3rd constraint from the original formula. */ Z3_ast * assumptions; Z3_ast p; static char v[50]; Z3_ast g[2]; int i, ret, index; Z3_ast proof; Z3_model m = 0; Z3_lbool result; Z3_ast * cs_core; unsigned cs_core_size; unsigned * b; int bindex; assumptions = (Z3_ast *) malloc(sizeof(Z3_ast) * cs_size); if (assumptions == NULL){ fprintf(stderr,"No more memory! \n"); exit(1); } for(i = 0; i < cs_size; i++){ sprintf(v,"p_%d",i); p = mk_bool_var((Z3_context) ctx,v); g[0] = cs[i]; g[1] = p; Z3_assert_cnstr((Z3_context) ctx, Z3_mk_or((Z3_context)ctx, 2, g)); // c_i or p_i assumptions[i] = Z3_mk_not((Z3_context) ctx, p); // not p_i } // (not p_1),...,(not p_n) |- (c_1 OR p_1) AND ... AND (c_n OR p_n) cs_core = (Z3_ast *) calloc(cs_size,sizeof(Z3_ast)); cs_core_size = cs_size; result = Z3_check_assumptions((Z3_context) ctx, cs_size, assumptions, &m, &proof, &cs_core_size, cs_core); // all elements are initialized to 0 b = (unsigned *) calloc(cs_size, sizeof(unsigned)); if (b == NULL){ fprintf(stderr,"No more memory! \n"); exit(1); } // printf("Size of the unsat core %d\n",cs_core_size); switch (result) { case Z3_L_FALSE: for (i = 0; i < cs_core_size; ++i){ bindex =find_core_assumption_index((Z3_context) ctx, assumptions, cs_size, cs_core[i]); b[bindex] = (unsigned) 1u; } // printf("unsat\n"); ret = SOLVER_ANS_FALSE; break; case Z3_L_UNDEF: // printf("undefined\n"); ret = SOLVER_ANS_UNDEF; break; case Z3_L_TRUE: // printf("sat\n"); ret = SOLVER_ANS_TRUE; break; } if (m) { Z3_del_model(ctx, m); } *bitvector_core = b; return ret; }