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.

555 lines
19 KiB

3 months ago
  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 "sylvan.h"
  12. #include "test_assert.h"
  13. #include "sylvan_int.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 int
  37. test_cache()
  38. {
  39. test_assert(cache_getused() == 0);
  40. /**
  41. * Test cache for large number of random entries
  42. */
  43. size_t number_add = 4000000;
  44. uint64_t *arr = (uint64_t*)malloc(sizeof(uint64_t)*4*number_add);
  45. for (size_t i=0; i<number_add*4; i++) arr[i] = xorshift_rand();
  46. for (size_t i=0; i<number_add; i++) {
  47. test_assert(cache_put(arr[4*i], arr[4*i+1], arr[4*i+2], arr[4*i+3]));
  48. uint64_t val;
  49. int res = cache_get(arr[4*i], arr[4*i+1], arr[4*i+2], &val);
  50. test_assert(res == 1);
  51. test_assert(val == arr[4*i+3]);
  52. }
  53. size_t count = 0;
  54. for (size_t i=0; i<number_add; i++) {
  55. uint64_t val;
  56. int res = cache_get(arr[4*i], arr[4*i+1], arr[4*i+2], &val);
  57. test_assert(res == 0 || val == arr[4*i+3]);
  58. if (res) count++;
  59. }
  60. test_assert(count == cache_getused());
  61. /**
  62. * Now also test for double entries
  63. */
  64. for (size_t i=0; i<number_add/2; i++) {
  65. test_assert(cache_put6(arr[8*i], arr[8*i+1], arr[8*i+2], arr[8*i+3], arr[8*i+4], arr[8*i+5], arr[8*i+6], arr[8*i+7]));
  66. uint64_t val1, val2;
  67. int res = cache_get6(arr[8*i], arr[8*i+1], arr[8*i+2], arr[8*i+3], arr[8*i+4], arr[8*i+5], &val1, &val2);
  68. test_assert(res == 1);
  69. test_assert(val1 == arr[8*i+6]);
  70. test_assert(val2 == arr[8*i+7]);
  71. }
  72. for (size_t i=0; i<number_add/2; i++) {
  73. uint64_t val1, val2;
  74. int res = cache_get6(arr[8*i], arr[8*i+1], arr[8*i+2], arr[8*i+3], arr[8*i+4], arr[8*i+5], &val1, &val2);
  75. test_assert(res == 0 || (val1 == arr[8*i+6] && val2 == arr[8*i+7]));
  76. }
  77. /**
  78. * And test that single entries are not corrupted
  79. */
  80. for (size_t i=0; i<number_add; i++) {
  81. uint64_t val;
  82. int res = cache_get(arr[4*i], arr[4*i+1], arr[4*i+2], &val);
  83. test_assert(res == 0 || val == arr[4*i+3]);
  84. }
  85. /**
  86. * TODO: multithreaded test
  87. */
  88. free(arr);
  89. return 0;
  90. }
  91. static inline BDD
  92. make_random(int i, int j)
  93. {
  94. if (i == j) return rng(0, 2) ? sylvan_true : sylvan_false;
  95. BDD yes = make_random(i+1, j);
  96. BDD no = make_random(i+1, j);
  97. BDD result = sylvan_invalid;
  98. switch(rng(0, 4)) {
  99. case 0:
  100. result = no;
  101. sylvan_deref(yes);
  102. break;
  103. case 1:
  104. result = yes;
  105. sylvan_deref(no);
  106. break;
  107. case 2:
  108. result = sylvan_ref(sylvan_makenode(i, yes, no));
  109. sylvan_deref(no);
  110. sylvan_deref(yes);
  111. break;
  112. case 3:
  113. default:
  114. result = sylvan_ref(sylvan_makenode(i, no, yes));
  115. sylvan_deref(no);
  116. sylvan_deref(yes);
  117. break;
  118. }
  119. return result;
  120. }
  121. static MDD
  122. make_random_ldd_set(int depth, int maxvalue, int elements)
  123. {
  124. uint32_t values[depth];
  125. MDD result = mtbdd_false; // empty set
  126. for (int i=0; i<elements; i++) {
  127. lddmc_refs_push(result);
  128. for (int j=0; j<depth; j++) {
  129. values[j] = rng(0, maxvalue);
  130. }
  131. result = lddmc_union_cube(result, values, depth);
  132. lddmc_refs_pop(1);
  133. }
  134. return result;
  135. }
  136. int testEqual(BDD a, BDD b)
  137. {
  138. if (a == b) return 1;
  139. if (a == sylvan_invalid) {
  140. fprintf(stderr, "a is invalid!\n");
  141. return 0;
  142. }
  143. if (b == sylvan_invalid) {
  144. fprintf(stderr, "b is invalid!\n");
  145. return 0;
  146. }
  147. fprintf(stderr, "a and b are not equal!\n");
  148. sylvan_fprint(stderr, a);fprintf(stderr, "\n");
  149. sylvan_fprint(stderr, b);fprintf(stderr, "\n");
  150. return 0;
  151. }
  152. int
  153. test_bdd()
  154. {
  155. test_assert(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_true) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_false)));
  156. test_assert(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_true) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_false)));
  157. test_assert(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_false) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_true)));
  158. test_assert(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_false) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_true)));
  159. return 0;
  160. }
  161. int
  162. test_cube()
  163. {
  164. LACE_ME;
  165. const BDDSET vars = sylvan_set_fromarray(((BDDVAR[]){1,2,3,4,6,8}), 6);
  166. uint8_t cube[6], check[6];
  167. int i, j;
  168. for (i=0;i<6;i++) cube[i] = rng(0,3);
  169. BDD bdd = sylvan_cube(vars, cube);
  170. sylvan_sat_one(bdd, vars, check);
  171. for (i=0; i<6;i++) test_assert(cube[i] == check[i] || (cube[i] == 2 && check[i] == 0));
  172. BDD picked_single = sylvan_pick_single_cube(bdd, vars);
  173. test_assert(testEqual(sylvan_and(picked_single, bdd), picked_single));
  174. assert(sylvan_satcount(picked_single, vars)==1);
  175. BDD picked = sylvan_pick_cube(bdd);
  176. test_assert(testEqual(sylvan_and(picked, bdd), picked));
  177. BDD t1 = sylvan_cube(vars, ((uint8_t[]){1,1,2,2,0,0}));
  178. BDD t2 = sylvan_cube(vars, ((uint8_t[]){1,1,1,0,0,2}));
  179. test_assert(testEqual(sylvan_union_cube(t1, vars, ((uint8_t[]){1,1,1,0,0,2})), sylvan_or(t1, t2)));
  180. t2 = sylvan_cube(vars, ((uint8_t[]){2,2,2,1,1,0}));
  181. test_assert(testEqual(sylvan_union_cube(t1, vars, ((uint8_t[]){2,2,2,1,1,0})), sylvan_or(t1, t2)));
  182. t2 = sylvan_cube(vars, ((uint8_t[]){1,1,1,0,0,0}));
  183. test_assert(testEqual(sylvan_union_cube(t1, vars, ((uint8_t[]){1,1,1,0,0,0})), sylvan_or(t1, t2)));
  184. bdd = make_random(1, 16);
  185. for (j=0;j<10;j++) {
  186. for (i=0;i<6;i++) cube[i] = rng(0,3);
  187. BDD c = sylvan_cube(vars, cube);
  188. test_assert(sylvan_union_cube(bdd, vars, cube) == sylvan_or(bdd, c));
  189. }
  190. for (i=0;i<10;i++) {
  191. picked = sylvan_pick_cube(bdd);
  192. test_assert(testEqual(sylvan_and(picked, bdd), picked));
  193. }
  194. // simple test for mtbdd_enum_all
  195. uint8_t arr[6];
  196. MTBDD leaf = mtbdd_enum_all_first(mtbdd_true, vars, arr, NULL);
  197. test_assert(leaf == mtbdd_true);
  198. test_assert(mtbdd_enum_all_first(mtbdd_true, vars, arr, NULL) == mtbdd_true);
  199. test_assert(arr[0] == 0 && arr[1] == 0 && arr[2] == 0 && arr[3] == 0 && arr[4] == 0 && arr[5] == 0);
  200. test_assert(mtbdd_enum_all_next(mtbdd_true, vars, arr, NULL) == mtbdd_true);
  201. test_assert(arr[0] == 0 && arr[1] == 0 && arr[2] == 0 && arr[3] == 0 && arr[4] == 0 && arr[5] == 1);
  202. test_assert(mtbdd_enum_all_next(mtbdd_true, vars, arr, NULL) == mtbdd_true);
  203. test_assert(arr[0] == 0 && arr[1] == 0 && arr[2] == 0 && arr[3] == 0 && arr[4] == 1 && arr[5] == 0);
  204. test_assert(mtbdd_enum_all_next(mtbdd_true, vars, arr, NULL) == mtbdd_true);
  205. test_assert(arr[0] == 0 && arr[1] == 0 && arr[2] == 0 && arr[3] == 0 && arr[4] == 1 && arr[5] == 1);
  206. test_assert(mtbdd_enum_all_next(mtbdd_true, vars, arr, NULL) == mtbdd_true);
  207. test_assert(arr[0] == 0 && arr[1] == 0 && arr[2] == 0 && arr[3] == 1 && arr[4] == 0 && arr[5] == 0);
  208. test_assert(mtbdd_enum_all_next(mtbdd_true, vars, arr, NULL) == mtbdd_true);
  209. test_assert(arr[0] == 0 && arr[1] == 0 && arr[2] == 0 && arr[3] == 1 && arr[4] == 0 && arr[5] == 1);
  210. test_assert(mtbdd_enum_all_next(mtbdd_true, vars, arr, NULL) == mtbdd_true);
  211. test_assert(arr[0] == 0 && arr[1] == 0 && arr[2] == 0 && arr[3] == 1 && arr[4] == 1 && arr[5] == 0);
  212. mtbdd_enum_all_first(mtbdd_true, vars, arr, NULL);
  213. size_t count = 1;
  214. while (mtbdd_enum_all_next(mtbdd_true, vars, arr, NULL) != mtbdd_false) {
  215. test_assert(count < 64);
  216. count++;
  217. }
  218. test_assert(count == 64);
  219. return 0;
  220. }
  221. static int
  222. test_operators()
  223. {
  224. // We need to test: xor, and, or, nand, nor, imp, biimp, invimp, diff, less
  225. LACE_ME;
  226. //int i;
  227. BDD a = sylvan_ithvar(1);
  228. BDD b = sylvan_ithvar(2);
  229. BDD one = make_random(1, 12);
  230. BDD two = make_random(6, 24);
  231. // Test or
  232. test_assert(testEqual(sylvan_or(a, b), sylvan_makenode(1, b, sylvan_true)));
  233. test_assert(testEqual(sylvan_or(a, b), sylvan_or(b, a)));
  234. test_assert(testEqual(sylvan_or(one, two), sylvan_or(two, one)));
  235. // Test and
  236. test_assert(testEqual(sylvan_and(a, b), sylvan_makenode(1, sylvan_false, b)));
  237. test_assert(testEqual(sylvan_and(a, b), sylvan_and(b, a)));
  238. test_assert(testEqual(sylvan_and(one, two), sylvan_and(two, one)));
  239. // Test xor
  240. test_assert(testEqual(sylvan_xor(a, b), sylvan_makenode(1, b, sylvan_not(b))));
  241. test_assert(testEqual(sylvan_xor(a, b), sylvan_xor(a, b)));
  242. test_assert(testEqual(sylvan_xor(a, b), sylvan_xor(b, a)));
  243. test_assert(testEqual(sylvan_xor(one, two), sylvan_xor(two, one)));
  244. test_assert(testEqual(sylvan_xor(a, b), sylvan_ite(a, sylvan_not(b), b)));
  245. // Test diff
  246. test_assert(testEqual(sylvan_diff(a, b), sylvan_diff(a, b)));
  247. test_assert(testEqual(sylvan_diff(a, b), sylvan_diff(a, sylvan_and(a, b))));
  248. test_assert(testEqual(sylvan_diff(a, b), sylvan_and(a, sylvan_not(b))));
  249. test_assert(testEqual(sylvan_diff(a, b), sylvan_ite(b, sylvan_false, a)));
  250. test_assert(testEqual(sylvan_diff(one, two), sylvan_diff(one, two)));
  251. test_assert(testEqual(sylvan_diff(one, two), sylvan_diff(one, sylvan_and(one, two))));
  252. test_assert(testEqual(sylvan_diff(one, two), sylvan_and(one, sylvan_not(two))));
  253. test_assert(testEqual(sylvan_diff(one, two), sylvan_ite(two, sylvan_false, one)));
  254. // Test biimp
  255. test_assert(testEqual(sylvan_biimp(a, b), sylvan_makenode(1, sylvan_not(b), b)));
  256. test_assert(testEqual(sylvan_biimp(a, b), sylvan_biimp(b, a)));
  257. test_assert(testEqual(sylvan_biimp(one, two), sylvan_biimp(two, one)));
  258. // Test nand / and
  259. test_assert(testEqual(sylvan_not(sylvan_and(a, b)), sylvan_nand(b, a)));
  260. test_assert(testEqual(sylvan_not(sylvan_and(one, two)), sylvan_nand(two, one)));
  261. // Test nor / or
  262. test_assert(testEqual(sylvan_not(sylvan_or(a, b)), sylvan_nor(b, a)));
  263. test_assert(testEqual(sylvan_not(sylvan_or(one, two)), sylvan_nor(two, one)));
  264. // Test xor / biimp
  265. test_assert(testEqual(sylvan_xor(a, b), sylvan_not(sylvan_biimp(b, a))));
  266. test_assert(testEqual(sylvan_xor(one, two), sylvan_not(sylvan_biimp(two, one))));
  267. // Test imp
  268. test_assert(testEqual(sylvan_imp(a, b), sylvan_ite(a, b, sylvan_true)));
  269. test_assert(testEqual(sylvan_imp(one, two), sylvan_ite(one, two, sylvan_true)));
  270. test_assert(testEqual(sylvan_imp(one, two), sylvan_not(sylvan_diff(one, two))));
  271. test_assert(testEqual(sylvan_invimp(one, two), sylvan_not(sylvan_less(one, two))));
  272. test_assert(testEqual(sylvan_imp(a, b), sylvan_invimp(b, a)));
  273. test_assert(testEqual(sylvan_imp(one, two), sylvan_invimp(two, one)));
  274. return 0;
  275. }
  276. int
  277. test_relprod()
  278. {
  279. LACE_ME;
  280. BDDVAR vars[] = {0,2,4};
  281. BDDVAR all_vars[] = {0,1,2,3,4,5};
  282. BDDSET vars_set = sylvan_set_fromarray(vars, 3);
  283. BDDSET all_vars_set = sylvan_set_fromarray(all_vars, 6);
  284. BDD s, t, next, prev;
  285. BDD zeroes, ones;
  286. // transition relation: 000 --> 111 and !000 --> 000
  287. t = sylvan_false;
  288. t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){0,1,0,1,0,1}));
  289. t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){1,0,2,0,2,0}));
  290. t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){2,0,1,0,2,0}));
  291. t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){2,0,2,0,1,0}));
  292. s = sylvan_cube(vars_set, (uint8_t[]){0,0,1});
  293. zeroes = sylvan_cube(vars_set, (uint8_t[]){0,0,0});
  294. ones = sylvan_cube(vars_set, (uint8_t[]){1,1,1});
  295. next = sylvan_relnext(s, t, all_vars_set);
  296. prev = sylvan_relprev(t, next, all_vars_set);
  297. test_assert(next == zeroes);
  298. test_assert(prev == sylvan_not(zeroes));
  299. next = sylvan_relnext(next, t, all_vars_set);
  300. prev = sylvan_relprev(t, next, all_vars_set);
  301. test_assert(next == ones);
  302. test_assert(prev == zeroes);
  303. t = sylvan_cube(all_vars_set, (uint8_t[]){0,0,0,0,0,1});
  304. test_assert(sylvan_relprev(t, s, all_vars_set) == zeroes);
  305. test_assert(sylvan_relprev(t, sylvan_not(s), all_vars_set) == sylvan_false);
  306. test_assert(sylvan_relnext(s, t, all_vars_set) == sylvan_false);
  307. test_assert(sylvan_relnext(zeroes, t, all_vars_set) == s);
  308. t = sylvan_cube(all_vars_set, (uint8_t[]){0,0,0,0,0,2});
  309. test_assert(sylvan_relprev(t, s, all_vars_set) == zeroes);
  310. test_assert(sylvan_relprev(t, zeroes, all_vars_set) == zeroes);
  311. test_assert(sylvan_relnext(sylvan_not(zeroes), t, all_vars_set) == sylvan_false);
  312. return 0;
  313. }
  314. int
  315. test_compose()
  316. {
  317. LACE_ME;
  318. BDD a = sylvan_ithvar(1);
  319. BDD b = sylvan_ithvar(2);
  320. BDD a_or_b = sylvan_or(a, b);
  321. BDD one = make_random(3, 16);
  322. BDD two = make_random(8, 24);
  323. BDDMAP map = sylvan_map_empty();
  324. map = sylvan_map_add(map, 1, one);
  325. map = sylvan_map_add(map, 2, two);
  326. test_assert(sylvan_map_key(map) == 1);
  327. test_assert(sylvan_map_value(map) == one);
  328. test_assert(sylvan_map_key(sylvan_map_next(map)) == 2);
  329. test_assert(sylvan_map_value(sylvan_map_next(map)) == two);
  330. test_assert(testEqual(one, sylvan_compose(a, map)));
  331. test_assert(testEqual(two, sylvan_compose(b, map)));
  332. test_assert(testEqual(sylvan_or(one, two), sylvan_compose(a_or_b, map)));
  333. map = sylvan_map_add(map, 2, one);
  334. test_assert(testEqual(sylvan_compose(a_or_b, map), one));
  335. map = sylvan_map_add(map, 1, two);
  336. test_assert(testEqual(sylvan_or(one, two), sylvan_compose(a_or_b, map)));
  337. test_assert(testEqual(sylvan_and(one, two), sylvan_compose(sylvan_and(a, b), map)));
  338. // test that composing [0:=true] on "0" yields true
  339. map = sylvan_map_add(sylvan_map_empty(), 1, sylvan_true);
  340. test_assert(testEqual(sylvan_compose(a, map), sylvan_true));
  341. // test that composing [0:=false] on "0" yields false
  342. map = sylvan_map_add(sylvan_map_empty(), 1, sylvan_false);
  343. test_assert(testEqual(sylvan_compose(a, map), sylvan_false));
  344. return 0;
  345. }
  346. int
  347. test_ldd()
  348. {
  349. // very basic testing of makenode
  350. for (int i=0; i<10; i++) {
  351. uint32_t value = rng(0, 100);
  352. MDD m = lddmc_makenode(value, lddmc_true, lddmc_false);
  353. test_assert(lddmc_getvalue(m) == value);
  354. test_assert(lddmc_getdown(m) == lddmc_true);
  355. test_assert(lddmc_getright(m) == lddmc_false);
  356. test_assert(lddmc_iscopy(m) == 0);
  357. test_assert(lddmc_follow(m, value) == lddmc_true);
  358. for (int j=0; j<100; j++) {
  359. uint32_t other_value = rng(0, 100);
  360. if (value != other_value) test_assert(lddmc_follow(m, other_value) == lddmc_false);
  361. }
  362. }
  363. // test handling of the copy node by primitives
  364. MDD m = lddmc_make_copynode(lddmc_true, lddmc_false);
  365. test_assert(lddmc_iscopy(m) == 1);
  366. test_assert(lddmc_getvalue(m) == 0);
  367. test_assert(lddmc_getdown(m) == lddmc_true);
  368. test_assert(lddmc_getright(m) == lddmc_false);
  369. m = lddmc_extendnode(m, 0, lddmc_true);
  370. test_assert(lddmc_iscopy(m) == 1);
  371. test_assert(lddmc_getvalue(m) == 0);
  372. test_assert(lddmc_getdown(m) == lddmc_true);
  373. test_assert(lddmc_getright(m) != lddmc_false);
  374. test_assert(lddmc_follow(m, 0) == lddmc_true);
  375. test_assert(lddmc_getvalue(lddmc_getright(m)) == 0);
  376. test_assert(lddmc_iscopy(lddmc_getright(m)) == 0);
  377. test_assert(lddmc_makenode(0, lddmc_true, lddmc_false) == lddmc_getright(m));
  378. LACE_ME;
  379. // test union_cube
  380. for (int i=0; i<100; i++) {
  381. int depth = rng(1, 6);
  382. int elements = rng(1, 30);
  383. m = make_random_ldd_set(depth, 10, elements);
  384. assert(m != lddmc_true);
  385. assert(m != lddmc_false);
  386. assert(lddmc_satcount(m) <= elements);
  387. assert(lddmc_satcount(m) >= 1);
  388. }
  389. // test simply transition relation
  390. {
  391. MDD states, rel, meta, expected;
  392. // relation: (0,0) to (1,1)
  393. rel = lddmc_cube((uint32_t[]){0,1,0,1}, 4);
  394. test_assert(lddmc_satcount(rel) == 1);
  395. // relation: (0,0) to (2,2)
  396. rel = lddmc_union_cube(rel, (uint32_t[]){0,2,0,2}, 4);
  397. test_assert(lddmc_satcount(rel) == 2);
  398. // meta: read write read write
  399. meta = lddmc_cube((uint32_t[]){1,2,1,2}, 4);
  400. test_assert(lddmc_satcount(meta) == 1);
  401. // initial state: (0,0)
  402. states = lddmc_cube((uint32_t[]){0,0}, 2);
  403. test_assert(lddmc_satcount(states) == 1);
  404. // relprod should give two states
  405. states = lddmc_relprod(states, rel, meta);
  406. test_assert(lddmc_satcount(states) == 2);
  407. // relprod should give states (1,1) and (2,2)
  408. expected = lddmc_cube((uint32_t[]){1,1}, 2);
  409. expected = lddmc_union_cube(expected, (uint32_t[]){2,2}, 2);
  410. test_assert(states == expected);
  411. // now test relprod union on the simple example
  412. states = lddmc_cube((uint32_t[]){0,0}, 2);
  413. states = lddmc_relprod_union(states, rel, meta, states);
  414. test_assert(lddmc_satcount(states) == 3);
  415. test_assert(states == lddmc_union(states, expected));
  416. // now create transition (1,1) --> (1,1) (using copy nodes)
  417. rel = lddmc_cube_copy((uint32_t[]){1,0,1,0}, (int[]){0,1,0,1}, 4);
  418. states = lddmc_relprod(states, rel, meta);
  419. // the result should be just state (1,1)
  420. test_assert(states == lddmc_cube((uint32_t[]){1,1}, 2));
  421. MDD statezero = lddmc_cube((uint32_t[]){0,0}, 2);
  422. states = lddmc_union_cube(statezero, (uint32_t[]){1,1}, 2);
  423. test_assert(lddmc_relprod_union(states, rel, meta, statezero) == states);
  424. // now create transition (*,*) --> (*,*) (copy nodes)
  425. rel = lddmc_cube_copy((uint32_t[]){0,0}, (int[]){1,1}, 2);
  426. meta = lddmc_cube((uint32_t[]){4,4}, 2);
  427. states = make_random_ldd_set(2, 10, 10);
  428. MDD states2 = make_random_ldd_set(2, 10, 10);
  429. test_assert(lddmc_union(states, states2) == lddmc_relprod_union(states, rel, meta, states2));
  430. }
  431. return 0;
  432. }
  433. int runtests()
  434. {
  435. // we are not testing garbage collection
  436. sylvan_gc_disable();
  437. if (test_cache()) return 1;
  438. if (test_bdd()) return 1;
  439. for (int j=0;j<10;j++) if (test_cube()) return 1;
  440. for (int j=0;j<10;j++) if (test_relprod()) return 1;
  441. for (int j=0;j<10;j++) if (test_compose()) return 1;
  442. for (int j=0;j<10;j++) if (test_operators()) return 1;
  443. if (test_ldd()) return 1;
  444. return 0;
  445. }
  446. int main()
  447. {
  448. // Standard Lace initialization with 1 worker
  449. lace_init(1, 0);
  450. lace_startup(0, NULL, NULL);
  451. // Simple Sylvan initialization, also initialize BDD, MTBDD and LDD support
  452. sylvan_set_sizes(1LL<<20, 1LL<<20, 1LL<<16, 1LL<<16);
  453. sylvan_init_package();
  454. sylvan_init_bdd();
  455. sylvan_init_mtbdd();
  456. sylvan_init_ldd();
  457. int res = runtests();
  458. sylvan_quit();
  459. lace_exit();
  460. return res;
  461. }