예제 #1
0
 ExecStatus
 Card<View>::propagate(Space& home, const ModEventDelta&) {
  int x1min, x1max;
  do {
    x1min = x1.min();
    x1max = x1.max();
    GECODE_ME_CHECK(x0.cardMin(home,static_cast<unsigned int>(x1min)));
    GECODE_ME_CHECK(x0.cardMax(home,static_cast<unsigned int>(x1max)));
    GECODE_ME_CHECK(x1.gq(home,static_cast<int>(x0.cardMin())));
    GECODE_ME_CHECK(x1.lq(home,static_cast<int>(x0.cardMax())));
  } while (x1.min() > x1min || x1.max() < x1max);
  if (x1.assigned())
    return home.ES_SUBSUMED(*this);
  return ES_FIX;
 }
예제 #2
0
파일: eq.hpp 프로젝트: Gecode/gecode
  ExecStatus
  NaryEq<View>::propagate(Space& home, const ModEventDelta& med) {
    assert(x.size() > 2);
    if (View::me(med) == ME_FLOAT_VAL) {
      // One of the variables is assigned
      for (int i = 0; ; i++)
        if (x[i].assigned()) {
          FloatVal n = x[i].val();
          x.move_lst(i);
          for (int j = x.size(); j--; )
            GECODE_ME_CHECK(x[j].eq(home,n));
          return home.ES_SUBSUMED(*this);
        }
      GECODE_NEVER;
    }

    FloatNum mn = x[0].min();
  restart_min:
    for (int i = x.size(); i--; ) {
      GECODE_ME_CHECK(x[i].gq(home,mn));
      if (mn < x[i].min()) {
        mn = x[i].min();
        goto restart_min;
      }
    }
    FloatNum mx = x[0].max();
  restart_max:
    for (int i = x.size(); i--; ) {
      GECODE_ME_CHECK(x[i].lq(home,mx));
      if (mx > x[i].max()) {
        mx = x[i].max();
        goto restart_max;
      }
    }
    return x[0].assigned() ? home.ES_SUBSUMED(*this) : ES_FIX;
  }
예제 #3
0
  ExecStatus
  Seq::propagate(Space& home, const ModEventDelta&) {
    bool modified = false;
    bool assigned;
    do {
      assigned = false; modified = false;
      GECODE_ES_CHECK(propagateSeq(home, modified, assigned, x));
    } while (assigned || modified);

    for (int i=x.size(); i--;)
      if (!x[i].assigned())
        return ES_FIX;

    return home.ES_SUBSUMED(*this);
  }
예제 #4
0
  ExecStatus
  Prop<View>::propagate(Space& home, const ModEventDelta& med) {
    // Add assigned views to value set
    if (View::me(med) == ME_INT_VAL)
      add(home,vs,x);

    // Eliminate views from x
    eliminate(home);
    
    if (x.size() == 0) {
      // y must have values in the value set
      ValSet::Ranges vsr(vs);
      GECODE_ME_CHECK(y.inter_r(home,vsr,false));
      return home.ES_SUBSUMED(*this);
    }

    // Constrain y to union of x and value set
    Region r(home);

    assert(x.size() > 0);
    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;
    }

    GECODE_ME_CHECK(y.inter_r(home,u,false));

    // Check whether all values in y are already in the value set
    if (vs.subset(y))
      return home.ES_SUBSUMED(*this);

    return ES_FIX;
  }
예제 #5
0
  ExecStatus
  LqInt<VY>::propagate(Space& home, const ModEventDelta& med) {
    // Add assigned views to value set
    if (IntView::me(med) == ME_INT_VAL)
      add(home);

    GECODE_ME_CHECK(y.gq(home, vs.size()));

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

    // All values must be in the value set
    if (y.max() == vs.size())
      return all_in_valset(home);

    if (x.size() + vs.size() <= y.min())
      return home.ES_SUBSUMED(*this);
      
    // Compute positions of disjoint views
    Region r(home);
    int* dis; int n_dis;
    disjoint(home,r,dis,n_dis);

    // Some views might have been eliminated as they are subsumed
    if (x.size() == 0)
      return home.ES_SUBSUMED(*this);

    // No lower bound pruning possible
    if (n_dis == 0)
      return ES_NOFIX;

    // Do lower bound-based pruning
    GECODE_ES_CHECK(prune_lower(home,dis,n_dis));

    return ES_NOFIX;
  }
