Fix the build script.
[tatoo.git] / src / auto / formula.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-03-09 11:16:29 CET by Kim Nguyen>
18 *)
19
20 INCLUDE "utils.ml"
21
22 open Format
23 open Utils
24
25 (*
26
27 (** Implementation of hashconsed Boolean formulae *)
28
29 *)
30 module type ATOM =
31 sig
32   type t
33   val neg : t -> t
34   include Hcons.Abstract with type t := t
35   include Common_sig.Printable with type t := t
36 end
37
38 type ('formula,'atom) expr =
39   | False
40   | True
41   | Or of 'formula * 'formula
42   | And of 'formula * 'formula
43   | Atom of 'atom
44
45 module Make (P: ATOM) =
46 struct
47
48
49   type 'hcons node = {
50     pos : ('hcons,P.t) expr;
51     mutable neg : 'hcons;
52   }
53
54   external hash_const_variant : [> ] -> int = "%identity"
55   external vb : bool -> int = "%identity"
56
57   module rec Node : Hcons.S
58     with type data = Data.t = Hcons.Make (Data)
59     and Data : Common_sig.HashedType  with type t = Node.t node =
60   struct
61     type t =  Node.t node
62     let equal x y =
63       match x.pos, y.pos with
64       | a,b when a == b -> true
65       | Or(xf1, xf2), Or(yf1, yf2)
66       | And(xf1, xf2), And(yf1,yf2)  -> xf1 == yf1 && xf2 == yf2
67       | Atom(p1), Atom(p2) -> p1 == p2
68       | _ -> false
69
70     let hash f =
71       match f.pos with
72       | False -> 0
73       | True -> 1
74       | Or (f1, f2) ->
75           HASHINT3 (PRIME1, Uid.to_int f1.Node.id, Uid.to_int f2.Node.id)
76       | And (f1, f2) ->
77           HASHINT3(PRIME3, Uid.to_int f1.Node.id, Uid.to_int f2.Node.id)
78       | Atom(p) -> HASHINT2(PRIME5, Uid.to_int (P.uid p))
79   end
80
81     type t = Node.t
82     let hash x = x.Node.hash
83     let uid x = x.Node.id
84     let equal = Node.equal
85     let expr f = f.Node.node.pos
86
87     let compare f1 f2 = compare f1.Node.id  f2.Node.id
88     let prio f =
89       match expr f with
90       | True | False -> 10
91       | Atom _ -> 8
92       | And _ -> 6
93       | Or _ -> 1
94
95     let rec print ?(parent=false) ppf f =
96       if parent then fprintf ppf "(";
97       let _ = match expr f with
98       | True -> fprintf ppf "%s" Pretty.top
99       | False -> fprintf ppf "%s" Pretty.bottom
100       | And(f1,f2) ->
101           print ~parent:(prio f > prio f1) ppf f1;
102           fprintf ppf " %s "  Pretty.wedge;
103           print ~parent:(prio f > prio f2) ppf f2;
104       | Or(f1,f2) ->
105           (print ppf f1);
106           fprintf ppf " %s " Pretty.vee;
107           (print ppf f2);
108       | Atom(p) -> fprintf ppf "%a" P.print p
109 (*          let _ = flush_str_formatter() in
110           let fmt = str_formatter in
111           let a_str, d_str =
112           match  dir with
113           | `Left ->  Pretty.down_arrow, Pretty.subscript 1
114           | `Right -> Pretty.down_arrow, Pretty.subscript 2
115           | `Epsilon -> Pretty.epsilon, ""
116           | `Up1 -> Pretty.up_arrow, Pretty.subscript 1
117           | `Up2 -> Pretty.up_arrow, Pretty.subscript 2
118         in
119         fprintf fmt "%s%s" a_str d_str;
120         State.print fmt s;
121         let str = flush_str_formatter() in
122         if b then fprintf ppf "%s" str
123         else Pretty.pp_overline ppf str *)
124   in
125     if parent then fprintf ppf ")"
126
127 let print ppf f =  print ~parent:false ppf f
128
129 let is_true f = (expr f) == True
130 let is_false f = (expr f) == False
131
132
133 let cons pos neg =
134   let nnode = Node.make { pos = neg; neg = Obj.magic 0 } in
135   let pnode = Node.make { pos = pos; neg = nnode } in
136     (Node.node nnode).neg <- pnode; (* works because the neg field isn't taken into
137                                        account for hashing ! *)
138     pnode,nnode
139
140
141 let true_,false_ = cons True False
142
143 let atom_ p = fst (cons (Atom(p)) (Atom(P.neg p)))
144
145 let not_ f = f.Node.node.neg
146
147 let order f1 f2 = if uid f1 < uid f2 then f2,f1 else f1,f2
148
149 let or_ f1 f2 =
150   (* Tautologies: x|x, x|not(x) *)
151
152   if equal f1 f2 then f1
153   else if equal f1 (not_ f2) then true_
154
155   (* simplification *)
156   else if is_true f1 || is_true f2 then true_
157   else if is_false f1 && is_false f2 then false_
158   else if is_false f1 then f2
159   else if is_false f2 then f1
160
161   (* commutativity of | *)
162   else
163     let f1, f2 = order f1 f2 in
164       fst (cons (Or(f1,f2)) (And(not_ f1, not_ f2)))
165
166
167 let and_ f1 f2 =
168   not_ (or_ (not_ f1) (not_ f2))
169
170
171 let of_bool = function true -> true_ | false -> false_
172
173 let fold f phi acc =
174   let rec loop phi acc =
175     match expr phi with
176     | And (phi1, phi2) | Or(phi1, phi2)  ->
177         loop phi2 (loop phi1 (f phi acc))
178     | _ -> f phi acc
179   in
180   loop phi acc
181
182 end