Exemplo n.º 1
0
  inline bool
  normalize(Space& home,
            ViewArray<View>& y,
            ViewArray<View>& x,
            bool& nofix) {

    int ys = y.size();
    for (int i = 1; i < ys; i++) {
      ModEvent me_lb = y[i].gq(home, y[i - 1].min());
      if (me_failed(me_lb))
        return false;
      nofix |= (me_modified(me_lb) && y[i - 1].min() != y[i].min());
    }

    for (int i = ys - 1; i--; ) {
      ModEvent me_ub = y[i].lq(home, y[i + 1].max());
      if (me_failed(me_ub))
        return false;
      nofix |= (me_modified(me_ub) && y[i + 1].max() != y[i].max());
    }

    int xs = x.size();
    for (int i = xs; i--; ) {
      ModEvent me = x[i].gq(home, y[0].min());
      if (me_failed(me))
        return false;
      nofix |= (me_modified(me) && x[i].min() != y[0].min());

      me = x[i].lq(home, y[xs - 1].max());
      if (me_failed(me))
        return false;
      nofix |= (me_modified(me) && x[i].max() != y[xs - 1].max());
    }
    return true;
  }
Exemplo n.º 2
0
ExecStatus
doprop_val(Space& home, int n, Info* x, Offset& ox,
           Info* y, Offset& oy,
           int& n_na, ProcessStack& xa, ProcessStack& ya) {
    do {
        int i = xa.pop();
        int j = ox(x[i].view).val();
        // Assign the y variable to i (or test if already assigned!)
        {
            ModEvent me = oy(y[j].view).eq(home,i);
            if (me_failed(me)) {
                return ES_FAILED;
            }
            // Record that y[j] has been assigned and must be propagated
            if (me_modified(me))
                ya.push(j);
        }
        // Prune the value j from all x variables
        for (int k=i; k--; ) {
            ModEvent me = ox(x[k].view).nq(home,j);
            if (me_failed(me)) {
                return ES_FAILED;
            }
            if (me_modified(me)) {
                if (me == ME_INT_VAL) {
                    // Record that x[k] has been assigned and must be propagated
                    xa.push(k);
                } else {
                    // One value has been removed and this removal does not need
                    // to be propagated again: after all y[j] = i, so it holds
                    // that y[j] != k.
                    x[k].removed(j);
                }
            }
        }
        // The same for the other views
        for (int k=i+1; k<n; k++) {
            ModEvent me = ox(x[k].view).nq(home,j);
            if (me_failed(me)) {
                return ES_FAILED;
            }
            if (me_modified(me)) {
                if (me == ME_INT_VAL) {
                    // Record that x[k] has been assigned and must be propagated
                    xa.push(k);
                } else {
                    // One value has been removed and this removal does not need
                    // to be propagated again: after all y[j] = i, so it holds
                    // that y[j] != k.
                    x[k].removed(j);
                }
            }
        }
        x[i].assigned();
        n_na--;
    } while (!xa.empty());
    return ES_OK;
}
Exemplo n.º 3
0
inline bool
narrow_domy(Space& home,
            ViewArray<View>& x, ViewArray<View>& y,
            int phi[], int phiprime[], bool& nofix) {
    for (int i=x.size(); i--; ) {
        ModEvent me_lb = y[i].gq(home, x[phiprime[i]].min());
        if (me_failed(me_lb)) {
            return false;
        }
        nofix |= (me_modified(me_lb) &&
                  x[phiprime[i]].min() != y[i].min());

        ModEvent me_ub = y[i].lq(home, x[phi[i]].max());
        if (me_failed(me_ub)) {
            return false;
        }
        nofix |= (me_modified(me_ub) &&
                  x[phi[i]].max() != y[i].max());
    }
    return true;
}
Exemplo n.º 4
0
 forceinline ExecStatus
 prop_mult_plus_bnd(Space& home, Propagator& p, VA x0, VB x1, VC x2) {
   assert(pos(x0) && pos(x1) && pos(x2));
   bool mod;
   do {
     mod = false;
     {
       ModEvent me = x2.lq(home,mll(x0.max(),x1.max()));
       if (me_failed(me)) return ES_FAILED;
       mod |= me_modified(me);
     }
     {
       ModEvent me = x2.gq(home,mll(x0.min(),x1.min()));
       if (me_failed(me)) return ES_FAILED;
       mod |= me_modified(me);
     }
     {
       ModEvent me = x0.lq(home,floor_div_pp(x2.max(),x1.min()));
       if (me_failed(me)) return ES_FAILED;
       mod |= me_modified(me);
     }
     {
       ModEvent me = x0.gq(home,ceil_div_pp(x2.min(),x1.max()));
       if (me_failed(me)) return ES_FAILED;
       mod |= me_modified(me);
     }
     {
       ModEvent me = x1.lq(home,floor_div_pp(x2.max(),x0.min()));
       if (me_failed(me)) return ES_FAILED;
       mod |= me_modified(me);
     }
     {
       ModEvent me = x1.gq(home,ceil_div_pp(x2.min(),x0.max()));
       if (me_failed(me)) return ES_FAILED;
       mod |= me_modified(me);
     }
   } while (mod);
   return x0.assigned() && x1.assigned() ?
     home.ES_SUBSUMED(p) : ES_FIX;
 }
