]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/paramodulation/indexing.ml
All the debug_print are now lazy.
[helm.git] / helm / ocaml / paramodulation / indexing.ml
1
2 let debug_print = Utils.debug_print;;
3
4
5 type retrieval_mode = Matching | Unification;;
6
7
8 let print_candidates mode term res =
9   let _ =
10     match mode with
11     | Matching ->
12         Printf.printf "| candidates Matching %s\n" (CicPp.ppterm term)
13     | Unification ->
14         Printf.printf "| candidates Unification %s\n" (CicPp.ppterm term)
15   in
16   print_endline
17     (String.concat "\n"
18        (List.map
19           (fun (p, e) ->
20              Printf.sprintf "| (%s, %s)" (Utils.string_of_pos p)
21                (Inference.string_of_equality e))
22           res));
23   print_endline "|";
24 ;;
25
26
27 let indexing_retrieval_time = ref 0.;;
28
29
30 (* let my_apply_subst subst term = *)
31 (*   let module C = Cic in *)
32 (*   let lookup lift_amount meta = *)
33 (*     match meta with *)
34 (*     | C.Meta (i, _) -> ( *)
35 (*         try *)
36 (*           let _, (_, t, _) = List.find (fun (m, _) -> m = i) subst in *)
37 (*           (\* CicSubstitution.lift lift_amount  *\)t *)
38 (*         with Not_found -> meta *)
39 (*       ) *)
40 (*     | _ -> assert false *)
41 (*   in *)
42 (*   let rec apply_aux lift_amount =  function *)
43 (*     | C.Meta (i, l) as t -> lookup lift_amount t *)
44 (*     | C.Appl l -> C.Appl (List.map (apply_aux lift_amount) l) *)
45 (*     | C.Prod (nn, s, t) -> *)
46 (*         C.Prod (nn, apply_aux lift_amount s, apply_aux (lift_amount+1) t) *)
47 (*     | C.Lambda (nn, s, t) -> *)
48 (*         C.Lambda (nn, apply_aux lift_amount s, apply_aux (lift_amount+1) t) *)
49 (*     | t -> t *)
50 (*   in *)
51 (*   apply_aux 0 term *)
52 (* ;; *)
53
54
55 (* let apply_subst subst term = *)
56 (*   Printf.printf "| apply_subst:\n| subst: %s\n| term: %s\n" *)
57 (*     (Utils.print_subst ~prefix:" ; " subst) (CicPp.ppterm term); *)
58 (*   let res = my_apply_subst subst term in *)
59 (* (\*   let res = CicMetaSubst.apply_subst subst term in *\) *)
60 (*   Printf.printf "| res: %s\n" (CicPp.ppterm res); *)
61 (*   print_endline "|"; *)
62 (*   res *)
63 (* ;; *)
64
65 (* let apply_subst = my_apply_subst *)
66 let apply_subst = CicMetaSubst.apply_subst
67
68
69 (* Profiling code
70 let apply_subst =
71   let profile = CicUtil.profile "apply_subst" in
72   (fun s a -> profile.profile (apply_subst s) a)
73 ;;
74 *)
75
76
77 (*
78 (* NO INDEXING *)
79 let empty_table () = []
80
81 let index table equality =
82   let _, _, (_, l, r, ordering), _, _ = equality in
83   match ordering with
84   | Utils.Gt -> (Utils.Left, equality)::table
85   | Utils.Lt -> (Utils.Right, equality)::table
86   | _ -> (Utils.Left, equality)::(Utils.Right, equality)::table
87 ;;
88
89 let remove_index table equality =
90   List.filter (fun (p, e) -> e != equality) table
91 ;;
92
93 let in_index table equality =
94   List.exists (fun (p, e) -> e == equality) table
95 ;;
96
97 let get_candidates mode table term = table
98 *)
99
100
101 (*
102 (* PATH INDEXING *)
103 let empty_table () =
104   Path_indexing.PSTrie.empty
105 ;;
106
107 let index = Path_indexing.index
108 and remove_index = Path_indexing.remove_index
109 and in_index = Path_indexing.in_index;;
110   
111 let get_candidates mode trie term =
112   let t1 = Unix.gettimeofday () in
113   let res = 
114     let s = 
115       match mode with
116       | Matching -> Path_indexing.retrieve_generalizations trie term
117       | Unification -> Path_indexing.retrieve_unifiables trie term
118 (*       Path_indexing.retrieve_all trie term *)
119     in
120     Path_indexing.PosEqSet.elements s
121   in
122 (*   print_candidates mode term res; *)
123   let t2 = Unix.gettimeofday () in
124   indexing_retrieval_time := !indexing_retrieval_time +. (t2 -. t1);
125   res
126 ;;
127 *)
128
129
130 (* DISCRIMINATION TREES *)
131 let empty_table () =
132   Discrimination_tree.DiscriminationTree.empty
133 ;;
134
135 let index = Discrimination_tree.index
136 and remove_index = Discrimination_tree.remove_index
137 and in_index = Discrimination_tree.in_index;;
138
139 let get_candidates mode tree term =
140   let t1 = Unix.gettimeofday () in
141   let res =
142     let s = 
143       match mode with
144       | Matching -> Discrimination_tree.retrieve_generalizations tree term
145       | Unification -> Discrimination_tree.retrieve_unifiables tree term
146     in
147     Discrimination_tree.PosEqSet.elements s
148   in
149 (*   print_candidates mode term res; *)
150 (*   print_endline (Discrimination_tree.string_of_discrimination_tree tree); *)
151 (*   print_newline (); *)
152   let t2 = Unix.gettimeofday () in
153   indexing_retrieval_time := !indexing_retrieval_time +. (t2 -. t1);
154   res
155 ;;
156
157
158 (* let get_candidates = *)
159 (*   let profile = CicUtil.profile "Indexing.get_candidates" in *)
160 (*   (fun mode tree term -> profile.profile (get_candidates mode tree) term) *)
161 (* ;; *)
162
163
164 let match_unif_time_ok = ref 0.;;
165 let match_unif_time_no = ref 0.;;
166
167
168 let rec find_matches metasenv context ugraph lift_amount term termty =
169   let module C = Cic in
170   let module U = Utils in
171   let module S = CicSubstitution in
172   let module M = CicMetaSubst in
173   let module HL = HelmLibraryObjects in
174   let cmp = !Utils.compare_terms in
175 (*   let names = Utils.names_of_context context in *)
176 (*   let termty, ugraph = *)
177 (*     CicTypeChecker.type_of_aux' metasenv context term ugraph *)
178 (*   in *)
179   function
180     | [] -> None
181     | candidate::tl ->
182         let pos, (_, proof, (ty, left, right, o), metas, args) = candidate in
183 (*         if not (fst (CicReduction.are_convertible *)
184 (*                        ~metasenv context termty ty ugraph)) then ( *)
185 (* (\*           debug_print (lazy ( *\) *)
186 (* (\*             Printf.sprintf "CANDIDATE HAS WRONG TYPE: %s required, %s found" *\) *)
187 (* (\*               (CicPp.pp termty names) (CicPp.pp ty names))); *\) *)
188 (*           find_matches metasenv context ugraph lift_amount term termty tl *)
189 (*         ) else *)
190           let do_match c other eq_URI =
191             let subst', metasenv', ugraph' =
192               let t1 = Unix.gettimeofday () in
193               try
194                 let r =
195                   Inference.matching (metasenv @ metas) context
196                     term (S.lift lift_amount c) ugraph in
197                 let t2 = Unix.gettimeofday () in
198                 match_unif_time_ok := !match_unif_time_ok +. (t2 -. t1);
199                 r
200               with Inference.MatchingFailure as e ->
201                 let t2 = Unix.gettimeofday () in
202                 match_unif_time_no := !match_unif_time_no +. (t2 -. t1);
203                 raise e
204             in
205             Some (C.Rel (1 + lift_amount), subst', metasenv', ugraph',
206                   (candidate, eq_URI))
207           in
208           let c, other, eq_URI =
209             if pos = Utils.Left then left, right, HL.Logic.eq_ind_URI
210             else right, left, HL.Logic.eq_ind_r_URI
211           in
212           if o <> U.Incomparable then
213             try
214               do_match c other eq_URI
215             with Inference.MatchingFailure ->
216               find_matches metasenv context ugraph lift_amount term termty tl
217           else
218             let res =
219               try do_match c other eq_URI
220               with Inference.MatchingFailure -> None
221             in
222             match res with
223             | Some (_, s, _, _, _) ->
224                 let c' = (* M. *)apply_subst s c
225                 and other' = (* M. *)apply_subst s other in
226                 let order = cmp c' other' in
227                 let names = U.names_of_context context in
228                 if order = U.Gt then
229                   res
230                 else
231                   find_matches
232                     metasenv context ugraph lift_amount term termty tl
233             | None ->
234                 find_matches metasenv context ugraph lift_amount term termty tl
235 ;;
236
237
238 let rec find_all_matches ?(unif_fun=Inference.unification)
239     metasenv context ugraph lift_amount term termty =
240   let module C = Cic in
241   let module U = Utils in
242   let module S = CicSubstitution in
243   let module M = CicMetaSubst in
244   let module HL = HelmLibraryObjects in
245   let cmp = !Utils.compare_terms in
246 (*   let names = Utils.names_of_context context in *)
247 (*   let termty, ugraph = *)
248 (*     CicTypeChecker.type_of_aux' metasenv context term ugraph *)
249 (*   in *)
250   function
251     | [] -> []
252     | candidate::tl ->
253         let pos, (_, _, (ty, left, right, o), metas, args) = candidate in
254 (*         if not (fst (CicReduction.are_convertible *)
255 (*                        ~metasenv context termty ty ugraph)) then ( *)
256 (* (\*           debug_print (lazy ( *\) *)
257 (* (\*             Printf.sprintf "CANDIDATE HAS WRONG TYPE: %s required, %s found" *\) *)
258 (* (\*               (CicPp.pp termty names) (CicPp.pp ty names))); *\) *)
259 (*           find_all_matches ~unif_fun metasenv context ugraph *)
260 (*             lift_amount term termty tl *)
261 (*         ) else *)
262           let do_match c other eq_URI =
263             let subst', metasenv', ugraph' =
264               let t1 = Unix.gettimeofday () in
265               try
266                 let r = 
267                   unif_fun (metasenv @ metas) context
268                     term (S.lift lift_amount c) ugraph in
269                 let t2 = Unix.gettimeofday () in
270                 match_unif_time_ok := !match_unif_time_ok +. (t2 -. t1);
271                 r
272               with
273               | Inference.MatchingFailure
274               | CicUnification.UnificationFailure _
275               | CicUnification.Uncertain _ as e ->
276                 let t2 = Unix.gettimeofday () in
277                 match_unif_time_no := !match_unif_time_no +. (t2 -. t1);
278                 raise e
279             in
280             (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, HL.Logic.eq_ind_URI
285             else right, left, HL.Logic.eq_ind_r_URI
286           in
287           if o <> U.Incomparable then
288             try
289               let res = do_match c other eq_URI in
290               res::(find_all_matches ~unif_fun metasenv context ugraph
291                       lift_amount term termty tl)
292             with
293             | Inference.MatchingFailure
294             | CicUnification.UnificationFailure _
295             | CicUnification.Uncertain _ ->
296               find_all_matches ~unif_fun metasenv context ugraph
297                 lift_amount term termty tl
298           else
299             try
300               let res = do_match c other eq_URI in
301               match res with
302               | _, s, _, _, _ ->
303                   let c' = (* M. *)apply_subst s c
304                   and other' = (* M. *)apply_subst s other in
305                   let order = cmp c' other' in
306                   let names = U.names_of_context context in
307                   if order <> U.Lt && order <> U.Le then
308                     res::(find_all_matches ~unif_fun metasenv context ugraph
309                             lift_amount term termty tl)
310                   else
311                     find_all_matches ~unif_fun metasenv context ugraph
312                       lift_amount term termty tl
313             with
314             | Inference.MatchingFailure
315             | CicUnification.UnificationFailure _
316             | CicUnification.Uncertain _ ->
317                 find_all_matches ~unif_fun metasenv context ugraph
318                   lift_amount term termty tl
319 ;;
320
321
322 let subsumption env table target =
323   let _, (ty, left, right, _), tmetas, _ = target in
324   let metasenv, context, ugraph = env in
325   let metasenv = metasenv @ tmetas in
326   let samesubst subst subst' =
327     let tbl = Hashtbl.create (List.length subst) in
328     List.iter (fun (m, (c, t1, t2)) -> Hashtbl.add tbl m (c, t1, t2)) subst;
329     List.for_all
330       (fun (m, (c, t1, t2)) ->
331          try
332            let c', t1', t2' = Hashtbl.find tbl m in
333            if (c = c') && (t1 = t1') && (t2 = t2') then true
334            else false
335          with Not_found ->
336            true)
337       subst'
338   in
339   let leftr =
340     match left with
341     | Cic.Meta _ -> []
342     | _ ->
343         let leftc = get_candidates Matching table left in
344         find_all_matches ~unif_fun:Inference.matching
345           metasenv context ugraph 0 left ty leftc
346   in
347   let ok what (_, subst, menv, ug, ((pos, (_, _, (_, l, r, o), _, _)), _)) =
348     try
349       let other = if pos = Utils.Left then r else l in
350       let subst', menv', ug' =
351         let t1 = Unix.gettimeofday () in
352         try
353           let r = 
354             Inference.matching metasenv context what other ugraph in
355           let t2 = Unix.gettimeofday () in
356           match_unif_time_ok := !match_unif_time_ok +. (t2 -. t1);
357           r
358         with Inference.MatchingFailure as e ->
359           let t2 = Unix.gettimeofday () in
360           match_unif_time_no := !match_unif_time_no +. (t2 -. t1);
361           raise e
362       in
363       samesubst subst subst'
364     with Inference.MatchingFailure ->
365       false
366   in
367   let r = List.exists (ok right) leftr in
368   if r then
369     true
370   else
371     let rightr =
372       match right with
373       | Cic.Meta _ -> []
374       | _ ->
375           let rightc = get_candidates Matching table right in
376           find_all_matches ~unif_fun:Inference.matching
377             metasenv context ugraph 0 right ty rightc
378     in
379     List.exists (ok left) rightr
380 ;;
381
382
383 let rec demodulate_term metasenv context ugraph table lift_amount term =
384   let module C = Cic in
385   let module S = CicSubstitution in
386   let module M = CicMetaSubst in
387   let module HL = HelmLibraryObjects in
388   let candidates = get_candidates Matching table term in
389   match term with
390   | C.Meta _ -> None
391   | term ->
392       let termty, ugraph =
393         C.Implicit None, ugraph
394 (*         CicTypeChecker.type_of_aux' metasenv context term ugraph *)
395       in
396       let res =
397         find_matches metasenv context ugraph lift_amount term termty candidates
398       in
399       if res <> None then
400         res
401       else
402         match term with
403         | C.Appl l ->
404             let res, ll = 
405               List.fold_left
406                 (fun (res, tl) t ->
407                    if res <> None then
408                      (res, tl @ [S.lift 1 t])
409                    else 
410                      let r =
411                        demodulate_term metasenv context ugraph table
412                          lift_amount t
413                      in
414                      match r with
415                      | None -> (None, tl @ [S.lift 1 t])
416                      | Some (rel, _, _, _, _) -> (r, tl @ [rel]))
417                 (None, []) l
418             in (
419               match res with
420               | None -> None
421               | Some (_, subst, menv, ug, eq_found) ->
422                   Some (C.Appl ll, subst, menv, ug, eq_found)
423             )
424         | C.Prod (nn, s, t) ->
425             let r1 =
426               demodulate_term metasenv context ugraph table lift_amount s in (
427               match r1 with
428               | None ->
429                   let r2 =
430                     demodulate_term metasenv
431                       ((Some (nn, C.Decl s))::context) ugraph
432                       table (lift_amount+1) t
433                   in (
434                     match r2 with
435                     | None -> None
436                     | Some (t', subst, menv, ug, eq_found) ->
437                         Some (C.Prod (nn, (S.lift 1 s), t'),
438                               subst, menv, ug, eq_found)
439                   )
440               | Some (s', subst, menv, ug, eq_found) ->
441                   Some (C.Prod (nn, s', (S.lift 1 t)),
442                         subst, menv, ug, eq_found)
443             )
444         | t ->
445             None
446 ;;
447
448
449 let build_ens_for_sym_eq ty x y = 
450   [(UriManager.uri_of_string
451       "cic:/Coq/Init/Logic/Logic_lemmas/equality/A.var", ty);
452    (UriManager.uri_of_string
453       "cic:/Coq/Init/Logic/Logic_lemmas/equality/x.var", x);
454    (UriManager.uri_of_string
455       "cic:/Coq/Init/Logic/Logic_lemmas/equality/y.var", y)]
456 ;;
457
458
459 let build_newtarget_time = ref 0.;;
460
461
462 let demod_counter = ref 1;;
463
464 let rec demodulation newmeta env table sign target =
465   let module C = Cic in
466   let module S = CicSubstitution in
467   let module M = CicMetaSubst in
468   let module HL = HelmLibraryObjects in
469   let metasenv, context, ugraph = env in
470   let _, proof, (eq_ty, left, right, order), metas, args = target in
471   let metasenv' = metasenv @ metas in
472
473   let maxmeta = ref newmeta in
474   
475   let build_newtarget is_left (t, subst, menv, ug, (eq_found, eq_URI)) =
476     let time1 = Unix.gettimeofday () in
477     
478     let pos, (_, proof', (ty, what, other, _), menv', args') = eq_found in
479     let what, other = if pos = Utils.Left then what, other else other, what in
480     let newterm, newproof =
481       let bo = (* M. *)apply_subst subst (S.subst other t) in
482       let t' =
483         let name = C.Name ("x_Demod_" ^ (string_of_int !demod_counter)) in
484         incr demod_counter;
485         let l, r =
486           if is_left then t, S.lift 1 right else S.lift 1 left, t in
487         (name, ty, S.lift 1 eq_ty, l, r)
488       in
489       if sign = Utils.Positive then
490         (bo,
491          Inference.ProofBlock (subst, eq_URI, t', eq_found, proof))
492       else
493         let metaproof = 
494           incr maxmeta;
495           let irl =
496             CicMkImplicit.identity_relocation_list_for_metavariable context in
497           Printf.printf "\nADDING META: %d\n" !maxmeta;
498           print_newline ();
499           C.Meta (!maxmeta, irl)
500         in
501         let target' =
502           let eq_found =
503             let proof' =
504               let ens =
505                 if pos = Utils.Left then
506                   build_ens_for_sym_eq ty what other
507                 else
508                   build_ens_for_sym_eq ty other what
509               in
510               Inference.ProofSymBlock (ens, proof')
511             in
512             let what, other =
513               if pos = Utils.Left then what, other else other, what
514             in
515             pos, (0, proof', (ty, other, what, Utils.Incomparable),
516                   menv', args')
517           in
518           let target_proof =
519             let pb =
520               Inference.ProofBlock (subst, eq_URI, t', eq_found,
521                                     Inference.BasicProof metaproof)
522             in
523             match proof with
524             | Inference.BasicProof _ ->
525                 print_endline "replacing a BasicProof";
526                 pb
527             | Inference.ProofGoalBlock (_, parent_eq) ->
528                 print_endline "replacing another ProofGoalBlock";
529                 Inference.ProofGoalBlock (pb, parent_eq)
530             | _ -> assert false
531           in
532           (0, target_proof, (eq_ty, left, right, order), metas, args)
533         in
534         let refl =
535           C.Appl [C.MutConstruct (* reflexivity *)
536                     (HelmLibraryObjects.Logic.eq_URI, 0, 1, []);
537                   eq_ty; if is_left then right else left]          
538         in
539         (bo,
540          Inference.ProofGoalBlock (Inference.BasicProof refl, target'))
541     in
542     let left, right = if is_left then newterm, right else left, newterm in
543     let m = (Inference.metas_of_term left) @ (Inference.metas_of_term right) in
544     let newmetasenv = List.filter (fun (i, _, _) -> List.mem i m) metas
545     and newargs =
546       List.filter
547         (function C.Meta (i, _) -> List.mem i m | _ -> assert false)
548         args
549     in
550     let ordering = !Utils.compare_terms left right in
551
552     let time2 = Unix.gettimeofday () in
553     build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
554
555     let res =
556       let w = Utils.compute_equality_weight eq_ty left right in
557       (w, newproof, (eq_ty, left, right, ordering), newmetasenv, newargs)
558     in
559 (*     if sign = Utils.Positive then ( *)
560 (*       let newm, res = Inference.fix_metas !maxmeta res in *)
561 (*       maxmeta := newm; *)
562 (*       !maxmeta, res *)
563 (*     ) else *)
564     !maxmeta(* newmeta *), res
565   in
566   let res = demodulate_term metasenv' context ugraph table 0 left in
567 (*   let build_identity (w, p, (t, l, r, o), m, a) = *)
568 (*     match o with *)
569 (*     | Utils.Gt -> (w, p, (t, r, r, Utils.Eq), m, a) *)
570 (*     | _ -> (w, p, (t, l, l, Utils.Eq), m, a) *)
571 (*   in *)
572   match res with
573   | Some t ->
574       let newmeta, newtarget = build_newtarget true t in
575       if (Inference.is_identity (metasenv', context, ugraph) newtarget) ||
576         (Inference.meta_convertibility_eq target newtarget) then
577           newmeta, newtarget
578       else
579 (*         if subsumption env table newtarget then *)
580 (*           newmeta, build_identity newtarget *)
581 (*         else *)
582         demodulation newmeta env table sign newtarget
583   | None ->
584       let res = demodulate_term metasenv' context ugraph table 0 right in
585       match res with
586       | Some t ->
587           let newmeta, newtarget = build_newtarget false t in
588           if (Inference.is_identity (metasenv', context, ugraph) newtarget) ||
589             (Inference.meta_convertibility_eq target newtarget) then
590               newmeta, newtarget
591           else
592 (*             if subsumption env table newtarget then *)
593 (*               newmeta, build_identity newtarget *)
594 (*             else *)
595               demodulation newmeta env table sign newtarget
596       | None ->
597           newmeta, target
598 ;;
599
600
601 let rec betaexpand_term metasenv context ugraph table lift_amount term =
602   let module C = Cic in
603   let module S = CicSubstitution in
604   let module M = CicMetaSubst in
605   let module HL = HelmLibraryObjects in
606   let candidates = get_candidates Unification table term in
607   let res, lifted_term = 
608     match term with
609     | C.Meta (i, l) ->
610         let l', lifted_l = 
611           List.fold_right
612             (fun arg (res, lifted_tl) ->
613                match arg with
614                | Some arg ->
615                    let arg_res, lifted_arg =
616                      betaexpand_term metasenv context ugraph table
617                        lift_amount arg in
618                    let l1 =
619                      List.map
620                        (fun (t, s, m, ug, eq_found) ->
621                           (Some t)::lifted_tl, s, m, ug, eq_found)
622                        arg_res
623                    in
624                    (l1 @
625                       (List.map
626                          (fun (l, s, m, ug, eq_found) ->
627                             (Some lifted_arg)::l, s, m, ug, eq_found)
628                          res),
629                     (Some lifted_arg)::lifted_tl)
630                | None ->
631                    (List.map
632                       (fun (r, s, m, ug, eq_found) ->
633                          None::r, s, m, ug, eq_found) res, 
634                     None::lifted_tl)
635             ) l ([], [])
636         in
637         let e = 
638           List.map
639             (fun (l, s, m, ug, eq_found) ->
640                (C.Meta (i, l), s, m, ug, eq_found)) l'
641         in
642         e, C.Meta (i, lifted_l)
643           
644     | C.Rel m ->
645         [], if m <= lift_amount then C.Rel m else C.Rel (m+1)
646           
647     | C.Prod (nn, s, t) ->
648         let l1, lifted_s =
649           betaexpand_term metasenv context ugraph table lift_amount s in
650         let l2, lifted_t =
651           betaexpand_term metasenv ((Some (nn, C.Decl s))::context) ugraph
652             table (lift_amount+1) t in
653         let l1' =
654           List.map
655             (fun (t, s, m, ug, eq_found) ->
656                C.Prod (nn, t, lifted_t), s, m, ug, eq_found) l1
657         and l2' =
658           List.map
659             (fun (t, s, m, ug, eq_found) ->
660                C.Prod (nn, lifted_s, t), s, m, ug, eq_found) l2 in
661         l1' @ l2', C.Prod (nn, lifted_s, lifted_t)
662           
663     | C.Appl l ->
664         let l', lifted_l =
665           List.fold_right
666             (fun arg (res, lifted_tl) ->
667                let arg_res, lifted_arg =
668                  betaexpand_term metasenv context ugraph table lift_amount arg
669                in
670                let l1 =
671                  List.map
672                    (fun (a, s, m, ug, eq_found) ->
673                       a::lifted_tl, s, m, ug, eq_found)
674                    arg_res
675                in
676                (l1 @
677                   (List.map
678                      (fun (r, s, m, ug, eq_found) ->
679                         lifted_arg::r, s, m, ug, eq_found)
680                      res),
681                 lifted_arg::lifted_tl)
682             ) l ([], [])
683         in
684         (List.map
685            (fun (l, s, m, ug, eq_found) -> (C.Appl l, s, m, ug, eq_found)) l',
686          C.Appl lifted_l)
687
688     | t -> [], (S.lift lift_amount t)
689   in
690   match term with
691   | C.Meta _ -> res, lifted_term
692   | term ->
693       let termty, ugraph =
694         C.Implicit None, ugraph
695 (*         CicTypeChecker.type_of_aux' metasenv context term ugraph *)
696       in
697       let r = 
698         find_all_matches
699           metasenv context ugraph lift_amount term termty candidates
700       in
701       r @ res, lifted_term
702 ;;
703
704
705 let sup_l_counter = ref 1;;
706
707 let superposition_left newmeta (metasenv, context, ugraph) table target =
708   let module C = Cic in
709   let module S = CicSubstitution in
710   let module M = CicMetaSubst in
711   let module HL = HelmLibraryObjects in
712   let module CR = CicReduction in
713   let module U = Utils in
714   let weight, proof, (eq_ty, left, right, ordering), _, _ = target in
715   let expansions, _ =
716     let term = if ordering = U.Gt then left else right in
717     betaexpand_term metasenv context ugraph table 0 term
718   in
719   let maxmeta = ref newmeta in
720   let build_new (bo, s, m, ug, (eq_found, eq_URI)) =
721
722     print_endline "\nSUPERPOSITION LEFT\n";
723     
724     let time1 = Unix.gettimeofday () in
725     
726     let pos, (_, proof', (ty, what, other, _), menv', args') = eq_found in
727     let what, other = if pos = Utils.Left then what, other else other, what in
728     let newgoal, newproof =
729       let bo' = (* M. *)apply_subst s (S.subst other bo) in
730       let t' =
731         let name = C.Name ("x_SupL_" ^ (string_of_int !sup_l_counter)) in
732         incr sup_l_counter;
733         let l, r =
734           if ordering = U.Gt then bo, S.lift 1 right else S.lift 1 left, bo in
735         (name, ty, S.lift 1 eq_ty, l, r)
736       in
737 (*       let bo'' = *)
738 (*         C.Appl ( *)
739 (*           [C.MutInd (HL.Logic.eq_URI, 0, []); *)
740 (*            S.lift 1 eq_ty] @ *)
741 (*             if ordering = U.Gt then [S.lift 1 bo'; S.lift 1 right] *)
742 (*             else [S.lift 1 left; S.lift 1 bo']) *)
743 (*       in *)
744 (*       let t' = *)
745 (*         let name = C.Name ("x_SupL_" ^ (string_of_int !sup_l_counter)) in *)
746 (*         incr sup_l_counter; *)
747 (*         C.Lambda (name, ty, bo'') *)
748 (*       in *)
749       incr maxmeta;
750       let metaproof =
751         let irl =
752           CicMkImplicit.identity_relocation_list_for_metavariable context in
753         C.Meta (!maxmeta, irl)
754       in
755       let target' =
756         let eq_found =
757           let proof' =
758             let ens =
759               if pos = Utils.Left then
760                 build_ens_for_sym_eq ty what other
761               else
762                 build_ens_for_sym_eq ty other what
763             in
764             Inference.ProofSymBlock (ens, proof')
765           in
766           let what, other =
767             if pos = Utils.Left then what, other else other, what
768           in
769           pos, (0, proof', (ty, other, what, Utils.Incomparable), menv', args')
770         in
771         let target_proof =
772           let pb =
773             Inference.ProofBlock (s, eq_URI, t', eq_found,
774                                   Inference.BasicProof metaproof)
775           in
776           match proof with
777           | Inference.BasicProof _ ->
778               print_endline "replacing a BasicProof";
779               pb
780           | Inference.ProofGoalBlock (_, parent_eq) ->
781               print_endline "replacing another ProofGoalBlock";
782               Inference.ProofGoalBlock (pb, parent_eq)
783           | _ -> assert false
784         in
785         (weight, target_proof, (eq_ty, left, right, ordering), [], [])
786       in
787       let refl =
788         C.Appl [C.MutConstruct (* reflexivity *)
789                   (HelmLibraryObjects.Logic.eq_URI, 0, 1, []);
790                 eq_ty; if ordering = U.Gt then right else left]
791       in
792       (bo',
793        Inference.ProofGoalBlock (Inference.BasicProof refl, target'))
794     in
795     let left, right =
796       if ordering = U.Gt then newgoal, right else left, newgoal in
797     let neworder = !Utils.compare_terms left right in
798
799     let time2 = Unix.gettimeofday () in
800     build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
801
802     let res =
803       let w = Utils.compute_equality_weight eq_ty left right in
804       (w, newproof, (eq_ty, left, right, neworder), [], [])
805     in
806     res
807   in
808   !maxmeta, List.map build_new expansions
809 ;;
810
811
812 let sup_r_counter = ref 1;;
813
814 let superposition_right newmeta (metasenv, context, ugraph) table target =
815   let module C = Cic in
816   let module S = CicSubstitution in
817   let module M = CicMetaSubst in
818   let module HL = HelmLibraryObjects in
819   let module CR = CicReduction in
820   let module U = Utils in
821   let _, eqproof, (eq_ty, left, right, ordering), newmetas, args = target in
822   let metasenv' = metasenv @ newmetas in
823   let maxmeta = ref newmeta in
824   let res1, res2 =
825     match ordering with
826     | U.Gt -> fst (betaexpand_term metasenv' context ugraph table 0 left), []
827     | U.Lt -> [], fst (betaexpand_term metasenv' context ugraph table 0 right)
828     | _ ->
829         let res l r =
830           List.filter
831             (fun (_, subst, _, _, _) ->
832                let subst = (* M. *)apply_subst subst in
833                let o = !Utils.compare_terms (subst l) (subst r) in
834                o <> U.Lt && o <> U.Le)
835             (fst (betaexpand_term metasenv' context ugraph table 0 l))
836         in
837         (res left right), (res right left)
838   in
839   let build_new ordering (bo, s, m, ug, (eq_found, eq_URI)) =
840
841     let time1 = Unix.gettimeofday () in
842     
843     let pos, (_, proof', (ty, what, other, _), menv', args') = eq_found in
844     let what, other = if pos = Utils.Left then what, other else other, what in
845     let newgoal, newproof =
846       let bo' = (* M. *)apply_subst s (S.subst other bo) in
847       let t' =
848         let name = C.Name ("x_SupR_" ^ (string_of_int !sup_r_counter)) in
849         incr sup_r_counter;
850         let l, r =
851           if ordering = U.Gt then bo, S.lift 1 right else S.lift 1 left, bo in
852         (name, ty, S.lift 1 eq_ty, l, r)
853       in
854 (*       let bo'' = *)
855 (*         C.Appl ( *)
856 (*           [C.MutInd (HL.Logic.eq_URI, 0, []); S.lift 1 eq_ty] @ *)
857 (*             if ordering = U.Gt then [S.lift 1 bo'; S.lift 1 right] *)
858 (*             else [S.lift 1 left; S.lift 1 bo']) *)
859 (*       in *)
860 (*       let t' = *)
861 (*         let name = C.Name ("x_SupR_" ^ (string_of_int !sup_r_counter)) in *)
862 (*         incr sup_r_counter; *)
863 (*         C.Lambda (name, ty, bo'') *)
864 (*       in *)
865       bo',
866       Inference.ProofBlock (s, eq_URI, t', eq_found, eqproof(* target *))
867 (*       (\* M. *\)apply_subst s *)
868 (*         (C.Appl [C.Const (eq_URI, []); ty; what; t'; *)
869 (*                  eqproof; other; proof']) *)
870     in
871     let newmeta, newequality = 
872       let left, right =
873         if ordering = U.Gt then newgoal, (* M. *)apply_subst s right
874         else (* M. *)apply_subst s left, newgoal in
875       let neworder = !Utils.compare_terms left right 
876       and newmenv = newmetas @ menv'
877       and newargs = args @ args' in
878       let eq' =
879         let w = Utils.compute_equality_weight eq_ty left right in
880         (w, newproof, (eq_ty, left, right, neworder), newmenv, newargs)
881       and env = (metasenv, context, ugraph) in
882       let newm, eq' = Inference.fix_metas !maxmeta eq' in
883       newm, eq'
884     in
885     maxmeta := newmeta;
886
887     let time2 = Unix.gettimeofday () in
888     build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
889
890     newequality
891   in
892
893 (*   let build_new = *)
894 (*     let profile = CicUtil.profile "Indexing.superposition_right.build_new" in *)
895 (*     (fun o e -> profile.profile (build_new o) e) *)
896 (*   in *)
897   
898   let new1 = List.map (build_new U.Gt) res1
899   and new2 = List.map (build_new U.Lt) res2 in
900   let ok = function
901     | _, _, (_, left, right, _), _, _ ->
902         not (fst (CR.are_convertible context left right ugraph))
903   in
904   (!maxmeta,
905    (List.filter ok (new1 @ new2)))
906 ;;