예제 #1
0
  /// The actual problem
  OpenShop(const SizeOptions& opt)
    : spec(examples[opt.size()]),
      b(*this, (spec.n+spec.m-2)*spec.n*spec.m/2, 0,1),
      makespan(*this, 0, Int::Limits::max),
      _start(*this, spec.m*spec.n, 0, Int::Limits::max) {

    Matrix<IntVarArray> start(_start, spec.m, spec.n);
    IntArgs _dur(spec.m*spec.n, spec.p);
    Matrix<IntArgs> dur(_dur, spec.m, spec.n);

    int minmakespan;
    int maxmakespan;
    crosh(dur, minmakespan, maxmakespan);
    rel(*this, makespan <= maxmakespan);
    rel(*this, makespan >= minmakespan);

    int k=0;
    for (int m=0; m<spec.m; m++)
      for (int j0=0; j0<spec.n-1; j0++)
        for (int j1=j0+1; j1<spec.n; j1++) {
          // The tasks on machine m of jobs j0 and j1 must be disjoint
          rel(*this,
              b[k] == (start(m,j0) + dur(m,j0) <= start(m,j1)));
          rel(*this,
              b[k++] == (start(m,j1) + dur(m,j1) > start(m,j0)));
        }
    
    for (int j=0; j<spec.n; j++)
      for (int m0=0; m0<spec.m-1; m0++)
        for (int m1=m0+1; m1<spec.m; m1++) {
          // The tasks in job j on machine m0 and m1 must be disjoint
          rel(*this,
              b[k] == (start(m0,j) + dur(m0,j) <= start(m1,j)));
          rel(*this,
              b[k++] == (start(m1,j) + dur(m1,j) > start(m0,j)));
        }

    // The makespan is greater than the end time of the latest job
    for (int m=0; m<spec.m; m++) {
      for (int j=0; j<spec.n; j++) {
        rel(*this, start(m,j) + dur(m,j) <= makespan);
      }
    }

    // First branch over the precedences
    branch(*this, b, INT_VAR_AFC_MAX(opt.decay()), INT_VAL_MAX());
    // When the precedences are fixed, simply assign the start times
    assign(*this, _start, INT_ASSIGN_MIN());
    // When the start times are fixed, use the tightest makespan
    assign(*this, makespan, INT_ASSIGN_MIN());
  }
예제 #2
0
  /// 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;
    }
  }
예제 #3
0
  /// 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());
  }
예제 #4
0
  /// The actual problem
  Kakuro(const SizeOptions& opt)
    : w(examples[opt.size()][0]),  h(examples[opt.size()][1]),
      f(*this,w*h) {
    IntVar black(*this,0,0);
    // Initialize all fields as black (unused). Only if a field
    // is actually used in a constraint, create a fresh variable
    // for it (done via init).
    for (int i=w*h; i--; )
      f[i] = black;

    // Cache of already computed tuple sets
    Cache cache;

    // Matrix for accessing board fields
    Matrix<IntVarArray> b(f,w,h);
    // Access to hints
    const int* k = &examples[opt.size()][2];

    // Process vertical hints
    while (*k >= 0) {
      int x=*k++; int y=*k++; int n=*k++; int s=*k++;
      IntVarArgs col(n);
      for (int i=n; i--; )
        col[i]=init(b(x,y+i+1));
      distinctlinear(cache,col,s,opt);
    }
    k++;

    // Process horizontal hints
    while (*k >= 0) {
      int x=*k++; int y=*k++; int n=*k++; int s=*k++;
      IntVarArgs row(n);
      for (int i=n; i--; )
        row[i]=init(b(x+i+1,y));
      distinctlinear(cache,row,s,opt);
    }
    branch(*this, f, INT_VAR_AFC_SIZE_MAX(opt.decay()), INT_VAL_SPLIT_MIN());
  }
예제 #5
0
  /// 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;
       }
    }
  }