summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/Makefile2
-rw-r--r--test/Results/bdd.out1
-rw-r--r--test/bdd.ml210
3 files changed, 212 insertions, 1 deletions
diff --git a/test/Makefile b/test/Makefile
index 0877f021b..10a5601da 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -11,7 +11,7 @@ CODERUNPARAMS=CAMLRUNPARAM='o=100'
BYTE_EXE=fib.byt takc.byt taku.byt sieve.byt quicksort.byt quicksort.fast.byt \
fft.byt fft.fast.byt soli.byt soli.fast.byt boyer.byt kb.byt \
- nucleic.byt genlex.byt
+ nucleic.byt genlex.byt bdd.byt
CODE_EXE=$(BYTE_EXE:.byt=.out)
diff --git a/test/Results/bdd.out b/test/Results/bdd.out
new file mode 100644
index 000000000..d86bac9de
--- /dev/null
+++ b/test/Results/bdd.out
@@ -0,0 +1 @@
+OK
diff --git a/test/bdd.ml b/test/bdd.ml
new file mode 100644
index 000000000..50f1414ef
--- /dev/null
+++ b/test/bdd.ml
@@ -0,0 +1,210 @@
+type bdd = One | Zero | Node of bdd * int * int * bdd
+
+let rec eval bdd vars =
+ match bdd with
+ Zero -> false
+ | One -> true
+ | Node(l, v, _, h) ->
+ if vars.(v) then eval h vars else eval l vars
+
+let rec getId bdd =
+ match bdd with
+ Node(_,_,id,_) -> id
+ | Zero -> 0
+ | One -> 1
+
+let initSize_1 = 8*1024 - 1
+let nodeC = ref 1
+let sz_1 = ref initSize_1
+let htab = ref(Array.create (!sz_1+1) [])
+let n_items = ref 0
+let hashVal x y v = x lsl 1 + y + v lsl 2
+
+let resize newSize =
+ let arr = !htab in
+ let newSz_1 = newSize-1 in
+ let newArr = Array.create newSize [] in
+ let rec copyBucket bucket =
+ match bucket with
+ [] -> ()
+ | n ::ns ->
+ match n with
+ Node(l,v,_,h) ->
+ let ind = hashVal (getId l) (getId h) v land newSz_1
+ in
+ newArr.(ind) <- (n :: newArr.(ind));
+ copyBucket ns
+ in
+ for n = 0 to !sz_1 do
+ copyBucket(arr.(n))
+ done;
+ htab := newArr;
+ sz_1 := newSz_1
+
+
+let rec insert idl idh v ind bucket newNode =
+ if !n_items <= !sz_1
+ then ( (!htab).(ind) <- (newNode :: bucket);
+ incr n_items )
+ else ( resize(!sz_1 + !sz_1 + 2);
+ let ind = hashVal idl idh v land (!sz_1)
+ in
+ (!htab).(ind) <- newNode :: (!htab).(ind)
+ )
+
+
+let resetUnique () = (
+ sz_1 := initSize_1;
+ htab := Array.create (!sz_1+1) [];
+ n_items := 0;
+ nodeC := 1
+ )
+
+let mkNode low v high =
+ let idl = getId low in
+ let idh = getId high
+ in
+ if idl = idh
+ then low
+ else let ind = hashVal idl idh v land (!sz_1) in
+ let bucket = (!htab).(ind) in
+ let rec lookup b =
+ match b with
+ [] -> let n = Node(low, v, (incr nodeC; !nodeC), high)
+ in
+ insert (getId low) (getId high) v ind bucket n; n
+ | n :: ns ->
+ match n with
+ Node(l,v',id,h) -> if v=v' & idl=getId l & idh=getId h
+ then n else lookup ns
+ in
+ lookup bucket
+
+
+type ordering = LESS | EQUAL | GREATER
+
+let cmpVar x y = if x<y then LESS else if x>y then GREATER else EQUAL
+
+let zero = Zero
+let one = One
+
+let mkVar x = mkNode zero x one
+
+
+let cacheSize = 1999
+let andslot1 = Array.create cacheSize 0
+let andslot2 = Array.create cacheSize 0
+let andslot3 = Array.create cacheSize zero
+let xorslot1 = Array.create cacheSize 0
+let xorslot2 = Array.create cacheSize 0
+let xorslot3 = Array.create cacheSize zero
+let notslot1 = Array.create cacheSize 0
+let notslot2 = Array.create cacheSize one
+let hash x y = ((x lsl 1)+y) mod cacheSize
+
+let rec not n =
+match n with
+ Zero -> One
+| One -> Zero
+| Node(l, v, id, r) -> let h = id mod cacheSize
+ in
+ if id=notslot1.(h) then notslot2.(h)
+ else let f = mkNode (not l) v (not r)
+ in
+ notslot1.(h) <- id; notslot2.(h) <- f; f
+
+let rec and2 n1 n2 =
+match n1 with
+ Node(l1, v1, i1, r1)
+ -> (match n2 with
+ Node(l2, v2, i2, r2)
+ -> let h = hash i1 i2
+ in
+ if i1=andslot1.(h) & i2=andslot2.(h) then andslot3.(h)
+ else let f = match cmpVar v1 v2 with
+ EQUAL -> mkNode (and2 l1 l2) v1 (and2 r1 r2)
+ | LESS -> mkNode (and2 l1 n2) v1 (and2 r1 n2)
+ | GREATER -> mkNode (and2 n1 l2) v2 (and2 n1 r2)
+ in
+ andslot1.(h) <- i1;
+ andslot2.(h) <- i2;
+ andslot3.(h) <- f;
+ f
+ | Zero -> Zero
+ | One -> n1)
+| Zero -> Zero
+| One -> n2
+
+
+let rec xor n1 n2 =
+match n1 with
+ Node(l1, v1, i1, r1)
+ -> (match n2 with
+ Node(l2, v2, i2, r2)
+ -> let h = hash i1 i2
+ in
+ if i1=andslot1.(h) & i2=andslot2.(h) then andslot3.(h)
+ else let f = match cmpVar v1 v2 with
+ EQUAL -> mkNode (xor l1 l2) v1 (xor r1 r2)
+ | LESS -> mkNode (xor l1 n2) v1 (xor r1 n2)
+ | GREATER -> mkNode (xor n1 l2) v2 (xor n1 r2)
+ in
+ andslot1.(h) <- i1;
+ andslot2.(h) <- i2;
+ andslot3.(h) <- f;
+ f
+ | Zero -> n1
+ | One -> not n1)
+| Zero -> n2
+| One -> not n2
+
+let hwb n =
+ let rec h i j = if i=j
+ then mkVar i
+ else xor (and2 (not(mkVar j)) (h i (j-1)))
+ (and2 (mkVar j) (g i (j-1)))
+ and g i j = if i=j
+ then mkVar i
+ else xor (and2 (not(mkVar i)) (h (i+1) j))
+ (and2 (mkVar i) (g (i+1) j))
+ in
+ h 1 n
+
+(* Testing *)
+let seed = ref 0
+
+let random() =
+ seed := !seed * 25173 + 17431; !seed land 1 > 0
+
+let random_vars n =
+ let vars = Array.create n false in
+ for i = 0 to n - 1 do vars.(i) <- random() done;
+ vars
+
+let test_hwb bdd vars =
+ (* We should have
+ eval bdd vars = vars.(n) if n > 0
+ eval bdd vars = 0 if n = 0
+ where n is the number of "true" elements in vars. *)
+ let ntrue = ref 0 in
+ for i = 0 to Array.length vars - 1 do
+ if vars.(i) then incr ntrue
+ done;
+ eval bdd vars = (if !ntrue > 0 then vars.(!ntrue) else false)
+
+let main () =
+ let n =
+ if Array.length Sys.argv >= 2 then int_of_string Sys.argv.(1) else 20 in
+ let ntests =
+ if Array.length Sys.argv >= 3 then int_of_string Sys.argv.(2) else 50 in
+ let bdd = hwb n in
+ let succeeded = ref true in
+ for i = 1 to ntests do
+ succeeded := !succeeded || test_hwb bdd (random_vars n)
+ done;
+ if !succeeded
+ then print_string "OK\n"
+ else print_string "FAILED\n";
+ exit 0
+
+let _ = main()