Exemplo n.º 5
0
  ExecStatus
  ElementUnion<SView,RView>::propagate(Space& home, const ModEventDelta&) {
    Region r(home);
    int n = iv.size();

    bool loopVar;
    do {
      loopVar = false;

      // Cache the upper bound iterator, as we have to
      // modify the upper bound while iterating
      LubRanges<RView> x1ub(x1);
      Iter::Ranges::Cache<LubRanges<RView> > x1ubc(r,x1ub);
      Iter::Ranges::ToValues<Iter::Ranges::Cache<LubRanges<RView> > >
        vx1ub(x1ubc);

      GlbRanges<RView> x1lb(x1);
      Iter::Ranges::Cache<GlbRanges<RView> > x1lbc(r,x1lb);
      Iter::Ranges::ToValues<Iter::Ranges::Cache<GlbRanges<RView> > >
        vx1(x1lbc);

      // In the first iteration, compute in before[i] the union
      // of all the upper bounds of the x_i. At the same time,
      // exclude inconsistent x_i from x1 and remove them from
      // the list, cancel their dependencies.

      GLBndSet sofarBefore(home);
      LUBndSet selectedInter(home, IntSet (Limits::min,
                                   Limits::max));
      GLBndSet* before =
        static_cast<GLBndSet*>(r.ralloc(sizeof(GLBndSet)*n));

      int j = 0;
      int i = 0;

      unsigned int maxCard = 0;
      unsigned int minCard = Limits::card;

      while ( vx1ub() ) {

        // Remove vars at indices not in the upper bound
        if (iv[i].idx < vx1ub.val()) {
          iv[i].view.cancel(home,*this, PC_SET_ANY);
          ++i;
          continue;
        }
        assert(iv[i].idx == vx1ub.val());
        iv[j] = iv[i];

        SView candidate = iv[j].view;
        int candidateInd = iv[j].idx;

        // inter = glb(candidate) & complement(lub(x0))
        GlbRanges<SView> candlb(candidate);
        LubRanges<SView> x0ub(x0);
        Iter::Ranges::Diff<GlbRanges<SView>,
          LubRanges<SView> > diff(candlb, x0ub);

        bool selectSingleInconsistent = false;
        if (x1.cardMax() <= 1) {
          GlbRanges<SView> x0lb(x0);
          LubRanges<SView> candub(candidate);
          Iter::Ranges::Diff<GlbRanges<SView>,
                             LubRanges<SView> > diff2(x0lb, candub);
          selectSingleInconsistent = diff2() || candidate.cardMax() < x0.cardMin();
        }

        // exclude inconsistent x_i
        // an x_i is inconsistent if
        //  * at most one x_i can be selected and there are
        //    elements in x_0 that can't be in x_i
        //    (selectSingleInconsistent)
        //  * its min cardinality is greater than maxCard of x0
        //  * inter is not empty (there are elements in x_i
        //    that can't be in x_0)
        if (selectSingleInconsistent ||
            candidate.cardMin() > x0.cardMax() ||
            diff()) {
          ModEvent me = (x1.exclude(home,candidateInd));
          loopVar |= me_modified(me);
          GECODE_ME_CHECK(me);

          iv[j].view.cancel(home,*this, PC_SET_ANY);
          ++i;
          ++vx1ub;
          continue;
        } else {
          // if x_i is consistent, check whether we know
          // that its index is in x1
          if (vx1() && vx1.val()==candidateInd) {
            // x0 >= candidate, candidate <= x0
            GlbRanges<SView> candlb(candidate);
            ModEvent me = x0.includeI(home,candlb);
            loopVar |= me_modified(me);
            GECODE_ME_CHECK(me);

            LubRanges<SView> x0ub(x0);
            me = candidate.intersectI(home,x0ub);
            loopVar |= me_modified(me);
            GECODE_ME_CHECK(me);
            ++vx1;
          }
          new (&before[j]) GLBndSet(home);
          before[j].update(home,sofarBefore);
          LubRanges<SView> cub(candidate);
          sofarBefore.includeI(home,cub);
          GlbRanges<SView> clb(candidate);
          selectedInter.intersectI(home,clb);
          maxCard = std::max(maxCard, candidate.cardMax());
          minCard = std::min(minCard, candidate.cardMin());
        }

        ++vx1ub;
        ++i; ++j;
      }

      // cancel the variables with index greater than
      // max of lub(x1)
      for (int k=i; k<n; k++) {
        iv[k].view.cancel(home,*this, PC_SET_ANY);
      }
      n = j;
      iv.size(n);

      if (x1.cardMax()==0) {
        // Selector is empty, hence the result must be empty
        {
          GECODE_ME_CHECK(x0.cardMax(home,0));
        }
        for (int i=n; i--;)
          before[i].dispose(home);
        return home.ES_SUBSUMED(*this);
      }

      if (x1.cardMin() > 0) {
        // Selector is not empty, hence the intersection of the
        // possibly selected lower bounds is contained in x0
        BndSetRanges si(selectedInter);
        ModEvent me = x0.includeI(home, si);
        loopVar |= me_modified(me);
        GECODE_ME_CHECK(me);
        me = x0.cardMin(home, minCard);
        loopVar |= me_modified(me);
        GECODE_ME_CHECK(me);
      }
      selectedInter.dispose(home);

      if (x1.cardMax() <= 1) {
        ModEvent me = x0.cardMax(home, maxCard);
        loopVar |= me_modified(me);
        GECODE_ME_CHECK(me);
      }

      {
        // x0 <= sofarBefore
        BndSetRanges sfB(sofarBefore);
        ModEvent me = x0.intersectI(home,sfB);
        loopVar |= me_modified(me);
        GECODE_ME_CHECK(me);
      }

      sofarBefore.dispose(home);

      GLBndSet sofarAfter(home);

      // In the second iteration, this time backwards, compute
      // sofarAfter as the union of all lub(x_j) with j>i
      for (int i=n; i--;) {
        // TODO: check for size of universe here?
        // if (sofarAfter.size() == 0) break;

        // extra = inter(before[i], sofarAfter) - lub(x0)
        BndSetRanges b(before[i]);
        BndSetRanges s(sofarAfter);
        GlbRanges<SView> x0lb(x0);
        Iter::Ranges::Union<BndSetRanges, BndSetRanges> inter(b,s);
        Iter::Ranges::Diff<GlbRanges<SView>,
          Iter::Ranges::Union<BndSetRanges,BndSetRanges> > diff(x0lb, inter);
        if (diff()) {
          ModEvent me = (x1.include(home,iv[i].idx));
          loopVar |= me_modified(me);
          GECODE_ME_CHECK(me);

          // candidate != extra
          me = iv[i].view.includeI(home,diff);
          loopVar |= me_modified(me);
          GECODE_ME_CHECK(me);
        }

        LubRanges<SView> iviub(iv[i].view);
        sofarAfter.includeI(home,iviub);
        before[i].dispose(home);
      }
      sofarAfter.dispose(home);

    } while (loopVar);

    // Test whether we determined x1 without determining x0
    if (x1.assigned() && !x0.assigned()) {
      int ubsize = static_cast<int>(x1.lubSize());
      if (ubsize > 2) {
        assert(ubsize==n);
        ViewArray<SView> is(home,ubsize);
        for (int i=n; i--;)
          is[i]=iv[i].view;
        GECODE_REWRITE(*this,(RelOp::UnionN<SView, SView>
                        ::post(home(*this),is,x0)));
      } else if (ubsize == 2) {
        assert(n==2);
        SView a = iv[0].view;
        SView b = iv[1].view;
        GECODE_REWRITE(*this,(RelOp::Union<SView, SView, SView>
                       ::post(home(*this),a,b,x0)));
      } else if (ubsize == 1) {
        assert(n==1);
        GECODE_REWRITE(*this,(Rel::Eq<SView,SView>::post(home(*this),x0,iv[0].view)));
      } else {
        GECODE_ME_CHECK(x0.cardMax(home, 0));
        return home.ES_SUBSUMED(*this);
      }
    }

    bool allAssigned = true;
    for (int i=iv.size(); i--;) {
      if (!iv[i].view.assigned()) {
        allAssigned = false;
        break;
      }
    }
    if (x0.assigned() && x1.assigned() && allAssigned) {
      return home.ES_SUBSUMED(*this);
    }

    return ES_FIX;
  }
