-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathkripke.ml
164 lines (158 loc) · 5.41 KB
/
kripke.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
open Term
type kripke_env = {
n : int;
accessibility : int array array
}
let new_kripke_env sat_env n =
let accessibility = Array.init n (fun _ ->
Array.init n (fun _ -> Sat.fresh_var sat_env)) in
(* reflexivity *)
for i = 0 to (n-1) do
Sat.add_clause sat_env [| accessibility.(i).(i) |]
done;
(* transitivity *)
for i = 0 to (n-1) do
for j = 0 to (n-1) do
for k = 0 to (n-1) do
Sat.add_clause sat_env [|
accessibility.(i).(k);
-accessibility.(i).(j);
-accessibility.(j).(k)
|]
done
done
done;
(* Wi |=> Wj implies i <= j *)
for i = 0 to (n-1) do
for j = 0 to (n-1) do
if i > j then
Sat.add_clause sat_env [| -accessibility.(i).(j) |]
done
done;
{
n = n;
accessibility = accessibility
}
let rec make_clauses sat_env kripke_env term_memo t =
try
Hashtbl.find term_memo t
with Not_found ->
let varids = Array.init kripke_env.n (fun _ -> Sat.fresh_var sat_env) in
Hashtbl.add term_memo t varids;
begin match t with
| PVar _ ->
(* herediety *)
for i = 0 to (kripke_env.n-1) do
for j = 0 to (kripke_env.n-1) do
Sat.add_clause sat_env [|
-varids.(i); varids.(j); -kripke_env.accessibility.(i).(j) |];
done
done
| PArrow (t0, t1) ->
let varids0 = make_clauses sat_env kripke_env term_memo t0 in
let varids1 = make_clauses sat_env kripke_env term_memo t1 in
let varids2 =
Array.init kripke_env.n (fun _ -> Sat.fresh_var sat_env) in
(* varids2 = not varids0 or varids1 *)
for i = 0 to (kripke_env.n-1) do
Sat.add_clause sat_env [| varids2.(i); varids0.(i) |];
Sat.add_clause sat_env [| varids2.(i); -varids1.(i) |];
Sat.add_clause sat_env [| -varids2.(i); -varids0.(i); varids1.(i) |]
done;
(* varids = square varids2 *)
for i = 0 to (kripke_env.n-1) do
let varids3 =
Array.init kripke_env.n (fun _ -> Sat.fresh_var sat_env) in
for j = 0 to (kripke_env.n-1) do
Sat.add_clause sat_env [| varids3.(j); -varids2.(j) |];
Sat.add_clause sat_env [|
varids3.(j); kripke_env.accessibility.(i).(j) |];
Sat.add_clause sat_env [|
-varids3.(j); varids2.(j); -kripke_env.accessibility.(i).(j) |];
done;
Sat.add_clause sat_env (Array.init (kripke_env.n + 1) (fun j ->
if j == kripke_env.n then
varids.(i)
else
-varids3.(j)
));
for j = 0 to (kripke_env.n-1) do
Sat.add_clause sat_env [| -varids.(i); varids3.(j) |];
done
done
| POr (t0, t1) ->
let varids0 = make_clauses sat_env kripke_env term_memo t0 in
let varids1 = make_clauses sat_env kripke_env term_memo t1 in
for i = 0 to (kripke_env.n-1) do
Sat.add_clause sat_env [| varids.(i); -varids0.(i) |];
Sat.add_clause sat_env [| varids.(i); -varids1.(i) |];
Sat.add_clause sat_env [| -varids.(i); varids0.(i); varids1.(i) |]
done
| PAnd (t0, t1) ->
let varids0 = make_clauses sat_env kripke_env term_memo t0 in
let varids1 = make_clauses sat_env kripke_env term_memo t1 in
for i = 0 to (kripke_env.n-1) do
Sat.add_clause sat_env [| -varids.(i); varids0.(i) |];
Sat.add_clause sat_env [| -varids.(i); varids1.(i) |];
Sat.add_clause sat_env [| varids.(i); -varids0.(i); -varids1.(i) |]
done
| PTop ->
for i = 0 to (kripke_env.n-1) do
Sat.add_clause sat_env [| varids.(i) |]
done
| PBot ->
for i = 0 to (kripke_env.n-1) do
Sat.add_clause sat_env [| -varids.(i) |]
done
end;
varids
type kripke_result =
Refutable of int * bool array array * (pterm, bool array) Hashtbl.t
| Irrefutable
| NotDetermined
let solve_n penv n t =
let sat_env = Sat.new_environment () in
let kripke_env = new_kripke_env sat_env n in
let term_memo = Hashtbl.create 13 in
let varids = make_clauses sat_env kripke_env term_memo t in
Sat.add_clause sat_env [| -varids.(0) |];
let minisat_result = Sat.invoke_minisat sat_env in
begin match minisat_result with
| Sat.Satisfiable asgn ->
(* Format.eprintf "Satisfiable@."; *)
(* for x = 1 to sat_env.maxvar do
if asgn.(x) then
Format.eprintf "%d@." x
else
Format.eprintf "%d@." (-x)
done; *)
(* Hashtbl.iter (fun t0 varids0 ->
Format.eprintf "%a = @." (pp_print_pterm penv 5) t0;
Format.eprintf " [";
Array.iter (fun x ->
Format.eprintf "%d, " (if asgn.(x) then 1 else 0)
) varids0;
Format.eprintf "]@."
) term_memo; *)
let accessibility = Array.map (fun row ->
Array.map (fun v -> asgn.(v)) row
) kripke_env.accessibility in
let term_asgn = Hashtbl.create 47 in
Hashtbl.iter (fun t0 varids0 ->
Hashtbl.add term_asgn t0 (Array.map (fun x -> asgn.(x)) varids0)
) term_memo;
Refutable (n, accessibility, term_asgn)
| Sat.Unsatisfiable ->
(* Format.eprintf "Unsatisfiable@."; *)
Irrefutable
| Sat.NotDetermined ->
(* Format.eprintf "Not determined@."; *)
NotDetermined
end
let solve penv t =
let ret = ref Irrefutable in
for n = 2 to 4 do
if !ret = Irrefutable then
ret := solve_n penv n t
done;
!ret