예제 #6
0
  ExecStatus
  ChannelBool<View>::propagate(Space& home, const ModEventDelta&) {
    running = true;
    if (zeros.size() > 0) {
      BndSetRanges zi(zeros);
      GECODE_ME_CHECK(y.excludeI(home, zi));
      zeros.init(home);
    }
    if (ones.size() > 0) {
      BndSetRanges oi(ones);
      GECODE_ME_CHECK(y.includeI(home, oi));
      ones.init(home);
    }
    running = false;

    if (delta.glbMin() != 1 || delta.glbMax() != 0) {
      if (!delta.glbAny()) {
        for (int i=delta.glbMin(); i<=delta.glbMax(); i++)
          GECODE_ME_CHECK(x[i].one(home));
      } else {
        GlbRanges<View> glb(y);
        for (Iter::Ranges::ToValues<GlbRanges<View> > gv(glb); gv(); ++gv) {
          GECODE_ME_CHECK(x[gv.val()].one(home));
        }
      }
    }
    if (delta.lubMin() != 1 || delta.lubMax() != 0) {
      if (!delta.lubAny()) {
        for (int i=delta.lubMin(); i<=delta.lubMax(); i++)
          GECODE_ME_CHECK(x[i].zero(home));
      } else {
        int cur = 0;
        for (LubRanges<View> lub(y); lub(); ++lub) {
          for (; cur < lub.min(); cur++) {
            GECODE_ME_CHECK(x[cur].zero(home));
          }
          cur = lub.max() + 1;
        }
        for (; cur < x.size(); cur++) {
          GECODE_ME_CHECK(x[cur].zero(home));
        }
      }
    }

    new (&delta) SetDelta();

    return y.assigned() ? home.ES_SUBSUMED(*this) : ES_FIX;
  }
예제 #7
0
파일: mult.hpp 프로젝트: kenhys/gecode
 ExecStatus
 Mult<A,B,C>::propagate(Space& home, const ModEventDelta&) {
   GECODE_ME_CHECK(x2.eq(home,x0.domain() * x1.domain()));
   if ( x2.assigned() && (x2.val() == 0) )
   {
     if (x0.zero_in() || x1.zero_in())
     {
        return ES_FIX;
     } else {
        return ES_FAILED;
     }
   }
   if (!x1.assigned() || (x1.val() != 0)) GECODE_ME_CHECK(x0.eq(home,x2.domain() / x1.domain()));
   if (!x0.assigned() || (x0.val() != 0)) GECODE_ME_CHECK(x1.eq(home,x2.domain() / x0.domain()));
   return (x0.assigned() && x1.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
 }
예제 #8
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;
  }
예제 #9
0
파일: purge.hpp 프로젝트: Gecode/gecode
  ExecStatus
  purge(Space& home, Propagator& p, TaskArray<OptTask>& t, Cap c) {
    int n=t.size();
    for (int i=n; i--; )
      if (t[i].excluded()) {
        t[i].cancel(home,p,PL::pc); t[i]=t[--n];
      }
    t.size(n);
    if (t.size() == 1) {
      if (t[0].mandatory())
        GECODE_ME_CHECK(c.gq(home, t[0].c()));
      else if (c.min() < t[0].c())
        return ES_OK;
    }

    return (t.size() < 2) ? home.ES_SUBSUMED(p) : ES_OK;
  }
예제 #10
0
 ExecStatus
 LinkSingle::propagate(Space& home, const ModEventDelta&) {
   if (x0.zero()) {
     GECODE_ME_CHECK(x1.eq(home,0));
   } else if (x0.one()) {
     GECODE_ME_CHECK(x1.eq(home,1));
   } else {
     assert(x0.none() && x1.assigned());
     if (x1.val() == 0) {
       GECODE_ME_CHECK(x0.zero_none(home));
     } else {
       assert(x1.val() == 1);
       GECODE_ME_CHECK(x0.one_none(home));
     }
   }
   return home.ES_SUBSUMED(*this);
 }
