Пример #1
0
/**
  \brief Finds the maximal number of assumptions that can be satisfied.
  An assumption is any formula preceded 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 i;
    Z3_optimize opt;
    unsigned num_hard_cnstrs, num_soft_cnstrs;
    Z3_ast * hard_cnstrs, * soft_cnstrs;
    Z3_ast_vector  hard, objs;
    Z3_app soft;
    unsigned result = 0;
    ctx = mk_context();
    s = mk_solver(ctx);
    opt = Z3_mk_optimize(ctx);
    Z3_optimize_inc_ref(ctx, opt);
    Z3_optimize_from_file(ctx, opt, file_name);
    hard = Z3_optimize_get_assertions(ctx, opt);
    Z3_ast_vector_inc_ref(ctx, hard);
    num_hard_cnstrs = Z3_ast_vector_size(ctx, hard);
    hard_cnstrs = (Z3_ast *) malloc(sizeof(Z3_ast) * (num_hard_cnstrs));
    for (i = 0; i < num_hard_cnstrs; i++) {
        hard_cnstrs[i] = Z3_ast_vector_get(ctx, hard, i);
    }
    objs = Z3_optimize_get_objectives(ctx, opt);
    Z3_ast_vector_inc_ref(ctx, objs);

    // soft constraints are stored in a single objective which is a sum 
    // of if-then-else expressions.
    soft = Z3_to_app(ctx, Z3_ast_vector_get(ctx, objs, 0));
    num_soft_cnstrs = Z3_get_app_num_args(ctx, soft);
    soft_cnstrs = (Z3_ast *) malloc(sizeof(Z3_ast) * (num_soft_cnstrs));
    for (i = 0; i < num_soft_cnstrs; ++i) {
        soft_cnstrs[i] = Z3_get_app_arg(ctx, Z3_to_app(ctx, Z3_get_app_arg(ctx, soft, i)), 0);
    }
    
    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);
    Z3_solver_dec_ref(ctx, s);
    Z3_optimize_dec_ref(ctx, opt);
    return result;
}
Пример #2
0
void display_solver_term(SOLVER_CONTEXT ctx, FILE * out, SOLVER_TERM term){

  Z3_context c = (Z3_context) ctx;
  Z3_ast     v = (Z3_ast) term;

  switch (Z3_get_ast_kind(c, v)) {
  case Z3_NUMERAL_AST: {
    Z3_sort t;
    fprintf(out, "%s", Z3_get_numeral_string(c, v));
    t = Z3_get_sort(c, v);
    fprintf(out, ":");
    display_sort(c, out, t);
    break;
  }
  case Z3_APP_AST: {
    unsigned i;
    Z3_app app = Z3_to_app(c, v);
    unsigned num_fields = Z3_get_app_num_args(c, app);
    Z3_func_decl d = Z3_get_app_decl(c, app);
    fprintf(out, "%s", Z3_func_decl_to_string(c, d));
    if (num_fields > 0) {
      fprintf(out, "[");
      for (i = 0; i < num_fields; i++) {
	if (i > 0) {
	  fprintf(out, ", ");
	}
	display_solver_term((SOLVER_CONTEXT) c, 
			    out, 
			    (SOLVER_TERM) Z3_get_app_arg(c, app, i));
      }
      fprintf(out, "]");
    }
    break;
  }
  case Z3_QUANTIFIER_AST: {
    fprintf(out, "quantifier");
    ;
  }
  default:
    fprintf(out, "#unknown");
  }
}
Пример #3
0
int main(int argc, const char **argv) {

  /* Create a Z3 context to contain formulas */

  Z3_config cfg = Z3_mk_config();
  Z3_context ctx = iz3_mk_context(cfg);
  Z3_set_error_handler(ctx, throw_z3_error);
    
  /* Make some constraints, by parsing an smtlib formatted file given as arg 1 */

  try {
    Z3_parse_smtlib_file(ctx, argv[1], 0, 0, 0, 0, 0, 0);
  }
  catch(const z3_error &err){
    std::cerr << "Z3 error: " << Z3_get_error_msg(err.c) << "\n";
    std::cerr << Z3_get_smtlib_error(ctx) << "\n";
    return(1);
  } 

  /* Get the constraints from the parser. */

  int num = Z3_get_smtlib_num_formulas(ctx);

  if(num == 0){
    std::cerr << "iZ3 error: File contains no formulas.\n";
    return 1;
  }


  Z3_ast *constraints = (Z3_ast *)malloc(num * sizeof(Z3_ast));

  int i;
  for (i = 0; i < num; i++)
    constraints[i] = Z3_get_smtlib_formula(ctx, i);

  /* if we get only one formula, and it is a conjunction, split it into conjuncts. */
  if(num == 1){
    Z3_app app = Z3_to_app(ctx,constraints[0]);
    Z3_func_decl func = Z3_get_app_decl(ctx,app);
    Z3_decl_kind dk = Z3_get_decl_kind(ctx,func);
    if(dk == Z3_OP_AND){
      int nconjs = Z3_get_app_num_args(ctx,app);
      if(nconjs > 1){
	std::cout << "Splitting formula into " << nconjs << " conjuncts...\n";
	num = nconjs;
	constraints = new Z3_ast[num];
	for(int k = 0; k < num; k++)
	  constraints[k] = Z3_get_app_arg(ctx,app,k);
      }
    }
  }


  /* print out the result for grins. */

  // Z3_string smtout = Z3_benchmark_to_smtlib_string (ctx, "foo", "QFLIA", "sat", "", num, constraints, Z3_mk_true(ctx));

  // Z3_string smtout = Z3_ast_to_string(ctx,constraints[0]);
  // Z3_string smtout = Z3_context_to_string(ctx);
  // puts(smtout);

  // iz3_print(ctx,num,constraints,"iZ3temp.smt");

  /* Make room for interpolants. */

  Z3_ast *interpolants = (Z3_ast *)malloc((num-1) * sizeof(Z3_ast));

  /* Make room for the model. */

  Z3_model model = 0;

  /* Call the prover */

  Z3_lbool result = iz3_interpolate(ctx, num, constraints, interpolants, &model);

  switch (result) {
  
    /* If UNSAT, print the interpolants */
  case Z3_L_FALSE:
    printf("unsat, interpolants:\n");
    for(i = 0; i < num-1; i++)
      printf("%s\n", Z3_ast_to_string(ctx, interpolants[i]));
    std::cout << "Checking interpolants...\n";
    const char *error;
    if(iZ3_check_interpolant(ctx, num, constraints, 0, interpolants, &error))
      std::cout << "Interpolant is correct\n";
    else {
      std::cout << "Interpolant is incorrect\n";
      std::cout << error << "\n";
    }
    break;
  case Z3_L_UNDEF:
    printf("fail\n");
    break;
  case Z3_L_TRUE:
    printf("sat\n");
    printf("model:\n%s\n", Z3_model_to_string(ctx, model));
    break;
  }

  /* Delete the model if there is one */
  
  if (model)
    Z3_del_model(ctx, model);
  
  /* Delete logical context (note, we call iz3_del_context, not
     Z3_del_context */

  iz3_del_context(ctx);

  return 0;
}
Пример #4
0
int main(int argc, const char **argv) {
    
  bool tree_mode = false;
  bool check_mode = false;
  bool profile_mode = false;
  bool incremental_mode = false;
  std::string output_file;
  bool flat_mode = false;
  bool anonymize = false;
  bool write = false;

  Z3_config cfg = Z3_mk_config();
  // Z3_interpolation_options options = Z3_mk_interpolation_options();
  Z3_params options = 0;

  /* Parse the command line */
  int argn = 1;
  while(argn < argc-1){
    std::string flag = argv[argn];
    if(flag[0] == '-'){
      if(flag == "-t" || flag == "--tree")
	tree_mode = true;
      else if(flag == "-c" || flag == "--check")
	check_mode = true;
      else if(flag == "-p" || flag == "--profile")
	profile_mode = true;
#if 0
      else if(flag == "-w" || flag == "--weak")
        Z3_set_interpolation_option(options,"weak","1");
      else if(flag == "--secondary")
        Z3_set_interpolation_option(options,"secondary","1");
#endif
      else if(flag == "-i" || flag == "--incremental")
        incremental_mode = true;
      else if(flag == "-o"){
        argn++;
        if(argn >= argc) return usage(argv);
        output_file = argv[argn];
      }
      else if(flag == "-f" || flag == "--flat")
        flat_mode = true;
      else if(flag == "-a" || flag == "--anon")
        anonymize = true;
      else if(flag == "-w" || flag == "--write")
        write = true;
      else if(flag == "-s" || flag == "--simple")
        Z3_set_param_value(cfg,"PREPROCESS","false");
      else
        return usage(argv);
    }
    argn++;
  }
  if(argn != argc-1)
    return usage(argv);
  const char *filename = argv[argn];


  /* Create a Z3 context to contain formulas */
  Z3_context ctx = Z3_mk_interpolation_context(cfg);

  if(write || anonymize)
    Z3_set_ast_print_mode(ctx,Z3_PRINT_SMTLIB2_COMPLIANT);
  else if(!flat_mode)
    Z3_set_ast_print_mode(ctx,Z3_PRINT_SMTLIB_COMPLIANT);
  
  /* Read an interpolation problem */

  unsigned num;
  Z3_ast *constraints;
  unsigned *parents = 0;
  const char *error;
  bool ok;
  unsigned num_theory;
  Z3_ast *theory;

  ok = Z3_read_interpolation_problem(ctx, &num, &constraints, tree_mode ? &parents : 0, filename, &error, &num_theory, &theory);

  /* If parse failed, print the error message */

  if(!ok){
    std::cerr << error << "\n";
    return 1;
  }

  /* if we get only one formula, and it is a conjunction, split it into conjuncts. */
  if(!tree_mode && num == 1){
    Z3_app app = Z3_to_app(ctx,constraints[0]);
    Z3_func_decl func = Z3_get_app_decl(ctx,app);
    Z3_decl_kind dk = Z3_get_decl_kind(ctx,func);
    if(dk == Z3_OP_AND){
      int nconjs = Z3_get_app_num_args(ctx,app);
      if(nconjs > 1){
	std::cout << "Splitting formula into " << nconjs << " conjuncts...\n";
	num = nconjs;
	constraints = new Z3_ast[num];
	for(int k = 0; k < num; k++)
	  constraints[k] = Z3_get_app_arg(ctx,app,k);
      }
    }
  }

  /* Write out anonymized version. */

  if(write || anonymize){
#if 0
    Z3_anonymize_ast_vector(ctx,num,constraints);
#endif
    std::string ofn = output_file.empty() ? "iz3out.smt2" : output_file;
    Z3_write_interpolation_problem(ctx, num, constraints, parents, ofn.c_str(), num_theory,  theory);
    std::cout << "anonymized problem written to " << ofn << "\n";
    exit(0);
  }

  /* Compute an interpolant, or get a model. */

  Z3_ast *interpolants = (Z3_ast *)malloc((num-1) * sizeof(Z3_ast));
  Z3_model model = 0;
  Z3_lbool result;

  if(!incremental_mode){
    /* In non-incremental mode, we just pass the constraints. */
      result = Z3_L_UNDEF; // FIXME: Z3_interpolate(ctx, num, constraints, parents,  options, interpolants, &model, 0, false, num_theory, theory);
  }
  else {

    /* This is a somewhat useless demonstration of incremental mode.
      Here, we assert the constraints in the context, then pass them to
      iZ3 in an array, so iZ3 knows the sequence. Note it's safe to pass
      "true", even though we haven't techically asserted if. */

    Z3_push(ctx);
    std::vector<Z3_ast> asserted(num);

    /* We start with nothing asserted. */
    for(int i = 0; i < num; i++)
      asserted[i] = Z3_mk_true(ctx);

    /* Now we assert the constrints one at a time until UNSAT. */

    for(int i = 0; i < num; i++){
      asserted[i] = constraints[i];
      Z3_assert_cnstr(ctx,constraints[i]);  // assert one constraint
      result = Z3_L_UNDEF; // FIXME: Z3_interpolate(ctx, num, &asserted[0], parents,  options, interpolants, &model, 0, true, 0, 0);
      if(result == Z3_L_FALSE){
	for(unsigned j = 0; j < num-1; j++)
          /* Since we want the interpolant formulas to survive a "pop", we
            "persist" them here. */
          Z3_persist_ast(ctx,interpolants[j],1);
        break;
      }
    }
    Z3_pop(ctx,1);
  }
  
  switch (result) {
  
    /* If UNSAT, print the interpolants */
  case Z3_L_FALSE:
    printf("unsat\n");
    if(output_file.empty()){
      printf("interpolant:\n");
      for(int i = 0; i < num-1; i++)
        printf("%s\n", Z3_ast_to_string(ctx, interpolants[i]));
    }
    else {
#if 0
      Z3_write_interpolation_problem(ctx,num-1,interpolants,0,output_file.c_str());
      printf("interpolant written to %s\n",output_file.c_str());
#endif
    }
#if 1
    if(check_mode){
      std::cout << "Checking interpolant...\n";
      bool chk;
      chk = Z3_check_interpolant(ctx,num,constraints,parents,interpolants,&error,num_theory,theory);  
      if(chk)
	std::cout << "Interpolant is correct\n";
      else {
        std::cout << "Interpolant is incorrect\n";
        std::cout << error;
        return 1;
      }
    }
#endif
    break;
  case Z3_L_UNDEF:
    printf("fail\n");
    break;
  case Z3_L_TRUE:
    printf("sat\n");
    printf("model:\n%s\n", Z3_model_to_string(ctx, model));
    break;
  }

  if(profile_mode)
    std::cout << Z3_interpolation_profile(ctx);

  /* Delete the model if there is one */
  
  if (model)
    Z3_del_model(ctx, model);
  
  /* Delete logical context. */

  Z3_del_context(ctx);
  free(interpolants);

  return 0;
}