Exemple #1
0
  void
  extensional(Home home, const BoolVarArgs& x, const TupleSet& t,
              IntPropLevel ipl) {
    using namespace Int;
    if (!t.finalized())
      throw NotYetFinalized("Int::extensional");
    if (t.arity() != x.size())
      throw ArgumentSizeMismatch("Int::extensional");
    GECODE_POST;

    if (t.tuples()==0) {
      if (x.size()!=0) {
        home.fail();
      }
      return;
    }

    // Construct view array
    ViewArray<BoolView> xv(home,x);
    if (ipl & IPL_MEMORY) {
      if (x.same(home)) {
        GECODE_ES_FAIL((Extensional::Basic<BoolView,true>
                             ::post(home,xv,t)));
      } else {
        GECODE_ES_FAIL((Extensional::Basic<BoolView,false>
                             ::post(home,xv,t)));
      }
    } else {
      GECODE_ES_FAIL((Extensional::Incremental<BoolView>
                           ::post(home,xv,t)));
    }
  }
void nonlinearity(Home home, const int n, const int m, const int threshold, const IntVarArgs& x) {
    if(DEBUG) { std::cerr << "P"; }
    // argument validation
    if(x.size() != pow(2,n)) {
        throw ArgumentSizeMismatch("setnonlinearity,x");
    } else if(threshold > pow(2,n)) {
        throw ArgumentSizeMismatch("setnonlinearity,threshold,high");
    } else if(!(n > 0)) {
        throw ArgumentSizeMismatch("setnonlinearity,n");
    } else if(!(m > 0)) {
        throw ArgumentSizeMismatch("setnonlinearity,m");
    } else if(!(threshold >= 0)) {
        throw ArgumentSizeMismatch("setnonlinearity,threshold,low");
    }
    // if space is already failed, don't post the propagator
    if(home.failed()) {
        return;
    }
    // create views
    ViewArray<IntView> vx(home,x);
    // size of the a,b array, for convenience 
    int size = numscores(n,m);
    // create storage for scoring
    int* scores = static_cast<Space&>(home).alloc<int>(size);
    // create storage for allocated list
    bool* assigned = static_cast<Space&>(home).alloc<bool>((int)pow(2,n));
    // not strictly sure this is ncessary, but...
    for(int i=0; i<pow(2,n); i++) {
        assigned[i] = false;
    }
    // if posting failed, fail the space
    if(NonLinearity::post(home,vx,scores,assigned,n,m,threshold,size) != ES_OK) {
        home.fail();
    }
}
Exemple #3
0
  void
  rel(Home home, const IntVarArgs& x, IntRelType irt, const IntVarArgs& y,
      IntConLevel icl) {
    if (home.failed()) return;

    switch (irt) {
    case IRT_GR:
      {
        ViewArray<IntView> xv(home,x), yv(home,y);
        GECODE_ES_FAIL(Rel::LexLqLe<IntView>::post(home,yv,xv,true));
      }
      break;
    case IRT_LE:
      {
        ViewArray<IntView> xv(home,x), yv(home,y);
        GECODE_ES_FAIL(Rel::LexLqLe<IntView>::post(home,xv,yv,true));
      }
      break;
    case IRT_GQ:
      {
        ViewArray<IntView> xv(home,x), yv(home,y);
        GECODE_ES_FAIL(Rel::LexLqLe<IntView>::post(home,yv,xv,false));
      }
      break;
    case IRT_LQ:
      {
        ViewArray<IntView> xv(home,x), yv(home,y);
        GECODE_ES_FAIL(Rel::LexLqLe<IntView>::post(home,xv,yv,false));
      }
      break;
    case IRT_EQ:
      if (x.size() != y.size()) {
        home.fail();
      } else if ((icl == ICL_DOM) || (icl == ICL_DEF))
        for (int i=x.size(); i--; ) {
          GECODE_ES_FAIL((Rel::EqDom<IntView,IntView>
                          ::post(home,x[i],y[i])));
        }
      else
        for (int i=x.size(); i--; ) {
          GECODE_ES_FAIL((Rel::EqBnd<IntView,IntView>
                          ::post(home,x[i],y[i])));
        }
      break;
    case IRT_NQ:
      {
        ViewArray<IntView> xv(home,x), yv(home,y);
        GECODE_ES_FAIL(Rel::LexNq<IntView>::post(home,xv,yv));
      }
      break;
    default:
      throw UnknownRelation("Int::rel");
    }
  }
