]> matita.cs.unibo.it Git - helm.git/blob - helm/ocaml/cic/cicUniv.ml
- implemented inductive type rendering
[helm.git] / helm / ocaml / cic / cicUniv.ml
1 (* Copyright (C) 2000, 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 (*****************************************************************************)
27 (*                                                                           *)
28 (*                               PROJECT HELM                                *)
29 (*                                                                           *)
30 (*                      Enrico Tassi <tassi@cs.unibo.it>                     *)
31 (*                                 23/04/2004                                *)
32 (*                                                                           *)
33 (* This module implements the aciclic graph of universes.                    *)
34 (*                                                                           *)
35 (*****************************************************************************)
36
37 (*****************************************************************************)
38 (** switch implementation                                                   **)
39 (*****************************************************************************)
40
41 let fast_implementation = ref false ;;
42
43 (*****************************************************************************)
44 (** open                                                                    **)
45 (*****************************************************************************)
46
47 open Printf
48
49 (*****************************************************************************)
50 (** Types and default values                                                **)
51 (*****************************************************************************)
52
53 type universe = int * UriManager.uri option 
54     
55 module UniverseType = struct
56   type t = universe
57   let compare = Pervasives.compare
58 end
59   
60 module SOF = Set.Make(UniverseType)
61   
62 type entry = {
63   eq_closure : SOF.t;
64   ge_closure : SOF.t;
65   gt_closure : SOF.t;
66   in_gegt_of   : SOF.t;
67   one_s_eq   : SOF.t;
68   one_s_ge   : SOF.t;
69   one_s_gt   : SOF.t;
70 }
71     
72 module MAL = Map.Make(UniverseType)
73   
74 type arc_type = GE | GT | EQ
75     
76 type bag = entry MAL.t 
77     
78 let empty_entry = {
79   eq_closure=SOF.empty;
80   ge_closure=SOF.empty;
81   gt_closure=SOF.empty;
82   in_gegt_of=SOF.empty;
83   one_s_eq=SOF.empty;
84   one_s_ge=SOF.empty;
85   one_s_gt=SOF.empty;
86 }
87 let empty_bag = MAL.empty
88
89 let are_set_eq s1 s2 = 
90   SOF.equal s1 s2
91
92 let are_entry_eq v1 v2 =
93   (are_set_eq v1.gt_closure v2.gt_closure ) &&
94   (are_set_eq v1.ge_closure v2.ge_closure ) &&
95   (are_set_eq v1.eq_closure v2.eq_closure ) &&
96   (*(are_set_eq v1.in_gegt_of v2.in_gegt_of ) &&*)
97   (are_set_eq v1.one_s_ge v2.one_s_ge ) &&
98   (are_set_eq v1.one_s_gt v2.one_s_gt ) &&
99   (are_set_eq v1.one_s_eq v2.one_s_eq )
100
101
102 (* ocaml 3.07 doesn't have MAP.equal, 3.08 has it! *)
103 (*
104   let are_ugraph_eq308 g h =
105     MAL.equal are_entry_eq g h
106 *)
107 let are_ugraph_eq307 g h = 
108   try
109     MAL.fold (
110       fun k v b -> 
111         if not b then 
112           raise (Failure "Different") 
113         else
114           try
115             let k_h = MAL.find k h in
116             are_entry_eq v k_h
117           with Not_found -> true
118         ) g true
119     with 
120       Failure "Different" -> false
121
122 let are_ugraph_eq = are_ugraph_eq307
123
124 (*****************************************************************************)
125 (** Pretty printings                                                        **)
126 (*****************************************************************************)
127
128 let string_of_universe (i,u) = 
129   match u with
130       Some u ->
131         ((string_of_int i) ^ " " ^ (UriManager.string_of_uri u))
132     | None -> (string_of_int i)
133
134 let string_of_universe_set l = 
135   SOF.fold (fun x s -> s ^ (string_of_universe x) ^ " ") l ""
136
137 let string_of_node n =
138   "{"^
139   "eq_c: " ^ (string_of_universe_set n.eq_closure) ^ "; " ^ 
140   "ge_c: " ^ (string_of_universe_set n.ge_closure) ^ "; " ^ 
141   "gt_c: " ^ (string_of_universe_set n.gt_closure) ^ "; " ^ 
142   "i_gegt: " ^ (string_of_universe_set n.in_gegt_of) ^ "}\n"
143
144 let string_of_arc (a,u,v) = 
145   "(" ^ (string_of_universe u) ^ " " ^ a ^ " " ^ (string_of_universe v) ^ ")"
146   
147 let string_of_mal m =
148   let rc = ref "" in
149   MAL.iter (fun k v ->  
150     rc := !rc ^ sprintf "%s --> %s" (string_of_universe k) 
151               (string_of_node v)) m;
152   !rc
153
154 let string_of_bag b = 
155   string_of_mal b
156
157 (*****************************************************************************)
158 (** Helpers                                                                 **)
159 (*****************************************************************************)
160
161 (* find the repr *)
162 let repr u m =
163   try 
164     MAL.find u m
165   with
166     Not_found -> empty_entry
167     
168 (* FIXME: May be faster if we make it by hand *)
169 let merge_closures f nodes m =  
170   SOF.fold (fun x i -> SOF.union (f (repr x m)) i ) nodes SOF.empty
171
172 (*****************************************************************************)
173 (** Benchmarking                                                            **)
174 (*****************************************************************************)
175 let time_spent = ref 0.0;;
176 let partial = ref 0.0 ;;
177
178 let reset_spent_time () = time_spent := 0.0;;
179 let get_spent_time () = !time_spent ;;
180 let begin_spending () =
181   assert (!partial = 0.0);
182   partial := Unix.gettimeofday ()
183 ;;
184
185 let end_spending () =
186   assert (!partial > 0.0);
187   let interval = (Unix.gettimeofday ()) -. !partial in
188     partial := 0.0;
189     time_spent := !time_spent +. interval
190 ;;
191   
192 \f
193 (*****************************************************************************)
194 (** _fats implementation                                                    **)
195 (*****************************************************************************)
196
197 let rec closure_of_fast ru m =
198   let eq_c = closure_eq_fast ru m in
199   let ge_c = closure_ge_fast ru m in
200   let gt_c = closure_gt_fast ru m in
201     {
202       eq_closure = eq_c;
203       ge_closure = ge_c;
204       gt_closure = gt_c;
205       in_gegt_of = ru.in_gegt_of;
206       one_s_eq = ru.one_s_eq;
207       one_s_ge = ru.one_s_ge;
208       one_s_gt = ru.one_s_gt
209     }
210       
211 and closure_eq_fast ru m = 
212   let eq_c =
213     let j = ru.one_s_eq in
214     let _Uj = merge_closures (fun x -> x.eq_closure) j m in
215     let one_step_eq = ru.one_s_eq in
216       (SOF.union one_step_eq _Uj)
217   in
218     eq_c
219       
220 and closure_ge_fast ru m =
221   let ge_c = 
222     let j = SOF.union ru.one_s_ge (SOF.union ru.one_s_gt ru.one_s_eq) in
223     let _Uj = merge_closures (fun x -> x.ge_closure) j m in
224     let _Ux = j in
225       (SOF.union _Uj _Ux)
226   in
227     ge_c
228       
229 and closure_gt_fast ru m =
230   let gt_c =
231     let j = ru.one_s_gt in
232     let k = ru.one_s_ge in
233     let l = ru.one_s_eq in
234     let _Uj = merge_closures (fun x -> x.ge_closure) j m in
235     let _Uk = merge_closures (fun x -> x.gt_closure) k m in
236     let _Ul = merge_closures (fun x -> x.gt_closure) l m in
237     let one_step_gt = ru.one_s_gt in
238       (SOF.union (SOF.union (SOF.union _Ul one_step_gt) _Uk) _Uj)
239   in
240     gt_c
241       
242 and print_rec_status u ru =
243   print_endline ("Aggiusto " ^ (string_of_universe u) ^ 
244                  "e ottengo questa chiusura\n " ^ (string_of_node ru))
245
246 and adjust_fast u m =
247   let ru = repr u m in
248   let gt_c = closure_gt_fast ru m in
249   let ge_c = closure_ge_fast ru m in
250   let eq_c = closure_eq_fast ru m in
251   let changed_eq = not (are_set_eq eq_c ru.eq_closure) in
252   let changed_gegt = 
253     (not (are_set_eq gt_c ru.gt_closure)) || 
254     (not (are_set_eq ge_c ru.ge_closure))
255   in
256     if ((not changed_gegt) &&  (not changed_eq)) then
257       m
258     else
259       begin
260         let ru' = {
261           eq_closure = eq_c;
262           ge_closure = ge_c;
263           gt_closure = gt_c;
264           in_gegt_of = ru.in_gegt_of;
265           one_s_eq = ru.one_s_eq;
266           one_s_ge = ru.one_s_ge;
267           one_s_gt = ru.one_s_gt}
268         in
269         let m = MAL.add u ru' m in
270         let m =
271             SOF.fold (fun x m -> adjust_fast  x m) 
272               (SOF.union ru'.eq_closure ru'.in_gegt_of) m
273               (* TESI: 
274                    ru'.in_gegt_of m 
275               *)
276         in
277           m (*adjust_fast  u m*)
278       end
279         
280 and add_gt_arc_fast u v m =
281   let ru = repr u m in
282   let ru' = {ru with one_s_gt = SOF.add v ru.one_s_gt} in
283   let m' = MAL.add u ru' m in
284   let rv = repr v m' in
285   let rv' = {rv with in_gegt_of = SOF.add u rv.in_gegt_of} in
286   let m'' = MAL.add v rv' m' in
287     adjust_fast u m''
288       
289 and add_ge_arc_fast u v m =
290   let ru = repr u m in
291   let ru' = { ru with one_s_ge = SOF.add v ru.one_s_ge} in
292   let m' = MAL.add u ru' m in
293   let rv = repr v m' in
294   let rv' = {rv with in_gegt_of = SOF.add u rv.in_gegt_of} in
295   let m'' = MAL.add v rv' m' in
296     adjust_fast u m''
297
298 and add_eq_arc_fast u v m =
299   let ru = repr u m in
300   let rv = repr v m in 
301   let ru' = {ru  with one_s_eq = SOF.add v ru.one_s_eq} in
302   (*TESI: let ru' = {ru' with in_gegt_of = SOF.add v ru.in_gegt_of} in *)
303   let m' = MAL.add u ru' m in
304   let rv' = {rv  with one_s_eq = SOF.add u rv.one_s_eq} in
305   (*TESI: let rv' = {rv' with in_gegt_of = SOF.add u rv.in_gegt_of} in *)
306   let m'' = MAL.add v rv' m' in
307     adjust_fast v (*(adjust_fast u*) m'' (* ) *)
308 ;;
309
310 \f
311 (*****************************************************************************)
312 (** safe implementation                                                     **)
313 (*****************************************************************************)
314
315 let closure_of u m =
316   let ru = repr u m in
317   let eq_c =
318     let j = ru.one_s_eq in
319     let _Uj = merge_closures (fun x -> x.eq_closure) j m in
320     let one_step_eq = ru.one_s_eq in
321             (SOF.union one_step_eq _Uj)
322   in
323   let ge_c = 
324     let j = SOF.union ru.one_s_ge (SOF.union ru.one_s_gt ru.one_s_eq) in
325     let _Uj = merge_closures (fun x -> x.ge_closure) j m in
326     let _Ux = j in
327       (SOF.union _Uj _Ux)
328   in
329   let gt_c =
330     let j = ru.one_s_gt in
331     let k = ru.one_s_ge in
332     let l = ru.one_s_eq in
333     let _Uj = merge_closures (fun x -> x.ge_closure) j m in
334     let _Uk = merge_closures (fun x -> x.gt_closure) k m in
335     let _Ul = merge_closures (fun x -> x.gt_closure) l m in
336     let one_step_gt = ru.one_s_gt in
337       (SOF.union (SOF.union (SOF.union _Ul one_step_gt) _Uk) _Uj)
338   in
339     {
340       eq_closure = eq_c;
341       ge_closure = ge_c;
342       gt_closure = gt_c;
343       in_gegt_of = ru.in_gegt_of;
344       one_s_eq = ru.one_s_eq;
345       one_s_ge = ru.one_s_ge;
346       one_s_gt = ru.one_s_gt
347     }
348
349 let rec simple_adjust m =
350   let m' = 
351     MAL.mapi (fun x _ -> closure_of x m) m
352   in
353     if not (are_ugraph_eq m  m') then(
354       simple_adjust m')
355     else
356       m'
357
358 let add_eq_arc u v m =
359   let ru = repr u m in
360   let rv = repr v m in
361   let ru' = {ru with one_s_eq = SOF.add v ru.one_s_eq} in
362   let m' = MAL.add u ru' m in
363   let rv' = {rv with one_s_eq = SOF.add u rv.one_s_eq} in
364   let m'' = MAL.add v rv' m' in
365     simple_adjust m''
366
367 let add_ge_arc u v m =
368   let ru = repr u m in
369   let ru' = { ru with one_s_ge = SOF.add v ru.one_s_ge} in
370   let m' = MAL.add u ru' m in
371     simple_adjust m'
372
373 let add_gt_arc u v m =
374   let ru = repr u m in
375   let ru' = {ru with one_s_gt = SOF.add v ru.one_s_gt} in
376   let m' = MAL.add u ru' m in
377     simple_adjust m'
378
379 \f
380 (*****************************************************************************)
381 (** Outhern interface, that chooses between _fast and safe                  **)
382 (*****************************************************************************)
383
384 (*                                                                            
385     given the 2 nodes plus the current bag, adds the arc, recomputes the 
386     closures and returns the new map
387 *) 
388 let add_eq fast u v b =
389   if fast then
390     add_eq_arc_fast u v b
391   else
392     add_eq_arc u v b
393
394 (*                                                                            
395     given the 2 nodes plus the current bag, adds the arc, recomputes the 
396     closures and returns the new map
397 *) 
398 let add_ge fast u v b =
399   if fast then
400     add_ge_arc_fast u v b
401   else
402     add_ge_arc u v b
403 (*                                                                            
404     given the 2 nodes plus the current bag, adds the arc, recomputes the 
405     closures and returns the new map
406 *)                                                                            
407 let add_gt fast u v b =
408   if fast then
409     add_gt_arc_fast u v b
410   else
411     add_gt_arc u v b
412
413
414 (*****************************************************************************)
415 (** Other real code                                                         **)
416 (*****************************************************************************)
417
418 exception UniverseInconsistency of string 
419
420 let error arc node1 closure_type node2 closure =
421   let s = "\n  ===== Universe Inconsistency detected =====\n\n" ^
422    "\tUnable to add "^ (string_of_arc arc) ^ " cause " ^ 
423    (string_of_universe node1) ^ " is in the " ^
424    closure_type ^ " closure {" ^
425    (string_of_universe_set closure) ^ "} of " ^ 
426    (string_of_universe node2) ^ "\n\n" ^
427    "  ===== Universe Inconsistency detected =====\n" in
428   prerr_endline s;
429   raise (UniverseInconsistency s)
430
431
432 let fill_empty_nodes_with_uri g uri =
433   let fill_empty_universe u =
434     match u with
435         (i,None) -> (i,Some uri)
436       | (i,Some _) as u -> u
437   in
438   let fill_empty_set s =
439     SOF.fold (fun e s -> SOF.add (fill_empty_universe e) s) s SOF.empty 
440   in
441   let fill_empty_entry e = {
442     eq_closure = (fill_empty_set e.eq_closure) ;
443     ge_closure = (fill_empty_set e.ge_closure) ;
444     gt_closure = (fill_empty_set e.gt_closure) ;
445     in_gegt_of = (fill_empty_set e.in_gegt_of) ;
446     one_s_eq = (fill_empty_set e.one_s_eq) ;
447     one_s_ge = (fill_empty_set e.one_s_ge) ;
448     one_s_gt = (fill_empty_set e.one_s_gt) ;
449   } in  
450   let m = g in
451   let m' = MAL.fold (
452     fun k v m -> 
453       MAL.add (fill_empty_universe k) (fill_empty_entry v) m) m MAL.empty
454   in
455     m'
456
457
458 (*****************************************************************************)
459 (** World interface                                                         **)
460 (*****************************************************************************)
461
462 type universe_graph = bag
463
464 let empty_ugraph = empty_bag
465
466 let current_index = ref (-1)
467
468 let restart_numbering () = current_index := (-1) 
469
470 let fresh () =
471   current_index := !current_index + 1;
472   (!current_index,None)
473
474 let print_ugraph g = 
475   prerr_endline (string_of_bag g)
476
477 let add_eq ?(fast=(!fast_implementation)) u v b =
478   (* should we check to no add twice the same?? *)
479   let m = b in
480   let ru = repr u m in
481   if SOF.mem v ru.gt_closure then
482     error ("EQ",u,v) v "GT" u ru.gt_closure
483   else
484     begin
485     let rv = repr v m in
486     if SOF.mem u rv.gt_closure then
487       error ("EQ",u,v) u "GT" v rv.gt_closure
488     else
489       add_eq fast u v b
490     end
491
492 let add_ge ?(fast=(!fast_implementation)) u v b =
493   (* should we check to no add twice the same?? *)
494   let m = b in
495   let rv = repr v m in
496   if SOF.mem u rv.gt_closure then
497     error ("GE",u,v) u "GT" v rv.gt_closure
498   else
499     add_ge fast u v b
500   
501 let add_gt ?(fast=(!fast_implementation)) u v b =
502   (* should we check to no add twice the same?? *)
503   (* 
504      FIXME : check the thesis... no need to check GT and EQ closure since the 
505      GE is a superset of both 
506   *)
507   let m = b in
508   let rv = repr v m in
509
510   if u = v then
511     error ("GT",u,v) u "==" v SOF.empty
512   else
513   
514   (*if SOF.mem u rv.gt_closure then
515     error ("GT",u,v) u "GT" v rv.gt_closure
516   else
517     begin*)
518       if SOF.mem u rv.ge_closure then
519         error ("GT",u,v) u "GE" v rv.ge_closure
520       else
521 (*        begin
522           if SOF.mem u rv.eq_closure then
523             error ("GT",u,v) u "EQ" v rv.eq_closure
524           else*)
525             add_gt fast u v b
526 (*      end
527     end*)
528
529 (*****************************************************************************)
530 (** START: Decomment this for performance comparisons                       **)
531 (*****************************************************************************)
532
533 let add_eq ?(fast=(!fast_implementation))  u v b =
534   begin_spending ();
535   let rc = add_eq ~fast u v b in
536     end_spending();
537     rc
538
539 let add_ge ?(fast=(!fast_implementation)) u v b =
540   begin_spending ();
541   let rc = add_ge ~fast u v b in
542  end_spending();
543     rc
544     
545 let add_gt ?(fast=(!fast_implementation)) u v b =
546   begin_spending ();
547   let rc = add_gt ~fast u v b in
548     end_spending();
549     rc
550
551 (*****************************************************************************)
552 (** END: Decomment this for performance comparisons                         **)
553 (*****************************************************************************)
554
555 let merge_ugraphs u v =
556   (* this sucks *)
557   let merge_brutal u v =
558     if u = empty_bag then v 
559     else if v = empty_bag then u 
560     else
561       let m1 = u in 
562       let m2 = v in 
563         MAL.fold (
564           fun k v x -> 
565             (SOF.fold (
566                fun u x -> 
567                  let m = add_gt k u x in m) v.one_s_gt 
568                (SOF.fold (
569                   fun u x -> 
570                     let m = add_ge k u x in m) v.one_s_ge
571                   (SOF.fold (
572                      fun u x -> 
573                        let m = add_eq k u x in m) v.one_s_eq x)))
574         ) m1 m2
575   in
576     merge_brutal u v
577
578
579 (*****************************************************************************)
580 (** Xml sesialization and parsing                                           **)
581 (*****************************************************************************)
582
583 let xml_of_set s =
584   let l = 
585     List.map (
586       function 
587           (i,Some u) -> 
588             Xml.xml_empty "node" [
589               None,"id",(string_of_int i) ;
590               None,"uri",(UriManager.string_of_uri u)]
591         | (_,None) -> 
592             raise (Failure "we can serialize only universes with uri")
593     ) (SOF.elements s) 
594   in
595     List.fold_left (fun s x -> [< s ; x >] ) [<>] l
596       
597 let xml_of_entry_content e =
598   let stream_of_field f name =
599     let eq_c = xml_of_set f in
600     if eq_c != [<>] then
601       Xml.xml_nempty name [] eq_c
602     else
603       [<>]
604   in
605   [<
606     (stream_of_field e.eq_closure "eq_closure");
607     (stream_of_field e.gt_closure "gt_closure");
608     (stream_of_field e.ge_closure "ge_closure");
609     (stream_of_field e.in_gegt_of "in_gegt_of");
610     (stream_of_field e.one_s_eq "one_s_eq");
611     (stream_of_field e.one_s_gt "one_s_gt");
612     (stream_of_field e.one_s_ge "one_s_ge")
613   >]
614
615 let xml_of_entry u e =
616   let (i,u') = u in
617   let u'' = 
618     match u' with 
619         Some x -> x 
620       | None -> 
621           raise (Failure "we can serialize only universes (entry) with uri")
622   in
623   let ent = Xml.xml_nempty "entry" [
624     None,"id",(string_of_int i) ; 
625     None,"uri",(UriManager.string_of_uri u'')] in
626   let content = xml_of_entry_content e in
627   ent content
628
629 let write_xml_of_ugraph filename m =
630     let o = open_out filename in
631     output_string o "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>\n";
632     Xml.pp_to_outchan (
633       Xml.xml_nempty "ugraph" [] (
634       MAL.fold (
635         fun k v s -> [< s ; (xml_of_entry k v) >])
636       m [<>])) o;
637     close_out o
638  
639 let rec clean_ugraph m f =
640   let m' = 
641     MAL.fold (fun k v x -> if (f k) then MAL.add k v x else x ) m MAL.empty in
642   let m'' =  MAL.fold (fun k v x -> 
643     let v' = {
644       eq_closure = SOF.filter f v.eq_closure;
645       ge_closure = SOF.filter f v.ge_closure;
646       gt_closure = SOF.filter f v.gt_closure;
647       in_gegt_of = SOF.filter f v.in_gegt_of;
648       one_s_eq = SOF.filter f v.one_s_eq;
649       one_s_ge = SOF.filter f v.one_s_ge;
650       one_s_gt = SOF.filter f v.one_s_gt
651     } in 
652     MAL.add k v' x ) m' MAL.empty in
653   let e_l = 
654     MAL.fold (fun k v l -> if v = empty_entry then k::l else l) m'' []
655   in
656     if e_l != [] then
657       clean_ugraph m'' (fun u -> (f u) && not (List.mem u e_l))
658     else
659       m''
660
661 let clean_ugraph g l =
662   clean_ugraph g (fun u -> List.mem u l)
663
664 open Pxp_types ;;
665
666 let assigner_of = 
667   function
668     "ge_closure" -> (fun e u->{e with ge_closure=SOF.add u e.ge_closure})
669   | "gt_closure" -> (fun e u->{e with gt_closure=SOF.add u e.gt_closure})
670   | "eq_closure" -> (fun e u->{e with eq_closure=SOF.add u e.eq_closure})
671   | "in_gegt_of"   -> (fun e u->{e with in_gegt_of  =SOF.add u e.in_gegt_of})
672   | "one_s_ge"   -> (fun e u->{e with one_s_ge  =SOF.add u e.one_s_ge})
673   | "one_s_gt"   -> (fun e u->{e with one_s_gt  =SOF.add u e.one_s_gt})
674   | "one_s_eq"   -> (fun e u->{e with one_s_eq  =SOF.add u e.one_s_eq})
675   | s -> raise (Failure ("unsupported tag " ^ s))
676 ;;
677
678 let cb_factory m = 
679   let current_node = ref (0,None) in
680   let current_entry = ref empty_entry in
681   let current_assign = ref (assigner_of "in_ge_of") in
682     function 
683       | E_error exn -> raise (Failure (Pxp_types.string_of_exn exn))
684       | E_start_tag ("entry",attlist,_,_) -> 
685           let id = List.assoc "id" attlist in      
686           let uri = List.assoc "uri" attlist in
687             current_node := (int_of_string id,Some (UriManager.uri_of_string uri))
688       | E_start_tag ("node",attlist,_,_) -> 
689           let id = int_of_string (List.assoc "id" attlist) in
690           let uri = List.assoc "uri" attlist in 
691             current_entry := !current_assign !current_entry 
692               (id,Some (UriManager.uri_of_string uri))
693       | E_start_tag (s,_,_,_) -> 
694           current_assign := assigner_of s
695       | E_end_tag ("entry",_) -> 
696           m := MAL.add !current_node !current_entry !m;
697           current_entry := empty_entry
698       | _ -> ()
699 ;; 
700
701 (* alternative implementation *)
702 let mapl = [
703   ("ge_closure",0);("gt_closure",1);("eq_closure",2);
704   ("in_gegt_of",  3);
705   ("one_s_ge",  4);("one_s_gt",  5);("one_s_eq",  6)]
706 ;;
707
708 let assigner_of' s = List.assoc s mapl ;;
709
710 let entry_of_array a = { 
711   ge_closure = a.(0); gt_closure = a.(1); eq_closure = a.(2);
712   in_gegt_of   = a.(3); 
713   one_s_ge   = a.(4); one_s_gt   = a.(5); one_s_eq   = a.(6)}
714 ;;
715
716 let cb_factory' m = 
717   let current_node = ref (0,None) in
718   let current_entry = Array.create 7 SOF.empty in
719   let current_assign = ref 0 in
720     function 
721       | E_error exn -> raise (Failure (Pxp_types.string_of_exn exn))
722       | E_start_tag ("entry",attlist,_,_) -> 
723            let id = List.assoc "id" attlist in      
724            let uri = List.assoc "uri" attlist in
725              current_node := (int_of_string id,Some (UriManager.uri_of_string uri))
726       | E_start_tag ("node",attlist,_,_) -> 
727           let id = int_of_string (List.assoc "id" attlist) in
728           let uri = List.assoc "uri" attlist in 
729             current_entry.(!current_assign) <- 
730             SOF.add (id,Some (UriManager.uri_of_string uri)) 
731               current_entry.(!current_assign) 
732       | E_start_tag (s,_,_,_) -> 
733           current_assign := assigner_of' s
734       | E_end_tag ("entry",_) -> 
735           m := MAL.add !current_node (entry_of_array current_entry) !m;
736           Array.fill current_entry 0 7 SOF.empty 
737       | _ -> ()
738 ;;
739
740      
741 let ugraph_of_xml filename =
742   let module PX = Pxp_ev_parser in
743   let module NE = Netconversion in 
744   let config = default_config in
745   let entry = `Entry_document [] in
746   let encoding = `Enc_iso88591 in
747   let source = from_file ~system_encoding:encoding filename in
748   let entity_manager = 
749     PX.create_entity_manager ~is_document:true config source in
750   let result = ref MAL.empty in
751   let cb = cb_factory result in
752 (*let cb = cb_factory' result in*)
753   PX.process_entity config entry entity_manager cb;
754   !result
755
756 \f
757 (*****************************************************************************)
758 (** the main, only for testing                                              **)
759 (*****************************************************************************)
760
761 (* 
762
763 type arc = Ge | Gt | Eq ;;
764
765 let randomize_actionlist n m =
766   let ge_percent = 0.7 in
767   let gt_percent = 0.15 in
768   let random_step () =
769     let node1 = Random.int m in
770     let node2 = Random.int m in
771     let op = 
772       let r = Random.float 1.0 in
773         if r < ge_percent then 
774           Ge 
775         else (if r < (ge_percent +. gt_percent) then 
776           Gt 
777         else 
778           Eq) 
779     in
780       op,node1,node2      
781   in
782   let rec aux n =
783     match n with 
784         0 -> []
785       | n -> (random_step ())::(aux (n-1))
786   in
787     aux n
788
789 let print_action_list l =
790   let string_of_step (op,node1,node2) =
791     (match op with
792          Ge -> "Ge"
793        | Gt -> "Gt"
794        | Eq -> "Eq") ^ 
795     "," ^ (string_of_int node1) ^ ","   ^ (string_of_int node2) 
796   in
797   let rec aux l =
798     match l with 
799         [] -> "]"
800       | a::tl ->
801           ";" ^ (string_of_step a) ^ (aux tl)
802   in
803   let body = aux l in
804   let l_body = (String.length body) - 1 in
805     prerr_endline ("[" ^ (String.sub body 1 l_body))
806   
807 let debug = false
808 let d_print_endline = if debug then print_endline else ignore 
809 let d_print_ugraph = if debug then print_ugraph else ignore
810
811 let _ = 
812   (if Array.length Sys.argv < 2 then
813     prerr_endline ("Usage " ^ Sys.argv.(0) ^ " max_edges max_nodes"));
814   Random.self_init ();
815   let max_edges = int_of_string Sys.argv.(1) in
816   let max_nodes = int_of_string Sys.argv.(2) in
817   let action_listR = randomize_actionlist max_edges max_nodes in
818
819   let action_list = [Ge,1,4;Ge,2,6;Ge,1,1;Eq,6,4;Gt,6,3] in
820   let action_list = action_listR in
821   
822   print_action_list action_list;
823   let prform_step ?(fast=false) (t,u,v) g =
824     let f,str = 
825       match t with
826           Ge -> add_ge,">="
827         | Gt -> add_gt,">"
828         | Eq -> add_eq,"="
829     in
830       d_print_endline (
831         "Aggiungo " ^ 
832         (string_of_int u) ^
833         " " ^ str ^ " " ^ 
834         (string_of_int v));
835       let g' = f ~fast (u,None) (v,None) g in
836         (*print_ugraph g' ;*)
837         g'
838   in
839   let fail = ref false in
840   let time1 = Unix.gettimeofday () in
841   let n_safe = ref 0 in
842   let g_safe =  
843     try 
844       d_print_endline "SAFE";
845       List.fold_left (
846         fun g e -> 
847           n_safe := !n_safe + 1;
848           prform_step e g
849       ) empty_ugraph action_list
850     with
851         UniverseInconsistency s -> fail:=true;empty_bag
852   in
853   let time2 = Unix.gettimeofday () in
854   d_print_ugraph g_safe;
855   let time3 = Unix.gettimeofday () in
856   let n_test = ref 0 in
857   let g_test = 
858     try
859       d_print_endline "FAST";
860       List.fold_left (
861         fun g e ->
862           n_test := !n_test + 1;
863           prform_step ~fast:true e g
864       ) empty_ugraph action_list
865     with
866         UniverseInconsistency s -> empty_bag
867   in
868   let time4 = Unix.gettimeofday () in
869   d_print_ugraph g_test;
870     if are_ugraph_eq g_safe g_test && !n_test = !n_safe then
871       begin
872         let num_eq = 
873           List.fold_left (
874             fun s (e,_,_) -> 
875               if e = Eq then s+1 else s 
876           ) 0 action_list 
877         in
878         let num_gt = 
879           List.fold_left (
880             fun s (e,_,_) ->
881               if e = Gt then s+1 else s
882           ) 0 action_list
883         in
884         let num_ge = max_edges - num_gt - num_eq in
885         let time_fast = (time4 -. time3) in
886         let time_safe = (time2 -. time1) in
887         let gap = ((time_safe -. time_fast) *. 100.0) /. time_safe in
888         let fail = if !fail then 1 else 0 in
889           print_endline 
890             (sprintf 
891                "OK %d safe %1.4f fast %1.4f %% %1.2f #eq %d #gt %d #ge %d %d" 
892                fail time_safe time_fast gap num_eq num_gt num_ge !n_safe);
893           exit 0
894       end
895     else
896       begin
897         print_endline "FAIL";
898         print_ugraph g_safe;
899         print_ugraph g_test;
900         exit 1
901       end
902 ;;
903
904  *)
905
906 (* EOF *)