예제 #11
0
파일: eq.hpp 프로젝트: akiernan/gecode
  ExecStatus
  Eq<View0,View1>::propagate(Space& home, const ModEventDelta& med) {

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

    Region r(home);

    if (testSetEventLB(me0,me1)) {
      GlbRanges<View0> x0lb(x0);
      GlbRanges<View1> x1lb(x1);
      Iter::Ranges::Union<GlbRanges<View0>,GlbRanges<View1> > lbu(x0lb,x1lb);
      Iter::Ranges::Cache<Iter::Ranges::Union
        <GlbRanges<View0>, GlbRanges<View1> > > lbuc(r,lbu);
      GECODE_ME_CHECK(x0.includeI(home,lbuc));
      lbuc.reset();
      GECODE_ME_CHECK(x1.includeI(home,lbuc));
    }

    if (testSetEventUB(me0,me1)) {
      LubRanges<View0> x0ub(x0);
      LubRanges<View1> x1ub(x1);
      Iter::Ranges::Inter<LubRanges<View0>,LubRanges<View1> > ubi(x0ub,x1ub);
      Iter::Ranges::Cache<Iter::Ranges::Inter
        <LubRanges<View0>,LubRanges<View1> > > ubic(r,ubi);
      GECODE_ME_CHECK(x0.intersectI(home,ubic));
      ubic.reset();
      GECODE_ME_CHECK(x1.intersectI(home,ubic));
    }

    if (testSetEventCard(me0,me1) ) {
      unsigned int max = std::min(x0.cardMax(),x1.cardMax());
      unsigned int min = std::max(x0.cardMin(),x1.cardMin());
      GECODE_ME_CHECK ( x0.cardMax(home,max) );
      GECODE_ME_CHECK ( x1.cardMax(home,max) );
      GECODE_ME_CHECK ( x0.cardMin(home,min) );
      GECODE_ME_CHECK ( x1.cardMin(home,min) );
    }

    if (x0.assigned()) {
      assert (x1.assigned());
      return home.ES_SUBSUMED(*this);
    }
    return shared(x0,x1) ? ES_NOFIX : ES_FIX;
  }
예제 #12
0
 forceinline ExecStatus
 prop_mult_dom(Space& home, Propagator& p, View x0, View x1, View x2) {
   Region r(home);
   SupportValues<View,Region> s0(r,x0), s1(r,x1), s2(r,x2);
   while (s0()) {
     while (s1()) {
       if (s2.support(mll(s0.val(),s1.val()))) {
         s0.support(); s1.support();
       }
       ++s1;
     }
     s1.reset(); ++s0;
   }
   GECODE_ME_CHECK(s0.tell(home));
   GECODE_ME_CHECK(s1.tell(home));
   GECODE_ME_CHECK(s2.tell(home));
   return x0.assigned() && x1.assigned() ? home.ES_SUBSUMED(p) : ES_FIX;
 }
예제 #13
0
파일: channel-int.hpp 프로젝트: lquan/CSAI
  ExecStatus
  ChannelInt<View>::propagate(Space& home, const ModEventDelta&) {
    int assigned = 0;
    for (int v=xs.size(); v--;) {
      if (xs[v].assigned()) {
        assigned += 1;
        for (int i=ys.size(); i--;) {
          if (i==xs[v].val()) {
            GECODE_ME_CHECK(ys[i].include(home, v));
          }
          else {
            GECODE_ME_CHECK(ys[i].exclude(home, v));
          }
        }
      } else {

        for (int i=ys.size(); i--;) {
          if (ys[i].notContains(v)) {
            GECODE_ME_CHECK(xs[v].nq(home, i));
          }
          if (ys[i].contains(v)) {
            GECODE_ME_CHECK(xs[v].eq(home, i));
          }
        }

        Gecode::Int::ViewRanges<Gecode::Int::IntView> xsv(xs[v]);
        int min = 0;
        for (; xsv(); ++xsv) {
          for (int i=min; i<xsv.min(); i++) {
            GECODE_ME_CHECK(ys[i].exclude(home, v));
          }
          min = xsv.max() + 1;
        }
        for (int i=min; i<ys.size(); i++) {
          GECODE_ME_CHECK(ys[i].exclude(home, v));
        }

      }
    }

    return (assigned==xs.size()) ? home.ES_SUBSUMED(*this) : ES_NOFIX;
  }
예제 #14
0
파일: pow-nroot.hpp 프로젝트: kenhys/gecode
 ExecStatus
 Pow<A,B>::propagate(Space& home, const ModEventDelta&) {
   GECODE_ME_CHECK(x1.eq(home,pow(x0.domain(),m_n)));
   if ((m_n % 2) == 0)
   {
     if (x0.min() >= 0)
       GECODE_ME_CHECK(x0.eq(home,nth_root(x1.domain(),m_n)));
     else if (x0.max() <= 0)
       GECODE_ME_CHECK(x0.eq(home,-nth_root(x1.domain(),m_n)));
     else
       GECODE_ME_CHECK(x0.eq(home,
                             hull(
                                 nth_root(x1.domain(),m_n),
                                 -nth_root(x1.domain(),m_n)
                             )
                       ));
   } else
     GECODE_ME_CHECK(x0.eq(home,nth_root(x1.domain(),m_n)));
   return x0.assigned() ? home.ES_SUBSUMED(*this) : ES_FIX;
 }
