Source file functorialisation.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
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
open Common
open Kernel
open Unchecked_types.Unchecked_types (Coh)
exception FunctorialiseMeta
exception NotClosed
exception Unsupported
let coh_depth1 = ref (fun _ -> Error.fatal "Uninitialised forward reference")
module Memo = struct
let tbl_whisk = Hashtbl.create 97
let find_whisk i f =
try Hashtbl.find tbl_whisk i
with Not_found ->
let res = f i in
Hashtbl.add tbl_whisk i res;
res
end
let check_upwards_closed ctx l =
let closed =
List.for_all
(fun x ->
List.for_all
(fun (y, (ty, _)) ->
(not (Unchecked.ty_contains_var ty x)) || List.mem y l)
ctx)
l
in
if not closed then raise NotClosed
let check_codim1 c n l =
let is_comdim1 =
List.for_all
(fun x ->
let ty, _ = List.assoc x c in
Unchecked.dim_ty ty >= n - 1)
l
in
if not is_comdim1 then raise Unsupported
let rec next_round l =
match l with
| [] -> ([], [])
| (_, 0) :: l ->
let vars, left = next_round l in
(vars, left)
| (v, n) :: l when n >= 1 ->
let vars, left = next_round l in
(v :: vars, (Var.Bridge v, n - 1) :: left)
| _ -> Error.fatal "cannot functorialise a negative number of times."
let compute_func_data l func =
let incr_db v i =
match v with Var.Db k -> Var.Db (k + i) | _ -> assert false
in
let is_mergeable =
match func with
| [] -> false
| f :: _ ->
List.for_all
(fun x ->
match List.assoc_opt x f with
| None -> false
| Some k -> List.for_all (fun (_, n) -> n <= k) f)
l
in
if is_mergeable then
let f, func =
match func with [] -> assert false | f :: func -> (f, func)
in
let rec add_in func v =
match func with
| [] -> [ (incr_db v 2, 1) ]
| (w, n) :: func when v = w -> (incr_db v 2, n + 1) :: func
| (w, n) :: func -> (incr_db w 2, n) :: add_in func v
in
let rec add_all func l =
match l with [] -> func | v :: l -> add_all (add_in func v) l
in
add_all f l :: func
else
let rec increase_in l =
match l with
| [] -> ([], 2)
| w :: l ->
let l, k = increase_in l in
((incr_db w k, 1) :: l, k + 2)
in
fst (increase_in l) :: func
let rec preimage ctx s l =
match (ctx, s) with
| [], [] -> []
| (x, _) :: c, (t, _) :: s when Unchecked.tm_contains_vars t l ->
x :: preimage c s l
| _ :: c, _ :: s -> preimage c s l
| [], _ :: _ | _ :: _, [] ->
Error.fatal "functorialisation in a non-existant place"
let rec tgt_subst l =
match l with [] -> [] | v :: tl -> (v, Var (Var.Plus v)) :: tgt_subst tl
let rec whisk n j k =
let build_whisk t =
let n, j, k = t in
let comp = Builtin.comp_n 2 in
let func_data = [ (Var.Db 4, k); (Var.Db 2, j) ] in
let whisk =
match coh_successively comp func_data with
| Coh (c, _), _ -> c
| _ -> assert false
in
Suspension.coh (Some n) whisk
in
Memo.find_whisk (n, j, k) build_whisk
and whisk_sub_ps k t1 ty1 t2 ty2 =
let rec take n l =
match l with h :: t when n > 0 -> h :: take (n - 1) t | _ -> []
in
let sub_base = Unchecked.ty_to_sub_ps ty1 in
let sub_ext = take ((2 * k) + 1) (Unchecked.ty_to_sub_ps ty2) in
List.concat [ [ (t2, true) ]; sub_ext; [ (t1, true) ]; sub_base ]
and src_prod t l tm tm_t d n =
match t with
| Arr (ty', src, _tgt) when Unchecked.tm_contains_vars src l ->
let whisk = whisk n 0 (d - n - 1) in
let _, whisk_ty, _ = Coh.forget whisk in
let prod, prod_ty = src_prod ty' l tm tm_t d (n - 1) in
let ty_f = ty ty' l src in
let src_f = tm_one_step_tm src l in
let sub_ps = whisk_sub_ps (d - n - 1) src_f ty_f prod prod_ty in
let sub = Unchecked.sub_ps_to_sub sub_ps in
(Coh (whisk, sub_ps), Unchecked.ty_apply_sub whisk_ty sub)
| Arr (_, _, _) | Obj -> (tm, tm_t)
| _ -> raise FunctorialiseMeta
and tgt_prod t l tm tm_t d n =
match t with
| Arr (ty', _src, tgt) when Unchecked.tm_contains_vars tgt l ->
let whisk = whisk n (d - n - 1) 0 in
let _, whisk_ty, _ = Coh.forget whisk in
let prod, prod_ty = tgt_prod ty' l tm tm_t d (n - 1) in
let ty_f = ty ty' l tgt in
let tgt_f = tm_one_step_tm tgt l in
let sub_ps = whisk_sub_ps 0 prod prod_ty tgt_f ty_f in
let sub = Unchecked.sub_ps_to_sub sub_ps in
(Coh (whisk, sub_ps), Unchecked.ty_apply_sub whisk_ty sub)
| Arr (_, _, _) | Obj -> (tm, tm_t)
| _ -> raise FunctorialiseMeta
and ty t l tm =
let d = Unchecked.dim_ty t in
let tgt_subst = tgt_subst l in
let tm_incl = Unchecked.tm_apply_sub tm tgt_subst in
let t_incl = Unchecked.ty_apply_sub t tgt_subst in
let src, src_t = tgt_prod t l tm t d (d - 1) in
let tgt, _tgt_t = src_prod t l tm_incl t_incl d (d - 1) in
Arr (src_t, src, tgt)
and ctx c l =
match c with
| [] -> []
| (x, (t, expl)) :: c when List.mem x l ->
let ty_tgt = Unchecked.ty_apply_sub t (tgt_subst l) in
let tf = ty t l (Var x) in
(Var.Bridge x, (tf, expl))
:: (Var.Plus x, (ty_tgt, false))
:: (x, (t, false))
:: ctx c l
| (x, a) :: c -> (x, a) :: ctx c l
and coh_depth0 coh l =
let ps, t, (name, susp, func) = Coh.forget coh in
let ctxf = ctx (Unchecked.ps_to_ctx ps) l in
let _, names, _ = Unchecked.db_levels ctxf in
let psf = PS.forget (PS.mk (Ctx.check ctxf)) in
let ty = ty t l (Coh (coh, Unchecked.identity_ps ps)) in
let ty = Unchecked.rename_ty ty names in
let func_data = compute_func_data l func in
check_coh psf ty (name, susp, func_data)
and coh coh l =
let ps, ty, _ = Coh.forget coh in
let c = Unchecked.ps_to_ctx ps in
check_upwards_closed c l;
let depth0 = List.for_all (fun (x, (_, e)) -> e || not (List.mem x l)) c in
let cohf =
if depth0 then
let id = Unchecked.identity_ps ps in
let sf = sub_ps id l in
let pscf = ctx (Unchecked.ps_to_ctx ps) l in
let cohf = coh_depth0 coh l in
(Coh (cohf, sf), pscf)
else (
check_codim1 c (Unchecked.dim_ty ty) l;
!coh_depth1 coh l)
in
cohf
and coh_successively c l =
let l, next = next_round l in
if l = [] then
let ps, _, _ = Coh.forget c in
let id = Unchecked.identity_ps ps in
(Coh (c, id), Unchecked.ps_to_ctx ps)
else
let cohf, ctxf = coh c l in
tm ctxf cohf next
and tm_one_step t l expl =
match t with
| Var v ->
[ (Var (Var.Bridge v), expl); (Var (Var.Plus v), false); (Var v, false) ]
| Coh (c, s) ->
let t' = Unchecked.tm_apply_sub t (tgt_subst l) in
let sf = sub_ps s l in
let ps, _, _ = Coh.forget c in
let psc = Unchecked.ps_to_ctx ps in
let places = preimage psc s l in
let cohf, pscf = coh c places in
let subf = Unchecked.list_to_sub (List.map fst sf) pscf in
let tm = Unchecked.tm_apply_sub cohf subf in
[ (tm, expl); (t', false); (t, false) ]
| Meta_tm _ -> raise FunctorialiseMeta
and tm_one_step_tm t l = fst (List.hd (tm_one_step t l true))
and sub_ps s l =
match s with
| [] -> []
| (t, expl) :: s ->
if not (Unchecked.tm_contains_vars t l) then (t, expl) :: sub_ps s l
else List.append (tm_one_step t l expl) (sub_ps s l)
and tm c t s =
let l, next = next_round s in
if l <> [] then
let c = ctx c l in
let t = tm_one_step_tm t l in
tm c t next
else (t, c)
let report_errors f str =
try f () with
| FunctorialiseMeta ->
Error.functorialisation (Lazy.force str)
"cannot functorialise meta-variables"
| NotClosed ->
Error.functorialisation (Lazy.force str)
"list of functorialised arguments is not closed"
| Unsupported ->
Error.functorialisation (Lazy.force str)
"higher-dimensional transformations in depth >= 0 are not yet supported"
let coh c l =
report_errors (fun _ -> coh c l) (lazy ("coherence: " ^ Coh.to_string c))
let coh_depth0 c l =
report_errors
(fun _ -> coh_depth0 c l)
(lazy ("coherence: " ^ Coh.to_string c))
let coh_successively c l =
report_errors
(fun _ -> coh_successively c l)
(lazy ("coherence: " ^ Coh.to_string c))
let rec sub s l =
match s with
| [] -> []
| (x, t) :: s when not (List.mem x l) -> (x, t) :: sub s l
| (x, t) :: s -> (
match tm_one_step t l true with
| [ (tm_f, _); (tgt_t, _); (src_t, _) ] ->
(Var.Bridge x, tm_f) :: (Var.Plus x, tgt_t) :: (x, src_t) :: sub s l
| [ (t, _) ] ->
Io.debug "no functorialisation needed for %s" (Var.to_string x);
(x, t) :: sub s l
| _ -> assert false)
let coh_all c =
let ps, _, _ = Coh.forget c in
let ct = Unchecked.ps_to_ctx ps in
let d = Unchecked.dim_ps ps in
let l =
List.filter_map
(fun (x, (ty, _)) -> if Unchecked.dim_ty ty = d then Some x else None)
ct
in
coh_depth0 c l
let tm c t s =
report_errors (fun _ -> tm c t s) (lazy ("term: " ^ Unchecked.tm_to_string t))
let ps p l =
let c = ctx (Unchecked.ps_to_ctx p) l in
let _, names, _ = Unchecked.db_levels c in
(PS.(forget (mk (Ctx.check c))), names)
let sub_w_tgt p s l =
let s_f = sub_ps s l in
let l = preimage (Unchecked.ps_to_ctx p) s l in
let p_f, names = ps p l in
(s_f, p_f, names, l)