/// Actual model Photo(const SizeOptions& opt) : IntMinimizeScript(opt), spec(opt.size() == 0 ? p_small : p_large), pos(*this,spec.n_names, 0, spec.n_names-1), violations(*this,0,spec.n_prefs) { // Map preferences to violation BoolVarArgs viol(spec.n_prefs); for (int i=0; i<spec.n_prefs; i++) { int pa = spec.prefs[2*i+0]; int pb = spec.prefs[2*i+1]; viol[i] = expr(*this, abs(pos[pa]-pos[pb]) > 1); } rel(*this, violations == sum(viol)); distinct(*this, pos, opt.icl()); // Break some symmetries rel(*this, pos[0] < pos[1]); if (opt.branching() == BRANCH_NONE) { branch(*this, pos, INT_VAR_NONE(), INT_VAL_MIN()); } else { branch(*this, pos, tiebreak(INT_VAR_DEGREE_MAX(),INT_VAR_SIZE_MIN()), INT_VAL_MIN()); } }
/// Constructor QueenArmies(const SizeOptions& opt) : n(opt.size()), U(*this, IntSet::empty, IntSet(0, n*n)), W(*this, IntSet::empty, IntSet(0, n*n)), w(*this, n*n, 0, 1), b(*this, n*n, 0, 1), q(*this, 0, n*n) { // Basic rules of the model for (int i = n*n; i--; ) { // w[i] means that no blacks are allowed on A[i] rel(*this, w[i] == (U || A[i])); // Make sure blacks and whites are disjoint. rel(*this, !w[i] || !b[i]); // If i in U, then b[i] has a piece. rel(*this, b[i] == (singleton(i) <= U)); } // Connect optimization variable to number of pieces linear(*this, w, IRT_EQ, q); linear(*this, b, IRT_GQ, q); // Connect cardinality of U to the number of black pieces. IntVar unknowns = expr(*this, cardinality(U)); rel(*this, q <= unknowns); linear(*this, b, IRT_EQ, unknowns); if (opt.branching() == BRANCH_NAIVE) { branch(*this, w, INT_VAR_NONE, INT_VAL_MAX); branch(*this, b, INT_VAR_NONE, INT_VAL_MAX); } else { QueenBranch::post(*this); assign(*this, b, INT_ASSIGN_MAX); } }
/// Actual model WordSquare(const SizeOptions& opt) : w_l(opt.size()), letters(*this, w_l*w_l) { // Initialize letters Matrix<IntVarArray> ml(letters, w_l, w_l); for (int i=0; i<w_l; i++) for (int j=i; j<w_l; j++) ml(i,j) = ml(j,i) = IntVar(*this, 'a','z'); // Number of words with that length const int n_w = dict.words(w_l); // Initialize word array IntVarArgs words(*this, w_l, 0, n_w-1); // All words must be different distinct(*this, words); // Link words with letters for (int i=0; i<w_l; i++) { // Map each word to i-th letter in that word IntSharedArray w2l(n_w); for (int n=n_w; n--; ) w2l[n]=dict.word(w_l,n)[i]; for (int j=0; j<w_l; j++) element(*this, w2l, words[j], ml(i,j)); } // Symmetry breaking: the last word must be later in the wordlist rel(*this, words[0], IRT_LE, words[w_l-1]); switch (opt.branching()) { case BRANCH_WORDS: // Branch by assigning words branch(*this, words, INT_VAR_SIZE_MIN(), INT_VAL_SPLIT_MIN()); break; case BRANCH_LETTERS: // Branch by assigning letters branch(*this, letters, INT_VAR_AFC_SIZE_MAX(opt.decay()), INT_VAL_MIN()); break; } }
/// 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; } }
/// The actual model GraphColor(const SizeOptions& opt) : g(opt.size() == 1 ? g2 : g1), v(*this,g.n_v,0,g.n_v), m(*this,0,g.n_v) { 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); } branch(*this, m, INT_VAL_MIN); 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_SIZE_DEGREE_MIN, INT_VAL_MIN); break; case BRANCH_SIZE_AFC: branch(*this, v, INT_VAR_SIZE_AFC_MIN, INT_VAL_MIN); break; default: 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 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. Nonogram(const SizeOptions& opt) : spec(specs[opt.size()]), b(*this,width()*height(),0,1) { Matrix<BoolVarArray> m(b, width(), height()); { int spos = 2; // Post constraints for columns for (int w=0; w<width(); w++) extensional(*this, m.col(w), line(spos)); // Post constraints for rows for (int h=0; h<height(); h++) extensional(*this, m.row(h), line(spos)); } switch (opt.branching()) { case BRANCH_NONE: { /* * The following branches either by columns or rows, depending on * whether there are more hints relative to the height or width * for columns or rows. * * This idea is due to Pascal Van Hentenryck and has been suggested * to us by Hakan Kjellerstrand. */ // Number of hints for columns int cols = 0; // Number of hints for rows int rows = 0; int spos = 2; for (int w=0; w<width(); w++) { int hint = spec[spos++]; cols += hint; spos += hint; } for (int h=0; h<height(); h++) { int hint = spec[spos++]; rows += hint; spos += hint; } if (rows*width() > cols*height()) { for (int w=0; w<width(); w++) branch(*this, m.col(w), INT_VAR_NONE, INT_VAL_MAX); } else { for (int h=0; h<height(); h++) branch(*this, m.row(h), INT_VAR_NONE, INT_VAL_MAX); } } break; case BRANCH_AFC: /* * The following just uses the AFC for branching. This is * equivalent to SIZE/AFC in this case since the variables are * binary. */ branch(*this, b, INT_VAR_AFC_MAX, INT_VAL_MAX); break; } }