1 (* Copyright (C) 2005, HELM Team.
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.
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.
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.
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,
22 * For details, see the HELM World-Wide-Web page,
23 * http://cs.unibo.it/helm/.
28 module Index = Equality_indexing.DT (* discrimination tree based indexing *)
30 module Index = Equality_indexing.DT (* path tree based indexing *)
33 let beta_expand_time = ref 0.;;
35 let debug_print = Utils.debug_print;;
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
44 CicTypeChecker.type_of_aux' metasenv' context left ugraph;
45 CicTypeChecker.type_of_aux' metasenv' context right ugraph;
48 CicUtil.Meta_not_found _ as exn ->
51 prerr_endline (CicPp.ppterm left);
52 prerr_endline (CicPp.ppterm right);
57 type retrieval_mode = Matching | Unification;;
59 let string_of_res ?env =
62 | Some (t, s, m, u, ((p,e), eq_URI)) ->
63 Printf.sprintf "Some: (%s, %s, %s)"
64 (Utils.string_of_pos p)
65 (Inference.string_of_equality ?env e)
69 let print_res ?env res =
72 (List.map (string_of_res ?env) res))
75 let print_candidates ?env mode term res =
79 prerr_endline ("| candidates Matching " ^ (CicPp.ppterm term))
81 prerr_endline ("| candidates Unification " ^ (CicPp.ppterm term))
87 Printf.sprintf "| (%s, %s)" (Utils.string_of_pos p)
88 (Inference.string_of_equality ?env e))
93 let indexing_retrieval_time = ref 0.;;
96 let apply_subst = Inference.apply_subst
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
104 let check_disjoint_invariant subst metasenv msg =
106 (fun (i,_,_) -> (List.exists (fun (j,_) -> i=j) subst)) metasenv)
109 prerr_endline ("not disjoint: " ^ msg);
114 let check_for_duplicates metas msg =
115 if List.length metas <>
116 List.length (HExtlib.list_uniq (List.sort Pervasives.compare metas)) then
118 prerr_endline ("DUPLICATI " ^ msg);
119 prerr_endline (CicMetaSubst.ppmetasenv [] metas);
124 let check_res res msg =
126 Some (t, subst, menv, ug, (eq_found, eq_URI)) ->
127 let eqs = Inference.string_of_equality (snd eq_found) in
128 check_disjoint_invariant subst menv msg;
129 check_for_duplicates menv (msg ^ "\nchecking " ^ eqs);
133 let check_target context target msg =
134 let w, proof, (eq_ty, left, right, order), metas = target in
135 (* check that metas does not contains duplicates *)
136 let eqs = Inference.string_of_equality target in
137 let _ = check_for_duplicates metas (msg ^ "\nchecking " ^ eqs) in
138 let actual = (Inference.metas_of_term left)@(Inference.metas_of_term right)
139 @(Inference.metas_of_term eq_ty)@(Inference.metas_of_proof proof) in
140 let menv = List.filter (fun (i, _, _) -> List.mem i actual) metas in
141 let _ = if menv <> metas then
143 prerr_endline ("extra metas " ^ msg);
144 prerr_endline (CicMetaSubst.ppmetasenv [] metas);
145 prerr_endline "**********************";
146 prerr_endline (CicMetaSubst.ppmetasenv [] menv);
147 prerr_endline ("left: " ^ (CicPp.ppterm left));
148 prerr_endline ("right: " ^ (CicPp.ppterm right));
149 prerr_endline ("ty: " ^ (CicPp.ppterm eq_ty));
155 ignore(CicTypeChecker.type_of_aux'
156 metas context (Inference.build_proof_term proof) CicUniv.empty_ugraph)
159 prerr_endline (Inference.string_of_proof proof);
160 prerr_endline (CicPp.ppterm (Inference.build_proof_term proof));
161 prerr_endline ("+++++++++++++left: " ^ (CicPp.ppterm left));
162 prerr_endline ("+++++++++++++right: " ^ (CicPp.ppterm right));
167 (* returns a list of all the equalities in the tree that are in relation
168 "mode" with the given term, where mode can be either Matching or
171 Format of the return value: list of tuples in the form:
172 (position - Left or Right - of the term that matched the given one in this
176 Note that if equality is "left = right", if the ordering is left > right,
177 the position will always be Left, and if the ordering is left < right,
178 position will be Right.
180 let local_max = ref 100;;
182 let make_variant (p,eq) =
183 let maxmeta, eq = Inference.fix_metas !local_max eq in
184 local_max := maxmeta;
188 let get_candidates ?env mode tree term =
189 let t1 = Unix.gettimeofday () in
193 | Matching -> Index.retrieve_generalizations tree term
194 | Unification -> Index.retrieve_unifiables tree term
196 Index.PosEqSet.elements s
198 (* print_endline (Discrimination_tree.string_of_discrimination_tree tree); *)
199 (* print_newline (); *)
200 let t2 = Unix.gettimeofday () in
201 indexing_retrieval_time := !indexing_retrieval_time +. (t2 -. t1);
202 (* make fresh instances *)
206 let profiler = HExtlib.profile "P/Indexing.get_candidates"
208 let get_candidates ?env mode tree term =
209 profiler.HExtlib.profile (get_candidates ?env mode tree) term
211 let match_unif_time_ok = ref 0.;;
212 let match_unif_time_no = ref 0.;;
216 finds the first equality in the index that matches "term", of type "termty"
217 termty can be Implicit if it is not needed. The result (one of the sides of
218 the equality, actually) should be not greater (wrt the term ordering) than
221 Format of the return value:
223 (term to substitute, [Cic.Rel 1 properly lifted - see the various
224 build_newtarget functions inside the various
225 demodulation_* functions]
226 substitution used for the matching,
228 ugraph, [substitution, metasenv and ugraph have the same meaning as those
229 returned by CicUnification.fo_unif]
230 (equality where the matching term was found, [i.e. the equality to use as
232 uri [either eq_ind_URI or eq_ind_r_URI, depending on the direction of
233 the equality: this is used to build the proof term, again see one of
234 the build_newtarget functions]
237 let rec find_matches metasenv context ugraph lift_amount term termty =
238 let module C = Cic in
239 let module U = Utils in
240 let module S = CicSubstitution in
241 let module M = CicMetaSubst in
242 let module HL = HelmLibraryObjects in
243 let cmp = !Utils.compare_terms in
244 let check = match termty with C.Implicit None -> false | _ -> true in
248 let pos, (_, proof, (ty, left, right, o), metas) = candidate in
249 if Utils.debug_metas then
250 ignore(check_target context (snd candidate) "find_matches");
251 if Utils.debug_res then
253 let c = "eq = " ^ (Inference.string_of_equality (snd candidate)) ^ "\n"in
254 let t = "t = " ^ (CicPp.ppterm term) ^ "\n" in
255 let m = "metas = " ^ (CicMetaSubst.ppmetasenv [] metas) ^ "\n" in
256 let p = "proof = " ^ (CicPp.ppterm (Inference.build_proof_term proof)) ^ "\n" in
257 check_for_duplicates metas "gia nella metas";
258 check_for_duplicates (metasenv @ metas) ("not disjoint" ^ c ^ t ^ m ^ p)
260 if check && not (fst (CicReduction.are_convertible
261 ~metasenv context termty ty ugraph)) then (
262 find_matches metasenv context ugraph lift_amount term termty tl
264 let do_match c eq_URI =
265 let subst', metasenv', ugraph' =
266 let t1 = Unix.gettimeofday () in
269 ( Inference.matching metasenv metas context
270 term (S.lift lift_amount c)) ugraph
272 let t2 = Unix.gettimeofday () in
273 match_unif_time_ok := !match_unif_time_ok +. (t2 -. t1);
276 | Inference.MatchingFailure as e ->
277 let t2 = Unix.gettimeofday () in
278 match_unif_time_no := !match_unif_time_no +. (t2 -. t1);
280 | CicUtil.Meta_not_found _ as exn -> raise exn
282 Some (C.Rel (1 + lift_amount), subst', metasenv', ugraph',
285 let c, other, eq_URI =
286 if pos = Utils.Left then left, right, Utils.eq_ind_URI ()
287 else right, left, Utils.eq_ind_r_URI ()
289 if o <> U.Incomparable then
293 with Inference.MatchingFailure ->
294 find_matches metasenv context ugraph lift_amount term termty tl
296 if Utils.debug_res then ignore (check_res res "find1");
300 try do_match c eq_URI
301 with Inference.MatchingFailure -> None
303 if Utils.debug_res then ignore (check_res res "find2");
305 | Some (_, s, _, _, _) ->
306 let c' = apply_subst s c in
308 let other' = U.guarded_simpl context (apply_subst s other) in *)
309 let other' = apply_subst s other in
310 let order = cmp c' other' in
315 metasenv context ugraph lift_amount term termty tl
317 find_matches metasenv context ugraph lift_amount term termty tl
321 as above, but finds all the matching equalities, and the matching condition
322 can be either Inference.matching or Inference.unification
324 let rec find_all_matches ?(unif_fun=Inference.unification)
325 metasenv context ugraph lift_amount term termty =
326 let module C = Cic in
327 let module U = Utils in
328 let module S = CicSubstitution in
329 let module M = CicMetaSubst in
330 let module HL = HelmLibraryObjects in
331 let cmp = !Utils.compare_terms in
335 let pos, (_, _, (ty, left, right, o), metas) = candidate in
336 let do_match c eq_URI =
337 let subst', metasenv', ugraph' =
338 let t1 = Unix.gettimeofday () in
341 unif_fun metasenv metas context
342 term (S.lift lift_amount c) ugraph in
343 let t2 = Unix.gettimeofday () in
344 match_unif_time_ok := !match_unif_time_ok +. (t2 -. t1);
347 | Inference.MatchingFailure
348 | CicUnification.UnificationFailure _
349 | CicUnification.Uncertain _ as e ->
350 let t2 = Unix.gettimeofday () in
351 match_unif_time_no := !match_unif_time_no +. (t2 -. t1);
354 (C.Rel (1 + lift_amount), subst', metasenv', ugraph',
357 let c, other, eq_URI =
358 if pos = Utils.Left then left, right, Utils.eq_ind_URI ()
359 else right, left, Utils.eq_ind_r_URI ()
361 if o <> U.Incomparable then
363 let res = do_match c eq_URI in
364 res::(find_all_matches ~unif_fun metasenv context ugraph
365 lift_amount term termty tl)
367 | Inference.MatchingFailure
368 | CicUnification.UnificationFailure _
369 | CicUnification.Uncertain _ ->
370 find_all_matches ~unif_fun metasenv context ugraph
371 lift_amount term termty tl
374 let res = do_match c eq_URI in
377 let c' = apply_subst s c
378 and other' = apply_subst s other in
379 let order = cmp c' other' in
380 if order <> U.Lt && order <> U.Le then
381 res::(find_all_matches ~unif_fun metasenv context ugraph
382 lift_amount term termty tl)
384 find_all_matches ~unif_fun metasenv context ugraph
385 lift_amount term termty tl
387 | Inference.MatchingFailure
388 | CicUnification.UnificationFailure _
389 | CicUnification.Uncertain _ ->
390 find_all_matches ~unif_fun metasenv context ugraph
391 lift_amount term termty tl
395 ?unif_fun metasenv context ugraph lift_amount term termty l
399 ?unif_fun metasenv context ugraph lift_amount term termty l
401 (*prerr_endline "CANDIDATES:";
402 List.iter (fun (_,x)->prerr_endline (Inference.string_of_equality x)) l;
403 prerr_endline ("MATCHING:" ^ CicPp.ppterm term ^ " are " ^ string_of_int
408 returns true if target is subsumed by some equality in table
410 let subsumption env table target =
413 prerr_endline (String.concat "\n" (List.map (fun (_, subst, menv, ug,
414 ((pos,equation),_)) -> Inference.string_of_equality equation)l))
417 let _, _, (ty, left, right, _), tmetas = target in
418 let metasenv, context, ugraph = env in
419 let metasenv = tmetas in
420 let merge_if_possible s1 s2 =
421 let already_in = Hashtbl.create 13 in
422 let rec aux acc = function
423 | ((i,x) as s)::tl ->
425 let x' = Hashtbl.find already_in i in
426 if x = x' then aux acc tl else None
429 Hashtbl.add already_in i x;
439 let leftc = get_candidates Matching table left in
440 find_all_matches ~unif_fun:Inference.matching
441 metasenv context ugraph 0 left ty leftc
443 (* print_res leftr;*)
444 let rec ok what = function
446 | (_, subst, menv, ug, ((pos,equation),_))::tl ->
447 let _, _, (_, l, r, o), m = equation in
449 let other = if pos = Utils.Left then r else l in
450 let subst', menv', ug' =
451 let t1 = Unix.gettimeofday () in
454 Inference.matching metasenv m context what other ugraph
456 let t2 = Unix.gettimeofday () in
457 match_unif_time_ok := !match_unif_time_ok +. (t2 -. t1);
459 with Inference.MatchingFailure as e ->
460 let t2 = Unix.gettimeofday () in
461 match_unif_time_no := !match_unif_time_no +. (t2 -. t1);
464 (match merge_if_possible subst subst' with
466 | Some s -> Some (s, equation))
467 with Inference.MatchingFailure ->
470 match ok right leftr with
471 | Some _ as res -> res
477 let rightc = get_candidates Matching table right in
478 find_all_matches ~unif_fun:Inference.matching
479 metasenv context ugraph 0 right ty rightc
481 (* print_res rightr;*)
486 (* (Printf.sprintf "SUBSUMPTION! %s\n%s\n" *)
487 (* (Inference.string_of_equality target) (Utils.print_subst s)))); *)
490 let rec demodulation_aux ?from ?(typecheck=false)
491 metasenv context ugraph table lift_amount term =
492 (* Printf.eprintf "term = %s\n" (CicPp.ppterm term); *)
493 let module C = Cic in
494 let module S = CicSubstitution in
495 let module M = CicMetaSubst in
496 let module HL = HelmLibraryObjects in
498 get_candidates ~env:(metasenv,context,ugraph) (* Unification *) Matching table term in
499 if List.exists (fun (i,_,_) -> i = 2840) metasenv
501 (prerr_endline ("term: " ^(CicPp.ppterm term));
502 List.iter (fun (_,x) -> prerr_endline (Inference.string_of_equality x))
504 prerr_endline ("-------");
505 prerr_endline ("+++++++"));
506 (* let candidates = List.map make_variant candidates in *)
513 CicTypeChecker.type_of_aux' metasenv context term ugraph
515 C.Implicit None, ugraph
518 find_matches metasenv context ugraph lift_amount term termty candidates
520 if Utils.debug_res then ignore(check_res res "demod1");
530 (res, tl @ [S.lift 1 t])
533 demodulation_aux ~from:"1" metasenv context ugraph table
537 | None -> (None, tl @ [S.lift 1 t])
538 | Some (rel, _, _, _, _) -> (r, tl @ [rel]))
543 | Some (_, subst, menv, ug, eq_found) ->
544 Some (C.Appl ll, subst, menv, ug, eq_found)
546 | C.Prod (nn, s, t) ->
548 demodulation_aux ~from:"2"
549 metasenv context ugraph table lift_amount s in (
553 demodulation_aux metasenv
554 ((Some (nn, C.Decl s))::context) ugraph
555 table (lift_amount+1) t
559 | Some (t', subst, menv, ug, eq_found) ->
560 Some (C.Prod (nn, (S.lift 1 s), t'),
561 subst, menv, ug, eq_found)
563 | Some (s', subst, menv, ug, eq_found) ->
564 Some (C.Prod (nn, s', (S.lift 1 t)),
565 subst, menv, ug, eq_found)
567 | C.Lambda (nn, s, t) ->
570 metasenv context ugraph table lift_amount s in (
574 demodulation_aux metasenv
575 ((Some (nn, C.Decl s))::context) ugraph
576 table (lift_amount+1) t
580 | Some (t', subst, menv, ug, eq_found) ->
581 Some (C.Lambda (nn, (S.lift 1 s), t'),
582 subst, menv, ug, eq_found)
584 | Some (s', subst, menv, ug, eq_found) ->
585 Some (C.Lambda (nn, s', (S.lift 1 t)),
586 subst, menv, ug, eq_found)
591 if Utils.debug_res then ignore(check_res res "demod_aux output");
596 let build_newtarget_time = ref 0.;;
599 let demod_counter = ref 1;;
603 let profiler = HExtlib.profile "P/Indexing.demod_eq[build_new_target]"
605 (** demodulation, when target is an equality *)
606 let rec demodulation_equality ?from newmeta env table sign target =
607 let module C = Cic in
608 let module S = CicSubstitution in
609 let module M = CicMetaSubst in
610 let module HL = HelmLibraryObjects in
611 let module U = Utils in
612 let metasenv, context, ugraph = env in
613 let w, proof, (eq_ty, left, right, order), metas = target in
614 (* first, we simplify *)
615 let right = U.guarded_simpl context right in
616 let left = U.guarded_simpl context left in
617 let order = !Utils.compare_terms left right in
618 let stat = (eq_ty, left, right, order) in
619 let w = Utils.compute_equality_weight stat in
620 let target = w, proof, stat, metas in
621 if Utils.debug_metas then
622 ignore(check_target context target "demod equalities input");
623 let metasenv' = (* metasenv @ *) metas in
624 let maxmeta = ref newmeta in
626 let build_newtarget is_left (t, subst, menv, ug, (eq_found, eq_URI)) =
627 let time1 = Unix.gettimeofday () in
629 if Utils.debug_metas then
631 ignore(check_for_duplicates menv "input1");
632 ignore(check_disjoint_invariant subst menv "input2");
633 let substs = Inference.ppsubst subst in
634 ignore(check_target context (snd eq_found) ("input3" ^ substs))
636 let pos, (_, proof', (ty, what, other, _), menv') = eq_found in
638 try fst (CicTypeChecker.type_of_aux' metasenv context what ugraph)
639 with CicUtil.Meta_not_found _ -> ty
641 let what, other = if pos = Utils.Left then what, other else other, what in
642 let newterm, newproof =
643 let bo = Utils.guarded_simpl context (apply_subst subst (S.subst other t)) in
644 let name = C.Name ("x_Demod" ^ (string_of_int !demod_counter)) in
647 let l, r = if is_left then t, S.lift 1 right else S.lift 1 left, t in
648 C.Appl [C.MutInd (LibraryObjects.eq_URI (), 0, []);
649 S.lift 1 eq_ty; l; r]
651 if sign = Utils.Positive then
653 Inference.ProofBlock (
654 subst, eq_URI, (name, ty), bo'(* t' *), eq_found, proof))
657 prerr_endline "***************************************negative";
661 CicMkImplicit.identity_relocation_list_for_metavariable context in
662 (* debug_print (lazy (Printf.sprintf "\nADDING META: %d\n" !maxmeta)); *)
663 (* print_newline (); *)
664 C.Meta (!maxmeta, irl)
669 if pos = Utils.Left then [ty; what; other]
670 else [ty; other; what]
672 Inference.ProofSymBlock (termlist, proof')
675 if pos = Utils.Left then what, other else other, what
677 pos, (0, proof', (ty, other, what, Utils.Incomparable),menv')
682 (subst, eq_URI, (name, ty), bo',
683 eq_found, Inference.BasicProof ([],metaproof))
686 | Inference.BasicProof _ ->
687 (* print_endline "replacing a BasicProof"; *)
689 | Inference.ProofGoalBlock (_, parent_proof) ->
690 (* print_endline "replacing another ProofGoalBlock"; *)
691 Inference.ProofGoalBlock (pb, parent_proof)
695 C.Appl [C.MutConstruct (* reflexivity *)
696 (LibraryObjects.eq_URI (), 0, 1, []);
697 eq_ty; if is_left then right else left]
700 Inference.ProofGoalBlock (Inference.BasicProof ([],refl), target_proof))
703 let newmenv = (* Inference.filter subst *) menv in
705 if Utils.debug_metas then
706 try ignore(CicTypeChecker.type_of_aux'
707 newmenv context (Inference.build_proof_term newproof) ugraph);
710 prerr_endline "sempre lui";
711 prerr_endline (Inference.ppsubst subst);
712 prerr_endline (CicPp.ppterm (Inference.build_proof_term newproof));
713 prerr_endline ("+++++++++++++termine: " ^ (CicPp.ppterm t));
714 prerr_endline ("+++++++++++++what: " ^ (CicPp.ppterm what));
715 prerr_endline ("+++++++++++++other: " ^ (CicPp.ppterm other));
716 prerr_endline ("+++++++++++++subst: " ^ (Inference.ppsubst subst));
717 prerr_endline ("+++++++++++++newmenv: " ^ (CicMetaSubst.ppmetasenv []
722 let left, right = if is_left then newterm, right else left, newterm in
723 let ordering = !Utils.compare_terms left right in
724 let stat = (eq_ty, left, right, ordering) in
725 let time2 = Unix.gettimeofday () in
726 build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
728 let w = Utils.compute_equality_weight stat in
729 (w, newproof, stat,newmenv) in
730 if Utils.debug_metas then
731 ignore(check_target context res "buildnew_target output");
734 let build_newtarget is_left x =
735 profiler.HExtlib.profile (build_newtarget is_left) x
738 let res = demodulation_aux ~from:"3" metasenv' context ugraph table 0 left in
739 if Utils.debug_res then check_res res "demod result";
740 let newmeta, newtarget =
743 let newmeta, newtarget = build_newtarget true t in
744 if (Inference.is_weak_identity (metasenv', context, ugraph) newtarget) ||
745 (Inference.meta_convertibility_eq target newtarget) then
748 demodulation_equality newmeta env table sign newtarget
750 let res = demodulation_aux metasenv' context ugraph table 0 right in
751 if Utils.debug_res then check_res res "demod result 1";
754 let newmeta, newtarget = build_newtarget false t in
755 if (Inference.is_weak_identity (metasenv', context, ugraph) newtarget) ||
756 (Inference.meta_convertibility_eq target newtarget) then
759 demodulation_equality newmeta env table sign newtarget
763 (* newmeta, newtarget *)
768 Performs the beta expansion of the term "term" w.r.t. "table",
769 i.e. returns the list of all the terms t s.t. "(t term) = t2", for some t2
772 let rec betaexpand_term metasenv context ugraph table lift_amount term =
773 let module C = Cic in
774 let module S = CicSubstitution in
775 let module M = CicMetaSubst in
776 let module HL = HelmLibraryObjects in
777 let candidates = get_candidates Unification table term in
779 let res, lifted_term =
784 (fun arg (res, lifted_tl) ->
787 let arg_res, lifted_arg =
788 betaexpand_term metasenv context ugraph table
792 (fun (t, s, m, ug, eq_found) ->
793 (Some t)::lifted_tl, s, m, ug, eq_found)
798 (fun (l, s, m, ug, eq_found) ->
799 (Some lifted_arg)::l, s, m, ug, eq_found)
801 (Some lifted_arg)::lifted_tl)
804 (fun (r, s, m, ug, eq_found) ->
805 None::r, s, m, ug, eq_found) res,
811 (fun (l, s, m, ug, eq_found) ->
812 (C.Meta (i, l), s, m, ug, eq_found)) l'
814 e, C.Meta (i, lifted_l)
817 [], if m <= lift_amount then C.Rel m else C.Rel (m+1)
819 | C.Prod (nn, s, t) ->
821 betaexpand_term metasenv context ugraph table lift_amount s in
823 betaexpand_term metasenv ((Some (nn, C.Decl s))::context) ugraph
824 table (lift_amount+1) t in
827 (fun (t, s, m, ug, eq_found) ->
828 C.Prod (nn, t, lifted_t), s, m, ug, eq_found) l1
831 (fun (t, s, m, ug, eq_found) ->
832 C.Prod (nn, lifted_s, t), s, m, ug, eq_found) l2 in
833 l1' @ l2', C.Prod (nn, lifted_s, lifted_t)
835 | C.Lambda (nn, s, t) ->
837 betaexpand_term metasenv context ugraph table lift_amount s in
839 betaexpand_term metasenv ((Some (nn, C.Decl s))::context) ugraph
840 table (lift_amount+1) t in
843 (fun (t, s, m, ug, eq_found) ->
844 C.Lambda (nn, t, lifted_t), s, m, ug, eq_found) l1
847 (fun (t, s, m, ug, eq_found) ->
848 C.Lambda (nn, lifted_s, t), s, m, ug, eq_found) l2 in
849 l1' @ l2', C.Lambda (nn, lifted_s, lifted_t)
854 (fun arg (res, lifted_tl) ->
855 let arg_res, lifted_arg =
856 betaexpand_term metasenv context ugraph table lift_amount arg
860 (fun (a, s, m, ug, eq_found) ->
861 a::lifted_tl, s, m, ug, eq_found)
866 (fun (r, s, m, ug, eq_found) ->
867 lifted_arg::r, s, m, ug, eq_found)
869 lifted_arg::lifted_tl)
873 (fun (l, s, m, ug, eq_found) -> (C.Appl l, s, m, ug, eq_found)) l',
876 | t -> [], (S.lift lift_amount t)
879 | C.Meta (i, l) -> res, lifted_term
882 C.Implicit None, ugraph
883 (* CicTypeChecker.type_of_aux' metasenv context term ugraph *)
887 metasenv context ugraph lift_amount term termty candidates
892 let profiler = HExtlib.profile "P/Indexing.betaexpand_term"
894 let betaexpand_term metasenv context ugraph table lift_amount term =
895 profiler.HExtlib.profile
896 (betaexpand_term metasenv context ugraph table lift_amount) term
899 let sup_l_counter = ref 1;;
903 returns a list of new clauses inferred with a left superposition step
904 the negative equation "target" and one of the positive equations in "table"
906 let superposition_left newmeta (metasenv, context, ugraph) table target =
907 let module C = Cic in
908 let module S = CicSubstitution in
909 let module M = CicMetaSubst in
910 let module HL = HelmLibraryObjects in
911 let module CR = CicReduction in
912 let module U = Utils in
913 let weight, proof, (eq_ty, left, right, ordering), menv = target in
914 if Utils.debug_metas then
915 ignore(check_target context target "superpositionleft");
917 let term = if ordering = U.Gt then left else right in
919 let t1 = Unix.gettimeofday () in
920 let res = betaexpand_term metasenv context ugraph table 0 term in
921 let t2 = Unix.gettimeofday () in
922 beta_expand_time := !beta_expand_time +. (t2 -. t1);
926 let maxmeta = ref newmeta in
927 let build_new (bo, s, m, ug, (eq_found, eq_URI)) =
928 (* debug_print (lazy "\nSUPERPOSITION LEFT\n"); *)
929 let time1 = Unix.gettimeofday () in
931 let pos, (_, proof', (ty, what, other, _), menv') = eq_found in
932 let what, other = if pos = Utils.Left then what, other else other, what in
933 let newgoal, newproof =
934 let bo' = U.guarded_simpl context (apply_subst s (S.subst other bo)) in
935 let name = C.Name ("x_SupL_" ^ (string_of_int !sup_l_counter)) in
939 if ordering = U.Gt then bo, S.lift 1 right else S.lift 1 left, bo in
940 C.Appl [C.MutInd (LibraryObjects.eq_URI (), 0, []);
941 S.lift 1 eq_ty; l; r]
946 CicMkImplicit.identity_relocation_list_for_metavariable context in
947 C.Meta (!maxmeta, irl)
952 if pos = Utils.Left then [ty; what; other]
953 else [ty; other; what]
955 Inference.ProofSymBlock (termlist, proof')
958 if pos = Utils.Left then what, other else other, what
960 pos, (0, proof', (ty, other, what, Utils.Incomparable), menv')
964 Inference.ProofBlock (s, eq_URI, (name, ty), bo'', eq_found,
965 Inference.BasicProof ([],metaproof))
968 | Inference.BasicProof _ ->
969 (* debug_print (lazy "replacing a BasicProof"); *)
971 | Inference.ProofGoalBlock (_, parent_proof) ->
972 (* debug_print (lazy "replacing another ProofGoalBlock"); *)
973 Inference.ProofGoalBlock (pb, parent_proof)
977 C.Appl [C.MutConstruct (* reflexivity *)
978 (LibraryObjects.eq_URI (), 0, 1, []);
979 eq_ty; if ordering = U.Gt then right else left]
982 Inference.ProofGoalBlock (Inference.BasicProof ([],refl), target_proof))
985 if ordering = U.Gt then newgoal, right else left, newgoal in
986 let neworder = !Utils.compare_terms left right in
987 let stat = (eq_ty, left, right, neworder) in
988 let newmenv = (* Inference.filter s *) menv in
989 let time2 = Unix.gettimeofday () in
990 build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
992 let w = Utils.compute_equality_weight stat in
993 (w, newproof, stat, newmenv)
996 !maxmeta, List.map build_new expansions
1000 let sup_r_counter = ref 1;;
1004 returns a list of new clauses inferred with a right superposition step
1005 between the positive equation "target" and one in the "table" "newmeta" is
1006 the first free meta index, i.e. the first number above the highest meta
1007 index: its updated value is also returned
1009 let superposition_right newmeta (metasenv, context, ugraph) table target =
1010 let module C = Cic in
1011 let module S = CicSubstitution in
1012 let module M = CicMetaSubst in
1013 let module HL = HelmLibraryObjects in
1014 let module CR = CicReduction in
1015 let module U = Utils in
1016 let w, eqproof, (eq_ty, left, right, ordering), newmetas = target in
1017 if Utils.debug_metas then
1018 ignore (check_target context target "superpositionright");
1019 let metasenv' = newmetas in
1020 let maxmeta = ref newmeta in
1022 let betaexpand_term metasenv context ugraph table d term =
1023 let t1 = Unix.gettimeofday () in
1024 let res = betaexpand_term metasenv context ugraph table d term in
1025 let t2 = Unix.gettimeofday () in
1026 beta_expand_time := !beta_expand_time +. (t2 -. t1);
1030 | U.Gt -> fst (betaexpand_term metasenv' context ugraph table 0 left), []
1031 | U.Lt -> [], fst (betaexpand_term metasenv' context ugraph table 0 right)
1035 (fun (_, subst, _, _, _) ->
1036 let subst = apply_subst subst in
1037 let o = !Utils.compare_terms (subst l) (subst r) in
1038 o <> U.Lt && o <> U.Le)
1039 (fst (betaexpand_term metasenv' context ugraph table 0 l))
1041 (res left right), (res right left)
1043 let build_new ordering (bo, s, m, ug, (eq_found, eq_URI)) =
1044 if Utils.debug_metas then
1045 ignore (check_target context (snd eq_found) "buildnew1" );
1046 let time1 = Unix.gettimeofday () in
1048 let pos, (_, proof', (ty, what, other, _), menv') = eq_found in
1049 let what, other = if pos = Utils.Left then what, other else other, what in
1050 let newgoal, newproof =
1052 let bo' = Utils.guarded_simpl context (apply_subst s (S.subst other bo)) in
1053 let name = C.Name ("x_SupR_" ^ (string_of_int !sup_r_counter)) in
1057 if ordering = U.Gt then bo, S.lift 1 right else S.lift 1 left, bo in
1058 C.Appl [C.MutInd (LibraryObjects.eq_URI (), 0, []);
1059 S.lift 1 eq_ty; l; r]
1062 Inference.ProofBlock (s, eq_URI, (name, ty), bo'', eq_found, eqproof)
1064 let newmeta, newequality =
1066 if ordering = U.Gt then newgoal, apply_subst s right
1067 else apply_subst s left, newgoal in
1068 let neworder = !Utils.compare_terms left right in
1069 let newmenv = (* Inference.filter s *) m in
1070 let stat = (eq_ty, left, right, neworder) in
1072 let w = Utils.compute_equality_weight stat in
1073 (w, newproof, stat, newmenv) in
1074 if Utils.debug_metas then
1075 ignore (check_target context eq' "buildnew3");
1076 let newm, eq' = Inference.fix_metas !maxmeta eq' in
1077 if Utils.debug_metas then
1078 ignore (check_target context eq' "buildnew4");
1082 let time2 = Unix.gettimeofday () in
1083 build_newtarget_time := !build_newtarget_time +. (time2 -. time1);
1084 if Utils.debug_metas then
1085 ignore(check_target context newequality "buildnew2");
1088 let new1 = List.map (build_new U.Gt) res1
1089 and new2 = List.map (build_new U.Lt) res2 in
1090 let ok e = not (Inference.is_identity (metasenv', context, ugraph) e) in
1092 (List.filter ok (new1 @ new2)))
1096 (** demodulation, when the target is a goal *)
1097 let rec demodulation_goal newmeta env table goal =
1098 let module C = Cic in
1099 let module S = CicSubstitution in
1100 let module M = CicMetaSubst in
1101 let module HL = HelmLibraryObjects in
1102 let metasenv, context, ugraph = env in
1103 let maxmeta = ref newmeta in
1104 let proof, metas, term = goal in
1105 let term = Utils.guarded_simpl (~debug:true) context term in
1106 let goal = proof, metas, term in
1107 let metasenv' = metas in
1109 let build_newgoal (t, subst, menv, ug, (eq_found, eq_URI)) =
1110 let pos, (_, proof', (ty, what, other, _), menv') = eq_found in
1111 let what, other = if pos = Utils.Left then what, other else other, what in
1113 try fst (CicTypeChecker.type_of_aux' metasenv context what ugraph)
1114 with CicUtil.Meta_not_found _ -> ty
1116 let newterm, newproof =
1117 let bo = Utils.guarded_simpl context (apply_subst subst (S.subst other t)) in
1118 let bo' = apply_subst subst t in
1119 let name = C.Name ("x_DemodGoal_" ^ (string_of_int !demod_counter)) in
1124 CicMkImplicit.identity_relocation_list_for_metavariable context in
1125 (* debug_print (lazy (Printf.sprintf "\nADDING META: %d\n" !maxmeta)); *)
1126 C.Meta (!maxmeta, irl)
1131 if pos = Utils.Left then [ty; what; other]
1132 else [ty; other; what]
1134 Inference.ProofSymBlock (termlist, proof')
1137 if pos = Utils.Left then what, other else other, what
1139 pos, (0, proof', (ty, other, what, Utils.Incomparable), menv')
1143 Inference.ProofBlock (subst, eq_URI, (name, ty), bo',
1144 eq_found, Inference.BasicProof ([],metaproof))
1146 let rec repl = function
1147 | Inference.NoProof ->
1148 (* debug_print (lazy "replacing a NoProof"); *)
1150 | Inference.BasicProof _ ->
1151 (* debug_print (lazy "replacing a BasicProof"); *)
1153 | Inference.ProofGoalBlock (_, parent_proof) ->
1154 (* debug_print (lazy "replacing another ProofGoalBlock"); *)
1155 Inference.ProofGoalBlock (pb, parent_proof)
1156 | Inference.SubProof (term, meta_index, p) ->
1157 prerr_endline "subproof!";
1158 Inference.SubProof (term, meta_index, repl p)
1162 bo, Inference.ProofGoalBlock (Inference.NoProof, goal_proof)
1164 let newmetasenv = (* Inference.filter subst *) menv in
1165 !maxmeta, (newproof, newmetasenv, newterm)
1168 demodulation_aux (* ~typecheck:true *) metasenv' context ugraph table 0 term
1172 let newmeta, newgoal = build_newgoal t in
1173 let _, _, newg = newgoal in
1174 if Inference.meta_convertibility term newg then
1177 demodulation_goal newmeta env table newgoal
1182 (** demodulation, when the target is a theorem *)
1183 let rec demodulation_theorem newmeta env table theorem =
1184 let module C = Cic in
1185 let module S = CicSubstitution in
1186 let module M = CicMetaSubst in
1187 let module HL = HelmLibraryObjects in
1188 let metasenv, context, ugraph = env in
1189 let maxmeta = ref newmeta in
1190 let term, termty, metas = theorem in
1191 let metasenv' = metas in
1193 let build_newtheorem (t, subst, menv, ug, (eq_found, eq_URI)) =
1194 let pos, (_, proof', (ty, what, other, _), menv') = eq_found in
1195 let what, other = if pos = Utils.Left then what, other else other, what in
1196 let newterm, newty =
1197 let bo = Utils.guarded_simpl context (apply_subst subst (S.subst other t)) in
1198 let bo' = apply_subst subst t in
1199 let name = C.Name ("x_DemodThm_" ^ (string_of_int !demod_counter)) in
1202 Inference.ProofBlock (subst, eq_URI, (name, ty), bo', eq_found,
1203 Inference.BasicProof ([],term))
1205 (Inference.build_proof_term newproof, bo)
1207 !maxmeta, (newterm, newty, menv)
1210 demodulation_aux (* ~typecheck:true *) metasenv' context ugraph table 0 termty
1214 let newmeta, newthm = build_newtheorem t in
1215 let newt, newty, _ = newthm in
1216 if Inference.meta_convertibility termty newty then
1219 demodulation_theorem newmeta env table newthm