Exemplo n.º 6
0
  /*
   * Propagation proper
   *
   */
  ExecStatus 
  Pack::propagate(Space& home, const ModEventDelta& med) {
    // Number of items
    int n = bs.size();
    // Number of bins
    int m = l.size();

    {
      Region region(home);

      // Possible sizes for bins
      int* s = region.alloc<int>(m);

      for (int j=m; j--; )
        s[j] = 0;

      // Compute sizes for bins
      if (OffsetView::me(med) == ME_INT_VAL) {
        // Also eliminate assigned items
        int k=0;
        for (int i=0; i<n; i++)
          if (bs[i].assigned()) {
            int j = bs[i].bin().val();
            l[j].offset(l[j].offset() - bs[i].size());
            t -= bs[i].size();
          } else {
            for (ViewValues<IntView> j(bs[i].bin()); j(); ++j)
              s[j.val()] += bs[i].size();
            bs[k++] = bs[i];
          }
        n=k; bs.size(n);
      } else {
        for (int i=n; i--; ) {
          assert(!bs[i].assigned());
          for (ViewValues<IntView> j(bs[i].bin()); j(); ++j)
            s[j.val()] += bs[i].size();
        }
      }

      // Propagate bin loads and compute lower and upper bound
      int min = t, max = t;
      for (int j=m; j--; ) {
        GECODE_ME_CHECK(l[j].gq(home,0));
        GECODE_ME_CHECK(l[j].lq(home,s[j]));
        min -= l[j].max(); max -= l[j].min();
      }

      // Propagate that load must be equal to total size
      for (bool mod = true; mod; ) {
        mod = false; ModEvent me;
        for (int j=m; j--; ) {
          int lj_min = l[j].min();
          me = l[j].gq(home, min + l[j].max());
          if (me_failed(me))
            return ES_FAILED;
          if (me_modified(me)) {
            max += lj_min - l[j].min(); mod = true;
          }
          int lj_max = l[j].max();
          me = l[j].lq(home, max + l[j].min());
          if (me_failed(me))
            return ES_FAILED;
          if (me_modified(me)) {
            min += lj_max - l[j].max(); mod = true;
          }
        }
      }

      if (n == 0) {
        assert(l.assigned());
        return home.ES_SUBSUMED(*this);
      }

    
      {
        TellCache tc(region,m);

        int k=0;
        for (int i=0; i<n; i++) {
          for (ViewValues<IntView> j(bs[i].bin()); j(); ++j) {
            if (bs[i].size() > l[j.val()].max())
              tc.nq(j.val());
            if (s[j.val()] - bs[i].size() < l[j.val()].min()) 
              tc.eq(j.val());
          }
          GECODE_ES_CHECK(tc.tell(home,bs[i].bin()));
          // Eliminate assigned bin
          if (bs[i].assigned()) {
            int j = bs[i].bin().val();
            l[j].offset(l[j].offset() - bs[i].size());
            t -= bs[i].size();
          } else {
            bs[k++] = bs[i];
          }
        }
        n=k; bs.size(n);
      }

    }

    // Only if the propagator is at fixpoint here, continue with the more
    // expensive stage for propagation.
    if (IntView::me(modeventdelta()) != ME_INT_NONE)
      return ES_NOFIX;

    // Now the invariant holds that no more assigned bins exist!
    {
      Region region(home);

      // Size of items
      SizeSetMinusOne* s = region.alloc<SizeSetMinusOne>(m);

      for (int j=m; j--; )
        s[j] = SizeSetMinusOne(region,n);

      // Set up size information
      for (int i=0; i<n; i++) {
        assert(!bs[i].assigned());
        for (ViewValues<IntView> j(bs[i].bin()); j(); ++j) 
          s[j.val()].add(bs[i].size());
      }

      for (int j=m; j--; ) {
        // Can items still be packed into bin?
        if (nosum(static_cast<SizeSet&>(s[j]), l[j].min(), l[j].max()))
          return ES_FAILED;
        int ap, bp;
        // Must there be packed more items into bin?
        if (nosum(static_cast<SizeSet&>(s[j]), l[j].min(), l[j].min(), 
                  ap, bp))
          GECODE_ME_CHECK(l[j].gq(home,bp));
        // Must there be packed less items into bin?
        if (nosum(static_cast<SizeSet&>(s[j]), l[j].max(), l[j].max(), 
                  ap, bp))
          GECODE_ME_CHECK(l[j].lq(home,ap));
      }

      TellCache tc(region,m);

      int k=0;
      for (int i=0; i<n; i++) {
        assert(!bs[i].assigned());
        for (ViewValues<IntView> j(bs[i].bin()); j(); ++j) {
          // Items must be removed in decreasing size!
          s[j.val()].minus(bs[i].size());
          // Can item i still be packed into bin j?
          if (nosum(s[j.val()], 
                    l[j.val()].min() - bs[i].size(),
                    l[j.val()].max() - bs[i].size()))
            tc.nq(j.val());
          // Must item i be packed into bin j?
          if (nosum(s[j.val()], l[j.val()].min(), l[j.val()].max()))
            tc.eq(j.val());
        }
        GECODE_ES_CHECK(tc.tell(home,bs[i].bin()));
        if (bs[i].assigned()) {
          int j = bs[i].bin().val();
          l[j].offset(l[j].offset() - bs[i].size());
          t -= bs[i].size();
        } else {
          bs[k++] = bs[i];
        }
      }
      n=k; bs.size(n);
    }

    // Perform lower bound checking
    if (n > 0) {
      Region region(home);

      // Find capacity estimate (we start from bs[0] as it might be
      // not packable, actually (will be detected later anyway)!
      int c = bs[0].size();
      for (int j=m; j--; )
        c = std::max(c,l[j].max());

      // Count how many items have a certain size (bucket sort)
      int* n_s = region.alloc<int>(c+1);

      for (int i=c+1; i--; )
        n_s[i] = 0;

      // Count unpacked items
      for (int i=n; i--; )
        n_s[bs[i].size()]++;

      // Number of items and remaining bin load
      int nm = n;

      // Only count positive remaining bin loads
      for (int j=m; j--; ) 
        if (l[j].max() < 0) {
          return ES_FAILED;
        } else if (c > l[j].max()) {
          n_s[c - l[j].max()]++; nm++;
        }

      // Sizes of items and remaining bin loads
      int* s = region.alloc<int>(nm);

      // Setup sorted sizes
      {
        int k=0;
        for (int i=c+1; i--; )
          for (int n=n_s[i]; n--; )
            s[k++]=i;
        assert(k == nm);
      }

      // Items in N1 are from 0 ... n1 - 1
      int n1 = 0;
      // Items in N2 are from n1 ... n12 - 1, we count elements in N1 and N2
      int n12 = 0;
      // Items in N3 are from n12 ... n3 - 1 
      int n3 = 0;
      // Free space in N2
      int f2 = 0;
      // Total size of items in N3
      int s3 = 0;

      // Initialize n12 and f2
      for (; (n12 < nm) && (s[n12] > c/2); n12++)
        f2 += c - s[n12];

      // Initialize n3 and s3
      for (n3 = n12; n3 < nm; n3++)
        s3 += s[n3];
        
      // Compute lower bounds
      for (int k=0; k<=c/2; k++) {
        // Make N1 larger by adding elements and N2 smaller
        for (; (n1 < nm) && (s[n1] > c-k); n1++)
          f2 -= c - s[n1];
        assert(n1 <= n12);
        // Make N3 smaller by removing elements
        for (; (s[n3-1] < k) && (n3 > n12); n3--)
          s3 -= s[n3-1];
        // Overspill
        int o = (s3 > f2) ? ((s3 - f2 + c - 1) / c) : 0;
        if (n12 + o > m)
          return ES_FAILED;
      }
    }

    return ES_NOFIX;
  }
