result_type operator() (logic::tag::xor_tag const& tag, result_type lhs, result_type rhs ) { result_type out = { int(impl::new_var_id()) }; clause3( lhs, rhs,-out); clause3( lhs,-rhs, out); clause3(-lhs, rhs, out); clause3(-lhs,-rhs,-out); return out; }
result_type operator() (logic::tag::ite_tag const& tag, result_type op1, result_type op2, result_type op3 ) { result_type out = { int(impl::new_var_id()) }; clause3( op1, op3, -out); clause3( op1,-op3, out); clause3(-op1, op2, -out); clause3(-op1,-op2, out); return out; }
void encodeToCNF() { #define clause2(a,b) \ ({add_lit(a); add_lit(b); add_lit(0);}) #define clause3(a,b,c) \ ({add_lit(a); add_lit(b); add_lit(c); add_lit(0);}) #define implies(a,b) clause2(-a, b); #define implies_or(a,b,c) clause3(-a, b, c); int f, d, l, t, e, c, r; for (f = 0; f < S2; f++) { clause3(white(f), black(f), nblack(f)); implies(white(f), -black(f)); implies(white(f), -nblack(f)); implies(nblack(f), -black(f)); implies(nblack(f), -white(f)); implies(black(f), -white(f)); implies(black(f), -nblack(f)); implies(white(f), numfield(f)); implies(nblack(f), xblack(f)); implies(nblack(f), numfield(f)); implies(black(f), xblack(f)); implies(white(f), -xblack(f)); implies(black(f), -numfield(f)); implies(xblack(f), -white(f)); implies(numfield(f), -black(f)); implies_or(numfield(f), white(f), nblack(f)); implies_or(xblack(f), black(f), nblack(f)); for (d = 0; d < S; d++) { implies(num(f,d), numfield(f)); for (e = 0; e < S; e++) { // each digit at most once in each row t = same_row_but(f, e); if (t != f) implies(num(f, d), -num(t, d)); // each digit at most once in each column t = same_col_but(f, e); if (t != f) implies(num(f, d), -num(t, d)); // only one digit at most in each cell if (d != e) implies(num(f, d), -num(f, e)); } } // numfield(f) => exists d . num(f,d) add_lit(-numfield(f)); for (d = 0; d < S; d++) add_lit(num(f, d)); add_lit(0); // no single white fields int c = field_col(f); int r = field_row(f); add_lit(-white(f)); if (c >= 1) add_lit(-xblack(field(c-1, r))); if (c < S-1) add_lit(-xblack(field(c+1, r))); if (r >= 1) add_lit(-xblack(field(c, r-1))); if (r < S-1) add_lit(-xblack(field(c, r+1))); add_lit(0); } // Encoding the straights: // A constellation like B W W W B is a straight of len 3, // when there are no blacks in between. // The two B's can also be the border. // Only straights of a length >= 2 are interesting. // The implications are encoded into clauses like this: // a&b => x // -(a&b) | x // -a | -b | x for (f = 0; f < S2; f++) { int col = field_col(f); int row = field_row(f); for (c = col+1; c < S; c++) { // col is the first column // c is the last column (inclusively) int len = c-col+1; if (col > 0) add_lit(-xblack(same_row_but(f, col-1))); if (c <= S-2) add_lit(-xblack(same_row_but(f, c+1))); for (int s = 0; s < len; s++) add_lit(-white(same_row_but(f, col+s))); add_lit(hstr(f, len)); add_lit(0); if (col > 0) implies(hstr(f,len), xblack(same_row_but(f, col-1))); if (c <= S-2) implies(hstr(f,len), xblack(same_row_but(f, c+1))); for (int s = 0; s < len; s++) implies(hstr(f,len), white(same_row_but(f, col+s))); // hstr(f,len) => hstrd(f,len,0) | hstrd(f,len,1) ... add_lit(-hstr(f, len)); int largest_mind = S-len; for (int mind = 0; mind <= largest_mind; mind++) add_lit(hstrd(f, len, mind)); add_lit(0); // hstrd(f,len,d) => num(f,d) | num(f,d+1) ... // for all the num()'s in the straight for (int sc = col; sc <= c; sc++) { int ff = same_row_but(f, sc); for (int mind = 0; mind <= largest_mind; mind++) { add_lit(-hstrd(f, len, mind)); for (int dig = 0; dig < len; dig++) add_lit(num(ff, mind+dig)); add_lit(0); } } } for (r = row+1; r < S; r++) { int len = r-row+1; if (row > 0) add_lit(-xblack(same_col_but(f, row-1))); if (r <= S-2) add_lit(-xblack(same_col_but(f, r+1))); for (int s = 0; s < len; s++) add_lit(-white(same_col_but(f, row+s))); add_lit(vstr(f, len)); add_lit(0); if (row > 0) implies(vstr(f,len), xblack(same_col_but(f, row-1))); if (r <= S-2) implies(vstr(f,len), xblack(same_col_but(f, r+1))); for (int s = 0; s < len; s++) implies(vstr(f,len), white(same_col_but(f, row+s))); // and the vstr(f,len) def add_lit(-vstr(f, len)); int largest_mind = S-len; for (int mind = 0; mind <= largest_mind; mind++) add_lit(vstrd(f, len, mind)); add_lit(0); // vstrd(f,len,d) => num(f,d) | num(f,d+1) ... // for all the num()'s in the straight for (int sc = row; sc <= r; sc++) { int ff = same_col_but(f, sc); for (int mind = 0; mind <= largest_mind; mind++) { add_lit(-vstrd(f, len, mind)); for (int dig = 0; dig < len; dig++) add_lit(num(ff, mind+dig)); add_lit(0); } } } } printf("encoded into %i clauses\n", clausesptr); }