summaryrefslogtreecommitdiff
path: root/abstract/abs_interp_edd.ml
diff options
context:
space:
mode:
Diffstat (limited to 'abstract/abs_interp_edd.ml')
-rw-r--r--abstract/abs_interp_edd.ml186
1 files changed, 101 insertions, 85 deletions
diff --git a/abstract/abs_interp_edd.ml b/abstract/abs_interp_edd.ml
index 3ff91a6..4f2ad81 100644
--- a/abstract/abs_interp_edd.ml
+++ b/abstract/abs_interp_edd.ml
@@ -11,8 +11,6 @@ module I (ND : NUMERICAL_ENVIRONMENT_DOMAIN) : sig
val do_prog : cmdline_opt -> rooted_prog -> unit
- val test : unit -> unit
-
end = struct
@@ -31,10 +29,11 @@ end = struct
ev_order : (id, int) Hashtbl.t;
}
- type edd =
+ type edd_node =
| DBot
| DVal of int
| DChoice of id * (item * edd) list
+ and edd = int * edd_node
type edd_v = {
ve : varenv;
@@ -43,40 +42,66 @@ end = struct
(* add here eventual annotations *)
}
+ (*
+ Utility functions for memoization
+
+ memo : (((int * 'a) -> (int * 'b)) -> 'a -> 'b) -> (int * 'a) -> (int * 'b)
+ memo2 : (((int * 'a) -> (int * 'b) -> (int * 'c)) -> 'a -> 'b -> 'c) -> (int * 'a) -> (int * 'b) -> (int * 'c)
+ *)
+ let memo f =
+ let n = ref 0 in
+ let memo = Hashtbl.create 12 in
+ let rec ff (id, v) =
+ try Hashtbl.find memo id
+ with Not_found ->
+ let r = f ff v in
+ incr n;
+ Hashtbl.add memo id (n, r);
+ n, r
+ in ff
+ let memo2 f =
+ let n = ref 0 in
+ let memo = Hashtbl.create 12 in
+ let rec ff (id1, v1) (id2, v2) =
+ try Hashtbl.find memo (id1, id2)
+ with Not_found ->
+ let r = f ff v1 v2 in
+ incr n;
+ Hashtbl.add memo (id1, id2) (n, r);
+ n, r
+ in ff
(*
edd_print : Format.formatter -> edd_v -> unit
*)
let edd_print fmt v =
- let ids = Hashtbl.create 12 in
- let n = ref 0 in
- let rec mkid = function
- | DChoice(_, l) as x ->
- if not (Hashtbl.mem ids x) then begin
- incr n; Hashtbl.add ids x !n;
- List.iter (fun (_, x) -> mkid x) l
+ let c_nodes = Hashtbl.create 12 in
+ let rec add = function
+ | n, (DChoice(_, l) as x) ->
+ if not (Hashtbl.mem c_nodes n) then begin
+ Hashtbl.add c_nodes n x;
+ List.iter (fun (_, y) -> add y) l
end
| _ -> ()
- in mkid v.root;
+ in add v.root;
+
let print_n fmt = function
- | DBot -> Format.fprintf fmt "⊥";
- | DVal i -> Format.fprintf fmt "v%d" i;
- | DChoice _ as x -> Format.fprintf fmt "n%d" (Hashtbl.find ids x)
+ | (_, DBot) -> Format.fprintf fmt "⊥";
+ | (_, DVal i) -> Format.fprintf fmt "v%d" i;
+ | (n, DChoice _) -> Format.fprintf fmt "n%d" n
in
Format.fprintf fmt "Root: %a@." print_n v.root;
- for id = 1 to !n do
- let c = ref None in
- Hashtbl.iter (fun u i -> if i = id then c := Some u) ids;
- let x = match !c with | Some x -> x | None -> assert false in
- match x with
+
+ Hashtbl.iter
+ (fun id x -> match x with
| DChoice (var, l) ->
let p fmt (c, l) = Format.fprintf fmt "%s → %a" c print_n l in
Format.fprintf fmt "n%d: %a ? @[<hov>%a@]@."
id Formula_printer.print_id var
(print_list p ", ") l
- | _ -> assert false
- done;
+ | _ -> assert false)
+ c_nodes;
Hashtbl.iter
(fun id v -> Format.fprintf fmt "v%d: %a@." id ND.print v)
v.leaves
@@ -86,7 +111,7 @@ end = struct
(*
edd_bot : varenv -> edd_v
*)
- let edd_bot ve = { ve; root = DBot; leaves = Hashtbl.create 1 }
+ let edd_bot ve = { ve; root = (0, DBot); leaves = Hashtbl.create 1 }
(*
edd_top : evar list -> nvar list -> edd_v
@@ -94,7 +119,7 @@ end = struct
let edd_top ve =
let leaves = Hashtbl.create 1 in
Hashtbl.add leaves 0 (ND.top ve.nvars);
- { ve; root = DVal 0; leaves }
+ { ve; root = (1, DVal 0); leaves }
(*
edd_of_cons : varenv -> enum_cons -> edd_v
@@ -105,23 +130,27 @@ end = struct
let leaves = Hashtbl.create 1 in
Hashtbl.add leaves 0 (ND.top ve.nvars);
+ let bot, top = (0, DBot), (1, DVal 0) in
+
let root = match r with
| EItem x ->
- DChoice(vid,
- List.map (fun v -> if op v x then v, DVal 0 else v, DBot)
- (List.assoc vid ve.evars))
+ 2, DChoice(vid,
+ List.map (fun v -> if op v x then v, bot else v, top)
+ (List.assoc vid ve.evars))
| EIdent vid2 ->
let a, b =
if Hashtbl.find ve.ev_order vid < Hashtbl.find ve.ev_order vid2
then vid, vid2
else vid2, vid
in
+ let n = ref 2 in
let nb x =
- DChoice(b,
- List.map (fun v -> if op v x then v, DVal 0 else v, DBot)
- (List.assoc b ve.evars))
+ incr n;
+ !n, DChoice(b,
+ List.map (fun v -> if op v x then v, top else v, bot)
+ (List.assoc b ve.evars))
in
- DChoice(a, List.map (fun x -> x, nb x) (List.assoc a ve.evars))
+ 2, DChoice(a, List.map (fun x -> x, nb x) (List.assoc a ve.evars))
in
{ ve; root; leaves }
@@ -131,10 +160,9 @@ end = struct
let edd_join a b =
let ve = a.ve in
- let leaves = Hashtbl.copy a.leaves in
- let n = ref 0 in
- Hashtbl.iter (fun i _ -> if i > !n then n := i) leaves;
+ let leaves = Hashtbl.create 12 in
+ let n = ref 0 in
let get_leaf x =
let id = ref None in
Hashtbl.iter (fun i v -> if ND.eq v x then id := Some i) leaves;
@@ -147,61 +175,47 @@ end = struct
end
in
- let memo_bcopy = Hashtbl.create 12 in
- let rec bcopy nb =
- try Hashtbl.find memo_bcopy nb
- with Not_found -> let r =
- match nb with
- | DBot -> DBot
- | DVal i -> get_leaf (Hashtbl.find b.leaves i)
- | DChoice (v, x) ->
- DChoice(v, List.map (fun (c, n) -> c, bcopy n) x)
- in Hashtbl.add memo_bcopy nb r; r
- in
- let memo = Hashtbl.create 12 in
- let rec f (na, nb) =
- try Hashtbl.find memo (na, nb)
- with Not_found -> let r =
- let dq v l =
- let _, x0 = List.hd l in
- if List.exists (fun (_, x) -> x <> x0) l
- then DChoice(v, l)
- else x0
+ let f f_rec na nb =
+ let dq v l =
+ let _, (i, x0) = List.hd l in
+ if List.exists (fun (_, (j, x)) -> j <> i || x <> x0) l
+ then DChoice(v, l)
+ else x0
+ in
+ match na, nb with
+ | DBot, DBot -> DBot
+ | DBot, DVal i -> get_leaf (Hashtbl.find b.leaves i)
+ | x, DBot -> x
+
+ | DChoice(va, la), DChoice(vb, lb) when va = vb ->
+ let kl = List.map2
+ (fun (ta, ba) (tb, bb) -> assert (ta = tb);
+ ta, f (ba, bb))
+ la lb
in
- match na, nb with
- | DBot, x -> bcopy x
- | x, DBot -> x
-
- | DChoice(va, la), DChoice(vb, lb) when va = vb ->
- let kl = List.map2
- (fun (ta, ba) (tb, bb) -> assert (ta = tb);
- ta, f (ba, bb))
- la lb
- in
- dq va kl
- | DChoice(va, la), DChoice(vb, lb) ->
- let v, kl =
- if Hashtbl.find ve.ev_order va < Hashtbl.find ve.ev_order vb then
- va, List.map (fun (k, ca) -> k, f (ca, nb)) la
- else
- vb, List.map (fun (k, cb) -> k, f (na, cb)) lb
- in
- dq v kl
-
- | DChoice(va, la), _ ->
- let kl = List.map (fun (k, ca) -> k, f (ca, nb)) la in
- dq va kl
- | _, DChoice(vb, lb) ->
- let kl = List.map (fun (k, cb) -> k, f (na, cb)) lb in
- dq vb kl
-
- | DVal u, DVal v ->
- let x = ND.join (Hashtbl.find a.leaves u) (Hashtbl.find b.leaves v) in
- get_leaf x
- in Hashtbl.add memo (na, nb) r; r
+ dq va kl
+ | DChoice(va, la), DChoice(vb, lb) ->
+ let v, kl =
+ if Hashtbl.find ve.ev_order va < Hashtbl.find ve.ev_order vb then
+ va, List.map (fun (k, ca) -> k, f (ca, nb)) la
+ else
+ vb, List.map (fun (k, cb) -> k, f (na, cb)) lb
+ in
+ dq v kl
+
+ | DChoice(va, la), _ ->
+ let kl = List.map (fun (k, ca) -> k, f (ca, nb)) la in
+ dq va kl
+ | _, DChoice(vb, lb) ->
+ let kl = List.map (fun (k, cb) -> k, f (na, cb)) lb in
+ dq vb kl
+
+ | DVal u, DVal v ->
+ let x = ND.join (Hashtbl.find a.leaves u) (Hashtbl.find b.leaves v) in
+ get_leaf x
in
- { leaves; ve; root = f (a.root, b.root) }
+ { leaves; ve; root = memo2 f a.root b.root }
(*
edd_meet : edd_v -> edd_v -> edd_v
@@ -342,6 +356,7 @@ end = struct
in f (a.root, b.root)
+ (*
let test () =
let ve = {
evars = ["x", ["tt"; "ff"]; "y", ["tt"; "ff"]; "z", ["tt"; "ff"]];
@@ -358,6 +373,7 @@ end = struct
Format.printf "x = y && y != z : @[%a@]@." edd_print w;
let t = edd_join u v in
Format.printf "x = y || y != z : @[%a@]@." edd_print t
+ *)
(* ******************************