]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/tactics/paramodulation/indexing.ml
- Removed old proofs
[helm.git] / helm / software / components / tactics / paramodulation / indexing.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 module Index = Equality_indexing.DT (* discrimination tree based indexing *)
29 (*
30 module Index = Equality_indexing.DT (* path tree based indexing *)
31 *)
32
33 let beta_expand_time = ref 0.;;
34
35 let debug_print = Utils.debug_print;;
36
37 (* 
38 for debugging 
39 let check_equation env equation msg =
40   let w, proof, (eq_ty, left, right, order), metas, args = equation in
41   let metasenv, context, ugraph = env 
42   let metasenv' = metasenv @ metas in
43     try
44       CicTypeChecker.type_of_aux' metasenv' context left ugraph;
45       CicTypeChecker.type_of_aux' metasenv' context right ugraph;
46       ()
47     with 
48         CicUtil.Meta_not_found _ as exn ->
49           begin
50             prerr_endline msg; 
51             prerr_endline (CicPp.ppterm left);
52             prerr_endline (CicPp.ppterm right);
53             raise exn
54           end 
55 *)
56
57 type retrieval_mode = Matching | Unification;;
58
59 let string_of_res ?env =
60   function
61       None -> "None"
62     | Some (t, s, m, u, ((p,e), eq_URI)) ->
63         Printf.sprintf "Some: (%s, %s, %s)" 
64           (Utils.string_of_pos p)
65           (Equality.string_of_equality ?env e)
66           (CicPp.ppterm t)
67 ;;
68
69 let print_res ?env res = 
70   prerr_endline 
71     (String.concat "\n"
72        (List.map (string_of_res ?env) res))
73 ;;
74
75 let print_candidates ?env mode term res =
76   let _ =
77     match mode with
78     | Matching ->
79         prerr_endline ("| candidates Matching " ^ (CicPp.ppterm term))
80     | Unification ->
81         prerr_endline ("| candidates Unification " ^ (CicPp.ppterm term))
82   in
83   prerr_endline 
84     (String.concat "\n"
85        (List.map
86           (fun (p, e) ->
87              Printf.sprintf "| (%s, %s)" (Utils.string_of_pos p)
88                (Equality.string_of_equality ?env e))
89           res));
90 ;;
91
92
93 let indexing_retrieval_time = ref 0.;;
94
95
96 let apply_subst = Subst.apply_subst
97
98 let index = Index.index
99 let remove_index = Index.remove_index
100 let in_index = Index.in_index
101 let empty = Index.empty 
102 let init_index = Index.init_index
103
104 let check_disjoint_invariant subst metasenv msg =
105   if (List.exists 
106         (fun (i,_,_) -> (Subst.is_in_subst i subst)) metasenv)
107   then 
108     begin 
109       prerr_endline ("not disjoint: " ^ msg);
110       assert false
111     end
112 ;;
113
114 let check_for_duplicates metas msg =
115   if List.length metas <> 
116   List.length (HExtlib.list_uniq (List.sort Pervasives.compare metas)) then
117     begin 
118       prerr_endline ("DUPLICATI " ^ msg);
119       prerr_endline (CicMetaSubst.ppmetasenv [] metas);
120       assert false
121     end
122 ;;
123
124 let check_res res msg =
125   match res with
126       Some (t, subst, menv, ug, (eq_found, eq_URI)) ->
127         let eqs = Equality.string_of_equality (snd eq_found) in
128         check_disjoint_invariant subst menv msg;
129         check_for_duplicates menv (msg ^ "\nchecking " ^ eqs);
130     | None -> ()
131 ;;
132
133 let check_target context target msg =
134   let w, proof, (eq_ty, left, right, order), metas,_ = 
135     Equality.open_equality target in
136   (* check that metas does not contains duplicates *)
137   let eqs = Equality.string_of_equality target in
138   let _ = check_for_duplicates metas (msg ^ "\nchecking " ^ eqs) in
139   let actual = (Utils.metas_of_term left)@(Utils.metas_of_term right)
140     @(Utils.metas_of_term eq_ty)@(Equality.metas_of_proof proof)  in
141   let menv = List.filter (fun (i, _, _) -> List.mem i actual) metas in
142   let _ = if menv <> metas then 
143     begin 
144       prerr_endline ("extra metas " ^ msg);
145       prerr_endline (CicMetaSubst.ppmetasenv [] metas);
146       prerr_endline "**********************";
147       prerr_endline (CicMetaSubst.ppmetasenv [] menv);
148       prerr_endline ("left: " ^ (CicPp.ppterm left));
149       prerr_endline ("right: " ^ (CicPp.ppterm right)); 
150       prerr_endline ("ty: " ^ (CicPp.ppterm eq_ty));
151       assert false
152     end
153   else () in ()
154 (*
155   try 
156       ignore(CicTypeChecker.type_of_aux'
157         metas context (Inference.build_proof_term proof) CicUniv.empty_ugraph)
158   with e ->  
159       prerr_endline msg;
160       prerr_endline (Inference.string_of_proof proof);
161       prerr_endline (CicPp.ppterm (Inference.build_proof_term proof));
162       prerr_endline ("+++++++++++++left: " ^ (CicPp.ppterm left));
163       prerr_endline ("+++++++++++++right: " ^ (CicPp.ppterm right)); 
164       raise e 
165 *)
166
167
168 (* returns a list of all the equalities in the tree that are in relation
169    "mode" with the given term, where mode can be either Matching or
170    Unification.
171
172    Format of the return value: list of tuples in the form:
173    (position - Left or Right - of the term that matched the given one in this
174      equality,
175     equality found)
176    
177    Note that if equality is "left = right", if the ordering is left > right,
178    the position will always be Left, and if the ordering is left < right,
179    position will be Right.
180 *)
181
182 let get_candidates ?env mode tree term =
183   let t1 = Unix.gettimeofday () in
184   let res =
185     let s = 
186       match mode with
187       | Matching -> Index.retrieve_generalizations tree term
188       | Unification -> Index.retrieve_unifiables tree term
189     in
190     Index.PosEqSet.elements s
191   in
192 (*   print_endline (Discrimination_tree.string_of_discrimination_tree tree); *)
193 (*   print_newline (); *)
194   let t2 = Unix.gettimeofday () in
195   indexing_retrieval_time := !indexing_retrieval_time +. (t2 -. t1); 
196  (* make fresh instances *)
197   res 
198 ;;
199
200 let profiler = HExtlib.profile "P/Indexing.get_candidates"
201
202 let get_candidates ?env mode tree term =
203   profiler.HExtlib.profile (get_candidates ?env mode tree) term
204
205 let match_unif_time_ok = ref 0.;;
206 let match_unif_time_no = ref 0.;;
207
208
209 (*
210   finds the first equality in the index that matches "term", of type "termty"
211   termty can be Implicit if it is not needed. The result (one of the sides of
212   the equality, actually) should be not greater (wrt the term ordering) than
213   term
214
215   Format of the return value:
216
217   (term to substitute, [Cic.Rel 1 properly lifted - see the various
218                         build_newtarget functions inside the various
219                         demodulation_* functions]
220    substitution used for the matching,
221    metasenv,
222    ugraph, [substitution, metasenv and ugraph have the same meaning as those
223    returned by CicUnification.fo_unif]
224    (equality where the matching term was found, [i.e. the equality to use as
225                                                 rewrite rule]
226     uri [either eq_ind_URI or eq_ind_r_URI, depending on the direction of
227          the equality: this is used to build the proof term, again see one of
228          the build_newtarget functions]
229    ))
230 *)
231 let rec find_matches metasenv context ugraph lift_amount term termty =
232   let module C = Cic in
233   let module U = Utils in
234   let module S = CicSubstitution in
235   let module M = CicMetaSubst in
236   let module HL = HelmLibraryObjects in
237   let cmp = !Utils.compare_terms in
238   let check = match termty with C.Implicit None -> false | _ -> true in
239   function
240     | [] -> None
241     | candidate::tl ->
242         let pos, equality = candidate in
243         let (_, proof, (ty, left, right, o), metas,_) = 
244           Equality.open_equality equality in
245         if Utils.debug_metas then 
246           ignore(check_target context (snd candidate) "find_matches");
247         if Utils.debug_res then 
248           begin
249             let c="eq = "^(Equality.string_of_equality (snd candidate)) ^ "\n"in
250             let t="t = " ^ (CicPp.ppterm term) ^ "\n" in
251             let m="metas = " ^ (CicMetaSubst.ppmetasenv [] metas) ^ "\n" in
252             let p="proof = "^
253               (CicPp.ppterm(Equality.build_proof_term proof))^"\n" 
254             in
255               check_for_duplicates metas "gia nella metas";
256               check_for_duplicates (metasenv@metas) ("not disjoint"^c^t^m^p)
257           end;
258         if check && not (fst (CicReduction.are_convertible
259                                 ~metasenv context termty ty ugraph)) then (
260           find_matches metasenv context ugraph lift_amount term termty tl
261         ) else
262           let do_match c eq_URI =
263             let subst', metasenv', ugraph' =
264               let t1 = Unix.gettimeofday () in
265               try
266                 let r =
267                   ( Inference.matching metasenv metas context 
268                     term (S.lift lift_amount c)) ugraph
269                 in
270                 let t2 = Unix.gettimeofday () in
271                 match_unif_time_ok := !match_unif_time_ok +. (t2 -. t1);
272                 r
273               with 
274                 | Inference.MatchingFailure as e ->
275                 let t2 = Unix.gettimeofday () in
276                 match_unif_time_no := !match_unif_time_no +. (t2 -. t1);
277                   raise e
278                 | CicUtil.Meta_not_found _ as exn -> raise exn
279             in
280             Some (C.Rel (1 + lift_amount), subst', metasenv', ugraph',
281                   (candidate, eq_URI))
282           in
283           let c, other, eq_URI =
284             if pos = Utils.Left then left, right, Utils.eq_ind_URI ()
285             else right, left, Utils.eq_ind_r_URI ()
286           in
287           if o <> U.Incomparable then
288             let res =
289               try
290                 do_match c eq_URI
291               with Inference.MatchingFailure ->
292                 find_matches metasenv context ugraph lift_amount term termty tl
293             in
294               if Utils.debug_res then ignore (check_res res "find1");
295               res
296           else
297             let res =
298               try do_match c eq_URI
299               with Inference.MatchingFailure -> None
300             in
301             if Utils.debug_res then ignore (check_res res "find2");
302             match res with
303             | Some (_, s, _, _, _) ->
304                 let c' = apply_subst s c in
305                 (* 
306              let other' = U.guarded_simpl context (apply_subst s other) in *)
307                 let other' = apply_subst s other in
308                 let order = cmp c' other' in
309                 if order = U.Gt then
310                   res
311                 else
312                   find_matches
313                     metasenv context ugraph lift_amount term termty tl
314             | None ->
315                 find_matches metasenv context ugraph lift_amount term termty tl
316 ;;
317
318 (*
319   as above, but finds all the matching equalities, and the matching condition
320   can be either Inference.matching or Inference.unification
321 *)
322 let rec find_all_matches ?(unif_fun=Inference.unification)
323     metasenv context ugraph lift_amount term termty =
324   let module C = Cic in
325   let module U = Utils in
326   let module S = CicSubstitution in
327   let module M = CicMetaSubst in
328   let module HL = HelmLibraryObjects in
329   let cmp = !Utils.compare_terms in
330   function
331     | [] -> []
332     | candidate::tl ->
333         let pos, equality = candidate in 
334         let (_,_,(ty,left,right,o),metas,_)=Equality.open_equality equality in
335         let do_match c eq_URI =
336           let subst', metasenv', ugraph' =
337             let t1 = Unix.gettimeofday () in
338             try
339               let r = 
340                 unif_fun metasenv metas context
341                   term (S.lift lift_amount c) ugraph in
342               let t2 = Unix.gettimeofday () in
343               match_unif_time_ok := !match_unif_time_ok +. (t2 -. t1);
344               r
345             with
346             | Inference.MatchingFailure
347             | CicUnification.UnificationFailure _
348             | CicUnification.Uncertain _ as e ->
349                 let t2 = Unix.gettimeofday () in
350                 match_unif_time_no := !match_unif_time_no +. (t2 -. t1);
351                 raise e
352           in
353           (C.Rel (1 + lift_amount), subst', metasenv', ugraph',
354            (candidate, eq_URI))
355         in
356         let c, other, eq_URI =
357           if pos = Utils.Left then left, right, Utils.eq_ind_URI ()
358           else right, left, Utils.eq_ind_r_URI ()
359         in
360         if o <> U.Incomparable then
361           try
362             let res = do_match c eq_URI in
363             res::(find_all_matches ~unif_fun metasenv context ugraph
364                     lift_amount term termty tl)
365           with
366           | Inference.MatchingFailure
367           | CicUnification.UnificationFailure _
368           | CicUnification.Uncertain _ ->
369               find_all_matches ~unif_fun metasenv context ugraph
370                 lift_amount term termty tl
371         else
372           try
373             let res = do_match c eq_URI in
374             match res with
375             | _, s, _, _, _ ->
376                 let c' = apply_subst s c
377                 and other' = apply_subst s other in
378                 let order = cmp c' other' in
379                 if order <> U.Lt && order <> U.Le then
380                   res::(find_all_matches ~unif_fun metasenv context ugraph
381                           lift_amount term termty tl)
382                 else
383                   find_all_matches ~unif_fun metasenv context ugraph
384                     lift_amount term termty tl
385           with
386           | Inference.MatchingFailure
387           | CicUnification.UnificationFailure _
388           | CicUnification.Uncertain _ ->
389               find_all_matches ~unif_fun metasenv context ugraph
390                 lift_amount term termty tl
391 ;;
392
393 let find_all_matches 
394   ?unif_fun metasenv context ugraph lift_amount term termty l 
395 =
396   let rc = 
397     find_all_matches 
398       ?unif_fun metasenv context ugraph lift_amount term termty l 
399   in
400   (*prerr_endline "CANDIDATES:";
401   List.iter (fun (_,x)->prerr_endline (Inference.string_of_equality x)) l;
402   prerr_endline ("MATCHING:" ^ CicPp.ppterm term ^ " are " ^ string_of_int
403   (List.length rc));*)
404   rc
405
406 (*
407   returns true if target is subsumed by some equality in table
408 *)
409 let subsumption env table target = 
410   (* 
411   let print_res l =
412     prerr_endline (String.concat "\n" (List.map (fun (_, subst, menv, ug,
413     ((pos,equation),_)) -> Inference.string_of_equality equation)l))
414   in
415   *)
416   let _, _, (ty, left, right, _), tmetas, _ = Equality.open_equality target in
417   let metasenv, context, ugraph = env in
418   let metasenv = tmetas in
419   let leftr =
420     match left with
421     | Cic.Meta _ -> []   
422     | _ ->
423         let leftc = get_candidates Matching table left in
424         find_all_matches ~unif_fun:Inference.matching
425           metasenv context ugraph 0 left ty leftc
426   in
427 (*  print_res leftr;*)
428   let rec ok what = function
429     | [] -> None
430     | (_, subst, menv, ug, ((pos,equation),_))::tl ->
431         let _, _, (_, l, r, o), m,_ = Equality.open_equality equation in
432         try
433           let other = if pos = Utils.Left then r else l in
434           let subst', menv', ug' =
435             let t1 = Unix.gettimeofday () in
436             try
437               let r = 
438                 Inference.matching metasenv m context what other ugraph
439               in
440               let t2 = Unix.gettimeofday () in
441               match_unif_time_ok := !match_unif_time_ok +. (t2 -. t1);
442               r
443             with Inference.MatchingFailure as e ->
444               let t2 = Unix.gettimeofday () in
445               match_unif_time_no := !match_unif_time_no +. (t2 -. t1);
446               raise e
447           in
448           (match Subst.merge_subst_if_possible subst subst' with
449           | None -> ok what tl
450           | Some s -> Some (s, equation))
451         with Inference.MatchingFailure ->
452           ok what tl
453   in
454   match ok right leftr with
455   | Some _ as res -> res
456   | None -> 
457       let rightr =
458         match right with
459           | Cic.Meta _ -> [] 
460           | _ ->
461               let rightc = get_candidates Matching table right in
462                 find_all_matches ~unif_fun:Inference.matching
463                   metasenv context ugraph 0 right ty rightc
464       in
465 (*        print_res rightr;*)
466         ok left rightr
467 (*     (if r then  *)
468 (*        debug_print  *)
469 (*          (lazy *)
470 (*             (Printf.sprintf "SUBSUMPTION! %s\n%s\n" *)
471 (*                (Inference.string_of_equality target) (Utils.print_subst s)))); *)
472 ;;
473
474 let rec demodulation_aux ?from ?(typecheck=false) 
475   metasenv context ugraph table lift_amount term =
476   (* Printf.eprintf "term = %s\n" (CicPp.ppterm term); *)
477   let module C = Cic in
478   let module S = CicSubstitution in
479   let module M = CicMetaSubst in
480   let module HL = HelmLibraryObjects in
481   let candidates = 
482     get_candidates ~env:(metasenv,context,ugraph) (* Unification *) Matching table term in
483   if List.exists (fun (i,_,_) -> i = 2840) metasenv
484   then
485     (prerr_endline ("term: " ^(CicPp.ppterm term));
486      List.iter (fun (_,x) -> prerr_endline (Equality.string_of_equality  x))
487        candidates;
488      prerr_endline ("-------");
489      prerr_endline ("+++++++"));
490   let res =
491     match term with
492       | C.Meta _ -> None
493       | term ->
494           let termty, ugraph =
495             if typecheck then
496               CicTypeChecker.type_of_aux' metasenv context term ugraph
497             else
498               C.Implicit None, ugraph
499           in
500           let res =
501             find_matches metasenv context ugraph lift_amount term termty candidates
502           in
503           if Utils.debug_res then ignore(check_res res "demod1"); 
504             if res <> None then
505               res
506             else
507               match term with
508                 | C.Appl l ->
509                     let res, ll = 
510                       List.fold_left
511                         (fun (res, tl) t ->
512                            if res <> None then
513                              (res, tl @ [S.lift 1 t])
514                            else 
515                              let r =
516                                demodulation_aux ~from:"1" metasenv context ugraph table
517                                  lift_amount t
518                              in
519                                match r with
520                                  | None -> (None, tl @ [S.lift 1 t])
521                                  | Some (rel, _, _, _, _) -> (r, tl @ [rel]))
522                         (None, []) l
523                     in (
524                         match res with
525                           | None -> None
526                           | Some (_, subst, menv, ug, eq_found) ->
527                               Some (C.Appl ll, subst, menv, ug, eq_found)
528                       )
529                 | C.Prod (nn, s, t) ->
530                     let r1 =
531                       demodulation_aux ~from:"2"
532                         metasenv context ugraph table lift_amount s in (
533                         match r1 with
534                           | None ->
535                               let r2 =
536                                 demodulation_aux metasenv
537                                   ((Some (nn, C.Decl s))::context) ugraph
538                                   table (lift_amount+1) t
539                               in (
540                                   match r2 with
541                                     | None -> None
542                                     | Some (t', subst, menv, ug, eq_found) ->
543                                         Some (C.Prod (nn, (S.lift 1 s), t'),
544                                               subst, menv, ug, eq_found)
545                                 )
546                           | Some (s', subst, menv, ug, eq_found) ->
547                               Some (C.Prod (nn, s', (S.lift 1 t)),
548                                     subst, menv, ug, eq_found)
549                       )
550                 | C.Lambda (nn, s, t) ->
551                     let r1 =
552                       demodulation_aux 
553                         metasenv context ugraph table lift_amount s in (
554                         match r1 with
555                           | None ->
556                               let r2 =
557                                 demodulation_aux metasenv
558                                   ((Some (nn, C.Decl s))::context) ugraph
559                                   table (lift_amount+1) t
560                               in (
561                                   match r2 with
562                                     | None -> None
563                                     | Some (t', subst, menv, ug, eq_found) ->
564                                         Some (C.Lambda (nn, (S.lift 1 s), t'),
565                                               subst, menv, ug, eq_found)
566                                 )
567                           | Some (s', subst, menv, ug, eq_found) ->
568                               Some (C.Lambda (nn, s', (S.lift 1 t)),
569                                     subst, menv, ug, eq_found)
570                       )
571                 | t ->
572                     None
573   in
574   if Utils.debug_res then ignore(check_res res "demod_aux output"); 
575   res
576 ;;
577
578
579 let build_newtarget_time = ref 0.;;
580
581
582 let demod_counter = ref 1;;
583
584 exception Foo
585
586 let profiler = HExtlib.profile "P/Indexing.demod_eq[build_new_target]"
587
588 (** demodulation, when target is an equality *)
589 let rec demodulation_equality ?from newmeta env table sign target =
590   let module C = Cic in
591   let module S = CicSubstitution in
592   let module M = CicMetaSubst in
593   let module HL = HelmLibraryObjects in
594   let module U = Utils in
595   let metasenv, context, ugraph = env in
596   let w, proof, (eq_ty, left, right, order), metas, id = 
597     Equality.open_equality target 
598   in
599   (* first, we simplify *)
600 (*   let right = U.guarded_simpl context right in *)
601 (*   let left = U.guarded_simpl context left in *)
602 (*   let order = !Utils.compare_terms left right in *)
603 (*   let stat = (eq_ty, left, right, order) in  *)
604 (*  let w = Utils.compute_equality_weight stat in*)
605   (* let target = Equality.mk_equality (w, proof, stat, metas) in *)
606   if Utils.debug_metas then 
607     ignore(check_target context target "demod equalities input");
608   let metasenv' = (* metasenv @ *) metas in
609   let maxmeta = ref newmeta in
610   
611   let build_newtarget is_left (t, subst, menv, ug, (eq_found, eq_URI)) =
612     let time1 = Unix.gettimeofday () in
613     
614     if Utils.debug_metas then
615       begin
616         ignore(check_for_duplicates menv "input1");
617         ignore(check_disjoint_invariant subst menv "input2");
618         let substs = Subst.ppsubst subst in 
619         ignore(check_target context (snd eq_found) ("input3" ^ substs))
620       end;
621     let pos, equality = eq_found in
622     let (_, proof', 
623         (ty, what, other, _), menv',id') = Equality.open_equality equality in
624     let ty =
625       try fst (CicTypeChecker.type_of_aux' metasenv context what ugraph)
626       with CicUtil.Meta_not_found _ -> ty
627     in
628     let what, other = if pos = Utils.Left then what, other else other, what in
629     let newterm, newproof =
630       let bo = 
631         Utils.guarded_simpl context (apply_subst subst (S.subst other t)) in
632 (*      let name = C.Name ("x_Demod" ^ (string_of_int !demod_counter)) in*)
633       let name = C.Name "x" in
634       incr demod_counter;
635       let bo' =
636         let l, r = if is_left then t, S.lift 1 right else S.lift 1 left, t in
637           C.Appl [C.MutInd (LibraryObjects.eq_URI (), 0, []);
638                   S.lift 1 eq_ty; l; r]
639       in
640       if sign = Utils.Positive then
641           (bo, (Equality.Step (subst,(Equality.Demodulation, id,(pos,id'),
642           (Cic.Lambda (name, ty, bo'))))))
643       else
644         assert false
645 (*
646         begin
647         prerr_endline "***************************************negative";
648         let metaproof = 
649           incr maxmeta;
650           let irl =
651             CicMkImplicit.identity_relocation_list_for_metavariable context in
652 (*        debug_print (lazy (Printf.sprintf "\nADDING META: %d\n" !maxmeta)); *)
653 (*        print_newline (); *)
654           C.Meta (!maxmeta, irl)
655         in
656           let eq_found =
657             let proof'_old' =
658               let termlist =
659                 if pos = Utils.Left then [ty; what; other]
660                 else [ty; other; what]
661               in
662               Equality.ProofSymBlock (termlist, proof'_old)
663             in
664             let proof'_new' = assert false (* not implemented *) in
665             let what, other =
666               if pos = Utils.Left then what, other else other, what
667             in
668             pos, 
669               Equality.mk_equality 
670                 (0, (proof'_new',proof'_old'), 
671                 (ty, other, what, Utils.Incomparable),menv')
672           in
673           let target_proof =
674             let pb =
675               Equality.ProofBlock 
676                 (subst, eq_URI, (name, ty), bo',
677                  eq_found, Equality.BasicProof (Equality.empty_subst,metaproof))
678             in
679             assert false, (* not implemented *)
680             (match snd proof with
681             | Equality.BasicProof _ ->
682                 (* print_endline "replacing a BasicProof"; *)
683                 pb
684             | Equality.ProofGoalBlock (_, parent_proof) ->
685   (* print_endline "replacing another ProofGoalBlock"; *)
686                 Equality.ProofGoalBlock (pb, parent_proof)
687             | _ -> assert false)
688           in
689         let refl =
690           C.Appl [C.MutConstruct (* reflexivity *)
691                     (LibraryObjects.eq_URI (), 0, 1, []);
692                   eq_ty; if is_left then right else left]          
693         in
694         (bo,
695          (assert false, (* not implemented *)
696          Equality.ProofGoalBlock 
697            (Equality.BasicProof (Equality.empty_subst,refl), snd target_proof)))
698       end
699 *)
700     in
701     let newmenv = (* Inference.filter subst *) menv in
702     let _ = 
703       if Utils.debug_metas then 
704         try ignore(CicTypeChecker.type_of_aux'
705           newmenv context 
706             (Equality.build_proof_term newproof) ugraph);
707           () 
708         with exc ->                   
709           prerr_endline "sempre lui";
710           prerr_endline (Subst.ppsubst subst);
711           prerr_endline (CicPp.ppterm 
712             (Equality.build_proof_term newproof));
713           prerr_endline ("+++++++++++++termine: " ^ (CicPp.ppterm t));
714           prerr_endline ("+++++++++++++what: " ^ (CicPp.ppterm what));
715           prerr_endline ("+++++++++++++other: " ^ (CicPp.ppterm other));
716           prerr_endline ("+++++++++++++subst: " ^ (Subst.ppsubst subst));
717           prerr_endline ("+++++++++++++newmenv: " ^ (CicMetaSubst.ppmetasenv []
718             newmenv));
719           raise exc;
720       else () 
721     in
722     let left, right = if is_left then newterm, right else left, newterm in
723     let ordering = !Utils.compare_terms left right in
724     let stat = (eq_ty, left, right, ordering) in
725     let time2 = Unix.gettimeofday () in
726     build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
727     let res =
728       let w = Utils.compute_equality_weight stat in
729       Equality.mk_equality (w, newproof, stat,newmenv) 
730     in
731     if Utils.debug_metas then 
732       ignore(check_target context res "buildnew_target output");
733     !maxmeta, res 
734   in
735   let build_newtarget is_left x =
736     profiler.HExtlib.profile (build_newtarget is_left) x
737   in
738
739   let res = demodulation_aux ~from:"3" metasenv' context ugraph table 0 left in
740   if Utils.debug_res then check_res res "demod result";
741   let newmeta, newtarget = 
742     match res with
743     | Some t ->
744         let newmeta, newtarget = build_newtarget true t in
745           assert (not (Equality.meta_convertibility_eq target newtarget));
746           if (Equality.is_weak_identity newtarget) ||
747             (Equality.meta_convertibility_eq target newtarget) then
748               newmeta, newtarget
749           else 
750             demodulation_equality ?from newmeta env table sign newtarget
751     | None ->
752         let res = demodulation_aux metasenv' context ugraph table 0 right in
753         if Utils.debug_res then check_res res "demod result 1"; 
754           match res with
755           | Some t ->
756               let newmeta, newtarget = build_newtarget false t in
757                 if (Equality.is_weak_identity newtarget) ||
758                   (Equality.meta_convertibility_eq target newtarget) then
759                     newmeta, newtarget
760                 else
761                    demodulation_equality ?from newmeta env table sign newtarget
762           | None ->
763               newmeta, target
764   in
765   (* newmeta, newtarget *)
766   newmeta,newtarget 
767 ;;
768
769 (**
770    Performs the beta expansion of the term "term" w.r.t. "table",
771    i.e. returns the list of all the terms t s.t. "(t term) = t2", for some t2
772    in table.
773 *)
774 let rec betaexpand_term metasenv context ugraph table lift_amount term =
775   let module C = Cic in
776   let module S = CicSubstitution in
777   let module M = CicMetaSubst in
778   let module HL = HelmLibraryObjects in
779   let candidates = get_candidates Unification table term in
780   
781   let res, lifted_term = 
782     match term with
783     | C.Meta (i, l) ->
784         let l', lifted_l =
785           List.fold_right
786             (fun arg (res, lifted_tl) ->
787                match arg with
788                | Some arg ->
789                    let arg_res, lifted_arg =
790                      betaexpand_term metasenv context ugraph table
791                        lift_amount arg in
792                    let l1 =
793                      List.map
794                        (fun (t, s, m, ug, eq_found) ->
795                           (Some t)::lifted_tl, s, m, ug, eq_found)
796                        arg_res
797                    in
798                    (l1 @
799                       (List.map
800                          (fun (l, s, m, ug, eq_found) ->
801                             (Some lifted_arg)::l, s, m, ug, eq_found)
802                          res),
803                     (Some lifted_arg)::lifted_tl)
804                | None ->
805                    (List.map
806                       (fun (r, s, m, ug, eq_found) ->
807                          None::r, s, m, ug, eq_found) res,
808                     None::lifted_tl)
809             ) l ([], [])
810         in
811         let e =
812           List.map
813             (fun (l, s, m, ug, eq_found) ->
814                (C.Meta (i, l), s, m, ug, eq_found)) l'
815         in
816         e, C.Meta (i, lifted_l)
817           
818     | C.Rel m ->
819         [], if m <= lift_amount then C.Rel m else C.Rel (m+1)
820           
821     | C.Prod (nn, s, t) ->
822         let l1, lifted_s =
823           betaexpand_term metasenv context ugraph table lift_amount s in
824         let l2, lifted_t =
825           betaexpand_term metasenv ((Some (nn, C.Decl s))::context) ugraph
826             table (lift_amount+1) t in
827         let l1' =
828           List.map
829             (fun (t, s, m, ug, eq_found) ->
830                C.Prod (nn, t, lifted_t), s, m, ug, eq_found) l1
831         and l2' =
832           List.map
833             (fun (t, s, m, ug, eq_found) ->
834                C.Prod (nn, lifted_s, t), s, m, ug, eq_found) l2 in
835         l1' @ l2', C.Prod (nn, lifted_s, lifted_t)
836           
837     | C.Lambda (nn, s, t) ->
838         let l1, lifted_s =
839           betaexpand_term metasenv context ugraph table lift_amount s in
840         let l2, lifted_t =
841           betaexpand_term metasenv ((Some (nn, C.Decl s))::context) ugraph
842             table (lift_amount+1) t in
843         let l1' =
844           List.map
845             (fun (t, s, m, ug, eq_found) ->
846                C.Lambda (nn, t, lifted_t), s, m, ug, eq_found) l1
847         and l2' =
848           List.map
849             (fun (t, s, m, ug, eq_found) ->
850                C.Lambda (nn, lifted_s, t), s, m, ug, eq_found) l2 in
851         l1' @ l2', C.Lambda (nn, lifted_s, lifted_t)
852
853     | C.Appl l ->
854         let l', lifted_l =
855           List.fold_right
856             (fun arg (res, lifted_tl) ->
857                let arg_res, lifted_arg =
858                  betaexpand_term metasenv context ugraph table lift_amount arg
859                in
860                let l1 =
861                  List.map
862                    (fun (a, s, m, ug, eq_found) ->
863                       a::lifted_tl, s, m, ug, eq_found)
864                    arg_res
865                in
866                (l1 @
867                   (List.map
868                      (fun (r, s, m, ug, eq_found) ->
869                         lifted_arg::r, s, m, ug, eq_found)
870                      res),
871                 lifted_arg::lifted_tl)
872             ) l ([], [])
873         in
874         (List.map
875            (fun (l, s, m, ug, eq_found) -> (C.Appl l, s, m, ug, eq_found)) l',
876          C.Appl lifted_l)
877
878     | t -> [], (S.lift lift_amount t)
879   in
880   match term with
881   | C.Meta (i, l) -> res, lifted_term
882   | term ->
883       let termty, ugraph =
884         C.Implicit None, ugraph
885 (*         CicTypeChecker.type_of_aux' metasenv context term ugraph *)
886       in
887       let r = 
888         find_all_matches
889           metasenv context ugraph lift_amount term termty candidates
890       in
891       r @ res, lifted_term
892 ;;
893
894 let profiler = HExtlib.profile "P/Indexing.betaexpand_term"
895
896 let betaexpand_term metasenv context ugraph table lift_amount term =
897   profiler.HExtlib.profile 
898     (betaexpand_term metasenv context ugraph table lift_amount) term
899
900
901 let sup_l_counter = ref 1;;
902
903 (**
904    superposition_left 
905    returns a list of new clauses inferred with a left superposition step
906    the negative equation "target" and one of the positive equations in "table"
907 *)
908 let superposition_left newmeta (metasenv, context, ugraph) table target = 
909   assert false
910 (*
911 let superposition_left newmeta (metasenv, context, ugraph) table target =
912   let module C = Cic in
913   let module S = CicSubstitution in
914   let module M = CicMetaSubst in
915   let module HL = HelmLibraryObjects in
916   let module CR = CicReduction in
917   let module U = Utils in
918   let weight, proof, (eq_ty, left, right, ordering), menv, id = 
919     Equality.open_equality target 
920   in
921   if Utils.debug_metas then
922     ignore(check_target context target "superpositionleft");
923   let expansions, _ =
924     let term = if ordering = U.Gt then left else right in
925     betaexpand_term metasenv context ugraph table 0 term
926   in
927   let maxmeta = ref newmeta in
928   let build_new (bo, s, m, ug, (eq_found, eq_URI)) =
929 (*     debug_print (lazy "\nSUPERPOSITION LEFT\n"); *)
930     let time1 = Unix.gettimeofday () in
931     
932     let pos, equality = eq_found in
933     let _,proof',(ty,what,other,_),menv',id'=Equality.open_equality equality in
934     let proof'_new, proof'_old = proof' in
935     let what, other = if pos = Utils.Left then what, other else other, what in
936     let newgoal, newproof =
937       let bo' =  U.guarded_simpl context (apply_subst s (S.subst other bo)) in
938       let name = C.Name ("x_SupL_" ^ (string_of_int !sup_l_counter)) in
939       incr sup_l_counter;
940       let bo'' = 
941         let l, r =
942           if ordering = U.Gt then bo, S.lift 1 right else S.lift 1 left, bo in
943         C.Appl [C.MutInd (LibraryObjects.eq_URI (), 0, []);
944                 S.lift 1 eq_ty; l; r]
945       in
946       incr maxmeta;
947       let metaproof =
948         let irl =
949           CicMkImplicit.identity_relocation_list_for_metavariable context in
950         C.Meta (!maxmeta, irl)
951       in
952       let eq_found =
953         let proof' =
954           let termlist =
955             if pos = Utils.Left then [ty; what; other]
956             else [ty; other; what]
957           in
958           proof'_new, (* MAH????? *)
959           Equality.ProofSymBlock (termlist, proof'_old)
960         in
961         let what, other =
962           if pos = Utils.Left then what, other else other, what
963         in
964         pos, 
965           Equality.mk_equality 
966             (0, proof', (ty, other, what, Utils.Incomparable), menv')
967       in
968       let target_proof = assert false (*
969         let pb =
970           Equality.ProofBlock 
971             (s, eq_URI, (name, ty), bo'', eq_found,
972             Equality.BasicProof (Equality.empty_subst,metaproof))
973         in
974         match proof with
975         | Equality.BasicProof _ ->
976 (*             debug_print (lazy "replacing a BasicProof"); *)
977             pb
978         | Equality.ProofGoalBlock (_, parent_proof) ->
979 (*             debug_print (lazy "replacing another ProofGoalBlock"); *)
980             Equality.ProofGoalBlock (pb, parent_proof)
981         | _ -> assert false*)
982       in
983       let refl =
984         C.Appl [C.MutConstruct (* reflexivity *)
985                   (LibraryObjects.eq_URI (), 0, 1, []);
986                 eq_ty; if ordering = U.Gt then right else left]
987       in
988       (bo',
989        (Equality.Step (Equality.SuperpositionLeft,id,(pos,id'),
990          assert false), (* il predicato della beta expand non viene tenuto? *) 
991        Equality.ProofGoalBlock 
992         (Equality.BasicProof (Equality.empty_subst,refl), target_proof)))
993     in
994     let left, right =
995       if ordering = U.Gt then newgoal, right else left, newgoal in
996     let neworder = !Utils.compare_terms left right in
997     let stat = (eq_ty, left, right, neworder) in
998     let newmenv = (* Inference.filter s *) menv in  
999     let time2 = Unix.gettimeofday () in
1000     build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
1001
1002     let w = Utils.compute_equality_weight stat in
1003     Equality.mk_equality (w, newproof, stat, newmenv) 
1004
1005   in
1006   !maxmeta, List.map build_new expansions
1007 ;;
1008 *)
1009
1010 let sup_r_counter = ref 1;;
1011
1012 (**
1013    superposition_right
1014    returns a list of new clauses inferred with a right superposition step
1015    between the positive equation "target" and one in the "table" "newmeta" is
1016    the first free meta index, i.e. the first number above the highest meta
1017    index: its updated value is also returned
1018 *)
1019 let superposition_right newmeta (metasenv, context, ugraph) table target =
1020   let module C = Cic in
1021   let module S = CicSubstitution in
1022   let module M = CicMetaSubst in
1023   let module HL = HelmLibraryObjects in
1024   let module CR = CicReduction in
1025   let module U = Utils in 
1026   let w, eqproof, (eq_ty, left, right, ordering), newmetas,id = 
1027     Equality.open_equality target 
1028   in 
1029   if Utils.debug_metas then 
1030     ignore (check_target context target "superpositionright");
1031   let metasenv' = newmetas in
1032   let maxmeta = ref newmeta in
1033   let res1, res2 =
1034     let betaexpand_term metasenv context ugraph table d term =
1035       let t1 = Unix.gettimeofday () in
1036       let res = betaexpand_term metasenv context ugraph table d term in
1037       let t2 = Unix.gettimeofday () in
1038         beta_expand_time := !beta_expand_time  +. (t2 -. t1);
1039         res
1040     in
1041     match ordering with
1042     | U.Gt -> fst (betaexpand_term metasenv' context ugraph table 0 left), []
1043     | U.Lt -> [], fst (betaexpand_term metasenv' context ugraph table 0 right)
1044     | _ ->
1045         let res l r =
1046           List.filter
1047             (fun (_, subst, _, _, _) ->
1048                let subst = apply_subst subst in
1049                let o = !Utils.compare_terms (subst l) (subst r) in
1050                o <> U.Lt && o <> U.Le)
1051             (fst (betaexpand_term metasenv' context ugraph table 0 l))
1052         in
1053         (res left right), (res right left)
1054   in
1055   let build_new ordering (bo, s, m, ug, (eq_found, eq_URI)) =
1056     if Utils.debug_metas then 
1057       ignore (check_target context (snd eq_found) "buildnew1" );
1058     let time1 = Unix.gettimeofday () in
1059     
1060     let pos, equality =  eq_found in
1061     let (_, proof', (ty, what, other, _), menv',id') = 
1062       Equality.open_equality  equality in
1063     let what, other = if pos = Utils.Left then what, other else other, what in
1064     let newgoal, newproof =
1065       (* qua *)
1066       let bo' =
1067         Utils.guarded_simpl context (apply_subst s (S.subst other bo)) 
1068       in
1069       let name = C.Name "x" in
1070       incr sup_r_counter;
1071       let bo'' =
1072         let l, r =
1073           if ordering = U.Gt then bo, S.lift 1 right else S.lift 1 left, bo in
1074         C.Appl [C.MutInd (LibraryObjects.eq_URI (), 0, []);
1075                 S.lift 1 eq_ty; l; r]
1076       in
1077       bo',
1078         Equality.Step 
1079           (s,(Equality.SuperpositionRight,
1080                id,(pos,id'),(Cic.Lambda(name,ty,bo''))))
1081     in
1082     let newmeta, newequality = 
1083       let left, right =
1084         if ordering = U.Gt then newgoal, apply_subst s right
1085         else apply_subst s left, newgoal in
1086       let neworder = !Utils.compare_terms left right in
1087       let newmenv = (* Inference.filter s *) m in
1088       let stat = (eq_ty, left, right, neworder) in
1089       let eq' =
1090         let w = Utils.compute_equality_weight stat in
1091         Equality.mk_equality (w, newproof, stat, newmenv) in
1092       if Utils.debug_metas then 
1093         ignore (check_target context eq' "buildnew3");
1094       let newm, eq' = Equality.fix_metas !maxmeta eq' in
1095       if Utils.debug_metas then 
1096         ignore (check_target context eq' "buildnew4");
1097       newm, eq'
1098     in
1099     maxmeta := newmeta;
1100     let time2 = Unix.gettimeofday () in
1101     build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
1102     if Utils.debug_metas then 
1103       ignore(check_target context newequality "buildnew2"); 
1104     newequality
1105   in
1106   let new1 = List.map (build_new U.Gt) res1
1107   and new2 = List.map (build_new U.Lt) res2 in
1108   let ok e = not (Equality.is_identity (metasenv', context, ugraph) e) in
1109   (!maxmeta,
1110    (List.filter ok (new1 @ new2)))
1111 ;;
1112
1113
1114 (** demodulation, when the target is a goal *)
1115 let rec demodulation_goal newmeta env table goal =
1116   let module C = Cic in
1117   let module S = CicSubstitution in
1118   let module M = CicMetaSubst in
1119   let module HL = HelmLibraryObjects in
1120   let metasenv, context, ugraph = env in
1121   let maxmeta = ref newmeta in
1122   let goalproof, metas, term = goal in
1123   let term = Utils.guarded_simpl (~debug:true) context term in
1124   let goal = goalproof, metas, term in
1125   let metasenv' = metas in
1126   
1127   let build_newgoal (t, subst, menv, ug, (eq_found, eq_URI)) =
1128     let pos, equality = eq_found in
1129     let (_, proof', (ty, what, other, _), menv',id) = 
1130       Equality.open_equality equality in
1131     let what, other = if pos = Utils.Left then what, other else other, what in
1132     let ty =
1133       try fst (CicTypeChecker.type_of_aux' metasenv context what ugraph)
1134       with CicUtil.Meta_not_found _ -> ty
1135     in
1136     let newterm, newgoalproof =
1137       let bo = 
1138         Utils.guarded_simpl context (apply_subst subst(S.subst other t)) 
1139       in
1140       let bo' = (*apply_subst subst*) t in 
1141       let name = C.Name "x" in
1142       incr demod_counter;
1143       let newgoalproofstep = (pos,id,subst,Cic.Lambda (name,ty,bo')) in
1144       bo, (newgoalproofstep::goalproof)
1145     in
1146     let newmetasenv = (* Inference.filter subst *) menv in
1147     !maxmeta, (newgoalproof, newmetasenv, newterm)
1148   in  
1149   let res =
1150     demodulation_aux (* ~typecheck:true *) metasenv' context ugraph table 0 term
1151   in
1152   match res with
1153   | Some t ->
1154       let newmeta, newgoal = build_newgoal t in
1155       let _, _, newg = newgoal in
1156       if Equality.meta_convertibility term newg then
1157         false, newmeta, newgoal
1158       else
1159         let changed, newmeta, newgoal = 
1160           demodulation_goal newmeta env table newgoal 
1161         in
1162         true, newmeta, newgoal
1163   | None ->
1164       false, newmeta, goal
1165 ;;
1166
1167 (** demodulation, when the target is a theorem *)
1168 let rec demodulation_theorem newmeta env table theorem =
1169   let module C = Cic in
1170   let module S = CicSubstitution in
1171   let module M = CicMetaSubst in
1172   let module HL = HelmLibraryObjects in
1173   let metasenv, context, ugraph = env in
1174   let maxmeta = ref newmeta in
1175   let term, termty, metas = theorem in
1176   let metasenv' = metas in
1177   
1178   let build_newtheorem (t, subst, menv, ug, (eq_found, eq_URI)) =
1179     let pos, equality = eq_found in
1180     let (_, proof', (ty, what, other, _), menv',id) = 
1181       Equality.open_equality equality in
1182     let what, other = if pos = Utils.Left then what, other else other, what in
1183     let newterm, newty =
1184       let bo = Utils.guarded_simpl context (apply_subst subst (S.subst other t)) in
1185 (*      let bo' = apply_subst subst t in *)
1186 (*      let name = C.Name ("x_DemodThm_" ^ (string_of_int !demod_counter)) in*)
1187       incr demod_counter;
1188 (*
1189       let newproofold =
1190         Equality.ProofBlock (subst, eq_URI, (name, ty), bo', eq_found,
1191                               Equality.BasicProof (Equality.empty_subst,term))
1192       in
1193       (Equality.build_proof_term_old newproofold, bo)
1194 *)
1195       (* TODO, not ported to the new proofs *) 
1196       if true then assert false; term, bo
1197     in    
1198     !maxmeta, (newterm, newty, menv)
1199   in  
1200   let res =
1201     demodulation_aux (* ~typecheck:true *) metasenv' context ugraph table 0 termty
1202   in
1203   match res with
1204   | Some t ->
1205       let newmeta, newthm = build_newtheorem t in
1206       let newt, newty, _ = newthm in
1207       if Equality.meta_convertibility termty newty then
1208         newmeta, newthm
1209       else
1210         demodulation_theorem newmeta env table newthm
1211   | None ->
1212       newmeta, theorem
1213 ;;
1214