예제 #15
0
파일: eq.hpp 프로젝트: Gecode/gecode
 ExecStatus
 Eq<View0,View1>::propagate(Space& home, const ModEventDelta&) {
   if (x0.assigned()) {
     GECODE_ME_CHECK(x1.eq(home,x0.val()));
   } else if (x1.assigned()) {
     GECODE_ME_CHECK(x0.eq(home,x1.val()));
   } else {
     do {
       GECODE_ME_CHECK(x0.gq(home,x1.min()));
       GECODE_ME_CHECK(x1.gq(home,x0.min()));
     } while (x0.min() != x1.min());
     do {
       GECODE_ME_CHECK(x0.lq(home,x1.max()));
       GECODE_ME_CHECK(x1.lq(home,x0.max()));
     } while (x0.max() != x1.max());
     if (!x0.assigned())
       return ES_FIX;
   }
   assert(x0.assigned() && x1.assigned());
   return home.ES_SUBSUMED(*this);
 }
예제 #16
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;
 }
예제 #17
0
파일: eq.hpp 프로젝트: Gecode/gecode
 ExecStatus
 ReEqFloat<View,CtrlView,rm>::propagate(Space& home, const ModEventDelta&) {
   if (b.one()) {
     if (rm != RM_PMI)
       GECODE_ME_CHECK(x0.eq(home,c));
   } else {
     switch (rtest_eq(x0,c)) {
     case RT_TRUE:
       if (rm != RM_IMP)
         GECODE_ME_CHECK(b.one(home));
       break;
     case RT_FALSE:
       if (rm != RM_PMI)
         GECODE_ME_CHECK(b.zero(home));
       break;
     case RT_MAYBE:
       return ES_FIX;
     default: GECODE_NEVER;
     }
   }
   return home.ES_SUBSUMED(*this);
 }
예제 #18
0
파일: int.hpp 프로젝트: Wushaowei001/vcp
  ExecStatus
  ChannelInt<View>::propagate(Space& home, const ModEventDelta&) {
    int assigned = 0;
    for (int v=xs.size(); v--;) {
      if (xs[v].assigned()) {
        assigned++;
        if (xs[v].modified())
          GECODE_ME_CHECK(ys[xs[v].val()].include(home,v));
      }
      if (xs[v].modified()) {
        Gecode::Int::ViewDiffRanges<Gecode::Int::IntView> d(xs[v]);
        Iter::Ranges::ToValues<Gecode::Int::ViewDiffRanges<
          Gecode::Int::IntView> > dv(d);
        for (; dv(); ++dv)
          GECODE_ME_CHECK(ys[dv.val()].exclude(home, v));
        xs[v].cache(home);
      }
    }

    for (int i=ys.size(); i--;) {
      if (ys[i].glbModified()) {
        GlbDiffRanges<View> yilb(ys[i]);
        Iter::Ranges::ToValues<GlbDiffRanges<View> > dv(yilb);
        for (;dv();++dv)
          GECODE_ME_CHECK(xs[dv.val()].eq(home,i));
        ys[i].cacheGlb(home);
      }
      if (ys[i].lubModified()) {
        LubDiffRanges<View> yiub(ys[i]);
        Iter::Ranges::ToValues<LubDiffRanges<View> > dv(yiub);
        for (;dv();++dv)
          GECODE_ME_CHECK(xs[dv.val()].nq(home,i));
        ys[i].cacheLub(home);
      }
    }

    return (assigned==xs.size()) ? home.ES_SUBSUMED(*this) : ES_NOFIX;
  }
  forceinline ExecStatus
  notlast(Space& home, Propagator& p, TaskViewArray<OptTaskView>& t) {
    sort<OptTaskView,STO_LCT,true>(t);

    Region r(home);

    OmegaTree<OptTaskView> o(r,t);
    ManTaskViewIter<OptTaskView,STO_LST,true> q(r,t);
    int* lct = r.alloc<int>(t.size());

    for (int i=t.size(); i--; )
      lct[i] = t[i].lct();

    for (int i=0; i<t.size(); i++) {
      int j = -1;
      while (q() && (t[i].lct() > t[q.task()].lst())) {
        if ((j >= 0) && (o.ect() > t[q.task()].lst()))
          lct[q.task()] = std::min(lct[q.task()],t[j].lst());
        j = q.task();
        o.insert(j); ++q;
      }
      if ((j >= 0) && (o.ect(i) > t[i].lst()))
        lct[i] = std::min(lct[i],t[j].lst());
    }

    int n = t.size();
    for (int i=n; i--; )
      if (t[i].mandatory()) {
        GECODE_ME_CHECK(t[i].lct(home,lct[i]));
      } else if (lct[i] < t[i].ect()) {
        //        GECODE_ME_CHECK(t[i].excluded(home));
        //        t[i].cancel(home,p); t[i]=t[--n];
      }
    t.size(n);

    return (t.size() < 2) ? home.ES_SUBSUMED(p) : ES_OK;
  }
