/// The actual problem Queens(const SizeOptions& opt) : q(*this,opt.size(),0,opt.size()-1) { const int n = q.size(); switch (opt.propagation()) { case PROP_BINARY: for (int i = 0; i<n; i++) for (int j = i+1; j<n; j++) { rel(*this, q[i] != q[j]); rel(*this, q[i]+i != q[j]+j); rel(*this, q[i]-i != q[j]-j); } break; case PROP_MIXED: for (int i = 0; i<n; i++) for (int j = i+1; j<n; j++) { rel(*this, q[i]+i != q[j]+j); rel(*this, q[i]-i != q[j]-j); } distinct(*this, q, opt.icl()); break; case PROP_DISTINCT: distinct(*this, IntArgs::create(n,0,1), q, opt.icl()); distinct(*this, IntArgs::create(n,0,-1), q, opt.icl()); distinct(*this, q, opt.icl()); break; } switch(opt.branching()) { case BRANCH_MIN: branch(*this, q, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); break; case BRANCH_MID: branch(*this, q, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); break; case BRANCH_MAX_MAX: branch(*this, q, INT_VAR_SIZE_MAX(), INT_VAL_MIN()); break; case BRANCH_KNIGHT_MOVE: branch(*this, q, INT_VAR_MIN_MIN(), INT_VAL_MED()); break; } }
SUSHI_EQUATION(const SizeOptions& opt) : n_x(*this, 1, wordlength), n_y(*this, 1, wordlength), n_z(*this, 1, wordlength), n_t(*this, opt.size()+1, opt.size()+1), X(*this, wordlength , val_dom_min, val_dom_max), Y(*this, wordlength , val_dom_min, val_dom_max), Z(*this, wordlength , val_dom_min, val_dom_max), T(*this, opt.size()+1 , val_dom_min, val_dom_max){ int n = opt.size(); gecode_find_solution = false; REG r_a(1); REG r_b(2); REG dum(dummy_sym); REG reg_z = r_b(n,n) + r_a + r_b(n,n); if (opt.propagation() == PROP_PAD) { reg_z += (*dum); } DFA myDFA_z(reg_z); // T = "a" . Y[0,n] rel(*this, T[0]==1); for (int i = 0; (i < n) && (i+1 < T.size()); i++){ T[i+1] = Y[i]; } rel(*this, n_y >= n); switch(opt.propagation()){ case PROP_OPEN: extensional(*this, Z, myDFA_z, n_z); //concat(*this, X, n_x, T, n_t, Z, n_z, ICL_BND); rel(*this, n_z == (n_x+n_t)); for(int i=0; i<wordlength; i++) { rel(*this, (i<n_x) >> (X[i]==Z[i])); BoolVar b = expr(*this, i==n_x); for(int j=0; (i+j)<wordlength; j++) { rel(*this, (b&&(j<n_t)) >> (T[j]==Z[i+j])); } } break; case PROP_CLOSED: extensional(*this, Z, myDFA_z); rel(*this, n_z == (n_x+n_t)); rel(*this, n_y == wordlength); for(int i=0; i<wordlength; i++) { rel(*this, (i<n_x) >> (X[i]==Z[i])); BoolVar b = expr(*this, i==n_x); for(int j=0; (j < T.size()) && ((i+j)<wordlength); j++) { rel(*this, (b&&(j<n_t)) >> (T[j]==Z[i+j])); } } break; case PROP_PAD: extensional(*this, Z, myDFA_z); for(int i=0; i<wordlength; i++) { rel(*this, (Z[i]==dummy_sym) == (n_z<=i)); rel(*this, (Y[i]==dummy_sym) == (n_y<=i)); rel(*this, (X[i]==dummy_sym) == (n_x<=i)); } rel(*this, n_z == (n_x+n_t)); for(int i=0; i<wordlength; i++) { rel(*this, (i<n_x) >> (X[i]==Z[i])); BoolVar b = expr(*this, i==n_x); for(int j=0; (j < T.size()) && ((i+j)<wordlength); j++) { rel(*this, (b&&(j<n_t)) >> (T[j]==Z[i+j])); } } break; } IntVarArgs lengths; lengths << n_z << n_x << n_y; switch(opt.branching()){ case BRANCH_N_A: branch(*this, lengths, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, Z, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, X, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, Y, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); break; case BRANCH_A_N: branch(*this, Z, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, X, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, Y, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, lengths, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); break; case BRANCH_BOUND: boundednone(*this, Z, n_z); boundednone(*this, X, n_x); boundednone(*this, Y, n_y); break; } }
/// Actual model PerfectSquare(const SizeOptions& opt) : x(*this,specs[opt.size()][0],0,specs[opt.size()][1]-1), y(*this,specs[opt.size()][0],0,specs[opt.size()][1]-1) { const int* s = specs[opt.size()]; int n = *s++; int w = *s++; // Restrict position according to square size for (int i=n; i--; ) { rel(*this, x[i], IRT_LQ, w-s[i]); rel(*this, y[i], IRT_LQ, w-s[i]); } IntArgs sa(n,s); // Squares do not overlap nooverlap(*this, x, sa, y, sa); /* * Capacity constraints * */ switch (opt.propagation()) { case PROP_REIFIED: { for (int cx=0; cx<w; cx++) { BoolVarArgs bx(*this,n,0,1); for (int i=0; i<n; i++) dom(*this, x[i], cx-s[i]+1, cx, bx[i]); linear(*this, sa, bx, IRT_EQ, w); } for (int cy=0; cy<w; cy++) { BoolVarArgs by(*this,n,0,1); for (int i=0; i<n; i++) dom(*this, y[i], cy-s[i]+1, cy, by[i]); linear(*this, sa, by, IRT_EQ, w); } } break; case PROP_CUMULATIVES: { IntArgs m(n), dh(n); for (int i = n; i--; ) { m[i]=0; dh[i]=s[i]; } IntArgs limit(1, w); { // x-direction IntVarArgs e(n); for (int i=n; i--;) e[i]=expr(*this, x[i]+dh[i]); cumulatives(*this, m, x, dh, e, dh, limit, true); cumulatives(*this, m, x, dh, e, dh, limit, false); } { // y-direction IntVarArgs e(n); for (int i=n; i--;) e[i]=expr(*this, y[i]+dh[i]); cumulatives(*this, m, y, dh, e, dh, limit, true); cumulatives(*this, m, y, dh, e, dh, limit, false); } } break; default: GECODE_NEVER; } branch(*this, x, INT_VAR_MIN_MIN(), INT_VAL_MIN()); branch(*this, y, INT_VAR_MIN_MIN(), INT_VAL_MIN()); }
KaluzaExample(const SizeOptions& opt) : var_0xINPUT_9_n(*this,1,wordlength), T0_2_n(*this,1,wordlength), T1_2_n(*this,1,wordlength), PCTEMP_LHS_1_idx_0_n(*this,1,wordlength), T2_2_n(*this,1,wordlength), PCTEMP_LHS_1_group_1_n(*this,1,wordlength), PCTEMP_LHS_1_len_0(*this,1,wordlength), var_0xINPUT_9(*this,wordlength,val_dom_min,val_dom_max), T0_2(*this,wordlength,val_dom_min,val_dom_max), T1_2(*this,wordlength,val_dom_min,val_dom_max), PCTEMP_LHS_1_idx_0(*this,wordlength,val_dom_min,val_dom_max), T2_2(*this,wordlength,val_dom_min,val_dom_max), PCTEMP_LHS_1_group_1(*this,wordlength,val_dom_min,val_dom_max){ // PCTEMP_LHS_1_len_0 == Len(PCTEMP_LHS_1_idx_0); rel(*this, PCTEMP_LHS_1_len_0==PCTEMP_LHS_1_idx_0_n); // PCTEMP_LHS_1_len_0 < 15; rel(*this, PCTEMP_LHS_1_len_0 < 15); switch(opt.propagation()){ case PROP_PAD: { PAD_INVARIANT(*this,var_0xINPUT_9, var_0xINPUT_9_n); PAD_INVARIANT(*this,T0_2, T0_2_n); PAD_INVARIANT(*this,T1_2, T1_2_n); PAD_INVARIANT(*this,PCTEMP_LHS_1_idx_0, PCTEMP_LHS_1_idx_0_n); PAD_INVARIANT(*this,T2_2, T2_2_n); PAD_INVARIANT(*this,PCTEMP_LHS_1_group_1, PCTEMP_LHS_1_group_1_n); //var_0xINPUT_9 := T0_2 . T1_2; rel(*this, var_0xINPUT_9_n == (T0_2_n+T1_2_n)); // Zn=Xn+Yn for(int i=0; i<wordlength; i++) { rel(*this, (i<T0_2_n) >> (T0_2[i]==var_0xINPUT_9[i])); // i<Xn --> X[i]=Z[i] BoolVar b = expr(*this, i==T0_2_n); // b <-> i=Xn for(int j=0; (i+j)<wordlength; j++) //(i+j)<|Z|&j<|Y| rel(*this, (b&&(j<T1_2_n)) >> (T1_2[j]==var_0xINPUT_9[i+j])); // b&(j<Yn) --> Y[i]=Z[i] } //T1_2 := PCTEMP_LHS_1_idx_0 . T2_2; rel(*this, T1_2_n == (PCTEMP_LHS_1_idx_0_n+T2_2_n)); // Zn=Xn+Yn for(int i=0; i<wordlength; i++) { rel(*this, (i<PCTEMP_LHS_1_idx_0_n) >> (PCTEMP_LHS_1_idx_0[i]==T1_2[i])); // i<Xn --> X[i]=Z[i] BoolVar b = expr(*this, i==PCTEMP_LHS_1_idx_0_n); // b <-> i=Xn for(int j=0; (i+j)<wordlength; j++) //(i+j)<|Z|&j<|Y| rel(*this, (b&&(j<T2_2_n)) >> (T2_2[j]==T1_2[i+j])); // b&(j<Yn) --> Y[i]=Z[i] } //PCTEMP_LHS_1_group_1 == PCTEMP_LHS_1_idx_0; PAD_EQUAL(*this, PCTEMP_LHS_1_group_1, PCTEMP_LHS_1_group_1_n, PCTEMP_LHS_1_idx_0, PCTEMP_LHS_1_idx_0_n); // PCTEMP_LHS_1_idx_0 \in CapturedBrack(/john/,0); Gecode::DFA::Transition tp[] = {{0,75,1},{1,80,2},{2,73,3},{3,79,4},{4,dummy_sym,4},{-1,0,0}}; int fp1[] = {4,-1}; john = DFA(0,tp,fp1); extensional(*this, PCTEMP_LHS_1_idx_0, john); // T0_2 \notin CapturedBrack(/john/, 0); int fp2[] = {0,1,2,3,5,-1}; notjohn = DFA(0,bigp,fp2); extensional(*this, T0_2, notjohn); break; } case PROP_OPEN: { open_invariant(*this,var_0xINPUT_9, var_0xINPUT_9_n); open_invariant(*this,T0_2, T0_2_n); open_invariant(*this,T1_2, T1_2_n); open_invariant(*this,PCTEMP_LHS_1_idx_0, PCTEMP_LHS_1_idx_0_n); open_invariant(*this,T2_2, T2_2_n); open_invariant(*this,PCTEMP_LHS_1_group_1, PCTEMP_LHS_1_group_1_n); //var_0xINPUT_9 := T0_2 . T1_2; open_concat(*this, T0_2, T0_2_n, T1_2, T1_2_n, var_0xINPUT_9, var_0xINPUT_9_n); //T1_2 := PCTEMP_LHS_1_idx_0 . T2_2; open_concat(*this, PCTEMP_LHS_1_idx_0, PCTEMP_LHS_1_idx_0_n, T2_2, T2_2_n, T1_2, T1_2_n); //PCTEMP_LHS_1_group_1 == PCTEMP_LHS_1_idx_0; open_equal(*this, PCTEMP_LHS_1_group_1, PCTEMP_LHS_1_group_1_n, PCTEMP_LHS_1_idx_0, PCTEMP_LHS_1_idx_0_n); // PCTEMP_LHS_1_idx_0 \in CapturedBrack(/john/,0); Gecode::DFA::Transition tp[] = {{0,75,1},{1,80,2},{2,73,3},{3,79,4},{4,dummy_sym,4},{-1,0,0}}; int fp1[] = {4,-1}; john = DFA(0,tp,fp1); extensional(*this, PCTEMP_LHS_1_idx_0, john); // T0_2 \notin CapturedBrack(/john/, 0); int fp2[] = {0,1,2,3,5,-1}; notjohn = DFA(0,bigp,fp2); extensional(*this, T0_2, notjohn); // // PCTEMP_LHS_1_idx_0 \in CapturedBrack(/john/,0); // Gecode::DFA::Transition t[] = {{0,75,1},{1,80,2},{2,73,3},{3,79,4},{-1,0,0}}; // int f1[] = {4,-1}; // john = DFA(0,t,f1); // extensional(*this, PCTEMP_LHS_1_idx_0, john, PCTEMP_LHS_1_idx_0_n); // // T0_2 \notin CapturedBrack(/john/, 0); // int f2[] = {0,1,2,3,5,-1}; // notjohn = DFA(0,big,f2); // extensional(*this, T0_2, notjohn, T0_2_n); break; } } branch(*this, var_0xINPUT_9, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, T0_2, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, T1_2, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, PCTEMP_LHS_1_idx_0, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, T2_2, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, PCTEMP_LHS_1_group_1, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); }
/// Actual model Domino(const SizeOptions& opt) : spec(specs[opt.size()]), width(spec[0]), height(spec[1]), x(*this, (width+1)*height, 0, 28) { spec+=2; // skip board size information // Copy spec information to the board IntArgs board((width+1)*height); for (int i=0; i<width; i++) for (int j=0; j<height; j++) board[j*(width+1)+i] = spec[j*width+i]; // Initialize the separator column in the board for (int i=0; i<height; i++) { board[i*(width+1)+8] = -1; rel(*this, x[i*(width+1)+8]==28); } // Variables representing the coordinates of the first // and second half of a domino piece IntVarArgs p1(*this, 28, 0, (width+1)*height-1); IntVarArgs p2(*this, 28, 0, (width+1)*height-1); if (opt.propagation() == PROP_ELEMENT) { int dominoCount = 0; int possibleDiffsA[] = {1, width+1}; IntSet possibleDiffs(possibleDiffsA, 2); for (int i=0; i<=6; i++) for (int j=i; j<=6; j++) { // The two coordinates must be adjacent. // I.e., they may differ by 1 or by the width. // The separator column makes sure that a field // at the right border is not adjacent to the first field // in the next row. IntVar diff(*this, possibleDiffs); abs(*this, expr(*this, p1[dominoCount]-p2[dominoCount]), diff, ICL_DOM); // If the piece is symmetrical, order the locations if (i == j) rel(*this, p1[dominoCount], IRT_LE, p2[dominoCount]); // Link the current piece to the board element(*this, board, p1[dominoCount], i); element(*this, board, p2[dominoCount], j); // Link the current piece to the array where its // number is stored. element(*this, x, p1[dominoCount], dominoCount); element(*this, x, p2[dominoCount], dominoCount); dominoCount++; } } else { int dominoCount = 0; for (int i=0; i<=6; i++) for (int j=i; j<=6; j++) { // Find valid placements for piece i-j // Extensional is used as a table-constraint listing all valid // tuples. // Note that when i == j, only one of the orientations are used. REG valids; for (int pos = 0; pos < (width+1)*height; ++pos) { if ((pos+1) % (width+1) != 0) { // not end-col if (board[pos] == i && board[pos+1] == j) valids |= REG(pos) + REG(pos+1); if (board[pos] == j && board[pos+1] == i && i != j) valids |= REG(pos+1) + REG(pos); } if (pos/(width+1) < height-1) { // not end-row if (board[pos] == i && board[pos+width+1] == j) valids |= REG(pos) + REG(pos+width+1); if (board[pos] == j && board[pos+width+1] == i && i != j) valids |= REG(pos+width+1) + REG(pos); } } IntVarArgs piece(2); piece[0] = p1[dominoCount]; piece[1] = p2[dominoCount]; extensional(*this, piece, valids); // Link the current piece to the array where its // number is stored. element(*this, x, p1[dominoCount], dominoCount); element(*this, x, p2[dominoCount], dominoCount); dominoCount++; } } // Branch by piece IntVarArgs ps(28*2); for (int i=0; i<28; i++) { ps[2*i] = p1[i]; ps[2*i+1] = p2[i]; } branch(*this, ps, INT_VAR_NONE, INT_VAL_MIN); }
/// Construction of the model. Pentominoes(const SizeOptions& opt) : spec(examples[opt.size()]), width(spec[0].width+1), // Add one for extra row at end. height(spec[0].height), filled(spec[0].amount), nspecs(examples_size[opt.size()]-1), ntiles(compute_number_of_tiles(spec+1, nspecs)), board(*this, width*height, filled,ntiles+1) { spec += 1; // No need for the specification-part any longer // Set end-of-line markers for (int h = 0; h < height; ++h) { for (int w = 0; w < width-1; ++w) rel(*this, board[h*width + w], IRT_NQ, ntiles+1); rel(*this, board[h*width + width - 1], IRT_EQ, ntiles+1); } // Post constraints if (opt.propagation() == PROPAGATION_INT) { int tile = 0; for (int i = 0; i < nspecs; ++i) { for (int j = 0; j < spec[i].amount; ++j) { // Color int col = tile+1; // Expression for color col REG mark(col); // Build expression for complement to color col REG other; bool first = true; for (int j = filled; j <= ntiles; ++j) { if (j == col) continue; if (first) { other = REG(j); first = false; } else { other |= REG(j); } } // End of line marker REG eol(ntiles+1); extensional(*this, board, get_constraint(i, mark, other, eol)); ++tile; } } } else { // opt.propagation() == PROPAGATION_BOOLEAN int ncolors = ntiles + 2; // Boolean variables for channeling BoolVarArgs p(*this,ncolors * board.size(),0,1); // Post channel constraints for (int i=board.size(); i--; ) { BoolVarArgs c(ncolors); for (int j=ncolors; j--; ) c[j]=p[i*ncolors+j]; channel(*this, c, board[i]); } // For placing tile i, we construct the expression over // 0/1-variables and apply it to the projection of // the board on the color for the tile. REG other(0), mark(1); int tile = 0; for (int i = 0; i < nspecs; ++i) { for (int j = 0; j < spec[i].amount; ++j) { int col = tile+1; // Projection for color col BoolVarArgs c(board.size()); for (int k = board.size(); k--; ) { c[k] = p[k*ncolors+col]; } extensional(*this, c, get_constraint(i, mark, other, other)); ++tile; } } } if (opt.symmetry() == SYMMETRY_FULL) { // Remove symmetrical boards IntVarArgs orig(board.size()-height), symm(board.size()-height); int pos = 0; for (int i = 0; i < board.size(); ++i) { if ((i+1)%width==0) continue; orig[pos++] = board[i]; } int w2, h2; bsymmfunc syms[] = {flipx, flipy, flipd1, flipd2, rot90, rot180, rot270}; int symscnt = sizeof(syms)/sizeof(bsymmfunc); for (int i = 0; i < symscnt; ++i) { syms[i](orig, width-1, height, symm, w2, h2); if (width-1 == w2 && height == h2) rel(*this, orig, IRT_LQ, symm); } } // Install branching branch(*this, board, INT_VAR_NONE, INT_VAL_MIN); }
/// The model of the problem CrowdedChess(const SizeOptions& opt) : n(opt.size()), s(*this, n*n, 0, PMAX-1), queens(*this, n, 0, n-1), rooks(*this, n, 0, n-1), knights(*this, n*n, 0, 1) { const int nkval = sizeof(kval)/sizeof(int); const int nn = n*n, q = n, r = n, b = (2*n)-2, k = n <= nkval ? kval[n-1] : kval[nkval-1]; const int e = nn - (q + r + b + k); assert(nn == (e + q + r + b + k)); Matrix<IntVarArray> m(s, n); // *********************** // Basic model // *********************** count(*this, s, E, IRT_EQ, e, opt.icl()); count(*this, s, Q, IRT_EQ, q, opt.icl()); count(*this, s, R, IRT_EQ, r, opt.icl()); count(*this, s, B, IRT_EQ, b, opt.icl()); count(*this, s, K, IRT_EQ, k, opt.icl()); // Collect rows and columns for handling rooks and queens for (int i = 0; i < n; ++i) { IntVarArgs aa = m.row(i), bb = m.col(i); count(*this, aa, Q, IRT_EQ, 1, opt.icl()); count(*this, bb, Q, IRT_EQ, 1, opt.icl()); count(*this, aa, R, IRT_EQ, 1, opt.icl()); count(*this, bb, R, IRT_EQ, 1, opt.icl()); // Connect (queens|rooks)[i] to the row it is in element(*this, aa, queens[i], Q, ICL_DOM); element(*this, aa, rooks[i], R, ICL_DOM); } // N-queens constraints distinct(*this, queens, ICL_DOM); distinct(*this, IntArgs::create(n,0,1), queens, ICL_DOM); distinct(*this, IntArgs::create(n,0,-1), queens, ICL_DOM); // N-rooks constraints distinct(*this, rooks, ICL_DOM); // Collect diagonals for handling queens and bishops for (int l = n; l--; ) { const int il = (n-1) - l; IntVarArgs d1(l+1), d2(l+1), d3(l+1), d4(l+1); for (int i = 0; i <= l; ++i) { d1[i] = m(i+il, i); d2[i] = m(i, i+il); d3[i] = m((n-1)-i-il, i); d4[i] = m((n-1)-i, i+il); } count(*this, d1, Q, IRT_LQ, 1, opt.icl()); count(*this, d2, Q, IRT_LQ, 1, opt.icl()); count(*this, d3, Q, IRT_LQ, 1, opt.icl()); count(*this, d4, Q, IRT_LQ, 1, opt.icl()); if (opt.propagation() == PROP_DECOMPOSE) { count(*this, d1, B, IRT_LQ, 1, opt.icl()); count(*this, d2, B, IRT_LQ, 1, opt.icl()); count(*this, d3, B, IRT_LQ, 1, opt.icl()); count(*this, d4, B, IRT_LQ, 1, opt.icl()); } } if (opt.propagation() == PROP_TUPLE_SET) { IntVarArgs b(s.size()); for (int i = s.size(); i--; ) b[i] = channel(*this, expr(*this, (s[i] == B))); extensional(*this, b, bishops, EPK_DEF, opt.icl()); } // Handle knigths // Connect knigths to board for(int i = n*n; i--; ) knights[i] = expr(*this, (s[i] == K)); knight_constraints(); // *********************** // Redundant constraints // *********************** // Queens and rooks not in the same place // Faster than going through the channelled board-connection for (int i = n; i--; ) rel(*this, queens[i], IRT_NQ, rooks[i]); // Place bishops in two corners (from Schimpf and Hansens solution) // Avoids some symmetries of the problem rel(*this, m(n-1, 0), IRT_EQ, B); rel(*this, m(n-1, n-1), IRT_EQ, B); // *********************** // Branching // *********************** // Place each piece in turn branch(*this, s, INT_VAR_MIN_MIN(), INT_VAL_MIN()); }