Hashcons transition evaluation based on node configuration.
[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-22 15:31:24 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 Ata.todo = Ata.get_trans auto tag auto.Ata.states;
66                summary = Ata.node_summary
67                  (node == T.first_child tree parent) (* is_left *)
68                  (node == T.next_sibling tree parent) (* is_right *)
69                  (fc != T.nil) (* has_left *)
70                  (ns != T.nil) (* has_right *)
71                  (T.kind tree node) (* kind *)
72              }
73           else c
74         in
75
76         TRACE(html tree node _i config0 "Entering node");
77
78         let ps = get cache tree parent in
79         let fcs = get cache tree fc in
80         let nss = get cache tree ns in
81         let config1 = Ata.eval_trans auto fcs nss ps config0 in
82
83         TRACE(html tree node _i config1 "Updating transitions");
84
85         if config0 != config1 then set cache tree node config1;
86         let () = loop fc in
87         let fcs1 = get cache tree fc in
88         let config2 = Ata.eval_trans auto fcs1 nss ps config1 in
89
90         TRACE(html tree node _i config2 "Updating transitions (after first-child)");
91
92         if config1 != config2 then set cache tree node config2;
93         let () = loop ns in
94         let config3 = Ata.eval_trans auto fcs1 (get cache tree ns) ps config2 in
95
96         TRACE(html tree node _i config3 "Updating transitions (after next-sibling)");
97
98         if config2 != config3 then set cache tree node config3;
99         (* We do set the redo flat if : *)
100         if not (
101           config0 == config3 (* did not gain any new information *)
102           || !redo (* already set *)
103           || Ata.TransList.nil == config3.Ata.Config.node.Ata.todo ) (* no more transition to check *)
104         then redo := true
105       end
106     in
107     loop node;
108     !redo
109
110   let get_results auto tree node cache =
111     let rec loop node acc =
112       if node == T.nil then acc
113       else
114         let acc0 = loop (T.next_sibling tree node) acc in
115         let acc1 = loop (T.first_child tree node) acc0 in
116
117         if StateSet.intersect (get cache tree node).Ata.Config.node.Ata.sat auto.Ata.selection_states then
118           node::acc1
119         else
120           acc1
121     in
122     loop node []
123
124   let eval auto tree node =
125     let cache = Cache.N1.create
126       (Ata.Config.make { Ata.sat = StateSet.empty;
127                          Ata.unsat = StateSet.empty;
128                          Ata.todo = Ata.TransList.nil;
129                          Ata.summary = Ata.dummy_summary;
130                        })
131     in
132     let redo = ref true in
133     let iter = ref 0 in
134     Ata.reset auto;
135     while !redo do
136       redo := false;
137       Ata.reset auto;
138       redo := top_down_run auto tree node cache !iter;
139       incr iter;
140     done;
141     at_exit (fun () -> eprintf "INFO: %i iterations\n" !iter);
142     let r = get_results auto tree node cache in
143     TRACE(Html.gen_trace (module T : Tree.S with type t = T.t) (tree));
144     r
145
146 end