#include <z3.h>
#include <stdio.h>
int main() {
Z3_config cfg = Z3_mk_config();
Z3_context ctx = Z3_mk_context(cfg);
Z3_del_config(cfg);
Z3_fixedpoint fp = Z3_mk_fixedpoint(ctx);
Z3_fixedpoint_inc_ref(ctx, fp);
// Declare predicates: edge(int, int), path(int, int)
Z3_sort int_sort = Z3_mk_int_sort(ctx);
Z3_sort domain[2] = {int_sort, int_sort};
Z3_func_decl edge = Z3_mk_func_decl(
ctx,
Z3_mk_string_symbol(ctx, "edge"),
2, domain, Z3_mk_bool_sort(ctx)
);
Z3_func_decl path = Z3_mk_func_decl(
ctx,
Z3_mk_string_symbol(ctx, "path"),
2, domain, Z3_mk_bool_sort(ctx)
);
Z3_fixedpoint_register_relation(ctx, fp, edge);
Z3_fixedpoint_register_relation(ctx, fp, path);
// Add facts: edge(1,2), edge(2,3)
unsigned fact1[2] = {1, 2};
unsigned fact2[2] = {2, 3};
Z3_fixedpoint_add_fact(ctx, fp, edge, 2, fact1);
Z3_fixedpoint_add_fact(ctx, fp, edge, 2, fact2);
// Add rules:
// path(x,y) :- edge(x,y)
// path(x,z) :- path(x,y), edge(y,z)
Z3_sort var_sorts[3] = {int_sort, int_sort, int_sort};
Z3_symbol var_names[3] = {
Z3_mk_string_symbol(ctx, "x"),
Z3_mk_string_symbol(ctx, "y"),
Z3_mk_string_symbol(ctx, "z")
};
Z3_ast x = Z3_mk_bound(ctx, 0, int_sort);
Z3_ast y = Z3_mk_bound(ctx, 1, int_sort);
Z3_ast z = Z3_mk_bound(ctx, 2, int_sort);
// Rule 1: path(x,y) :- edge(x,y)
Z3_ast edge_xy_args[2] = {x, y};
Z3_ast edge_xy = Z3_mk_app(ctx, edge, 2, edge_xy_args);
Z3_ast path_xy_args[2] = {x, y};
Z3_ast path_xy = Z3_mk_app(ctx, path, 2, path_xy_args);
Z3_ast rule1 = Z3_mk_implies(ctx, edge_xy, path_xy);
// Rule 2: path(x,z) :- path(x,y) and edge(y,z)
Z3_ast edge_yz_args[2] = {y, z};
Z3_ast edge_yz = Z3_mk_app(ctx, edge, 2, edge_yz_args);
Z3_ast path_xz_args[2] = {x, z};
Z3_ast path_xz = Z3_mk_app(ctx, path, 2, path_xz_args);
Z3_ast body_args[2] = {path_xy, edge_yz};
Z3_ast body = Z3_mk_and(ctx, 2, body_args);
Z3_ast rule2 = Z3_mk_implies(ctx, body, path_xz);
Z3_fixedpoint_add_rule(ctx, fp, rule1, 0);
Z3_fixedpoint_add_rule(ctx, fp, rule2, 0);
// Query: path(1, 3)?
Z3_ast one = Z3_mk_int(ctx, 1, int_sort);
Z3_ast three = Z3_mk_int(ctx, 3, int_sort);
Z3_ast query_args[2] = {one, three};
Z3_ast query = Z3_mk_app(ctx, path, 2, query_args);
Z3_lbool result = Z3_fixedpoint_query(ctx, fp, query);
if (result == Z3_L_TRUE) {
printf("Path(1,3) is derivable\n");
Z3_ast answer = Z3_fixedpoint_get_answer(ctx, fp);
printf("Derivation: %s\n", Z3_ast_to_string(ctx, answer));
} else {
printf("Path(1,3) is not derivable\n");
}
Z3_fixedpoint_dec_ref(ctx, fp);
Z3_del_context(ctx);
return 0;
}