forked from CakeML/candle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
firstorder.ml
257 lines (204 loc) · 8.19 KB
/
firstorder.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
(* ========================================================================= *)
(* General facilities for manipulating first-order shadow terms. *)
(* *)
(* (c) Copyright, Michael Faerber and Cezary Kaliszyk, 2014-2018. *)
(* ========================================================================= *)
needs "meson.ml";;
(* ------------------------------------------------------------------------- *)
(* Controls verbosity of these and the main CoP functions. *)
(* ------------------------------------------------------------------------- *)
let copverb = ref false;; (* Controls output verbosity of the CoPs *)
(* ------------------------------------------------------------------------- *)
(* Misc utility functions. *)
(* ------------------------------------------------------------------------- *)
module Utils = struct
let ( %> ) f g x = g (f x)
let ( % ) f g x = f (g x)
let const x _ = x
let ( >>= ) x f = match x with None -> None | Some y -> f y
module Pair =
struct
let mapn f (x, y) = (f x, f y)
end
module List =
struct
include List
let cons x l = x :: l
let list_rest l =
let rec go acc = function
x :: xs -> (x, (acc, xs)) :: go (x :: acc) xs
| [] -> [] in
go [] l
(* "nth_rest i l" returns the i-th element of l as well as
the elements before and after (in order)
*)
let nth_rest n =
let rec go acc i = function
x :: xs when i > 0 -> go (x :: acc) (i-1) xs
| x :: xs when i = 0 -> x, (List.rev acc, xs)
| _ -> failwith "nth_rest"
in go [] n
let insert_at i elem l =
let rec go acc = function
(0, xs) -> List.rev_append acc (elem::xs)
| (n, []) -> failwith "insert_at"
| (n, x :: xs) -> go (x::acc) (n-1, xs)
in go [] (i, l)
let take_drop n =
let rec go acc i = function
[] when i > 0 -> failwith "take_drop"
| x :: xs when i > 0 -> go (x::acc) (i-1) xs
| xs -> List.rev acc, xs
in go [] n
let take n l = fst (take_drop n l)
let rec findi p l =
let rec loop n = function
| [] -> raise Not_found
| h :: t ->
if p n h then (n,h) else loop (n+1) t
in loop 0 l
let concat_map f l = List.concat (List.map f l)
let fsum = List.fold_left (+.) 0.
let rec last = function
[] -> failwith "last"
| [h] -> h
| h :: t -> last t
let rec union1 x y = match x with
[] -> y
| h :: t -> if List.mem h y then union1 t y else h :: union1 t y
(* tail-recursive version -- reverses first argument *)
let rec union2 x y = match x with
[] -> y
| h :: t -> if List.mem h y then union1 t y else union2 t (h :: y)
let rec fold_right1 f = function
x :: [] -> x
| x :: xs -> f x (fold_right1 f xs)
| [] -> failwith "fold_right1"
let fold_left_map f acc = List.fold_left
(fun (acc, ys) x -> let (acc', y) = f acc x in (acc', y :: ys)) (acc, [])
let fold_right_map f acc xs = List.fold_right
(fun x (acc, ys) -> let (acc', y) = f acc x in (acc', y :: ys)) xs (acc, [])
let fold_map f sf l = let (sf, rev) = fold_left_map f sf l in sf, List.rev rev
let rec filter_map f = function
[] -> []
| x :: xs -> (match f x with None -> filter_map f xs | Some y -> y :: filter_map f xs)
let exists_unique p l =
let rec go acc = function
[] -> acc
| x :: xs -> if p x then (if acc then false else go true xs) else go acc xs
in go false l
end
end
(* ------------------------------------------------------------------------- *)
(* Adapted from meson.ml. The main change is that creating HOL versions of *)
(* fresh variables requires HOL types. *)
(* ------------------------------------------------------------------------- *)
module Mapping = struct
let reset_vars,fol_of_var,hol_of_var =
let vstore = ref []
and gstore = ref []
and vcounter = ref 0 in
let inc_vcounter() =
let n = !vcounter in
let m = n + 1 in
(vcounter := m; n) in
let reset_vars() = vstore := []; gstore := []; vcounter := 0 in
let fol_of_var v =
try assoc v !vstore with Failure _ ->
let n = inc_vcounter() in
if !copverb then
Format.printf "fol_of_var: %s (ty = %s) <- %d\n%!"
(string_of_term v) (string_of_type (type_of v)) n;
vstore := (v,n)::!vstore; n in
let hol_of_var v ty =
try rev_assoc v !gstore with Failure _ ->
let gv = genvar ty in
gstore := (gv,v)::!gstore; gv in
reset_vars,fol_of_var,hol_of_var
let reset_consts,fol_of_const,hol_of_const =
Meson.reset_consts,Meson.fol_of_const,Meson.hol_of_const
let rec fol_of_term env consts tm =
if is_var tm && not (mem tm consts) then
Fvar(fol_of_var tm)
else
let f,args = strip_comb tm in
if mem f env then failwith "fol_of_term: higher order" else
let ff = fol_of_const f in
Fnapp(ff,map (fol_of_term env consts) args)
let fol_of_atom env consts tm =
let f,args = strip_comb tm in
if mem f env then failwith "fol_of_atom: higher order" else
let ff = fol_of_const f in
ff,map (fol_of_term env consts) args
let fol_of_literal env consts tm =
try let tm' = dest_neg tm in
let p,a = fol_of_atom env consts tm' in
-p,a
with Failure _ -> fol_of_atom env consts tm
let rec fol_of_form env consts tm =
try let v,bod = dest_forall tm in
let fv = fol_of_var v in
let fbod = fol_of_form (v::env) (subtract consts [v]) bod in
Forallq(fv,fbod)
with Failure _ -> try
let l,r = dest_conj tm in
let fl = fol_of_form env consts l
and fr = fol_of_form env consts r in
Conj(fl,fr)
with Failure _ -> try
let l,r = dest_disj tm in
let fl = fol_of_form env consts l
and fr = fol_of_form env consts r in
Disj(fl,fr)
with Failure _ ->
Atom(fol_of_literal env consts tm)
(* ----------------------------------------------------------------------- *)
(* Further translation functions for HOL formulas. *)
(* ----------------------------------------------------------------------- *)
let rec hol_of_term ty tm =
match tm with
Fvar v -> hol_of_var v ty
| Fnapp (f,args) -> hol_of_atom (f, args)
and hol_of_atom (f, args) =
let f' = hol_of_const f in
let tys = fst (splitlist dest_fun_ty (type_of f')) in
(* Functions can be translated to FOF
without the full number of its arguments (due to partial application).
Therefore obtain only as many types of arguments
as present in the FO term. *)
assert (List.length args <= List.length tys);
let tys' = Utils.List.take (List.length args) tys in
list_mk_comb (f', List.map2 hol_of_term tys' args)
let hol_of_literal (p,args) =
if p < 0 then mk_neg(hol_of_atom(-p,args))
else hol_of_atom (p,args)
(* ----------------------------------------------------------------------- *)
(* Creation of tagged contrapositives from a HOL clause. *)
(* This includes any possible support clauses (1 = falsity). *)
(* The rules are partitioned into association lists. *)
(* ----------------------------------------------------------------------- *)
let fol_of_hol_clauses =
let eqt (a1,(b1,c1)) (a2, (b2,c2)) =
((a1 = a2) && (b1 = b2) && (equals_thm c1 c2)) in
let rec mk_contraposes n th used unused sofar =
match unused with
[] -> sofar
| h::t -> let nw = (map Meson.mk_negated (used @ t),h),(n,th) in
mk_contraposes (n + 1) th (used@[h]) t (nw::sofar) in
let fol_of_hol_clause th =
let lconsts = freesl (hyp th) in
let tm = concl th in
let hlits = disjuncts tm in
let flits = map (fol_of_literal [] lconsts) hlits in
let basics = mk_contraposes 0 th [] flits [] in
if forall (fun (p,_) -> p < 0) flits then
((map Meson.mk_negated flits,(1,[])),(-1,th))::basics
else basics in
fun thms ->
let rawrules = itlist (union' eqt o fol_of_hol_clause) thms [] in
let prs = setify (map (fst o snd o fst) rawrules) in
let prules =
map (fun t -> t,filter ((=) t o fst o snd o fst) rawrules) prs in
let srules = sort (fun (p,_) (q,_) -> abs(p) <= abs(q)) prules in
srules
end