X-Git-Url: http://git.nguyen.vg/gitweb/?p=tatoo.git;a=blobdiff_plain;f=src%2Fboolean.ml;fp=src%2Fboolean.ml;h=296f7a66893992089588992d3d9d26181b5ac858;hp=0000000000000000000000000000000000000000;hb=90ce5857f6cad2ebc753fdbc8e37882a1ff47415;hpb=9a127b83fbb1171ebd36e6f42780093412a5e91a diff --git a/src/boolean.ml b/src/boolean.ml new file mode 100644 index 0000000..296f7a6 --- /dev/null +++ b/src/boolean.ml @@ -0,0 +1,161 @@ +(***********************************************************************) +(* *) +(* TAToo *) +(* *) +(* Kim Nguyen, LRI UMR8623 *) +(* Université Paris-Sud & CNRS *) +(* *) +(* Copyright 2010-2013 Université Paris-Sud and Centre National de la *) +(* Recherche Scientifique. All rights reserved. This file is *) +(* distributed under the terms of the GNU Lesser General Public *) +(* License, with the special exception on linking described in file *) +(* ../LICENSE. *) +(* *) +(***********************************************************************) + +INCLUDE "utils.ml" + +open Format +open Misc + +(* + +(** Implementation of hashconsed Boolean formulae *) + +*) +module type ATOM = +sig + include Hcons.S + include Common_sig.Printable with type t := t +end + +type ('formula,'atom) expr = + | False + | True + | Or of 'formula * 'formula + | And of 'formula * 'formula + | Atom of 'atom * bool + +module Make (A: ATOM) = +struct + + + type 'hcons node = { + pos : ('hcons,A.t) expr; + mutable neg : 'hcons; + } + + external hash_const_variant : [> ] -> int = "%identity" + external vb : bool -> int = "%identity" + + module rec Node : Hcons.S + with type data = Data.t = Hcons.Make (Data) + and Data : Common_sig.HashedType with type t = Node.t node = + struct + type t = Node.t node + let equal x y = + match x.pos, y.pos with + | a,b when a == b -> true + | Or(xf1, xf2), Or(yf1, yf2) + | And(xf1, xf2), And(yf1,yf2) -> xf1 == yf1 && xf2 == yf2 + | Atom(p1, b1), Atom(p2, b2) -> p1 == p2 && b1 == b2 + | _ -> false + + let hash f = + match f.pos with + | False -> 0 + | True -> 1 + | Or (f1, f2) -> + HASHINT3 (PRIME1, Uid.to_int f1.Node.id, Uid.to_int f2.Node.id) + | And (f1, f2) -> + HASHINT3(PRIME3, Uid.to_int f1.Node.id, Uid.to_int f2.Node.id) + | Atom(p, b) -> HASHINT3(PRIME5, Uid.to_int (A.uid p), int_of_bool b) + end + + type t = Node.t + let hash x = x.Node.hash + let uid x = x.Node.id + let equal = Node.equal + let expr f = f.Node.node.pos + + let compare f1 f2 = compare f1.Node.id f2.Node.id + let prio f = + match expr f with + | True | False -> 10 + | Atom _ -> 8 + | And _ -> 6 + | Or _ -> 1 + + let rec print ?(parent=false) ppf f = + if parent then fprintf ppf "("; + let _ = match expr f with + | True -> fprintf ppf "%s" Pretty.top + | False -> fprintf ppf "%s" Pretty.bottom + | And(f1,f2) -> + print ~parent:(prio f > prio f1) ppf f1; + fprintf ppf " %s " Pretty.wedge; + print ~parent:(prio f > prio f2) ppf f2; + | Or(f1,f2) -> + (print ppf f1); + fprintf ppf " %s " Pretty.vee; + (print ppf f2); + | Atom(p,b) -> fprintf ppf "%s%a" (if b then "" else Pretty.lnot) A.print p + in + if parent then fprintf ppf ")" + +let print ppf f = print ~parent:false ppf f + +let is_true f = (expr f) == True +let is_false f = (expr f) == False + +let cons pos neg = + let nnode = Node.make { pos = neg; neg = Obj.magic 0 } in + let pnode = Node.make { pos = pos; neg = nnode } in + (Node.node nnode).neg <- pnode; (* works because the neg field isn't taken into + account for hashing ! *) + pnode,nnode + + +let true_,false_ = cons True False + +let atom_ p = + let a, _ = cons (Atom(p, true)) (Atom(p, false)) in a + +let not_ f = f.Node.node.neg + +let order f1 f2 = if uid f1 < uid f2 then f2,f1 else f1,f2 + +let or_ f1 f2 = + (* Tautologies: x|x, x|not(x) *) + + if equal f1 f2 then f1 + else if equal f1 (not_ f2) then true_ + + (* simplification *) + else if is_true f1 || is_true f2 then true_ + else if is_false f1 && is_false f2 then false_ + else if is_false f1 then f2 + else if is_false f2 then f1 + + (* commutativity of | *) + else + let f1, f2 = order f1 f2 in + fst (cons (Or(f1,f2)) (And(not_ f1, not_ f2))) + + +let and_ f1 f2 = + not_ (or_ (not_ f1) (not_ f2)) + + +let of_bool = function true -> true_ | false -> false_ + +let fold f phi acc = + let rec loop phi acc = + match expr phi with + | And (phi1, phi2) | Or(phi1, phi2) -> + loop phi2 (loop phi1 (f phi acc)) + | _ -> f phi acc + in + loop phi acc + +end