You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

331 lines
10 KiB

  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <pthread.h>
  6. #include <unistd.h>
  7. #include <time.h>
  8. #include <sys/types.h>
  9. #include <sys/time.h>
  10. #include <inttypes.h>
  11. #include "llmsset.h"
  12. #include "sylvan.h"
  13. #include "test_assert.h"
  14. __thread uint64_t seed = 1;
  15. uint64_t
  16. xorshift_rand(void)
  17. {
  18. uint64_t x = seed;
  19. if (seed == 0) seed = rand();
  20. x ^= x >> 12;
  21. x ^= x << 25;
  22. x ^= x >> 27;
  23. seed = x;
  24. return x * 2685821657736338717LL;
  25. }
  26. double
  27. uniform_deviate(uint64_t seed)
  28. {
  29. return seed * (1.0 / (0xffffffffffffffffL + 1.0));
  30. }
  31. int
  32. rng(int low, int high)
  33. {
  34. return low + uniform_deviate(xorshift_rand()) * (high-low);
  35. }
  36. static inline BDD
  37. make_random(int i, int j)
  38. {
  39. if (i == j) return rng(0, 2) ? sylvan_true : sylvan_false;
  40. BDD yes = make_random(i+1, j);
  41. BDD no = make_random(i+1, j);
  42. BDD result = sylvan_invalid;
  43. switch(rng(0, 4)) {
  44. case 0:
  45. result = no;
  46. sylvan_deref(yes);
  47. break;
  48. case 1:
  49. result = yes;
  50. sylvan_deref(no);
  51. break;
  52. case 2:
  53. result = sylvan_ref(sylvan_makenode(i, yes, no));
  54. sylvan_deref(no);
  55. sylvan_deref(yes);
  56. break;
  57. case 3:
  58. default:
  59. result = sylvan_ref(sylvan_makenode(i, no, yes));
  60. sylvan_deref(no);
  61. sylvan_deref(yes);
  62. break;
  63. }
  64. return result;
  65. }
  66. int testEqual(BDD a, BDD b)
  67. {
  68. if (a == b) return 1;
  69. if (a == sylvan_invalid) {
  70. fprintf(stderr, "a is invalid!\n");
  71. return 0;
  72. }
  73. if (b == sylvan_invalid) {
  74. fprintf(stderr, "b is invalid!\n");
  75. return 0;
  76. }
  77. fprintf(stderr, "a and b are not equal!\n");
  78. sylvan_fprint(stderr, a);fprintf(stderr, "\n");
  79. sylvan_fprint(stderr, b);fprintf(stderr, "\n");
  80. return 0;
  81. }
  82. int
  83. test_bdd()
  84. {
  85. test_assert(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_true) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_false)));
  86. test_assert(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_true) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_false)));
  87. test_assert(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_false) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_true)));
  88. test_assert(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_false) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_true)));
  89. return 0;
  90. }
  91. int
  92. test_cube()
  93. {
  94. LACE_ME;
  95. BDDSET vars = sylvan_set_fromarray(((BDDVAR[]){1,2,3,4,6,8}), 6);
  96. uint8_t cube[6], check[6];
  97. int i, j;
  98. for (i=0;i<6;i++) cube[i] = rng(0,3);
  99. BDD bdd = sylvan_cube(vars, cube);
  100. sylvan_sat_one(bdd, vars, check);
  101. for (i=0; i<6;i++) test_assert(cube[i] == check[i] || (cube[i] == 2 && check[i] == 0));
  102. BDD picked = sylvan_pick_cube(bdd);
  103. test_assert(testEqual(sylvan_and(picked, bdd), picked));
  104. BDD t1 = sylvan_cube(vars, ((uint8_t[]){1,1,2,2,0,0}));
  105. BDD t2 = sylvan_cube(vars, ((uint8_t[]){1,1,1,0,0,2}));
  106. test_assert(testEqual(sylvan_union_cube(t1, vars, ((uint8_t[]){1,1,1,0,0,2})), sylvan_or(t1, t2)));
  107. t2 = sylvan_cube(vars, ((uint8_t[]){2,2,2,1,1,0}));
  108. test_assert(testEqual(sylvan_union_cube(t1, vars, ((uint8_t[]){2,2,2,1,1,0})), sylvan_or(t1, t2)));
  109. t2 = sylvan_cube(vars, ((uint8_t[]){1,1,1,0,0,0}));
  110. test_assert(testEqual(sylvan_union_cube(t1, vars, ((uint8_t[]){1,1,1,0,0,0})), sylvan_or(t1, t2)));
  111. bdd = make_random(1, 16);
  112. for (j=0;j<10;j++) {
  113. for (i=0;i<6;i++) cube[i] = rng(0,3);
  114. BDD c = sylvan_cube(vars, cube);
  115. test_assert(sylvan_union_cube(bdd, vars, cube) == sylvan_or(bdd, c));
  116. }
  117. for (i=0;i<10;i++) {
  118. picked = sylvan_pick_cube(bdd);
  119. test_assert(testEqual(sylvan_and(picked, bdd), picked));
  120. }
  121. return 0;
  122. }
  123. static int
  124. test_operators()
  125. {
  126. // We need to test: xor, and, or, nand, nor, imp, biimp, invimp, diff, less
  127. LACE_ME;
  128. //int i;
  129. BDD a = sylvan_ithvar(1);
  130. BDD b = sylvan_ithvar(2);
  131. BDD one = make_random(1, 12);
  132. BDD two = make_random(6, 24);
  133. // Test or
  134. test_assert(testEqual(sylvan_or(a, b), sylvan_makenode(1, b, sylvan_true)));
  135. test_assert(testEqual(sylvan_or(a, b), sylvan_or(b, a)));
  136. test_assert(testEqual(sylvan_or(one, two), sylvan_or(two, one)));
  137. // Test and
  138. test_assert(testEqual(sylvan_and(a, b), sylvan_makenode(1, sylvan_false, b)));
  139. test_assert(testEqual(sylvan_and(a, b), sylvan_and(b, a)));
  140. test_assert(testEqual(sylvan_and(one, two), sylvan_and(two, one)));
  141. // Test xor
  142. test_assert(testEqual(sylvan_xor(a, b), sylvan_makenode(1, b, sylvan_not(b))));
  143. test_assert(testEqual(sylvan_xor(a, b), sylvan_xor(a, b)));
  144. test_assert(testEqual(sylvan_xor(a, b), sylvan_xor(b, a)));
  145. test_assert(testEqual(sylvan_xor(one, two), sylvan_xor(two, one)));
  146. test_assert(testEqual(sylvan_xor(a, b), sylvan_ite(a, sylvan_not(b), b)));
  147. // Test diff
  148. test_assert(testEqual(sylvan_diff(a, b), sylvan_diff(a, b)));
  149. test_assert(testEqual(sylvan_diff(a, b), sylvan_diff(a, sylvan_and(a, b))));
  150. test_assert(testEqual(sylvan_diff(a, b), sylvan_and(a, sylvan_not(b))));
  151. test_assert(testEqual(sylvan_diff(a, b), sylvan_ite(b, sylvan_false, a)));
  152. test_assert(testEqual(sylvan_diff(one, two), sylvan_diff(one, two)));
  153. test_assert(testEqual(sylvan_diff(one, two), sylvan_diff(one, sylvan_and(one, two))));
  154. test_assert(testEqual(sylvan_diff(one, two), sylvan_and(one, sylvan_not(two))));
  155. test_assert(testEqual(sylvan_diff(one, two), sylvan_ite(two, sylvan_false, one)));
  156. // Test biimp
  157. test_assert(testEqual(sylvan_biimp(a, b), sylvan_makenode(1, sylvan_not(b), b)));
  158. test_assert(testEqual(sylvan_biimp(a, b), sylvan_biimp(b, a)));
  159. test_assert(testEqual(sylvan_biimp(one, two), sylvan_biimp(two, one)));
  160. // Test nand / and
  161. test_assert(testEqual(sylvan_not(sylvan_and(a, b)), sylvan_nand(b, a)));
  162. test_assert(testEqual(sylvan_not(sylvan_and(one, two)), sylvan_nand(two, one)));
  163. // Test nor / or
  164. test_assert(testEqual(sylvan_not(sylvan_or(a, b)), sylvan_nor(b, a)));
  165. test_assert(testEqual(sylvan_not(sylvan_or(one, two)), sylvan_nor(two, one)));
  166. // Test xor / biimp
  167. test_assert(testEqual(sylvan_xor(a, b), sylvan_not(sylvan_biimp(b, a))));
  168. test_assert(testEqual(sylvan_xor(one, two), sylvan_not(sylvan_biimp(two, one))));
  169. // Test imp
  170. test_assert(testEqual(sylvan_imp(a, b), sylvan_ite(a, b, sylvan_true)));
  171. test_assert(testEqual(sylvan_imp(one, two), sylvan_ite(one, two, sylvan_true)));
  172. test_assert(testEqual(sylvan_imp(one, two), sylvan_not(sylvan_diff(one, two))));
  173. test_assert(testEqual(sylvan_invimp(one, two), sylvan_not(sylvan_less(one, two))));
  174. test_assert(testEqual(sylvan_imp(a, b), sylvan_invimp(b, a)));
  175. test_assert(testEqual(sylvan_imp(one, two), sylvan_invimp(two, one)));
  176. return 0;
  177. }
  178. int
  179. test_relprod()
  180. {
  181. LACE_ME;
  182. BDDVAR vars[] = {0,2,4};
  183. BDDVAR all_vars[] = {0,1,2,3,4,5};
  184. BDDSET vars_set = sylvan_set_fromarray(vars, 3);
  185. BDDSET all_vars_set = sylvan_set_fromarray(all_vars, 6);
  186. BDD s, t, next, prev;
  187. BDD zeroes, ones;
  188. // transition relation: 000 --> 111 and !000 --> 000
  189. t = sylvan_false;
  190. t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){0,1,0,1,0,1}));
  191. t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){1,0,2,0,2,0}));
  192. t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){2,0,1,0,2,0}));
  193. t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){2,0,2,0,1,0}));
  194. s = sylvan_cube(vars_set, (uint8_t[]){0,0,1});
  195. zeroes = sylvan_cube(vars_set, (uint8_t[]){0,0,0});
  196. ones = sylvan_cube(vars_set, (uint8_t[]){1,1,1});
  197. next = sylvan_relnext(s, t, all_vars_set);
  198. prev = sylvan_relprev(t, next, all_vars_set);
  199. test_assert(next == zeroes);
  200. test_assert(prev == sylvan_not(zeroes));
  201. next = sylvan_relnext(next, t, all_vars_set);
  202. prev = sylvan_relprev(t, next, all_vars_set);
  203. test_assert(next == ones);
  204. test_assert(prev == zeroes);
  205. t = sylvan_cube(all_vars_set, (uint8_t[]){0,0,0,0,0,1});
  206. test_assert(sylvan_relprev(t, s, all_vars_set) == zeroes);
  207. test_assert(sylvan_relprev(t, sylvan_not(s), all_vars_set) == sylvan_false);
  208. test_assert(sylvan_relnext(s, t, all_vars_set) == sylvan_false);
  209. test_assert(sylvan_relnext(zeroes, t, all_vars_set) == s);
  210. t = sylvan_cube(all_vars_set, (uint8_t[]){0,0,0,0,0,2});
  211. test_assert(sylvan_relprev(t, s, all_vars_set) == zeroes);
  212. test_assert(sylvan_relprev(t, zeroes, all_vars_set) == zeroes);
  213. test_assert(sylvan_relnext(sylvan_not(zeroes), t, all_vars_set) == sylvan_false);
  214. return 0;
  215. }
  216. int
  217. test_compose()
  218. {
  219. LACE_ME;
  220. BDD a = sylvan_ithvar(1);
  221. BDD b = sylvan_ithvar(2);
  222. BDD a_or_b = sylvan_or(a, b);
  223. BDD one = make_random(3, 16);
  224. BDD two = make_random(8, 24);
  225. BDDMAP map = sylvan_map_empty();
  226. map = sylvan_map_add(map, 1, one);
  227. map = sylvan_map_add(map, 2, two);
  228. test_assert(sylvan_map_key(map) == 1);
  229. test_assert(sylvan_map_value(map) == one);
  230. test_assert(sylvan_map_key(sylvan_map_next(map)) == 2);
  231. test_assert(sylvan_map_value(sylvan_map_next(map)) == two);
  232. test_assert(testEqual(one, sylvan_compose(a, map)));
  233. test_assert(testEqual(two, sylvan_compose(b, map)));
  234. test_assert(testEqual(sylvan_or(one, two), sylvan_compose(a_or_b, map)));
  235. map = sylvan_map_add(map, 2, one);
  236. test_assert(testEqual(sylvan_compose(a_or_b, map), one));
  237. map = sylvan_map_add(map, 1, two);
  238. test_assert(testEqual(sylvan_or(one, two), sylvan_compose(a_or_b, map)));
  239. test_assert(testEqual(sylvan_and(one, two), sylvan_compose(sylvan_and(a, b), map)));
  240. return 0;
  241. }
  242. int runtests()
  243. {
  244. // we are not testing garbage collection
  245. sylvan_gc_disable();
  246. if (test_bdd()) return 1;
  247. for (int j=0;j<10;j++) if (test_cube()) return 1;
  248. for (int j=0;j<10;j++) if (test_relprod()) return 1;
  249. for (int j=0;j<10;j++) if (test_compose()) return 1;
  250. for (int j=0;j<10;j++) if (test_operators()) return 1;
  251. return 0;
  252. }
  253. int main()
  254. {
  255. // Standard Lace initialization with 1 worker
  256. lace_init(1, 0);
  257. lace_startup(0, NULL, NULL);
  258. // Simple Sylvan initialization, also initialize BDD support
  259. sylvan_init_package(1LL<<20, 1LL<<20, 1LL<<16, 1LL<<16);
  260. sylvan_init_bdd(1);
  261. int res = runtests();
  262. sylvan_quit();
  263. lace_exit();
  264. return res;
  265. }