/// 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());
  }
예제 #2
0
  SetCovering(const SizeOptions& opt) 
  : 
    x(*this, num_alternatives, 0, 1),
    z(*this, 0, 999999)
  {

    // costs per alternative
    int _costs[] = {19, 16, 18, 13, 15, 19, 15, 17, 16, 15};
    IntArgs costs(num_alternatives, _costs);

    // the alternatives and the objects they contain
    int _a[] = {
   // 1 2 3 4 5 6 7 8  the objects 
      1,0,0,0,0,1,0,0,  // alternative 1
      0,1,0,0,0,1,0,1,  // alternative 2
      1,0,0,1,0,0,1,0,  // alternative 3
      0,1,1,0,1,0,0,0,  // alternative 4
      0,1,0,0,1,0,0,0,  // alternative 5
      0,1,1,0,0,0,0,0,  // alternative 6
      0,1,1,1,0,0,0,0,  // alternative 7
      0,0,0,1,1,0,0,1,  // alternative 8
      0,0,1,0,0,1,0,1,  // alternative 9
      1,0,0,0,0,1,1,0,  // alternative 10
    };
    IntArgs a(num_alternatives*num_objects, _a);


    for(int j = 0; j < num_objects; j++) {
      IntVarArgs tmp; 
      for(int i = 0; i < num_alternatives; i++) {
        tmp << expr(*this, x[i]*a[i*num_objects+j]);
      }
      if (opt.size() == 0) {
        // set partition problem:
        // objects must be covered _exactly_ once
        rel(*this, sum(tmp) == 1);
      } else {
        // set covering problem
        // all objects must be covered _at least_ once
        rel(*this, sum(tmp) >= 1);
      }      
    }

    if (opt.search() == SEARCH_DFS) {
      if (opt.size() == 0) {
        rel(*this, z <= 49);
      } else {
        rel(*this, z <= 45);
      }
    }
    
    linear(*this, costs, x, IRT_EQ, z);

    branch(*this, x, INT_VAR_NONE(), INT_VAL_MIN()); 

  }
예제 #3
0
파일: queen-armies.cpp 프로젝트: lquan/CSAI
  /// 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);
    }
  }
예제 #4
0
  /// 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());
  }
예제 #5
0
  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()); 

  }
예제 #6
0
파일: photo.cpp 프로젝트: Wushaowei001/vcp
  /// 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());
    }
  }
예제 #7
0
  /// 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());
  }
예제 #8
0
  /// 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());
  }
예제 #9
0
파일: queens.cpp 프로젝트: SteveLTN/CPAss
 /// 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;
   }
 }
예제 #10
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());
  }
예제 #11
0
파일: open-shop.cpp 프로젝트: emosei/chef
    /// 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, 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);
    }
예제 #12
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());
  }
  /// 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);
  }
예제 #14
0
  /// 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());

  }
예제 #15
0
    /// Actual model
    MineSweeper(const SizeOptions& opt)
        : spec(specs[opt.size()]),
          size(spec_size(spec)),
          b(*this,size*size,0,1) {
        Matrix<BoolVarArray> m(b, size, size);

        // Initialize matrix and post constraints
        for (int h=0; h<size; h++)
            for (int w=0; w<size; w++) {
                int v = mineField(spec, size, h, w);
                if (v != -1) {
                    rel(*this, m(w, h), IRT_EQ, 0);
                    linear(*this, fieldsAround(m, w, h), IRT_EQ, v);
                }
            }

        // Install branching
        branch(*this, b, INT_VAR_NONE(), INT_VAL_MAX());
    }
예제 #16
0
  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());

  }
예제 #17
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;
    }
  }
예제 #18
0
  /// 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;
    }
  }
예제 #19
0
  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()); 

  }
예제 #20
0
  /// 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);
  }
예제 #21
0
  /// The actual problem
  DominatingQueens(const SizeOptions& opt)
    : IntMinimizeScript(opt),
      n(opt.size()), b(*this,n*n,0,n*n-1), q(*this,1,n) {

    // Constrain field to the fields that can attack a field
    for (int i=0; i<n*n; i++)
      dom(*this, b[i], attacked(i));

    // At most q queens can be placed
    nvalues(*this, b, IRT_LQ, q);

    /*
     * According to: P. R. J. Östergard and W. D. Weakley, Values
     * of Domination Numbers of the Queen's Graph, Electronic Journal
     * of Combinatorics, 8:1-19, 2001, for n <= 120, the minimal number
     * of queens is either ceil(n/2) or ceil(n/2 + 1).
     */
    if (n <= 120)
      dom(*this, q, (n+1)/2, (n+1)/2 + 1);

    branch(*this, b, INT_VAR_SIZE_MIN(), INT_VAL_MIN());
    // Try the easier solution first
    branch(*this, q, INT_VAL_MAX());
  }
