* http://cs.unibo.it/helm/.
*)
-let _profiler = <:profiler<_profiler>>;;
+(* let _profiler = <:profiler<_profiler>>;; *)
(* $Id$ *)
open Utils;;
open Printf;;
+type auto_type =
+ AutoTypes.flags ->
+ ProofEngineTypes.proof ->
+ Cic.context ->
+ ?universe:AutoTypes.universe -> AutoTypes.cache ->
+ ProofEngineTypes.goal list ->
+ Cic.substitution list * AutoTypes.cache * AutoTypes.universe
+
+let debug_print s = prerr_endline (Lazy.force s);;
+
let check_disjoint_invariant subst metasenv msg =
if (List.exists
(fun (i,_,_) -> (Subst.is_in_subst i subst)) metasenv)
let rec is_simple_term = function
| Cic.Appl ((Cic.Meta _)::_) -> false
| Cic.Appl l -> List.for_all is_simple_term l
- | Cic.Meta (i, l) -> check_irl 1 l
+ | Cic.Meta (i, l) -> let l = [] in check_irl 1 l
| Cic.Rel _ -> true
| Cic.Const _ -> true
| Cic.MutInd (_, _, []) -> true
let lookup = Subst.lookup_subst in
let rec occurs_check subst what where =
match where with
- | t when what = t -> true
+ | Cic.Meta(i,_) when i = what -> true
| C.Appl l -> List.exists (occurs_check subst what) l
| C.Meta _ ->
let t = lookup where subst in
in
match s, t with
| s, t when s = t -> subst, menv
+ (* sometimes the same meta has different local contexts; this
+ could create "cyclic" substitutions *)
+ | C.Meta (i, _), C.Meta (j, _) when i=j -> subst, menv
| C.Meta (i, _), C.Meta (j, _)
when (locked locked_menv i) &&(locked locked_menv j) ->
raise
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 ->
+ | C.Meta (i,_), t when occurs_check subst i t ->
raise
(U.UnificationFailure (lazy "Inference.unification.unif"))
| C.Meta (i, l), t when (locked locked_menv i) ->
else ()
;;
-let find_equalities context proof =
+let default_auto _ _ _ ?(universe:AutoTypes.universe option) _ _ =
+ [],AutoTypes.cache_empty,AutoTypes.empty_universe
+;;
+
+(* far sta roba e' un casino perche' bisogna pulire il contesto lasciando solo
+ * la roba che non dipende da i *)
+let pi_of_ctx t i ctx =
+ let rec aux j = function
+ | [] -> t
+ | (Some (nam, Cic.Decl (term)))::tl -> Cic.Prod(nam,term,aux (j-1) tl)
+ | _ -> assert false (* not implemented *)
+ in
+ aux (List.length ctx-1) (List.rev ctx)
+;;
+
+let lambda_of_ctx t i ctx =
+ let rec aux j = function
+ | [] -> t
+ | (Some (nam, Cic.Decl (term)))::tl -> Cic.Lambda(nam,term,aux (j-1) tl)
+ | _ -> assert false (* not implemented *)
+ in
+ aux (List.length ctx -1) (List.rev ctx)
+;;
+
+let rec skip_lambda t l =
+ match t,l with
+ | Cic.Lambda (_,_,t), _::((_::_) as tl) -> skip_lambda t tl
+ | Cic.Lambda (_,_,t), _::[] -> t
+ | _ -> assert false
+;;
+
+let ty_of_eq = function
+ | Cic.Appl [Cic.MutInd (_, _, _); ty; _; _] -> ty
+ | _ -> assert false
+;;
+
+exception UnableToSaturate of AutoTypes.universe option * AutoTypes.cache
+
+let saturate_term context metasenv oldnewmeta term ?universe cache auto fast =
+ let head, metasenv, args, newmeta =
+ ProofEngineHelpers.saturate_term oldnewmeta metasenv context term 0
+ in
+ let args_for_auto =
+ HExtlib.filter_map
+ (function
+ | Cic.Meta(i,_) ->
+ let _,_,mt = CicUtil.lookup_meta i metasenv in
+ let sort,u =
+ CicTypeChecker.type_of_aux' metasenv context mt
+ CicUniv.empty_ugraph
+ in
+ let b, _ =
+ CicReduction.are_convertible ~metasenv context
+ sort (Cic.Sort Cic.Prop) u
+ in
+ if b then Some i else None
+ (* maybe unif or conv should be used instead of = *)
+ | _ -> assert false)
+ args
+ in
+ let results,universe,cache =
+ if args_for_auto = [] then
+ let newmetas = List.filter (fun (i,_,_) -> i >= oldnewmeta) metasenv in
+ [args,metasenv,newmetas,head,newmeta],universe,cache
+ else
+ let proof =
+ None,metasenv,term,term (* term non e' significativo *)
+ in
+ let flags =
+ if fast then
+ {AutoTypes.timeout = 1.0;maxwidth = 2;maxdepth = 2}
+ else
+ {AutoTypes.timeout = 1.0;maxwidth = 3;maxdepth = 3}
+ in
+ match auto flags proof context ?universe cache args_for_auto with
+ | [],cache,universe -> raise (UnableToSaturate (Some universe,cache))
+ | substs,cache,universe ->
+ List.map
+ (fun subst ->
+ let metasenv =
+ CicMetaSubst.apply_subst_metasenv subst metasenv
+ in
+ let head = CicMetaSubst.apply_subst subst head in
+ let newmetas =
+ List.filter (fun (i,_,_) ->i >= oldnewmeta) metasenv
+ in
+ let args = List.map (CicMetaSubst.apply_subst subst) args in
+ args,metasenv,newmetas,head,newmeta)
+ substs,
+ Some universe,cache
+ in
+ results,universe,cache
+;;
+
+let rec is_an_equality = function
+ | Cic.Appl [Cic.MutInd (uri, _, _); ty; t1; t2]
+ when (LibraryObjects.is_eq_URI uri) -> true
+ | Cic.Prod (name, s, t) -> is_an_equality t
+ | _ -> false
+;;
+
+let build_equality_of_hypothesis index head args newmetas =
+ match head with
+ | Cic.Appl [Cic.MutInd (uri, _, _); ty; t1; t2] ->
+ let p =
+ if args = [] then Cic.Rel index else Cic.Appl ((Cic.Rel index)::args)
+ in
+ debug_print
+ (lazy
+ (Printf.sprintf "OK: %s" (CicPp.ppterm p)));
+ let o = !Utils.compare_terms t1 t2 in
+ let stat = (ty,t1,t2,o) in
+ (* let w = compute_equality_weight stat in *)
+ let w = 0 in
+ let proof = Equality.Exact p in
+ Equality.mk_equality (w, proof, stat, newmetas)
+ | _ -> assert false
+;;
+
+let build_equality ty t1 t2 proof menv =
+ let o = !Utils.compare_terms t1 t2 in
+ let stat = (ty,t1,t2,o) in
+ let w = compute_equality_weight stat in
+ let proof = Equality.Exact proof in
+ Equality.mk_equality (w, proof, stat, menv)
+;;
+
+let find_equalities ?(auto = default_auto) context proof ?universe cache =
+ prerr_endline "find_equalities";
let module C = Cic in
let module S = CicSubstitution in
let module T = CicTypeChecker in
- let eq_uri = LibraryObjects.eq_URI () in
+ let _,metasenv,_,_ = proof in
let newmeta = ProofEngineHelpers.new_meta_of_proof ~proof in
- let ok_types ty menv =
- List.for_all (fun (_, _, mt) -> mt = ty) menv
- in
- let rec aux index newmeta = function
- | [] -> [], newmeta
+ let rec aux universe cache index newmeta = function
+ | [] -> [], newmeta,universe,cache
| (Some (_, C.Decl (term)))::tl ->
+ debug_print
+ (lazy
+ (Printf.sprintf "Examining: %d (%s)" index (CicPp.ppterm term)));
let do_find context term =
match term with
- | C.Prod (name, s, t) ->
- let (head, newmetas, args, newmeta) =
- ProofEngineHelpers.saturate_term newmeta []
- context (S.lift index term) 0
- in
- let p =
- if List.length args = 0 then
- C.Rel index
- else
- C.Appl ((C.Rel index)::args)
- in (
- match head with
- | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
- when (UriManager.eq uri eq_uri) && (ok_types ty newmetas) ->
- debug_print
- (lazy
- (Printf.sprintf "OK: %s" (CicPp.ppterm term)));
- let o = !Utils.compare_terms t1 t2 in
- let stat = (ty,t1,t2,o) in
- let w = compute_equality_weight stat in
- let proof = Equality.Exact p in
- let e = Equality.mk_equality (w, proof, stat, newmetas) in
- Some e, (newmeta+1)
- | _ -> None, newmeta
- )
+ | C.Prod (name, s, t) when is_an_equality t ->
+ (try
+ let term = S.lift index term in
+ let saturated ,universe,cache =
+ saturate_term context metasenv newmeta term
+ ?universe cache auto false
+ in
+ let eqs,newmeta =
+ List.fold_left
+ (fun (acc,newmeta) (args,metasenv,newmetas,head,newmeta') ->
+ let equality =
+ build_equality_of_hypothesis index head args newmetas
+ in
+ equality::acc,(max newmeta newmeta' + 1))
+ ([],0) saturated
+ in
+ eqs, newmeta, universe, cache
+ with UnableToSaturate (universe,cache) ->
+ [],newmeta,universe,cache)
| C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
- when UriManager.eq uri eq_uri ->
- 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 stat = (ty,t1,t2,o) in
- let w = compute_equality_weight stat in
- let p = C.Rel index in
- let proof = Equality.Exact p in
- let e = Equality.mk_equality (w, proof,stat,[]) in
- Some e, (newmeta+1)
- | _ -> None, newmeta
- in (
- match do_find context term with
- | Some p, newmeta ->
- let tl, newmeta' = (aux (index+1) newmeta tl) in
- if newmeta' < newmeta then
- prerr_endline "big trouble";
- (index, p)::tl, newmeta' (* max???? *)
- | None, _ ->
- aux (index+1) newmeta tl
- )
+ when LibraryObjects.is_eq_URI uri ->
+ let term = S.lift index term in
+ let e = build_equality_of_hypothesis index term [] [] in
+ [e], (newmeta+1),universe,cache
+ | _ -> [], newmeta, universe, cache
+ in
+ let eqs, newmeta, universe, cache = do_find context term in
+ if eqs = [] then
+ debug_print (lazy "skipped")
+ else
+ debug_print (lazy "ok");
+ let rest, newmeta,universe,cache =
+ aux universe cache (index+1) newmeta tl
+ in
+ List.map (fun x -> index,x) eqs @ rest, newmeta, universe, cache
| _::tl ->
- aux (index+1) newmeta tl
+ aux universe cache (index+1) newmeta tl
+ in
+ let il, maxm, universe, cache =
+ aux universe cache 1 newmeta context
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
+ indexes, equalities, maxm, universe, cache
;;
*)
let equations_blacklist = UriManager.UriSet.empty;;
+let tty_of_u u =
+(* let _ = <:start<tty_of_u>> in *)
+ let t = CicUtil.term_of_uri u in
+ let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
+(* let _ = <:stop<tty_of_u>> in *)
+ t, ty
+;;
+
+let utty_of_u u =
+ let t,ty = tty_of_u u in
+ u, t, ty
+;;
-let find_library_equalities dbd context status maxmeta =
+let find_library_equalities
+ ?(auto = default_auto) caso_strano dbd context status maxmeta ?universe cache
+=
+ prerr_endline "find_library_equalities";
let module C = Cic in
let module S = CicSubstitution in
let module T = CicTypeChecker in
- let blacklist =
- List.fold_left
- (fun s u -> UriManager.UriSet.add u s)
- equations_blacklist
- [eq_XURI (); sym_eq_URI (); trans_eq_URI (); eq_ind_URI ();
- eq_ind_r_URI ()]
- in
- let candidates =
- List.fold_left
- (fun l uri ->
- if UriManager.UriSet.mem uri blacklist then
- l
- else
- let t = CicUtil.term_of_uri uri in
- let ty, _ =
- CicTypeChecker.type_of_aux' [] context t CicUniv.empty_ugraph
- in
- (uri, t, ty)::l)
- []
- (let t1 = Unix.gettimeofday () in
- let eqs = (MetadataQuery.equations_for_goal ~dbd status) in
- let t2 = Unix.gettimeofday () in
- (debug_print
- (lazy
- (Printf.sprintf "Tempo di MetadataQuery.equations_for_goal: %.9f\n"
- (t2 -. t1))));
- eqs)
- in
- let eq_uri1 = eq_XURI ()
- and eq_uri2 = LibraryObjects.eq_URI () in
- let iseq uri =
- (UriManager.eq uri eq_uri1) || (UriManager.eq uri eq_uri2)
+(* let _ = <:start<equations_for_goal>> in *)
+ let proof, goalno = status in
+ let _,metasenv,_,_ = proof in
+ let metano,context,ty = CicUtil.lookup_meta goalno metasenv in
+ let signature =
+ if caso_strano then
+ begin
+ match ty with
+ | Cic.Appl[Cic.MutInd(u,0,_);eq_ty;l;r] ->
+ (let mainl, sigl = MetadataConstraints.signature_of l in
+ let mainr, sigr = MetadataConstraints.signature_of r in
+ match mainl,mainr with
+ | Some (uril,tyl), Some (urir, tyr)
+ when LibraryObjects.is_eq_URI uril &&
+ LibraryObjects.is_eq_URI urir &&
+ tyl = tyr ->
+ Some (mainl,MetadataConstraints.UriManagerSet.union sigl sigr)
+ | _ ->
+ let u = (UriManager.uri_of_string
+ (UriManager.string_of_uri u ^ "#xpointer(1/1)")) in
+ let main = Some (u, []) in
+ Some (main,MetadataConstraints.UriManagerSet.union sigl sigr))
+ | _ -> assert false
+ end
+ else
+ None
in
- let ok_types ty menv =
- List.for_all (fun (_, _, mt) -> mt = ty) menv
- in
- let rec has_vars = function
- | C.Meta _ | C.Rel _ | C.Const _ -> false
- | C.Var _ -> true
- | C.Appl l -> List.exists has_vars l
- | C.Prod (_, s, t) | C.Lambda (_, s, t)
- | C.LetIn (_, s, t) | C.Cast (s, t) ->
- (has_vars s) || (has_vars t)
- | _ -> false
+ prerr_endline "find_library_equalities.1";
+ let eqs = MetadataQuery.equations_for_goal ~dbd ?signature status in
+(* let _ = <:stop<equations_for_goal>> in *)
+ prerr_endline "find_library_equalities.2";
+ let is_var_free (_,term,_ty) =
+ let rec is_var_free = function
+ | C.Var _ -> false
+ | C.Appl l -> List.for_all is_var_free l
+ | C.Prod (_, s, t) | C.Lambda (_, s, t)
+ | C.LetIn (_, s, t) | C.Cast (s, t) -> (is_var_free s) && (is_var_free t)
+ | _ -> true
+ in
+ is_var_free term
in
- let rec aux newmeta = function
- | [] -> [], newmeta
+ let is_monomorphic_eq (_,term,termty) =
+ let rec last = function
+ | Cic.Prod(_,_,t) -> last t
+ | t -> t
+ in
+ match last termty with
+ | C.Appl [C.MutInd (_, _, []); Cic.Rel _; _; _] -> false
+ | C.Appl [C.MutInd (_, _, []); _; _; _] -> true
+ | _ -> false
+ in
+ let candidates = List.map utty_of_u eqs in
+ let candidates = List.filter is_monomorphic_eq candidates in
+ let candidates = List.filter is_var_free candidates in
+ let rec aux universe cache newmeta = function
+ | [] -> [], newmeta, universe, cache
| (uri, term, termty)::tl ->
debug_print
(lazy
(Printf.sprintf "Examining: %s (%s)"
(CicPp.ppterm term) (CicPp.ppterm termty)));
- let res, newmeta =
+ let res, newmeta, universe, cache =
match termty with
- | C.Prod (name, s, t) when not (has_vars termty) ->
- let head, newmetas, args, newmeta =
- ProofEngineHelpers.saturate_term newmeta [] context termty 0
- in
- let p =
- if List.length args = 0 then
- term
- else
- C.Appl (term::args)
- in (
- match head with
- | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
- when (iseq uri) && (ok_types ty newmetas) ->
- debug_print
- (lazy
- (Printf.sprintf "OK: %s" (CicPp.ppterm term)));
- let o = !Utils.compare_terms t1 t2 in
- let stat = (ty,t1,t2,o) in
- let w = compute_equality_weight stat in
- let proof = Equality.Exact p in
- let e = Equality.mk_equality (w, proof, stat, newmetas) 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 stat = (ty,t1,t2,o) in
- let w = compute_equality_weight stat in
- let proof = Equality.Exact term in
- let e = Equality.mk_equality (w, proof, stat, []) in
- Some e, (newmeta+1)
- | _ -> None, newmeta
+ | C.Prod (name, s, t) ->
+ (try
+ let saturated, universe,cache =
+ saturate_term context metasenv newmeta termty
+ ?universe cache auto true
+ in
+ let eqs,newmeta =
+ List.fold_left
+ (fun (acc,newmeta) (args,metasenv,newmetas,head,newmeta') ->
+ match head with
+ | C.Appl [C.MutInd (uri, _, _); ty; t1; t2]
+ when LibraryObjects.is_eq_URI uri ->
+ let proof = C.Appl (term::args) in
+ prerr_endline ("PROVA: " ^ CicPp.ppterm proof);
+ let equality =
+ build_equality ty t1 t2 proof newmetas
+ in
+ equality::acc,(max newmeta newmeta' + 1)
+ | _ -> assert false)
+ ([],0) saturated
+ in
+ eqs, newmeta , universe, cache
+ with UnableToSaturate (universe,cache) ->
+ [], newmeta , universe, cache)
+ | C.Appl [C.MutInd (uri, _, _); ty; t1; t2] ->
+ let e = build_equality ty t1 t2 term [] in
+ [e], (newmeta+1), universe, cache
+ | _ -> assert false
in
- match res with
- | Some e ->
- let tl, newmeta' = aux newmeta tl in
- if newmeta' < newmeta then
- prerr_endline "big trouble";
- (uri, e)::tl, newmeta' (* max???? *)
- | None ->
- aux newmeta tl
+ let res = List.map (fun e -> uri, e) res in
+ let tl, newmeta, universe, cache = aux universe cache newmeta tl in
+ res @ tl, newmeta, universe, cache
+ in
+ let found, maxm, universe, cache =
+ aux universe cache maxmeta candidates
in
- let found, maxm = aux maxmeta candidates in
let uriset, eqlist =
let mceq = Equality.meta_convertibility_eq in
(List.fold_left
) else (UriManager.UriSet.add u s, (u, e)::l))
(UriManager.UriSet.empty, []) found)
in
- uriset, eqlist, maxm
-;;
-
-
-let find_library_theorems dbd env status equalities_uris =
- let module C = Cic in
- let module S = CicSubstitution in
- let module T = CicTypeChecker in
- let blacklist =
- let refl_equal =
- UriManager.uri_of_string "cic:/Coq/Init/Logic/eq.ind#xpointer(1/1/1)" in
- let s =
- UriManager.UriSet.remove refl_equal
- (UriManager.UriSet.union equalities_uris equations_blacklist)
- in
- List.fold_left
- (fun s u -> UriManager.UriSet.add u s)
- s [eq_XURI () ;sym_eq_URI (); trans_eq_URI (); eq_ind_URI ();
- eq_ind_r_URI ()]
- in
- let metasenv, context, ugraph = env in
- let candidates =
- List.fold_left
- (fun l uri ->
- if UriManager.UriSet.mem uri blacklist then l
- else
- let t = CicUtil.term_of_uri uri in
- let ty, _ = CicTypeChecker.type_of_aux' metasenv context t ugraph in
- (t, ty, [])::l)
- [] (MetadataQuery.signature_of_goal ~dbd status)
- in
- let refl_equal =
- let u = eq_XURI () in
- let t = CicUtil.term_of_uri u in
- let ty, _ = CicTypeChecker.type_of_aux' [] [] t CicUniv.empty_ugraph in
- (t, ty, [])
- in
- refl_equal::candidates
-;;
-
-
-let find_context_hypotheses env equalities_indexes =
- let metasenv, context, ugraph = env in
- let _, res =
- List.fold_left
- (fun (n, l) entry ->
- match entry with
- | None -> (n+1, l)
- | Some _ ->
- if List.mem n equalities_indexes then
- (n+1, l)
- else
- let t = Cic.Rel n in
- let ty, _ =
- CicTypeChecker.type_of_aux' metasenv context t ugraph in
- (n+1, (t, ty, [])::l))
- (1, []) context
- in
- res
+ uriset, eqlist, maxm, universe, cache
;;
-let get_stats () = <:show<Inference.>> ;;
+let get_stats () = "" (*<:show<Inference.>>*) ;;