Exemplo n.º 7
0
  inline bool
  perm_bc(Space& home, int tau[],
          SccComponent sinfo[],
          int scclist[],
          ViewArray<View>& x,
          ViewArray<View>& z,
          bool& crossingedge,
          bool& nofix) {

    int ps = x.size();

    for (int i = 1; i < ps; i++) {
      // if there are "crossed edges"
      if (x[i - 1].min() < x[i].min()) {
        if (z[i - 1].min() > z[i].min()) {
          if (z[i].min() != sinfo[scclist[i]].leftmost) {
            // edge does not take part in solution
            if (z[i].assigned()) { // vital edge do not remove it
              if (x[i - 1].max() < x[i].min()) {
                // invalid permutation
                // the upper bound sorting cannot fix this
                return false;
              }
            } else {
              crossingedge = true;
              // and the permutation can still be changed
              // fix the permutation, i.e. modify z
              ModEvent me_z = z[i].gq(home, z[i - 1].min());
              if (me_failed(me_z)) {
                return false;
              }
              nofix |= ( me_modified(me_z) &&
                         z[i - 1].min() != z[i].min());
            }
          }
        }
      }
    }

    // the same check as above for the upper bounds
    for (int i = ps - 1; i--; ) {
      if (x[tau[i]].max() < x[tau[i + 1]].max()) {
        if (z[tau[i]].max() > z[tau[i + 1]].max()) {
          if (z[tau[i]].max() != sinfo[scclist[tau[i]]].rightmost) {
            // edge does not take part in solution
            if (z[tau[i]].assigned()) {
              if (x[tau[i + 1]].min() > x[tau[i]].max()) {
                // invalid permutation
                return false;
              }
            } else {
              crossingedge = true;
              ModEvent me_z = z[tau[i]].lq(home, z[tau[i + 1]].max());
              if (me_failed(me_z)) {
                return false;
              }
              nofix |= (me_modified(me_z) &&
                        z[tau[i + 1]].max() != z[tau[i]].max());
            }
          }
        }
      }
    }

    return true;
  }
