Пример #1
0
  void
  nooverlap(Home home, 
            const IntVarArgs& x0, const IntVarArgs& w, const IntVarArgs& x1,
            const IntVarArgs& y0, const IntVarArgs& h, const IntVarArgs& y1,
            IntConLevel) {
    using namespace Int;
    using namespace NoOverlap;
    if ((x0.size() != w.size())  || (x0.size() != x1.size()) || 
        (x0.size() != y0.size()) || (x0.size() != h.size()) || 
        (x0.size() != y1.size()))
      throw ArgumentSizeMismatch("Int::nooverlap");
    if (x0.same(home) || w.same(home) || x1.same(home) ||
        y0.same(home) || h.same(home) || y1.same(home))
      throw ArgumentSame("Int::nooverlap");
    if (home.failed()) return;

    for (int i=x0.size(); i--; ) {
      GECODE_ME_FAIL(IntView(w[i]).gq(home,0));
      GECODE_ME_FAIL(IntView(h[i]).gq(home,0));
    }

    if (w.assigned() && h.assigned()) {
      IntArgs wc(x0.size()), hc(x0.size());
      for (int i=x0.size(); i--; ) {
        wc[i] = w[i].val();
        hc[i] = h[i].val();
      }
      nooverlap(home, x0, wc, y0, hc);
    } else {
      ManBox<FlexDim,2>* b 
        = static_cast<Space&>(home).alloc<ManBox<FlexDim,2> >(x0.size());
      for (int i=x0.size(); i--; ) {
        b[i][0] = FlexDim(x0[i],w[i],x1[i]);
        b[i][1] = FlexDim(y0[i],h[i],y1[i]);
      }
      GECODE_ES_FAIL((NoOverlap::ManProp<FlexDim,2>::post(home,b,x0.size())));
    }
  }
Пример #2
0
  void
  multibinpacking(Home home, 
         int n, int m, int k,
         const IntVarArgs& y, 
         const IntVarArgs& x, 
         const IntSharedArray& D,
         const IntSharedArray& B,
         IntConLevel) 
   {
      /// Check input sizes
      if (n*k != D.size() )
         throw ArgumentSizeMismatch("Int::multibinpacking");      

      if (k != B.size() )
         throw ArgumentSizeMismatch("Int::multibinpacking");      
    
      if (n != x.size() )
         throw ArgumentSizeMismatch("Int::multibinpacking");      
      
      if (m*k != y.size() )
         throw ArgumentSizeMismatch("Int::multibinpacking");      
      
      for (int i=B.size(); i--; )
         Limits::nonnegative(B[i],"Int::multibinpacking");

      if (home.failed()) return;

      /// Post first each single binpacking constraint
      /// Capacity constraint for each dimension
      for ( int j = 0; j < m; ++j )
         for ( int l = 0; l < k; ++l ) {
            IntView yi(y[j*k+l]);
            GECODE_ME_FAIL(yi.lq(home,B[l]));
         }

      /// Post a binpacking constraints for each dimension
      for ( int l = 0; l < k; ++l ) {
         ViewArray<OffsetView> yv(home,m);
         for (int j=m; j--; )
            yv[j] = OffsetView(y[j*k+l],0);

         ViewArray<BinPacking::Item> xs(home,x.size());
         for (int i=xs.size(); i--; )
            xs[i] = BinPacking::Item(x[i],D[i*k+l]);

         Support::quicksort(&xs[0], xs.size());

         GECODE_ES_FAIL(Int::BinPacking::Pack::post(home,yv,xs));
      }

      /// Clique Finding and Alldifferent posting
      {
         /// Firt construct the conflict graph
         graph_t* g = graph_new(n);
         for ( int a = 0; a < n-1; ++a ) {
            for ( int b = a+1; b < n; ++b ) {
               int v = a;  /// The variable with smaller domain
               int w = b;
               unsigned int nl = 0;
               if ( x[a].size() > x[b].size() ) {
                  v = b;
                  w = a;
               }
               IntVarValues i(x[v]);
               IntVarValues j(x[w]);
               while ( i() ) {
                  if ( i.val() != j.val() ) {
                     if ( i.val() < j.val() )
                        break;
                     else
                        ++i;
                  } else {
                     for ( int l = 0; l < k; ++l )
                        if ( D[a*k+l] + D[b*k+l] > B[l] ) {
                           nl++;
                           break;
                        }
                     ++i; ++j;
                  }
               }
               if ( nl >= x[v].size() )
                  GRAPH_ADD_EDGE(g,a,b);
            }
         }
         /// Consitency cheking: look for the maximum clique
         clique_options* opts;
         opts = (clique_options*) malloc (sizeof(clique_options));
         opts->time_function=NULL;
         opts->reorder_function=reorder_by_default;
         opts->reorder_map=NULL;
         opts->user_function=NULL;
         opts->user_data=NULL;
         opts->clique_list=NULL;
         opts->clique_list_length=0;
         set_t s;
         s = clique_find_single ( g, 0, 0, TRUE, opts);
         if ( s != NULL ) {
            if ( set_size(s) > m ) {
                set_free(s);
                free(opts);
                graph_free(g);
                GECODE_ES_FAIL(ES_FAILED);
            }
            if ( true ) { //option == 1 ) {  FIXING
               for ( int a = 0, j = 0; a < n; ++a ) {
                  if ( SET_CONTAINS_FAST(s,a) ) {
                     assert( x[a].in(j) );
                     IntView xi(x[a]);
                     GECODE_ME_FAIL(xi.eq(home,j++));
                  }
               }
            }
         }
         if ( s!=NULL )
            set_free(s);
         /// List every maximal clique in the conflict graph
         opts->user_function=record_clique_func;
         clique_find_all ( g, 2, 0, TRUE, opts);
         for ( int c = 0; c < clique_count; c++ ) {
            ViewArray<IntView> xv(home, set_size(clique_list[c]));
            for ( int a = 0, idx = 0; a < n; ++a )
               if ( SET_CONTAINS_FAST(clique_list[c],a) )
                  xv[idx++] = x[a];
            GECODE_ES_FAIL(Distinct::Dom<IntView>::post(home,xv));
            set_free(clique_list[c]);
         }
         free(opts);
         graph_free(g);
      }
   }
