Full implem of BU_over_Max and TP_max (to be tested) + my.xml from thesis + stuffs...
[tatoo.git] / src / run.ml
1 (***********************************************************************)
2 (*                                                                     *)
3 (*                               TAToo                                 *)
4 (*                                                                     *)
5 (*                   Lucca Hirschi, LRI UMR8623                        *)
6 (*                   Université Paris-Sud & CNRS                       *)
7 (*                                                                     *)
8 (*  Copyright 2010-2012 Université Paris-Sud and Centre National de la *)
9 (*  Recherche Scientifique. All rights reserved.  This file is         *)
10 (*  distributed under the terms of the GNU Lesser General Public       *)
11 (*  License, with the special exception on linking described in file   *)
12 (*  ../LICENSE.                                                        *)
13 (*                                                                     *)
14 (***********************************************************************)
15
16 module Node  =
17 struct
18   type t = int
19   let hash n = n
20   let compare = (-)
21   let equal = (=)
22 end
23   
24 module NodeHash = Hashtbl.Make (Node)
25   
26 type t = (StateSet.t*StateSet.t) NodeHash.t
27 (** Map from nodes to query and recognizing states *)
28 (* Note that we do not consider the nil nodes *)
29
30 exception Oracle_fail
31 exception Over_max_fail
32 exception Max_fail
33
34 (* Mapped sets for leaves *)
35 let map_leaf asta = (Asta.bot_states asta, StateSet.empty)
36 let empty = (StateSet.empty,StateSet.empty)
37
38 (* Build the Oracle *)
39 let rec bu_oracle asta run tree tnode =
40   let node = Tree.preorder tree tnode in
41   if Tree.is_leaf tree tnode
42   then
43     if tnode == Tree.nil
44     then ()
45     else NodeHash.add run node (map_leaf asta)
46   else
47     let tfnode = Tree.first_child tree tnode (* first child *)
48     and tnnode = Tree.next_sibling tree tnode in (* next-sibling *)
49     let fnode,nnode =
50       (Tree.preorder tree tfnode, Tree.preorder tree tnnode) in
51     begin
52       bu_oracle asta run tree tfnode;
53       bu_oracle asta run tree tnnode;
54       let q_rec n =
55         try NodeHash.find run n
56         with Not_found -> map_leaf asta in
57       let (_,qfr),(_,qnr) = q_rec fnode,q_rec nnode (* computed in rec call *)
58       and lab = Tree.tag tree tnode in
59       let _,list_tr = Asta.transitions_lab asta lab in (* only take reco. *)
60       let rec result set = function
61         | [] -> set
62         | (q,form) :: tl ->
63           if Formula.eval_form (qfr,qnr) form
64           then result (StateSet.add q set) tl
65           else result set tl in
66       let result_set = result StateSet.empty list_tr in
67       NodeHash.add run node (StateSet.empty, result_set)
68     end
69
70 (* Build the over-approx. of the maximal run *)
71 let rec bu_over_max asta run tree tnode =
72   if (Tree.is_leaf tree tnode)      (* BU_oracle has already created the map *)
73   then
74     ()
75   else
76     let tfnode = Tree.first_child tree tnode
77     and tnnode = Tree.next_sibling tree tnode in
78     begin
79       bu_over_max asta run tree tfnode;
80       bu_over_max asta run tree tnnode;
81       let (fnode,nnode) =
82         (Tree.preorder tree tfnode, Tree.preorder tree tnnode)
83       and node = Tree.preorder tree tnode in          
84       let q_rec n =
85         try NodeHash.find run n
86         with Not_found -> map_leaf asta in
87       let (qfq,qfr),(qnq,qnr) = q_rec fnode,q_rec nnode in
88       let lab = Tree.tag tree tnode in
89       let list_tr,_ = Asta.transitions_lab asta lab in (* only take query st. *)
90       let rec result set = function
91         | [] -> set
92         | (q,form) :: tl ->
93           if Formula.infer_form (qfq,qnq) (qfr,qnr) form
94           then result (StateSet.add q set) tl
95           else result set tl in
96       let _,resultr = try NodeHash.find run node
97         with _ -> raise Over_max_fail in      
98       let result_set = result StateSet.empty list_tr in
99       NodeHash.replace run node (result_set, resultr)
100     (* Never remove elt in Hash (the old one would appear) *)
101     end
102
103
104 (* Build the maximal run *)
105 let rec tp_max asta run tree tnode =
106   if (Tree.is_leaf tree tnode)      (* BU_oracle has already created the map *)
107   then
108     ()
109   else
110     let node = Tree.preorder tree tnode
111     and tfnode = Tree.first_child tree tnode
112     and tnnode = Tree.next_sibling tree tnode in
113     let (fnode,nnode) =
114       (Tree.preorder tree tfnode, Tree.preorder tree tnnode) in
115     let q_rec n =
116       try NodeHash.find run n
117       with Not_found -> (Asta.bot_states asta,StateSet.empty) in
118     let (qf),(qn) = q_rec fnode,q_rec nnode in
119     let lab = Tree.tag tree tnode in
120     let list_tr,_ = Asta.transitions_lab asta lab in (* only take query. *)
121     let set_node,_ = try NodeHash.find run node
122       with _ -> raise Max_fail in
123     let rec result = function
124       | [] -> []
125       | (q,form) :: tl ->
126         if (Formula.infer_form qf qn form) && (StateSet.mem q set_node)
127         then form :: (result tl)
128         else result tl in
129     let list_form = result list_tr in
130     let rec add_st (ql,qr) = function
131       | [] -> ql,qr
132       | f :: tl -> let sql,sqr = Formula.st f in
133                    let ql' = StateSet.union sql ql
134                    and qr' = StateSet.union sqr qr in
135                    add_st (ql',qr') tl in
136     let ql,qr = add_st (StateSet.empty, StateSet.empty) list_form in
137     let qfq,qfr = try NodeHash.find run fnode
138       with | _ -> map_leaf asta
139     and qnq,qnr = try NodeHash.find run nnode
140       with | _ -> map_leaf asta in
141     begin
142       if Tree.is_leaf tree tfnode
143       then ()
144       else NodeHash.replace run fnode (StateSet.inter qfq ql,qfr);
145       if Tree.is_leaf tree tnnode
146       then ()
147       else NodeHash.replace run nnode (StateSet.inter qnq qr,qnr);
148       tp_max asta run tree tfnode;
149       tp_max asta run tree tnnode;
150     end
151
152 let compute tree asta =
153   let flag = 2 in                       (* debug  *)
154   let size_tree = 10000 in              (* todo *)
155   let map = NodeHash.create size_tree in
156   bu_oracle asta map tree (Tree.root tree);
157   if flag > 0 then begin
158     bu_over_max asta map tree (Tree.root tree);
159     if flag = 2
160     then
161       tp_max asta map tree (Tree.root tree)
162     else ()
163   end
164   else ();
165   map
166
167 let selected_nodes tree asta =
168   let run = compute tree asta in
169   NodeHash.fold
170     (fun key set acc ->
171       if not(StateSet.is_empty
172                (StateSet.inter (fst set) (Asta.selec_states asta)))        
173       then key :: acc
174       else acc)
175     run []
176
177 let print fmt run =
178   let print_d_set fmt (s_1,s_2) =
179     Format.fprintf fmt "(%a,%a)"
180       StateSet.print s_1 StateSet.print s_2 in
181   let print_map fmt run =
182     let pp = Format.fprintf fmt in
183     if NodeHash.length run = 0
184     then Format.fprintf fmt "ø"
185     else
186       NodeHash.iter (fun cle set -> pp "|  %i->%a  @ " cle print_d_set set)
187         run in
188   let print_box fmt run =
189     let pp = Format.fprintf fmt in
190     pp "@[<hov 0>@.  # Mapping:@.   @[<hov 0>%a@]@]"
191       print_map run
192   in
193   Format.fprintf fmt "@[<hov 0>##### RUN #####@, %a@]@." print_box run