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/.
26 (* let _profiler = <:profiler<_profiler>>;; *)
30 module Index = Equality_indexing.DT (* discrimination tree based indexing *)
32 module Index = Equality_indexing.DT (* path tree based indexing *)
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)) ->
63 Printf.sprintf "Some: (%s, %s, %s)"
64 (Utils.string_of_pos p)
65 (Equality.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 (Equality.string_of_equality ?env e))
93 let apply_subst = Subst.apply_subst
95 let index = Index.index
96 let remove_index = Index.remove_index
97 let in_index = Index.in_index
98 let empty = Index.empty
99 let init_index = Index.init_index
101 let check_disjoint_invariant subst metasenv msg =
103 (fun (i,_,_) -> (Subst.is_in_subst i subst)) metasenv)
106 prerr_endline ("not disjoint: " ^ msg);
111 let check_for_duplicates metas msg =
112 let rec aux = function
114 | (m,_,_)::tl -> not (List.exists (fun (i, _, _) -> i = m) tl) && aux tl in
118 prerr_endline ("DUPLICATI " ^ msg);
119 prerr_endline (CicMetaSubst.ppmetasenv [] metas);
125 let check_metasenv msg menv =
128 try ignore(CicTypeChecker.type_of_aux' menv ctx ty
129 CicUniv.empty_ugraph)
131 | CicUtil.Meta_not_found _ ->
132 prerr_endline (msg ^ CicMetaSubst.ppmetasenv [] menv);
138 (* the metasenv returned by res must included in the original one,
139 due to matching. If it fails, it is probably because we are not
140 demodulating with a unit equality *)
142 let not_unit_eq ctx eq =
143 let (_,_,(ty,left,right,o),metas,_) = Equality.open_equality eq in
148 let s,_ = CicTypeChecker.type_of_aux' metas ctx ty CicUniv.empty_ugraph
149 in s = Cic.Sort(Cic.Prop)
151 prerr_endline ("ERROR typing " ^ CicPp.ppterm ty); assert false) metas
154 if b then prerr_endline ("not a unit equality: " ^ Equality.string_of_equality eq); b *)
157 let check_demod_res res metasenv msg =
159 | Some (_, _, menv, _, _) ->
163 (List.exists (fun (j,_,_) -> i=j) metasenv)) menv
167 prerr_endline ("extended context " ^ msg);
168 prerr_endline (CicMetaSubst.ppmetasenv [] menv);
174 let check_res res msg =
176 | Some (t, subst, menv, ug, eq_found) ->
177 let eqs = Equality.string_of_equality (snd eq_found) in
178 check_metasenv msg menv;
179 check_disjoint_invariant subst menv msg;
180 check_for_duplicates menv (msg ^ "\nchecking " ^ eqs);
184 let check_target bag context target msg =
185 let w, proof, (eq_ty, left, right, order), metas,_ =
186 Equality.open_equality target in
187 (* check that metas does not contains duplicates *)
188 let eqs = Equality.string_of_equality target in
189 let _ = check_for_duplicates metas (msg ^ "\nchecking " ^ eqs) in
190 let actual = (Utils.metas_of_term left)@(Utils.metas_of_term right)
191 @(Utils.metas_of_term eq_ty)@(Equality.metas_of_proof bag proof) in
192 let menv = List.filter (fun (i, _, _) -> List.mem i actual) metas in
193 let _ = if menv <> metas then
195 prerr_endline ("extra metas " ^ msg);
196 prerr_endline (CicMetaSubst.ppmetasenv [] metas);
197 prerr_endline "**********************";
198 prerr_endline (CicMetaSubst.ppmetasenv [] menv);
199 prerr_endline ("left: " ^ (CicPp.ppterm left));
200 prerr_endline ("right: " ^ (CicPp.ppterm right));
201 prerr_endline ("ty: " ^ (CicPp.ppterm eq_ty));
207 ignore(CicTypeChecker.type_of_aux'
208 metas context (Founif.build_proof_term proof) CicUniv.empty_ugraph)
211 prerr_endline (Founif.string_of_proof proof);
212 prerr_endline (CicPp.ppterm (Founif.build_proof_term proof));
213 prerr_endline ("+++++++++++++left: " ^ (CicPp.ppterm left));
214 prerr_endline ("+++++++++++++right: " ^ (CicPp.ppterm right));
219 (* returns a list of all the equalities in the tree that are in relation
220 "mode" with the given term, where mode can be either Matching or
223 Format of the return value: list of tuples in the form:
224 (position - Left or Right - of the term that matched the given one in this
228 Note that if equality is "left = right", if the ordering is left > right,
229 the position will always be Left, and if the ordering is left < right,
230 position will be Right.
233 let get_candidates ?env mode tree term =
237 Index.retrieve_generalizations tree term
239 Index.retrieve_unifiables tree term
242 Index.PosEqSet.elements s
246 finds the first equality in the index that matches "term", of type "termty"
247 termty can be Implicit if it is not needed. The result (one of the sides of
248 the equality, actually) should be not greater (wrt the term ordering) than
251 Format of the return value:
253 (term to substitute, [Cic.Rel 1 properly lifted - see the various
254 build_newtarget functions inside the various
255 demodulation_* functions]
256 substitution used for the matching,
258 ugraph, [substitution, metasenv and ugraph have the same meaning as those
259 returned by CicUnification.fo_unif]
260 (equality where the matching term was found, [i.e. the equality to use as
262 uri [either eq_ind_URI or eq_ind_r_URI, depending on the direction of
263 the equality: this is used to build the proof term, again see one of
264 the build_newtarget functions]
267 let rec find_matches bag metasenv context ugraph lift_amount term termty =
268 let module C = Cic in
269 let module U = Utils in
270 let module S = CicSubstitution in
271 let module M = CicMetaSubst in
272 let module HL = HelmLibraryObjects in
273 let cmp = !Utils.compare_terms in
274 let check = match termty with C.Implicit None -> false | _ -> true in
278 let pos, equality = candidate in
279 (* if not_unit_eq context equality then
281 prerr_endline "not a unit";
282 prerr_endline (Equality.string_of_equality equality)
284 let (_, proof, (ty, left, right, o), metas,_) =
285 Equality.open_equality equality
287 if Utils.debug_metas then
288 ignore(check_target bag context (snd candidate) "find_matches");
289 if Utils.debug_res then
291 let c="eq = "^(Equality.string_of_equality (snd candidate)) ^ "\n"in
292 let t="t = " ^ (CicPp.ppterm term) ^ "\n" in
293 let m="metas = " ^ (CicMetaSubst.ppmetasenv [] metas) ^ "\n" in
294 let ms="metasenv =" ^ (CicMetaSubst.ppmetasenv [] metasenv) ^ "\n" in
296 match LibraryObjects.eq_URI () with
298 | None -> raise (ProofEngineTypes.Fail (lazy "equality not declared")) in
300 (CicPp.ppterm(Equality.build_proof_term bag eq_uri [] 0 proof))^"\n"
303 check_for_duplicates metas "gia nella metas";
304 check_for_duplicates metasenv "gia nel metasenv";
305 check_for_duplicates (metasenv@metas) ("not disjoint"^c^t^m^ms^p)
307 if check && not (fst (CicReduction.are_convertible
308 ~metasenv context termty ty ugraph)) then (
309 find_matches bag metasenv context ugraph lift_amount term termty tl
312 let subst', metasenv', ugraph' =
314 metasenv metas context term (S.lift lift_amount c) ugraph
316 check_metasenv "founif :" metasenv';
317 Some (Cic.Rel(1+lift_amount),subst',metasenv',ugraph',candidate)
320 if pos = Utils.Left then left, right
323 if o <> U.Incomparable then
327 with Founif.MatchingFailure ->
328 find_matches bag metasenv context ugraph lift_amount term termty tl
330 if Utils.debug_res then ignore (check_res res "find1");
335 with Founif.MatchingFailure -> None
337 if Utils.debug_res then ignore (check_res res "find2");
339 | Some (_, s, _, _, _) ->
340 let c' = apply_subst s c in
342 let other' = U.guarded_simpl context (apply_subst s other) in *)
343 let other' = apply_subst s other in
344 let order = cmp c' other' in
349 metasenv context ugraph lift_amount term termty tl
351 find_matches bag metasenv context ugraph lift_amount term termty tl
354 let find_matches metasenv context ugraph lift_amount term termty =
355 find_matches metasenv context ugraph lift_amount term termty
359 as above, but finds all the matching equalities, and the matching condition
360 can be either Founif.matching or Inference.unification
362 (* XXX termty unused *)
363 let rec find_all_matches ?(unif_fun=Founif.unification)
364 metasenv context ugraph lift_amount term termty =
365 let module C = Cic in
366 let module U = Utils in
367 let module S = CicSubstitution in
368 let module M = CicMetaSubst in
369 let module HL = HelmLibraryObjects in
370 let cmp = !Utils.compare_terms in
371 let check = match termty with C.Implicit None -> false | _ -> true in
375 let pos, equality = candidate in
376 let (_,_,(ty,left,right,o),metas,_)= Equality.open_equality equality in
377 if check && not (fst (CicReduction.are_convertible
378 ~metasenv context termty ty ugraph)) then (
379 find_all_matches metasenv context ugraph lift_amount term termty tl
382 let subst', metasenv', ugraph' =
383 unif_fun metasenv metas context term (S.lift lift_amount c) ugraph
385 (C.Rel (1+lift_amount),subst',metasenv',ugraph',candidate)
389 if pos = Utils.Left then left, right
392 if o <> U.Incomparable then
394 let res = do_match c in
395 res::(find_all_matches ~unif_fun metasenv context ugraph
396 lift_amount term termty tl)
398 | Founif.MatchingFailure
399 | CicUnification.UnificationFailure _
400 | CicUnification.Uncertain _ ->
401 find_all_matches ~unif_fun metasenv context ugraph
402 lift_amount term termty tl
405 let res = do_match c in
408 let c' = apply_subst s c
409 and other' = apply_subst s other in
410 let order = cmp c' other' in
411 if order <> U.Lt && order <> U.Le then
412 res::(find_all_matches ~unif_fun metasenv context ugraph
413 lift_amount term termty tl)
415 find_all_matches ~unif_fun metasenv context ugraph
416 lift_amount term termty tl
418 | Founif.MatchingFailure
419 | CicUnification.UnificationFailure _
420 | CicUnification.Uncertain _ ->
421 find_all_matches ~unif_fun metasenv context ugraph
422 lift_amount term termty tl
426 ?unif_fun metasenv context ugraph lift_amount term termty l
429 ?unif_fun metasenv context ugraph lift_amount term termty l
430 (*prerr_endline "CANDIDATES:";
431 List.iter (fun (_,x)->prerr_endline (Founif.string_of_equality x)) l;
432 prerr_endline ("MATCHING:" ^ CicPp.ppterm term ^ " are " ^ string_of_int
436 returns true if target is subsumed by some equality in table
440 prerr_endline (String.concat "\n" (List.map (fun (_, subst, menv, ug,
441 ((pos,equation),_)) -> Equality.string_of_equality equation)l))
445 let subsumption_aux use_unification env table target =
446 let _, _, (ty, left, right, _), tmetas, _ = Equality.open_equality target in
447 let _, context, ugraph = env in
448 let metasenv = tmetas in
449 let predicate, unif_fun =
450 if use_unification then
451 Unification, Founif.unification
453 Matching, Founif.matching
457 | Cic.Meta _ when not use_unification -> []
459 let leftc = get_candidates predicate table left in
460 find_all_matches ~unif_fun
461 metasenv context ugraph 0 left ty leftc
463 let rec ok what leftorright = function
465 | (_, subst, menv, ug, (pos,equation))::tl ->
466 let _, _, (_, l, r, o), m,_ = Equality.open_equality equation in
468 let other = if pos = Utils.Left then r else l in
469 let what' = Subst.apply_subst subst what in
470 let other' = Subst.apply_subst subst other in
471 let subst', menv', ug' =
472 unif_fun metasenv m context what' other' ugraph
474 (match Subst.merge_subst_if_possible subst subst' with
475 | None -> ok what leftorright tl
476 | Some s -> Some (s, equation, leftorright <> pos ))
478 | Founif.MatchingFailure
479 | CicUnification.UnificationFailure _ -> ok what leftorright tl
481 match ok right Utils.Left leftr with
482 | Some _ as res -> res
486 | Cic.Meta _ when not use_unification -> []
488 let rightc = get_candidates predicate table right in
489 find_all_matches ~unif_fun
490 metasenv context ugraph 0 right ty rightc
492 ok left Utils.Right rightr
495 let subsumption x y z =
496 subsumption_aux false x y z
499 let unification x y z =
500 subsumption_aux true x y z
503 (* the target must be disjoint from the equations in the table *)
504 let subsumption_aux_all use_unification env table target =
505 let _, _, (ty, left, right, _), tmetas, _ = Equality.open_equality target in
506 let _, context, ugraph = env in
507 let metasenv = tmetas in
508 check_for_duplicates metasenv "subsumption_aux_all";
509 let predicate, unif_fun =
510 if use_unification then
511 Unification, Founif.unification
513 Matching, Founif.matching
517 | Cic.Meta _ (*when not use_unification*) -> []
519 let leftc = get_candidates predicate table left in
520 find_all_matches ~unif_fun
521 metasenv context ugraph 0 left ty leftc
525 | Cic.Meta _ (*when not use_unification*) -> []
527 let rightc = get_candidates predicate table right in
528 find_all_matches ~unif_fun
529 metasenv context ugraph 0 right ty rightc
531 let rec ok_all what leftorright = function
533 | (_, subst, menv, ug, (pos,equation))::tl ->
534 let _, _, (_, l, r, o), m,_ = Equality.open_equality equation in
536 let other = if pos = Utils.Left then r else l in
537 let what' = Subst.apply_subst subst what in
538 let other' = Subst.apply_subst subst other in
539 let subst', menv', ug' =
540 unif_fun metasenv m context what' other' ugraph
542 (match Subst.merge_subst_if_possible subst subst' with
543 | None -> ok_all what leftorright tl
545 (s, equation, leftorright <> pos )::(ok_all what leftorright tl))
547 | Founif.MatchingFailure
548 | CicUnification.UnificationFailure _ -> (ok_all what leftorright tl)
550 (ok_all right Utils.Left leftr)@(ok_all left Utils.Right rightr )
553 let subsumption_all x y z =
554 subsumption_aux_all false x y z
557 let unification_all x y z =
558 subsumption_aux_all true x y z
561 let rec demodulation_aux bag ?from ?(typecheck=false)
562 metasenv context ugraph table lift_amount term =
563 let module C = Cic in
564 let module S = CicSubstitution in
565 let module M = CicMetaSubst in
566 let module HL = HelmLibraryObjects in
567 (* prerr_endline ("demodulating " ^ CicPp.ppterm term); *)
568 check_for_duplicates metasenv "in input a demodulation aux";
571 ~env:(metasenv,context,ugraph) (* Unification *) Matching table term
572 in let candidates = List.filter (fun _,x -> not (not_unit_eq context x)) candidates
582 CicTypeChecker.type_of_aux' metasenv context term ugraph
584 C.Implicit None, ugraph
586 find_matches bag metasenv context ugraph
587 lift_amount term termty candidates
589 prerr_endline "type checking error";
590 prerr_endline ("menv :\n" ^ CicMetaSubst.ppmetasenv [] metasenv);
591 prerr_endline ("term: " ^ (CicPp.ppterm term));
596 (if Utils.debug_res then
597 ignore(check_res res "demod1");
598 if check_demod_res res metasenv "demod" then res else None) in
608 (res, tl @ [S.lift 1 t])
611 demodulation_aux bag ~from:"1" metasenv context ugraph table ~typecheck
615 | None -> (None, tl @ [S.lift 1 t])
616 | Some (rel, _, _, _, _) -> (r, tl @ [rel]))
621 | Some (_, subst, menv, ug, eq_found) ->
622 Some (C.Appl ll, subst, menv, ug, eq_found)
625 | C.Prod (nn, s, t) ->
627 demodulation_aux bag ~from:"2"
628 metasenv context ugraph table lift_amount s in (
632 demodulation_aux bag metasenv
633 ((Some (nn, C.Decl s))::context) ugraph
634 table (lift_amount+1) t
638 | Some (t', subst, menv, ug, eq_found) ->
639 Some (C.Prod (nn, (S.lift 1 s), t'),
640 subst, menv, ug, eq_found)
642 | Some (s', subst, menv, ug, eq_found) ->
643 Some (C.Prod (nn, s', (S.lift 1 t)),
644 subst, menv, ug, eq_found)
646 | C.Lambda (nn, s, t) ->
647 prerr_endline "siam qui";
650 metasenv context ugraph table lift_amount s in (
654 demodulation_aux bag metasenv
655 ((Some (nn, C.Decl s))::context) ugraph
656 table (lift_amount+1) t
660 | Some (t', subst, menv, ug, eq_found) ->
661 Some (C.Lambda (nn, (S.lift 1 s), t'),
662 subst, menv, ug, eq_found)
664 | Some (s', subst, menv, ug, eq_found) ->
665 Some (C.Lambda (nn, s', (S.lift 1 t)),
666 subst, menv, ug, eq_found)
672 if Utils.debug_res then ignore(check_res res "demod_aux output");
678 (** demodulation, when target is an equality *)
679 let rec demodulation_equality bag ?from eq_uri newmeta env table target =
681 prerr_endline ("demodulation_eq:\n");
682 Index.iter table (fun l ->
683 let l = Index.PosEqSet.elements l in
685 List.map (fun (p,e) ->
686 Utils.string_of_pos p ^ Equality.string_of_equality e) l in
687 prerr_endline (String.concat "\n" l)
690 let module C = Cic in
691 let module S = CicSubstitution in
692 let module M = CicMetaSubst in
693 let module HL = HelmLibraryObjects in
694 let module U = Utils in
695 let metasenv, context, ugraph = env in
696 let w, proof, (eq_ty, left, right, order), metas, id =
697 Equality.open_equality target
699 (* first, we simplify *)
700 (* let right = U.guarded_simpl context right in *)
701 (* let left = U.guarded_simpl context left in *)
702 (* let order = !Utils.compare_terms left right in *)
703 (* let stat = (eq_ty, left, right, order) in *)
704 (* let w = Utils.compute_equality_weight stat in*)
705 (* let target = Equality.mk_equality (w, proof, stat, metas) in *)
706 if Utils.debug_metas then
707 ignore(check_target bag context target "demod equalities input");
708 let metasenv' = (* metasenv @ *) metas in
709 let maxmeta = ref newmeta in
711 let build_newtarget is_left (t, subst, menv, ug, eq_found) =
713 if Utils.debug_metas then
715 ignore(check_for_duplicates menv "input1");
716 ignore(check_disjoint_invariant subst menv "input2");
717 let substs = Subst.ppsubst subst in
718 ignore(check_target bag context (snd eq_found) ("input3" ^ substs))
720 let pos, equality = eq_found in
722 (ty, what, other, _), menv',id') = Equality.open_equality equality in
724 try fst (CicTypeChecker.type_of_aux' metasenv context what ugraph)
725 with CicUtil.Meta_not_found _ -> ty
727 let ty, eq_ty = apply_subst subst ty, apply_subst subst eq_ty in
728 let what, other = if pos = Utils.Left then what, other else other, what in
729 let newterm, newproof =
731 Utils.guarded_simpl context (apply_subst subst (S.subst other t)) in
732 (* let name = C.Name ("x_Demod" ^ (string_of_int !demod_counter)) in*)
733 let name = C.Name "x" in
735 let l, r = if is_left then t, S.lift 1 right else S.lift 1 left, t in
736 C.Appl [C.MutInd (eq_uri, 0, []); S.lift 1 eq_ty; l; r]
738 (bo, (Equality.Step (subst,(Equality.Demodulation, id,(pos,id'),
739 (Cic.Lambda (name, ty, bo'))))))
741 let newmenv = menv in
742 let left, right = if is_left then newterm, right else left, newterm in
743 let ordering = !Utils.compare_terms left right in
744 let stat = (eq_ty, left, right, ordering) in
746 let w = Utils.compute_equality_weight stat in
747 (Equality.mk_equality bag (w, newproof, stat,newmenv))
749 if Utils.debug_metas then
750 ignore(check_target bag context res "buildnew_target output");
755 demodulation_aux bag ~from:"3" metasenv' context ugraph table 0 left
757 if Utils.debug_res then check_res res "demod result";
758 let newmeta, newtarget =
761 let newmeta, newtarget = build_newtarget true t in
762 (* assert (not (Equality.meta_convertibility_eq target newtarget)); *)
763 if (Equality.is_weak_identity newtarget) (* || *)
764 (*Equality.meta_convertibility_eq target newtarget*) then
767 demodulation_equality bag ?from eq_uri newmeta env table newtarget
769 let res = demodulation_aux bag metasenv' context ugraph table 0 right in
770 if Utils.debug_res then check_res res "demod result 1";
773 let newmeta, newtarget = build_newtarget false t in
774 if (Equality.is_weak_identity newtarget) ||
775 (Equality.meta_convertibility_eq target newtarget) then
778 demodulation_equality bag ?from eq_uri newmeta env table newtarget
782 (* newmeta, newtarget *)
787 Performs the beta expansion of the term "term" w.r.t. "table",
788 i.e. returns the list of all the terms t s.t. "(t term) = t2", for some t2
791 let rec betaexpand_term
792 ?(subterms_only=false) metasenv context ugraph table lift_amount term
794 let module C = Cic in
795 let module S = CicSubstitution in
796 let module M = CicMetaSubst in
797 let module HL = HelmLibraryObjects in
799 let res, lifted_term =
805 (fun arg (res, lifted_tl) ->
808 let arg_res, lifted_arg =
809 betaexpand_term metasenv context ugraph table
813 (fun (t, s, m, ug, eq_found) ->
814 (Some t)::lifted_tl, s, m, ug, eq_found)
819 (fun (l, s, m, ug, eq_found) ->
820 (Some lifted_arg)::l, s, m, ug, eq_found)
822 (Some lifted_arg)::lifted_tl)
825 (fun (r, s, m, ug, eq_found) ->
826 None::r, s, m, ug, eq_found) res,
832 (fun (l, s, m, ug, eq_found) ->
833 (C.Meta (i, l), s, m, ug, eq_found)) l'
835 e, C.Meta (i, lifted_l)
838 [], if m <= lift_amount then C.Rel m else C.Rel (m+1)
840 | C.Prod (nn, s, t) ->
842 betaexpand_term metasenv context ugraph table lift_amount s in
844 betaexpand_term metasenv ((Some (nn, C.Decl s))::context) ugraph
845 table (lift_amount+1) t in
848 (fun (t, s, m, ug, eq_found) ->
849 C.Prod (nn, t, lifted_t), s, m, ug, eq_found) l1
852 (fun (t, s, m, ug, eq_found) ->
853 C.Prod (nn, lifted_s, t), s, m, ug, eq_found) l2 in
854 l1' @ l2', C.Prod (nn, lifted_s, lifted_t)
856 | C.Lambda (nn, s, t) ->
858 betaexpand_term metasenv context ugraph table lift_amount s in
860 betaexpand_term metasenv ((Some (nn, C.Decl s))::context) ugraph
861 table (lift_amount+1) t in
864 (fun (t, s, m, ug, eq_found) ->
865 C.Lambda (nn, t, lifted_t), s, m, ug, eq_found) l1
868 (fun (t, s, m, ug, eq_found) ->
869 C.Lambda (nn, lifted_s, t), s, m, ug, eq_found) l2 in
870 l1' @ l2', C.Lambda (nn, lifted_s, lifted_t)
875 (fun (res, lifted_tl) arg ->
876 let arg_res, lifted_arg =
877 betaexpand_term metasenv context ugraph table lift_amount arg
881 (fun (a, s, m, ug, eq_found) ->
882 a::lifted_tl, s, m, ug, eq_found)
887 (fun (r, s, m, ug, eq_found) ->
888 lifted_arg::r, s, m, ug, eq_found)
890 lifted_arg::lifted_tl)
891 ) ([], []) (List.rev l)
894 (fun (l, s, m, ug, eq_found) -> (C.Appl l, s, m, ug, eq_found)) l',
897 | t -> [], (S.lift lift_amount t)
900 | C.Meta (i, l) -> res, lifted_term
903 (* C.Implicit None, ugraph *)
904 CicTypeChecker.type_of_aux' metasenv context term ugraph
906 let candidates = get_candidates Unification table term in
908 if subterms_only then
912 metasenv context ugraph lift_amount term termty candidates
919 returns a list of new clauses inferred with a right superposition step
920 between the positive equation "target" and one in the "table" "newmeta" is
921 the first free meta index, i.e. the first number above the highest meta
922 index: its updated value is also returned
924 let superposition_right bag
925 ?(subterms_only=false) eq_uri newmeta (metasenv, context, ugraph) table target=
926 let module C = Cic in
927 let module S = CicSubstitution in
928 let module M = CicMetaSubst in
929 let module HL = HelmLibraryObjects in
930 let module CR = CicReduction in
931 let module U = Utils in
932 let w, eqproof, (eq_ty, left, right, ordering), newmetas,id =
933 Equality.open_equality target
935 if Utils.debug_metas then
936 ignore (check_target bag context target "superpositionright");
937 let metasenv' = newmetas in
938 let maxmeta = ref newmeta in
942 fst (betaexpand_term ~subterms_only metasenv' context ugraph table 0 left), []
944 [], fst (betaexpand_term ~subterms_only metasenv' context ugraph table 0 right)
948 (fun (_, subst, _, _, _) ->
949 let subst = apply_subst subst in
950 let o = !Utils.compare_terms (subst l) (subst r) in
951 o <> U.Lt && o <> U.Le)
952 (fst (betaexpand_term ~subterms_only metasenv' context ugraph table 0 l))
954 (res left right), (res right left)
956 let build_new ordering (bo, s, m, ug, eq_found) =
957 if Utils.debug_metas then
958 ignore (check_target bag context (snd eq_found) "buildnew1" );
960 let pos, equality = eq_found in
961 let (_, proof', (ty, what, other, _), menv',id') =
962 Equality.open_equality equality in
963 let what, other = if pos = Utils.Left then what, other else other, what in
965 let ty, eq_ty = apply_subst s ty, apply_subst s eq_ty in
966 let newgoal, newproof =
969 Utils.guarded_simpl context (apply_subst s (S.subst other bo))
971 let name = C.Name "x" in
974 if ordering = U.Gt then bo, S.lift 1 right else S.lift 1 left, bo in
975 C.Appl [C.MutInd (eq_uri, 0, []); S.lift 1 eq_ty; l; r]
979 (s,(Equality.SuperpositionRight,
980 id,(pos,id'),(Cic.Lambda(name,ty,bo''))))
982 let newmeta, newequality =
984 if ordering = U.Gt then newgoal, apply_subst s right
985 else apply_subst s left, newgoal in
986 let neworder = !Utils.compare_terms left right in
987 let newmenv = (* Founif.filter s *) m in
988 let stat = (eq_ty, left, right, neworder) in
990 let w = Utils.compute_equality_weight stat in
991 Equality.mk_equality bag (w, newproof, stat, newmenv) in
992 if Utils.debug_metas then
993 ignore (check_target bag context eq' "buildnew3");
994 let newm, eq' = Equality.fix_metas bag !maxmeta eq' in
995 if Utils.debug_metas then
996 ignore (check_target bag context eq' "buildnew4");
1000 if Utils.debug_metas then
1001 ignore(check_target bag context newequality "buildnew2");
1004 let new1 = List.map (build_new U.Gt) res1
1005 and new2 = List.map (build_new U.Lt) res2 in
1006 let ok e = not (Equality.is_identity (metasenv', context, ugraph) e) in
1008 (List.filter ok (new1 @ new2)))
1011 (** demodulation, when the target is a theorem *)
1012 let rec demodulation_theorem bag env table theorem =
1013 let module C = Cic in
1014 let module S = CicSubstitution in
1015 let module M = CicMetaSubst in
1016 let module HL = HelmLibraryObjects in
1018 match LibraryObjects.eq_URI() with
1020 | None -> assert false in
1021 let metasenv, context, ugraph = env in
1022 let proof, theo, metas = theorem in
1023 let build_newtheorem (t, subst, menv, ug, eq_found) =
1024 let pos, equality = eq_found in
1025 let (_, proof', (ty, what, other, _), menv',id) =
1026 Equality.open_equality equality in
1029 | Equality.Exact p -> p
1030 | _ -> assert false in
1032 if pos = Utils.Left then what, other else other, what in
1033 let newtheo = apply_subst subst (S.subst other t) in
1034 let name = C.Name "x" in
1035 let body = apply_subst subst t in
1036 let pred = C.Lambda(name,ty,body) in
1040 Equality.mk_eq_ind eq_uri ty what pred proof other peq
1042 Equality.mk_eq_ind eq_uri ty what pred proof other peq
1046 let res = demodulation_aux bag metas context ugraph table 0 theo in
1049 let newproof, newtheo = build_newtheorem t in
1050 if Equality.meta_convertibility theo newtheo then
1053 demodulation_theorem bag env table (newproof,newtheo,[])
1058 (*****************************************************************************)
1059 (** OPERATIONS ON GOALS **)
1061 (** DEMODULATION_GOAL & SUPERPOSITION_LEFT **)
1062 (*****************************************************************************)
1064 (* new: demodulation of non_equality terms *)
1065 let build_newg bag context goal rule expansion =
1066 let goalproof,_,_ = goal in
1067 let (t,subst,menv,ug,eq_found) = expansion in
1068 let pos, equality = eq_found in
1069 let (_, proof', (ty, what, other, _), menv',id) =
1070 Equality.open_equality equality in
1071 let what, other = if pos = Utils.Left then what, other else other, what in
1072 let newterm, newgoalproof =
1074 Utils.guarded_simpl context
1075 (apply_subst subst (CicSubstitution.subst other t))
1077 let bo' = apply_subst subst t in
1078 let ty = apply_subst subst ty in
1079 let name = Cic.Name "x" in
1080 let newgoalproofstep = (rule,pos,id,subst,Cic.Lambda (name,ty,bo')) in
1081 bo, (newgoalproofstep::goalproof)
1083 let newmetasenv = (* Founif.filter subst *) menv in
1084 (newgoalproof, newmetasenv, newterm)
1087 let rec demod bag env table goal =
1088 let goalproof,menv,t = goal in
1089 let _, context, ugraph = env in
1090 let res = demodulation_aux bag menv context ugraph table 0 t (~typecheck:true)in
1094 build_newg bag context goal Equality.Demodulation newt
1096 let _,_,newt = newg in
1097 if Equality.meta_convertibility t newt then
1100 true, snd (demod bag env table newg)
1107 | (proof,menv,Cic.Appl[(Cic.MutInd(uri,0,_)) as eq;ty;l;r]) ->
1108 (* assert (LibraryObjects.is_eq_URI uri); *)
1109 proof,menv,eq,ty,l,r
1112 let ty_of_goal (_,_,ty) = ty ;;
1114 (* checks if two goals are metaconvertible *)
1115 let goal_metaconvertibility_eq g1 g2 =
1116 Equality.meta_convertibility (ty_of_goal g1) (ty_of_goal g2)
1119 (* when the betaexpand_term function is called on the left/right side of the
1120 * goal, the predicate has to be fixed
1121 * C[x] ---> (eq ty unchanged C[x])
1122 * [posu] is the side of the [unchanged] term in the original goal
1125 let fix_expansion goal posu (t, subst, menv, ug, eq_f) =
1126 let _,_,eq,ty,l,r = open_goal goal in
1127 let unchanged = if posu = Utils.Left then l else r in
1128 let unchanged = CicSubstitution.lift 1 unchanged in
1129 let ty = CicSubstitution.lift 1 ty in
1132 | Utils.Left -> Cic.Appl [eq;ty;unchanged;t]
1133 | Utils.Right -> Cic.Appl [eq;ty;t;unchanged]
1135 (pred, subst, menv, ug, eq_f)
1138 (* ginve the old [goal], the side that has not changed [posu] and the
1139 * expansion builds a new goal *)
1140 let build_newgoal bag context goal posu rule expansion =
1141 let goalproof,_,_,_,_,_ = open_goal goal in
1142 let (t,subst,menv,ug,eq_found) = fix_expansion goal posu expansion in
1143 let pos, equality = eq_found in
1144 let (_, proof', (ty, what, other, _), menv',id) =
1145 Equality.open_equality equality in
1146 let what, other = if pos = Utils.Left then what, other else other, what in
1147 let newterm, newgoalproof =
1149 Utils.guarded_simpl context
1150 (apply_subst subst (CicSubstitution.subst other t))
1152 let bo' = apply_subst subst t in
1153 let ty = apply_subst subst ty in
1154 let name = Cic.Name "x" in
1155 let newgoalproofstep = (rule,pos,id,subst,Cic.Lambda (name,ty,bo')) in
1156 bo, (newgoalproofstep::goalproof)
1158 let newmetasenv = (* Founif.filter subst *) menv in
1159 (newgoalproof, newmetasenv, newterm)
1164 returns a list of new clauses inferred with a left superposition step
1165 the negative equation "target" and one of the positive equations in "table"
1167 let superposition_left bag (metasenv, context, ugraph) table goal maxmeta =
1168 let names = Utils.names_of_context context in
1169 let proof,menv,eq,ty,l,r = open_goal goal in
1170 let c = !Utils.compare_terms l r in
1172 if c = Utils.Incomparable then
1174 let expansionsl, _ = betaexpand_term menv context ugraph table 0 l in
1175 let expansionsr, _ = betaexpand_term menv context ugraph table 0 r in
1176 (* prerr_endline "incomparable";
1177 prerr_endline (string_of_int (List.length expansionsl));
1178 prerr_endline (string_of_int (List.length expansionsr));
1180 List.map (build_newgoal bag context goal Utils.Right Equality.SuperpositionLeft) expansionsl
1182 List.map (build_newgoal bag context goal Utils.Left Equality.SuperpositionLeft) expansionsr
1186 | Utils.Gt -> (* prerr_endline "GT"; *)
1187 let big,small,possmall = l,r,Utils.Right in
1188 let expansions, _ = betaexpand_term menv context ugraph table 0 big in
1190 (build_newgoal bag context goal possmall Equality.SuperpositionLeft)
1192 | Utils.Lt -> (* prerr_endline "LT"; *)
1193 let big,small,possmall = r,l,Utils.Left in
1194 let expansions, _ = betaexpand_term menv context ugraph table 0 big in
1196 (build_newgoal bag context goal possmall Equality.SuperpositionLeft)
1201 ("NOT GT, LT NOR EQ : "^CicPp.pp l names^" - "^CicPp.pp r names);
1204 (* rinfresco le meta *)
1207 let max,g = Equality.fix_metas_goal max g in max,g::acc)
1208 newgoals (maxmeta,[])
1211 (** demodulation, when the target is a goal *)
1212 let rec demodulation_goal bag env table goal =
1213 let goalproof,menv,_,_,left,right = open_goal goal in
1214 let _, context, ugraph = env in
1215 (* let term = Utils.guarded_simpl (~debug:true) context term in*)
1217 let resright = demodulation_aux bag menv context ugraph table 0 right in
1221 build_newgoal bag context goal Utils.Left Equality.Demodulation t
1223 if goal_metaconvertibility_eq goal newg then
1226 true, snd (demodulation_goal bag env table newg)
1227 | None -> false, goal
1229 let resleft = demodulation_aux bag menv context ugraph table 0 left in
1232 let newg = build_newgoal bag context goal Utils.Right Equality.Demodulation t in
1233 if goal_metaconvertibility_eq goal newg then
1236 true, snd (demodulation_goal bag env table newg)
1237 | None -> do_right ()
1241 type solved = Yes of Equality.goal | No of Equality.goal list
1243 (* returns all the 1 step demodulations *)
1245 module S = CicSubstitution;;
1246 let rec demodulation_all_aux
1247 metasenv context ugraph table lift_amount term
1250 get_candidates ~env:(metasenv,context,ugraph) Matching table term
1255 let termty, ugraph = C.Implicit None, ugraph in
1258 metasenv context ugraph lift_amount term termty candidates
1267 (fun (rel, s, m, ug, c) ->
1268 (Cic.Appl (l@[rel]@List.tl r), s, m, ug, c))
1269 (demodulation_all_aux
1270 metasenv context ugraph table lift_amount t),
1271 l@[List.hd r], List.tl r)
1272 (res, [], List.map (S.lift 1) l) l
1276 | C.Lambda (nn, s, t) ->
1277 let context = (Some (nn, C.Decl s))::context in
1280 | Cic.Prod _ -> Cic.Prod (nn,s,t) | _ -> Cic.Lambda (nn,s,t)
1284 (fun (rel, subst, m, ug, c) ->
1285 mk (S.lift 1 s) rel, subst, m, ug, c)
1286 (demodulation_all_aux
1287 metasenv context ugraph table (lift_amount+1) t)
1288 (* we could demodulate also in s, but then t may be badly
1293 let solve_demodulating bag env table initgoal steps =
1294 let _, context, ugraph = env in
1295 let solved goal res side =
1296 let newg = build_newgoal bag context goal side Equality.Demodulation res in
1298 | (goalproof,m,Cic.Appl[Cic.MutInd(uri,n,ens);eq_ty;left;right])
1299 when LibraryObjects.is_eq_URI uri ->
1302 Founif.unification m m context left right CicUniv.empty_ugraph
1305 with CicUnification.UnificationFailure _ -> No [newg])
1308 let solved goal res_list side =
1309 let newg = List.map (fun x -> solved goal x side) res_list in
1311 List.find (function Yes _ -> true | _ -> false) newg
1313 No (List.flatten (List.map (function No s -> s | _-> assert false) newg))
1320 | None -> first f tl
1321 | Some x as ok -> ok
1323 let rec aux steps next goal =
1324 if steps = 0 then None else
1325 let goalproof,menv,_,_,left,right = open_goal goal in
1327 demodulation_all_aux menv context ugraph table 0 t
1331 (match do_step left with
1333 (match solved goal res Utils.Right with
1335 (match first (aux (steps - 1) L) newgoals with
1336 | Some g as success -> success
1337 | None -> aux steps R goal)
1338 | Yes newgoal -> Some newgoal)
1339 | [] -> aux steps R goal)
1341 (match do_step right with
1343 (match solved goal res Utils.Left with
1345 (match first (aux (steps - 1) L) newgoals with
1346 | Some g as success -> success
1348 | Yes newgoal -> Some newgoal)
1351 aux steps L initgoal
1354 let get_stats () = "" ;;