/** \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(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; }