static bddp hit_z2b_rec(zddp f, my_hash *h) { if(f == zdd_top()) return bdd_bot(); if(f == zdd_bot()) return bdd_top(); bddp r; if(ht_search((uintptr_t)f, (uintptr_t*)&r, h)) return r; INC_RECDEPTH(recdepth); bddp r0 = hit_z2b_rec(zdd_lo(f), h); bddp r1 = hit_z2b_rec(zdd_hi(f), h); DEC_RECDEPTH(recdepth); bddp t = bdd_node(zdd_itemval(f), r1, bdd_top()); ENSURE_TRUE_MSG(t != BDD_NULL, "BDD operation failed"); r = bdd_and(r0, t); ENSURE_TRUE_MSG(r != BDD_NULL, "BDD operation failed"); ht_insert((uintptr_t)f, (uintptr_t)r, h); #ifdef SIZE_LOG const uintmax_t insize = zdd_size(f); const uintmax_t outsize = bdd_size(r); fprintf(sizelog, "%ju\t%ju\n", insize, outsize); if(maxsize < outsize) maxsize = outsize; #endif /*SIZE_LOG*/ return r; }
// Construct ZDD of sets containing exactly 1 occurrence of digit d in row r. // For instance, if d = 3, r = 0: // // 1 === 2 === 3 // 3 ... 4a, --- 4b // 4a === 5a === ... === 9a === ... === 11a === 12 // 4b === 5b === ... === 9b === ... === 11b === 13b // 12 ... 13a, --- 13b // 13a === ... === 20a === 21 // 13b === ... === 20b === 22b // and so on until: // 74a === 75 ... F, --- 76 // 74b === 76 // 76 === ... === 729 === T // // This ZDD has 9*2^720 members. // When intersected with the one-digit-per-box set, the result has // 9*8^8*9^72 members. (Pick 1 of 9 positions ford, leaving 8 possible choices // forthe remaining 8 boxes in that row. The other 81 - 9 boxes can contain // any single digitS.) // The intersection forall d and a fixed r has 9!*9^72 members. // The intersection forall r and a fixed d has 9^9*8^72 members. void unique_digit_per_row(int d, int r) { zdd_push(); // The order is determined by sorting by number, then by letter. int next = 81 * r + d; // The next node involving the digit d. int v = 1; int state = 0; while (v <= 729) { if (v == next) { next += 9; state++; if (state == 1) { // The first split in the ZDD. zdd_add_node(v, 1, 2); } else if (state < 9) { // Fix previous node. We must not have a second occurrence of d. uint32_t n = zdd_last_node(); zdd_set_hilo(n, n + 3); // If this is the first occurrence of d, we're on notice. zdd_add_node(v, 1, 2); } else { // If we never saw d, then branch to FALSE. // Otherwise reunite the branches. zdd_add_node(v, 0, 1); next = -1; } } else if (state == 0 || state == 9) { zdd_add_node(v, 1, 1); } else { zdd_add_node(v, 2, 2); zdd_add_node(v, 2, 2); } v++; } // Fix last nodes. uint32_t n = zdd_last_node(); if (zdd_lo(n - 1) > n) zdd_set_lo(n - 1, 1); if (zdd_hi(n - 1) > n) zdd_set_hi(n - 1, 1); if (zdd_lo(n) > n) zdd_set_lo(n, 1); if (zdd_hi(n) > n) zdd_set_hi(n, 1); }
// Construct ZDD of sets containing all elements in the given list. // The list is terminated by -1. void contains_all(int *list) { zdd_push(); int v = 1; int *next = list; while (v <= 729) { if (v == *next) { next++; zdd_add_node(v, 0, 1); } else { zdd_add_node(v, 1, 1); } v++; } // Fix 729. uint32_t n = zdd_last_node(); if (zdd_lo(n) > n) zdd_set_lo(n, 1); if (zdd_hi(n) > n) zdd_set_hi(n, 1); }
static zddp minhit_nonsup_rec(zddp f, my_hash *h) { if(f == zdd_bot()) return zdd_top(); if(f == zdd_top()) return zdd_bot(); zddp r; if(ht_search((uintptr_t)f, (uintptr_t*)&r, h)) return r; zddp t = zdd_union(zdd_lo(f), zdd_hi(f)); ENSURE_TRUE_MSG(t != BDD_NULL, "ZDD operation failed"); INC_RECDEPTH(recdepth); zddp r0 = minhit_nonsup_rec(t, h); zddp tt = minhit_nonsup_rec(zdd_lo(f), h); DEC_RECDEPTH(recdepth); zddp r1 = nonsup(tt, r0); ENSURE_TRUE_MSG(r1 != BDD_NULL, "ZDD extra operation failed"); r = zdd_node(zdd_itemval(f), r0, r1); ENSURE_TRUE_MSG(r != BDD_NULL, "ZDD operation failed"); ht_insert((uintptr_t)f, (uintptr_t)r, h); return r; }