open Utils;;
+let metas_of_proof_time = ref 0.;;
+let metas_of_term_time = ref 0.;;
type equality =
int * (* weight *)
| SubProof of Cic.term * int * proof
;;
-
let string_of_equality ?env =
match env with
| None -> (
Printf.sprintf "SubProof(%s, %s, %s)"
(CicPp.ppterm t) (string_of_int i) (string_of_proof p)
| ProofSymBlock _ -> "ProofSymBlock"
- | ProofBlock _ -> "ProofBlock"
+ | ProofBlock (subst, _, _, _ ,_,_) ->
+ "ProofBlock" ^ (CicMetaSubst.ppsubst subst)
| ProofGoalBlock (p1, p2) ->
Printf.sprintf "ProofGoalBlock(%s, %s)"
(string_of_proof p1) (string_of_proof p2)
;;
+let check_disjoint_invariant subst metasenv msg =
+ if (List.exists
+ (fun (i,_,_) -> (List.exists (fun (j,_) -> i=j) subst)) metasenv)
+ then
+ begin
+ prerr_endline ("not disjoint: " ^ msg);
+ assert false
+ end
+;;
+
+(* filter out from metasenv the variables in substs *)
+let filter subst metasenv =
+ List.filter
+ (fun (m, _, _) ->
+ try let _ = List.find (fun (i, _) -> m = i) subst in false
+ with Not_found -> true)
+ metasenv
+;;
+
(* returns an explicit named subst and a list of arguments for sym_eq_URI *)
let build_ens_for_sym_eq sym_eq_URI termlist =
let obj, _ = CicEnvironment.get_obj CicUniv.empty_ugraph sym_eq_URI in
| _ -> []
;;
+let rec metas_of_proof p =
+ if Utils.debug then
+ let t1 = Unix.gettimeofday () in
+ let res = metas_of_term (build_proof_term p) in
+ let t2 = Unix.gettimeofday () in
+ metas_of_proof_time := !metas_of_proof_time +. (t2 -. t1);
+ res
+ else
+ metas_of_term (build_proof_term p)
+;;
exception NotMetaConvertible;;
;;
-let lookup_subst meta subst =
+let rec lookup_subst meta subst =
match meta with
| Cic.Meta (i, _) -> (
- try let _, (_, t, _) = List.find (fun (m, _) -> m = i) subst in t
+ try let _, (_, t, _) = List.find (fun (m, _) -> m = i) subst
+ in lookup_subst t subst
with Not_found -> meta
)
- | _ -> assert false
+ | _ -> meta
;;
+let locked menv i =
+ List.exists (fun (j,_,_) -> i = j) menv
+;;
-let unification_simple metasenv context t1 t2 ugraph =
+let unification_simple locked_menv metasenv context t1 t2 ugraph =
let module C = Cic in
let module M = CicMetaSubst in
let module U = CicUnification in
let rec unif subst menv s t =
let s = match s with C.Meta _ -> lookup s subst | _ -> s
and t = match t with C.Meta _ -> lookup t subst | _ -> t
+
in
match s, t with
| s, t when s = t -> subst, menv
- | C.Meta (i, _), C.Meta (j, _) when i > j ->
+ | C.Meta (i, _), C.Meta (j, _)
+ when (locked locked_menv i) &&(locked locked_menv j) ->
+ raise
+ (U.UnificationFailure (lazy "Inference.unification.unif"))
+ | C.Meta (i, _), C.Meta (j, _) when (locked locked_menv i) ->
+ unif subst menv t s
+ | C.Meta (i, _), C.Meta (j, _) when (i > j) && not (locked locked_menv j) ->
unif subst menv t s
| C.Meta _, t when occurs_check subst s t ->
raise
(U.UnificationFailure (lazy "Inference.unification.unif"))
+ | C.Meta (i, l), t when (locked locked_menv i) ->
+ raise
+ (U.UnificationFailure (lazy "Inference.unification.unif"))
| C.Meta (i, l), t -> (
try
let _, _, ty = CicUtil.lookup_meta i menv in
- let subst =
- if not (List.mem_assoc i subst) then (i, (context, t, ty))::subst
- else subst
- in
+ assert (not (List.mem_assoc i subst));
+ let subst = (i, (context, t, ty))::subst in
let menv = menv in (* List.filter (fun (m, _, _) -> i <> m) menv in *)
subst, menv
with CicUtil.Meta_not_found m ->
raise (U.UnificationFailure (lazy "Inference.unification.unif"))
in
let subst, menv = unif [] metasenv t1 t2 in
- let menv =
- List.filter
- (fun (m, _, _) ->
- try let _ = List.find (fun (i, _) -> m = i) subst in false
- with Not_found -> true)
- menv
- in
+ let menv = filter subst menv in
List.rev subst, menv, ugraph
;;
+let profiler = HExtlib.profile "flatten"
-let unification metasenv context t1 t2 ugraph =
+let unification_aux b metasenv1 metasenv2 context t1 t2 ugraph =
+ let metasenv = metasenv1 @ metasenv2 in
let subst, menv, ug =
if not (is_simple_term t1) || not (is_simple_term t2) then (
debug_print
(lazy
(Printf.sprintf "NOT SIMPLE TERMS: %s %s"
(CicPp.ppterm t1) (CicPp.ppterm t2)));
- CicUnification.fo_unif metasenv context t1 t2 ugraph
+ raise (CicUnification .UnificationFailure (lazy "Inference.unification.unif"))
) else
- unification_simple metasenv context t1 t2 ugraph
- in
- let rec fix_term = function
- | (Cic.Meta (i, l) as t) ->
- let t' = lookup_subst t subst in
- if t <> t' then fix_term t' else t
- | Cic.Appl l -> Cic.Appl (List.map fix_term l)
- | t -> t
+ if b then
+ (* full unification *)
+ unification_simple [] metasenv context t1 t2 ugraph
+ else
+ (* matching: metasenv1 is locked *)
+ unification_simple metasenv1 metasenv context t1 t2 ugraph
in
- let rec fix_subst = function
- | [] -> []
- | (i, (c, t, ty))::tl -> (i, (c, fix_term t, fix_term ty))::(fix_subst tl)
+ if Utils.debug_res then
+ ignore(check_disjoint_invariant subst menv "unif");
+ let flatten subst =
+ List.map
+ (fun (i, (context, term, ty)) ->
+ let context = CicMetaSubst.apply_subst_context subst context in
+ let term = CicMetaSubst.apply_subst subst term in
+ let ty = CicMetaSubst.apply_subst subst ty in
+ (i, (context, term, ty))) subst
in
- fix_subst subst, menv, ug
+ let flatten subst = profiler.HExtlib.profile flatten subst in
+ let subst = flatten subst in
+ subst, menv, ug
;;
+exception MatchingFailure;;
-let unification = CicUnification.fo_unif;;
+let matching1 metasenv1 metasenv2 context t1 t2 ugraph =
+ try
+ unification_aux false metasenv1 metasenv2 context t1 t2 ugraph
+ with
+ CicUnification .UnificationFailure _ ->
+ raise MatchingFailure
+;;
-exception MatchingFailure;;
+let unification = unification_aux true
+;;
+
+
+
+(*
+let unification metasenv1 metasenv2 context t1 t2 ugraph =
+ let (subst, metasenv, ugraph) =
+ CicUnification.fo_unif (metasenv1@metasenv2) context t1 t2 ugraph in
+ if Utils.debug_res then
+ ignore(check_disjoint_invariant subst metasenv "fo_unif");
+ (subst, metasenv, ugraph)
+
+;;
+*)
(*
;;
*)
-
+(*
let matching metasenv context t1 t2 ugraph =
try
let subst, metasenv, ugraph =
-try
+ try
unification metasenv context t1 t2 ugraph
-with CicUtil.Meta_not_found _ as exn ->
- Printf.eprintf "t1 == %s\nt2 = %s\nmetasenv == %s\n%!"
- (CicPp.ppterm t1) (CicPp.ppterm t2) (CicMetaSubst.ppmetasenv [] metasenv);
- raise exn
+ with CicUtil.Meta_not_found _ as exn ->
+ Printf.eprintf "t1 == %s\nt2 = %s\nmetasenv == %s\n%!"
+ (CicPp.ppterm t1) (CicPp.ppterm t2)
+ (CicMetaSubst.ppmetasenv [] metasenv);
+ raise exn
in
+ if Utils.debug_res then
+ ignore(check_disjoint_invariant subst metasenv "qua-2");
let t' = CicMetaSubst.apply_subst subst t1 in
if not (meta_convertibility t1 t') then
raise MatchingFailure
else
+ if Utils.debug_res then
+ ignore(check_disjoint_invariant subst metasenv "qua-1");
let metas = metas_of_term t1 in
+ let subst =
+ List.map
+ (fun (i, (context, term, ty)) ->
+ let context = CicMetaSubst.apply_subst_context subst context in
+ let term = CicMetaSubst.apply_subst subst term in
+ let ty = CicMetaSubst.apply_subst subst ty in
+ (i, (context, term, ty))) subst in
+ if Utils.debug_res then
+ ignore(check_disjoint_invariant subst metasenv "qua0");
+
+ let subst, metasenv =
+ List.fold_left
+ (fun
+ (subst,metasenv) s ->
+ match s with
+ | (i, (c, Cic.Meta (j, lc), ty)) when List.mem i metas ->
+ let metasenv' =
+ List.filter (fun (x, _, _) -> x<>j) metasenv
+ in
+ ((j, (c, Cic.Meta (i, lc), ty))::subst,
+ (i,c,ty)::metasenv')
+ |_ -> s::subst,metasenv) ([],metasenv) subst
+ in
+ if Utils.debug_res then
+ ignore(check_disjoint_invariant subst metasenv "qua1");
+(*
let fix_subst = function
| (i, (c, Cic.Meta (j, lc), ty)) when List.mem i metas ->
(j, (c, Cic.Meta (i, lc), ty))
| s -> s
in
- let subst = List.map fix_subst subst in
- subst, metasenv, ugraph
+ let subst = List.map fix_subst subst in *)
+ if CicMetaSubst.apply_subst subst t1 = t1 then
+ subst, metasenv, ugraph
+ else
+ (prerr_endline "mah"; raise MatchingFailure)
with
| CicUnification.UnificationFailure _
| CicUnification.Uncertain _ ->
raise MatchingFailure
;;
+*)
+
+(** matching takes in input the _disjoint_ metasenv of t1 and t2;
+it perform unification in the union metasenv, then check that
+the first metasenv has not changed *)
+
+
+let matching2 metasenv1 metasenv2 context t1 t2 ugraph =
+ let subst, metasenv, ugraph =
+ try
+ unification metasenv1 metasenv2 context t1 t2 ugraph
+ with
+ CicUtil.Meta_not_found _ as exn ->
+ Printf.eprintf "t1 == %s\nt2 = %s\nmetasenv == %s\n%!"
+ (CicPp.ppterm t1) (CicPp.ppterm t2)
+ (CicMetaSubst.ppmetasenv [] (metasenv1@metasenv2));
+ raise exn
+ | CicUnification.UnificationFailure _
+ | CicUnification.Uncertain _ ->
+ raise MatchingFailure
+ in
+ if Utils.debug_res then
+ ignore(check_disjoint_invariant subst metasenv "qua-2");
+ (* let us unfold subst *)
+ if metasenv = metasenv1 then
+ let subst =
+ List.map
+ (fun (i, (context, term, ty)) ->
+ let context = CicMetaSubst.apply_subst_context subst context in
+ let term = CicMetaSubst.apply_subst subst term in
+ let ty = CicMetaSubst.apply_subst subst ty in
+ (i, (context, term, ty))) subst in
+ subst, metasenv, ugraph (* everything is fine *)
+ else
+ (* let us unfold subst *)
+ (*
+ let subst =
+ List.map
+ (fun (i, (context, term, ty)) ->
+ let context = CicMetaSubst.apply_subst_context subst context in
+ let term = CicMetaSubst.apply_subst subst term in
+ let ty = CicMetaSubst.apply_subst subst ty in
+ (i, (context, term, ty))) subst in
+ *)
+ (* let us revert Meta-Meta in subst privileging metasenv1 *)
+ let subst, metasenv =
+ List.fold_left
+ (fun
+ (subst,metasenv) s ->
+ match s with
+ | (i, (c, Cic.Meta (j, lc), ty))
+ when (List.exists (fun (x, _, _) -> x=i) metasenv1) &&
+ not (List.exists (fun (x, _) -> x=j) subst) ->
+ let metasenv' =
+ List.filter (fun (x, _, _) -> x<>j) metasenv
+ in
+ ((j, (c, Cic.Meta (i, lc), ty))::subst,
+ (i,c,ty)::metasenv')
+ |_ -> s::subst,metasenv) ([],metasenv) subst
+ in
+ (* finally, let us chek again that metasenv = metasenv1 *)
+ if metasenv = metasenv1 then
+ subst, metasenv, ugraph
+ else raise MatchingFailure
+;;
+(* debug
+let matching metasenv1 metasenv2 context t1 t2 ugraph =
+ let rc1 =
+ try Some (matching1 metasenv1 metasenv2 context t1 t2 ugraph)
+ with MatchingFailure -> None
+ in
+ let rc2 =
+ try
+ Some (matching2 metasenv1 metasenv2 context t1 t2 ugraph)
+ with MatchingFailure -> None
+ in
+ match rc1,rc2 with
+ | Some (s,m,g) , None ->
+ prerr_endline (CicPp.ppterm t1);
+ prerr_endline (CicPp.ppterm t2);
+ prerr_endline "SOLO NOI";
+ prerr_endline (CicMetaSubst.ppsubst s);
+ s,m,g
+ | None , Some _ ->
+ prerr_endline (CicPp.ppterm t1);
+ prerr_endline (CicPp.ppterm t2);
+ prerr_endline "SOLO LUI";
+ assert false
+ | None, None -> raise MatchingFailure
+ | Some (s,m,g), Some (s',m',g') ->
+ let s = List.sort (fun (i,_) (j,_) -> i - j) s in
+ let s' = List.sort (fun (i,_) (j,_) -> i - j) s' in
+ if s <> s' then
+ begin
+ prerr_endline (CicMetaSubst.ppsubst s);
+ prerr_endline (CicMetaSubst.ppsubst s');
+ prerr_endline (CicPp.ppterm t1);
+ prerr_endline (CicPp.ppterm t2);
+ end;
+ s,m,g
+*)
+let matching = matching1;;
+
+let check_eq context msg eq =
+ let w, proof, (eq_ty, left, right, order), metas, args = eq in
+ if not (fst (CicReduction.are_convertible ~metasenv:metas context eq_ty
+ (fst (CicTypeChecker.type_of_aux' metas context left CicUniv.empty_ugraph))
+ CicUniv.empty_ugraph))
+ then
+ begin
+ prerr_endline msg;
+ assert false;
+ end
+ else ()
+;;
let find_equalities context proof =
let module C = Cic in
(lazy
(Printf.sprintf "OK: %s" (CicPp.ppterm term)));
let o = !Utils.compare_terms t1 t2 in
- let w = compute_equality_weight ty t1 t2 in
+ let stat = (ty,t1,t2,o) in
+ let w = compute_equality_weight stat in
let proof = BasicProof p in
- let e = (w, proof, (ty, t1, t2, o), newmetas, args) in
+ let e = (w, proof, stat, newmetas, args) in
Some e, (newmeta+1)
| _ -> None, newmeta
)
| C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
when UriManager.eq uri eq_uri ->
- let t1 = S.lift index t1
- and t2 = S.lift index t2 in
+ let ty = S.lift index ty in
+ let t1 = S.lift index t1 in
+ let t2 = S.lift index t2 in
let o = !Utils.compare_terms t1 t2 in
- let w = compute_equality_weight ty t1 t2 in
- let e = (w, BasicProof (C.Rel index), (ty, t1, t2, o), [], []) in
+ let stat = (ty,t1,t2,o) in
+ let w = compute_equality_weight stat in
+ let e = (w, BasicProof (C.Rel index), stat, [], []) in
Some e, (newmeta+1)
| _ -> None, newmeta
in (
in
let il, maxm = aux 1 newmeta context in
let indexes, equalities = List.split il in
+ ignore (List.iter (check_eq context "find") equalities);
indexes, equalities, maxm
;;
(lazy
(Printf.sprintf "OK: %s" (CicPp.ppterm term)));
let o = !Utils.compare_terms t1 t2 in
- let w = compute_equality_weight ty t1 t2 in
+ let stat = (ty,t1,t2,o) in
+ let w = compute_equality_weight stat in
let proof = BasicProof p in
- let e = (w, proof, (ty, t1, t2, o), newmetas, args) in
+ let e = (w, proof, stat, newmetas, args) in
Some e, (newmeta+1)
| _ -> None, newmeta
)
| C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
when iseq uri && not (has_vars termty) ->
let o = !Utils.compare_terms t1 t2 in
- let w = compute_equality_weight ty t1 t2 in
- let e = (w, BasicProof term, (ty, t1, t2, o), [], []) in
+ let stat = (ty,t1,t2,o) in
+ let w = compute_equality_weight stat in
+ let e = (w, BasicProof term, stat, [], []) in
Some e, (newmeta+1)
| _ -> None, newmeta
in
let ty = repl ty
and left = repl left
and right = repl right in
- let metas = (metas_of_term left) @ (metas_of_term right) @ (metas_of_term ty) in
+ let metas =
+ (metas_of_term left) @
+ (metas_of_term right) @
+ (metas_of_term ty) @ (metas_of_proof p) in
let menv' = List.filter (fun (i, _, _) -> List.mem i metas) menv' in
let newargs =
List.filter
let fix_metas newmeta (w, p, (ty, left, right, o), menv, args) =
+ (*
+ let metas = (metas_of_term left)@(metas_of_term right)
+ @(metas_of_term ty)@(metas_of_proof p) in
+ let menv = List.filter (fun (i, _, _) -> List.mem i metas) menv in
+ *)
(* debug
let _ , eq =
fix_metas_old newmeta (w, p, (ty, left, right, o), menv, args) in
| NoProof -> NoProof
| BasicProof term -> BasicProof (CicMetaSubst.apply_subst subst term)
| ProofBlock (subst', eq_URI, namety, bo, (pos, eq), p) ->
- ProofBlock (subst' @ subst, eq_URI, namety, bo, (pos, eq), p)
+ (*
+ let newsubst =
+ List.map
+ (fun (i, (context, term, ty)) ->
+ let context = CicMetaSubst.apply_subst_context subst context in
+ let term = CicMetaSubst.apply_subst subst term in
+ let ty = CicMetaSubst.apply_subst subst ty in
+ (i, (context, term, ty))) subst' in *)
+ ProofBlock (subst@subst', eq_URI, namety, bo, (pos, eq), p)
| p -> assert false
in
- let metas = (metas_of_term left)@(metas_of_term right)@(metas_of_term ty) in
+ let p = fix_proof p in
+ (*
+ let metas = (metas_of_term left)@(metas_of_term right)
+ @(metas_of_term ty)@(metas_of_proof p) in
let metasenv = List.filter (fun (i, _, _) -> List.mem i metas) metasenv in
- let eq = (w, fix_proof p, (ty, left, right, o), metasenv, args) in
+ *)
+ let eq = (w, p, (ty, left, right, o), metasenv, args) in
(* debug prerr_endline (string_of_equality eq); *)
- newmeta, eq
+ newmeta+1, eq
let term_is_equality term =
let iseq uri = UriManager.eq uri (LibraryObjects.eq_URI ()) in
match term with
| Cic.Appl [Cic.MutInd (uri, _, _); ty; t1; t2] when iseq uri ->
let o = !Utils.compare_terms t1 t2 in
- let w = compute_equality_weight ty t1 t2 in
- let e = (w, BasicProof proof, (ty, t1, t2, o), [], []) in
+ let stat = (ty,t1,t2,o) in
+ let w = compute_equality_weight stat in
+ let e = (w, BasicProof proof, stat, [], []) in
e
| _ ->
raise TermIsNotAnEquality
let term_of_equality equality =
- let _, _, (ty, left, right, _), menv, args = equality in
+ let _, _, (ty, left, right, _), menv, _ = equality in
let eq i = function Cic.Meta (j, _) -> i = j | _ -> false in
- let argsno = List.length args in
+ let argsno = List.length menv in
let t =
CicSubstitution.lift argsno
(Cic.Appl [Cic.MutInd (LibraryObjects.eq_URI (), 0, []); ty; left; right])
in
snd (
List.fold_right
- (fun a (n, t) ->
- match a with
- | Cic.Meta (i, _) ->
- let name = Cic.Name ("X" ^ (string_of_int n)) in
- let _, _, ty = CicUtil.lookup_meta i menv in
- let t =
- ProofEngineReduction.replace
- ~equality:eq ~what:[i]
- ~with_what:[Cic.Rel (argsno - (n - 1))] ~where:t
- in
- (n-1, Cic.Prod (name, ty, t))
- | _ -> assert false)
- args (argsno, t))
+ (fun (i,_,ty) (n, t) ->
+ let name = Cic.Name ("X" ^ (string_of_int n)) in
+ let ty = CicSubstitution.lift (n-1) ty in
+ let t =
+ ProofEngineReduction.replace
+ ~equality:eq ~what:[i]
+ ~with_what:[Cic.Rel (argsno - (n - 1))] ~where:t
+ in
+ (n-1, Cic.Prod (name, ty, t)))
+ menv (argsno, t))
;;