59ebc03e8783f7f25ad6aa0f1cd816e103a1069a
[tatoo.git] / src / eval.ml
1 (***********************************************************************)
2 (*                                                                     *)
3 (*                               TAToo                                 *)
4 (*                                                                     *)
5 (*                     Kim Nguyen, LRI UMR8623                         *)
6 (*                   Université Paris-Sud & CNRS                       *)
7 (*                                                                     *)
8 (*  Copyright 2010-2013 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 (*
17   Time-stamp: <Last modified on 2013-04-19 01:13:47 CEST by Kim Nguyen>
18 *)
19
20 INCLUDE "utils.ml"
21 open Format
22
23 module Make (T : Tree.S) :
24   sig
25     val eval : Ata.t -> T.t -> T.node -> T.node list
26   end
27  = struct
28
29
30 IFDEF HTMLTRACE
31   THEN
32 DEFINE TRACE(e) = (e)
33   ELSE
34 DEFINE TRACE(e) = ()
35 END
36
37
38
39   type cache = StateSet.t Cache.N1.t
40   let get c t n = Cache.N1.find c (T.preorder t n)
41
42   let set c t n v = Cache.N1.add c (T.preorder t n) v
43
44
45   let top_down_run auto tree node cache _i =
46     let redo = ref false in
47     let rec loop node =
48       if node != T.nil then begin
49         let parent = T.parent tree node in
50         let fc = T.first_child tree node in
51         let ns = T.next_sibling tree node in
52         let tag = T.tag tree node in
53         let config0 =
54           let c = get cache tree node in
55           if c == Cache.N1.dummy cache then
56            Ata.Config.make
57              { c.Ata.Config.node with Ata.todo = Ata.get_trans auto tag auto.Ata.states }
58           else c
59         in
60
61         let () =
62           TRACE(
63             let config0 = config0.Ata.node in
64             Html.trace (T.preorder tree node) _i "Config0<br/>sat: %a<br/>unsat: %a<br/>todo: %a<br/>"
65                   StateSet.print config0.Ata.sat
66                   StateSet.print config0.Ata.unsat
67                   (Ata.TransList.print ~sep:"<br/>") config0.Ata.todo)
68         in
69
70         let ps = get cache tree parent in
71         let fcs = get cache tree fc in
72         let nss = get cache tree ns in
73         let is_left = node == T.first_child tree parent
74         and is_right = node == T.next_sibling tree parent
75         and has_left = fc != T.nil
76         and has_right = ns != T.nil
77         and kind = T.kind tree node
78         in
79         let config1 =
80           Ata.eval_trans auto fcs nss ps config0
81             is_left is_right has_left has_right kind
82         in
83         let () =
84           TRACE(
85             let config1 = config1.Ata.node in
86             Html.trace (T.preorder tree node) _i "Config1<br/>sat: %a<br/>unsat: %a<br/>todo: %a<br/>"
87                   StateSet.print config1.Ata.sat
88                   StateSet.print config1.Ata.unsat
89                   (Ata.TransList.print ~sep:"<br/>") config1.Ata.todo)
90         in
91         if config0 != config1 then set cache tree node config1;
92         let () = loop fc in
93         let fcs1 = get cache tree fc in
94         let config2 =
95           Ata.eval_trans auto
96             fcs1 nss ps config1
97             is_left is_right has_left has_right kind
98         in
99         let () =
100           TRACE(
101             let config2 = config2.Ata.node in
102             Html.trace (T.preorder tree node) _i "Config2<br/>sat: %a<br/>unsat: %a<br/>todo: %a<br/>"
103                   StateSet.print config2.Ata.sat
104                   StateSet.print config2.Ata.unsat
105                   (Ata.TransList.print ~sep:"<br/>") config2.Ata.todo)
106         in
107
108         if config1 != config2 then set cache tree node config2;
109         let () = loop ns in
110         let config3 =
111           Ata.eval_trans auto
112             fcs1 (get cache tree ns) ps config2
113             is_left is_right has_left has_right kind
114         in
115         let () =
116           TRACE(
117             let config3 = config3.Ata.node in
118             Html.trace (T.preorder tree node) _i "Config3<br/>sat: %a<br/>unsat: %a<br/>todo: %a<br/>"
119                   StateSet.print config3.Ata.sat
120                   StateSet.print config3.Ata.unsat
121                   (Ata.TransList.print ~sep:"<br/>") config3.Ata.todo)
122         in
123         if config2 != config3 then set cache tree node config3;
124         (* We do set the redo flat if : *)
125         if not (
126           !redo (* already set *)
127           || (Ata.TransList.nil == config3.Ata.Config.node.Ata.todo) (* no more transition to check *)
128           || (config0 == config3) (* did not gain any new information *)
129         )
130         then redo := true
131       end
132     in
133     loop node;
134     !redo
135
136   let get_results auto tree node cache =
137     let rec loop node acc =
138       if node == T.nil then acc
139       else
140         let acc0 = loop (T.next_sibling tree node) acc in
141         let acc1 = loop (T.first_child tree node) acc0 in
142
143         if StateSet.intersect (get cache tree node).Ata.Config.node.Ata.sat auto.Ata.selection_states then
144           node::acc1
145         else
146           acc1
147     in
148     loop node []
149
150   let eval auto tree node =
151     let cache = Cache.N1.create
152       (Ata.Config.make { Ata.sat = StateSet.empty;
153                          Ata.unsat = StateSet.empty;
154                          Ata.todo = Ata.TransList.nil })
155     in
156     let redo = ref true in
157     let iter = ref 0 in
158     Ata.reset auto;
159     while !redo do
160       redo := false;
161       redo := top_down_run auto tree node cache !iter;
162       incr iter;
163     done;
164     at_exit (fun () -> eprintf "INFO: %i iterations\n" !iter);
165     let r = get_results auto tree node cache in
166     TRACE(Html.gen_trace (module T : Tree.S with type t = T.t) (tree));
167     r
168
169 end