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/.
26 (* let _profiler = <:profiler<_profiler>>;; *)
33 let check_disjoint_invariant subst metasenv msg =
35 (fun (i,_,_) -> (Subst.is_in_subst i subst)) metasenv)
38 prerr_endline ("not disjoint: " ^ msg);
43 let rec check_irl start = function
45 | None::tl -> check_irl (start+1) tl
46 | (Some (Cic.Rel x))::tl ->
47 if x = start then check_irl (start+1) tl else false
51 let rec is_simple_term = function
52 | Cic.Appl ((Cic.Meta _)::_) -> false
53 | Cic.Appl l -> List.for_all is_simple_term l
54 | Cic.Meta (i, l) -> let l = [] in check_irl 1 l
57 | Cic.MutInd (_, _, []) -> true
58 | Cic.MutConstruct (_, _, _, []) -> true
63 List.exists (fun (j,_,_) -> i = j) menv
66 let unification_simple locked_menv metasenv context t1 t2 ugraph =
68 let module M = CicMetaSubst in
69 let module U = CicUnification in
70 let lookup = Subst.lookup_subst in
71 let rec occurs_check subst what where =
73 | Cic.Meta(i,_) when i = what -> true
74 | C.Appl l -> List.exists (occurs_check subst what) l
76 let t = lookup where subst in
77 if t <> where then occurs_check subst what t else false
80 let rec unif subst menv s t =
81 let s = match s with C.Meta _ -> lookup s subst | _ -> s
82 and t = match t with C.Meta _ -> lookup t subst | _ -> t
86 | s, t when s = t -> subst, menv
87 (* sometimes the same meta has different local contexts; this
88 could create "cyclic" substitutions *)
89 | C.Meta (i, _), C.Meta (j, _) when i=j -> subst, menv
90 | C.Meta (i, _), C.Meta (j, _)
91 when (locked locked_menv i) &&(locked locked_menv j) ->
93 (U.UnificationFailure (lazy "Inference.unification.unif"))
94 | C.Meta (i, _), C.Meta (j, _) when (locked locked_menv i) ->
96 | C.Meta (i, _), C.Meta (j, _) when (i > j) && not (locked locked_menv j) ->
98 | C.Meta (i,_), t when occurs_check subst i t ->
100 (U.UnificationFailure (lazy "Inference.unification.unif"))
101 | C.Meta (i, l), t when (locked locked_menv i) ->
103 (U.UnificationFailure (lazy "Inference.unification.unif"))
104 | C.Meta (i, l), t -> (
106 let _, _, ty = CicUtil.lookup_meta i menv in
107 assert (not (Subst.is_in_subst i subst));
108 let subst = Subst.buildsubst i context t ty subst in
109 let menv = menv in (* List.filter (fun (m, _, _) -> i <> m) menv in *)
111 with CicUtil.Meta_not_found m ->
112 let names = names_of_context context in
114 (lazy*) prerr_endline
115 (Printf.sprintf "Meta_not_found %d!: %s %s\n%s\n\n%s" m
116 (CicPp.pp t1 names) (CicPp.pp t2 names)
117 (print_metasenv menv) (print_metasenv metasenv));
120 | _, C.Meta _ -> unif subst menv t s
121 | C.Appl (hds::_), C.Appl (hdt::_) when hds <> hdt ->
122 raise (U.UnificationFailure (lazy "Inference.unification.unif"))
123 | C.Appl (hds::tls), C.Appl (hdt::tlt) -> (
126 (fun (subst', menv) s t -> unif subst' menv s t)
127 (subst, menv) tls tlt
128 with Invalid_argument _ ->
129 raise (U.UnificationFailure (lazy "Inference.unification.unif"))
132 raise (U.UnificationFailure (lazy "Inference.unification.unif"))
134 let subst, menv = unif Subst.empty_subst metasenv t1 t2 in
135 let menv = Subst.filter subst menv in
139 let profiler = HExtlib.profile "P/Inference.unif_simple[flatten]"
140 let profiler2 = HExtlib.profile "P/Inference.unif_simple[flatten_fast]"
141 let profiler3 = HExtlib.profile "P/Inference.unif_simple[resolve_meta]"
142 let profiler4 = HExtlib.profile "P/Inference.unif_simple[filter]"
144 let unification_aux b metasenv1 metasenv2 context t1 t2 ugraph =
146 HExtlib.list_uniq (List.sort Pervasives.compare (metasenv1 @ metasenv2))
147 (* metasenv1 @ metasenv2 *)
149 let subst, menv, ug =
150 if not (is_simple_term t1) || not (is_simple_term t2) then (
153 (Printf.sprintf "NOT SIMPLE TERMS: %s %s"
154 (CicPp.ppterm t1) (CicPp.ppterm t2)));
155 raise (CicUnification.UnificationFailure (lazy "Inference.unification.unif"))
158 (* full unification *)
159 unification_simple [] metasenv context t1 t2 ugraph
161 (* matching: metasenv1 is locked *)
162 unification_simple metasenv1 metasenv context t1 t2 ugraph
164 if Utils.debug_res then
165 ignore(check_disjoint_invariant subst menv "unif");
166 (* let flatten subst =
168 (fun (i, (context, term, ty)) ->
169 let context = apply_subst_context subst context in
170 let term = apply_subst subst term in
171 let ty = apply_subst subst ty in
172 (i, (context, term, ty))) subst
174 let flatten subst = profiler.HExtlib.profile flatten subst in
175 let subst = flatten subst in *)
179 exception MatchingFailure;;
181 (** matching takes in input the _disjoint_ metasenv of t1 and t2;
182 it perform unification in the union metasenv, then check that
183 the first metasenv has not changed *)
184 let matching metasenv1 metasenv2 context t1 t2 ugraph =
186 unification_aux false metasenv1 metasenv2 context t1 t2 ugraph
188 CicUnification.UnificationFailure _ ->
189 raise MatchingFailure
192 let unification m1 m2 c t1 t2 ug =
194 unification_aux true m1 m2 c t1 t2 ug
200 let check_eq context msg eq =
201 let w, proof, (eq_ty, left, right, order), metas = eq in
202 if not (fst (CicReduction.are_convertible ~metasenv:metas context eq_ty
203 (fst (CicTypeChecker.type_of_aux' metas context left CicUniv.empty_ugraph))
204 CicUniv.empty_ugraph))
213 let find_equalities context proof =
214 let module C = Cic in
215 let module S = CicSubstitution in
216 let module T = CicTypeChecker in
217 let newmeta = ProofEngineHelpers.new_meta_of_proof ~proof in
218 let ok_types ty menv =
219 List.for_all (fun (_, _, mt) -> mt = ty) menv
221 let rec aux index newmeta = function
223 | (Some (_, C.Decl (term)))::tl ->
224 let do_find context term =
226 | C.Prod (name, s, t) ->
227 let (head, newmetas, args, newmeta) =
228 ProofEngineHelpers.saturate_term newmeta []
229 context (S.lift index term) 0
232 if List.length args = 0 then
235 C.Appl ((C.Rel index)::args)
238 | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
239 when (LibraryObjects.is_eq_URI uri) &&
240 (ok_types ty newmetas) ->
243 (Printf.sprintf "OK: %s" (CicPp.ppterm term)));
244 let o = !Utils.compare_terms t1 t2 in
245 let stat = (ty,t1,t2,o) in
246 (* let w = compute_equality_weight stat in *)
248 let proof = Equality.Exact p in
249 let e = Equality.mk_equality (w, proof, stat, newmetas) in
253 | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
254 when LibraryObjects.is_eq_URI uri ->
255 let ty = S.lift index ty in
256 let t1 = S.lift index t1 in
257 let t2 = S.lift index t2 in
258 let o = !Utils.compare_terms t1 t2 in
259 let stat = (ty,t1,t2,o) in
260 let w = compute_equality_weight stat in
261 let p = C.Rel index in
262 let proof = Equality.Exact p in
263 let e = Equality.mk_equality (w, proof,stat,[]) in
267 match do_find context term with
269 let tl, newmeta' = (aux (index+1) newmeta tl) in
270 if newmeta' < newmeta then
271 prerr_endline "big trouble";
272 (index, p)::tl, newmeta' (* max???? *)
274 aux (index+1) newmeta tl
277 aux (index+1) newmeta tl
279 let il, maxm = aux 1 newmeta context in
280 let indexes, equalities = List.split il in
281 (* ignore (List.iter (check_eq context "find") equalities); *)
282 indexes, equalities, maxm
287 let equations_blacklist =
289 (fun s u -> UriManager.UriSet.add (UriManager.uri_of_string u) s)
290 UriManager.UriSet.empty [
291 "cic:/Coq/Init/Logic/eq.ind#xpointer(1/1/1)";
292 "cic:/Coq/Init/Logic/trans_eq.con";
293 "cic:/Coq/Init/Logic/f_equal.con";
294 "cic:/Coq/Init/Logic/f_equal2.con";
295 "cic:/Coq/Init/Logic/f_equal3.con";
296 "cic:/Coq/Init/Logic/f_equal4.con";
297 "cic:/Coq/Init/Logic/f_equal5.con";
298 "cic:/Coq/Init/Logic/sym_eq.con";
299 "cic:/Coq/Init/Logic/eq_ind.con";
300 "cic:/Coq/Init/Logic/eq_ind_r.con";
301 "cic:/Coq/Init/Logic/eq_rec.con";
302 "cic:/Coq/Init/Logic/eq_rec_r.con";
303 "cic:/Coq/Init/Logic/eq_rect.con";
304 "cic:/Coq/Init/Logic/eq_rect_r.con";
305 "cic:/Coq/Logic/Eqdep/UIP.con";
306 "cic:/Coq/Logic/Eqdep/UIP_refl.con";
307 "cic:/Coq/Logic/Eqdep_dec/eq2eqT.con";
308 "cic:/Coq/ZArith/Zcompare/rename.con";
309 (* ALB !!!! questo e` imbrogliare, ma x ora lo lasciamo cosi`...
310 perche' questo cacchio di teorema rompe le scatole :'( *)
311 "cic:/Rocq/SUBST/comparith/mult_n_2.con";
313 "cic:/matita/logic/equality/eq_f.con";
314 "cic:/matita/logic/equality/eq_f2.con";
315 "cic:/matita/logic/equality/eq_rec.con";
316 "cic:/matita/logic/equality/eq_rect.con";
320 let equations_blacklist = UriManager.UriSet.empty;;
323 (* let _ = <:start<tty_of_u>> in *)
324 let t = CicUtil.term_of_uri u in
325 let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
326 (* let _ = <:stop<tty_of_u>> in *)
331 let t,ty = tty_of_u u in
335 let find_library_equalities caso_strano dbd context status maxmeta =
336 let module C = Cic in
337 let module S = CicSubstitution in
338 let module T = CicTypeChecker in
339 (* let _ = <:start<equations_for_goal>> in *)
343 let proof, goalno = status in
344 let _,metasenv,_,_ = proof in
345 let metano,context,ty = CicUtil.lookup_meta goalno metasenv in
347 | Cic.Appl[Cic.MutInd(u,0,_);eq_ty;l;r] ->
348 (let mainl, sigl = MetadataConstraints.signature_of l in
349 let mainr, sigr = MetadataConstraints.signature_of r in
350 match mainl,mainr with
351 | Some (uril,tyl), Some (urir, tyr)
352 when LibraryObjects.is_eq_URI uril &&
353 LibraryObjects.is_eq_URI urir &&
355 Some (mainl,MetadataConstraints.UriManagerSet.union sigl sigr)
357 let u = (UriManager.uri_of_string
358 (UriManager.string_of_uri u ^ "#xpointer(1/1)")) in
359 let main = Some (u, []) in
360 Some (main,MetadataConstraints.UriManagerSet.union sigl sigr))
366 let eqs = (MetadataQuery.equations_for_goal ~dbd ?signature status) in
367 (* let _ = <:stop<equations_for_goal>> in *)
371 if LibraryObjects.is_eq_refl_URI uri ||
372 LibraryObjects.is_sym_eq_URI uri ||
373 LibraryObjects.is_trans_eq_URI uri ||
374 LibraryObjects.is_eq_ind_URI uri ||
375 LibraryObjects.is_eq_ind_r_URI uri
382 let ok_types ty menv =
383 List.for_all (fun (_, _, mt) -> mt = ty) menv
385 let rec has_vars = function
386 | C.Meta _ | C.Rel _ | C.Const _ -> false
388 | C.Appl l -> List.exists has_vars l
389 | C.Prod (_, s, t) | C.Lambda (_, s, t)
390 | C.LetIn (_, s, t) | C.Cast (s, t) ->
391 (has_vars s) || (has_vars t)
394 let rec aux newmeta = function
396 | (uri, term, termty)::tl ->
399 (Printf.sprintf "Examining: %s (%s)"
400 (CicPp.ppterm term) (CicPp.ppterm termty)));
403 | C.Prod (name, s, t) when not (has_vars termty) ->
404 let head, newmetas, args, newmeta =
405 ProofEngineHelpers.saturate_term newmeta [] context termty 0
408 if List.length args = 0 then
414 | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
415 when (LibraryObjects.is_eq_URI uri ||
416 LibraryObjects.is_eq_refl_URI uri) &&
417 (ok_types ty newmetas) ->
420 (Printf.sprintf "OK: %s" (CicPp.ppterm term)));
421 let o = !Utils.compare_terms t1 t2 in
422 let stat = (ty,t1,t2,o) in
423 let w = compute_equality_weight stat in
424 let proof = Equality.Exact p in
425 let e = Equality.mk_equality (w, proof, stat, newmetas) in
429 | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
431 (LibraryObjects.is_eq_URI uri ||
432 LibraryObjects.is_eq_refl_URI uri) &&
433 not (has_vars termty) ->
434 let o = !Utils.compare_terms t1 t2 in
435 let stat = (ty,t1,t2,o) in
436 let w = compute_equality_weight stat in
437 let proof = Equality.Exact term in
438 let e = Equality.mk_equality (w, proof, stat, []) in
444 let tl, newmeta' = aux newmeta tl in
445 if newmeta' < newmeta then
446 prerr_endline "big trouble";
447 (uri, e)::tl, newmeta' (* max???? *)
451 let found, maxm = aux maxmeta candidates in
453 let mceq = Equality.meta_convertibility_eq in
455 (fun (s, l) (u, e) ->
456 if List.exists (mceq e) (List.map snd l) then (
459 (Printf.sprintf "NO!! %s already there!"
460 (Equality.string_of_equality e)));
461 (UriManager.UriSet.add u s, l)
462 ) else (UriManager.UriSet.add u s, (u, e)::l))
463 (UriManager.UriSet.empty, []) found)
469 let find_library_theorems dbd env status equalities_uris =
470 let module C = Cic in
471 let module S = CicSubstitution in
472 let module T = CicTypeChecker in
476 if LibraryObjects.is_sym_eq_URI uri ||
477 LibraryObjects.is_trans_eq_URI uri ||
478 LibraryObjects.is_eq_ind_URI uri ||
479 LibraryObjects.is_eq_ind_r_URI uri
482 (let t,ty = tty_of_u uri in t, ty, [] )::l)
483 [] (MetadataQuery.signature_of_goal ~dbd status)
487 match LibraryObjects.eq_URI () with
491 (ProofEngineTypes.Fail
492 (lazy "No default eq defined when running find_library_theorems"))
494 let t = CicUtil.term_of_uri (LibraryObjects.eq_refl_URI ~eq) in
495 let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
498 let res = refl_equal::candidates in
503 let find_context_hypotheses env equalities_indexes =
504 let metasenv, context, ugraph = env in
511 if List.mem n equalities_indexes then
516 CicTypeChecker.type_of_aux' metasenv context t ugraph in
517 (n+1, (t, ty, [])::l))
523 let get_stats () = "" (*<:show<Inference.>>*) ;;