예제 #20
0
 ExecStatus
 MultZeroOne<View,pc>::propagate(Space& home, const ModEventDelta&) {
   switch (equal(x0,0)) {
   case RT_FALSE:
     GECODE_ME_CHECK(x1.eq(home,1));
     break;
   case RT_TRUE:
     break;
   case RT_MAYBE:
     switch (equal(x1,1)) {
     case RT_FALSE:
       GECODE_ME_CHECK(x0.eq(home,0));
       break;
     case RT_TRUE:
       break;
     case RT_MAYBE:
       return ES_FIX;
     default: GECODE_NEVER;
     }
     break;
   default: GECODE_NEVER;
   }
   return home.ES_SUBSUMED(*this);
 }
예제 #21
0
파일: tanatan.hpp 프로젝트: kenhys/gecode
 ExecStatus
 ATan<A,B>::propagate(Space& home, const ModEventDelta&) {
   GECODE_ME_CHECK(x1.eq(home,atan(x0.domain())));
   GECODE_ME_CHECK(x0.eq(home,tan(x1.domain())));
   return (x0.assigned() && x1.assigned()) ? home.ES_SUBSUMED(*this) : ES_FIX;
 }
예제 #22
0
파일: int-bin.hpp 프로젝트: Gecode/gecode
 ExecStatus
 GqBin<Val,A,B>::propagate(Space& home, const ModEventDelta&) {
   GECODE_ME_CHECK(x0.gq(home,c-x1.max()));
   GECODE_ME_CHECK(x1.gq(home,c-x0.max()));
   return (x0.min()+x1.min() >= c) ? home.ES_SUBSUMED(*this) : ES_FIX;
 }
예제 #23
0
파일: union.hpp 프로젝트: akiernan/gecode
  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;
  }
예제 #24
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;
  }
예제 #25
0
  ExecStatus
  Match<View>::propagate(Space& home, const ModEventDelta&) {

    int xs_size = xs.size();

    bool loopFlag;

    do {
      loopFlag = false;

      // Order int vars in xs
      GECODE_ME_CHECK(xs[0].gq(home,x0.lubMin()));
      for (int i=xs_size-1; i--; ) {
        GECODE_ME_CHECK_MODIFIED(loopFlag, xs[i+1].gq(home,xs[i].min() + 1));
      }

      GECODE_ME_CHECK_MODIFIED(loopFlag, xs[xs_size-1].lq(home,x0.lubMax()));
      for (int i=xs_size-2; i--; ) {
        GECODE_ME_CHECK_MODIFIED(loopFlag, xs[i].lq(home,xs[i+1].max() - 1));
      }

      // if y from xs is assigned, add to glb(x0)
      for (int i=xs_size; i--; ) {
        if (xs[i].assigned()) {
          GECODE_ME_CHECK_MODIFIED(loopFlag, x0.include(home,xs[i].val()));
        }
      }

      // intersect every y in xs with lub(x0)
      for (int i=xs_size; i--; ) {
        LubRanges<View> ub(x0);
        GECODE_ME_CHECK_MODIFIED(loopFlag, xs[i].inter_r(home,ub,false));
      }

      // remove gaps between vars in xs from lub(x0)
      GECODE_ME_CHECK_MODIFIED(loopFlag,
                        x0.exclude(home,Limits::min,xs[0].min()-1));
      GECODE_ME_CHECK_MODIFIED(loopFlag,
                        x0.exclude(home,xs[xs_size-1].max()+1,
                                   Limits::max));

      for (int i=xs_size-1; i--; ) {
        int start = xs[i].max() + 1;
        int end   = xs[i+1].min() - 1;
        if (start<=end) {
          GECODE_ME_CHECK_MODIFIED(loopFlag, x0.exclude(home,start,end));
        }
      }

      // try to assign vars in xs from glb(x0)
      if (x0.glbSize()>0) {

        LubRanges<View> ub(x0);
        Iter::Ranges::ToValues<LubRanges<View> > ubv(ub);
        GlbRanges<View> lb(x0);
        Iter::Ranges::ToValues<GlbRanges<View> > lbv(lb);

        int i=0;
        for (; ubv() && lbv() && ubv.val()==lbv.val();
            ++ubv, ++lbv, i++) {
          GECODE_ME_CHECK_MODIFIED(loopFlag, xs[i].eq(home,lbv.val()));
        }

        if (i<xs_size-1 && x0.lubMax()==x0.glbMax()) {
          LubRanges<View> lbx0(x0);
          GlbRanges<View> ubx0(x0);
          Iter::Ranges::Inter<LubRanges<View>,GlbRanges<View> >
            inter(lbx0, ubx0);

          int to = x0.glbMax();
          int from = to;
          while (inter()) {
            from = inter.min();
            ++inter;
          }

          int i=xs_size-1;
          for (int j=to; j>=from;j--,i--) {
            GECODE_ME_CHECK_MODIFIED(loopFlag, xs[i].eq(home,j));
          }
        }
      }

    } while (loopFlag);

    for (int i=xs_size; i--; )
      if (!xs[i].assigned())
        return ES_FIX;
    return home.ES_SUBSUMED(*this);
  }
