d0961d70a094ed88b6b48eaff8ca3a1043a41024
[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-23 14:53:43 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    let html tree node i config msg =
38      let config = config.Ata.Config.node in
39      Html.trace (T.preorder tree node) i
40        "%s<br/>sat: %a<br/>unsat: %a<br/>todo: %a<br/>"
41        msg
42        StateSet.print config.Ata.sat
43        StateSet.print config.Ata.unsat
44        (Ata.TransList.print ~sep:"<br/>") config.Ata.todo
45
46
47   type cache = StateSet.t Cache.N1.t
48   let get c t n = Cache.N1.find c (T.preorder t n)
49
50   let set c t n v = Cache.N1.add c (T.preorder t n) v
51
52
53   let top_down_run auto tree node cache _i =
54     let redo = ref false in
55     let rec loop node =
56       if node != T.nil then begin
57         let parent = T.parent tree node in
58         let fc = T.first_child tree node in
59         let ns = T.next_sibling tree node in
60         let tag = T.tag tree node in
61         let config0 =
62           let c = get cache tree node in
63           if c == Cache.N1.dummy cache then
64            Ata.Config.make
65              { c.Ata.Config.node with
66                Ata.todo = Ata.get_trans auto tag auto.Ata.states;
67                summary = Ata.node_summary
68                  (node == T.first_child tree parent) (* is_left *)
69                  (node == T.next_sibling tree parent) (* is_right *)
70                  (fc != T.nil) (* has_left *)
71                  (ns != T.nil) (* has_right *)
72                  (T.kind tree node) (* kind *)
73              }
74           else c
75         in
76
77         TRACE(html tree node _i config0 "Entering node");
78
79         let ps = get cache tree parent in
80         let fcs = get cache tree fc in
81         let nss = get cache tree ns in
82         let config1 = Ata.eval_trans auto fcs nss ps config0 in
83
84         TRACE(html tree node _i config1 "Updating transitions");
85
86         if config0 != config1 then set cache tree node config1;
87         let () = loop fc in
88         let fcs1 = get cache tree fc in
89         let config2 = Ata.eval_trans auto fcs1 nss ps config1 in
90
91         TRACE(html tree node _i config2 "Updating transitions (after first-child)");
92
93         if config1 != config2 then set cache tree node config2;
94         let () = loop ns in
95         let config3 = Ata.eval_trans auto fcs1 (get cache tree ns) ps config2 in
96
97         TRACE(html tree node _i config3 "Updating transitions (after next-sibling)");
98
99         if config2 != config3 then set cache tree node config3;
100         (* We do set the redo flat if : *)
101         if not (
102           config0 == config3 (* did not gain any new information *)
103           || !redo (* already set *)
104           || Ata.TransList.nil == config3.Ata.Config.node.Ata.todo ) (* no more transition to check *)
105         then redo := true
106       end
107     in
108     loop node;
109     !redo
110
111   let get_results auto tree node cache =
112     let rec loop node acc =
113       if node == T.nil then acc
114       else
115         let acc0 = loop (T.next_sibling tree node) acc in
116         let acc1 = loop (T.first_child tree node) acc0 in
117
118         if StateSet.intersect
119           (get cache tree node).Ata.Config.node.Ata.sat
120           auto.Ata.selection_states then node::acc1
121         else acc1
122     in
123     loop node []
124
125   let eval auto tree node =
126     let cache = Cache.N1.create
127       (Ata.Config.make { Ata.sat = StateSet.empty;
128                          Ata.unsat = StateSet.empty;
129                          Ata.todo = Ata.TransList.nil;
130                          Ata.summary = Ata.dummy_summary;
131                        })
132     in
133     let redo = ref true in
134     let iter = ref 0 in
135     Ata.reset auto;
136     while !redo do
137       redo := false;
138       Ata.reset auto; (* prevents the .cache2 and .cache4 memoization tables from growing too much *)
139       redo := top_down_run auto tree node cache !iter;
140       incr iter;
141     done;
142     at_exit (fun () -> eprintf "@[STATS: %i iterations@]@." !iter);
143     let r = get_results auto tree node cache in
144     TRACE(Html.gen_trace (module T : Tree.S with type t = T.t) (tree));
145     r
146
147 end