Esempio n. 1
0
File: eq.hpp Progetto: Gecode/gecode
 ExecStatus
 ReEq<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) {
   if (b.one()) {
     if (rm == RM_PMI)
       return home.ES_SUBSUMED(*this);
     GECODE_REWRITE(*this,(Eq<View,View>::post(home(*this),x0,x1)));
   }
   if (b.zero()) {
     if (rm == RM_IMP)
       return home.ES_SUBSUMED(*this);
     GECODE_REWRITE(*this,(Nq<View,View>::post(home(*this),x0,x1)));
   }
   switch (rtest_eq(x0,x1)) {
   case RT_TRUE:
     if (rm != RM_IMP)
       GECODE_ME_CHECK(b.one_none(home));
     break;
   case RT_FALSE:
     if (rm != RM_PMI)
       GECODE_ME_CHECK(b.zero_none(home));
     break;
   case RT_MAYBE:
     return ES_FIX;
   default: GECODE_NEVER;
   }
   return home.ES_SUBSUMED(*this);
 }
Esempio n. 2
0
 ExecStatus
 ReLq<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) {
   if (b.one()) {
     if (rm != RM_PMI)
       GECODE_REWRITE(*this,Lq<View>::post(home(*this),x0,x1));
   } else if (b.zero()) {
     if (rm != RM_IMP)
       GECODE_REWRITE(*this,Le<View>::post(home(*this),x1,x0));
   } else {
     switch (rtest_lq(x0,x1)) {
     case RT_TRUE:
       if (rm != RM_IMP)
         GECODE_ME_CHECK(b.one_none(home));
       break;
     case RT_FALSE:
       if (rm != RM_PMI)
         GECODE_ME_CHECK(b.zero_none(home)); 
       break;
     case RT_MAYBE:
       if (!x0.assigned() || !x1.assigned())
         return ES_FIX;
       else {
         if (rm != RM_IMP)
           GECODE_ME_CHECK(b.one_none(home));
         break;
       }
     default: GECODE_NEVER;
     }
   }
   return home.ES_SUBSUMED(*this);
 }
Esempio n. 3
0
 ExecStatus
 ReEqBin<Val,A,B,Ctrl,rm>::propagate(Space& home, const ModEventDelta&) {
   if (b.zero()) {
     if (rm == RM_IMP)
       return home.ES_SUBSUMED(*this);
     GECODE_REWRITE(*this,(NqBin<Val,A,B>::post(home(*this),x0,x1,c)));
   }
   if (b.one()) {
     if (rm == RM_PMI)
       return home.ES_SUBSUMED(*this);
     GECODE_REWRITE(*this,(EqBin<Val,A,B>::post(home(*this),x0,x1,c)));
   }
   if ((x0.min() + x1.min() > c) || (x0.max() + x1.max() < c)) {
     if (rm != RM_PMI)
       GECODE_ME_CHECK(b.zero_none(home));
     return home.ES_SUBSUMED(*this);
   }
   if (x0.assigned() && x1.assigned()) {
     assert(x0.val() + x1.val() == c);
     if (rm != RM_IMP)
       GECODE_ME_CHECK(b.one_none(home));
     return home.ES_SUBSUMED(*this);
   }
   return ES_FIX;
 }
