#include #include #include #include #include #include #include #include #include #include #include #include "llmsset.h" #include "sylvan.h" #define BLACK "\33[22;30m" #define GRAY "\33[01;30m" #define RED "\33[22;31m" #define LRED "\33[01;31m" #define GREEN "\33[22;32m" #define LGREEN "\33[01;32m" #define BLUE "\33[22;34m" #define LBLUE "\33[01;34m" #define BROWN "\33[22;33m" #define YELLOW "\33[01;33m" #define CYAN "\33[22;36m" #define LCYAN "\33[22;36m" #define MAGENTA "\33[22;35m" #define LMAGENTA "\33[01;35m" #define NC "\33[0m" #define BOLD "\33[1m" #define ULINE "\33[4m" //underline #define BLINK "\33[5m" #define INVERT "\33[7m" __thread uint64_t seed = 1; uint64_t xorshift_rand(void) { uint64_t x = seed; if (seed == 0) seed = rand(); x ^= x >> 12; x ^= x << 25; x ^= x >> 27; seed = x; return x * 2685821657736338717LL; } double uniform_deviate(uint64_t seed) { return seed * (1.0 / (0xffffffffffffffffL + 1.0)); } int rng(int low, int high) { return low + uniform_deviate(xorshift_rand()) * (high-low); } static inline BDD make_random(int i, int j) { if (i == j) return rng(0, 2) ? sylvan_true : sylvan_false; BDD yes = make_random(i+1, j); BDD no = make_random(i+1, j); BDD result = sylvan_invalid; switch(rng(0, 4)) { case 0: result = no; sylvan_deref(yes); break; case 1: result = yes; sylvan_deref(no); break; case 2: result = sylvan_ref(sylvan_makenode(i, yes, no)); sylvan_deref(no); sylvan_deref(yes); break; case 3: default: result = sylvan_ref(sylvan_makenode(i, no, yes)); sylvan_deref(no); sylvan_deref(yes); break; } return result; } void testFun(BDD p1, BDD p2, BDD r1, BDD r2) { if (r1 == r2) return; printf("Parameter 1:\n"); fflush(stdout); sylvan_printdot(p1); sylvan_print(p1);printf("\n"); printf("Parameter 2:\n"); fflush(stdout); sylvan_printdot(p2); sylvan_print(p2);printf("\n"); printf("Result 1:\n"); fflush(stdout); sylvan_printdot(r1); printf("Result 2:\n"); fflush(stdout); sylvan_printdot(r2); assert(0); } int testEqual(BDD a, BDD b) { if (a == b) return 1; if (a == sylvan_invalid) { printf("a is invalid!\n"); return 0; } if (b == sylvan_invalid) { printf("b is invalid!\n"); return 0; } printf("Not Equal!\n"); fflush(stdout); sylvan_print(a);printf("\n"); sylvan_print(b);printf("\n"); return 0; } void test_bdd() { sylvan_gc_disable(); assert(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_true) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_false))); assert(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_true) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_false))); assert(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_false) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_true))); assert(sylvan_makenode(sylvan_ithvar(1), sylvan_false, sylvan_false) == sylvan_not(sylvan_makenode(sylvan_ithvar(1), sylvan_true, sylvan_true))); sylvan_gc_enable(); } void test_cube() { LACE_ME; BDDSET vars = sylvan_set_fromarray(((BDDVAR[]){1,2,3,4,6,8}), 6); uint8_t cube[6], check[6]; int i, j; for (i=0;i<6;i++) cube[i] = rng(0,3); BDD bdd = sylvan_cube(vars, cube); sylvan_sat_one(bdd, vars, check); for (i=0; i<6;i++) assert(cube[i] == check[i] || cube[i] == 2 && check[i] == 0); BDD picked = sylvan_pick_cube(bdd); assert(testEqual(sylvan_and(picked, bdd), picked)); BDD t1 = sylvan_cube(vars, ((uint8_t[]){1,1,2,2,0,0})); BDD t2 = sylvan_cube(vars, ((uint8_t[]){1,1,1,0,0,2})); assert(testEqual(sylvan_union_cube(t1, vars, ((uint8_t[]){1,1,1,0,0,2})), sylvan_or(t1, t2))); t2 = sylvan_cube(vars, ((uint8_t[]){2,2,2,1,1,0})); assert(testEqual(sylvan_union_cube(t1, vars, ((uint8_t[]){2,2,2,1,1,0})), sylvan_or(t1, t2))); t2 = sylvan_cube(vars, ((uint8_t[]){1,1,1,0,0,0})); assert(testEqual(sylvan_union_cube(t1, vars, ((uint8_t[]){1,1,1,0,0,0})), sylvan_or(t1, t2))); sylvan_gc_disable(); bdd = make_random(1, 16); for (j=0;j<10;j++) { for (i=0;i<6;i++) cube[i] = rng(0,3); BDD c = sylvan_cube(vars, cube); assert(sylvan_union_cube(bdd, vars, cube) == sylvan_or(bdd, c)); } for (i=0;i<10;i++) { picked = sylvan_pick_cube(bdd); assert(testEqual(sylvan_and(picked, bdd), picked)); } sylvan_gc_enable(); } static void test_operators() { // We need to test: xor, and, or, nand, nor, imp, biimp, invimp, diff, less sylvan_gc_disable(); LACE_ME; //int i; BDD a = sylvan_ithvar(1); BDD b = sylvan_ithvar(2); BDD one = make_random(1, 12); BDD two = make_random(6, 24); // Test or assert(testEqual(sylvan_or(a, b), sylvan_makenode(1, b, sylvan_true))); assert(testEqual(sylvan_or(a, b), sylvan_or(b, a))); assert(testEqual(sylvan_or(one, two), sylvan_or(two, one))); // Test and assert(testEqual(sylvan_and(a, b), sylvan_makenode(1, sylvan_false, b))); assert(testEqual(sylvan_and(a, b), sylvan_and(b, a))); assert(testEqual(sylvan_and(one, two), sylvan_and(two, one))); // Test xor assert(testEqual(sylvan_xor(a, b), sylvan_makenode(1, b, sylvan_not(b)))); assert(testEqual(sylvan_xor(a, b), sylvan_xor(a, b))); assert(testEqual(sylvan_xor(a, b), sylvan_xor(b, a))); assert(testEqual(sylvan_xor(one, two), sylvan_xor(two, one))); assert(testEqual(sylvan_xor(a, b), sylvan_ite(a, sylvan_not(b), b))); // Test diff assert(testEqual(sylvan_diff(a, b), sylvan_diff(a, b))); assert(testEqual(sylvan_diff(a, b), sylvan_diff(a, sylvan_and(a, b)))); assert(testEqual(sylvan_diff(a, b), sylvan_and(a, sylvan_not(b)))); assert(testEqual(sylvan_diff(a, b), sylvan_ite(b, sylvan_false, a))); assert(testEqual(sylvan_diff(one, two), sylvan_diff(one, two))); assert(testEqual(sylvan_diff(one, two), sylvan_diff(one, sylvan_and(one, two)))); assert(testEqual(sylvan_diff(one, two), sylvan_and(one, sylvan_not(two)))); assert(testEqual(sylvan_diff(one, two), sylvan_ite(two, sylvan_false, one))); // Test biimp assert(testEqual(sylvan_biimp(a, b), sylvan_makenode(1, sylvan_not(b), b))); assert(testEqual(sylvan_biimp(a, b), sylvan_biimp(b, a))); assert(testEqual(sylvan_biimp(one, two), sylvan_biimp(two, one))); // Test nand / and assert(testEqual(sylvan_not(sylvan_and(a, b)), sylvan_nand(b, a))); assert(testEqual(sylvan_not(sylvan_and(one, two)), sylvan_nand(two, one))); // Test nor / or assert(testEqual(sylvan_not(sylvan_or(a, b)), sylvan_nor(b, a))); assert(testEqual(sylvan_not(sylvan_or(one, two)), sylvan_nor(two, one))); // Test xor / biimp assert(testEqual(sylvan_xor(a, b), sylvan_not(sylvan_biimp(b, a)))); assert(testEqual(sylvan_xor(one, two), sylvan_not(sylvan_biimp(two, one)))); // Test imp assert(testEqual(sylvan_imp(a, b), sylvan_ite(a, b, sylvan_true))); assert(testEqual(sylvan_imp(one, two), sylvan_ite(one, two, sylvan_true))); assert(testEqual(sylvan_imp(one, two), sylvan_not(sylvan_diff(one, two)))); assert(testEqual(sylvan_invimp(one, two), sylvan_not(sylvan_less(one, two)))); assert(testEqual(sylvan_imp(a, b), sylvan_invimp(b, a))); assert(testEqual(sylvan_imp(one, two), sylvan_invimp(two, one))); // Test constrain, exists and forall sylvan_gc_enable(); } static void test_relprod() { LACE_ME; sylvan_gc_disable(); BDDVAR vars[] = {0,2,4}; BDDVAR all_vars[] = {0,1,2,3,4,5}; BDDSET vars_set = sylvan_set_fromarray(vars, 3); BDDSET all_vars_set = sylvan_set_fromarray(all_vars, 6); BDD s, t, next, prev; BDD zeroes, ones; // transition relation: 000 --> 111 and !000 --> 000 t = sylvan_false; t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){0,1,0,1,0,1})); t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){1,0,2,0,2,0})); t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){2,0,1,0,2,0})); t = sylvan_union_cube(t, all_vars_set, ((uint8_t[]){2,0,2,0,1,0})); s = sylvan_cube(vars_set, (uint8_t[]){0,0,1}); zeroes = sylvan_cube(vars_set, (uint8_t[]){0,0,0}); ones = sylvan_cube(vars_set, (uint8_t[]){1,1,1}); next = sylvan_relnext(s, t, all_vars_set); prev = sylvan_relprev(t, next, all_vars_set); assert(next == zeroes); assert(prev == sylvan_not(zeroes)); next = sylvan_relnext(next, t, all_vars_set); prev = sylvan_relprev(t, next, all_vars_set); assert(next == ones); assert(prev == zeroes); t = sylvan_cube(all_vars_set, (uint8_t[]){0,0,0,0,0,1}); assert(sylvan_relprev(t, s, all_vars_set) == zeroes); assert(sylvan_relprev(t, sylvan_not(s), all_vars_set) == sylvan_false); assert(sylvan_relnext(s, t, all_vars_set) == sylvan_false); assert(sylvan_relnext(zeroes, t, all_vars_set) == s); t = sylvan_cube(all_vars_set, (uint8_t[]){0,0,0,0,0,2}); assert(sylvan_relprev(t, s, all_vars_set) == zeroes); assert(sylvan_relprev(t, zeroes, all_vars_set) == zeroes); assert(sylvan_relnext(sylvan_not(zeroes), t, all_vars_set) == sylvan_false); sylvan_gc_enable(); } static void test_compose() { sylvan_gc_disable(); LACE_ME; BDD a = sylvan_ithvar(1); BDD b = sylvan_ithvar(2); BDD a_or_b = sylvan_or(a, b); BDD one = make_random(3, 16); BDD two = make_random(8, 24); BDDMAP map = sylvan_map_empty(); map = sylvan_map_add(map, 1, one); map = sylvan_map_add(map, 2, two); assert(sylvan_map_key(map) == 1); assert(sylvan_map_value(map) == one); assert(sylvan_map_key(sylvan_map_next(map)) == 2); assert(sylvan_map_value(sylvan_map_next(map)) == two); assert(testEqual(one, sylvan_compose(a, map))); assert(testEqual(two, sylvan_compose(b, map))); assert(testEqual(sylvan_or(one, two), sylvan_compose(a_or_b, map))); map = sylvan_map_add(map, 2, one); assert(testEqual(sylvan_compose(a_or_b, map), one)); map = sylvan_map_add(map, 1, two); assert(testEqual(sylvan_or(one, two), sylvan_compose(a_or_b, map))); assert(testEqual(sylvan_and(one, two), sylvan_compose(sylvan_and(a, b), map))); sylvan_gc_enable(); } /** GC testing */ VOID_TASK_2(gctest_fill, int, levels, int, width) { if (levels > 1) { int i; for (i=0; i,<2,2,3,5,4,3>,<2,2,3,5,4,2>,<2,3,3,5,4,3>,<2,3,4,4,4,3>} MDD proj = lddmc_cube((uint32_t[]){1,1,-2},3); b = lddmc_cube((uint32_t[]){1,2}, 2); b = lddmc_union_cube(b, (uint32_t[]){2,2}, 2); b = lddmc_union_cube(b, (uint32_t[]){2,3}, 2); assert(lddmc_project(a, proj)==b); assert(lddmc_project_minus(a, proj, lddmc_false)==b); assert(lddmc_project_minus(a, proj, b)==lddmc_false); // Test relprod a = lddmc_cube((uint32_t[]){1},1); b = lddmc_cube((uint32_t[]){1,2},2); proj = lddmc_cube((uint32_t[]){1,2,-1}, 3); assert(lddmc_cube((uint32_t[]){2},1) == lddmc_relprod(a, b, proj)); assert(lddmc_cube((uint32_t[]){3},1) == lddmc_relprod(a, lddmc_cube((uint32_t[]){1,3},2), proj)); a = lddmc_union_cube(a, (uint32_t[]){2},1); assert(lddmc_satcount(a) == 2); assert(lddmc_cube((uint32_t[]){2},1) == lddmc_relprod(a, b, proj)); b = lddmc_union_cube(b, (uint32_t[]){2,2},2); assert(lddmc_cube((uint32_t[]){2},1) == lddmc_relprod(a, b, proj)); b = lddmc_union_cube(b, (uint32_t[]){2,3},2); assert(lddmc_satcount(lddmc_relprod(a, b, proj)) == 2); assert(lddmc_union(lddmc_cube((uint32_t[]){2},1),lddmc_cube((uint32_t[]){3},1)) == lddmc_relprod(a, b, proj)); // Test relprev MDD universe = lddmc_union(lddmc_cube((uint32_t[]){1},1), lddmc_cube((uint32_t[]){2},1)); a = lddmc_cube((uint32_t[]){2},1); b = lddmc_cube((uint32_t[]){1,2},2); assert(lddmc_cube((uint32_t[]){1},1) == lddmc_relprev(a, b, proj, universe)); assert(lddmc_cube((uint32_t[]){1},1) == lddmc_relprev(a, b, proj, lddmc_cube((uint32_t[]){1},1))); a = lddmc_cube((uint32_t[]){1},1); MDD next = lddmc_relprod(a, b, proj); assert(lddmc_relprev(next, b, proj, a) == a); // Random tests MDD rnd1, rnd2; int i; for (i=0; i<200; i++) { int depth = rng(1, 20); rnd1 = CALL(random_ldd, depth, rng(0, 30)); rnd2 = CALL(random_ldd, depth, rng(0, 30)); assert(rnd1 != lddmc_true); assert(rnd2 != lddmc_true); assert(lddmc_intersect(rnd1,rnd2) == lddmc_intersect(rnd2,rnd1)); assert(lddmc_union(rnd1,rnd2) == lddmc_union(rnd2,rnd1)); MDD tmp = lddmc_union(lddmc_minus(rnd1, rnd2), lddmc_minus(rnd2, rnd1)); assert(lddmc_intersect(tmp, lddmc_intersect(rnd1, rnd2)) == lddmc_false); assert(lddmc_union(tmp, lddmc_intersect(rnd1, rnd2)) == lddmc_union(rnd1, rnd2)); assert(lddmc_minus(rnd1,rnd2) == lddmc_minus(rnd1, lddmc_intersect(rnd1,rnd2))); } // Test file stuff for (i=0; i<10; i++) { FILE *f = fopen("__lddmc_test_bdd", "w+"); int N = 20; MDD rnd[N]; size_t a[N]; char sha[N][65]; int j; for (j=0;j 1) sscanf(argv[1], "%d", &threads); runtests(threads); printf(NC); exit(0); }