]> matita.cs.unibo.it Git - helm.git/blob - helm/software/components/ng_refiner/nDiscriminationTree.ml
fb9b4c021335b08188a39257d109294957cf4ebd
[helm.git] / helm / software / components / ng_refiner / nDiscriminationTree.ml
1 (* Copyright (C) 2005, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  *)
25
26 (* $Id$ *)
27
28 type path_string_elem = 
29   | Constant of NUri.uri * int (* name, arity *)
30   | Bound of int * int (* rel, arity *)
31   | Variable (* arity is 0 *)
32   | Proposition (* arity is 0 *) 
33   | Datatype (* arity is 0 *) 
34   | Dead (* arity is 0 *) 
35 ;;  
36       
37 let arity_of = function
38   | Constant (_,a) 
39   | Bound (_,a) -> a
40   | _ -> 0 
41 ;;
42
43 type path = path_string_elem list;;
44
45 let ppelem = function
46   | Constant (uri,arity) -> 
47       "("^NUri.name_of_uri uri ^ "," ^ string_of_int arity^")"
48   | Bound (i,arity) -> 
49       "("^string_of_int i ^ "," ^ string_of_int arity^")"
50   | Variable -> "?"
51   | Proposition -> "Prop"
52   | Datatype -> "Type"
53   | Dead -> "Dead"
54 ;;
55
56 let path_string_of_term_with_jl =
57   let rec aux arity = function
58     | NCic.Appl ((NCic.Meta _|NCic.Implicit _)::_) -> [Variable]
59     | NCic.Appl (NCic.Lambda _ :: _) -> [Variable] (* maybe we should b-reduce *)
60     | NCic.Appl [] -> assert false
61     | NCic.Appl (hd::tl) ->
62         aux (List.length tl) hd @ List.flatten (List.map (aux 0) tl) 
63     | NCic.Lambda _ | NCic.Prod _ -> [Variable]
64         (* I think we should CicSubstitution.subst Implicit t *)
65     | NCic.LetIn _ -> [Variable] (* z-reduce? *)
66     | NCic.Meta _ | NCic.Implicit _ -> assert (arity = 0); [Variable]
67     | NCic.Rel i -> [Bound (i, arity)]
68     | NCic.Sort (NCic.Prop) -> assert (arity=0); [Proposition]
69     | NCic.Sort _ -> assert (arity=0); [Datatype]
70     | NCic.Const (NReference.Ref (u,_)) -> [Constant (u, arity)]
71     | NCic.Match _ -> [Dead]
72   in 
73     aux 0
74 ;;
75
76 let compare_elem e1 e2 =
77   match e1,e2 with
78   | Constant (u1,a1),Constant (u2,a2) -> 
79        let x = NUri.compare u1 u2 in
80        if x = 0 then Pervasives.compare a1 a2 else x
81   | e1,e2 -> Pervasives.compare e1 e2
82 ;;
83
84 let string_of_path l = String.concat "." (List.map ppelem l) ;;
85
86 module DiscriminationTreeIndexing =  
87   functor (A:Set.S) -> 
88     struct
89
90       module OrderedPathStringElement = struct
91         type t = path_string_elem
92         let compare = compare_elem
93       end
94
95       module PSMap = Map.Make(OrderedPathStringElement);;
96
97       type key = PSMap.key
98
99       module DiscriminationTree = Trie.Make(PSMap);;
100
101       type t = A.t DiscriminationTree.t
102
103       let empty = DiscriminationTree.empty;;
104
105       let iter dt f = DiscriminationTree.iter (fun p x -> f p x) dt;;
106
107       let index tree term info =
108         let ps = path_string_of_term_with_jl term in
109         let ps_set =
110           try DiscriminationTree.find ps tree with Not_found -> A.empty 
111         in
112         DiscriminationTree.add ps (A.add info ps_set) tree
113       ;;
114
115       let remove_index tree term info =
116         let ps = path_string_of_term_with_jl term in
117         try
118           let ps_set = A.remove info (DiscriminationTree.find ps tree) in
119           if A.is_empty ps_set then DiscriminationTree.remove ps tree
120           else DiscriminationTree.add ps ps_set tree
121         with Not_found -> tree
122       ;;
123
124       let in_index tree term test =
125         let ps = path_string_of_term_with_jl term in
126         try
127           let ps_set = DiscriminationTree.find ps tree in
128           A.exists test ps_set
129         with Not_found -> false
130       ;;
131
132       (* You have h(f(x,g(y,z)),t) whose path_string_of_term_with_jl is 
133          (h,2).(f,2).(x,0).(g,2).(y,0).(z,0).(t,0) and you are at f and want to
134          skip all its progeny, thus you want to reach t.
135       
136          You need to skip as many elements as the sum of all arieties contained
137           in the progeny of f.
138       
139          The input ariety is the one of f while the path is x.g....t  
140          Should be the equivalent of after_t in the literature (handbook A.R.)
141        *)
142       let rec skip arity path =
143         if arity = 0 then path else match path with 
144         | [] -> assert false 
145         | m::tl -> skip (arity-1+arity_of m) tl
146       ;;
147
148       (* the equivalent of skip, but on the index, thus the list of trees
149          that are rooted just after the term represented by the tree root
150          are returned (we are skipping the root) *)
151       let skip_root = function DiscriminationTree.Node (_, map) ->
152         let rec get n = function DiscriminationTree.Node (_, m) as tree ->
153            if n = 0 then [tree] else 
154            PSMap.fold (fun k v res -> (get (n-1 + arity_of k) v) @ res) m []
155         in
156           PSMap.fold (fun k v res -> (get (arity_of k) v) @ res) map []
157       ;;
158
159       let retrieve unif tree term =
160         let path = path_string_of_term_with_jl term in
161         let rec retrieve path tree =
162           match tree, path with
163           | DiscriminationTree.Node (Some s, _), [] -> s
164           | DiscriminationTree.Node (None, _), [] -> A.empty 
165           | DiscriminationTree.Node _, Variable::path when unif ->
166               List.fold_left A.union A.empty
167                 (List.map (retrieve path) (skip_root tree))
168           | DiscriminationTree.Node (_, map), node::path ->
169               A.union
170                  (if not unif && node = Variable then A.empty else
171                   try retrieve path (PSMap.find node map)
172                   with Not_found -> A.empty)
173                  (try
174                     match PSMap.find Variable map,skip (arity_of node) path with
175                     | DiscriminationTree.Node (Some s, _), [] -> s
176                     | n, path -> retrieve path n
177                   with Not_found -> A.empty)
178        in
179         retrieve path tree
180       ;;
181
182       let retrieve_generalizations tree term = retrieve false tree term;;
183       let retrieve_unifiables tree term = retrieve true tree term;;
184   end
185 ;;
186