1 let print_metasenv metasenv =
2 String.concat "\n--------------------------\n"
3 (List.map (fun (i, context, term) ->
4 (string_of_int i) ^ " [\n" ^ (CicPp.ppcontext context) ^
5 "\n] " ^ (CicPp.ppterm term))
10 let print_subst subst =
13 (fun (i, (c, t, ty)) ->
14 Printf.sprintf "?%d -> %s : %s" i
15 (CicPp.ppterm t) (CicPp.ppterm ty))
19 (* (weight of constants, [(meta, weight_of_meta)]) *)
20 type weight = int * (int * int) list;;
22 let string_of_weight (cw, mw) =
25 (List.map (function (m, w) -> Printf.sprintf "(%d,%d)" m w) mw)
27 Printf.sprintf "[%d; %s]" cw s
30 let weight_of_term ?(consider_metas=true) term =
31 (* ALB: what to consider as a variable? I think "variables" in our case are
32 Metas and maybe Rels... *)
34 let vars_dict = Hashtbl.create 5 in
35 let rec aux = function
36 | C.Meta (metano, _) when consider_metas ->
38 let oldw = Hashtbl.find vars_dict metano in
39 Hashtbl.replace vars_dict metano (oldw+1)
41 Hashtbl.add vars_dict metano 1);
43 | C.Meta _ -> 0 (* "variables" are lighter than constants and functions...*)
47 | C.MutInd (_, _, ens)
48 | C.MutConstruct (_, _, _, ens) ->
49 List.fold_left (fun w (u, t) -> (aux t) + w) 1 ens
52 | C.Lambda (_, t1, t2)
54 | C.LetIn (_, t1, t2) ->
59 | C.Appl l -> List.fold_left (+) 0 (List.map aux l)
61 | C.MutCase (_, _, outt, t, pl) ->
64 let w3 = List.fold_left (+) 0 (List.map aux pl) in
68 List.fold_left (fun w (n, i, t1, t2) -> (aux t1) + (aux t2) + w) 1 fl
71 List.fold_left (fun w (n, t1, t2) -> (aux t1) + (aux t2) + w) 1 fl
77 Hashtbl.fold (fun meta metaw resw -> (meta, metaw)::resw) vars_dict [] in
80 | (m1, _), (m2, _) -> m2 - m1
82 (w, List.sort compare l) (* from the biggest meta to the smallest (0) *)
86 (* returns a "normalized" version of the polynomial weight wl (with type
87 * weight list), i.e. a list sorted ascending by meta number,
88 * from 0 to maxmeta. wl must be sorted descending by meta number. Example:
89 * normalize_weight 5 (3, [(3, 2); (1, 1)]) ->
90 * (3, [(1, 1); (2, 0); (3, 2); (4, 0); (5, 0)]) *)
91 let normalize_weight maxmeta (cw, wl) =
92 (* Printf.printf "normalize_weight: %d, %s\n" maxmeta *)
93 (* (string_of_weight (cw, wl)); *)
94 let rec aux = function
96 | m -> (m, 0)::(aux (m-1))
98 let tmpl = aux maxmeta in
101 (fun (m, _) (n, _) -> Pervasives.compare m n)
103 (fun res (m, w) -> (m, w)::(List.remove_assoc m res)) tmpl wl)
109 let normalize_weights (cw1, wl1) (cw2, wl2) =
110 let rec aux wl1 wl2 =
113 | (m, w)::tl1, (n, w')::tl2 when m = n ->
114 let res1, res2 = aux tl1 tl2 in
115 (m, w)::res1, (n, w')::res2
116 | (m, w)::tl1, ((n, w')::_ as wl2) when m < n ->
117 let res1, res2 = aux tl1 wl2 in
118 (m, w)::res1, (m, 0)::res2
119 | ((m, w)::_ as wl1), (n, w')::tl2 when m > n ->
120 let res1, res2 = aux wl1 tl2 in
121 (n, 0)::res1, (n, w')::res2
123 let res1, res2 = aux [] tl2 in
124 (n, 0)::res1, (n, w)::res2
126 let res1, res2 = aux tl1 [] in
127 (m, w)::res1, (m, 0)::res2
129 let cmp (m, _) (n, _) = compare m n in
130 let wl1, wl2 = aux (List.sort cmp wl1) (List.sort cmp wl2) in
131 (cw1, wl1), (cw2, wl2)
135 type comparison = Lt | Le | Eq | Ge | Gt | Incomparable;;
137 let string_of_comparison = function
143 | Incomparable -> "I"
146 let compare_weights ?(normalize=false)
147 ((h1, w1) as weight1) ((h2, w2) as weight2)=
148 let (h1, w1), (h2, w2) =
151 (* let maxmeta l = *)
153 (* match List.hd l with *)
155 (* with Failure _ -> 0 *)
157 (* max (maxmeta w1) (maxmeta w2) *)
159 (* (normalize_weight maxmeta (h1, w1)), (normalize_weight maxmeta (h2, w2)) *)
160 normalize_weights weight1 weight2
167 (fun ((lt, eq, gt), diffs) w1 w2 ->
169 | (meta1, w1), (meta2, w2) when meta1 = meta2 ->
170 let diffs = (w1 - w2) + diffs in
171 let r = compare w1 w2 in
172 if r < 0 then (lt+1, eq, gt), diffs
173 else if r = 0 then (lt, eq+1, gt), diffs
174 else (lt, eq, gt+1), diffs
175 | (meta1, w1), (meta2, w2) ->
176 Printf.printf "HMMM!!!! %s, %s\n"
177 (string_of_weight weight1) (string_of_weight weight2);
180 with Invalid_argument _ ->
181 Printf.printf "Invalid_argument: %s{%s}, %s{%s}, normalize = %s\n"
182 (string_of_weight (h1, w1)) (string_of_weight weight1)
183 (string_of_weight (h2, w2)) (string_of_weight weight2)
184 (string_of_bool normalize);
187 let hdiff = h1 - h2 in
191 else if hdiff > 0 then Gt
192 else Eq (* Incomparable *)
195 if m > 0 || hdiff < 0 then Lt
196 else if diffs >= (- hdiff) then Le else Incomparable
198 if diffs >= (- hdiff) then Le else Incomparable
201 if m > 0 || hdiff > 0 then Gt
202 else if (- diffs) >= hdiff then Ge else Incomparable
204 if (- diffs) >= hdiff then Ge else Incomparable
205 | (m, _, n) when m > 0 && n > 0 ->
210 let rec aux_ordering t1 t2 =
211 let module C = Cic in
212 let compare_uris u1 u2 =
214 compare (UriManager.string_of_uri u1) (UriManager.string_of_uri u2) in
216 else if res = 0 then Eq
221 | _, C.Meta _ -> Incomparable
223 | t1, t2 when t1 = t2 -> Eq
225 | C.Rel n, C.Rel m -> if n > m then Lt else Gt
229 | C.Const (u1, _), C.Const (u2, _) -> compare_uris u1 u2
233 | C.MutInd (u1, _, _), C.MutInd (u2, _, _) -> compare_uris u1 u2
234 | C.MutInd _, _ -> Lt
235 | _, C.MutInd _ -> Gt
237 | C.MutConstruct (u1, _, _, _), C.MutConstruct (u2, _, _, _) ->
239 | C.MutConstruct _, _ -> Lt
240 | _, C.MutConstruct _ -> Gt
242 | C.Appl l1, C.Appl l2 ->
248 | hd1::tl1, hd2::tl2 ->
249 let o = aux_ordering hd1 hd2 in
250 if o = Eq then cmp tl1 tl2
256 Printf.printf "These two terms are not comparable:\n%s\n%s\n\n"
257 (CicPp.ppterm t1) (CicPp.ppterm t2);
262 (* w1, w2 are the weights, they should already be normalized... *)
263 let nonrec_kbo_w (t1, w1) (t2, w2) =
264 match compare_weights w1 w2 with
265 | Le -> if aux_ordering t1 t2 = Lt then Lt else Incomparable
266 | Ge -> if aux_ordering t1 t2 = Gt then Gt else Incomparable
267 | Eq -> aux_ordering t1 t2
272 let nonrec_kbo t1 t2 =
273 let w1 = weight_of_term t1 in
274 let w2 = weight_of_term t2 in
275 match compare_weights ~normalize:true w1 w2 with
276 | Le -> if aux_ordering t1 t2 = Lt then Lt else Incomparable
277 | Ge -> if aux_ordering t1 t2 = Gt then Gt else Incomparable
278 | Eq -> aux_ordering t1 t2
283 let names_of_context context =
287 | Some (n, e) -> Some n)
296 let compare = Pervasives.compare
299 module TermSet = Set.Make(OrderedTerm);;
300 module TermMap = Map.Make(OrderedTerm);;
302 let symbols_of_term term =
303 let module C = Cic in
304 let rec aux map = function
307 List.fold_left (fun res t -> (aux res t)) map l
311 let c = TermMap.find t map in
312 TermMap.add t (c+1) map
318 aux TermMap.empty term
322 let metas_of_term term =
323 let module C = Cic in
324 let rec aux = function
325 | C.Meta _ as t -> TermSet.singleton t
327 List.fold_left (fun res t -> TermSet.union res (aux t)) TermSet.empty l
328 | t -> TermSet.empty (* TODO: maybe add other cases? *)
335 let module C = Cic in
337 | t1, t2 when t1 = t2 -> Eq
338 | t1, (C.Meta _ as m) ->
339 if TermSet.mem m (metas_of_term t1) then Gt else Incomparable
340 | (C.Meta _ as m), t2 ->
341 if TermSet.mem m (metas_of_term t2) then Lt else Incomparable
342 | C.Appl (hd1::tl1), C.Appl (hd2::tl2) -> (
350 let res1 = List.fold_left (f t2) false tl1 in
352 else let res2 = List.fold_left (f t1) false tl2 in
356 if res <> Incomparable then
360 if not r then false else
365 match aux_ordering hd1 hd2 with
367 let res = List.fold_left (f t1) false tl2 in
371 let res = List.fold_left (f t2) false tl1 in
378 (fun r t1 t2 -> if r <> Eq then r else lpo t1 t2)
380 with Invalid_argument _ ->
385 if List.fold_left (f t1) false tl2 then Gt
388 if List.fold_left (f t2) false tl1 then Lt
394 | t1, t2 -> aux_ordering t1 t2
398 (* settable by the user... *)
399 let compare_terms = ref nonrec_kbo;;
402 type equality_sign = Negative | Positive;;
404 let string_of_sign = function
405 | Negative -> "Negative"
406 | Positive -> "Positive"