Exemple #4
0
/*
 * Post the constraint that the rectangles defined by the coordinates
 * x and y and width w and height h do not overlap.
 *
 * This is the function that you will call from your model. The best
 * is to paste the entire file into your model.
 */
void nooverlap(Home home, 
               const IntVarArgs& x, const IntArgs& w,
               const IntVarArgs& y, const IntArgs& h) {
  // Check whether the arguments make sense
  if ((x.size() != y.size()) || (x.size() != w.size()) ||
      (y.size() != h.size()))
    throw ArgumentSizeMismatch("nooverlap");
  // Never post a propagator in a failed space
  if (home.failed()) return;
  // Set up array of views for the coordinates
  ViewArray<IntView> vx(home,x);
  ViewArray<IntView> vy(home,y);
  // Set up arrays (allocated in home) for width and height and initialize
  int* wc = static_cast<Space&>(home).alloc<int>(x.size());
  int* hc = static_cast<Space&>(home).alloc<int>(y.size());
  for (int i=x.size(); i--; ) {
    wc[i]=w[i]; hc[i]=h[i];
  }
  // If posting failed, fail space
  if (NoOverlap::post(home,vx,wc,vy,hc) != ES_OK)
    home.fail();
}
  IntSet
  binpacking(Home home, int d,
             const IntVarArgs& l, const IntVarArgs& b, 
             const IntArgs& s, const IntArgs& c,
             IntConLevel) {
    using namespace Int;

    if (l.same(home,b))
      throw ArgumentSame("Int::binpacking");

    // The number of items
    int n = b.size();
    // The number of bins
    int m = l.size() / d;

    // Check input sizes
    if ((n*d != s.size()) || (m*d != l.size()) || (d != c.size()))
      throw ArgumentSizeMismatch("Int::binpacking");      
    for (int i=s.size(); i--; )
      Limits::nonnegative(s[i],"Int::binpacking");
    for (int i=c.size(); i--; )
      Limits::nonnegative(c[i],"Int::binpacking");

    if (home.failed()) 
      return IntSet::empty;

    // Capacity constraint for each dimension
    for (int k=d; k--; )
      for (int j=m; j--; ) {
        IntView li(l[j*d+k]);
        if (me_failed(li.lq(home,c[k]))) {
          home.fail();
          return IntSet::empty;
        }
      }

    // Post a binpacking constraint for each dimension
    for (int k=d; k--; ) {
      ViewArray<OffsetView> lv(home,m);
      for (int j=m; j--; )
        lv[j] = OffsetView(l[j*d+k],0);
      
      ViewArray<BinPacking::Item> bv(home,n);
      for (int i=n; i--; )
        bv[i] = BinPacking::Item(b[i],s[i*d+k]);
      
      if (Int::BinPacking::Pack::post(home,lv,bv) == ES_FAILED) {
        home.fail();
        return IntSet::empty;
      }
    }


    // Clique Finding and distinct posting
    {
      // First construct the conflict graph
      Region r(home);
      BinPacking::ConflictGraph cg(home,r,b,m);

      for (int i=0; i<n-1; i++) {
        for (int j=i+1; j<n; j++) {
          unsigned int nl = 0;
          unsigned int ds = 0;
          IntVarValues ii(b[i]), jj(b[j]);
          while (ii() && jj()) {
            if (ii.val() < jj.val()) {
              ++ii;
            } else if (ii.val() > jj.val()) {
              ++jj;
            } else {
              ds++;
              for (int k=d; k--; )
                if (s[i*d+k] + s[j*d+k] > c[k]) {
                  nl++;
                  break;
                }
              ++ii; ++jj;
            }
          }
          if (nl >= ds)
            cg.edge(i,j);
        }
      }

      if (cg.post() == ES_FAILED)
        home.fail();

      // The clique can be computed even if home is failed
      return cg.maxclique();
    }
  }