Exemplo n.º 8
0
  ExecStatus
  ElementUnionConst<SView,RView>::propagate(Space& home, const ModEventDelta&) {
    Region r(home);

    bool* stillSelected = r.alloc<bool>(n_iv);

    bool loopVar;
    do {
      loopVar = false;
      for (int i=n_iv; i--;)
        stillSelected[i] = false;

      // Cache the upper bound iterator, as we have to
      // modify the upper bound while iterating
      LubRanges<RView> x1ub(x1);
      Iter::Ranges::Cache x1ubc(r,x1ub);
      Iter::Ranges::ToValues<Iter::Ranges::Cache>
        vx1ub(x1ubc);

      GlbRanges<RView> x1lb(x1);
      Iter::Ranges::Cache x1lbc(r,x1lb);
      Iter::Ranges::ToValues<Iter::Ranges::Cache>
        vx1(x1lbc);

      // In the first iteration, compute in before[i] the union
      // of all the upper bounds of the x_i. At the same time,
      // exclude inconsistent x_i from x1.

      GLBndSet sofarBefore(home);
      LUBndSet selectedInter(home, IntSet (Limits::min,
                                   Limits::max));
      GLBndSet* before =
        static_cast<GLBndSet*>(r.ralloc(sizeof(GLBndSet)*n_iv));

      unsigned int maxCard = 0;
      unsigned int minCard = Limits::card;

      while (vx1ub()) {
        int i = vx1ub.val();

        IntSetRanges candCardR(iv[i]);
        unsigned int candidateCard = Iter::Ranges::size(candCardR);

        IntSetRanges candlb(iv[i]);
        LubRanges<SView> x0ub(x0);
        Iter::Ranges::Diff<IntSetRanges,
          LubRanges<SView> > diff(candlb, x0ub);

        bool selectSingleInconsistent = false;
        if (x1.cardMax() <= 1) {
          GlbRanges<SView> x0lb(x0);
          IntSetRanges candub(iv[i]);
          Iter::Ranges::Diff<GlbRanges<SView>,
                             IntSetRanges > diff2(x0lb, candub);
          selectSingleInconsistent = diff2() || candidateCard < x0.cardMin();
        }

        // exclude inconsistent x_i
        // an x_i is inconsistent if
        //  * at most one x_i can be selected and there are
        //    elements in x_0 that can't be in x_i
        //    (selectSingleInconsistent)
        //  * its min cardinality is greater than maxCard of x0
        //  * inter is not empty (there are elements in x_i
        //    that can't be in x_0)
        if (selectSingleInconsistent ||
            candidateCard > x0.cardMax() ||
            diff()) {
          ModEvent me = (x1.exclude(home,i));
          loopVar |= me_modified(me);
          GECODE_ME_CHECK(me);
        } else {
          stillSelected[i] = true;
          // if x_i is consistent, check whether we know
          // that its index is in x1
          if (vx1() && vx1.val()==i) {
            // x0 >= candidate, candidate <= x0
            // GlbRanges<SView> candlb(candidate);
            IntSetRanges candlb(iv[i]);
            ModEvent me = x0.includeI(home,candlb);
            loopVar |= me_modified(me);
            GECODE_ME_CHECK(me);
            ++vx1;
          }
          new (&before[i]) GLBndSet(home);
          before[i].update(home,sofarBefore);
          IntSetRanges cub(iv[i]);
          sofarBefore.includeI(home,cub);
          IntSetRanges clb(iv[i]);
          selectedInter.intersectI(home,clb);
          maxCard = std::max(maxCard, candidateCard);
          minCard = std::min(minCard, candidateCard);
        }

        ++vx1ub;
      }

      if (x1.cardMax()==0) {
        // Selector is empty, hence the result must be empty
        {
          GECODE_ME_CHECK(x0.cardMax(home,0));
        }
        for (int i=n_iv; i--;)
          if (stillSelected[i])
            before[i].dispose(home);
        selectedInter.dispose(home);
        sofarBefore.dispose(home);
        return home.ES_SUBSUMED(*this);
      }

      if (x1.cardMin() > 0) {
        // Selector is not empty, hence the intersection of the
        // possibly selected lower bounds is contained in x0
        BndSetRanges si(selectedInter);
        ModEvent me = x0.includeI(home, si);
        loopVar |= me_modified(me);
        GECODE_ME_CHECK(me);
        me = x0.cardMin(home, minCard);
        loopVar |= me_modified(me);
        GECODE_ME_CHECK(me);
      }
      selectedInter.dispose(home);

      if (x1.cardMax() <= 1) {
        ModEvent me = x0.cardMax(home, maxCard);
        loopVar |= me_modified(me);
        GECODE_ME_CHECK(me);
      }

      {
        // x0 <= sofarBefore
        BndSetRanges sfB(sofarBefore);
        ModEvent me = x0.intersectI(home,sfB);
        loopVar |= me_modified(me);
        GECODE_ME_CHECK(me);
      }

      sofarBefore.dispose(home);

      GLBndSet sofarAfter(home);

      // In the second iteration, this time backwards, compute
      // sofarAfter as the union of all lub(x_j) with j>i
      for (int i=n_iv; i--;) {
        if (!stillSelected[i])
          continue;
        BndSetRanges b(before[i]);
        BndSetRanges s(sofarAfter);
        GlbRanges<SView> x0lb(x0);
        Iter::Ranges::Union<BndSetRanges, BndSetRanges> inter(b,s);
        Iter::Ranges::Diff<GlbRanges<SView>,
          Iter::Ranges::Union<BndSetRanges,BndSetRanges> > diff(x0lb, inter);
        if (diff()) {
          ModEvent me = (x1.include(home,i));
          loopVar |= me_modified(me);
          GECODE_ME_CHECK(me);

          // candidate != extra
          IntSetRanges ivi(iv[i]);
          if (!Iter::Ranges::subset(diff, ivi))
            GECODE_ME_CHECK(ME_SET_FAILED);
        }

        IntSetRanges iviub(iv[i]);
        sofarAfter.includeI(home,iviub);
        before[i].dispose(home);
      }
      sofarAfter.dispose(home);

    } while (loopVar);

    if (x1.assigned()) {
      assert(x0.assigned());
      return home.ES_SUBSUMED(*this);
    }

    return ES_FIX;
  }