Esempio n. 4
0
  ExecStatus
  ReEq<View0,View1>::propagate(Space& home, const ModEventDelta&) {
    if (b.one())
      GECODE_REWRITE(*this,(Eq<View0,View1>::post(home(*this),x0,x1)));
    if (b.zero())
      GECODE_REWRITE(*this,(Distinct<View0,View1>::post(home(*this),x0,x1)));

    if (x0.assigned() && x1.assigned()) {
      // directly test x0==x1
      GlbRanges<View0> x0lb(x0);
      GlbRanges<View1> x1lb(x1);
      for (; x0lb() && x1lb(); ++x0lb, ++x1lb) {
        if (x0lb.min() != x1lb.min() ||
            x0lb.max() != x1lb.max()) {
          GECODE_ME_CHECK(b.zero_none(home));
          return home.ES_SUBSUMED(*this);
        }
      }
      if (!x0lb() && !x1lb()) {
        GECODE_ME_CHECK(b.one_none(home));
        return home.ES_SUBSUMED(*this);
      } else {
        GECODE_ME_CHECK(b.zero_none(home));
        return home.ES_SUBSUMED(*this);
      }
    }

    // check whether cardinalities still allow equality
    if (x0.cardMin() > x1.cardMax() ||
        x1.cardMin() > x0.cardMax()) {
      GECODE_ME_CHECK(b.zero_none(home));
      return home.ES_SUBSUMED(*this);
    }

    // check glb(x0) subset lub(x1)
    GlbRanges<View0> x0lb(x0);
    LubRanges<View1> x1ub(x1);
    Iter::Ranges::Diff<GlbRanges<View0>, LubRanges<View1> > diff1(x0lb, x1ub);
    if ( diff1() ) {
      GECODE_ME_CHECK(b.zero_none(home));
      return home.ES_SUBSUMED(*this);
    }

    // check glb(x1) subset lub(x0)
    GlbRanges<View1> x1lb(x1);
    LubRanges<View0> x0ub(x0);
    Iter::Ranges::Diff<GlbRanges<View1>, LubRanges<View0> > diff2(x1lb, x0ub);
    if ( diff2() ) {
      GECODE_ME_CHECK(b.zero_none(home));
      return home.ES_SUBSUMED(*this);
    }

    return ES_FIX;
  }
  ExecStatus
  ReSubset<View0,View1>::propagate(Space& home, const ModEventDelta&) {
    if (b.one())
      GECODE_REWRITE(*this,(Subset<View0,View1>::post(home(*this),x0,x1)));
    if (b.zero())
      GECODE_REWRITE(*this,(NoSubset<View0,View1>::post(home(*this),x0,x1)));

    // check whether cardinalities still allow subset
    if (x0.cardMin() > x1.cardMax()) {
      GECODE_ME_CHECK(b.zero_none(home));
      return home.ES_SUBSUMED(*this);
    }

    // check lub(x0) subset glb(x1)
    {
      LubRanges<View0> x0ub(x0);
      GlbRanges<View1> x1lb(x1);
      Iter::Ranges::Diff<LubRanges<View0>,GlbRanges<View1> > d(x0ub,x1lb);
      if (!d()) {
        GECODE_ME_CHECK(b.one_none(home));
        return home.ES_SUBSUMED(*this);
      }
    }

    // check glb(x0) subset lub(x1)
    {
      GlbRanges<View0> x0lb(x0);
      LubRanges<View1> x1ub(x1);
      Iter::Ranges::Diff<GlbRanges<View0>,LubRanges<View1> > d(x0lb,x1ub);
      if (d()) {
        GECODE_ME_CHECK(b.zero_none(home));
        return home.ES_SUBSUMED(*this);
      } else if (x0.assigned() && x1.assigned()) {
        GECODE_ME_CHECK(b.one_none(home));
        return home.ES_SUBSUMED(*this);
      }
    }

    if (x0.cardMin() > 0) {
      LubRanges<View0> x0ub(x0);
      LubRanges<View1> x1ub(x1);
      Iter::Ranges::Inter<LubRanges<View0>,LubRanges<View1> >
        i(x0ub,x1ub);
      if (!i()) {
        GECODE_ME_CHECK(b.zero_none(home));
        return home.ES_SUBSUMED(*this);
      }
    }

    return ES_FIX;
  }
Esempio n. 6
0
 ExecStatus
 Distinct<View0,View1>::propagate(Space& home, const ModEventDelta&) {
   assert(x0.assigned()||x1.assigned());
   if (x0.assigned()) {
     GlbRanges<View0> xr(x0);
     IntSet xs(xr);
     ConstSetView cv(home, xs);
     GECODE_REWRITE(*this,(DistinctDoit<View1>::post(home(*this),x1,cv)));
   } else {
     GlbRanges<View1> yr(x1);
     IntSet ys(yr);
     ConstSetView cv(home, ys);
     GECODE_REWRITE(*this,(DistinctDoit<View0>::post(home(*this),x0,cv)));
   }
 }
Esempio n. 7
0
 ExecStatus
 EqBoolView<XV,YV>::propagate(Space& home, const ModEventDelta&) {
   int n = x.size();
   for (int i = n; i--; )
     if (x[i].one()) {
       x[i]=x[--n]; c--;
     } else if (x[i].zero()) {
       x[i]=x[--n];
     }
   x.size(n);
   GECODE_ME_CHECK(y.lq(home,n-c));
   GECODE_ME_CHECK(y.gq(home,-c));
   if (n == 0)
     return home.ES_SUBSUMED(*this);
   if (y.min()+c == n) {
     assert(y.assigned());
     for (int i = n; i--; )
       GECODE_ME_CHECK(x[i].one_none(home));
     return home.ES_SUBSUMED(*this);
   }
   if (y.max()+c == 0) {
     assert(y.assigned());
     for (int i = n; i--; )
       GECODE_ME_CHECK(x[i].zero_none(home));
     return home.ES_SUBSUMED(*this);
   }
   if (y.assigned())
     GECODE_REWRITE(*this,EqBoolInt<XV>::post(home(*this),x,y.val()+c));
   return ES_FIX;
 }