예제 #22
0
  /// Actual model
  Steiner(const SizeOptions& opt)
    : n(opt.size()), noOfTriples((n*(n-1))/6),
      triples(*this, noOfTriples, IntSet::empty, 1, n, 3, 3) {

    for (int i=0; i<noOfTriples; i++) {
      for (int j=i+1; j<noOfTriples; j++) {
        SetVar x = triples[i];
        SetVar y = triples[j];

        SetVar atmostOne(*this,IntSet::empty,1,n,0,1);
        rel(*this, (x & y) == atmostOne);

        IntVar x1(*this,1,n);
        IntVar x2(*this,1,n);
        IntVar x3(*this,1,n);
        IntVar y1(*this,1,n);
        IntVar y2(*this,1,n);
        IntVar y3(*this,1,n);

        if (opt.model() == MODEL_NONE) {
          /* Naive alternative:
           * just including the ints in the set
           */
          rel(*this, singleton(x1) <= x);
          rel(*this, singleton(x2) <= x);
          rel(*this, singleton(x3) <= x);
          rel(*this, singleton(y1) <= y);
          rel(*this, singleton(y2) <= y);
          rel(*this, singleton(y3) <= y);

        } else if (opt.model() == MODEL_MATCHING) {
          /* Smart alternative:
           * Using matching constraints
           */

          channelSorted(*this, IntVarArgs()<<x1<<x2<<x3, x);
          channelSorted(*this, IntVarArgs()<<y1<<y2<<y3, y);
        } else if (opt.model() == MODEL_SEQ) {
          SetVar sx1 = expr(*this, singleton(x1));
          SetVar sx2 = expr(*this, singleton(x2));
          SetVar sx3 = expr(*this, singleton(x3));
          SetVar sy1 = expr(*this, singleton(y1));
          SetVar sy2 = expr(*this, singleton(y2));
          SetVar sy3 = expr(*this, singleton(y3));
          sequence(*this,SetVarArgs()<<sx1<<sx2<<sx3,x);
          sequence(*this,SetVarArgs()<<sy1<<sy2<<sy3,y);
        }

        /* Breaking symmetries */
        rel(*this, x1 < x2);
        rel(*this, x2 < x3);
        rel(*this, x1 < x3);

        rel(*this, y1 < y2);
        rel(*this, y2 < y3);
        rel(*this, y1 < y3);

        linear(*this, IntArgs(6,(n+1)*(n+1),n+1,1,-(n+1)*(n+1),-(n+1),-1), 
               IntVarArgs()<<x1<<x2<<x3<<y1<<y2<<y3, IRT_LE, 0);
      }
    }

    branch(*this, triples, SET_VAR_NONE, SET_VAL_MIN_INC);
  }
예제 #23
0
	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;
    }
	}
예제 #24
0
        Queens(const SizeOptions& opt) : q(*this, opt.size() * opt.size(), 0, 1) {
            Matrix<IntVarArray> matrix(q, opt.size(), opt.size());

            // Distinct col
            for (int i = 0; i < opt.size(); ++i) {
                count(*this, matrix.col(i), 1, IRT_EQ, 1);
                count(*this, matrix.row(i), 1, IRT_EQ, 1);
            }

            // Diagonal
            for (int j = 0; j < opt.size(); ++j) {
                IntVarArray dia(*this, opt.size()-j);
                for (int i = 0; i+j < opt.size(); ++i) {
                    dia[i] = matrix(i+j, i);
                }
                count(*this, dia, 1, IRT_LQ, 1);
            }

            for (int j = 0; j < opt.size(); ++j) {
                IntVarArray dia(*this, opt.size()-j);
                for (int i = 0; i+j < opt.size(); ++i) {
                    dia[i] = matrix(i, i+j);
                }
                count(*this, dia, 1, IRT_LQ, 1);
            }

            for (int j = 0; j < opt.size(); ++j) {
                IntVarArray dia(*this, opt.size()-j);
                for (int i = 0; i+j < opt.size(); ++i) {
                    dia[i] = matrix((opt.size() - 1) - (i + j), i);
                }
                count(*this, dia, 1, IRT_LQ, 1);
            }

            for (int j = 0; j < opt.size(); ++j) {
                IntVarArray dia(*this, opt.size()-j);
                for (int i = 0; i+j < opt.size(); ++i) {
                    dia[i] = matrix((opt.size() - 1) - (i + 0), i + j);
                }
                count(*this, dia, 1, IRT_LQ, 1);
            }

            branch(*this, q, INT_VAR_RND, INT_VAL_MAX);
        }
