]> matita.cs.unibo.it Git - helm.git/blobdiff - helm/ocaml/paramodulation/path_indexing.ml
path indexing working!
[helm.git] / helm / ocaml / paramodulation / path_indexing.ml
diff --git a/helm/ocaml/paramodulation/path_indexing.ml b/helm/ocaml/paramodulation/path_indexing.ml
new file mode 100644 (file)
index 0000000..87e917f
--- /dev/null
@@ -0,0 +1,308 @@
+(* path indexing implementation *)
+
+(* position of the subterm, subterm (Appl are not stored...) *)
+type path_string_elem = Index of int | Term of Cic.term;;
+type path_string = path_string_elem list;; 
+
+
+let rec path_strings_of_term index =
+  let module C = Cic in function
+  | C.Meta _ -> [ [Index index; Term (C.Implicit None)] ]
+  | C.Appl (hd::tl) ->
+      let p = if index > 0 then [Index index; Term hd] else [Term hd] in
+      let _, res = 
+        List.fold_left
+          (fun (i, r) t ->
+             let rr = path_strings_of_term i t in
+             (i+1, r @ (List.map (fun ps -> p @ ps) rr)))
+          (1, []) tl
+      in
+      res
+  | term -> [ [Index index; Term term] ]
+;;
+
+
+let string_of_path_string ps =
+  String.concat "."
+    (List.map
+       (fun e ->
+          let s =
+            match e with
+            | Index i -> "Index " ^ (string_of_int i)
+            | Term t -> "Term " ^ (CicPp.ppterm t)
+          in
+          "(" ^ s ^ ")")
+       ps)
+;;  
+
+
+module OrderedPathStringElement = struct
+  type t = path_string_elem
+
+  let compare t1 t2 =
+    match t1, t2 with
+    | Index i, Index j -> Pervasives.compare i j
+    | Term t1, Term t2 -> if t1 = t2 then 0 else Pervasives.compare t1 t2
+    | Index _, Term _ -> -1
+    | Term _, Index _ -> 1
+end
+
+module PSMap = Map.Make(OrderedPathStringElement);;
+
+(* module PSTrie = Trie.Make(PathStringElementMap);; *)
+
+module OrderedPosEquality = struct
+  type t = Utils.pos * Inference.equality
+
+  let compare = Pervasives.compare
+end
+
+module PosEqSet = Set.Make(OrderedPosEquality);;
+
+(*
+ * Trie: maps over lists.
+ * Copyright (C) 2000 Jean-Christophe FILLIATRE
+ *)
+module PSTrie = struct
+  type key = path_string
+  type t = Node of PosEqSet.t option * (t PSMap.t)
+
+  let empty = Node (None, PSMap.empty)
+
+  let rec find l t =
+    match (l, t) with
+    | [], Node (None, _) -> raise Not_found
+    | [], Node (Some v, _) -> v
+    | x::r, Node (_, m) -> find r (PSMap.find x m)
+        
+  let rec mem l t =
+    match (l, t) with
+    | [], Node (None, _) -> false
+    | [], Node (Some _, _) -> true
+    | x::r, Node (_, m) -> try mem r (PSMap.find x m) with Not_found -> false
+
+  let add l v t =
+    let rec ins = function
+      | [], Node (_, m) -> Node (Some v, m)
+      | x::r, Node (v, m) ->
+         let t' = try PSMap.find x m with Not_found -> empty in
+         let t'' = ins (r, t') in
+         Node (v, PSMap.add x t'' m)
+    in
+    ins (l, t)
+
+  let rec remove l t =
+    match (l, t) with
+    | [], Node (_, m) -> Node (None, m)
+    | x::r, Node (v, m) -> 
+       try
+         let t' = remove r (PSMap.find x m) in
+         Node (v, if t' = empty then PSMap.remove x m else PSMap.add x t' m)
+       with Not_found ->
+         t
+
+  let rec fold f t acc =
+    let rec traverse revp t acc = match t with
+      | Node (None, m) -> 
+         PSMap.fold (fun x -> traverse (x::revp)) m acc
+      | Node (Some v, m) -> 
+         f (List.rev revp) v (PSMap.fold (fun x -> traverse (x::revp)) m acc)
+    in
+    traverse [] t acc
+
+end
+
+
+let index trie equality =
+  let _, (_, l, r, ordering), _, _ = equality in
+  let psl = path_strings_of_term 0 l
+  and psr = path_strings_of_term 0 r in
+  let index pos trie ps =
+    let ps_set = try PSTrie.find ps trie with Not_found -> PosEqSet.empty in
+    let trie = PSTrie.add ps (PosEqSet.add (pos, equality) ps_set) trie in
+(*     if PosEqSet.mem (pos, equality) (PSTrie.find ps trie) then *)
+(*       Printf.printf "OK: %s, %s indexed\n" (Utils.string_of_pos pos) *)
+(*         (Inference.string_of_equality equality); *)
+    trie
+  in
+  match ordering with
+  | Utils.Gt -> List.fold_left (index Utils.Left) trie psl
+  | Utils.Lt -> List.fold_left (index Utils.Right) trie psr
+  | _ ->
+      let trie = List.fold_left (index Utils.Left) trie psl in
+      List.fold_left (index Utils.Right) trie psr
+;;
+      
+
+let remove_index trie equality =
+  let _, (_, l, r, ordering), _, _ = equality in
+  let psl = path_strings_of_term 0 l
+  and psr = path_strings_of_term 0 r in
+  let remove_index pos trie ps =
+    try
+      let ps_set = PosEqSet.remove (pos, equality) (PSTrie.find ps trie) in
+      if PosEqSet.is_empty ps_set then
+        PSTrie.remove ps trie
+      else
+        PSTrie.add ps ps_set trie
+    with Not_found ->
+(*       Printf.printf "NOT_FOUND: %s, %s\n" (Utils.string_of_pos pos) *)
+(*         (Inference.string_of_equality equality); *)
+      trie
+(*       raise Not_found *)
+  in
+  match ordering with
+  | Utils.Gt -> List.fold_left (remove_index Utils.Left) trie psl
+  | Utils.Lt -> List.fold_left (remove_index Utils.Right) trie psr
+  | _ ->
+      let trie = List.fold_left (remove_index Utils.Left) trie psl in
+      List.fold_left (remove_index Utils.Right) trie psr
+;;
+
+
+let head_of_term = function
+  | Cic.Appl (hd::tl) -> hd
+  | term -> term
+;;
+
+
+let subterm_at_pos index term =
+  if index = 0 then
+    term
+  else
+    match term with
+    | Cic.Appl l ->
+        (try List.nth l index with Failure _ -> raise Not_found)
+    | _ -> raise Not_found
+;;
+
+
+let rec retrieve_generalizations trie term =
+  match trie with
+  | PSTrie.Node (value, map) ->
+      let res = 
+        match term with
+        | Cic.Meta _ -> PosEqSet.empty
+        | term ->
+            let hd_term = head_of_term term in
+            try
+              let n = PSMap.find (Term hd_term) map in
+              match n with
+              | PSTrie.Node (Some s, _) -> s
+              | PSTrie.Node (None, m) ->
+                  let l = 
+                    PSMap.fold
+                      (fun k v res ->
+                         match k with
+                         | Index i ->
+                             let t = subterm_at_pos i term in
+                             let s = retrieve_generalizations v t in
+                             s::res
+                         | _ -> res)
+                      m []
+                  in
+                  match l with
+                  | hd::tl ->
+                      List.fold_left (fun r s -> PosEqSet.inter r s) hd tl
+                  | _ -> PosEqSet.empty
+            with Not_found ->
+              PosEqSet.empty
+      in
+      try
+        let n = PSMap.find (Term (Cic.Implicit None)) map in
+        match n with
+        | PSTrie.Node (Some s, _) -> PosEqSet.union res s
+        | _ -> res
+      with Not_found ->
+        res
+;;
+
+
+let rec retrieve_unifiables trie term =
+  match trie with
+  | PSTrie.Node (value, map) ->
+      let res = 
+        match term with
+        | Cic.Meta _ ->
+            PSTrie.fold
+              (fun ps v res -> PosEqSet.union res v)
+              (PSTrie.Node (None, map))
+              PosEqSet.empty
+        | _ ->
+            let hd_term = head_of_term term in
+            try
+              let n = PSMap.find (Term hd_term) map in
+              match n with
+              | PSTrie.Node (Some v, _) -> v
+              | PSTrie.Node (None, m) ->
+                  let l = 
+                    PSMap.fold
+                      (fun k v res ->
+                         match k with
+                         | Index i ->
+                             let t = subterm_at_pos i term in
+                             let s = retrieve_unifiables v t in
+                             s::res
+                         | _ -> res)
+                      m []
+                  in
+                  match l with
+                  | hd::tl ->
+                      List.fold_left (fun r s -> PosEqSet.inter r s) hd tl
+                  | _ -> PosEqSet.empty
+            with Not_found ->
+(*               Printf.printf "Not_found: %s, term was: %s\n" *)
+(*                 (CicPp.ppterm hd_term) (CicPp.ppterm term); *)
+(*               Printf.printf "map is:\n %s\n\n" *)
+(*                 (String.concat "\n" *)
+(*                    (PSMap.fold *)
+(*                       (fun k v l -> *)
+(*                          match k with *)
+(*                          | Index i -> ("Index " ^ (string_of_int i))::l *)
+(*                          | Term t -> ("Term " ^ (CicPp.ppterm t))::l) *)
+(*                       map [])); *)
+              PosEqSet.empty
+      in
+      try
+        let n = PSMap.find (Term (Cic.Implicit None)) map in
+        match n with
+        | PSTrie.Node (Some s, _) -> PosEqSet.union res s
+        | _ -> res
+      with Not_found ->
+        res
+;;
+
+
+let string_of_pstrie trie =
+  let rec to_string level = function
+    | PSTrie.Node (v, map) ->
+        let s =
+          match v with
+          | Some v ->
+              (String.make (2 * level) ' ') ^
+                "{" ^ (String.concat "; "
+                         (List.map
+                            (fun (p, e) ->
+                               "(" ^ (Utils.string_of_pos p) ^ ", " ^ 
+                                 (Inference.string_of_equality e) ^ ")")
+                            (PosEqSet.elements v))) ^ "}"
+          | None -> ""
+        in
+        let rest =
+          String.concat "\n"
+            (PSMap.fold
+               (fun k v s ->
+                  let ks = 
+                    match k with
+                    | Index i -> "Index " ^ (string_of_int i)
+                    | Term t -> "Term " ^ (CicPp.ppterm t)
+                  in
+                  let rs = to_string (level+1) v in
+                  ((String.make (2 * level) ' ') ^ ks ^ "\n" ^ rs)::s)
+               map [])
+        in
+        s ^ rest
+  in
+  to_string 0 trie
+;;
+