Esempio n. 8
0
 ExecStatus 
 ManProp<ManTask,Cap>::propagate(Space& home, const ModEventDelta& med) {
   // Only bounds changes?
   if (Int::IntView::me(med) != Int::ME_INT_DOM)
     GECODE_ES_CHECK(overload(home,c.max(),t));
   GECODE_ES_CHECK(edgefinding(home,c.max(),t));
   bool subsumed;
   ExecStatus es = basic(home,subsumed,c,t);
   GECODE_ES_CHECK(es);
   if (subsumed)
     return home.ES_SUBSUMED(*this);
   if (Cap::varderived() && c.assigned() && c.val()==1) {
     // Check that tasks do not overload resource
     for (int i=t.size(); i--; )
       if (t[i].c() > 1)
         return ES_FAILED;
     // Rewrite to unary resource constraint
     TaskArray<typename TaskTraits<ManTask>::UnaryTask> ut(home,t.size());
     for (int i=t.size(); i--;)
       ut[i]=t[i];
     GECODE_REWRITE(*this,
       (Unary::ManProp<typename TaskTraits<ManTask>::UnaryTask>
         ::post(home(*this),ut)));
   } else {
     return es;
   }
 }
Esempio n. 9
0
  ExecStatus
  ManProp<ManTask,Cap,PL>::propagate(Space& home, const ModEventDelta& med) {
    // Only bounds changes?
    if (IntView::me(med) != ME_INT_DOM)
      GECODE_ES_CHECK(overload(home,c.max(),t));

    if (PL::advanced)
      GECODE_ES_CHECK(edgefinding(home,c.max(),t));

    if (PL::basic)
      GECODE_ES_CHECK(timetabling(home,*this,c,t));

    if (Cap::varderived() && c.assigned() && (c.val() == 1)) {
      // Check that tasks do not overload resource
      for (int i=t.size(); i--; )
        if (t[i].c() > 1)
          return ES_FAILED;
      // Rewrite to unary resource constraint
      TaskArray<typename TaskTraits<ManTask>::UnaryTask> ut(home,t.size());
      for (int i=t.size(); i--;)
        ut[i]=t[i];
      GECODE_REWRITE(*this,
        (Unary::ManProp<typename TaskTraits<ManTask>::UnaryTask,PL>
          ::post(home(*this),ut)));
    }

    if (!PL::basic && c.assigned())
      GECODE_ES_CHECK(subsumed(home,*this,c.val(),t));

    return ES_NOFIX;
  }
Esempio n. 10
0
  ExecStatus
  IteBnd<View>::propagate(Space& home, const ModEventDelta&) {
    if (b.one())
      GECODE_REWRITE(*this,(Rel::EqBnd<View,View>::post(home(*this),x2,x0)));
    if (b.zero())
      GECODE_REWRITE(*this,(Rel::EqBnd<View,View>::post(home(*this),x2,x1)));

    GECODE_ME_CHECK(x2.lq(home,std::max(x0.max(),x1.max())));
    GECODE_ME_CHECK(x2.gq(home,std::min(x0.min(),x1.min())));
    
    RelTest eq20 = rtest_eq_bnd(x2,x0);
    RelTest eq21 = rtest_eq_bnd(x2,x1);

    if ((eq20 == RT_FALSE) && (eq21 == RT_FALSE))
      return ES_FAILED;

    if (eq20 == RT_FALSE) {
      GECODE_ME_CHECK(b.zero_none(home));
      if (eq21 == RT_TRUE)
        return home.ES_SUBSUMED(*this);
      else
        GECODE_REWRITE(*this,(Rel::EqBnd<View,View>::post(home(*this),x2,x1)));
    }

    if (eq21 == RT_FALSE) {
      GECODE_ME_CHECK(b.one_none(home));
      if (eq20 == RT_TRUE)
        return home.ES_SUBSUMED(*this);
      else
        GECODE_REWRITE(*this,(Rel::EqBnd<View,View>::post(home(*this),x2,x0)));
    }
    
    if ((eq20 == RT_TRUE) && (eq21 == RT_TRUE))
      return home.ES_SUBSUMED(*this);

    return ES_FIX;
  }
Esempio n. 11
0
 ExecStatus
 ReLqBin<Val,A,B,rm>::propagate(Space& home, const ModEventDelta&) {
   if (b.one()) {
     if (rm == RM_PMI)
       return home.ES_SUBSUMED(*this);
     GECODE_REWRITE(*this,(LqBin<Val,A,B>::post(home(*this),x0,x1,c)));
   }
   if (b.zero()) {
     if (rm == RM_IMP)
       return home.ES_SUBSUMED(*this);
     GECODE_REWRITE(*this,(GqBin<Val,A,B>::post(home(*this),x0,x1,c+1)));
   }
   if (x0.max() + x1.max() <= c) {
     if (rm != RM_IMP)
       GECODE_ME_CHECK(b.one_none(home));
     return home.ES_SUBSUMED(*this);
   }
   if (x0.min() + x1.min() > c) {
     if (rm != RM_PMI)
       GECODE_ME_CHECK(b.zero_none(home));
     return home.ES_SUBSUMED(*this);
   }
   return ES_FIX;
 }
