/** \brief Finds the maximal number of assumptions that can be satisfied. An assumption is any formula preceeded with the :assumption keyword. "Hard" constraints can be supported by using the :formula keyword. Input: file in SMT-LIB format, and MaxSAT algorithm to be used: 0 - Naive, 1 - Fu&Malik's algo. Output: the maximum number of assumptions that can be satisfied. */ int smtlib_maxsat(char * file_name, int approach) { Z3_context ctx; Z3_solver s; unsigned num_hard_cnstrs, num_soft_cnstrs; Z3_ast * hard_cnstrs, * soft_cnstrs; unsigned result = 0; ctx = mk_context(); s = Z3_mk_solver(ctx); Z3_parse_smtlib_file(ctx, file_name, 0, 0, 0, 0, 0, 0); hard_cnstrs = get_hard_constraints(ctx, &num_hard_cnstrs); soft_cnstrs = get_soft_constraints(ctx, &num_soft_cnstrs); switch (approach) { case NAIVE_MAXSAT: result = naive_maxsat(ctx, s, num_hard_cnstrs, hard_cnstrs, num_soft_cnstrs, soft_cnstrs); break; case FU_MALIK_MAXSAT: result = fu_malik_maxsat(ctx, s, num_hard_cnstrs, hard_cnstrs, num_soft_cnstrs, soft_cnstrs); break; default: /* Exercise: implement your own MaxSAT algorithm.*/ error("Not implemented yet."); break; } free_cnstr_array(hard_cnstrs); free_cnstr_array(soft_cnstrs); return result; }
int main(){ Z3_context context; Z3_solver solver; Z3_sort bvsort1; Z3_sort bvsort4; Z3_sort memsort; Z3_ast x_ast,y_ast,z_ast,u_ast,v_ast,w_ast,test_ast; Z3_model model; Z3_config config = Z3_mk_config(); Z3_set_param_value(config,"model","true"); context = Z3_mk_context_rc(config); Z3_set_error_handler(context,error_handler); solver = Z3_mk_solver(context); Z3_solver_inc_ref(context,solver); bvsort1 = Z3_mk_bv_sort(context,8); bvsort4 = Z3_mk_bv_sort(context,32); memsort = Z3_mk_array_sort(context,bvsort4,bvsort1); y_ast = Z3_mk_const(context,Z3_mk_string_symbol(context,"mem"),memsort); Z3_inc_ref(context,y_ast); u_ast = Z3_mk_unsigned_int64(context,13,bvsort4); Z3_inc_ref(context,u_ast); v_ast = Z3_mk_select(context,y_ast,u_ast); Z3_inc_ref(context,v_ast); z_ast = Z3_mk_unsigned_int64(context,7,bvsort1); Z3_inc_ref(context,z_ast); test_ast = Z3_mk_eq(context,v_ast,z_ast); Z3_inc_ref(context,test_ast); Z3_solver_assert(context,solver,test_ast); w_ast = Z3_mk_const(context,Z3_mk_string_symbol(context,"w"),bvsort1); y_ast = Z3_mk_store(context,y_ast,u_ast,w_ast); Z3_inc_ref(context,y_ast); v_ast = Z3_mk_select(context,y_ast,u_ast); Z3_inc_ref(context,v_ast); z_ast = Z3_mk_unsigned_int64(context,2,bvsort1); Z3_inc_ref(context,z_ast); test_ast = Z3_mk_eq(context,v_ast,z_ast); Z3_inc_ref(context,test_ast); Z3_solver_assert(context,solver,test_ast); Z3_solver_check(context,solver); model = Z3_solver_get_model(context,solver); fprintf(stderr,"%s\n",Z3_model_to_string(context,model)); fprintf(stderr,"%s\n",Z3_simplify_get_help(context)); return 0; }
Z3Solver::Z3Solver(Z3Ctx Ctx) : Z3Object(Ctx) { if (Ctx != Z3Ctx::NullPtr) { Solver = Z3_mk_solver(*Ctx); } else { Solver = nullptr; } if (Ctx != Z3Ctx::NullPtr && Solver != nullptr) { Z3_solver_inc_ref(*Ctx, Solver); } }
void z3_wrapper_init(z3_wrapper *z3) { /* init ctx */ Z3_config cfg = Z3_mk_config(); Z3_set_param_value(cfg, "model", "true"); z3->ctx = Z3_mk_context(cfg); /* init error handling */ Z3_set_error_handler(z3->ctx, z3_error_handler); /* init solver */ z3->solver = Z3_mk_solver(z3->ctx); Z3_solver_inc_ref(z3->ctx, z3->solver); Z3_del_config(cfg); z3->Ek_consts = NULL; }
/** \brief Small test for the at-most-one constraint. */ void tst_at_most_one() { Z3_context ctx = mk_context(); Z3_solver s = Z3_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); printf("model:\n%s\n", Z3_model_to_string(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); 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_del_context(ctx); }
Z3_solver mk_solver(Z3_context ctx) { Z3_solver r = Z3_mk_solver(ctx); Z3_solver_inc_ref(ctx, r); return r; }
bool Z3SolverImpl::internalRunSolver( const Query &query, const std::vector<const Array *> *objects, std::vector<std::vector<unsigned char> > *values, bool &hasSolution) { TimerStatIncrementer t(stats::queryTime); // NOTE: Z3 will switch to using a slower solver internally if push/pop are // used so for now it is likely that creating a new solver each time is the // right way to go until Z3 changes its behaviour. // // TODO: Investigate using a custom tactic as described in // https://github.com/klee/klee/issues/653 Z3_solver theSolver = Z3_mk_solver(builder->ctx); Z3_solver_inc_ref(builder->ctx, theSolver); Z3_solver_set_params(builder->ctx, theSolver, solverParameters); runStatusCode = SOLVER_RUN_STATUS_FAILURE; for (ConstraintManager::const_iterator it = query.constraints.begin(), ie = query.constraints.end(); it != ie; ++it) { Z3_solver_assert(builder->ctx, theSolver, builder->construct(*it)); } ++stats::queries; if (objects) ++stats::queryCounterexamples; Z3ASTHandle z3QueryExpr = Z3ASTHandle(builder->construct(query.expr), builder->ctx); // KLEE Queries are validity queries i.e. // ∀ X Constraints(X) → query(X) // but Z3 works in terms of satisfiability so instead we ask the // negation of the equivalent i.e. // ∃ X Constraints(X) ∧ ¬ query(X) Z3_solver_assert( builder->ctx, theSolver, Z3ASTHandle(Z3_mk_not(builder->ctx, z3QueryExpr), builder->ctx)); if (dumpedQueriesFile) { *dumpedQueriesFile << "; start Z3 query\n"; *dumpedQueriesFile << Z3_solver_to_string(builder->ctx, theSolver); *dumpedQueriesFile << "(check-sat)\n"; *dumpedQueriesFile << "(reset)\n"; *dumpedQueriesFile << "; end Z3 query\n\n"; dumpedQueriesFile->flush(); } ::Z3_lbool satisfiable = Z3_solver_check(builder->ctx, theSolver); runStatusCode = handleSolverResponse(theSolver, satisfiable, objects, values, hasSolution); Z3_solver_dec_ref(builder->ctx, theSolver); // Clear the builder's cache to prevent memory usage exploding. // By using ``autoClearConstructCache=false`` and clearning now // we allow Z3_ast expressions to be shared from an entire // ``Query`` rather than only sharing within a single call to // ``builder->construct()``. builder->clearConstructCache(); if (runStatusCode == SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE || runStatusCode == SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE) { if (hasSolution) { ++stats::queriesInvalid; } else { ++stats::queriesValid; } return true; // success } return false; // failed }