예제 #26
0
  ExecStatus
  SuperOfInter<View0,View1,View2>::propagate(Space& home, const ModEventDelta& med) {

    bool allassigned = x0.assigned() && x1.assigned() && x2.assigned();

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

    bool modified = false;

    do {
      // glb(x2) >= glb(x0) ^ glb(x1)
      if ( modified || Rel::testSetEventLB(me0,me1)) {
        GlbRanges<View0> lb0(x0);
        GlbRanges<View1> lb1(x1);
        Iter::Ranges::Inter<GlbRanges<View0>,GlbRanges<View1> >
          is(lb0, lb1);

        GECODE_ME_CHECK_MODIFIED(modified,x2.includeI(home,is));
      }

      // lub(x0) -= glb(x1)-lub(x2)
      // lub(x1) -= glb(x0)-lub(x2)
      if ( modified || Rel::testSetEventAnyB(me0,me1,me2)) {
         modified = false;
        GlbRanges<View1> lb12(x1);
        LubRanges<View2> ub22(x2);
        Iter::Ranges::Diff<GlbRanges<View1>, LubRanges<View2> >
          diff1(lb12, ub22);

        GECODE_ME_CHECK_MODIFIED(modified, x0.excludeI(home,diff1));

        GlbRanges<View0> lb01(x0);
        LubRanges<View2> ub23(x2);
        Iter::Ranges::Diff<GlbRanges<View0>, LubRanges<View2> >
          diff2(lb01, ub23);

        GECODE_ME_CHECK_MODIFIED(modified, x1.excludeI(home,diff2));
      } else {
         modified = false;
      }

      // Cardinality propagation
      if ( modified ||
            Rel::testSetEventCard(me0,me1,me2) ||
           Rel::testSetEventUB(me0,me1)
           ) {

        LubRanges<View0> ub0(x0);
        LubRanges<View1> ub1(x1);
        Iter::Ranges::Union<LubRanges<View0>, LubRanges<View1> > u(ub0,ub1);

        unsigned int m = Iter::Ranges::size(u);

        if (m < x0.cardMin() + x1.cardMin()) {
          GECODE_ME_CHECK_MODIFIED(modified,
                            x2.cardMin( home,
                                        x0.cardMin()+x1.cardMin() - m ) );
        }
        if (m + x2.cardMax() > x1.cardMin()) {
          GECODE_ME_CHECK_MODIFIED(modified,
                            x0.cardMax( home,
                                        m+x2.cardMax()-x1.cardMin() )  );
        }
        if (m + x2.cardMax() > x0.cardMin()) {
          GECODE_ME_CHECK_MODIFIED(modified,
                            x1.cardMax( home,
                                        m+x2.cardMax()-x0.cardMin() )  );
        }
      }
    } while (modified);


    if (shared(x0,x1,x2)) {
      if (allassigned) {
        return home.ES_SUBSUMED(*this);
      } else {
        return ES_NOFIX;
      }
    } else {
      if (x0.assigned() + x1.assigned() + x2.assigned() >= 2) {
         return home.ES_SUBSUMED(*this);
      } else {
        return ES_FIX;
      }
    }

  }
