1 (* Copyright (C) 2005, HELM Team.
3 * This file is part of HELM, an Hypertextual, Electronic
4 * Library of Mathematics, developed at the Computer Science
5 * Department, University of Bologna, Italy.
7 * HELM is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * HELM is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with HELM; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22 * For details, see the HELM World-Wide-Web page,
23 * http://cs.unibo.it/helm/.
31 let check_disjoint_invariant subst metasenv msg =
33 (fun (i,_,_) -> (Equality.is_in_subst i subst)) metasenv)
36 prerr_endline ("not disjoint: " ^ msg);
41 let rec check_irl start = function
43 | None::tl -> check_irl (start+1) tl
44 | (Some (Cic.Rel x))::tl ->
45 if x = start then check_irl (start+1) tl else false
49 let rec is_simple_term = function
50 | Cic.Appl ((Cic.Meta _)::_) -> false
51 | Cic.Appl l -> List.for_all is_simple_term l
52 | Cic.Meta (i, l) -> check_irl 1 l
55 | Cic.MutInd (_, _, []) -> true
56 | Cic.MutConstruct (_, _, _, []) -> true
61 List.exists (fun (j,_,_) -> i = j) menv
64 let unification_simple locked_menv metasenv context t1 t2 ugraph =
66 let module M = CicMetaSubst in
67 let module U = CicUnification in
68 let lookup = Equality.lookup_subst in
69 let rec occurs_check subst what where =
71 | t when what = t -> true
72 | C.Appl l -> List.exists (occurs_check subst what) l
74 let t = lookup where subst in
75 if t <> where then occurs_check subst what t else false
78 let rec unif subst menv s t =
79 let s = match s with C.Meta _ -> lookup s subst | _ -> s
80 and t = match t with C.Meta _ -> lookup t subst | _ -> t
84 | s, t when s = t -> subst, menv
85 | C.Meta (i, _), C.Meta (j, _)
86 when (locked locked_menv i) &&(locked locked_menv j) ->
88 (U.UnificationFailure (lazy "Inference.unification.unif"))
89 | C.Meta (i, _), C.Meta (j, _) when (locked locked_menv i) ->
91 | C.Meta (i, _), C.Meta (j, _) when (i > j) && not (locked locked_menv j) ->
93 | C.Meta _, t when occurs_check subst s t ->
95 (U.UnificationFailure (lazy "Inference.unification.unif"))
96 | C.Meta (i, l), t when (locked locked_menv i) ->
98 (U.UnificationFailure (lazy "Inference.unification.unif"))
99 | C.Meta (i, l), t -> (
101 let _, _, ty = CicUtil.lookup_meta i menv in
102 assert (not (Equality.is_in_subst i subst));
103 let subst = Equality.buildsubst i context t ty subst in
104 let menv = menv in (* List.filter (fun (m, _, _) -> i <> m) menv in *)
106 with CicUtil.Meta_not_found m ->
107 let names = names_of_context context in
109 (lazy*) prerr_endline
110 (Printf.sprintf "Meta_not_found %d!: %s %s\n%s\n\n%s" m
111 (CicPp.pp t1 names) (CicPp.pp t2 names)
112 (print_metasenv menv) (print_metasenv metasenv));
115 | _, C.Meta _ -> unif subst menv t s
116 | C.Appl (hds::_), C.Appl (hdt::_) when hds <> hdt ->
117 raise (U.UnificationFailure (lazy "Inference.unification.unif"))
118 | C.Appl (hds::tls), C.Appl (hdt::tlt) -> (
121 (fun (subst', menv) s t -> unif subst' menv s t)
122 (subst, menv) tls tlt
123 with Invalid_argument _ ->
124 raise (U.UnificationFailure (lazy "Inference.unification.unif"))
127 raise (U.UnificationFailure (lazy "Inference.unification.unif"))
129 let subst, menv = unif Equality.empty_subst metasenv t1 t2 in
130 let menv = Equality.filter subst menv in
134 let profiler = HExtlib.profile "P/Inference.unif_simple[flatten]"
135 let profiler2 = HExtlib.profile "P/Inference.unif_simple[flatten_fast]"
136 let profiler3 = HExtlib.profile "P/Inference.unif_simple[resolve_meta]"
137 let profiler4 = HExtlib.profile "P/Inference.unif_simple[filter]"
139 let unification_aux b metasenv1 metasenv2 context t1 t2 ugraph =
140 let metasenv = metasenv1 @ metasenv2 in
141 let subst, menv, ug =
142 if not (is_simple_term t1) || not (is_simple_term t2) then (
145 (Printf.sprintf "NOT SIMPLE TERMS: %s %s"
146 (CicPp.ppterm t1) (CicPp.ppterm t2)));
147 raise (CicUnification .UnificationFailure (lazy "Inference.unification.unif"))
150 (* full unification *)
151 unification_simple [] metasenv context t1 t2 ugraph
153 (* matching: metasenv1 is locked *)
154 unification_simple metasenv1 metasenv context t1 t2 ugraph
156 if Utils.debug_res then
157 ignore(check_disjoint_invariant subst menv "unif");
158 (* let flatten subst =
160 (fun (i, (context, term, ty)) ->
161 let context = apply_subst_context subst context in
162 let term = apply_subst subst term in
163 let ty = apply_subst subst ty in
164 (i, (context, term, ty))) subst
166 let flatten subst = profiler.HExtlib.profile flatten subst in
167 let subst = flatten subst in *)
171 exception MatchingFailure;;
173 let matching1 metasenv1 metasenv2 context t1 t2 ugraph =
175 unification_aux false metasenv1 metasenv2 context t1 t2 ugraph
177 CicUnification .UnificationFailure _ ->
178 raise MatchingFailure
181 let unification = unification_aux true
184 (** matching takes in input the _disjoint_ metasenv of t1 and t2;
185 it perform unification in the union metasenv, then check that
186 the first metasenv has not changed *)
188 let matching = matching1;;
190 let check_eq context msg eq =
191 let w, proof, (eq_ty, left, right, order), metas = eq in
192 if not (fst (CicReduction.are_convertible ~metasenv:metas context eq_ty
193 (fst (CicTypeChecker.type_of_aux' metas context left CicUniv.empty_ugraph))
194 CicUniv.empty_ugraph))
203 let find_equalities context proof =
204 let module C = Cic in
205 let module S = CicSubstitution in
206 let module T = CicTypeChecker in
207 let eq_uri = LibraryObjects.eq_URI () in
208 let newmeta = ProofEngineHelpers.new_meta_of_proof ~proof in
209 let ok_types ty menv =
210 List.for_all (fun (_, _, mt) -> mt = ty) menv
212 let rec aux index newmeta = function
214 | (Some (_, C.Decl (term)))::tl ->
215 let do_find context term =
217 | C.Prod (name, s, t) ->
218 let (head, newmetas, args, newmeta) =
219 ProofEngineHelpers.saturate_term newmeta []
220 context (S.lift index term) 0
223 if List.length args = 0 then
226 C.Appl ((C.Rel index)::args)
229 | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
230 when (UriManager.eq uri eq_uri) && (ok_types ty newmetas) ->
233 (Printf.sprintf "OK: %s" (CicPp.ppterm term)));
234 let o = !Utils.compare_terms t1 t2 in
235 let stat = (ty,t1,t2,o) in
236 let w = compute_equality_weight stat in
238 Equality.BasicProof (Equality.empty_subst,p) in
239 let proof_new = Equality.Exact p in
240 let proof = proof_new , proof_old in
241 let e = Equality.mk_equality (w, proof, stat, newmetas) in
245 | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
246 when UriManager.eq uri eq_uri ->
247 let ty = S.lift index ty in
248 let t1 = S.lift index t1 in
249 let t2 = S.lift index t2 in
250 let o = !Utils.compare_terms t1 t2 in
251 let stat = (ty,t1,t2,o) in
252 let w = compute_equality_weight stat in
253 let p = C.Rel index in
254 let proof_old = Equality.BasicProof (Equality.empty_subst,p) in
255 let proof_new = Equality.Exact p in
256 let proof = proof_new, proof_old in
257 let e = Equality.mk_equality (w, proof,stat,[]) in
261 match do_find context term with
263 let tl, newmeta' = (aux (index+1) newmeta tl) in
264 if newmeta' < newmeta then
265 prerr_endline "big trouble";
266 (index, p)::tl, newmeta' (* max???? *)
268 aux (index+1) newmeta tl
271 aux (index+1) newmeta tl
273 let il, maxm = aux 1 newmeta context in
274 let indexes, equalities = List.split il in
275 (* ignore (List.iter (check_eq context "find") equalities); *)
276 indexes, equalities, maxm
281 let equations_blacklist =
283 (fun s u -> UriManager.UriSet.add (UriManager.uri_of_string u) s)
284 UriManager.UriSet.empty [
285 "cic:/Coq/Init/Logic/eq.ind#xpointer(1/1/1)";
286 "cic:/Coq/Init/Logic/trans_eq.con";
287 "cic:/Coq/Init/Logic/f_equal.con";
288 "cic:/Coq/Init/Logic/f_equal2.con";
289 "cic:/Coq/Init/Logic/f_equal3.con";
290 "cic:/Coq/Init/Logic/f_equal4.con";
291 "cic:/Coq/Init/Logic/f_equal5.con";
292 "cic:/Coq/Init/Logic/sym_eq.con";
293 "cic:/Coq/Init/Logic/eq_ind.con";
294 "cic:/Coq/Init/Logic/eq_ind_r.con";
295 "cic:/Coq/Init/Logic/eq_rec.con";
296 "cic:/Coq/Init/Logic/eq_rec_r.con";
297 "cic:/Coq/Init/Logic/eq_rect.con";
298 "cic:/Coq/Init/Logic/eq_rect_r.con";
299 "cic:/Coq/Logic/Eqdep/UIP.con";
300 "cic:/Coq/Logic/Eqdep/UIP_refl.con";
301 "cic:/Coq/Logic/Eqdep_dec/eq2eqT.con";
302 "cic:/Coq/ZArith/Zcompare/rename.con";
303 (* ALB !!!! questo e` imbrogliare, ma x ora lo lasciamo cosi`...
304 perche' questo cacchio di teorema rompe le scatole :'( *)
305 "cic:/Rocq/SUBST/comparith/mult_n_2.con";
307 "cic:/matita/logic/equality/eq_f.con";
308 "cic:/matita/logic/equality/eq_f2.con";
309 "cic:/matita/logic/equality/eq_rec.con";
310 "cic:/matita/logic/equality/eq_rect.con";
314 let equations_blacklist = UriManager.UriSet.empty;;
317 let find_library_equalities dbd context status maxmeta =
318 let module C = Cic in
319 let module S = CicSubstitution in
320 let module T = CicTypeChecker in
323 (fun s u -> UriManager.UriSet.add u s)
325 [eq_XURI (); sym_eq_URI (); trans_eq_URI (); eq_ind_URI ();
331 if UriManager.UriSet.mem uri blacklist then
334 let t = CicUtil.term_of_uri uri in
336 CicTypeChecker.type_of_aux' [] context t CicUniv.empty_ugraph
340 (let t1 = Unix.gettimeofday () in
341 let eqs = (MetadataQuery.equations_for_goal ~dbd status) in
342 let t2 = Unix.gettimeofday () in
345 (Printf.sprintf "Tempo di MetadataQuery.equations_for_goal: %.9f\n"
349 let eq_uri1 = eq_XURI ()
350 and eq_uri2 = LibraryObjects.eq_URI () in
352 (UriManager.eq uri eq_uri1) || (UriManager.eq uri eq_uri2)
354 let ok_types ty menv =
355 List.for_all (fun (_, _, mt) -> mt = ty) menv
357 let rec has_vars = function
358 | C.Meta _ | C.Rel _ | C.Const _ -> false
360 | C.Appl l -> List.exists has_vars l
361 | C.Prod (_, s, t) | C.Lambda (_, s, t)
362 | C.LetIn (_, s, t) | C.Cast (s, t) ->
363 (has_vars s) || (has_vars t)
366 let rec aux newmeta = function
368 | (uri, term, termty)::tl ->
371 (Printf.sprintf "Examining: %s (%s)"
372 (CicPp.ppterm term) (CicPp.ppterm termty)));
375 | C.Prod (name, s, t) when not (has_vars termty) ->
376 let head, newmetas, args, newmeta =
377 ProofEngineHelpers.saturate_term newmeta [] context termty 0
380 if List.length args = 0 then
386 | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
387 when (iseq uri) && (ok_types ty newmetas) ->
390 (Printf.sprintf "OK: %s" (CicPp.ppterm term)));
391 let o = !Utils.compare_terms t1 t2 in
392 let stat = (ty,t1,t2,o) in
393 let w = compute_equality_weight stat in
395 Equality.BasicProof (Equality.empty_subst,p) in
396 let proof_new = Equality.Exact p in
397 let proof = proof_new, proof_old in
398 let e = Equality.mk_equality (w, proof, stat, newmetas) in
402 | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
403 when iseq uri && not (has_vars termty) ->
404 let o = !Utils.compare_terms t1 t2 in
405 let stat = (ty,t1,t2,o) in
406 let w = compute_equality_weight stat in
407 let old_proof = Equality.BasicProof (Equality.empty_subst,term) in
408 let new_proof = Equality.Exact term in
409 let proof = new_proof, old_proof in
410 let e = Equality.mk_equality (w, proof, stat, []) in
416 let tl, newmeta' = aux newmeta tl in
417 if newmeta' < newmeta then
418 prerr_endline "big trouble";
419 (uri, e)::tl, newmeta' (* max???? *)
423 let found, maxm = aux maxmeta candidates in
425 let mceq = Equality.meta_convertibility_eq in
427 (fun (s, l) (u, e) ->
428 if List.exists (mceq e) (List.map snd l) then (
431 (Printf.sprintf "NO!! %s already there!"
432 (Equality.string_of_equality e)));
433 (UriManager.UriSet.add u s, l)
434 ) else (UriManager.UriSet.add u s, (u, e)::l))
435 (UriManager.UriSet.empty, []) found)
441 let find_library_theorems dbd env status equalities_uris =
442 let module C = Cic in
443 let module S = CicSubstitution in
444 let module T = CicTypeChecker in
447 UriManager.uri_of_string "cic:/Coq/Init/Logic/eq.ind#xpointer(1/1/1)" in
449 UriManager.UriSet.remove refl_equal
450 (UriManager.UriSet.union equalities_uris equations_blacklist)
453 (fun s u -> UriManager.UriSet.add u s)
454 s [eq_XURI () ;sym_eq_URI (); trans_eq_URI (); eq_ind_URI ();
457 let metasenv, context, ugraph = env in
461 if UriManager.UriSet.mem uri blacklist then l
463 let t = CicUtil.term_of_uri uri in
464 let ty, _ = CicTypeChecker.type_of_aux' metasenv context t ugraph in
466 [] (MetadataQuery.signature_of_goal ~dbd status)
469 let u = eq_XURI () in
470 let t = CicUtil.term_of_uri u in
471 let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
474 refl_equal::candidates
478 let find_context_hypotheses env equalities_indexes =
479 let metasenv, context, ugraph = env in
486 if List.mem n equalities_indexes then
491 CicTypeChecker.type_of_aux' metasenv context t ugraph in
492 (n+1, (t, ty, [])::l))