Esempio n. 12
0
  ExecStatus
  Pair::propagate(Space& home, const ModEventDelta&) {
    Region r(home);
    
    if (x0.assigned()) {
      // Bitset for supported div and mod values
      Support::BitSet<Region> d(r,static_cast<unsigned int>((x2.max() / w)+1));
      for (ViewValues<IntView> i(x2); i(); ++i) {
        d.set(static_cast<unsigned int>(i.val() / w));
      }
      Iter::Values::BitSet<Support::BitSet<Region> > id(d,x1.min(),x1.max());
      GECODE_ME_CHECK(x1.inter_v(home,id,false));
    } else {
      // Bitset for supported div and mod values
      Support::BitSet<Region> 
        d(r,static_cast<unsigned int>((x2.max() / w)+1)), 
        m(r,static_cast<unsigned int>(w));
      for (ViewValues<IntView> i(x2); i(); ++i) {
        d.set(static_cast<unsigned int>(i.val() / w)); 
        m.set(static_cast<unsigned int>(i.val() % w));
      }
      Iter::Values::BitSet<Support::BitSet<Region> > im(m,x0.min(),x0.max());
      GECODE_ME_CHECK(x0.inter_v(home,im,false));
      Iter::Values::BitSet<Support::BitSet<Region> > id(d,x1.min(),x1.max());
      GECODE_ME_CHECK(x1.inter_v(home,id,false));
    }

    if (x0.assigned() && x1.assigned()) {
      GECODE_ME_CHECK(x2.eq(home,x0.val()+w*x1.val()));
      return home.ES_SUBSUMED(*this);
    } else if (x1.assigned()) {
      OffsetView x0x1w(x0,x1.val()*w);
      GECODE_REWRITE(*this,(Rel::EqDom<OffsetView,IntView>
                            ::post(home(*this),x0x1w,x2)));
    }

    PairValues xy(x0,x1,w);
    GECODE_ME_CHECK(x2.inter_v(home,xy,false));

    if (x2.assigned()) {
      GECODE_ME_CHECK(x0.eq(home,x2.val() % w));
      GECODE_ME_CHECK(x1.eq(home,static_cast<int>(x2.val() / w)));
      return home.ES_SUBSUMED(*this);
    }

    return ES_NOFIX;
  }
Esempio n. 13
0
  ExecStatus
  LqView<VX,VY,VZ,shr>::propagate(Space& home, const ModEventDelta&) {
    count(home);
    GECODE_ME_CHECK(z.gq(home,atleast()));

    if (z.max() == atleast()) {
      GECODE_ES_CHECK(post_false(home,x,y));
      return home.ES_SUBSUMED(*this);
    }

    if (x.size() == 0)
      return home.ES_SUBSUMED(*this);

    if (z.assigned()) {
      VY yc(y);
      GECODE_REWRITE(*this,(LqInt<VX,VY>::post(home(*this),x,yc,z.val()+c)));
    }

    return shr ? ES_NOFIX : ES_FIX;
  }
Esempio n. 14
0
  ExecStatus
  EqView<VX,VY,VZ,shr,dom>::propagate(Space& home, const ModEventDelta&) {
    count(home);

    GECODE_ME_CHECK(z.gq(home,atleast()));
    GECODE_ME_CHECK(z.lq(home,atmost()));

    if (z.assigned()) {
      if (z.val() == atleast()) {
        GECODE_ES_CHECK(post_false(home,x,y));
        return home.ES_SUBSUMED(*this);
      }
      if (z.val() == atmost()) {
        GECODE_ES_CHECK(post_true(home,x,y));
        return home.ES_SUBSUMED(*this);
      }
      if (!dom || (vtd(y) != VTD_VARVIEW)) {
        VY yc(y);
        GECODE_REWRITE(*this,(EqInt<VX,VY>
                              ::post(home(*this),x,yc,z.val()+c)));    
      }
    }


    if (dom && (vtd(y) == VTD_VARVIEW) && (z.min() > 0)) {
      /* 
       * Only if the propagator is at fixpoint here, continue
       * when things are shared: the reason is that prune
       * requires that the views in x overlap with y!
       */
      if (shr && (VX::me(Propagator::modeventdelta()) != ME_INT_NONE))
        return ES_NOFIX;

      GECODE_ES_CHECK(prune(home,x,y));

      return ES_NOFIX;
    }
    
    return shr ? ES_NOFIX : ES_FIX;
  }