예제 #27
0
  ExecStatus
  Eqv<BVA,BVB,BVC>::propagate(Space& home, const ModEventDelta&) {
#define GECODE_INT_STATUS(S0,S1,S2) \
  ((BVA::S0<<(2*BVA::BITS))|(BVB::S1<<(1*BVB::BITS))|(BVC::S2<<(0*BVC::BITS)))
    switch ((x0.status() << (2*BVA::BITS)) | (x1.status() << (1*BVB::BITS)) |
            (x2.status() << (0*BVC::BITS))) {
    case GECODE_INT_STATUS(NONE,NONE,NONE):
      GECODE_NEVER;
    case GECODE_INT_STATUS(NONE,NONE,ZERO):
    case GECODE_INT_STATUS(NONE,NONE,ONE):
    case GECODE_INT_STATUS(NONE,ZERO,NONE):
      return ES_FIX;
    case GECODE_INT_STATUS(NONE,ZERO,ZERO):
      GECODE_ME_CHECK(x0.one_none(home)); break;
    case GECODE_INT_STATUS(NONE,ZERO,ONE):
      GECODE_ME_CHECK(x0.zero_none(home)); break;
    case GECODE_INT_STATUS(NONE,ONE,NONE):
      return ES_FIX;
    case GECODE_INT_STATUS(NONE,ONE,ZERO):
      GECODE_ME_CHECK(x0.zero_none(home)); break;
    case GECODE_INT_STATUS(NONE,ONE,ONE):
      GECODE_ME_CHECK(x0.one_none(home)); break;
    case GECODE_INT_STATUS(ZERO,NONE,NONE):
      return ES_FIX;
    case GECODE_INT_STATUS(ZERO,NONE,ZERO):
      GECODE_ME_CHECK(x1.one_none(home)); break;
    case GECODE_INT_STATUS(ZERO,NONE,ONE):
      GECODE_ME_CHECK(x1.zero_none(home)); break;
    case GECODE_INT_STATUS(ZERO,ZERO,NONE):
      GECODE_ME_CHECK(x2.one_none(home)); break;
    case GECODE_INT_STATUS(ZERO,ZERO,ZERO):
      return ES_FAILED;
    case GECODE_INT_STATUS(ZERO,ZERO,ONE):
      break;
    case GECODE_INT_STATUS(ZERO,ONE,NONE):
      GECODE_ME_CHECK(x2.zero_none(home)); break;
    case GECODE_INT_STATUS(ZERO,ONE,ZERO):
      break;
    case GECODE_INT_STATUS(ZERO,ONE,ONE):
      return ES_FAILED;
    case GECODE_INT_STATUS(ONE,NONE,NONE):
      return ES_FIX;
    case GECODE_INT_STATUS(ONE,NONE,ZERO):
      GECODE_ME_CHECK(x1.zero_none(home)); break;
    case GECODE_INT_STATUS(ONE,NONE,ONE):
      GECODE_ME_CHECK(x1.one_none(home)); break;
    case GECODE_INT_STATUS(ONE,ZERO,NONE):
      GECODE_ME_CHECK(x2.zero_none(home)); break;
    case GECODE_INT_STATUS(ONE,ZERO,ZERO):
      break;
    case GECODE_INT_STATUS(ONE,ZERO,ONE):
      return ES_FAILED;
    case GECODE_INT_STATUS(ONE,ONE,NONE):
      GECODE_ME_CHECK(x2.one_none(home)); break;
    case GECODE_INT_STATUS(ONE,ONE,ZERO):
      return ES_FAILED;
    case GECODE_INT_STATUS(ONE,ONE,ONE):
      break;
    default:
      GECODE_NEVER;
    }
    return home.ES_SUBSUMED(*this);
#undef GECODE_INT_STATUS
  }
예제 #28
0
파일: int-dom.hpp 프로젝트: MGKhKhD/easy-IP
  ExecStatus
  DomEq<Val,View>::propagate(Space& home, const ModEventDelta& med) {
    if (View::me(med) != ME_INT_DOM) {
      ExecStatus es = prop_bnd<Val,View,View>(home,med,*this,x,y,c);
      GECODE_ES_CHECK(es);
      return home.ES_FIX_PARTIAL(*this,View::med(ME_INT_DOM));
    }

    // Value of equation for partial assignment
    Val d = -c;

    int n = x.size();
    int m = y.size();

    Region r(home);
    // Create support-base iterators
    PosSupportIter<Val>* xp = r.alloc<PosSupportIter<Val> >(n);
    NegSupportIter<Val>* yp = r.alloc<NegSupportIter<Val> >(m);

    // Initialize views for assignments
    {
      Val l = 0;
      Val u = 0;
      for (int j=m; j--; ) {
        yp[j].init(r,-y[j].scale(),y[j].base(),l,u);
        l += y[j].max(); u += y[j].min();
      }
      for (int i=n; i--; ) {
        xp[i].init(r,x[i].scale(),x[i].base(),l,u);
        l -= x[i].min(); u -= x[i].max();
      }
    }

    // Collect support information by iterating assignments
    {
      // Force reset of all iterators in first round
      int i = 0;
      int j = 0;

    next_i:
      // Reset all iterators for positive views and update d
      while (i<n) {
        if (!xp[i].reset(d)) goto prev_i;
        i++;
      }
    next_j:
      // Reset all iterators for negative views and update d
      while (j<m) {
        if (!yp[j].reset(d)) goto prev_j;
        j++;
      }
      // Check whether current assignment is solution
      if (d == 0) {
        // Record support
        for (int is=n; is--; ) xp[is].support();
        for (int js=m; js--; ) yp[js].support();
      }
    prev_j:
      // Try iterating to next assignment: negative views
      while (j>0) {
        if (yp[j-1].adjust(d)) goto next_j;
        j--;
      }
    prev_i:
      // Try iterating to next assignment: positive views
      while (i>0) {
        if (xp[i-1].adjust(d)) goto next_i;
        i--;
      }
    }

    // Tell back new variable domains
    bool assigned = true;
    for (int i=n; i--; ) {
      GECODE_ME_CHECK(xp[i].tell(home));
      if (!x[i].assigned())
        assigned = false;
    }
    for (int j=m; j--; ) {
      GECODE_ME_CHECK(yp[j].tell(home));
      if (!y[j].assigned())
        assigned = false;
    }
    if (assigned)
      return home.ES_SUBSUMED(*this);
    return ES_FIX;
  }
