]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/software/components/tactics/paramodulation/inference.ml
auto snapshot
[helm.git] / helm / software / components / tactics / paramodulation / inference.ml
index 6a21bb173d1f76f8cc380b56b4bd34160beed287..e7f3d8d21eff29bcd40c9499e1fbd9fae49a3f27 100644 (file)
  * 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)
@@ -51,7 +61,7 @@ let rec check_irl start = function
 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
@@ -70,7 +80,7 @@ let unification_simple locked_menv metasenv context t1 t2 ugraph =
   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
@@ -84,6 +94,9 @@ let unification_simple locked_menv metasenv context t1 t2 ugraph =
     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
@@ -92,7 +105,7 @@ let unification_simple locked_menv metasenv context t1 t2 ugraph =
         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) -> 
@@ -207,75 +220,192 @@ let check_eq context msg eq =
   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
 ;;
 
 
@@ -315,109 +445,125 @@ let equations_blacklist =
 *)
 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
@@ -431,65 +577,7 @@ let find_library_equalities dbd context status maxmeta =
           ) 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.>>*) ;;