Esempio n. 15
0
  ExecStatus
  Subset<View0,View1>::propagate(Space& home, const ModEventDelta&) {
    bool oneassigned = x0.assigned() || x1.assigned();
    unsigned int x0glbsize;
    do {
      GlbRanges<View0> x0lb(x0);
      GECODE_ME_CHECK ( x1.includeI(home,x0lb) );
      GECODE_ME_CHECK ( x1.cardMin(home,x0.cardMin()) );
      LubRanges<View1> x1ub(x1);
      x0glbsize = x0.glbSize();
      GECODE_ME_CHECK ( x0.intersectI(home,x1ub) );
      GECODE_ME_CHECK ( x0.cardMax(home,x1.cardMax()) );
    } while (x0.glbSize() > x0glbsize);

    if (x0.cardMin() == x1.cardMax())
      GECODE_REWRITE(*this,(Eq<View0,View1>::post(home(*this),x0,x1)));

    if (shared(x0,x1)) {
      return oneassigned ? home.ES_SUBSUMED(*this) : ES_NOFIX;
    }
    return (x0.assigned() || x1.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
  }
Esempio n. 16
0
 forceinline ExecStatus
 IntBase<VY>::prune_upper(Space& home, Graph& g) {
   if (!g.initialized()) {
     g.init(home,vs,x);
   } else {
     g.purge();
     g.sync(home);
   }
   GECODE_ME_CHECK(y.lq(home, g.size()));
   if (y.min() == g.size()) {
     // All values must be taken on
     if (vs.size() + x.size() == g.size()) {
       // This is in fact a distinct, simplify and rewrite
       for (int i=x.size(); i--; ) {
         ValSet::Ranges vsr(vs);
         GECODE_ME_CHECK(x[i].minus_r(home, vsr, false));
       }
       GECODE_REWRITE(*this,Distinct::Dom<IntView>::post(home,x));
     }
     if (g.mark(home))
       GECODE_ES_CHECK(g.prune(home));
   }
   return ES_OK;
 }
Esempio n. 17
0
  ExecStatus
  ReLq<View0,View1,strict>::propagate(Space& home, const ModEventDelta&) {
    if (b.one())
      GECODE_REWRITE(*this,(Lq<View0,View1,strict>::post(home(*this),x0,x1)));
    if (b.zero())
      GECODE_REWRITE(*this,(Lq<View1,View0,!strict>::post(home(*this),x1,x0)));

    if (x0.cardMax() == 0) {
      if ( (!strict) || x1.cardMin() > 0) {
        GECODE_ME_CHECK(b.one_none(home));
        return home.ES_SUBSUMED(*this);
      }
      if (strict && x1.cardMax() == 0) {
        GECODE_ME_CHECK(b.zero_none(home));
        return home.ES_SUBSUMED(*this);
      }
    }

    if (x0.assigned() && x1.assigned()) {
      // directly test x0<=x1
      int min01;
      {
        GlbRanges<View0> x0l(x0);
        GlbRanges<View1> x1l(x1);
        Iter::Ranges::Diff<GlbRanges<View1>,GlbRanges<View0> > d(x1l,x0l);
        if (!d()) {
          if ((!strict) && x0.cardMax() == x1.cardMax()) {
            // equal
            GECODE_ME_CHECK(b.one_none(home));
          } else {
            // subset
            GECODE_ME_CHECK(b.zero_none(home));
          }
          return home.ES_SUBSUMED(*this);
        }
        min01 = d.min();
      }
      int min10;
      {
        GlbRanges<View0> x0l(x0);
        GlbRanges<View1> x1l(x1);
        Iter::Ranges::Diff<GlbRanges<View0>,GlbRanges<View1> > d(x0l,x1l);
        if (!d()) {
          if (strict && x0.cardMax() == x1.cardMax()) {
            // equal
            GECODE_ME_CHECK(b.zero_none(home));
          } else {
            // subset
            GECODE_ME_CHECK(b.one_none(home));
          }
          return home.ES_SUBSUMED(*this);
        }
        min10 = d.min();
      }

      assert(min01 != min10);
      if (min01<min10) {
        GECODE_ME_CHECK(b.one_none(home));
      } else {
        GECODE_ME_CHECK(b.zero_none(home));
      }
      return home.ES_SUBSUMED(*this);
    }

    // min(x0lb - x1ub) < min(x1ub) -> b=0
    if (x1.cardMax() > 0) {
      GlbRanges<View0> x0l(x0);
      LubRanges<View1> x1u(x1);
      int x1umin=x1u.min();
      Iter::Ranges::Diff<GlbRanges<View0>,LubRanges<View1> > d(x0l,x1u);
      if (d() && d.min() < x1umin) {
        GECODE_ME_CHECK(b.zero_none(home));
        return home.ES_SUBSUMED(*this);
      }
    }
    // min(x1lb - x0ub) < min(x0ub) -> b=1
    if (x0.cardMax() > 0) {
      LubRanges<View0> x0u(x0);
      GlbRanges<View1> x1l(x1);
      int x0umin=x0u.min();
      Iter::Ranges::Diff<GlbRanges<View1>,LubRanges<View0> > d(x1l,x0u);
      if (d() && d.min() < x0umin) {
        GECODE_ME_CHECK(b.one_none(home));
        return home.ES_SUBSUMED(*this);
      }
    }

    return ES_FIX;
  }
Esempio n. 18
0
  ExecStatus
  ReProp<View,rm>::propagate(Space& home, const ModEventDelta& med) {
    // Add assigned views to value set
    if (View::me(med) == ME_INT_VAL)
      add(home,vs,x);

    if (b.one()) {
      if (rm == RM_PMI)
        return home.ES_SUBSUMED(*this);
      ValSet vsc(vs);
      vs.flush();
      GECODE_REWRITE(*this,Prop<View>::post(home,vsc,x,y));
    }

    if (b.zero()) {
      if (rm != RM_IMP) {
        ValSet::Ranges vsr(vs);
        GECODE_ME_CHECK(y.minus_r(home,vsr,false));
        for (int i=x.size(); i--; )
          GECODE_ES_CHECK(Rel::Nq<View>::post(home,x[i],y));
      }
      return home.ES_SUBSUMED(*this);
    }

    // Eliminate views from x
    eliminate(home);
    
    switch (vs.compare(y)) {
    case Iter::Ranges::CS_SUBSET:
      if (rm != RM_IMP)
        GECODE_ME_CHECK(b.one(home));
      return home.ES_SUBSUMED(*this);
    case Iter::Ranges::CS_DISJOINT:
      if (x.size() == 0) {
        if (rm != RM_PMI)
          GECODE_ME_CHECK(b.zero(home));
        return home.ES_SUBSUMED(*this);
      }
      break;
    case Iter::Ranges::CS_NONE:
      break;
    default:
      GECODE_NEVER;
    }

    // Check whether y is in union of x and value set
    if (x.size() > 0) {
      Region r(home);

      ValSet::Ranges vsr(vs);
      ViewRanges<View> xsr(x[x.size()-1]);
      Iter::Ranges::NaryUnion  u(r,vsr,xsr);
      for (int i=x.size()-1; i--; ) {
        ViewRanges<View> xir(x[i]);
        u |= xir;
      }

      ViewRanges<View> yr(y);
      
      if (Iter::Ranges::disjoint(u,yr)) {
        if (rm != RM_PMI)
          GECODE_ME_CHECK(b.zero(home));
        return home.ES_SUBSUMED(*this);
      }
    }

    return ES_FIX;
  }
Esempio n. 19
0
  ExecStatus
  IteDom<View>::propagate(Space& home, const ModEventDelta& med) {
    if (b.one())
      GECODE_REWRITE(*this,(Rel::EqDom<View,View>::post(home(*this),x2,x0)));
    if (b.zero())
      GECODE_REWRITE(*this,(Rel::EqDom<View,View>::post(home(*this),x2,x1)));

    GECODE_ME_CHECK(x2.lq(home,std::max(x0.max(),x1.max())));
    GECODE_ME_CHECK(x2.gq(home,std::min(x0.min(),x1.min())));

    if (View::me(med) != ME_INT_DOM) {
      RelTest eq20 = rtest_eq_bnd(x2,x0);
      RelTest eq21 = rtest_eq_bnd(x2,x1);

      if ((eq20 == RT_FALSE) && (eq21 == RT_FALSE))
        return ES_FAILED;

      if (eq20 == RT_FALSE) {
        GECODE_ME_CHECK(b.zero_none(home));
        if (eq21 == RT_TRUE)
          return home.ES_SUBSUMED(*this);
        else
          GECODE_REWRITE(*this,
                         (Rel::EqDom<View,View>::post(home(*this),x2,x1)));
      }
      
      if (eq21 == RT_FALSE) {
        GECODE_ME_CHECK(b.one_none(home));
        if (eq20 == RT_TRUE)
          return home.ES_SUBSUMED(*this);
        else
          GECODE_REWRITE(*this,
                         (Rel::EqDom<View,View>::post(home(*this),x2,x0)));
      }
    
      if ((eq20 == RT_TRUE) && (eq21 == RT_TRUE))
        return home.ES_SUBSUMED(*this);

      return home.ES_FIX_PARTIAL(*this,View::med(ME_INT_DOM));
    }

    RelTest eq20 = rtest_eq_dom(x2,x0);
    RelTest eq21 = rtest_eq_dom(x2,x1);

    if ((eq20 == RT_FALSE) && (eq21 == RT_FALSE))
      return ES_FAILED;

    if (eq20 == RT_FALSE) {
      GECODE_ME_CHECK(b.zero_none(home));
      if (eq21 == RT_TRUE)
        return home.ES_SUBSUMED(*this);
      else
        GECODE_REWRITE(*this,
                       (Rel::EqDom<View,View>::post(home(*this),x2,x1)));
    }
      
    if (eq21 == RT_FALSE) {
      GECODE_ME_CHECK(b.one_none(home));
      if (eq20 == RT_TRUE)
        return home.ES_SUBSUMED(*this);
      else
        GECODE_REWRITE(*this,
                       (Rel::EqDom<View,View>::post(home(*this),x2,x0)));
    }
    
    assert((eq20 != RT_TRUE) || (eq21 != RT_TRUE));

    ViewRanges<View> r0(x0), r1(x1);
    Iter::Ranges::Union<ViewRanges<View>,ViewRanges<View> > u(r0,r1);
    
    if (!same(x0,x2) && !same(x1,x2))
      GECODE_ME_CHECK(x2.inter_r(home,u,false));
    else
      GECODE_ME_CHECK(x2.inter_r(home,u,true));

    return ES_FIX;
  }
Esempio n. 20
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;
  }
