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