]> matita.cs.unibo.it Git - helm.git/blobdiff - components/tactics/paramodulation/inference.ml
New unification and new matching.
[helm.git] / components / tactics / paramodulation / inference.ml
index dfb67583ec6836c6ddbb3aca8910f2dd1a8a3965..f5508c8c146cc72bc2c418b5ae80770febf6fd4c 100644 (file)
@@ -27,6 +27,8 @@
 
 open Utils;;
 
+let metas_of_proof_time = ref 0.;;
+let metas_of_term_time = ref 0.;;
 
 type equality =
     int  *               (* weight *)
@@ -49,7 +51,6 @@ and proof =
   | SubProof of Cic.term * int * proof
 ;;
 
-
 let string_of_equality ?env =
   match env with
   | None -> (
@@ -76,13 +77,33 @@ let rec string_of_proof = function
       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
@@ -186,6 +207,16 @@ let rec metas_of_term = function
   | _ -> []
 ;;      
 
+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;;
 
@@ -336,17 +367,21 @@ let rec is_simple_term = function
 ;;
 
 
-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
@@ -363,21 +398,29 @@ let unification_simple metasenv context t1 t2 ugraph =
   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 ->
@@ -404,46 +447,69 @@ let unification_simple metasenv context t1 t2 ugraph =
         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)
+    
+;;
+*)
 
 
 (*
@@ -493,35 +559,184 @@ let matching_simple metasenv context t1 t2 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
@@ -555,19 +770,22 @@ let find_equalities context proof =
                       (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 (
@@ -585,6 +803,7 @@ let find_equalities context proof =
   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
 ;;
 
@@ -701,17 +920,19 @@ let find_library_equalities dbd context status maxmeta =
                       (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
@@ -834,7 +1055,10 @@ let fix_metas_old newmeta (w, p, (ty, left, right, o), menv, args) =
   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
@@ -912,6 +1136,11 @@ let relocate newmeta menv =
 
 
 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
@@ -925,14 +1154,26 @@ let fix_metas newmeta (w, p, (ty, left, right, o), menv, args) =
     | 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
@@ -950,8 +1191,9 @@ let equality_of_term proof term =
   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
@@ -980,26 +1222,23 @@ let is_identity (metasenv, context, ugraph) = function
 
 
 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))
 ;;