Exemple #6
0
  void
  dopost(Home home, Term* t, int n, FloatRelType frt, FloatVal c) {
    Limits::check(c,"Float::linear");

    for (int i=n; i--; )
      if (t[i].x.assigned()) {
        c -= t[i].a * t[i].x.val();
        t[i]=t[--n];
      }

    if ((c < Limits::min) || (c > Limits::max))
      throw OutOfLimits("Float::linear");

    /*
     * Join coefficients for aliased variables:
     *
     */
    {
      // Group same variables
      TermLess tl;
      Support::quicksort<Term,TermLess>(t,n,tl);

      // Join adjacent variables
      int i = 0;
      int j = 0;
      while (i < n) {
        Limits::check(t[i].a,"Float::linear");
        FloatVal a = t[i].a;
        FloatView x = t[i].x;
        while ((++i < n) && same(t[i].x,x)) {
          a += t[i].a;
          Limits::check(a,"Float::linear");
        }
        if (a != 0.0) {
          t[j].a = a; t[j].x = x; j++;
        }
      }
      n = j;
    }

    Term *t_p, *t_n;
    int n_p, n_n;

    /*
     * Partition into positive/negative coefficents
     *
     */
    if (n > 0) {
      int i = 0;
      int j = n-1;
      while (true) {
        while ((t[j].a < 0) && (--j >= 0)) ;
        while ((t[i].a > 0) && (++i <  n)) ;
        if (j <= i) break;
        std::swap(t[i],t[j]);
      }
      t_p = t;     n_p = i;
      t_n = t+n_p; n_n = n-n_p;
    } else {
      t_p = t; n_p = 0;
      t_n = t; n_n = 0;
    }

    /*
     * Make all coefficients positive
     *
     */
    for (int i=n_n; i--; )
      t_n[i].a = -t_n[i].a;

    if (frt == FRT_GQ) {
      frt = FRT_LQ;
      std::swap(n_p,n_n); std::swap(t_p,t_n); c = -c;
    }

    if (n == 0) {
      switch (frt) {
      case FRT_EQ: if (!c.in(0.0)) home.fail(); break;
      case FRT_LQ: if (c.max() < 0.0) home.fail(); break;
      default: GECODE_NEVER;
      }
      return;
    }

    /*
     * Test for unit coefficients only
     *
     */
    bool is_unit = true;
    for (int i=n; i--; )
      if (t[i].a != 1.0) {
        is_unit = false;
        break;
      }

    if (is_unit) {
      // Unit coefficients
      ViewArray<FloatView> x(home,n_p);
      for (int i = n_p; i--; )
        x[i] = t_p[i].x;
      ViewArray<FloatView> y(home,n_n);
      for (int i = n_n; i--; )
        y[i] = t_n[i].x;
      post_nary<FloatView>(home,x,y,frt,c);
    } else {
      // Arbitrary coefficients
      ViewArray<ScaleView> x(home,n_p);
      for (int i = n_p; i--; )
        x[i] = ScaleView(t_p[i].a,t_p[i].x);
      ViewArray<ScaleView> y(home,n_n);
      for (int i = n_n; i--; )
        y[i] = ScaleView(t_n[i].a,t_n[i].x);
      post_nary<ScaleView>(home,x,y,frt,c);
    }
  }
  void
  sequence(Home home, const IntVarArgs& x, const IntSet &s, 
           int q, int l, int u, IntConLevel) {
    Limits::check(s.min(),"Int::sequence");
    Limits::check(s.max(),"Int::sequence");

    if (x.size() == 0)
      throw TooFewArguments("Int::sequence");

    Limits::check(q,"Int::sequence");
    Limits::check(l,"Int::sequence");
    Limits::check(u,"Int::sequence");

    if (x.same(home))
      throw ArgumentSame("Int::sequence");

    if ((q < 1) || (q > x.size()))
      throw OutOfLimits("Int::sequence");

    if (home.failed())
      return;

    // Normalize l and u
    l=std::max(0,l); u=std::min(q,u);

    // Lower bound of values taken can never exceed upper bound
    if (u < l) {
      home.fail(); return;
    }

    // Already subsumed as any number of values taken is okay
    if ((0 == l) && (q == u)) 
      return;

    // All variables must take a value in s
    if (l == q) {
      for (int i=x.size(); i--; ) {
        IntView xv(x[i]);
        IntSetRanges ris(s);
        GECODE_ME_FAIL(xv.inter_r(home,ris,false));
      }
      return;
    }

    // No variable can take a value in s
    if (0 == u) {
      for (int i=x.size(); i--; ) {
        IntView xv(x[i]);
        IntSetRanges ris(s);
        GECODE_ME_FAIL(xv.minus_r(home,ris,false));
      }
      return;
    }

    ViewArray<IntView> xv(home,x);
    if (s.size() == 1) {
      GECODE_ES_FAIL(
                     (Sequence::Sequence<IntView,int>::post
                      (home,xv,s.min(),q,l,u)));
    } else {
      GECODE_ES_FAIL(
                     (Sequence::Sequence<IntView,IntSet>::post
                      (home,xv,s,q,l,u)));
    }
  }
  void
  sequence(Home home, const BoolVarArgs& x, const IntSet& s, 
           int q, int l, int u, IntConLevel) {
    if ((s.min() < 0) || (s.max() > 1))
      throw NotZeroOne("Int::sequence");

    if (x.size() == 0)
      throw TooFewArguments("Int::sequence");

    Limits::check(q,"Int::sequence");
    Limits::check(l,"Int::sequence");
    Limits::check(u,"Int::sequence");

    if (x.same(home))
      throw ArgumentSame("Int::sequence");

    if ((q < 1) || (q > x.size()))
      throw OutOfLimits("Int::sequence");

    if (home.failed())
      return;

    // Normalize l and u
    l=std::max(0,l); u=std::min(q,u);

    // Lower bound of values taken can never exceed upper bound
    if (u < l) {
      home.fail(); return;
    }

    // Already subsumed as any number of values taken is okay
    if ((0 == l) && (q == u)) 
      return;

    // Check whether the set is {0,1}, then the number of values taken is q
    if ((s.min() == 0) && (s.max() == 1)) {
      if ((l > 0) || (u < q))
        home.failed();
      return;
    }
    assert(s.min() == s.max());

    // All variables must take a value in s
    if (l == q) {
      if (s.min() == 0) {
        for (int i=x.size(); i--; ) {
          BoolView xv(x[i]); GECODE_ME_FAIL(xv.zero(home));
        }
      } else {
        assert(s.min() == 1);
        for (int i=x.size(); i--; ) {
          BoolView xv(x[i]); GECODE_ME_FAIL(xv.one(home));
        }
      }
      return;
    }

    // No variable can take a value in s
    if (0 == u) {
      if (s.min() == 0) {
        for (int i=x.size(); i--; ) {
          BoolView xv(x[i]); GECODE_ME_FAIL(xv.one(home));
        }
      } else {
        assert(s.min() == 1);
        for (int i=x.size(); i--; ) {
          BoolView xv(x[i]); GECODE_ME_FAIL(xv.zero(home));
        }
      }
      return;
    }

    ViewArray<BoolView> xv(home,x);

    GECODE_ES_FAIL(
                   (Sequence::Sequence<BoolView,int>::post
                    (home,xv,s.min(),q,l,u)));
  }