Z3_bool Z3_API Z3_eval(Z3_context c, Z3_model m, Z3_ast t, Z3_ast * v) { model_evaluator_params p; return Z3_model_eval(c, m, t, p.completion(), v); }
bool Z3SolverImpl::validateZ3Model(::Z3_solver &theSolver, ::Z3_model &theModel) { bool success = true; ::Z3_ast_vector constraints = Z3_solver_get_assertions(builder->ctx, theSolver); Z3_ast_vector_inc_ref(builder->ctx, constraints); unsigned size = Z3_ast_vector_size(builder->ctx, constraints); for (unsigned index = 0; index < size; ++index) { Z3ASTHandle constraint = Z3ASTHandle( Z3_ast_vector_get(builder->ctx, constraints, index), builder->ctx); ::Z3_ast rawEvaluatedExpr; bool successfulEval = Z3_model_eval(builder->ctx, theModel, constraint, /*model_completion=*/Z3_TRUE, &rawEvaluatedExpr); assert(successfulEval && "Failed to evaluate model"); // Use handle to do ref-counting. Z3ASTHandle evaluatedExpr(rawEvaluatedExpr, builder->ctx); Z3SortHandle sort = Z3SortHandle(Z3_get_sort(builder->ctx, evaluatedExpr), builder->ctx); assert(Z3_get_sort_kind(builder->ctx, sort) == Z3_BOOL_SORT && "Evaluated expression has wrong sort"); Z3_lbool evaluatedValue = Z3_get_bool_value(builder->ctx, evaluatedExpr); if (evaluatedValue != Z3_L_TRUE) { llvm::errs() << "Validating model failed:\n" << "The expression:\n"; constraint.dump(); llvm::errs() << "evaluated to \n"; evaluatedExpr.dump(); llvm::errs() << "But should be true\n"; success = false; } } if (!success) { llvm::errs() << "Solver state:\n" << Z3_solver_to_string(builder->ctx, theSolver) << "\n"; llvm::errs() << "Model:\n" << Z3_model_to_string(builder->ctx, theModel) << "\n"; } Z3_ast_vector_dec_ref(builder->ctx, constraints); return success; }
/** \brief Return the number of soft-constraints that were disable by the given model. A soft-constraint was disabled if the associated auxiliary variable was assigned to true. */ unsigned get_num_disabled_soft_constraints(Z3_context ctx, Z3_model m, unsigned num_soft_cnstrs, Z3_ast * aux_vars) { unsigned i; unsigned num_disabled = 0; Z3_ast t = Z3_mk_true(ctx); for (i = 0; i < num_soft_cnstrs; i++) { Z3_ast val; if (Z3_model_eval(ctx, m, aux_vars[i], 1, &val) == true) { // printf("%s", Z3_ast_to_string(ctx, aux_vars[i])); // printf(" -> %s\n", Z3_ast_to_string(ctx, val)); if (Z3_is_eq_ast(ctx, val, t)) { num_disabled++; } } } return num_disabled; }
void get_function(z3_wrapper *z3, Z3_func_decl fun, uint32_t fun_arity, struct fun *kfun) { Z3_model m = Z3_solver_get_model(z3->ctx, z3->solver); assert(m); /* printf("------\n%s\n------\n", Z3_model_to_string(z3->ctx, m)); */ Z3_model_inc_ref(z3->ctx, m); fun_init(kfun, fun_arity); for(size_t xs = 0; xs < int_pow(K, fun_arity); ++xs) { /* represent `xs` in the K-ary form, * with digits[0] being the highest digit. */ uint32_t digits[fun_arity]; get_K_digits(digits, fun_arity, xs); Z3_ast args[fun_arity]; for(size_t i = 0; i < fun_arity; ++i) { args[i] = z3->Ek_consts[digits[i]]; } /* eval func on given args */ Z3_ast t = Z3_mk_app(z3->ctx, fun, fun_arity, args); Z3_ast res; assert(Z3_model_eval(z3->ctx, m, t, 1, &res) == Z3_TRUE); /* printf("%s == %s\n", Z3_ast_to_string(z3->ctx, t), Z3_ast_to_string(z3->ctx, res)); */ /* interpret the result of function application */ uint64_t y; sscanf(Z3_ast_to_string(z3->ctx, res), "V%lu", &y); fun_set_val(kfun, xs, y); } Z3_model_dec_ref(z3->ctx, m); }
SolverImpl::SolverRunStatus Z3SolverImpl::handleSolverResponse( ::Z3_solver theSolver, ::Z3_lbool satisfiable, const std::vector<const Array *> *objects, std::vector<std::vector<unsigned char> > *values, bool &hasSolution) { switch (satisfiable) { case Z3_L_TRUE: { hasSolution = true; if (!objects) { // No assignment is needed assert(values == NULL); return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; } assert(values && "values cannot be nullptr"); ::Z3_model theModel = Z3_solver_get_model(builder->ctx, theSolver); assert(theModel && "Failed to retrieve model"); Z3_model_inc_ref(builder->ctx, theModel); values->reserve(objects->size()); for (std::vector<const Array *>::const_iterator it = objects->begin(), ie = objects->end(); it != ie; ++it) { const Array *array = *it; std::vector<unsigned char> data; data.reserve(array->size); for (unsigned offset = 0; offset < array->size; offset++) { // We can't use Z3ASTHandle here so have to do ref counting manually ::Z3_ast arrayElementExpr; Z3ASTHandle initial_read = builder->getInitialRead(array, offset); bool successfulEval = Z3_model_eval(builder->ctx, theModel, initial_read, /*model_completion=*/Z3_TRUE, &arrayElementExpr); assert(successfulEval && "Failed to evaluate model"); Z3_inc_ref(builder->ctx, arrayElementExpr); assert(Z3_get_ast_kind(builder->ctx, arrayElementExpr) == Z3_NUMERAL_AST && "Evaluated expression has wrong sort"); int arrayElementValue = 0; bool successGet = Z3_get_numeral_int(builder->ctx, arrayElementExpr, &arrayElementValue); assert(successGet && "failed to get value back"); assert(arrayElementValue >= 0 && arrayElementValue <= 255 && "Integer from model is out of range"); data.push_back(arrayElementValue); Z3_dec_ref(builder->ctx, arrayElementExpr); } values->push_back(data); } Z3_model_dec_ref(builder->ctx, theModel); return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_SOLVABLE; } case Z3_L_FALSE: hasSolution = false; return SolverImpl::SOLVER_RUN_STATUS_SUCCESS_UNSOLVABLE; case Z3_L_UNDEF: { ::Z3_string reason = ::Z3_solver_get_reason_unknown(builder->ctx, theSolver); if (strcmp(reason, "timeout") == 0 || strcmp(reason, "canceled") == 0) { return SolverImpl::SOLVER_RUN_STATUS_TIMEOUT; } if (strcmp(reason, "unknown") == 0) { return SolverImpl::SOLVER_RUN_STATUS_FAILURE; } llvm::errs() << "Unexpected solver failure. Reason is \"" << reason << "\"\n"; abort(); } default: llvm_unreachable("unhandled Z3 result"); } }