예제 #29
0
파일: union.hpp 프로젝트: Gecode/gecode
  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;
      }
    }
  }
예제 #30
0
  ExecStatus
  LinkMulti::propagate(Space& home, const ModEventDelta& med) {
    int n = x.size();

    // Always maintain the invariant that y lies inside the x-array
    assert((y.min()-o >= 0) && (y.max()-o < n));

    if (y.assigned()) {
      status = S_RUN;
      int j=y.val()-o;
      GECODE_ME_CHECK(x[j].one(home));
      for (int i=0; i<j; i++)
        GECODE_ME_CHECK(x[i].zero(home));
      for (int i=j+1; i<n; i++)
        GECODE_ME_CHECK(x[i].zero(home));
      return home.ES_SUBSUMED(*this);
    }

    // Check whether there is a one
    if (status == S_ONE) {
      status = S_RUN;
      for (int i=0; true; i++)
        if (x[i].one()) {
          for (int j=0; j<i; j++)
            GECODE_ME_CHECK(x[j].zero(home));
          for (int j=i+1; j<n; j++)
            GECODE_ME_CHECK(x[j].zero(home));
          GECODE_ME_CHECK(y.eq(home,i+o));
          return home.ES_SUBSUMED(*this);
        }
      GECODE_NEVER;
    }

    status = S_RUN;

  redo:

    // Assign all Boolean views to zero that are outside bounds
    {
      int min=y.min()-o;
      for (int i=0; i<min; i++)
        GECODE_ME_CHECK(x[i].zero(home));
      x.drop_fst(min); o += min; n = x.size();

      int max=y.max()-o;
      for (int i=max+1; i<n; i++)
        GECODE_ME_CHECK(x[i].zero(home));
      x.drop_lst(max); n = x.size();
    }

    {
      // Remove zeros on the left
      int i=0;
      while ((i < n) && x[i].zero()) i++;
      if (i >= n)
        return ES_FAILED;
      x.drop_fst(i); o += i; n = x.size();
    }

    {
      // Remove zeros on the right
      int i=n-1;
      while ((i >= 0) && x[i].zero()) i--;
      assert(i >= 0);
      x.drop_lst(i); n = x.size();
    }

    assert(n >= 1);

    // Is there only one left?
    if (n == 1) {
      GECODE_ME_CHECK(x[0].one(home));
      GECODE_ME_CHECK(y.eq(home,o));
      return home.ES_SUBSUMED(*this);
    }

    // Update bounds
    GECODE_ME_CHECK(y.gq(home,o));
    GECODE_ME_CHECK(y.lq(home,o+n-1));
    if ((y.min() > o) || (y.max() < o+n-1))
      goto redo;

    assert((n >= 2) && x[0].none() && x[n-1].none());
    assert((y.min()-o == 0) && (y.max()-o == n-1));

    // Propagate from y to Boolean views
    if ((IntView::me(med) == ME_INT_BND) || (IntView::me(med) == ME_INT_DOM)) {
      ViewValues<IntView> v(y);
      int i=0;
      do {
        int j = v.val()-o;
        if (i < j) {
          GECODE_ME_CHECK(x[i].zero(home));
          ++i;
        } else if (i > j) {
          ++v;
        } else {
          assert(i == j);
          ++i; ++v;
        }
      } while (v() && (i < n));
    }

    // Propagate from Boolean views to y
    if (BoolView::me(med) == ME_BOOL_VAL) {
      BoolIter bv(x,o);
      GECODE_ME_CHECK(y.minus_v(home,bv,false));
    }
    status = S_NONE;
    return ES_FIX;
  }