Пример #3
0
  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();
    }
  }
Пример #4
0
  void
  cumulative(Home home, Cap c, const TaskTypeArgs& t,
             const IntVarArgs& s, const IntArgs& p, const IntArgs& u, 
             IntConLevel icl) {
    using namespace Gecode::Int;
    using namespace Gecode::Int::Cumulative;
    if ((s.size() != p.size()) || (s.size() != u.size()) ||
        (s.size() != t.size()))
      throw Int::ArgumentSizeMismatch("Int::cumulative");
    long long int w = 0;
    for (int i=p.size(); i--; ) {
      Limits::nonnegative(p[i],"Int::cumulative");
      Limits::nonnegative(u[i],"Int::cumulative");
      Limits::check(static_cast<long long int>(s[i].max()) + p[i], 
                    "Int::cumulative");
      mul_check(p[i],u[i]);
      w += s[i].width();
    }
    mul_check(c.max(),w,s.size());
    if (home.failed()) return;

    int minU = INT_MAX; int minU2 = INT_MAX; int maxU = INT_MIN;
    for (int i=u.size(); i--;) {
      if (u[i] < minU) {
        minU2 = minU;
        minU = u[i];
      } else if (u[i] < minU2)
        minU2 = u[i];
      if (u[i] > maxU)
        maxU = u[i];
    }
    bool disjunctive =
      (minU > c.max()/2) || (minU2 > c.max()/2 && minU+minU2>c.max());
    if (disjunctive) {
      GECODE_ME_FAIL(c.gq(home,maxU));
      unary(home,t,s,p,icl);
    } else {
      bool fixp = true;
      for (int i=t.size(); i--;)
        if (t[i] != TT_FIXP) {
          fixp = false; break;
        }
      int nonOptionals = 0;
      for (unsigned int i=u.size(); i--;)
        if (u[i]>0) nonOptionals++;
      if (fixp) {
        TaskArray<ManFixPTask> tasks(home,nonOptionals);
        int cur = 0;
        for (int i=0; i<s.size(); i++)
          if (u[i] > 0)
            tasks[cur++].init(s[i],p[i],u[i]);
        GECODE_ES_FAIL((ManProp<ManFixPTask,Cap>::post(home,c,tasks)));
      } else {
        TaskArray<ManFixPSETask> tasks(home,nonOptionals);
        int cur = 0;
        for (int i=s.size(); i--;)
          if (u[i] > 0)
            tasks[cur++].init(t[i],s[i],p[i],u[i]);
        GECODE_ES_FAIL((ManProp<ManFixPSETask,Cap>::post(home,c,tasks)));
      }
    }
  }
