Пример #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;
  }
Пример #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;
}
Пример #3
0
 ExecStatus
 ViewValuesBrancher<n,min>::commit(Space& home, const Choice& c, 
                                   unsigned int a) {
   const PosValuesChoice& pvc
     = static_cast<const PosValuesChoice&>(c);
   IntView x(ViewBrancher<IntView,n>::view(pvc.pos()));
   unsigned int b = min ? a : (pvc.alternatives() - 1 - a);
   return me_failed(x.eq(home,pvc.val(b))) ? ES_FAILED : ES_OK;
 }
 ExecStatus
 ViewValuesBrancher<ViewSel,View>
 ::commit(Space& home, const Choice& c, unsigned int a) {
   const PosValuesChoice<ViewSel,View>& pvc
     = static_cast<const PosValuesChoice<ViewSel,View>&>(c);
   View v(ViewBrancher<ViewSel>::view(pvc.pos()).varimp());
   viewsel.commit(home, pvc.viewchoice(), a);
   return me_failed(v.eq(home,pvc.val(a))) ? ES_FAILED : ES_OK;
 }
Пример #5
0
 forceinline ModEvent
 ManFlexTask::norun(Space& home, int e, int l) {
   if (e <= l) {
     Iter::Ranges::Singleton sr(e-_p.min()+1,l);
     if (me_failed(_s.minus_r(home,sr,false)))
       return Int::ME_INT_FAILED;
     Iter::Ranges::Singleton er(e+1,_p.min()+l);
     return _e.minus_r(home,er,false);
   } else {
     return Int::ME_INT_NONE;
   }
 }
Пример #6
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;
}
Пример #7
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;
 }
Пример #8
0
 ExecStatus
 ExcNGL::prune(Space& home) {
   return me_failed(x.include(home,n)) ? ES_FAILED : ES_OK;
 }
Пример #9
0
 ExecStatus
 NqNGL<View>::prune(Space& home) {
   return me_failed(x.eq(home,n)) ? ES_FAILED : ES_OK;
 }
Пример #10
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;
  }
Пример #11
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;
  }
Пример #12
0
  ExecStatus
  prop_val(Space& home, ViewArray<View>& x) {
    assert(x.size() > 1);
    int n = x.size();

    Region r(home);
    int* stack = r.alloc<int>(n);
    int* c_v = &stack[0];
    // c_n is the current number of values on stack
    int c_n = 0;

    // Collect all assigned variables on stack
    for (int i = n; i--; )
      if (x[i].assigned()) {
        c_v[c_n++]=x[i].val(); x[i]=x[--n];
      }

    // The number of trips
    int t = 0;
    do {
      t++;
      if (!complete && (t > 16)) {
        // Give up after sixteen iterations, but the values must be
        // propagated first
        // Maybe we are lucky in that this iteration does the trick...
        ExecStatus es = ES_FIX;
        while (c_n > 0) {
          int v = c_v[--c_n];
          // Check whether value is on stack only once
          for (int i = c_n; i--; )
            if (c_v[i] == v)
              goto failed;
          // Tell and do not collect new values
          for (int i = n; i--; ) {
            ModEvent me = x[i].nq(home,v);
            if (me_failed(me))
              goto failed;
            if (me == ME_INT_VAL)
              es = ES_NOFIX;
          }
        }
        x.size(n);
        return es;
      }
      if (c_n > 31) {
        // Many values, use full domain operation
        IntSet d(&c_v[0],c_n);
        // If the size s of d is different from the number of values,
        // a value must have appeared multiply: failure
        if (d.size() != static_cast<unsigned int>(c_n))
          goto failed;
        // We do not need the values on the stack any longer, reset
        c_n = 0;
        // Tell and collect new values
        for (int i = n; i--; )
          if ((d.min() <= x[i].max()) && (d.max() >= x[i].min())) {
            IntSetRanges dr(d);
            ModEvent me = x[i].minus_r(home,dr,false);
            if (me_failed(me))
              goto failed;
            if (me == ME_INT_VAL) {
              c_v[c_n++]=x[i].val(); x[i]=x[--n];
            }
          }
      } else {
        // Values for next iteration
        int* n_v = &c_v[c_n];
        // Stack top for the next iteration
        int n_n = 0;
        while (c_n > 0) {
          int v = c_v[--c_n];
          // Check whether value is not on current stack
          for (int i = c_n; i--; )
            if (c_v[i] == v)
              goto failed;
          // Check whether value is not on next stack
          for (int i = n_n; i--; )
            if (n_v[i] == v)
              goto failed;
          // Tell and collect new values
          for (int i = n; i--; ) {
            ModEvent me = x[i].nq(home,v);
            if (me_failed(me))
              goto failed;
            if (me == ME_INT_VAL) {
              n_v[n_n++]=x[i].val(); x[i]=x[--n];
            }
          }
        }
        c_v = n_v; c_n = n_n;
      }
    } while (c_n > 0);
    x.size(n);
    return ES_FIX;
  failed:
    x.size(0);
    return ES_FAILED;
  }
Пример #13
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;
}