]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/tactics/paramodulation/inference.ml
f088d54543aa265f6550e53bf0552f886c409e8f
[helm.git] / helm / software / components / tactics / paramodulation / inference.ml
1 (* Copyright (C) 2005, HELM Team.
2  * 
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.
6  * 
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.
11  * 
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.
16  *
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,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  *)
25
26 (* $Id$ *)
27
28 open Utils;;
29 open Printf;;
30
31 let check_disjoint_invariant subst metasenv msg =
32   if (List.exists 
33         (fun (i,_,_) -> (Equality.is_in_subst i subst)) metasenv)
34   then 
35     begin 
36       prerr_endline ("not disjoint: " ^ msg);
37       assert false
38     end
39 ;;
40
41 let rec check_irl start = function
42   | [] -> true
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
46   | _ -> false
47 ;;
48
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
53   | Cic.Rel _ -> true
54   | Cic.Const _ -> true
55   | Cic.MutInd (_, _, []) -> true
56   | Cic.MutConstruct (_, _, _, []) -> true
57   | _ -> false
58 ;;
59
60 let locked menv i =
61   List.exists (fun (j,_,_) -> i = j) menv
62 ;;
63
64 let unification_simple locked_menv metasenv context t1 t2 ugraph =
65   let module C = Cic in
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 =
70     match where with
71     | t when what = t -> true
72     | C.Appl l -> List.exists (occurs_check subst what) l
73     | C.Meta _ ->
74         let t = lookup where subst in
75         if t <> where then occurs_check subst what t else false
76     | _ -> false
77   in
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
81     
82     in
83     match s, t with
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) ->
87         raise
88           (U.UnificationFailure (lazy "Inference.unification.unif"))
89     | C.Meta (i, _), C.Meta (j, _) when (locked locked_menv i) ->          
90         unif subst menv t s
91     | C.Meta (i, _), C.Meta (j, _) when (i > j) && not (locked locked_menv j) ->
92         unif subst menv t s
93     | C.Meta _, t when occurs_check subst s t ->
94         raise
95           (U.UnificationFailure (lazy "Inference.unification.unif"))
96     | C.Meta (i, l), t when (locked locked_menv i) -> 
97         raise
98           (U.UnificationFailure (lazy "Inference.unification.unif"))
99     | C.Meta (i, l), t -> (
100         try
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 *)
105           subst, menv
106         with CicUtil.Meta_not_found m ->
107           let names = names_of_context context in
108           (*debug_print
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));
113           assert false
114       )
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) -> (
119         try
120           List.fold_left2
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"))
125       )
126     | _, _ ->
127         raise (U.UnificationFailure (lazy "Inference.unification.unif"))
128   in
129   let subst, menv = unif Equality.empty_subst metasenv t1 t2 in
130   let menv = Equality.filter subst menv in
131   subst, menv, ugraph
132 ;;
133
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]"
138
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 (
143       debug_print
144         (lazy
145            (Printf.sprintf "NOT SIMPLE TERMS: %s %s"
146               (CicPp.ppterm t1) (CicPp.ppterm t2)));
147       raise (CicUnification .UnificationFailure (lazy "Inference.unification.unif"))
148     ) else
149       if b then
150         (* full unification *)
151         unification_simple [] metasenv context t1 t2 ugraph
152       else
153         (* matching: metasenv1 is locked *)
154         unification_simple metasenv1 metasenv context t1 t2 ugraph
155   in
156   if Utils.debug_res then
157             ignore(check_disjoint_invariant subst menv "unif");
158   (* let flatten subst = 
159     List.map
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 
165   in
166   let flatten subst = profiler.HExtlib.profile flatten subst in
167   let subst = flatten subst in *)
168     subst, menv, ug
169 ;;
170
171 exception MatchingFailure;;
172
173 let matching1 metasenv1 metasenv2 context t1 t2 ugraph = 
174   try 
175     unification_aux false metasenv1 metasenv2 context t1 t2 ugraph
176   with
177     CicUnification .UnificationFailure _ ->
178       raise MatchingFailure
179 ;;
180
181 let unification = unification_aux true 
182 ;;
183
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 *)
187
188 let matching = matching1;;
189
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))
195   then
196     begin
197       prerr_endline msg;
198       assert false;
199     end
200   else ()
201 ;;
202
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
211   in
212   let rec aux index newmeta = function
213     | [] -> [], newmeta
214     | (Some (_, C.Decl (term)))::tl ->
215         let do_find context term =
216           match term with
217           | C.Prod (name, s, t) ->
218               let (head, newmetas, args, newmeta) =
219                 ProofEngineHelpers.saturate_term newmeta []
220                   context (S.lift index term) 0
221               in
222               let p =
223                 if List.length args = 0 then
224                   C.Rel index
225                 else
226                   C.Appl ((C.Rel index)::args)
227               in (
228                 match head with
229                 | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
230                     when (UriManager.eq uri eq_uri) && (ok_types ty newmetas) ->
231                     debug_print
232                       (lazy
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
237                     let proof_old = 
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
242                     Some e, (newmeta+1)
243                 | _ -> None, newmeta
244               )
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
258               Some e, (newmeta+1)
259           | _ -> None, newmeta
260         in (
261           match do_find context term with
262           | Some p, newmeta ->
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???? *)
267           | None, _ ->
268               aux (index+1) newmeta tl
269         )
270     | _::tl ->
271         aux (index+1) newmeta tl
272   in
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
277 ;;
278
279
280 (*
281 let equations_blacklist =
282   List.fold_left
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";
306
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";
311     ]
312 ;;
313 *)
314 let equations_blacklist = UriManager.UriSet.empty;;
315
316
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
321   let blacklist =
322     List.fold_left
323       (fun s u -> UriManager.UriSet.add u s)
324       equations_blacklist
325       [eq_XURI (); sym_eq_URI (); trans_eq_URI (); eq_ind_URI ();
326        eq_ind_r_URI ()]
327   in
328   let candidates =
329     List.fold_left
330       (fun l uri ->
331          if UriManager.UriSet.mem uri blacklist then
332            l
333          else
334            let t = CicUtil.term_of_uri uri in
335            let ty, _ =
336              CicTypeChecker.type_of_aux' [] context t CicUniv.empty_ugraph
337            in
338            (uri, t, ty)::l)
339       []
340       (let t1 = Unix.gettimeofday () in
341        let eqs = (MetadataQuery.equations_for_goal ~dbd status) in
342        let t2 = Unix.gettimeofday () in
343        (debug_print
344           (lazy
345              (Printf.sprintf "Tempo di MetadataQuery.equations_for_goal: %.9f\n"
346                 (t2 -. t1))));
347        eqs)
348   in
349   let eq_uri1 = eq_XURI ()
350   and eq_uri2 = LibraryObjects.eq_URI () in
351   let iseq uri =
352     (UriManager.eq uri eq_uri1) || (UriManager.eq uri eq_uri2)
353   in
354   let ok_types ty menv =
355     List.for_all (fun (_, _, mt) -> mt = ty) menv
356   in
357   let rec has_vars = function
358     | C.Meta _ | C.Rel _ | C.Const _ -> false
359     | C.Var _ -> true
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)
364     | _ -> false
365  in
366   let rec aux newmeta = function
367     | [] -> [], newmeta
368     | (uri, term, termty)::tl ->
369         debug_print
370           (lazy
371              (Printf.sprintf "Examining: %s (%s)"
372                 (CicPp.ppterm term) (CicPp.ppterm termty)));
373         let res, newmeta = 
374           match termty with
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
378               in
379               let p =
380                 if List.length args = 0 then
381                   term
382                 else
383                   C.Appl (term::args)
384               in (
385                   match head with
386                     | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
387                         when (iseq uri) && (ok_types ty newmetas) ->
388                     debug_print
389                       (lazy
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
394                     let proof_old = 
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
399                     Some e, (newmeta+1)
400                 | _ -> None, newmeta
401               )
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
411               Some e, (newmeta+1)
412           | _ -> None, newmeta
413         in
414         match res with
415         | Some e ->
416             let tl, newmeta' = aux newmeta tl in
417               if newmeta' < newmeta then 
418                 prerr_endline "big trouble";
419               (uri, e)::tl, newmeta' (* max???? *)
420         | None ->
421             aux newmeta tl
422   in
423   let found, maxm = aux maxmeta candidates in
424   let uriset, eqlist = 
425     let mceq = Equality.meta_convertibility_eq in
426     (List.fold_left
427        (fun (s, l) (u, e) ->
428           if List.exists (mceq e) (List.map snd l) then (
429             debug_print
430               (lazy
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)
436   in
437   uriset, eqlist, maxm
438 ;;
439
440
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
445   let blacklist =
446     let refl_equal =
447       UriManager.uri_of_string "cic:/Coq/Init/Logic/eq.ind#xpointer(1/1/1)" in
448     let s =
449       UriManager.UriSet.remove refl_equal
450         (UriManager.UriSet.union equalities_uris equations_blacklist)
451     in
452     List.fold_left
453       (fun s u -> UriManager.UriSet.add u s)
454       s [eq_XURI () ;sym_eq_URI (); trans_eq_URI (); eq_ind_URI ();
455          eq_ind_r_URI ()]
456   in
457   let metasenv, context, ugraph = env in
458   let candidates =
459     List.fold_left
460       (fun l uri ->
461          if UriManager.UriSet.mem uri blacklist then l
462          else
463            let t = CicUtil.term_of_uri uri in
464            let ty, _ = CicTypeChecker.type_of_aux' metasenv context t ugraph in
465            (t, ty, [])::l)
466       [] (MetadataQuery.signature_of_goal ~dbd status)
467   in
468   let refl_equal =
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
472     (t, ty, [])
473   in
474   refl_equal::candidates
475 ;;
476
477
478 let find_context_hypotheses env equalities_indexes =
479   let metasenv, context, ugraph = env in
480   let _, res = 
481     List.fold_left
482       (fun (n, l) entry ->
483          match entry with
484          | None -> (n+1, l)
485          | Some _ ->
486              if List.mem n equalities_indexes then
487                (n+1, l)
488              else
489                let t = Cic.Rel n in
490                let ty, _ =
491                  CicTypeChecker.type_of_aux' metasenv context t ugraph in 
492                (n+1, (t, ty, [])::l))
493       (1, []) context
494   in
495   res
496 ;;
497