Exemplo n.º 1
0
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);
  // TODO: Does making a new solver for each query have a performance
  // impact vs making one global solver and using push and pop?
  // TODO: is the "simple_solver" the right solver to use for
  // best performance?
  Z3_solver theSolver = Z3_mk_simple_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));

  ::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
}
Exemplo n.º 2
0
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;
}
static void tst_get_implied_equalities1() {
    Z3_config cfg = Z3_mk_config();
    Z3_context ctx = Z3_mk_context(cfg);
    Z3_del_config(cfg);
    Z3_sort int_ty = Z3_mk_int_sort(ctx);
    Z3_ast a = mk_int_var(ctx,"a");
    Z3_ast b = mk_int_var(ctx,"b");
    Z3_ast c = mk_int_var(ctx,"c");
    Z3_ast d = mk_int_var(ctx,"d");
    Z3_func_decl f = Z3_mk_func_decl(ctx, Z3_mk_string_symbol(ctx,"f"), 1, &int_ty, int_ty);
    Z3_ast fa = Z3_mk_app(ctx, f, 1, &a);
    Z3_ast fb = Z3_mk_app(ctx, f, 1, &b);
    Z3_ast fc = Z3_mk_app(ctx, f, 1, &c);
    unsigned const num_terms = 7;
    unsigned i;
    Z3_ast terms[7] = { a, b, c, d, fa, fb, fc };
    unsigned class_ids[7] = { 0, 0, 0, 0, 0, 0, 0 };
    Z3_solver solver = Z3_mk_simple_solver(ctx);
    Z3_solver_inc_ref(ctx, solver);
        
    Z3_solver_assert(ctx, solver, Z3_mk_eq(ctx, a, b));
    Z3_solver_assert(ctx, solver, Z3_mk_eq(ctx, b, d));
    Z3_solver_assert(ctx, solver, Z3_mk_le(ctx, fa, fc));
    Z3_solver_assert(ctx, solver, Z3_mk_le(ctx, fc, d));
    
    Z3_get_implied_equalities(ctx, solver, num_terms, terms, class_ids);
    for (i = 0; i < num_terms; ++i) {
        printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]);
    }
    SASSERT(class_ids[1] == class_ids[0]);
    SASSERT(class_ids[2] != class_ids[0]);
    SASSERT(class_ids[3] == class_ids[0]);
    SASSERT(class_ids[4] != class_ids[0]);
    SASSERT(class_ids[5] != class_ids[0]);
    SASSERT(class_ids[6] != class_ids[0]);
    SASSERT(class_ids[4] == class_ids[5]);

    printf("asserting b <= f(a)\n");
    Z3_solver_assert(ctx, solver, Z3_mk_le(ctx, b, fa));
    Z3_get_implied_equalities(ctx, solver, num_terms, terms, class_ids);
    for (i = 0; i < num_terms; ++i) {
        printf("Class %s |-> %d\n", Z3_ast_to_string(ctx, terms[i]), class_ids[i]);
    }
    SASSERT(class_ids[1] == class_ids[0]);
    SASSERT(class_ids[2] != class_ids[0]);
    SASSERT(class_ids[3] == class_ids[0]);
    SASSERT(class_ids[4] == class_ids[0]);
    SASSERT(class_ids[5] == class_ids[0]);
    SASSERT(class_ids[6] == class_ids[0]);

    
    Z3_solver_dec_ref(ctx, solver);
    /* delete logical context */
    Z3_del_context(ctx);    
}
Exemplo n.º 4
0
/**
   \brief Assert hard constraints stored in the given array.
*/
void assert_hard_constraints(Z3_context ctx, Z3_solver s, unsigned num_cnstrs, Z3_ast * cnstrs) 
{
    unsigned i;
    for (i = 0; i < num_cnstrs; i++) {
        Z3_solver_assert(ctx, s, cnstrs[i]);
    }
}
/* (declare-fun p_name (E3 E3 ...) Bool) */
Z3_func_decl gen_pred(z3_wrapper *z3, const char *name, const pred *pred) {
  Z3_symbol symb = Z3_mk_string_symbol(z3->ctx, name);
  Z3_sort domain[pred->arity];
  for(size_t i = 0; i < pred->arity; ++i) {
      domain[i] = z3->Ek_sort;
  }
  Z3_sort range = Z3_mk_bool_sort(z3->ctx);
  Z3_func_decl p = Z3_mk_func_decl(z3->ctx, symb, pred->arity, domain, range);
  
  /* create assertions */
  for(size_t xs = 0; xs < int_pow(K, pred->arity); ++xs) {
    /* represent `xs` in the K-ary form,
     * with digits[0] being the highest digit. */
    uint32_t digits[pred->arity];
    get_K_digits(digits, pred->arity, xs);
    
    Z3_ast args[pred->arity];
    for(size_t i = 0; i < pred->arity; ++i) {
      args[i] = z3->Ek_consts[digits[i]];
    }
    Z3_ast phi = Z3_mk_app(z3->ctx, p, pred->arity, args);

    /* if the predicate equals to false on `xs` */
    if(!pred_compute(pred, xs)) {
      phi = Z3_mk_not(z3->ctx, phi);
    }

    /* printf("\n%s\n", Z3_ast_to_string(z3->ctx, phi)); */
    Z3_solver_assert(z3->ctx, z3->solver, phi);
  }

  return p;
}
Exemplo n.º 6
0
/**
   \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);
}
Exemplo n.º 7
0
/**
   \brief Assert soft constraints stored in the given array.
   This function will assert each soft-constraint C_i as (C_i or k_i) where k_i is a fresh boolean variable.
   It will also return an array containing these fresh variables.
*/
Z3_ast * assert_soft_constraints(Z3_context ctx, Z3_solver s, unsigned num_cnstrs, Z3_ast * cnstrs) 
{
    unsigned i;
    Z3_ast * aux_vars;
    aux_vars = mk_fresh_bool_var_array(ctx, num_cnstrs);
    for (i = 0; i < num_cnstrs; i++) {
        Z3_ast assumption = cnstrs[i];
        Z3_solver_assert(ctx, s, mk_binary_or(ctx, assumption, aux_vars[i]));
    }
    return aux_vars;
}
Exemplo n.º 8
0
/**
  \brief Implement one step of the Fu&Malik algorithm.
  See fu_malik_maxsat function for more details.
  
  Input:    soft constraints + aux-vars (aka answer literals) 
  Output:   done/not-done  when not done return updated set of soft-constraints and aux-vars. 
  - if SAT --> terminates
  - if UNSAT 
     * compute unsat core
     * add blocking variable to soft-constraints in the core
         - replace soft-constraint with the one with the blocking variable
         - we should also add an aux-var
         - replace aux-var with a new one
     * add at-most-one constraint with blocking 
*/
int fu_malik_maxsat_step(Z3_context ctx, Z3_solver s, unsigned num_soft_cnstrs, Z3_ast * soft_cnstrs, Z3_ast * aux_vars) 
{
    // create assumptions
    Z3_ast * assumptions = (Z3_ast*) malloc(sizeof(Z3_ast) * num_soft_cnstrs);
    Z3_lbool is_sat;
    Z3_ast_vector core;
    unsigned core_size;
    unsigned i = 0;
    unsigned k = 0;
    Z3_ast * block_vars;
    for (i = 0; i < num_soft_cnstrs; i++) {
        // Recall that we asserted (soft_cnstrs[i] \/ aux_vars[i])
        // So using (NOT aux_vars[i]) as an assumption we are actually forcing the soft_cnstrs[i] to be considered.
        assumptions[i] = Z3_mk_not(ctx, aux_vars[i]);
    }
    
    is_sat = Z3_solver_check_assumptions(ctx, s, num_soft_cnstrs, assumptions);
    if (is_sat != Z3_L_FALSE) {
        return 1; // done
    }
    else {
        core = Z3_solver_get_unsat_core(ctx, s);
        Z3_ast_vector_inc_ref(ctx, core);
	core_size = Z3_ast_vector_size(ctx, core);
        block_vars = (Z3_ast*) malloc(sizeof(Z3_ast) * core_size);
        k = 0;
        // update soft-constraints and aux_vars
        for (i = 0; i < num_soft_cnstrs; i++) {
            unsigned j;
            // check whether assumption[i] is in the core or not
            for (j = 0; j < core_size; j++) {
              if (assumptions[i] == Z3_ast_vector_get(ctx, core, j))
                    break;
            }
            if (j < core_size) {
                // assumption[i] is in the unsat core... so soft_cnstrs[i] is in the unsat core
                Z3_ast block_var   = mk_fresh_bool_var(ctx);
                Z3_ast new_aux_var = mk_fresh_bool_var(ctx);
                soft_cnstrs[i]     = mk_binary_or(ctx, soft_cnstrs[i], block_var);
                aux_vars[i]        = new_aux_var;
                block_vars[k]      = block_var;
                k++;
                // Add new constraint containing the block variable.
                // Note that we are using the new auxiliary variable to be able to use it as an assumption.
                Z3_solver_assert(ctx, s, mk_binary_or(ctx, soft_cnstrs[i], new_aux_var));
            }
        }
        assert_at_most_one(ctx, s, k, block_vars);
        Z3_ast_vector_dec_ref(ctx, core);
        return 0; // not done.
    }
}
Exemplo n.º 9
0
/**
   \brief Given an integer val encoded in n bits (boolean variables), assert the constraint that val <= k.
*/
void assert_le_k(Z3_context ctx, Z3_solver s, unsigned n, Z3_ast * val, unsigned k) 
{
    Z3_ast i1, i2, not_val, out;
    unsigned idx;
    not_val = Z3_mk_not(ctx, val[0]);
    if (get_bit(k, 0))
        out = Z3_mk_true(ctx);
    else
        out = not_val;
    for (idx = 1; idx < n; idx++) {
        not_val = Z3_mk_not(ctx, val[idx]);
        if (get_bit(k, idx)) {
            i1 = not_val;
            i2 = out;
        }
        else {
            i1 = Z3_mk_false(ctx);
            i2 = Z3_mk_false(ctx);
        }
        out = mk_ternary_or(ctx, i1, i2, mk_binary_and(ctx, not_val, out));
    }
    // printf("at-most-k:\n%s\n", Z3_ast_to_string(ctx, out));
    Z3_solver_assert(ctx, s, out);
}
Exemplo n.º 10
0
void gen_preserve(z3_wrapper *z3, int not_preserve, Z3_func_decl fun, uint32_t fun_arity, Z3_func_decl pred, uint32_t pred_arity) {
  /* create bound variables */
  Z3_ast bound_vars[fun_arity][pred_arity];
  size_t idx = fun_arity * pred_arity - 1;
  for(int i = 0; i < fun_arity; ++i) {
    for(int j = 0; j < pred_arity; ++j) {
      bound_vars[i][j] = Z3_mk_bound(z3->ctx, idx, z3->Ek_sort);
      --idx;
    }
  }

  /* create left-hand side of implication */
  Z3_ast t1;
  if(fun_arity == 0) {
    t1 = Z3_mk_true(z3->ctx);
  } else { /* fun_arity >= 1*/
    Z3_ast and_args[fun_arity];
    for(int i = 0; i < fun_arity; ++i) {
      Z3_ast pred_args[pred_arity];
      for(int j = 0; j < pred_arity; ++j) {
        pred_args[j] = bound_vars[i][j];
      }
      and_args[i] = Z3_mk_app(z3->ctx, pred, pred_arity, pred_args);
    }
    t1 = Z3_mk_and(z3->ctx, fun_arity, and_args);
  }
  
  /* create right-hand side of implication */
  Z3_ast pred_args[pred_arity];
  for(int j = 0; j < pred_arity; ++j) {
    Z3_ast fun_args[fun_arity];
    for(int i = 0; i < fun_arity; ++i) {
      fun_args[i] = bound_vars[i][j];
    }
    pred_args[j] = Z3_mk_app(z3->ctx, fun, fun_arity, fun_args);
  }
  Z3_ast t2 = Z3_mk_app(z3->ctx, pred, pred_arity, pred_args);

  /* create implication */
  Z3_ast body = Z3_mk_implies(z3->ctx, t1, t2);

  /* create quantified formula phi */
  size_t num_decls = fun_arity * pred_arity;
  Z3_sort sorts[num_decls];
  for(int i = 0; i < num_decls; ++i) {
    sorts[i] = z3->Ek_sort;
  }
  Z3_symbol decl_names[num_decls];
  idx = fun_arity * pred_arity - 1;
  for(int i = 0; i < fun_arity; ++i) {
    for(int j = 0; j < pred_arity; ++j) {
      char s[16];
      sprintf(s, "x%d_%d ", i, j);
      decl_names[idx] = Z3_mk_string_symbol(z3->ctx, s);
      --idx;
    }
  }
  Z3_ast phi = Z3_mk_forall(z3->ctx, 0, 0, NULL, num_decls, sorts, decl_names, body);

  if(not_preserve) {
    phi = Z3_mk_not(z3->ctx, phi);
  }

  /* printf("\n%s\n", Z3_ast_to_string(z3->ctx, phi)); */
  Z3_solver_assert(z3->ctx, z3->solver, phi);
}
Exemplo n.º 11
0
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
}