Esempio n. 21
0
  ExecStatus
  Union<View0,View1,View2>::propagate(Space& home, const ModEventDelta& med) {
    // This propagator implements the constraint
    // x2 = x0 u x1

    bool x0ass = x0.assigned();
    bool x1ass = x1.assigned();
    bool x2ass = x2.assigned();

    ModEvent me0 = View0::me(med);
    ModEvent me1 = View1::me(med);
    ModEvent me2 = View2::me(med);

    bool x0ubmod = false;
    bool x1ubmod = false;
    bool modified = false;

    do {

      modified = false;
      do {
        // 4) lub(x2) <= lub(x0) u lub(x1)
        {
          LubRanges<View0> x0ub(x0);
          LubRanges<View1> x1ub(x1);
          Iter::Ranges::Union<LubRanges<View0>, LubRanges<View1> > u2(x0ub,x1ub);
          GECODE_ME_CHECK_MODIFIED(modified, x2.intersectI(home,u2) );
        }

        if (modified || Rel::testSetEventUB(me2) )
          {
            modified = false;
            // 5) x0 <= x2
            LubRanges<View2> x2ub1(x2);
            GECODE_ME_CHECK_MODIFIED(modified, x0.intersectI(home,x2ub1) );
            x0ubmod |= modified;

            // 6) x1 <= x2
            bool modified2=false;
            LubRanges<View2> x2ub2(x2);
            GECODE_ME_CHECK_MODIFIED(modified2, x1.intersectI(home,x2ub2) );
            x1ubmod |= modified2;
            modified |= modified2;
          }

      } while (modified);

      modified = false;
      do {
        bool modifiedOld = modified;
        modified = false;

        if (Rel::testSetEventLB(me2) || Rel::testSetEventUB(me0)
             || x0ubmod || modifiedOld)
          {
            // 1) glb(x0) \ lub(x1) <= glb(x2)
            GlbRanges<View2> x2lb(x2);
            LubRanges<View0> x0ub(x0);
            Iter::Ranges::Diff<GlbRanges<View2>, LubRanges<View0> >
              diff(x2lb, x0ub);
            GECODE_ME_CHECK_MODIFIED(modified, x1.includeI(home,diff) );
          }

        if (Rel::testSetEventLB(me2) || Rel::testSetEventUB(me1)
            || x1ubmod || modifiedOld)
          {
            // 2) glb(x0) \ lub(x2) <= glb(x1)
            GlbRanges<View2> x2lb(x2);
            LubRanges<View1> x1ub(x1);
            Iter::Ranges::Diff<GlbRanges<View2>, LubRanges<View1> >
              diff(x2lb, x1ub);
            GECODE_ME_CHECK_MODIFIED(modified, x0.includeI(home,diff) );
          }

         if (Rel::testSetEventLB(me0,me1) || modified)
          {
            //            modified = false;
            // 3) glb(x1) u glb(x2) <= glb(x0)
            GlbRanges<View0> x0lb(x0);
            GlbRanges<View1> x1lb(x1);
            Iter::Ranges::Union<GlbRanges<View0>, GlbRanges<View1> >
              u1(x0lb,x1lb);
            GECODE_ME_CHECK_MODIFIED(modified, x2.includeI(home,u1) );
          }

      } while(modified);

      modified = false;
      {
        // cardinality
        ExecStatus ret = unionCard(home,modified, x0, x1, x2);
        GECODE_ES_CHECK(ret);
      }

      if (x2.cardMax() == 0) {
        GECODE_ME_CHECK( x0.cardMax(home, 0) );
        GECODE_ME_CHECK( x1.cardMax(home, 0) );
        return home.ES_SUBSUMED(*this);
      }

      if (x0.cardMax() == 0)
        GECODE_REWRITE(*this,(Rel::Eq<View1,View2>::post(home(*this),x1,x2)));
      if (x1.cardMax() == 0)
        GECODE_REWRITE(*this,(Rel::Eq<View0,View2>::post(home(*this),x0,x2)));

    } while(modified);

    if (shared(x0,x1,x2)) {
      return (x0ass && x1ass && x2ass) ? home.ES_SUBSUMED(*this) : ES_NOFIX;
    } else {
      if (x0ass && x1ass && x2ass)
        return home.ES_SUBSUMED(*this);
      if (x0ass != x0.assigned() ||
          x1ass != x1.assigned() ||
          x2ass != x2.assigned()) {
        return ES_NOFIX;
      } else {
         return ES_FIX;
      }
    }
  }
