Commentaries
[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_s asta, StateSet.empty)
36
37 (* Build the Oracle *)
38 let rec bu_oracle asta run tree tnode =
39   let node = Tree.preorder tree tnode in
40   if Tree.is_leaf tree tnode
41   then
42     if tnode == Tree.nil
43     then ()
44     else NodeHash.add run node (map_leaf asta)
45   else
46     let tfnode = Tree.first_child tree tnode (* first child *)
47     and tnnode = Tree.next_sibling tree tnode in (* next-sibling *)
48     let fnode,nnode =                            (* their preorders *)
49       (Tree.preorder tree tfnode, Tree.preorder tree tnnode) in
50     begin
51       bu_oracle asta run tree tfnode;
52       bu_oracle asta run tree tnnode;
53       let q_rec n =                     (* compute the set for child/sibling *)
54         try NodeHash.find run n
55         with Not_found -> map_leaf asta in
56       let (_,qfr),(_,qnr) = q_rec fnode,q_rec nnode (* computed in rec call *)
57       and lab = Tree.tag tree tnode in
58       let _,list_tr = Asta.transitions_lab asta lab in (* only reco. tran.*)
59       let rec result set = function
60         | [] -> set
61         | (q,form) :: tl ->
62           if Formula.eval_form (qfr,qnr) form (* evaluates the formula *)
63           then result (StateSet.add q set) tl
64           else result set tl in
65       let result_set = result StateSet.empty list_tr in
66       NodeHash.add run node (StateSet.empty, result_set)
67     end
68
69 (* Build the over-approx. of the maximal run *)
70 let rec bu_over_max asta run tree tnode =
71   if (Tree.is_leaf tree tnode)      (* BU_oracle has already created the map *)
72   then
73     ()
74   else
75     let tfnode = Tree.first_child tree tnode
76     and tnnode = Tree.next_sibling tree tnode in
77     begin
78       bu_over_max asta run tree tfnode;
79       bu_over_max asta run tree tnnode;
80       let (fnode,nnode) =
81         (Tree.preorder tree tfnode, Tree.preorder tree tnnode)
82       and node = Tree.preorder tree tnode in          
83       let q_rec n =
84         try NodeHash.find run n
85         with Not_found -> map_leaf asta in
86       let (qfq,qfr),(qnq,qnr) = q_rec fnode,q_rec nnode in
87       let lab = Tree.tag tree tnode in
88       let list_tr,_ = Asta.transitions_lab asta lab in (* only take query st. *)
89       let rec result set = function
90         | [] -> set
91         | (q,form) :: tl ->
92           if Formula.infer_form (qfq,qnq) (qfr,qnr) form (* infers the formula*)
93           then result (StateSet.add q set) tl
94           else result set tl in
95       let _,resultr = try NodeHash.find run node
96         with _ -> raise Over_max_fail in      
97       let result_set = result StateSet.empty list_tr in
98       (* we keep the old recognizing states set *)
99       NodeHash.replace run node (result_set, resultr)
100     end
101
102
103 (* Build the maximal run *)
104 let rec tp_max asta run tree tnode =
105   if (Tree.is_leaf tree tnode)      (* BU_oracle has already created the map *)
106   then
107     ()
108   else
109     let node = Tree.preorder tree tnode
110     and tfnode = Tree.first_child tree tnode
111     and tnnode = Tree.next_sibling tree tnode in
112     let (fnode,nnode) =
113       (Tree.preorder tree tfnode, Tree.preorder tree tnnode) in
114     begin
115       if tnode == Tree.root tree        (* we must intersect with top states *)
116       then let setq,_  = try NodeHash.find run node
117         with _ -> raise Max_fail in
118            NodeHash.replace run node
119              ((StateSet.inter (Asta.top_states_s asta) setq),StateSet.empty)
120       else ();
121       let q_rec n =
122         try NodeHash.find run n
123         with Not_found -> map_leaf asta in
124       let (qfq,qfr),(qnq,qnr) = q_rec fnode,q_rec nnode in
125       let lab = Tree.tag tree tnode in
126       let list_tr,_ = Asta.transitions_lab asta lab in (* only take query. *)
127       let set_node,_ = try NodeHash.find run node
128         with _ -> raise Max_fail in
129       let rec result = function
130         | [] -> []
131         | (q,form) :: tl ->
132           if (Formula.infer_form (qfq,qnq) (qfr,qnr) form) &&
133             (StateSet.mem q set_node)   (* infers & trans. can start here *)
134           then form :: (result tl)
135           else result tl in
136       let list_form = result list_tr in (* tran. candidates *)
137       (* compute states occuring in transition candidates *)
138       let rec add_st (ql,qr) = function
139         | [] -> ql,qr
140         | f :: tl -> let sql,sqr = Formula.st f in
141                      let ql' = StateSet.union sql ql
142                      and qr' = StateSet.union sqr qr in
143                      add_st (ql',qr') tl in
144       let ql,qr = add_st (StateSet.empty, StateSet.empty) list_form in
145       let qfq,qfr = try NodeHash.find run fnode
146         with | _ -> map_leaf asta
147       and qnq,qnr = try NodeHash.find run nnode
148         with | _ -> map_leaf asta in
149       begin
150         if tfnode == Tree.nil
151         then ()
152         else NodeHash.replace run fnode (StateSet.inter qfq ql,qfr);
153         if tnnode == Tree.nil
154         then ()
155         else NodeHash.replace run nnode (StateSet.inter qnq qr,qnr);
156         tp_max asta run tree tfnode;
157         tp_max asta run tree tnnode;
158       end;
159     end
160         
161 let compute tree asta =
162   let flag = 2 in                       (* debug  *)
163   let size_tree = 10000 in              (* todo (Tree.size ?) *)
164   let map = NodeHash.create size_tree in
165   bu_oracle asta map tree (Tree.root tree);
166   if flag > 0 then begin
167     bu_over_max asta map tree (Tree.root tree);
168     if flag = 2
169     then
170       tp_max asta map tree (Tree.root tree)
171     else ()
172   end
173   else ();
174   map
175
176 let selected_nodes tree asta =
177   let run = compute tree asta in
178   NodeHash.fold
179     (fun key set acc ->
180       if not(StateSet.is_empty
181                (StateSet.inter (fst set) (Asta.selec_states asta)))        
182       then key :: acc
183       else acc)
184     run []
185
186 let print fmt run =
187   let print_d_set fmt (s_1,s_2) =
188     Format.fprintf fmt "(%a,%a)"
189       StateSet.print s_1 StateSet.print s_2 in
190   let print_map fmt run =
191     let pp = Format.fprintf fmt in
192     if NodeHash.length run = 0
193     then Format.fprintf fmt "ø"
194     else
195       NodeHash.iter (fun cle set -> pp "|  %i->%a  @ " cle print_d_set set)
196         run in
197   let print_box fmt run =
198     let pp = Format.fprintf fmt in
199     pp "@[<hov 0>@.  # Mapping:@.   @[<hov 0>%a@]@]"
200       print_map run
201   in
202   Format.fprintf fmt "@[<hov 0>##### RUN #####@, %a@]@." print_box run