]> matita.cs.unibo.it Git - helm.git/blob - components/tactics/paramodulation/indexing.ml
d71e7c5a793702bbdd2210f40b9f44ebe5146699
[helm.git] / 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 = Equality.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,_,_) -> (Equality.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_old (snd 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 Equality.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_new, proof_old) as proof), 
597      (eq_ty, left, right, order), metas, id = 
598     Equality.open_equality target 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 = Equality.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'_new,proof'_old), 
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,
642            (Equality.Step (subst,(Equality.Demodulation,id,(pos,id'),
643                          (*apply_subst subst*) (Cic.Lambda (name, ty, bo')))),
644            Equality.ProofBlock (
645              subst, eq_URI, (name, ty), bo'(* t' *), eq_found, proof_old)))
646       else
647         assert false
648 (*
649         begin
650         prerr_endline "***************************************negative";
651         let metaproof = 
652           incr maxmeta;
653           let irl =
654             CicMkImplicit.identity_relocation_list_for_metavariable context in
655 (*        debug_print (lazy (Printf.sprintf "\nADDING META: %d\n" !maxmeta)); *)
656 (*        print_newline (); *)
657           C.Meta (!maxmeta, irl)
658         in
659           let eq_found =
660             let proof'_old' =
661               let termlist =
662                 if pos = Utils.Left then [ty; what; other]
663                 else [ty; other; what]
664               in
665               Equality.ProofSymBlock (termlist, proof'_old)
666             in
667             let proof'_new' = assert false (* not implemented *) in
668             let what, other =
669               if pos = Utils.Left then what, other else other, what
670             in
671             pos, 
672               Equality.mk_equality 
673                 (0, (proof'_new',proof'_old'), 
674                 (ty, other, what, Utils.Incomparable),menv')
675           in
676           let target_proof =
677             let pb =
678               Equality.ProofBlock 
679                 (subst, eq_URI, (name, ty), bo',
680                  eq_found, Equality.BasicProof (Equality.empty_subst,metaproof))
681             in
682             assert false, (* not implemented *)
683             (match snd proof with
684             | Equality.BasicProof _ ->
685                 (* print_endline "replacing a BasicProof"; *)
686                 pb
687             | Equality.ProofGoalBlock (_, parent_proof) ->
688   (* print_endline "replacing another ProofGoalBlock"; *)
689                 Equality.ProofGoalBlock (pb, parent_proof)
690             | _ -> assert false)
691           in
692         let refl =
693           C.Appl [C.MutConstruct (* reflexivity *)
694                     (LibraryObjects.eq_URI (), 0, 1, []);
695                   eq_ty; if is_left then right else left]          
696         in
697         (bo,
698          (assert false, (* not implemented *)
699          Equality.ProofGoalBlock 
700            (Equality.BasicProof (Equality.empty_subst,refl), snd target_proof)))
701       end
702 *)
703     in
704     let newmenv = (* Inference.filter subst *) menv in
705     let _ = 
706       if Utils.debug_metas then 
707         try ignore(CicTypeChecker.type_of_aux'
708           newmenv context 
709             (Equality.build_proof_term_old (snd newproof)) ugraph);
710           () 
711         with exc ->                   
712           prerr_endline "sempre lui";
713           prerr_endline (Equality.ppsubst subst);
714           prerr_endline (CicPp.ppterm 
715             (Equality.build_proof_term_old (snd newproof)));
716           prerr_endline ("+++++++++++++termine: " ^ (CicPp.ppterm t));
717           prerr_endline ("+++++++++++++what: " ^ (CicPp.ppterm what));
718           prerr_endline ("+++++++++++++other: " ^ (CicPp.ppterm other));
719           prerr_endline ("+++++++++++++subst: " ^ (Equality.ppsubst subst));
720           prerr_endline ("+++++++++++++newmenv: " ^ (CicMetaSubst.ppmetasenv []
721             newmenv));
722           raise exc;
723       else () 
724     in
725     let left, right = if is_left then newterm, right else left, newterm in
726     let ordering = !Utils.compare_terms left right in
727     let stat = (eq_ty, left, right, ordering) in
728     let time2 = Unix.gettimeofday () in
729     build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
730     let res =
731       let w = Utils.compute_equality_weight stat in
732       Equality.mk_equality (w, newproof, stat,newmenv) 
733     in
734     if Utils.debug_metas then 
735       ignore(check_target context res "buildnew_target output");
736     !maxmeta, res 
737   in
738   let build_newtarget is_left x =
739     profiler.HExtlib.profile (build_newtarget is_left) x
740   in
741
742   let res = demodulation_aux ~from:"3" metasenv' context ugraph table 0 left in
743   if Utils.debug_res then check_res res "demod result";
744   let newmeta, newtarget = 
745     match res with
746     | Some t ->
747         let newmeta, newtarget = build_newtarget true t in
748           if (Equality.is_weak_identity newtarget) ||
749             (Equality.meta_convertibility_eq target newtarget) then
750               newmeta, newtarget
751           else 
752             demodulation_equality newmeta env table sign newtarget
753     | None ->
754         let res = demodulation_aux metasenv' context ugraph table 0 right in
755         if Utils.debug_res then check_res res "demod result 1"; 
756           match res with
757           | Some t ->
758               let newmeta, newtarget = build_newtarget false t in
759                 if (Equality.is_weak_identity newtarget) ||
760                   (Equality.meta_convertibility_eq target newtarget) then
761                     newmeta, newtarget
762                 else
763                    demodulation_equality newmeta env table sign newtarget
764           | None ->
765               newmeta, target
766   in
767   (* newmeta, newtarget *)
768   newmeta,newtarget 
769 ;;
770
771 (**
772    Performs the beta expansion of the term "term" w.r.t. "table",
773    i.e. returns the list of all the terms t s.t. "(t term) = t2", for some t2
774    in table.
775 *)
776 let rec betaexpand_term metasenv context ugraph table lift_amount term =
777   let module C = Cic in
778   let module S = CicSubstitution in
779   let module M = CicMetaSubst in
780   let module HL = HelmLibraryObjects in
781   let candidates = get_candidates Unification table term in
782   
783   let res, lifted_term = 
784     match term with
785     | C.Meta (i, l) ->
786         let l', lifted_l =
787           List.fold_right
788             (fun arg (res, lifted_tl) ->
789                match arg with
790                | Some arg ->
791                    let arg_res, lifted_arg =
792                      betaexpand_term metasenv context ugraph table
793                        lift_amount arg in
794                    let l1 =
795                      List.map
796                        (fun (t, s, m, ug, eq_found) ->
797                           (Some t)::lifted_tl, s, m, ug, eq_found)
798                        arg_res
799                    in
800                    (l1 @
801                       (List.map
802                          (fun (l, s, m, ug, eq_found) ->
803                             (Some lifted_arg)::l, s, m, ug, eq_found)
804                          res),
805                     (Some lifted_arg)::lifted_tl)
806                | None ->
807                    (List.map
808                       (fun (r, s, m, ug, eq_found) ->
809                          None::r, s, m, ug, eq_found) res,
810                     None::lifted_tl)
811             ) l ([], [])
812         in
813         let e =
814           List.map
815             (fun (l, s, m, ug, eq_found) ->
816                (C.Meta (i, l), s, m, ug, eq_found)) l'
817         in
818         e, C.Meta (i, lifted_l)
819           
820     | C.Rel m ->
821         [], if m <= lift_amount then C.Rel m else C.Rel (m+1)
822           
823     | C.Prod (nn, s, t) ->
824         let l1, lifted_s =
825           betaexpand_term metasenv context ugraph table lift_amount s in
826         let l2, lifted_t =
827           betaexpand_term metasenv ((Some (nn, C.Decl s))::context) ugraph
828             table (lift_amount+1) t in
829         let l1' =
830           List.map
831             (fun (t, s, m, ug, eq_found) ->
832                C.Prod (nn, t, lifted_t), s, m, ug, eq_found) l1
833         and l2' =
834           List.map
835             (fun (t, s, m, ug, eq_found) ->
836                C.Prod (nn, lifted_s, t), s, m, ug, eq_found) l2 in
837         l1' @ l2', C.Prod (nn, lifted_s, lifted_t)
838           
839     | C.Lambda (nn, s, t) ->
840         let l1, lifted_s =
841           betaexpand_term metasenv context ugraph table lift_amount s in
842         let l2, lifted_t =
843           betaexpand_term metasenv ((Some (nn, C.Decl s))::context) ugraph
844             table (lift_amount+1) t in
845         let l1' =
846           List.map
847             (fun (t, s, m, ug, eq_found) ->
848                C.Lambda (nn, t, lifted_t), s, m, ug, eq_found) l1
849         and l2' =
850           List.map
851             (fun (t, s, m, ug, eq_found) ->
852                C.Lambda (nn, lifted_s, t), s, m, ug, eq_found) l2 in
853         l1' @ l2', C.Lambda (nn, lifted_s, lifted_t)
854
855     | C.Appl l ->
856         let l', lifted_l =
857           List.fold_right
858             (fun arg (res, lifted_tl) ->
859                let arg_res, lifted_arg =
860                  betaexpand_term metasenv context ugraph table lift_amount arg
861                in
862                let l1 =
863                  List.map
864                    (fun (a, s, m, ug, eq_found) ->
865                       a::lifted_tl, s, m, ug, eq_found)
866                    arg_res
867                in
868                (l1 @
869                   (List.map
870                      (fun (r, s, m, ug, eq_found) ->
871                         lifted_arg::r, s, m, ug, eq_found)
872                      res),
873                 lifted_arg::lifted_tl)
874             ) l ([], [])
875         in
876         (List.map
877            (fun (l, s, m, ug, eq_found) -> (C.Appl l, s, m, ug, eq_found)) l',
878          C.Appl lifted_l)
879
880     | t -> [], (S.lift lift_amount t)
881   in
882   match term with
883   | C.Meta (i, l) -> res, lifted_term
884   | term ->
885       let termty, ugraph =
886         C.Implicit None, ugraph
887 (*         CicTypeChecker.type_of_aux' metasenv context term ugraph *)
888       in
889       let r = 
890         find_all_matches
891           metasenv context ugraph lift_amount term termty candidates
892       in
893       r @ res, lifted_term
894 ;;
895
896 let profiler = HExtlib.profile "P/Indexing.betaexpand_term"
897
898 let betaexpand_term metasenv context ugraph table lift_amount term =
899   profiler.HExtlib.profile 
900     (betaexpand_term metasenv context ugraph table lift_amount) term
901
902
903 let sup_l_counter = ref 1;;
904
905 (**
906    superposition_left 
907    returns a list of new clauses inferred with a left superposition step
908    the negative equation "target" and one of the positive equations in "table"
909 *)
910 let superposition_left newmeta (metasenv, context, ugraph) table target = 
911   assert false
912 (*
913 let superposition_left newmeta (metasenv, context, ugraph) table target =
914   let module C = Cic in
915   let module S = CicSubstitution in
916   let module M = CicMetaSubst in
917   let module HL = HelmLibraryObjects in
918   let module CR = CicReduction in
919   let module U = Utils in
920   let weight, proof, (eq_ty, left, right, ordering), menv, id = 
921     Equality.open_equality target 
922   in
923   if Utils.debug_metas then
924     ignore(check_target context target "superpositionleft");
925   let expansions, _ =
926     let term = if ordering = U.Gt then left else right in
927     betaexpand_term metasenv context ugraph table 0 term
928   in
929   let maxmeta = ref newmeta in
930   let build_new (bo, s, m, ug, (eq_found, eq_URI)) =
931 (*     debug_print (lazy "\nSUPERPOSITION LEFT\n"); *)
932     let time1 = Unix.gettimeofday () in
933     
934     let pos, equality = eq_found in
935     let _,proof',(ty,what,other,_),menv',id'=Equality.open_equality equality in
936     let proof'_new, proof'_old = proof' in
937     let what, other = if pos = Utils.Left then what, other else other, what in
938     let newgoal, newproof =
939       let bo' =  U.guarded_simpl context (apply_subst s (S.subst other bo)) in
940       let name = C.Name ("x_SupL_" ^ (string_of_int !sup_l_counter)) in
941       incr sup_l_counter;
942       let bo'' = 
943         let l, r =
944           if ordering = U.Gt then bo, S.lift 1 right else S.lift 1 left, bo in
945         C.Appl [C.MutInd (LibraryObjects.eq_URI (), 0, []);
946                 S.lift 1 eq_ty; l; r]
947       in
948       incr maxmeta;
949       let metaproof =
950         let irl =
951           CicMkImplicit.identity_relocation_list_for_metavariable context in
952         C.Meta (!maxmeta, irl)
953       in
954       let eq_found =
955         let proof' =
956           let termlist =
957             if pos = Utils.Left then [ty; what; other]
958             else [ty; other; what]
959           in
960           proof'_new, (* MAH????? *)
961           Equality.ProofSymBlock (termlist, proof'_old)
962         in
963         let what, other =
964           if pos = Utils.Left then what, other else other, what
965         in
966         pos, 
967           Equality.mk_equality 
968             (0, proof', (ty, other, what, Utils.Incomparable), menv')
969       in
970       let target_proof = assert false (*
971         let pb =
972           Equality.ProofBlock 
973             (s, eq_URI, (name, ty), bo'', eq_found,
974             Equality.BasicProof (Equality.empty_subst,metaproof))
975         in
976         match proof with
977         | Equality.BasicProof _ ->
978 (*             debug_print (lazy "replacing a BasicProof"); *)
979             pb
980         | Equality.ProofGoalBlock (_, parent_proof) ->
981 (*             debug_print (lazy "replacing another ProofGoalBlock"); *)
982             Equality.ProofGoalBlock (pb, parent_proof)
983         | _ -> assert false*)
984       in
985       let refl =
986         C.Appl [C.MutConstruct (* reflexivity *)
987                   (LibraryObjects.eq_URI (), 0, 1, []);
988                 eq_ty; if ordering = U.Gt then right else left]
989       in
990       (bo',
991        (Equality.Step (Equality.SuperpositionLeft,id,(pos,id'),
992          assert false), (* il predicato della beta expand non viene tenuto? *) 
993        Equality.ProofGoalBlock 
994         (Equality.BasicProof (Equality.empty_subst,refl), target_proof)))
995     in
996     let left, right =
997       if ordering = U.Gt then newgoal, right else left, newgoal in
998     let neworder = !Utils.compare_terms left right in
999     let stat = (eq_ty, left, right, neworder) in
1000     let newmenv = (* Inference.filter s *) menv in  
1001     let time2 = Unix.gettimeofday () in
1002     build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
1003
1004     let w = Utils.compute_equality_weight stat in
1005     Equality.mk_equality (w, newproof, stat, newmenv) 
1006
1007   in
1008   !maxmeta, List.map build_new expansions
1009 ;;
1010 *)
1011
1012 let sup_r_counter = ref 1;;
1013
1014 (**
1015    superposition_right
1016    returns a list of new clauses inferred with a right superposition step
1017    between the positive equation "target" and one in the "table" "newmeta" is
1018    the first free meta index, i.e. the first number above the highest meta
1019    index: its updated value is also returned
1020 *)
1021 let superposition_right newmeta (metasenv, context, ugraph) table target =
1022   let module C = Cic in
1023   let module S = CicSubstitution in
1024   let module M = CicMetaSubst in
1025   let module HL = HelmLibraryObjects in
1026   let module CR = CicReduction in
1027   let module U = Utils in 
1028   let w, (eqproof1,eqproof2), (eq_ty, left, right, ordering), newmetas,id = 
1029     Equality.open_equality target 
1030   in 
1031   if Utils.debug_metas then 
1032     ignore (check_target context target "superpositionright");
1033   let metasenv' = newmetas in
1034   let maxmeta = ref newmeta in
1035   let res1, res2 =
1036     let betaexpand_term metasenv context ugraph table d term =
1037       let t1 = Unix.gettimeofday () in
1038       let res = betaexpand_term metasenv context ugraph table d term in
1039       let t2 = Unix.gettimeofday () in
1040         beta_expand_time := !beta_expand_time  +. (t2 -. t1);
1041         res
1042     in
1043     match ordering with
1044     | U.Gt -> fst (betaexpand_term metasenv' context ugraph table 0 left), []
1045     | U.Lt -> [], fst (betaexpand_term metasenv' context ugraph table 0 right)
1046     | _ ->
1047         let res l r =
1048           List.filter
1049             (fun (_, subst, _, _, _) ->
1050                let subst = apply_subst subst in
1051                let o = !Utils.compare_terms (subst l) (subst r) in
1052                o <> U.Lt && o <> U.Le)
1053             (fst (betaexpand_term metasenv' context ugraph table 0 l))
1054         in
1055         (res left right), (res right left)
1056   in
1057   let build_new ordering (bo, s, m, ug, (eq_found, eq_URI)) =
1058     if Utils.debug_metas then 
1059       ignore (check_target context (snd eq_found) "buildnew1" );
1060     let time1 = Unix.gettimeofday () in
1061     
1062     let pos, equality =  eq_found in
1063     let (_, proof', (ty, what, other, _), menv',id') = 
1064       Equality.open_equality  equality in
1065     let what, other = if pos = Utils.Left then what, other else other, what in
1066     let newgoal, newproof =
1067       (* qua *)
1068       let bo' = Utils.guarded_simpl context (apply_subst s (S.subst other bo)) in
1069 (*      let name = C.Name ("x_SupR_" ^ (string_of_int !sup_r_counter)) in*)
1070       let name = C.Name "x" in
1071       incr sup_r_counter;
1072       let bo'' =
1073         let l, r =
1074           if ordering = U.Gt then bo, S.lift 1 right else S.lift 1 left, bo in
1075         C.Appl [C.MutInd (LibraryObjects.eq_URI (), 0, []);
1076                 S.lift 1 eq_ty; l; r]
1077       in
1078       bo',
1079       ( Equality.Step (s,(Equality.SuperpositionRight,
1080                       id,(pos,id'),(*apply_subst s*) (Cic.Lambda(name,ty,bo'')))),
1081         Equality.ProofBlock (s, eq_URI, (name, ty), bo'', eq_found, eqproof2))
1082        
1083     in
1084     let newmeta, newequality = 
1085       let left, right =
1086         if ordering = U.Gt then newgoal, apply_subst s right
1087         else apply_subst s left, newgoal in
1088       let neworder = !Utils.compare_terms left right in
1089       let newmenv = (* Inference.filter s *) m in
1090       let stat = (eq_ty, left, right, neworder) in
1091       let eq' =
1092         let w = Utils.compute_equality_weight stat in
1093         Equality.mk_equality (w, newproof, stat, newmenv) in
1094       if Utils.debug_metas then 
1095         ignore (check_target context eq' "buildnew3");
1096       let newm, eq' = Equality.fix_metas !maxmeta eq' in
1097       if Utils.debug_metas then 
1098         ignore (check_target context eq' "buildnew4");
1099       newm, eq'
1100     in
1101     maxmeta := newmeta;
1102     let time2 = Unix.gettimeofday () in
1103     build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
1104     if Utils.debug_metas then 
1105       ignore(check_target context newequality "buildnew2"); 
1106     newequality
1107   in
1108   let new1 = List.map (build_new U.Gt) res1
1109   and new2 = List.map (build_new U.Lt) res2 in
1110   let ok e = not (Equality.is_identity (metasenv', context, ugraph) e) in
1111   (!maxmeta,
1112    (List.filter ok (new1 @ new2)))
1113 ;;
1114
1115
1116 (** demodulation, when the target is a goal *)
1117 let rec demodulation_goal newmeta env table goal =
1118   let module C = Cic in
1119   let module S = CicSubstitution in
1120   let module M = CicMetaSubst in
1121   let module HL = HelmLibraryObjects in
1122   let metasenv, context, ugraph = env in
1123   let maxmeta = ref newmeta in
1124   let (cicproof,proof), metas, term = goal in
1125   let term = Utils.guarded_simpl (~debug:true) context term in
1126   let goal = (cicproof,proof), metas, term in
1127   let metasenv' = metas in
1128   
1129   let build_newgoal (t, subst, menv, ug, (eq_found, eq_URI)) =
1130     let pos, equality = eq_found in
1131     let (_, (proofnew',proof'), (ty, what, other, _), menv',id) = 
1132       Equality.open_equality equality in
1133     let what, other = if pos = Utils.Left then what, other else other, what in
1134     let ty =
1135       try fst (CicTypeChecker.type_of_aux' metasenv context what ugraph)
1136       with CicUtil.Meta_not_found _ -> ty
1137     in
1138     let newterm, newproof, newcicproof =
1139       let bo = 
1140         Utils.guarded_simpl context (apply_subst subst(S.subst other t)) 
1141       in
1142       let bo' = apply_subst subst t in 
1143 (*      let name = C.Name ("x_DemodGoal_" ^ (string_of_int !demod_counter)) in*)
1144       let name = C.Name "x" in
1145       incr demod_counter;
1146       let metaproof = 
1147         incr maxmeta;
1148         let irl = [] (*
1149           CicMkImplicit.identity_relocation_list_for_metavariable context *) in 
1150 (*         debug_print (lazy (Printf.sprintf "\nADDING META: %d\n" !maxmeta)); *)
1151         C.Meta (!maxmeta, irl)
1152       in
1153       let eq_found =
1154         let eq_found_proof =
1155           let termlist =
1156             if pos = Utils.Left then [ty; what; other]
1157             else [ty; other; what]
1158           in
1159           Equality.ProofSymBlock (termlist, proof')
1160         in
1161         let what, other =
1162           if pos = Utils.Left then what, other else other, what
1163         in
1164         pos, 
1165         Equality.mk_equality 
1166           (0,(proofnew',eq_found_proof), (ty, other, what, Utils.Incomparable), menv')
1167       in
1168       let goal_proof =
1169         let pb =
1170           Equality.ProofBlock 
1171             (subst, eq_URI, (name, ty), bo',
1172              eq_found, Equality.BasicProof (Equality.empty_subst,metaproof))
1173         in
1174         let rec repl = function
1175           | Equality.NoProof ->
1176 (*               debug_print (lazy "replacing a NoProof"); *)
1177               pb
1178           | Equality.BasicProof _ ->
1179 (*               debug_print (lazy "replacing a BasicProof"); *)
1180               pb
1181           | Equality.ProofGoalBlock (_, parent_proof) ->
1182 (*               debug_print (lazy "replacing another ProofGoalBlock"); *)
1183               Equality.ProofGoalBlock (pb, parent_proof)
1184           | Equality.SubProof (term, meta_index, p)  ->
1185               prerr_endline "subproof!";
1186               Equality.SubProof (term, meta_index, repl p)
1187           | _ -> assert false
1188         in repl proof
1189       in
1190       let newcicproofstep = (pos,id,subst,Cic.Lambda (name,ty,bo')) in
1191       bo, Equality.ProofGoalBlock (Equality.NoProof, goal_proof),
1192         (newcicproofstep::cicproof)
1193     in
1194     let newmetasenv = (* Inference.filter subst *) menv in
1195     !maxmeta, ((newcicproof,newproof), newmetasenv, newterm)
1196   in  
1197   let res =
1198     demodulation_aux (* ~typecheck:true *) metasenv' context ugraph table 0 term
1199   in
1200   match res with
1201   | Some t ->
1202       let newmeta, newgoal = build_newgoal t in
1203       let _, _, newg = newgoal in
1204       if Equality.meta_convertibility term newg then
1205         true, newmeta, newgoal
1206       else
1207         demodulation_goal newmeta env table newgoal
1208   | None ->
1209       false, newmeta, goal
1210 ;;
1211
1212 (** demodulation, when the target is a theorem *)
1213 let rec demodulation_theorem newmeta env table theorem =
1214   let module C = Cic in
1215   let module S = CicSubstitution in
1216   let module M = CicMetaSubst in
1217   let module HL = HelmLibraryObjects in
1218   let metasenv, context, ugraph = env in
1219   let maxmeta = ref newmeta in
1220   let term, termty, metas = theorem in
1221   let metasenv' = metas in
1222   
1223   let build_newtheorem (t, subst, menv, ug, (eq_found, eq_URI)) =
1224     let pos, equality = eq_found in
1225     let (_, proof', (ty, what, other, _), menv',id) = 
1226       Equality.open_equality equality in
1227     let what, other = if pos = Utils.Left then what, other else other, what in
1228     let newterm, newty =
1229       let bo = Utils.guarded_simpl context (apply_subst subst (S.subst other t)) in
1230       let bo' = apply_subst subst t in 
1231       let name = C.Name ("x_DemodThm_" ^ (string_of_int !demod_counter)) in
1232       incr demod_counter;
1233       let newproofold =
1234         Equality.ProofBlock (subst, eq_URI, (name, ty), bo', eq_found,
1235                               Equality.BasicProof (Equality.empty_subst,term))
1236       in
1237       (Equality.build_proof_term_old newproofold, bo)
1238     in    
1239     !maxmeta, (newterm, newty, menv)
1240   in  
1241   let res =
1242     demodulation_aux (* ~typecheck:true *) metasenv' context ugraph table 0 termty
1243   in
1244   match res with
1245   | Some t ->
1246       let newmeta, newthm = build_newtheorem t in
1247       let newt, newty, _ = newthm in
1248       if Equality.meta_convertibility termty newty then
1249         newmeta, newthm
1250       else
1251         demodulation_theorem newmeta env table newthm
1252   | None ->
1253       newmeta, theorem
1254 ;;
1255