|
|
@ -1,58 +1,57 @@ |
|
|
|
module Base = struct |
|
|
|
type var = int |
|
|
|
|
|
|
|
type expr = Expr.Lang.t |
|
|
|
|
|
|
|
(* TODO *) |
|
|
|
let inv_tbl = Hashtbl.create 512 |
|
|
|
|
|
|
|
let string_of_var = Hashtbl.find inv_tbl |
|
|
|
|
|
|
|
let var_of_string, reset, max_var = |
|
|
|
let tbl = Hashtbl.create 512 in |
|
|
|
let gen, reset = Utils.gen_tag () in |
|
|
|
(fun x -> |
|
|
|
try Hashtbl.find tbl x |
|
|
|
with Not_found -> |
|
|
|
let v = gen () in |
|
|
|
Hashtbl.add inv_tbl v x; |
|
|
|
Hashtbl.add tbl x v; |
|
|
|
(* Printf.printf "added %s -> %d\n" x v; |
|
|
|
( (fun x -> |
|
|
|
try Hashtbl.find tbl x |
|
|
|
with Not_found -> |
|
|
|
let v = gen () in |
|
|
|
Hashtbl.add inv_tbl v x ; |
|
|
|
Hashtbl.add tbl x v ; |
|
|
|
(* Printf.printf "added %s -> %d\n" x v; |
|
|
|
flush stdout;*) |
|
|
|
v), |
|
|
|
(fun () -> reset ()), |
|
|
|
(fun () -> Hashtbl.length tbl) |
|
|
|
v) |
|
|
|
, (fun () -> reset ()) |
|
|
|
, fun () -> Hashtbl.length tbl ) |
|
|
|
end |
|
|
|
|
|
|
|
module type S = sig |
|
|
|
|
|
|
|
type hidden |
|
|
|
type view = |
|
|
|
| True |
|
|
|
| False |
|
|
|
| Node of Base.var * hidden * hidden |
|
|
|
|
|
|
|
module Hash: Hashtbl.HashedType with type t = hidden |
|
|
|
module Mem: Memo.S with type t = hidden |
|
|
|
type view = True | False | Node of Base.var * hidden * hidden |
|
|
|
|
|
|
|
val hc: view -> hidden |
|
|
|
val view: hidden -> view |
|
|
|
end |
|
|
|
module Hash : Hashtbl.HashedType with type t = hidden |
|
|
|
|
|
|
|
module Make (M: S) = struct |
|
|
|
module Mem : Memo.S with type t = hidden |
|
|
|
|
|
|
|
val hc : view -> hidden |
|
|
|
|
|
|
|
val view : hidden -> view |
|
|
|
end |
|
|
|
|
|
|
|
module Make (M : S) = struct |
|
|
|
include M |
|
|
|
|
|
|
|
let true_bdd = hc True |
|
|
|
|
|
|
|
let false_bdd = hc False |
|
|
|
|
|
|
|
let fview f bdd = view bdd |> f |
|
|
|
|
|
|
|
let get_order = fview (function |
|
|
|
| True | False -> max_int |
|
|
|
| Node (v, _, _) -> v |
|
|
|
) |
|
|
|
let get_order = |
|
|
|
fview (function True | False -> max_int | Node (v, _, _) -> v) |
|
|
|
|
|
|
|
let node v l h = |
|
|
|
if v >= get_order l || v >= get_order h then invalid_arg "node"; |
|
|
|
if v >= get_order l || v >= get_order h then invalid_arg "node" ; |
|
|
|
if Hash.equal l h then l else hc (Node (v, l, h)) |
|
|
|
|
|
|
|
let ite _ _ _ = true_bdd (* TODO *) |
|
|
@ -61,191 +60,259 @@ module Make (M: S) = struct |
|
|
|
|
|
|
|
let to_string bdd = |
|
|
|
let b = Buffer.create 512 in |
|
|
|
let rec aux bdd = match view bdd with |
|
|
|
| True -> Buffer.add_string b "true" |
|
|
|
| False -> Buffer.add_string b "false" |
|
|
|
| Node (var, low, high) -> |
|
|
|
Buffer.add_string b (Base.string_of_var var); |
|
|
|
Buffer.add_string b ("(" ^ (string_of_int var) ^ ") ? ("); |
|
|
|
aux high; |
|
|
|
Buffer.add_string b ") : ("; |
|
|
|
aux low; |
|
|
|
Buffer.add_string b ")" |
|
|
|
let rec aux bdd = |
|
|
|
match view bdd with |
|
|
|
| True -> |
|
|
|
Buffer.add_string b "true" |
|
|
|
| False -> |
|
|
|
Buffer.add_string b "false" |
|
|
|
| Node (var, low, high) -> |
|
|
|
Buffer.add_string b (Base.string_of_var var) ; |
|
|
|
Buffer.add_string b ("(" ^ string_of_int var ^ ") ? (") ; |
|
|
|
aux high ; |
|
|
|
Buffer.add_string b ") : (" ; |
|
|
|
aux low ; |
|
|
|
Buffer.add_string b ")" |
|
|
|
in |
|
|
|
aux bdd; |
|
|
|
Buffer.contents b |
|
|
|
|
|
|
|
let of_bool = function |
|
|
|
| true -> true_bdd |
|
|
|
| false -> false_bdd |
|
|
|
|
|
|
|
let neg x = Mem.memo (fun neg -> |
|
|
|
fview (function |
|
|
|
| True -> false_bdd |
|
|
|
| False -> true_bdd |
|
|
|
| Node (var, low, high) -> node var (neg low) (neg high))) x |
|
|
|
aux bdd ; Buffer.contents b |
|
|
|
|
|
|
|
let of_bool = function true -> true_bdd | false -> false_bdd |
|
|
|
|
|
|
|
let neg x = |
|
|
|
Mem.memo |
|
|
|
(fun neg -> |
|
|
|
fview (function |
|
|
|
| True -> |
|
|
|
false_bdd |
|
|
|
| False -> |
|
|
|
true_bdd |
|
|
|
| Node (var, low, high) -> |
|
|
|
node var (neg low) (neg high))) |
|
|
|
x |
|
|
|
|
|
|
|
(* let rec comb_comm op n1 n2 = |
|
|
|
let comb_comm = comb_comm op in *) |
|
|
|
let comb_comm op x y = Mem.memo2 (fun comb_comm n1 n2 -> |
|
|
|
match view n1, view n2 with |
|
|
|
| Node (v1, l1, h1), Node (v2, l2, h2) when v1 = v2 -> |
|
|
|
node v1 (comb_comm l1 l2) (comb_comm h1 h2) |
|
|
|
| Node (v1, l1, h1), Node (v2, _, _) when v1 < v2 -> |
|
|
|
node v1 (comb_comm l1 n2) (comb_comm h1 n2) |
|
|
|
| Node (_, _, _), Node (v2, l2, h2) -> |
|
|
|
node v2 (comb_comm n1 l2) (comb_comm n1 h2) |
|
|
|
| True, Node (v, l, h) | Node (v, l, h), True -> |
|
|
|
node v (comb_comm l true_bdd) (comb_comm h true_bdd) |
|
|
|
| False, Node (v, l, h) | Node (v, l, h), False -> |
|
|
|
node v (comb_comm l false_bdd) (comb_comm h false_bdd) |
|
|
|
| False, False -> of_bool (op false false) |
|
|
|
| False, True | True, False -> of_bool (op true false) |
|
|
|
| True, True -> of_bool (op true true) |
|
|
|
) x y |
|
|
|
|
|
|
|
let comb op x y = Mem.memo2 (fun comb n1 n2 -> |
|
|
|
match view n1, view n2 with |
|
|
|
| Node (v1, l1, h1), Node (v2, l2, h2) when v1 = v2 -> |
|
|
|
node v1 (comb l1 l2) (comb h1 h2) |
|
|
|
| Node (v1, l1, h1), Node (v2, _, _) when v1 < v2 -> |
|
|
|
node v1 (comb l1 n2) (comb h1 n2) |
|
|
|
| Node (_, _, _), Node (v2, l2, h2) -> |
|
|
|
node v2 (comb n1 l2) (comb n1 h2) |
|
|
|
| True, Node (v, l, h) -> |
|
|
|
node v (comb true_bdd l) (comb true_bdd h) |
|
|
|
| Node (v, l, h), True -> |
|
|
|
node v (comb l true_bdd) (comb h true_bdd) |
|
|
|
| False, Node (v, l, h) -> |
|
|
|
node v (comb false_bdd l) (comb false_bdd h) |
|
|
|
| Node (v, l, h), False -> |
|
|
|
node v (comb l false_bdd) (comb h false_bdd) |
|
|
|
| False, False -> of_bool (op false false) |
|
|
|
| False, True -> of_bool (op false true) |
|
|
|
| True, False -> of_bool (op true false) |
|
|
|
| True, True -> of_bool (op true true)) x y |
|
|
|
let comb_comm op x y = |
|
|
|
Mem.memo2 |
|
|
|
(fun comb_comm n1 n2 -> |
|
|
|
match (view n1, view n2) with |
|
|
|
| Node (v1, l1, h1), Node (v2, l2, h2) when v1 = v2 -> |
|
|
|
node v1 (comb_comm l1 l2) (comb_comm h1 h2) |
|
|
|
| Node (v1, l1, h1), Node (v2, _, _) when v1 < v2 -> |
|
|
|
node v1 (comb_comm l1 n2) (comb_comm h1 n2) |
|
|
|
| Node (_, _, _), Node (v2, l2, h2) -> |
|
|
|
node v2 (comb_comm n1 l2) (comb_comm n1 h2) |
|
|
|
| True, Node (v, l, h) | Node (v, l, h), True -> |
|
|
|
node v (comb_comm l true_bdd) (comb_comm h true_bdd) |
|
|
|
| False, Node (v, l, h) | Node (v, l, h), False -> |
|
|
|
node v (comb_comm l false_bdd) (comb_comm h false_bdd) |
|
|
|
| False, False -> |
|
|
|
of_bool (op false false) |
|
|
|
| False, True | True, False -> |
|
|
|
of_bool (op true false) |
|
|
|
| True, True -> |
|
|
|
of_bool (op true true)) |
|
|
|
x y |
|
|
|
|
|
|
|
let comb op x y = |
|
|
|
Mem.memo2 |
|
|
|
(fun comb n1 n2 -> |
|
|
|
match (view n1, view n2) with |
|
|
|
| Node (v1, l1, h1), Node (v2, l2, h2) when v1 = v2 -> |
|
|
|
node v1 (comb l1 l2) (comb h1 h2) |
|
|
|
| Node (v1, l1, h1), Node (v2, _, _) when v1 < v2 -> |
|
|
|
node v1 (comb l1 n2) (comb h1 n2) |
|
|
|
| Node (_, _, _), Node (v2, l2, h2) -> |
|
|
|
node v2 (comb n1 l2) (comb n1 h2) |
|
|
|
| True, Node (v, l, h) -> |
|
|
|
node v (comb true_bdd l) (comb true_bdd h) |
|
|
|
| Node (v, l, h), True -> |
|
|
|
node v (comb l true_bdd) (comb h true_bdd) |
|
|
|
| False, Node (v, l, h) -> |
|
|
|
node v (comb false_bdd l) (comb false_bdd h) |
|
|
|
| Node (v, l, h), False -> |
|
|
|
node v (comb l false_bdd) (comb h false_bdd) |
|
|
|
| False, False -> |
|
|
|
of_bool (op false false) |
|
|
|
| False, True -> |
|
|
|
of_bool (op false true) |
|
|
|
| True, False -> |
|
|
|
of_bool (op true false) |
|
|
|
| True, True -> |
|
|
|
of_bool (op true true)) |
|
|
|
x y |
|
|
|
|
|
|
|
let conj = comb_comm (fun x y -> x && y) |
|
|
|
|
|
|
|
let disj = comb_comm (fun x y -> x || y) |
|
|
|
|
|
|
|
let imp = comb (fun x y -> (not x) || y) |
|
|
|
|
|
|
|
let eq = comb_comm (fun x y -> x = y) |
|
|
|
|
|
|
|
let compute tbl = |
|
|
|
let compute_aux = Mem.memo (fun compute_aux -> |
|
|
|
fview (function |
|
|
|
| False -> false_bdd |
|
|
|
| True -> true_bdd |
|
|
|
| Node (v, l, h) -> ( match Hashtbl.find tbl v with |
|
|
|
| exception Not_found -> |
|
|
|
failwith ("truth value of " ^ (Base.string_of_var v) ^ " is missing") |
|
|
|
| true -> compute_aux h |
|
|
|
| false -> compute_aux l))) |
|
|
|
in compute_aux |
|
|
|
let compute_aux = |
|
|
|
Mem.memo (fun compute_aux -> |
|
|
|
fview (function |
|
|
|
| False -> |
|
|
|
false_bdd |
|
|
|
| True -> |
|
|
|
true_bdd |
|
|
|
| Node (v, l, h) -> ( |
|
|
|
match Hashtbl.find tbl v with |
|
|
|
| exception Not_found -> |
|
|
|
failwith |
|
|
|
("truth value of " ^ Base.string_of_var v ^ " is missing") |
|
|
|
| true -> |
|
|
|
compute_aux h |
|
|
|
| false -> |
|
|
|
compute_aux l ))) |
|
|
|
in |
|
|
|
compute_aux |
|
|
|
|
|
|
|
let to_expr = |
|
|
|
Mem.memo (fun to_expr -> |
|
|
|
let module E = Expr.Lang in |
|
|
|
fview (function |
|
|
|
| False -> E.False |
|
|
|
| True -> E.True |
|
|
|
| Node (v, l, h) -> |
|
|
|
E.Or ( |
|
|
|
E.And (E.Var (Base.string_of_var v), (to_expr l)), |
|
|
|
E.And (E.Neg (E.Var (Base.string_of_var v)), (to_expr h))))) |
|
|
|
let module E = Expr.Lang in |
|
|
|
fview (function |
|
|
|
| False -> |
|
|
|
E.False |
|
|
|
| True -> |
|
|
|
E.True |
|
|
|
| Node (v, l, h) -> |
|
|
|
E.Or |
|
|
|
( E.And (E.Var (Base.string_of_var v), to_expr l) |
|
|
|
, E.And (E.Neg (E.Var (Base.string_of_var v)), to_expr h) ))) |
|
|
|
|
|
|
|
let rec of_expr = |
|
|
|
let module E = Expr.Lang in function |
|
|
|
| E.True -> true_bdd |
|
|
|
| E.False -> false_bdd |
|
|
|
| E.Var v -> (try var_bdd (int_of_string v) with _ -> var_bdd (Base.var_of_string (E.var_to_string v))) |
|
|
|
| E.Neg e -> neg (of_expr e) |
|
|
|
| E.And (e1, e2) -> conj (of_expr e1) (of_expr e2) |
|
|
|
| E.Or (e1, e2) -> disj (of_expr e1) (of_expr e2) |
|
|
|
| E.Imp (e1, e2) -> imp (of_expr e1) (of_expr e2) |
|
|
|
| E.Eq (e1, e2) -> eq (of_expr e1) (of_expr e2) |
|
|
|
| E.BigAnd e -> Seq.fold_left (fun acc el -> conj (of_expr el) acc) true_bdd e |
|
|
|
| E.BigOr e -> Seq.fold_left (fun acc el -> disj (of_expr el) acc) false_bdd e |
|
|
|
let module E = Expr.Lang in |
|
|
|
function |
|
|
|
| E.True -> |
|
|
|
true_bdd |
|
|
|
| E.False -> |
|
|
|
false_bdd |
|
|
|
| E.Var v -> ( |
|
|
|
try var_bdd (int_of_string v) |
|
|
|
with _ -> var_bdd (Base.var_of_string (E.var_to_string v)) ) |
|
|
|
| E.Neg e -> |
|
|
|
neg (of_expr e) |
|
|
|
| E.And (e1, e2) -> |
|
|
|
conj (of_expr e1) (of_expr e2) |
|
|
|
| E.Or (e1, e2) -> |
|
|
|
disj (of_expr e1) (of_expr e2) |
|
|
|
| E.Imp (e1, e2) -> |
|
|
|
imp (of_expr e1) (of_expr e2) |
|
|
|
| E.Eq (e1, e2) -> |
|
|
|
eq (of_expr e1) (of_expr e2) |
|
|
|
| E.BigAnd e -> |
|
|
|
Seq.fold_left (fun acc el -> conj (of_expr el) acc) true_bdd e |
|
|
|
| E.BigOr e -> |
|
|
|
Seq.fold_left (fun acc el -> disj (of_expr el) acc) false_bdd e |
|
|
|
|
|
|
|
let of_string s = of_expr (Expr.Comp.from_string s) |
|
|
|
|
|
|
|
let size = |
|
|
|
(* TODO *) |
|
|
|
let module H = Hashtbl.Make(struct |
|
|
|
let module H = Hashtbl.Make (struct |
|
|
|
type t = M.Hash.t |
|
|
|
let equal = (==) |
|
|
|
|
|
|
|
let equal = ( == ) |
|
|
|
|
|
|
|
let hash = Hashtbl.hash (* TODO *) |
|
|
|
end) in |
|
|
|
let tbl = H.create 512 in |
|
|
|
let rec size bdd = match view bdd with |
|
|
|
| False | True -> 0 |
|
|
|
| _ when H.mem tbl bdd -> 0 |
|
|
|
| Node (_, l, h) -> H.add tbl bdd (); 1 + size l + size h |
|
|
|
in size |
|
|
|
let rec size bdd = |
|
|
|
match view bdd with |
|
|
|
| False | True -> |
|
|
|
0 |
|
|
|
| _ when H.mem tbl bdd -> |
|
|
|
0 |
|
|
|
| Node (_, l, h) -> |
|
|
|
H.add tbl bdd () ; |
|
|
|
1 + size l + size h |
|
|
|
in |
|
|
|
size |
|
|
|
|
|
|
|
let is_sat = fview (function |
|
|
|
| False -> false |
|
|
|
| _ -> true) |
|
|
|
let is_sat = fview (function False -> false | _ -> true) |
|
|
|
|
|
|
|
let count_sat maxn = |
|
|
|
|
|
|
|
let get_var = fview (function |
|
|
|
| False | True -> maxn |
|
|
|
| Node (v, _, _) -> v |
|
|
|
) in |
|
|
|
|
|
|
|
let count = Mem.memo (fun count -> fview (function |
|
|
|
| False -> 0 |
|
|
|
| True -> 1 |
|
|
|
| Node (v, l, h) -> |
|
|
|
assert (0 <= v && v < maxn || (Printf.printf "v = %d\n" v; false) ); |
|
|
|
(count l) lsl (get_var l - v - 1) + (count h) lsl (get_var h - v - 1) |
|
|
|
)) in |
|
|
|
fun bdd -> |
|
|
|
(count bdd) lsl (get_var bdd) |
|
|
|
let get_var = |
|
|
|
fview (function False | True -> maxn | Node (v, _, _) -> v) |
|
|
|
in |
|
|
|
let count = |
|
|
|
Mem.memo (fun count -> |
|
|
|
fview (function |
|
|
|
| False -> |
|
|
|
0 |
|
|
|
| True -> |
|
|
|
1 |
|
|
|
| Node (v, l, h) -> |
|
|
|
assert ( |
|
|
|
(0 <= v && v < maxn) || (Printf.printf "v = %d\n" v ; false) |
|
|
|
) ; |
|
|
|
(count l lsl (get_var l - v - 1)) |
|
|
|
+ (count h lsl (get_var h - v - 1)))) |
|
|
|
in |
|
|
|
fun bdd -> count bdd lsl get_var bdd |
|
|
|
|
|
|
|
let any_sat = |
|
|
|
let rec aux assign = fview (function |
|
|
|
| False -> None |
|
|
|
| True -> Some assign |
|
|
|
| Node (v, l, h) -> (match aux assign l with |
|
|
|
| None -> aux ((v, true) :: assign) h |
|
|
|
| Some assign -> Some ((v, false) :: assign))) |
|
|
|
in aux [] |
|
|
|
let rec aux assign = |
|
|
|
fview (function |
|
|
|
| False -> |
|
|
|
None |
|
|
|
| True -> |
|
|
|
Some assign |
|
|
|
| Node (v, l, h) -> ( |
|
|
|
match aux assign l with |
|
|
|
| None -> |
|
|
|
aux ((v, true) :: assign) h |
|
|
|
| Some assign -> |
|
|
|
Some ((v, false) :: assign) )) |
|
|
|
in |
|
|
|
aux [] |
|
|
|
|
|
|
|
let all_sat bdd = |
|
|
|
let add_assign v b = function |
|
|
|
| None -> None |
|
|
|
| Some assign -> Some ((v, b)::assign) |
|
|
|
| None -> |
|
|
|
None |
|
|
|
| Some assign -> |
|
|
|
Some ((v, b) :: assign) |
|
|
|
in |
|
|
|
|
|
|
|
let rec aux assign = fview (function |
|
|
|
| False -> [ None ] |
|
|
|
| True -> [ Some assign ] |
|
|
|
| Node (v, l, h) -> |
|
|
|
let add_assign = add_assign v in |
|
|
|
let aux = aux assign in |
|
|
|
(List.map (add_assign false) (aux l)) @ List.map (add_assign true) (aux h)) |
|
|
|
let rec aux assign = |
|
|
|
fview (function |
|
|
|
| False -> |
|
|
|
[None] |
|
|
|
| True -> |
|
|
|
[Some assign] |
|
|
|
| Node (v, l, h) -> |
|
|
|
let add_assign = add_assign v in |
|
|
|
let aux = aux assign in |
|
|
|
List.map (add_assign false) (aux l) |
|
|
|
@ List.map (add_assign true) (aux h)) |
|
|
|
in |
|
|
|
List.fold_left |
|
|
|
(fun acc -> function None -> acc | Some assign -> assign :: acc) |
|
|
|
[] (aux [] bdd) |
|
|
|
|
|
|
|
List.fold_left (fun acc -> |
|
|
|
function None -> acc | Some assign -> assign::acc |
|
|
|
) [] (aux [] bdd) |
|
|
|
|
|
|
|
(* TODO: in each assign, add all the unused vars. ? *) |
|
|
|
|
|
|
|
let random_sat maxn = |
|
|
|
let _ = count_sat maxn in |
|
|
|
let rec aux assign = fview (function |
|
|
|
| False -> None |
|
|
|
| True -> Some assign |
|
|
|
| Node (v, l, h) -> begin |
|
|
|
if is_sat l && is_sat h then begin |
|
|
|
if true (* TODO *) then aux ((v, false) :: assign) h |
|
|
|
else aux ((v, true) :: assign) l |
|
|
|
end else match aux assign l with |
|
|
|
| None -> aux ((v, true) :: assign) h |
|
|
|
| Some assign -> Some ((v, false) :: assign) |
|
|
|
end) |
|
|
|
in aux [] |
|
|
|
(* TODO: in each assign, add all the unused vars. ? *) |
|
|
|
|
|
|
|
let random_sat _ = |
|
|
|
(* let _ = count_sat maxn in *) |
|
|
|
let rec aux assign = |
|
|
|
fview (function |
|
|
|
| False -> |
|
|
|
None |
|
|
|
| True -> |
|
|
|
Some assign |
|
|
|
| Node (v, l, h) -> ( |
|
|
|
if is_sat l && is_sat h then |
|
|
|
if true (* TODO *) then aux ((v, false) :: assign) h |
|
|
|
else aux ((v, true) :: assign) l |
|
|
|
else |
|
|
|
match aux assign l with |
|
|
|
| None -> |
|
|
|
aux ((v, true) :: assign) h |
|
|
|
| Some assign -> |
|
|
|
Some ((v, false) :: assign) )) |
|
|
|
in |
|
|
|
aux [] |
|
|
|
end |
|
|
|