forked from cubicle-model-checker/cubicle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvariable.ml
279 lines (222 loc) · 7.63 KB
/
variable.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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
(**************************************************************************)
(* *)
(* Cubicle *)
(* *)
(* Copyright (C) 2011-2014 *)
(* *)
(* Sylvain Conchon and Alain Mebsout *)
(* Universite Paris-Sud 11 *)
(* *)
(* *)
(* This file is distributed under the terms of the Apache Software *)
(* License version 2.0 *)
(* *)
(**************************************************************************)
open Options
open Format
type t = Hstring.t
type subst = (t * t) list
module Set = Hstring.HSet
let compare = Hstring.compare
let compare_list = Hstring.compare_list
let gen_vars s n =
let l = ref [] in
for i = 1 to max_proc do
l := Hstring.make (s^(string_of_int i)) :: !l
done;
List.rev !l
let alphas = gen_vars "$" max_proc
let procs = gen_vars "#" max_proc
let freshs = gen_vars "?" max_proc
let proc_vars_int =
let l = ref [] in
for i = 1 to max_proc do
l := i :: !l
done;
List.rev !l
let number v =
let s = Hstring.view v in
if s.[0] = '#' then
int_of_string (String.sub s 1 (String.length s - 1))
else 1
let is_proc v =
let s = Hstring.view v in
s.[0] = '#' || s.[0] = '$'
let build_subst args a_args =
let rec a_subst acc args a_args =
match args, a_args with
| [], _ -> List.rev acc
| x::args, ax::a_args ->
a_subst ((x, ax)::acc) args a_args
| _ -> assert false
in
a_subst [] args a_args
let is_subst_identity sigma =
List.for_all (fun (x,y) -> Hstring.equal x y) sigma
let well_formed_subst sigma =
try
ignore (
List.fold_left (fun (acc_x, acc_y) (x, y) ->
if Hstring.list_mem x acc_x || Hstring.list_mem y acc_y
then raise Exit;
x :: acc_x, y :: acc_y
) ([],[]) sigma);
true
with Exit -> false
let rec all_permutations_not_tail_recursive l1 l2 =
(*assert (List.length l1 <= List.length l2);*)
match l1 with
| [] -> [[]]
| x::l -> cross l [] x l2
and cross l pr x st =
match st with
| [] -> []
| y::p ->
let acc = all_permutations_not_tail_recursive l (pr@p) in
let acc =
if acc = [] then [[x,y]]
else List.map (fun ds -> (x, y)::ds) acc in
acc@(cross l (y::pr) x p)
let rec all_permutations l1 l2 =
(*assert (List.length l1 <= List.length l2);*)
match l1 with
| [] -> [[]]
| x::l -> cross l [] x l2
and cross l pr x st =
match st with
| [] -> []
| y::p ->
let acc = all_permutations l (List.rev_append pr p) in
let acc =
if acc = [] then [[x,y]]
else List.rev_map (fun ds -> (x, y)::ds) acc in
List.rev_append acc (cross l (y::pr) x p)
let rec all_parts l = match l with
| [] -> []
| [x] -> [[x]]
| x::r -> let pr = all_parts r in
[x]::pr@(List.map (fun p -> x::p) pr)
let all_parts_elem l = List.map (fun x -> [x]) l
let rec all_partial_permutations l1 l2 =
List.flatten (
List.fold_left (fun acc l -> (all_permutations l l2)::acc) [] (all_parts l1)
)
let rec all_arrangements n l =
assert (n > 0);
match n with
| 1 -> List.map (fun x -> [x]) l
| _ ->
List.fold_left (fun acc l' ->
List.fold_left (fun acc x -> (x :: l') :: acc) acc l
) [] (all_arrangements (n - 1) l)
let arity s = List.length (fst (Smt.Symbol.type_of s))
let rec all_arrangements_arity s l = all_arrangements (arity s) l
let rec all_instantiations l1 l2 =
match l1 with
| [] -> []
| [x1] -> List.map (fun x2 -> [x1, x2]) l2
| x1 :: r1 ->
List.fold_left (fun acc l' ->
List.fold_left (fun acc x2 -> ((x1, x2) :: l') :: acc) acc l2
) [] (all_instantiations r1 l2)
let rec mix x = function
| [] -> [[x]]
| y::r as l ->
(x :: l) :: (List.map (fun l' -> y :: l') (mix x r))
let rec interleave l1 l2 =
let rec aux acc = function
| [], [] -> acc
| l, [] | [], l -> List.map (List.rev_append l) acc
| (x :: r1 as l1), (y :: r2 as l2) ->
let acc1 = List.map (fun n -> x :: n) acc in
let acc1 = aux acc1 (r1, l2) in
let acc2 = List.map (fun n -> y :: n) acc in
let acc2 = aux acc2 (l1, r2) in
List.rev_append acc1 acc2
in
aux [[]] (List.rev l1, List.rev l2)
let rec perms = function
| [] -> [[]]
| x :: r -> List.flatten (List.map (mix x) (perms r))
(* renamed in extra_procs *)
(* let extra_args args tr_args = *)
(* let rec aux acc cpt = function *)
(* | [] -> List.rev acc *)
(* | _::r -> aux ((List.nth procs (cpt - 1)) :: acc) (cpt+1) r *)
(* in *)
(* aux [] (List.length args + 1) tr_args *)
let append_extra_procs_to acc args tr_args =
let rec aux acc args tr_args procs =
match args, tr_args, procs with
| [], [], _ -> List.rev acc
| [], x :: rtr, p :: rpr -> aux (p::acc) [] rtr rpr
| a :: ra, _, p :: rpr -> aux acc ra tr_args rpr
| _, _, [] -> failwith "Not enough procs"
in
aux (List.rev acc) args tr_args procs
let append_extra_procs args tr_args = append_extra_procs_to args args tr_args
let extra_procs args tr_args = append_extra_procs_to [] args tr_args
let rec first_n n l =
assert (n >= 0);
let rec aux acc = function
| 0, _ | _, [] -> List.rev acc
| n, x :: r -> aux (x :: acc) (n-1, r)
in aux [] (n, l)
let missing args tr_args extra =
let nb = List.length tr_args - List.length args in
if nb <= 0 then []
else first_n nb extra
let insert_missing l tr_args =
let ex = extra_procs l tr_args in
let ms = missing l tr_args ex in
List.flatten (List.map (fun x -> mix x l) ms)
let rec all_parts_max n l =
List.filter (fun p -> List.length p <= n) (all_parts l)
let permutations_missing tr_args l =
let parts = [] :: List.flatten
(List.map perms (all_parts_max (List.length tr_args) l))
in
let ex = extra_procs l tr_args in
let l' = List.fold_left
(fun acc l ->
let ms = missing l tr_args ex in
List.rev_append (interleave l ms) acc)
[] parts in
List.map (List.combine tr_args) l'
(* List.map (insert_missing tr_args) parts *)
let extra_vars vs1 vs2 =
let rec aux dif vs1 vs2 = match vs1, vs2 with
| [], [] -> dif
| _::_, [] -> vs1
| [], _::_ -> dif
| a::ra, b::rb -> aux dif ra rb
in
aux [] vs1 vs2
let give_procs n =
let rp, _ =
List.fold_left (fun (acc, n) v ->
if n > 0 then v :: acc, n - 1
else acc, n) ([], n) procs in
List.rev rp
let print fmt v = Hstring.print fmt v
let rec print_vars fmt = function
| [] -> ()
| [a] ->
let s = Hstring.view a in
let s = if dmcmt then (String.sub s 1 (String.length s - 1)) else s in
if dmcmt then fprintf fmt "_%s" s
else fprintf fmt "%s" s
| a::r ->
let s = Hstring.view a in
let s = if dmcmt then (String.sub s 1 (String.length s - 1)) else s in
if dmcmt then fprintf fmt "_%s%a" s print_vars r
else fprintf fmt "%s, %a" s print_vars r
let rec print_subst fmt = function
| [] -> ()
| [x,y] ->
fprintf fmt "%a -> %a" print x print y
| (x,y)::r ->
fprintf fmt "%a -> %a, %a" print x print y print_subst r
let subst sigma v =
try Hstring.list_assoc v sigma
with Not_found -> v