1 (***********************************************************************)
5 (* Lucca Hirschi, LRI UMR8623 *)
6 (* Université Paris-Sud & CNRS *)
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 *)
14 (***********************************************************************)
24 module NodeHash = Hashtbl.Make (Node)
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 *)
31 exception Over_max_fail
34 (* Mapped sets for leaves *)
35 let map_leaf asta = (Asta.bot_states_s asta, StateSet.empty)
36 let empty = (StateSet.empty,StateSet.empty)
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
45 else NodeHash.add run node (map_leaf asta)
47 let tfnode = Tree.first_child tree tnode (* first child *)
48 and tnnode = Tree.next_sibling tree tnode in (* next-sibling *)
50 (Tree.preorder tree tfnode, Tree.preorder tree tnnode) in
52 bu_oracle asta run tree tfnode;
53 bu_oracle asta run tree tnnode;
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
63 if Formula.eval_form (qfr,qnr) form
64 then result (StateSet.add q set) tl
66 let result_set = result StateSet.empty list_tr in
67 NodeHash.add run node (StateSet.empty, result_set)
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 *)
76 let tfnode = Tree.first_child tree tnode
77 and tnnode = Tree.next_sibling tree tnode in
79 bu_over_max asta run tree tfnode;
80 bu_over_max asta run tree tnnode;
82 (Tree.preorder tree tfnode, Tree.preorder tree tnnode)
83 and node = Tree.preorder tree tnode in
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
93 if Formula.infer_form (qfq,qnq) (qfr,qnr) form
94 then result (StateSet.add q set) tl
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) *)
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 *)
110 let node = Tree.preorder tree tnode
111 and tfnode = Tree.first_child tree tnode
112 and tnnode = Tree.next_sibling tree tnode in
114 (Tree.preorder tree tfnode, Tree.preorder tree tnnode) in
116 if tnode == Tree.root tree (* we must intersectt with top states *)
117 then let setq,_ = try NodeHash.find run node
118 with _ -> raise Max_fail in
119 NodeHash.replace run node
120 ((StateSet.inter (Asta.top_states_s asta) setq),StateSet.empty)
123 try NodeHash.find run n
124 with Not_found -> map_leaf asta in
125 let (qfq,qfr),(qnq,qnr) = q_rec fnode,q_rec nnode in
126 let lab = Tree.tag tree tnode in
127 let list_tr,_ = Asta.transitions_lab asta lab in (* only take query. *)
128 let set_node,_ = try NodeHash.find run node
129 with _ -> raise Max_fail in
130 let rec result = function
133 if (Formula.infer_form (qfq,qnq) (qfr,qnr) form) &&
134 (StateSet.mem q set_node)
135 then form :: (result tl)
137 let list_form = result list_tr in
138 let rec add_st (ql,qr) = function
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
150 if tfnode == Tree.nil
152 else NodeHash.replace run fnode (StateSet.inter qfq ql,qfr);
153 if tnnode == Tree.nil
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;
161 let compute tree asta =
162 let flag = 2 in (* debug *)
163 let size_tree = 10000 in (* todo *)
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);
170 tp_max asta map tree (Tree.root tree)
176 let selected_nodes tree asta =
177 let run = compute tree asta in
180 if not(StateSet.is_empty
181 (StateSet.inter (fst set) (Asta.selec_states asta)))
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 "ø"
195 NodeHash.iter (fun cle set -> pp "| %i->%a @ " cle print_d_set set)
197 let print_box fmt run =
198 let pp = Format.fprintf fmt in
199 pp "@[<hov 0>@. # Mapping:@. @[<hov 0>%a@]@]"
202 Format.fprintf fmt "@[<hov 0>##### RUN #####@, %a@]@." print_box run