1 (* Copyright (C) 2000, HELM Team.
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.
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.
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.
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,
22 * For details, see the HELM World-Wide-Web page,
23 * http://cs.unibo.it/helm/.
26 (******************************************************************************)
30 (* Enrico Tassi <tassi@cs.unibo.it> *)
33 (* This module implements the aciclic graph of universes. *)
35 (******************************************************************************)
40 - in add_eq there is probably no need of add_gt, simple @ the gt lists
41 - the problem of duplicates in the 1steg gt/ge list if two of them are
42 add_eq may be "fixed" in some ways:
43 - lazy, do nothing on add_eq and eventually update the ge list
45 - add a check_duplicates_after_eq function called by add_eq
46 - do something like rmap, add a list of canonical that point to us
47 so when we collapse we have the list of the canonical we may update
48 - don't use failure but another exception
52 (* ************************************************************************** *)
54 (* ************************************************************************** *)
57 type canonical_repr = {
58 mutable ge:universe list;
59 mutable gt:universe list;
60 (* since we collapse we may need the reverse map *)
61 mutable eq:universe list;
62 (* the canonical representer *)
66 module UniverseType = struct
68 let compare = Pervasives.compare
71 module MapUC = Map.Make(UniverseType)
73 (* ************************************************************************** *)
75 (* ************************************************************************** *)
77 let map = ref MapUC.empty
80 (* ************************************************************************** *)
82 (* ************************************************************************** *)
84 (* create a canonical for [u] *)
86 {u = u ; gt = [] ; ge = [] ; eq = [u] }
88 (* give a new universe *)
91 map := MapUC.add !used (mk_canonical !used) !map;
98 (* ************************************************************************** *)
100 (* ************************************************************************** *)
102 let string_of_universe = string_of_int
105 let canonical_to_string c =
107 List.fold_left (fun s u -> s ^ (string_of_universe u) ^ " ") "" c.gt in
109 List.fold_left (fun s u -> s ^ (string_of_universe u) ^ " ") "" c.ge in
111 List.fold_left (fun s u -> s ^ (string_of_universe u) ^ " ") "" c.eq in
112 let s_u = (string_of_universe c.u) in
113 "{ u:" ^ s_u ^ " ; gt:" ^ s_gt ^ " ; ge:" ^ s_ge ^ " ; eq: " ^ s_eq ^ "}"
115 (* print the content of map *)
117 MapUC.iter (fun u c ->
119 (" " ^ (string_of_universe u) ^ " -> " ^ (canonical_to_string c)))
123 (* ************************************************************************** *)
124 (* The way we fail *)
125 (* ************************************************************************** *)
126 (* we are doing bad *)
128 (*prerr_endline " ======= Universe Inconsistency =========";
130 prerr_endline (" " ^ s ^ "\n");
133 (* ************************************************************************** *)
135 (* ************************************************************************** *)
138 (* the canonical representer of the [u] equaliti class *)
143 Not_found -> error ("map inconsistency, unbound " ^ (string_of_universe u))
145 (* all the nodes we can ifer in the ge list of u *)
147 let repr_u = repr u in
148 let rec close_ge_aux tofollow bag =
151 | v::tl -> let repr_v = repr v in
152 if List.mem repr_v bag then (* avoid loops *)
153 (close_ge_aux tl bag )
155 (close_ge_aux (tl @ repr_v.ge) (repr_v::bag))
156 (* we assume that v==u -> v \notin (repr u).ge *)
158 close_ge_aux repr_u.ge []
160 (* all the nodes we can ifer in the gt list of u,
161 we must follow bot gt and ge arcs, but we must put in bag only
162 the nodes that have a gt in theys path
165 let repr_u = repr u in
166 let rec close_gt_aux bag todo inspected =
167 (*print_all bag todo;Unix.sleep 1;*)
170 | [],p::may -> let repr_p = repr p in
171 if List.mem repr_p.u inspected then (* avoid loops *)
172 close_gt_aux bag ([],may) inspected
174 close_gt_aux bag (repr_p.gt,repr_p.ge @ may)
175 (repr_p.u::inspected)
176 | s::secure,may -> let repr_s = repr s in
177 if List.mem repr_s.u inspected then (* avoid loops *)
178 if List.mem repr_s bag then
179 close_gt_aux bag (secure,may) inspected
181 (* even if we ave already inspected the node, now
182 it is in the secure list so we want it in the bag
184 close_gt_aux (repr_s::bag) (secure,may) inspected
186 close_gt_aux ((repr_s)::bag)
187 (repr_s.gt @ repr_s.ge,may) (repr_s.u::inspected)
189 close_gt_aux [] (repr_u.gt,repr_u.ge) []
191 (* when we add an eq we have to change the mapping of u to c*)
193 let repr_u = repr u in
194 List.iter (fun u' -> if u <> u' then map := MapUC.remove u' !map) repr_u.eq;
195 List.iter (fun u' -> map := MapUC.add u' c !map) repr_u.eq
197 (* we suspect that u and v are connected by a == implyed by two >= *)
198 let rec collapse u v =
199 let repr_u = repr u in
200 let repr_v = repr v in
201 let ge_v = close_ge v in
202 let ge_u = close_ge u in
203 if List.mem repr_u ge_v && List.mem repr_v ge_u then
206 (* we have to add u == v *)
208 let repr_u = repr u in
209 let repr_v = repr v in
210 (* if we already have u == v then do nothing *)
211 if repr_u = repr_v then
214 (* if we already have v > u then fail *)
215 let gt_v = close_gt v in
216 if List.mem repr_u gt_v then
217 error ("Asking for " ^ (string_of_universe u) ^ " == " ^
218 (string_of_universe v) ^ " but " ^
219 (string_of_universe v) ^ " > " ^ (string_of_universe u))
221 (* if we already have u > v then fail *)
222 let gt_u = close_gt u in
223 if List.mem repr_v gt_u then
224 error ("Asking for " ^ (string_of_universe u) ^ " == " ^
225 (string_of_universe v) ^ " but " ^
226 (string_of_universe u) ^ " > " ^ (string_of_universe v))
228 (* add the inherited > constraints *)
229 List.iter (fun v -> add_gt u v ) (*gt_v*) repr_v.gt;
230 (* add the inherited >= constraints *)
231 (* close_ge assumes that v==u -> v \notin (repr u).ge *)
232 repr_u.ge <- List.filter (fun x -> x <> u && x <> v)
233 (repr_v.ge @ repr_u.ge);
234 (* mege the eq list, we assume they are disjuncted *)
235 repr_u.eq <- repr_u.eq @ repr_v.eq;
236 (* we have to remap all node represented by repr_v to repr_u *)
238 (* FIXME: not sure this is what we have to do
239 think more to the list of suspected cicles
241 List.iter (fun x -> collapse u x) repr_u.ge
243 (* we have to add u >= v *)
245 let repr_u = repr u in
246 let repr_v = repr v in
247 (* if we already have u == v then do nothing *)
248 if repr_u = repr_v then
251 (* if we already have v > u then fail *)
252 let gt = close_gt v in
253 if List.memq repr_u gt then
254 error ("Asking for " ^ (string_of_universe u) ^ " >= " ^
255 (string_of_universe v) ^ " but " ^
256 (string_of_universe v) ^ " > " ^ (string_of_universe u))
258 (* it is now safe to add u >= v *)
259 repr_u.ge <- v::repr_u.ge;
260 (* but we may have introduced a cicle *)
261 collapse u v (* FIXME: not sure it is from u to v, think more. *)
263 (* we have to add u > v *)
265 let repr_u = repr u in
266 let repr_v = repr v in
267 (* if we already have u == v then fail *)
268 if repr_u = repr_v then
269 error ("Asking for " ^ (string_of_universe u) ^ " > " ^
270 (string_of_universe v) ^ " but " ^
271 (string_of_universe u) ^ " == " ^ (string_of_universe v))
273 (* if we already have u > v do nothing *)
274 let gt_u = close_gt u in
275 if List.memq repr_v gt_u then
278 (* if we already have v > u then fail *)
279 let gt = close_gt v in
280 if List.memq repr_u gt then
281 error ("Asking for " ^ (string_of_universe u) ^ " > " ^
282 (string_of_universe v) ^ " but " ^
283 (string_of_universe v) ^ " > " ^ (string_of_universe u))
285 (* if we already have v >= u then fail *)
286 let ge = close_ge v in
287 if List.memq repr_u ge then
288 error ("Asking for " ^ (string_of_universe u) ^ " > " ^
289 (string_of_universe v) ^ " but " ^
290 (string_of_universe v) ^ " >= " ^ (string_of_universe u))
292 (* it is safe to add u > v *)
293 repr_u.gt <- v::repr_u.gt
315 (* ************************************************************************** *)
317 (* ************************************************************************** *)
320 let check_status_eq l =
321 let s = List.fold_left (fun s u -> s^(string_of_universe u) ^ ";") "" l in
322 let repr_u = repr (List.hd l) in
323 let rec check_status_eq_aux c =
325 [] -> print_endline (" Result check_status_eq["^s^"] = OK");true
326 | u::tl -> if repr u != repr_u then
327 (print_endline (" Result check_status_eq["^s^"] = FAILED");
328 print_endline ((string_of_universe u) ^ " != " ^
329 (string_of_universe repr_u.u));
332 check_status_eq_aux tl
334 check_status_eq_aux (List.tl l)
337 (* ************************************************************************** *)
338 (* Fake implementation *)
339 (* ************************************************************************** *)
342 let add_ge u v = true
343 let add_gt u v = true
344 let add_eq u v = true