Exemplo n.º 9
0
inline bool
narrow_domx(Space& home,
            ViewArray<View>& x,
            ViewArray<View>& y,
            ViewArray<View>& z,
            int tau[],
            int[],
            int scclist[],
            SccComponent sinfo[],
            bool& nofix) {

    int xs = x.size();

    // For every x node
    for (int i = 0; i < xs; i++) {

        int xmin = x[i].min();
        /*
         * take the scc-list for the current x node
         * start from the leftmost reachable y node of the scc
         * and check which Y node in the scc is
         * really the rightmost node intersecting x, i.e.
         * search for the greatest lower bound of x
         */
        int start = sinfo[scclist[i]].leftmost;
        while (y[start].max() < xmin) {
            start = sinfo[start].right;
        }

        if (Perm) {
            // start is the leftmost-position for x_i
            // that denotes the lower bound on p_i

            ModEvent me_plb = z[i].gq(home, start);
            if (me_failed(me_plb)) {
                return false;
            }
            nofix |= (me_modified(me_plb) && start != z[i].min());
        }

        ModEvent me_lb = x[i].gq(home, y[start].min());
        if (me_failed(me_lb)) {
            return false;
        }
        nofix |= (me_modified(me_lb) &&
                  y[start].min() != x[i].min());

        int ptau = tau[xs - 1 - i];
        int xmax = x[ptau].max();
        /*
         * take the scc-list for the current x node
         * start from the rightmost reachable node and check which
         * y node in the scc is
         * really the rightmost node intersecting x, i.e.
         * search for the smallest upper bound of x
         */
        start = sinfo[scclist[ptau]].rightmost;
        while (y[start].min() > xmax) {
            start = sinfo[start].left;
        }

        if (Perm) {
            //start is the rightmost-position for x_i
            //that denotes the upper bound on p_i
            ModEvent me_pub = z[ptau].lq(home, start);
            if (me_failed(me_pub)) {
                return false;
            }
            nofix |= (me_modified(me_pub) && start != z[ptau].max());
        }

        ModEvent me_ub = x[ptau].lq(home, y[start].max());
        if (me_failed(me_ub)) {
            return false;
        }
        nofix |= (me_modified(me_ub) &&
                  y[start].max() != x[ptau].max());
    }
    return true;
}
Exemplo n.º 10
0
  ExecStatus
  Weights<View>::propagate(Space& home, const ModEventDelta&) {

    ModEvent me = ME_SET_NONE;

    if (!x.assigned()) {
      // Collect the weights of the elements in the unknown set in an array
      int size = elements.size();
      Region r(home);
      int* currentWeights = r.alloc<int>(size);

      UnknownRanges<View> ur(x);
      Iter::Ranges::ToValues<UnknownRanges<View> > urv(ur);
      for (int i=0; i<size; i++) {
        if (!urv() || elements[i]<urv.val()) {
          currentWeights[i] = 0;
        } else {
          assert(elements[i] == urv.val());
          currentWeights[i] = weights[i];
          ++urv;
        }
      }

      // Sort the weights of the unknown elements
      IntLess il;
      Support::quicksort<int>(currentWeights, size, il);

      // The maximum number of elements that can still be added to x
      int delta = static_cast<int>(std::min(x.unknownSize(), x.cardMax() - x.glbSize()));

      // The weight of the elements already in x
      GlbRanges<View> glb(x);
      int glbWeight = weightI<GlbRanges<View> >(elements, weights, glb);

      // Compute the weight of the current lower bound of x, plus at most
      // delta-1 further elements with smallest negative weights. This weight
      // determines which elements in the upper bound cannot possibly be
      // added to x (those whose weight would exceed the capacity even if
      // all other elements are minimal)
      int lowWeight = glbWeight;
      for (int i=0; i<delta-1; i++) {
        if (currentWeights[i] >= 0)
          break;
        lowWeight+=currentWeights[i];
      }

      // Compute the lowest possible weight of x. If there is another element
      // with negative weight left, then add its weight to lowWeight.
      // Otherwise lowWeight is already the lowest possible weight.
      int lowestWeight = lowWeight;
      if (delta>0 && currentWeights[delta-1]<0)
        lowestWeight+=currentWeights[delta-1];

      // If after including the minimal number of required elements,
      // no more element with negative weight is available, then
      // a tighter lower bound can be computed.
      if ( (x.cardMin() - x.glbSize() > 0 &&
            currentWeights[x.cardMin() - x.glbSize() - 1] >= 0) ||
           currentWeights[0] >= 0 ) {
        int lowestPosWeight = glbWeight;
        for (unsigned int i=0; i<x.cardMin() - x.glbSize(); i++) {
          lowestPosWeight += currentWeights[i];
        }
        lowestWeight = std::max(lowestWeight, lowestPosWeight);        
      }

      // Compute the highest possible weight of x as the weight of the lower
      // bound plus the weight of the delta heaviest elements still in the
      // upper bound.
      int highestWeight = glbWeight;
      for (int i=0; i<delta; i++) {
        if (currentWeights[size-i-1]<=0)
          break;
        highestWeight += currentWeights[size-i-1];
      }

      // Prune the weight using the computed bounds
      GECODE_ME_CHECK(y.gq(home, lowestWeight));
      GECODE_ME_CHECK(y.lq(home, highestWeight));

      // Exclude all elements that are too heavy from the set x.
      // Elements are too heavy if their weight alone already
      // exceeds the remaining capacity
      int remainingCapacity = y.max()-lowWeight;

      UnknownRanges<View> ur2(x);
      Iter::Ranges::ToValues<UnknownRanges<View> > urv2(ur2);
      OverweightValues<Iter::Ranges::ToValues<UnknownRanges<View> > >
        ov(remainingCapacity, elements, weights, urv2);
      Iter::Values::ToRanges<OverweightValues<
        Iter::Ranges::ToValues<UnknownRanges<View> > > > ovr(ov);
      me = x.excludeI(home, ovr);
      GECODE_ME_CHECK(me);
    }
    if (x.assigned()) {
      // If x is assigned, just compute its weight and assign y.
      GlbRanges<View> glb(x);
      int w =
        weightI<GlbRanges<View> >(elements, weights, glb);
      GECODE_ME_CHECK(y.eq(home, w));
      return home.ES_SUBSUMED(*this);
    }

    return me_modified(me) ? ES_NOFIX : ES_FIX;
  }