Пример #5
0
  void
  channel(Home home, const IntVarArgs& x, int xoff,
          const IntVarArgs& y, int yoff,
          IntConLevel icl) {
    using namespace Int;
    using namespace Channel;
    int n = x.size();
    if (n != y.size())
      throw ArgumentSizeMismatch("Int::channel");
    if (x.same(home) || y.same(home))
      throw ArgumentSame("Int::channel");
    Limits::check(xoff,"Int::channel");
    Limits::check(yoff,"Int::channel");
    if ((xoff < 0) || (yoff < 0))
      throw OutOfLimits("Int::channel");
    if (home.failed()) return;
    if (n == 0)
      return;

    if ((xoff < 2) && (yoff < 2) && (xoff == yoff)) {
      if (icl == ICL_DOM) {
        DomInfo<IntView,NoOffset<IntView> >* di = 
          static_cast<Space&>(home).
            alloc<DomInfo<IntView,NoOffset<IntView> > >(2*(n+xoff));
        for (int i=n; i--; ) {
          di[xoff+i    ].init(x[i],n+xoff);
          di[2*xoff+i+n].init(y[i],n+xoff);
        }
        if (xoff == 1) {
          IntVar x0(home,0,0);
          di[0].init(x0, n+xoff);
          IntVar y0(home,0,0);
          di[n+xoff].init(y0, n+xoff);
        }
        NoOffset<IntView> noff;
        if (x.same(home,y)) {
          GECODE_ES_FAIL((Dom<IntView,NoOffset<IntView>,true>
            ::post(home,n+xoff,di,noff,noff)));
        } else {
          GECODE_ES_FAIL((Dom<IntView,NoOffset<IntView>,false>
            ::post(home,n+xoff,di,noff,noff)));
        }
      } else {
        ValInfo<IntView>* vi = 
          static_cast<Space&>(home).alloc<ValInfo<IntView> >(2*(n+xoff));
        for (int i=n; i--; ) {
          vi[xoff+i    ].init(x[i],n+xoff);
          vi[2*xoff+i+n].init(y[i],n+xoff);
        }
        if (xoff == 1) {
          IntVar x0(home,0,0);
          vi[0].init(x0, n+xoff);
          IntVar y0(home,0,0);
          vi[n+xoff].init(y0, n+xoff);
        }
        NoOffset<IntView> noff;
        if (x.same(home,y)) {
          GECODE_ES_FAIL((Val<IntView,NoOffset<IntView>,true>
            ::post(home,n+xoff,vi,noff,noff)));
        } else {
          GECODE_ES_FAIL((Val<IntView,NoOffset<IntView>,false>
            ::post(home,n+xoff,vi,noff,noff)));
        }
      }
    } else {
      if (icl == ICL_DOM) {
        DomInfo<IntView,Offset>* di = 
          static_cast<Space&>(home).alloc<DomInfo<IntView,Offset> >(2*n);
        for (int i=n; i--; ) {
          di[i  ].init(x[i],n);
          di[i+n].init(y[i],n);
        }
        Offset ox(-xoff);
        Offset oy(-yoff);
        if (x.same(home,y)) {
          GECODE_ES_FAIL((Dom<IntView,Offset,true>
                          ::post(home,n,di,ox,oy)));
        } else {
          GECODE_ES_FAIL((Dom<IntView,Offset,false>
                          ::post(home,n,di,ox,oy)));
        }
      } else {
        ValInfo<IntView>* vi = 
          static_cast<Space&>(home).alloc<ValInfo<IntView> >(2*n);
        for (int i=n; i--; ) {
          vi[i  ].init(x[i],n);
          vi[i+n].init(y[i],n);
        }
        Offset ox(-xoff);
        Offset oy(-yoff);
        if (x.same(home,y)) {
          GECODE_ES_FAIL((Val<IntView,Offset,true>
                          ::post(home,n,vi,ox,oy)));
        } else {
          GECODE_ES_FAIL((Val<IntView,Offset,false>
                          ::post(home,n,vi,ox,oy)));
        }
      }
    }

  }
Пример #6
0
  // constant cards
  void count(Home home, const IntVarArgs& x,
             const IntSetArgs& _c, const IntArgs& _v,
             IntConLevel icl) {
    using namespace Int;
    IntSetArgs c(_c);
    IntArgs v(_v);
    if (v.size() != c.size())
      throw ArgumentSizeMismatch("Int::count");
    if (x.same(home))
      throw ArgumentSame("Int::count");
    for (int i=c.size(); i--; ) {
      Limits::check(v[i],"Int::count");
      Limits::check(c[i].min(),"Int::count");
      Limits::check(c[i].max(),"Int::count");
    }

    if (home.failed())
      return;

    removeDuplicates(home,c,v);    

    ViewArray<IntView> xv(home, x);

    for (int i = v.size(); i--; ) {
      if (c[i].ranges() > 1) {
        // Found hole, so create temporary variables
        ViewArray<GCC::CardView> cv(home, v.size());
        for (int j = v.size(); j--; )
          cv[j].init(home,c[j],v[j]);
        switch (icl) {
        case ICL_BND:
          GECODE_ES_FAIL( 
                         (GCC::Bnd<GCC::CardView>::post(home, xv, cv)));
          break;
        case ICL_DOM:
          GECODE_ES_FAIL( 
                         (GCC::Dom<GCC::CardView>::post(home, xv, cv)));
          break;
        default:
          GECODE_ES_FAIL( 
                         (GCC::Val<GCC::CardView>::post(home, xv, cv)));
        }
        return;
      }
    }
    
    // No holes: create CardConsts
    ViewArray<GCC::CardConst> cv(home, c.size());

    for (int i = c.size(); i--; )
      cv[i].init(home,c[i].min(),c[i].max(),v[i]);

    switch (icl) {
    case ICL_BND:
      GECODE_ES_FAIL(
                     (GCC::Bnd<GCC::CardConst>::post(home, xv, cv)));
      break;
    case ICL_DOM:
      GECODE_ES_FAIL(
                     (GCC::Dom<GCC::CardConst>::post(home, xv, cv)));
      break;
    default:
      GECODE_ES_FAIL(
                     (GCC::Val<GCC::CardConst>::post(home, xv, cv)));
    }
  }