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; }
vector<hb_ptr> encoding::get_hbs( z3::model& m ) { vector<hb_ptr> result; //todo: how does the following code knows to read from which solver? // the following looks in the context, not in solver ?? z3::expr_vector asserted = z3.c.collect_last_asserted_linear_constr(); z3::expr_vector asserted_po = z3.c.collect_last_asserted_po_constr(); for( unsigned i = 0; i<asserted.size(); i++ ) { z3::expr atom = asserted[i]; auto hb = get_hb( atom ); if( hb && !hb->loc1->special && !hb->loc2->special && hb->loc1->thread != hb->loc2->thread ) { if( hb->e1 && hb->e2 ) { // for compatibility of the earlier version of tara z3::expr v1 = m.eval( hb->e1->guard ); z3::expr v2 = m.eval( hb->e2->guard ); if( Z3_get_bool_value( v1.ctx(), v1) != Z3_L_TRUE || Z3_get_bool_value( v2.ctx(), v2) != Z3_L_TRUE ) { continue; } } assert(eval_hb(m, hb->loc1, hb->loc2)); hb_ptr h = make_shared<hb_enc::hb>(*hb); result.push_back(h); } } for( unsigned i = 0; i < asserted_po.size(); i++ ) { z3::expr atom = asserted_po[i]; // std::cout << atom << std::endl; auto hb = get_hb( atom ); if( hb && !hb->loc1->special && !hb->loc2->special && hb->loc1->thread != hb->loc2->thread ) { if( hb->e1 && hb->e2 ) { // for compatibility of the earlier version of tara z3::expr v1 = m.eval( hb->e1->guard ); z3::expr v2 = m.eval( hb->e2->guard ); if( Z3_get_bool_value( v1.ctx(), v1) != Z3_L_TRUE || Z3_get_bool_value( v2.ctx(), v2) != Z3_L_TRUE ) { continue; } } hb_ptr h = make_shared<hb_enc::hb>(*hb); result.push_back(h); // std::cerr << atom << "\n"; } } // current_rf_map.clear(); //get rf hbs for( auto& it : rf_map ) { std::string bname = std::get<0>(it); z3::expr b = z3.c.bool_const( bname.c_str() ); z3::expr bv = m.eval( b ); if( Z3_get_bool_value( bv.ctx(), bv) == Z3_L_TRUE ) { hb_enc::se_ptr wr = std::get<1>(it); hb_enc::se_ptr rd = std::get<2>(it); // z3::expr bp = z3::implies(wr->guard && rd->guard, b ); // z3::expr bp = z3::implies(wr->guard, b ); z3::expr bp = b; hb_ptr h = make_shared<hb_enc::hb>(wr, rd, bp, false, hb_t::rf); result.push_back( h ); current_rf_map.insert( std::make_pair( bname, h ) ); } } return result; }