Sudoku(const SizeOptions& opt) : x(*this, 9 * 9, 1, 9) { Matrix<IntVarArray> m(x, 9, 9); for (int i = 0; i < 9; i++) { distinct(*this, m.row(i), opt.icl()); distinct(*this, m.col(i), opt.icl()); } for (int i = 0; i < 9; i += 3) { for (int j = 0; j < 9; j += 3) { distinct(*this, m.slice(i, i + 3, j, j + 3), opt.icl()); } } for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (int v = sudokuField(board, i, j)) { //Here the m(i, j) is the element in colomn i and row j. rel(*this, m(i, j), IRT_EQ, v); } } } branch(*this, x, INT_VAR_NONE(), INT_VAL_SPLIT_MIN()); }
Coins3(const SizeOptions& opt) : num_coins_val(opt.size()), x(*this, n, 0, 99), num_coins(*this, 0, 99) { // values of the coins int _variables[] = {1, 2, 5, 10, 25, 50}; IntArgs variables(n, _variables); // sum the number of coins linear(*this, x, IRT_EQ, num_coins, opt.icl()); // This is the "main loop": // Checks that all changes from 1 to 99 can be made for(int j = 0; j < 99; j++) { IntVarArray tmp(*this, n, 0, 99); linear(*this, variables, tmp, IRT_EQ, j, opt.icl()); for(int i = 0; i < n; i++) { rel(*this, tmp[i] <= x[i], opt.icl()); } } // set the number of coins (via opt.size()) // don't forget // -search dfs if (num_coins_val) { rel(*this, num_coins == num_coins_val, opt.icl()); } branch(*this, x, INT_VAR_SIZE_MAX(), INT_VAL_MIN()); }
/// Actual model OrthoLatinSquare(const SizeOptions& opt) : Script(opt), n(opt.size()), x1(*this,n*n,1,n), x2(*this,n*n,1,n) { const int nn = n*n; IntVarArgs z(*this,nn,0,n*n-1); distinct(*this, z, opt.icl()); // Connect { IntArgs mod(n*n); IntArgs div(n*n); for (int i=0; i<n; i++) for (int j=0; j<n; j++) { mod[i*n+j] = j+1; div[i*n+j] = i+1; } for (int i = nn; i--; ) { element(*this, div, z[i], x2[i]); element(*this, mod, z[i], x1[i]); } } // Rows for (int i = n; i--; ) { IntVarArgs ry(n); for (int j = n; j--; ) ry[j] = y1(i,j); distinct(*this, ry, opt.icl()); for (int j = n; j--; ) ry[j] = y2(i,j); distinct(*this, ry, opt.icl()); } for (int j = n; j--; ) { IntVarArgs cy(n); for (int i = n; i--; ) cy[i] = y1(i,j); distinct(*this, cy, opt.icl()); for (int i = n; i--; ) cy[i] = y2(i,j); distinct(*this, cy, opt.icl()); } for (int i = 1; i<n; i++) { IntVarArgs ry1(n); IntVarArgs ry2(n); for (int j = n; j--; ) { ry1[j] = y1(i-1,j); ry2[j] = y2(i,j); } rel(*this, ry1, IRT_GQ, ry2); } branch(*this, z, INT_VAR_SIZE_MIN(), INT_VAL_SPLIT_MIN()); }
/// Actual model TSP(const SizeOptions& opt) : p(ps[opt.size()]), succ(*this, p.size(), 0, p.size()-1), total(*this, 0, p.max()) { int n = p.size(); // Cost matrix IntArgs c(n*n, p.d()); for (int i=n; i--; ) for (int j=n; j--; ) if (p.d(i,j) == 0) rel(*this, succ[i], IRT_NQ, j); // Cost of each edge IntVarArgs costs(*this, n, Int::Limits::min, Int::Limits::max); // Enforce that the succesors yield a tour with appropriate costs circuit(*this, c, succ, costs, total, opt.icl()); // Just assume that the circle starts forwards { IntVar p0(*this, 0, n-1); element(*this, succ, p0, 0); rel(*this, p0, IRT_LE, succ[0]); } // First enumerate cost values, prefer those that maximize cost reduction branch(*this, costs, INT_VAR_REGRET_MAX_MAX(), INT_VAL_SPLIT_MIN()); // Then fix the remaining successors branch(*this, succ, INT_VAR_MIN_MIN(), INT_VAL_MIN()); }
/// 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()); } }
/// Actual model GolombRuler(const SizeOptions& opt) : IntMinimizeScript(opt), m(*this,opt.size(),0, (opt.size() < 31) ? (1 << (opt.size()-1))-1 : Int::Limits::max) { // Assume first mark to be zero rel(*this, m[0], IRT_EQ, 0); // Order marks rel(*this, m, IRT_LE); // Number of marks and differences const int n = m.size(); const int n_d = (n*n-n)/2; // Array of differences IntVarArgs d(n_d); // Setup difference constraints for (int k=0, i=0; i<n-1; i++) for (int j=i+1; j<n; j++, k++) // d[k] is m[j]-m[i] and must be at least sum of first j-i integers rel(*this, d[k] = expr(*this, m[j]-m[i]), IRT_GQ, (j-i)*(j-i+1)/2); distinct(*this, d, opt.icl()); // Symmetry breaking if (n > 2) rel(*this, d[0], IRT_LE, d[n_d-1]); branch(*this, m, INT_VAR_NONE(), INT_VAL_MIN()); }
/// Post a distinct-linear constraint on variables \a x with sum \a c void distinctlinear(Cache& dc, const IntVarArgs& x, int c, const SizeOptions& opt) { int n=x.size(); if (opt.model() == MODEL_DECOMPOSE) { if (n < 8) linear(*this, x, IRT_EQ, c, opt.icl()); else if (n == 8) rel(*this, x, IRT_NQ, 9*(9+1)/2 - c); distinct(*this, x, opt.icl()); } else { switch (n) { case 0: return; case 1: rel(*this, x[0], IRT_EQ, c); return; case 8: // Prune the single missing digit rel(*this, x, IRT_NQ, 9*(9+1)/2 - c); break; case 9: break; default: if (c == n*(n+1)/2) { // sum has unique decomposition: 1 + ... + n rel(*this, x, IRT_LQ, n); } else if (c == n*(n+1)/2 + 1) { // sum has unique decomposition: 1 + ... + n-1 + n+1 rel(*this, x, IRT_LQ, n+1); rel(*this, x, IRT_NQ, n); } else if (c == 9*(9+1)/2 - (9-n)*(9-n+1)/2) { // sum has unique decomposition: (9-n+1) + (9-n+2) + ... + 9 rel(*this, x, IRT_GQ, 9-n+1); } else if (c == 9*(9+1)/2 - (9-n)*(9-n+1)/2 + 1) { // sum has unique decomposition: (9-n) + (9-n+2) + ... + 9 rel(*this, x, IRT_GQ, 9-n); rel(*this, x, IRT_NQ, 9-n+1); } else { extensional(*this, x, dc.get(n,c)); return; } } distinct(*this, x, opt.icl()); } }
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) : x(*this, opt.size(), 0, opt.size()-1), d(*this, opt.size()-1, 1, opt.size()-1) { const int n = x.size(); // Set up variables for distance for (int i=0; i<n-1; i++) rel(*this, d[i] == abs(x[i+1]-x[i]), opt.icl()); distinct(*this, x, opt.icl()); distinct(*this, d, opt.icl()); // Break mirror symmetry rel(*this, x[0], IRT_LE, x[1]); // Break symmetry of dual solution rel(*this, d[0], IRT_GR, d[n-2]); branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_SPLIT_MIN()); }
// Actual model AllEqual(const SizeOptions& opt) : x(*this, n, 0, 6) { all_equal(*this, x, n, opt.icl()); // branching branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); }
/// 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; } }
SetCovering(const SizeOptions& opt) : min_distance(opt.size()), x(*this, num_cities, 0, 1), z(*this, 0, num_cities) { // distance between the cities int distance[] = { 0,10,20,30,30,20, 10, 0,25,35,20,10, 20,25, 0,15,30,20, 30,35,15, 0,15,25, 30,20,30,15, 0,14, 20,10,20,25,14, 0 }; // z = sum of placed fire stations linear(*this, x, IRT_EQ, z, opt.icl()); // ensure that all cities are covered by at least one fire station for(int i = 0; i < num_cities; i++) { IntArgs in_distance(num_cities); // the cities within the distance for(int j = 0; j < num_cities; j++) { if (distance[i*num_cities+j] <= min_distance) { in_distance[j] = 1; } else { in_distance[j] = 0; } } linear(*this, in_distance, x, IRT_GQ, 1, opt.icl()); } branch(*this, x, INT_VAR_SIZE_MAX(), INT_VAL_SPLIT_MIN()); }
/// Actual model AllInterval(const SizeOptions& opt) : x(*this, opt.size(), 0, opt.size() - 1) { const int n = x.size(); IntVarArgs d(n-1); // Set up variables for distance for (int i=0; i<n-1; i++) d[i] = expr(*this, abs(x[i+1]-x[i]), opt.icl()); // Constrain them to be between 1 and n-1 dom(*this, d, 1, n-1); distinct(*this, x, opt.icl()); distinct(*this, d, opt.icl()); // Break mirror symmetry rel(*this, x[0], IRT_LE, x[1]); // Break symmetry of dual solution rel(*this, d[0], IRT_GR, d[n-2]); branch(*this, x, INT_VAR_SIZE_MIN, INT_VAL_SPLIT_MIN); }
/// Post constraints MagicSquare(const SizeOptions& opt) : n(opt.size()), x(*this,n*n,1,n*n) { // Number of fields on square const int nn = n*n; // Sum of all a row, column, or diagonal const int s = nn*(nn+1) / (2*n); // Matrix-wrapper for the square Matrix<IntVarArray> m(x, n, n); for (int i = n; i--; ) { linear(*this, m.row(i), IRT_EQ, s, opt.icl()); linear(*this, m.col(i), IRT_EQ, s, opt.icl()); } // Both diagonals must have sum s { IntVarArgs d1y(n); IntVarArgs d2y(n); for (int i = n; i--; ) { d1y[i] = m(i,i); d2y[i] = m(n-i-1,i); } linear(*this, d1y, IRT_EQ, s, opt.icl()); linear(*this, d2y, IRT_EQ, s, opt.icl()); } // All fields must be distinct distinct(*this, x, opt.icl()); // Break some (few) symmetries rel(*this, m(0,0), IRT_GR, m(0,n-1)); rel(*this, m(0,0), IRT_GR, m(n-1,0)); branch(*this, x, INT_VAR_SIZE_MIN, INT_VAL_SPLIT_MIN); }
// Actual model AlldifferentCst(const SizeOptions& opt) : x(*this, n, 1, 9), cst(*this, n, 0, 9) { int _cst1[] = {0,1,0,4}; IntArgs cst1(n, _cst1); for(int i = 0; i < n; i++) { rel(*this, cst[i] == cst1[i]); } alldifferent_cst(*this, x, cst, n, opt.icl()); // branching branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); }
// Actual model AlldifferentModulo(const SizeOptions& opt) : x(*this, n, 1, 25), m(*this, 1, 5) { int _tmp[] = {25,1,14,3}; IntArgs tmp(n, _tmp); for(int i = 0; i < n; i++) { rel(*this, x[i] == tmp[i]); } alldifferent_modulo(*this, x, n, m, opt.icl()); // rel(*this, m==5); // branching branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, m, INT_VAL_MIN()); }
/// Actual model Partition(const SizeOptions& opt) : x(*this,opt.size(),1,2*opt.size()), y(*this,opt.size(),1,2*opt.size()) { const int n = opt.size(); // Break symmetries by ordering numbers in each group rel(*this, x, IRT_LE); rel(*this, y, IRT_LE); rel(*this, x[0], IRT_LE, y[0]); IntVarArgs xy(2*n); for (int i = n; i--; ) { xy[i] = x[i]; xy[n+i] = y[i]; } distinct(*this, xy, opt.icl()); IntArgs c(2*n); for (int i = n; i--; ) { c[i] = 1; c[n+i] = -1; } linear(*this, c, xy, IRT_EQ, 0); // Array of products IntVarArgs sxy(2*n), sx(n), sy(n); for (int i = n; i--; ) { sx[i] = sxy[i] = expr(*this, sqr(x[i])); sy[i] = sxy[n+i] = expr(*this, sqr(y[i])); } linear(*this, c, sxy, IRT_EQ, 0); // Redundant constraints linear(*this, x, IRT_EQ, 2*n*(2*n+1)/4); linear(*this, y, IRT_EQ, 2*n*(2*n+1)/4); linear(*this, sx, IRT_EQ, 2*n*(2*n+1)*(4*n+1)/12); linear(*this, sy, IRT_EQ, 2*n*(2*n+1)*(4*n+1)/12); branch(*this, xy, INT_VAR_AFC_SIZE_MAX(opt.decay()), INT_VAL_MIN()); }
/// 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; } }
// Actual model AlldifferentOnIntersection(const SizeOptions& opt) : x(*this, m, 1, 9), y(*this, n, 1, 9) { int _xtmp[] = {5,9,1,5}; IntArgs xtmp(m, _xtmp); for(int i = 0; i < m; i++) { rel(*this, x[i] == xtmp[i]); } int _ytmp[] = {2, 1, 6, 9, 6, 2}; IntArgs ytmp(n, _ytmp); for(int j = 0; j < n; j++) { rel(*this, y[j] == ytmp[j]); } alldifferent_on_intersection(*this, x, m, y, n, opt.icl()); // branching branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, y, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); }
/// Setup model SportsLeague(const SizeOptions& opt) : teams(opt.size()), home(*this, periods() * teams, 1, weeks()), away(*this, periods() * teams, 2, weeks()+1), game(*this, weeks()*periods(), 2, teams*weeks()) { // Initialize round robin schedule RRS r(teams); // Domain for gamenumber of period for (int w=0; w<weeks(); w++) { IntArgs rh(periods()), ra(periods()), rg(periods()); IntVarArgs n(*this,periods(),0,periods()-1); distinct(*this, n, opt.icl()); r.hag(w,rh,ra,rg); for (int p=0; p<periods(); p++) { element(*this, rh, n[p], h(p,w)); element(*this, ra, n[p], a(p,w)); element(*this, rg, n[p], g(p,w)); } } /// (h,a) and (a,h) are the same game, focus on home (that is, h<a) for (int p=0; p<periods(); p++) for (int w=0; w<teams; w++) rel(*this, h(p,w), IRT_LE, a(p,w)); // Home teams in first week are ordered { IntVarArgs h0(periods()); for (int p=0; p<periods(); p++) h0[p] = h(p,0); rel(*this, h0, IRT_LE); } // Fix first pair rel(*this, h(0,0), IRT_EQ, 1); rel(*this, a(0,0), IRT_EQ, 2); /// Column constraint: each team occurs exactly once for (int w=0; w<teams; w++) { IntVarArgs c(teams); for (int p=0; p<periods(); p++) { c[2*p] = h(p,w); c[2*p+1] = a(p,w); } distinct(*this, c, opt.icl()); } /// Row constraint: no team appears more than twice for (int p=0; p<periods(); p++) { IntVarArgs r(2*teams); for (int t=0; t<teams; t++) { r[2*t] = h(p,t); r[2*t+1] = a(p,t); } IntArgs values(teams); for (int i=1; i<=teams; i++) values[i-1] = i; count(*this, r, IntSet(2,2), values, opt.icl()); } // Redundant constraint for (int p=0; p<periods(); p++) for (int w=0; w<weeks(); w ++) rel(*this, teams * h(p,w) + a(p,w) - g(p,w) == teams); distinct(*this, game, opt.icl()); branch(*this, game, INT_VAR_NONE(), INT_VAL_SPLIT_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()); }
// Actual model Strimko(const SizeOptions& opt) : prob(problems[opt.size()]), x(*this, prob_size()*prob_size(), 1, prob_size()) { int n = prob_size(); std::cout << "Problem " << opt.size() << " size: " << n << std::endl; // // get data for this problem // int s = 1; // we have already taken n (the size) // streams int streams[n*n]; std::cout << "streams: " << std::endl; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { streams[i*n+j] = prob[s++]; std::cout << streams[i*n+j] << " "; } std::cout << std::endl; } // placed int num_placed = prob[s++];// 5; int placed[num_placed*3]; std::cout << "\nplaced: " << std::endl; for(int i = 0; i < num_placed; i++) { for(int j = 0; j < 3; j++) { placed[i*3+j] = prob[s++]; std::cout << placed[i*3+j] << " " ; } std::cout << std::endl; } std::cout << std::endl; Matrix<IntVarArray> x_m(x, n, n); /* * * Constraints * */ // // Latin Square // for (int i = 0; i < n; i++) { distinct(*this, x_m.row(i), opt.icl()); distinct(*this, x_m.col(i), opt.icl()); } // // Streams // for(int st = 1; st <= n; st++) { IntVarArgs stream; for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { if (streams[i*n+j] == st) { // stream << x[i*n+j]; // direct on x stream << x_m(j,i); // matrix access } } } distinct(*this, stream, opt.icl()); } // // Placed hints // for(int i = 0; i < num_placed; i++) { int pi = placed[i*3]-1; int pi1 = placed[i*3+1]-1; int pi2 = placed[i*3+2]; // rel(*this, x[pi*n+pi1] == pi2, opt.icl()); // direct on x rel(*this, x_m(pi1,pi) == pi2, opt.icl()); // matrix access } branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); }
/// 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)); }
// Actual model Speakers(const SizeOptions& opt) : x(*this, n, 1, n) { // // available slots: // /* // First solution: populate from a integer array // where the first number represents the number of items int __available[] = { // size: available // Reasoning. Step# : reason 4, 3,4,5,6, // #2: the only one with 6 after speaker F -> 1 2, 3,4, // #5: 3 or 4 4, 2,3,4,5, // #3: only with 5 after F -> 1 and A -> 6 3, 2,3,4, // #4: only with 2 after C -> 5 and F -> 1 2, 3,4, // #5: 3 or 4 6, 1,2,3,4,5,6 // #1: the only with 1 }; // convert to IntSet IntSet _available[n]; int s = 0; for(int i = 0; i < n; i++) { int num = __available[s++]; IntArgs tmp; for(int j = 0; j < num; j++) { tmp << __available[s++]; } _available[i] = IntSet(tmp); } // and then to IntSetArgs IntSetArgs available(n, _available); */ // // Oh, this is much easier, at least for this small example // IntSetArgs available(n); available[0] = IntSet( IntArgs() << 3 << 4 << 5 << 6 ); available[1] = IntSet( IntArgs() << 3 << 4 ); available[2] = IntSet( IntArgs() << 2 << 3 << 4 << 5 ); available[3] = IntSet( IntArgs() << 2 << 3 << 4 ); available[4] = IntSet( IntArgs() << 3 << 4 ); available[5] = IntSet( IntArgs() << 1 << 2 << 3 << 4 << 5 << 6 ); distinct(*this, x, opt.icl()); for(int i = 0; i < n; i++) { // From Modeling and Programming in Gecode, // section 5.2.2, Relation constraints: // """ // If x is a set variable and y is an integer variable, then // rel(home, x, SRT_SUP, y); // constrains x to be a superset of the singleton set {y}, // which means that y must be an element of x. // """ // // corresponds to: forall(i in 1..n) (x[i] in available[i]) // // rel(*this, SetVar(*this, available[i],available[i]), SRT_SUP, x[i]); // this is easier: rel(*this, singleton(x[i]) <= available[i]); } branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); }
/// 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; } } }
DriveYaNuts(const SizeOptions& opt) : x(*this, m*n, 1, n), pos(*this, m, 0, m-1), pos_inv(*this, m, 0, m-1), start_ix(*this, m, 0, n-1) { // data // in base 1 (fixed below) int _connections[] = { //nuts sides to be equal 1,2, 3,6, 2,3, 4,1, 3,4, 5,2, 4,5, 6,3, 5,6, 1,4, 6,1, 2,5, 7,1, 1,4, 7,2, 2,5, 7,3, 3,6, 7,4, 4,1, 7,5, 5,2, 7,6, 6,3, }; IntArgs connections(num_connections*4, _connections); // This is the nuts in the solution order. // 1,4,6,2,3,5, 1,4,6,2,3,5, // 1 // 1,6,5,3,2,4, 1,6,5,3,2,4, // 2 // 1,4,3,6,5,2, 1,4,3,6,5,2, // 3 // 1,2,3,4,5,6, 1,2,3,4,5,6, // 4 // 1,6,4,2,5,3, 1,6,4,2,5,3, // 5 // 1,6,5,4,3,2, 1,6,5,4,3,2, // 6 // 1,6,2,4,5,3, 1,6,2,4,5,3, // 7 // center nut // Note that pos_inv for the shown solution is the permutation // [4,3,1,7,5,2,6] int _nuts[] = { 1,2,3,4,5,6, 1,2,3,4,5,6, // 4 (row 4 in the solution order) 1,4,3,6,5,2, 1,4,3,6,5,2, // 3 1,4,6,2,3,5, 1,4,6,2,3,5, // 1 1,6,2,4,5,3, 1,6,2,4,5,3, // 7 [center nut] 1,6,4,2,5,3, 1,6,4,2,5,3, // 5 1,6,5,3,2,4, 1,6,5,3,2,4, // 2 1,6,5,4,3,2, 1,6,5,4,3,2, // 6 }; IntArgs nuts1(m*n*2, _nuts); Matrix<IntArgs> nuts(nuts1, n*2, m); Matrix<IntVarArray> xm(x, n, m); for(int i = 0; i < m; i++) { distinct(*this, xm.row(i), opt.icl()); IntVar k(*this, 0, n-1); IntVar p(*this, 0, m-1); rel(*this, start_ix[i] == k); rel(*this, pos[i] == p); for(int j = 0; j < n; j++) { // x[i,j] == nuts[p, j+k] // Using matrix element IntVar jk(*this, 0, n*2-1); rel(*this, jk == j+k); element(*this, nuts, jk, p, xm(j,i)); // Using plain element /* IntVar pjk(*this, 0, 2*n*m); rel(*this, pjk == p*n*2+j+k); element(*this, nuts1, pjk, xm(j,i)); */ } } distinct(*this, pos, opt.icl()); channel(*this, pos, pos_inv); // check the connections for(int c = 0; c < num_connections; c++) { // note: xm(col, row) rel(*this, xm(connections[c*4+2]-1,connections[c*4+0]-1) == xm(connections[c*4+3]-1,connections[c*4+1]-1)); } // symmetry breaking: // We pick the solution where the center nut (nut 7) start with 1. rel(*this, start_ix[m-1] == 0); branch(*this, pos, INT_VAR_SIZE_MIN(), INT_VAL_SPLIT_MIN()); branch(*this, x, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); branch(*this, start_ix, INT_VAR_SIZE_MIN(), INT_VAL_MIN()); }
/// Actual model Calculs(const SizeOptions& opt) : X(*this, N, -N, N), X_abs(*this, N, 0, N), x_max(*this, 0, N), show_all(opt.size()) { IntVar a(X[ 0]), b(X[ 1]), c(X[ 2]), e(X[ 4]), f(X[ 5]), g(X[ 6]), h(X[ 7]), i(X[ 8]), j(X[ 9]), k(X[10]), l(X[11]), m(X[12]), n(X[13]), o(X[14]), p(X[15]), q(X[16]), r(X[17]), s(X[18]), t(X[19]), u(X[20]), v(X[21]), w(X[22]), x(X[23]), y(X[24]), z(X[25]); // x_max is the max value of abs(X) for(int i = 0; i < N; i++) { abs(*this, X[i], X_abs[i], opt.icl()); } max(*this, X_abs, x_max, opt.icl()); rel(*this, z+e+r+o == 0, opt.icl()); rel(*this, o+n+e == 1, opt.icl()); rel(*this, t+w+o == 2, opt.icl()); rel(*this, t+h+r+e+e == 3, opt.icl()); rel(*this, f+o+u+r == 4, opt.icl()); rel(*this, f+i+v+e == 5, opt.icl()); rel(*this, s+i+x == 6, opt.icl()); rel(*this, s+e+v+e+n == 7, opt.icl()); rel(*this, e+i+g+h+t == 8, opt.icl()); rel(*this, n+i+n+e == 9, opt.icl()); rel(*this, t+e+n == 10, opt.icl()); rel(*this, e+l+e+v+e+n == 11, opt.icl()); rel(*this, t+w+e+l+f == 12, opt.icl()); distinct(*this, X, opt.icl()); // for showing all solutions (there are many) if (show_all) { rel(*this, x_max == 16, opt.icl()); } branch(*this, X, INT_VAR_DEGREE_MAX(), INT_VAL_MIN()); }