LatinSquares(const SizeOptions& opt) : n(opt.size()), x(*this, n*n, 1, n) { // Matrix wrapper for the x grid Matrix<IntVarArray> m(x, n, n); latin_square(*this, m, opt.icl()); // Symmetry breaking. 0 is upper left column if (opt.symmetry() == SYMMETRY_MIN) { rel(*this, x[0] == 1, opt.icl()); } branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_RANGE_MAX()); }
/// Actual model AllInterval(const SizeOptions& opt) : Script(opt), x(*this, opt.size(), 0, 66) { // 66 or opt.size() - 1 const int n = x.size(); IntVarArgs d(n-1); IntVarArgs dd(66); IntVarArgs xx_(n); // pitch class for AllInterval Chords IntVar douze; Rnd r(1U); if ((opt.model() == MODEL_SET) || (opt.model() == MODEL_SET_CHORD) || (opt.model() == MODEL_SSET_CHORD) ||(opt.model() == MODEL_SYMMETRIC_SET)) // Modele original : serie { // Set up variables for distance for (int i=0; i<n-1; i++) d[i] = expr(*this, abs(x[i+1]-x[i]), opt.ipl()); // Constrain them to be between 1 and n-1 dom(*this, d, 1, n-1); dom(*this, x, 0, n-1); if((opt.model() == MODEL_SET_CHORD) || (opt.model() == MODEL_SSET_CHORD)) { /*expr(*this,dd[0]==0); // Set up variables for distance for (int i=0; i<n-1; i++) { expr(*this, dd[i+1] == (dd[i]+d[i])%12, opt.icl()); } // Constrain them to be between 1 and n-1 dom(*this, dd,0, n-1); distinct(*this, dd, opt.icl()); */ rel(*this, abs(x[0]-x[n-1]) == 6, opt.ipl()); } if(opt.symmetry()) { // Break mirror symmetry (renversement) rel(*this, x[0], IRT_LE, x[1]); // Break symmetry of dual solution (retrograde de la serie) -> 1928 solutions pour accords de 12 sons rel(*this, d[0], IRT_GR, d[n-2]); } //series symetriques if ((opt.model() == MODEL_SYMMETRIC_SET)|| (opt.model() == MODEL_SSET_CHORD)) { rel (*this, d[n/2 - 1] == 6); // pivot = triton for (int i=0; i<(n/2)-2; i++) rel(*this,d[i]+d[n-i-2]==12); } } else { for (int j=0; j<n; j++) xx_[j] = expr(*this, x[j] % 12); dom(*this, xx_, 0, 11); distinct(*this, xx_, opt.ipl()); //intervalles for (int i=0; i<n-1; i++) d[i] = expr(*this,x[i+1] - x[i],opt.ipl()); dom(*this, d, 1, n-1); dom(*this, x, 0, n * (n - 1) / 2.); //d'autres choses dont on est certain (contraintes redondantes) : rel(*this, x[0] == 0); rel(*this, x[n-1] == n * (n - 1) / 2.); // break symmetry of dual solution (renversement de l'accord) if(opt.symmetry()) rel(*this, d[0], IRT_GR, d[n-2]); //accords symetriques if (opt.model() == MODEL_SYMMETRIC_CHORD) { rel (*this, d[n/2 - 1] == 6); // pivot = triton for (int i=0; i<(n/2)-2; i++) rel(*this,d[i]+d[n-i-2]==12); } if (opt.model() == MODEL_PARALLEL_CHORD) { rel (*this, d[n/2 - 1] == 6); // pivot = triton for (int i=0; i<(n/2)-2; i++) rel(*this,d[i]+d[n/2 + i]==12); } } distinct(*this, x, opt.ipl()); distinct(*this, d, opt.ipl()); #if 0 //TEST IntVarArray counter(*this,12,0,250); IntVar testcounter(*this,0,250); for (int i=1; i<11; i++) { count(*this, d, i,IRT_EQ,testcounter,opt.icl()); // OK } count(*this, d, counter,opt.icl()); // OK #endif //END TEST if(opt.branching() == 0) branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_SPLIT_MIN()); else branch(*this, x, INT_VAR_RND(r), INT_VAL_RND(r)); }
/// The actual model GraphColor(const SizeOptions& opt) : IntMinimizeScript(opt), g(opt.size() == 1 ? g2 : g1), v(*this,g.n_v,0,g.n_v-1), m(*this,0,g.n_v-1) { rel(*this, v, IRT_LQ, m); for (int i = 0; g.e[i] != -1; i += 2) rel(*this, v[g.e[i]], IRT_NQ, v[g.e[i+1]]); const int* c = g.c; for (int i = *c++; i--; c++) rel(*this, v[*c], IRT_EQ, i); while (*c != -1) { int n = *c; IntVarArgs x(n); c++; for (int i = n; i--; c++) x[i] = v[*c]; distinct(*this, x, opt.icl()); if (opt.model() == MODEL_CLIQUE) rel(*this, m, IRT_GQ, n-1); } /// Branching on the number of colors branch(*this, m, INT_VAL_MIN()); if (opt.symmetry() == SYMMETRY_NONE) { /// Branching without symmetry breaking switch (opt.branching()) { case BRANCH_SIZE: branch(*this, v, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); break; case BRANCH_DEGREE: branch(*this, v, tiebreak(INT_VAR_DEGREE_MAX(),INT_VAR_SIZE_MIN()), INT_VAL_MIN()); break; case BRANCH_SIZE_DEGREE: branch(*this, v, INT_VAR_DEGREE_SIZE_MAX(), INT_VAL_MIN()); break; case BRANCH_SIZE_AFC: branch(*this, v, INT_VAR_AFC_SIZE_MAX(opt.decay()), INT_VAL_MIN()); break; case BRANCH_SIZE_ACTIVITY: branch(*this, v, INT_VAR_ACTIVITY_SIZE_MAX(opt.decay()), INT_VAL_MIN()); break; default: break; } } else { // opt.symmetry() == SYMMETRY_LDSB /// Branching while considering value symmetry breaking /// (every permutation of color values gives equivalent solutions) Symmetries syms; syms << ValueSymmetry(IntArgs::create(g.n_v,0)); switch (opt.branching()) { case BRANCH_SIZE: branch(*this, v, INT_VAR_SIZE_MIN(), INT_VAL_MIN(), syms); break; case BRANCH_DEGREE: branch(*this, v, tiebreak(INT_VAR_DEGREE_MAX(),INT_VAR_SIZE_MIN()), INT_VAL_MIN(), syms); break; case BRANCH_SIZE_DEGREE: branch(*this, v, INT_VAR_DEGREE_SIZE_MAX(), INT_VAL_MIN(), syms); break; case BRANCH_SIZE_AFC: branch(*this, v, INT_VAR_AFC_SIZE_MAX(opt.decay()), INT_VAL_MIN(), syms); break; case BRANCH_SIZE_ACTIVITY: branch(*this, v, INT_VAR_ACTIVITY_SIZE_MAX(opt.decay()), INT_VAL_MIN(), syms); break; default: break; } } }
/// 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); }