예제 #1
0
 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;
 }
예제 #2
0
 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;
 }
예제 #3
0
파일: twirl.c 프로젝트: malie/twirl
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);
}