예제 #25
0
  /// 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);
  }
예제 #26
0
  /// 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));		
	}
예제 #27
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;
       }
    }
  }
예제 #28
0
        SquarePacking(const SizeOptions& opt) 
                : x(*this, opt.size()), y(*this, opt.size()) {
            // Step 1b: Initialize variables s, x, y
            int min = 0;
            int max = 0;
            for (int i = 0; i < opt.size(); ++i) {
                min += i*i;
                max += i;
            }
            s = IntVar(*this, sqrt(min), max);

            for (int i = 0; i < opt.size(); ++i) {
                x[i] = IntVar(*this, 0, max);
                y[i] = IntVar(*this, 0, max);
            }

            for (int i = 0; i < N; ++i) {
                rel(*this, (x[i] + size(i)) <= s);
                rel(*this, (y[i] + size(i)) <= s);
            }

            // Step 2: No overlapping between squares, expressed with
            // reification.
            for (int i = 0; i < N-1; i++) {
               for (int j = i+1; j < N-1; j++) {
                   rel(*this, 
                        (x[i] + size(i) <= x[j]) || 
                        (x[j] + size(j) <= x[i]) ||
                        (y[i] + size(i) <= y[j]) || 
                        (y[j] + size(j) <= y[i]));  
                }
            }

            // Step 3: Sum of square sizes for every row and column less than
            // s, expressed with reification.
            IntArgs sizes(N-1);
            for (int i = 0; i < N-1; ++i) {
                sizes[i] = size(i);
            }

            for (int col = 0; col < s.max(); ++col) {
                BoolVarArgs bx(*this, N-1, 0, 1);
                for (int i = 0; i < N-1; ++i) {
                    dom(*this, y[i], col - size(i) + 1, col, bx[i]);
                }
                linear(*this, sizes, bx, IRT_LQ, s);
            }

            for (int col = 0; col < s.max(); ++col) {
                BoolVarArgs bx(*this, N-1, 0, 1);
                for (int i = 0; i < N-1; ++i) {
                    dom(*this, x[i], col - size(i) + 1, col, bx[i]);
                }
                linear(*this, sizes, bx, IRT_LQ, s);
             }

            // Step 4.1: Problem decomposition 
            rel(*this, (s*s) > ((N * (N+1) * (2 * N+1))/6));

            // Step 4.2: Symmetry removal
            rel(*this, x[0] <= ((s - N)/2));
            rel(*this, y[0] <= ((s - N)/2));

            // Step 4.3: Empty strip dominance
            for (int i = 0; i < N; ++i) {
                int siz = size(i);
                int gt = 0;
                if (siz == 2 || siz == 4)
                    gt = 2;
                else if (siz == 3 || (siz >= 5 && siz <= 8))
                    gt = 3;
                else if (siz <= 11)
                    gt = 4;
                else if (siz <= 17)
                    gt = 5;
                else if (siz <= 21)
                    gt = 6;
                else if (siz <= 29)
                    gt = 7;
                else if (siz <= 34)
                    gt = 8;
                else if (siz <= 44)
                    gt = 9;
                else if (siz <= 45)
                    gt = 10;

                if (gt != 0) {
                    rel(*this, x[i] != gt);
                    rel(*this, y[i] != gt);
                }
            }

            // Step 4.4: Ignoring size 1 squares, this is done by only looping
            // until N-1 instead of N

            // Step 5: Branching heuristics
            branch(*this, s, INT_VAL_MIN); // (5a) Branch on s first

            // Interval branch
            IntArgs nsizes(N);
            for (int i = 0; i < N; ++i) {
                nsizes[i] = size(i);
            }
            interval(*this, x, nsizes, 0.6);
            interval(*this, y, nsizes, 0.6);

            // (5c) INT_VAR_NONE means going through the array in order, that
            // is from the biggest to the smallest square
            // (5d) INT_VAL_MIN chooses the minimum value, that is placing it
            // from left to right and top to botom.
            // (5b) First assign x-coordinates.     
            branch(*this, x, INT_VAR_NONE, INT_VAL_MIN);
            // (5b) then y-coordinates. 
            branch(*this, y, INT_VAR_NONE, INT_VAL_MIN);
        }
예제 #29
0
  /// 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());
  }
예제 #30
0
  /// 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);
  }