Esempio n. 22
0
  ExecStatus
  Mult<View>::propagate(Space& home, const ModEventDelta&) {
    Rounding r;
    if (pos(x0)) {
      if (pos(x1) || pos(x2)) goto rewrite_ppp;
      if (neg(x1) || neg(x2)) goto rewrite_pnn;
      goto prop_pxx;
    }
    if (neg(x0)) {
      if (neg(x1) || pos(x2)) goto rewrite_nnp;
      if (pos(x1) || neg(x2)) goto rewrite_npn;
      goto prop_nxx;
    }
    if (pos(x1)) {
      if (pos(x2)) goto rewrite_ppp;
      if (neg(x2)) goto rewrite_npn;
      goto prop_xpx;
    }
    if (neg(x1)) {
      if (pos(x2)) goto rewrite_nnp;
      if (neg(x2)) goto rewrite_pnn;
      goto prop_xnx;
    }

    assert(any(x0) && any(x1));
    GECODE_ME_CHECK(x2.lq(home,std::max(r.mul_up(x0.max(),x1.max()),
                                        r.mul_up(x0.min(),x1.min()))));
    GECODE_ME_CHECK(x2.gq(home,std::min(r.mul_down(x0.min(),x1.max()),
                                        r.mul_down(x0.max(),x1.min()))));

    if (pos(x2)) {
      if (r.div_up(x2.min(),x1.min()) < x0.min())
        GECODE_ME_CHECK(x0.gq(home,0));
      if (r.div_up(x2.min(),x0.min()) < x1.min())
        GECODE_ME_CHECK(x1.gq(home,0));
    }
    if (neg(x2)) {
      if (r.div_up(x2.max(),x1.max()) < x0.min())
        GECODE_ME_CHECK(x0.gq(home,0));
      if (r.div_up(x2.max(),x0.max()) < x1.min())
        GECODE_ME_CHECK(x1.gq(home,0));
    }

    if (x0.assigned()) {
      assert((x0.val() == 0.0) && (x2.val() == 0.0));
      return home.ES_SUBSUMED(*this);
    }

    if (x1.assigned()) {
      assert((x1.val() == 0.0) && (x2.val() == 0.0));
      return home.ES_SUBSUMED(*this);
    }

    return ES_NOFIX;

  prop_xpx:
    std::swap(x0,x1);
  prop_pxx:
    assert(pos(x0) && any(x1) && any(x2));

    GECODE_ME_CHECK(x2.lq(home,r.mul_up(x0.max(),x1.max())));
    GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.max(),x1.min())));

    if (pos(x2)) goto rewrite_ppp;
    if (neg(x2)) goto rewrite_pnn;

    GECODE_ME_CHECK(x1.lq(home,r.div_up(x2.max(),x0.min())));
    GECODE_ME_CHECK(x1.gq(home,r.div_down(x2.min(),x0.min())));

    if (x0.assigned() && x1.assigned()) {
      GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val()));
      return home.ES_SUBSUMED(*this);
    }

    return ES_NOFIX;

  prop_xnx:
    std::swap(x0,x1);
  prop_nxx:
    assert(neg(x0) && any(x1) && any(x2));

    GECODE_ME_CHECK(x2.lq(home,r.mul_up(x0.min(),x1.min())));
    GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.min(),x1.max())));

    if (pos(x2)) goto rewrite_nnp;
    if (neg(x2)) goto rewrite_npn;

    if (x0.max() != 0.0) {
      GECODE_ME_CHECK(x1.lq(home,r.div_up(x2.min(),x0.max())));
      GECODE_ME_CHECK(x1.gq(home,r.div_down(x2.max(),x0.max())));
    }

    if (x0.assigned() && x1.assigned()) {
      GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val()));
      return home.ES_SUBSUMED(*this);
    }

    return ES_NOFIX;

  rewrite_ppp:
    GECODE_REWRITE(*this,(MultPlus<FloatView,FloatView,FloatView>
                         ::post(home(*this),x0,x1,x2)));
  rewrite_nnp:
    GECODE_REWRITE(*this,(MultPlus<MinusView,MinusView,FloatView>
                         ::post(home(*this),MinusView(x0),MinusView(x1),x2)));
  rewrite_pnn:
    std::swap(x0,x1);
  rewrite_npn:
    GECODE_REWRITE(*this,(MultPlus<MinusView,FloatView,MinusView>
                         ::post(home(*this),MinusView(x0),x1,MinusView(x2))));
  }