예제 #1
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;
  }
예제 #2
0
  void
  cumulative(Home home, Cap c, const IntVarArgs& s, 
             const IntArgs& p, const IntArgs& u, IntConLevel icl) {
    using namespace Gecode::Int;
    using namespace Gecode::Int::Cumulative;
    if ((s.size() != p.size()) || (s.size() != u.size()))
      throw Int::ArgumentSizeMismatch("Int::cumulative");
    long long int w = 0;
    for (int i=p.size(); i--; ) {
      Limits::nonnegative(p[i],"Int::cumulative");
      Limits::nonnegative(u[i],"Int::cumulative");
      Limits::check(static_cast<long long int>(s[i].max()) + p[i],
                    "Int::cumulative");
      mul_check(p[i],u[i]);
      w += s[i].width();
    }
    mul_check(c.max(),w,s.size());
    if (home.failed()) return;

    int minU = INT_MAX; int minU2 = INT_MAX; int maxU = INT_MIN;
    for (int i=u.size(); i--;) {
      if (u[i] < minU) {
        minU2 = minU;
        minU = u[i];
      } else if (u[i] < minU2)
        minU2 = u[i];
      if (u[i] > maxU)
        maxU = u[i];
    }
    bool disjunctive = 
      (minU > c.max()/2) || (minU2 > c.max()/2 && minU+minU2>c.max());
    if (disjunctive) {
      GECODE_ME_FAIL(c.gq(home,maxU));
      unary(home,s,p,icl);
    } else {
      int nonOptionals = 0;
      for (unsigned int i=u.size(); i--;)
        if (u[i]>0) nonOptionals++;
      TaskArray<ManFixPTask> t(home,nonOptionals);
      int cur = 0;
      for (int i=0; i<s.size(); i++)
        if (u[i]>0)
          t[cur++].init(s[i],p[i],u[i]);
      GECODE_ES_FAIL((ManProp<ManFixPTask,Cap>::post(home,c,t)));
    }
  }
예제 #3
0
 void
 cumulative(Home home, Cap c, const TaskTypeArgs& t,
            const IntVarArgs& s, const IntArgs& p, const IntArgs& u,
            const BoolVarArgs& m, IntConLevel icl) {
   using namespace Gecode::Int;
   using namespace Gecode::Int::Cumulative;
   if ((s.size() != p.size()) || (s.size() != u.size()) ||
       (s.size() != t.size()) || (s.size() != m.size()))
     throw Int::ArgumentSizeMismatch("Int::cumulative");
   long long int w = 0;
   for (int i=p.size(); i--; ) {
     Limits::nonnegative(p[i],"Int::cumulative");
     Limits::nonnegative(u[i],"Int::cumulative");
     Limits::check(static_cast<long long int>(s[i].max()) + p[i],
                   "Int::cumulative");
     mul_check(p[i],u[i]);
     w += s[i].width();
   }
   mul_check(c.max(),w,s.size());
   if (home.failed()) return;
   
   bool allMandatory = true;
   for (int i=m.size(); i--;) {
     if (!m[i].one()) {
       allMandatory = false;
       break;
     }
   }
   if (allMandatory) {
     cumulative(home,c,t,s,p,u,icl);
   } else {
     bool fixp = true;
     for (int i=t.size(); i--;)
       if (t[i] != TT_FIXP) {
         fixp = false; break;
       }
     int nonOptionals = 0;
     for (unsigned int i=u.size(); i--;)
       if (u[i]>0) nonOptionals++;
     if (fixp) {
       TaskArray<OptFixPTask> tasks(home,nonOptionals);
       int cur = 0;
       for (int i=0; i<s.size(); i++)
         if (u[i]>0)
           tasks[cur++].init(s[i],p[i],u[i],m[i]);
       GECODE_ES_FAIL((OptProp<OptFixPTask,Cap>::post(home,c,tasks)));
     } else {
       TaskArray<OptFixPSETask> tasks(home,nonOptionals);
       int cur = 0;
       for (int i=s.size(); i--;)
         if (u[i]>0)
           tasks[cur++].init(t[i],s[i],p[i],u[i],m[i]);
       GECODE_ES_FAIL((OptProp<OptFixPSETask,Cap>::post(home,c,tasks)));
     }
   }
 }
예제 #4
0
 forceinline ExecStatus 
 ManProp<ManTask,Cap>::post(Home home, Cap c, TaskArray<ManTask>& t) {
   // Capacity must be nonnegative
   GECODE_ME_CHECK(c.gq(home, 0));
   // Check that tasks do not overload resource
   for (int i=t.size(); i--; )
     if (t[i].c() > c.max())
       return ES_FAILED;
   if (t.size() == 1)
     GECODE_ME_CHECK(c.gq(home, t[0].c()));
   if (t.size() > 1) {
     if (c.assigned() && c.val()==1) {
       TaskArray<typename TaskTraits<ManTask>::UnaryTask> mt(home,t.size());
       for (int i=t.size(); i--; )
         mt[i]=t[i];
       return Unary::ManProp<typename TaskTraits<ManTask>::UnaryTask>
         ::post(home,mt);
     } else {
       (void) new (home) ManProp<ManTask,Cap>(home,c,t);
     }
   }
   return ES_OK;
 }
예제 #5
0
  void
  cumulative(Home home, Cap c, const IntVarArgs& s, 
             const IntVarArgs& p, const IntVarArgs& e,
             const IntArgs& u, IntConLevel icl) {
    using namespace Gecode::Int;
    using namespace Gecode::Int::Cumulative;
    if ((s.size() != p.size()) || (s.size() != e.size()) ||
        (s.size() != u.size()))
      throw Int::ArgumentSizeMismatch("Int::cumulative");
    long long int w = 0;
    for (int i=p.size(); i--; ) {
      rel(home, p[i], IRT_GQ, 0);
    }
    for (int i=p.size(); i--; ) {
      Limits::nonnegative(u[i],"Int::cumulative");
      Limits::check(static_cast<long long int>(s[i].max()) + p[i].max(),
                    "Int::cumulative");
      mul_check(p[i].max(),u[i]);
      w += s[i].width();
    }
    mul_check(c.max(),w,s.size());
    if (home.failed()) return;

    bool fixP = true;
    for (int i=p.size(); i--;) {
      if (!p[i].assigned()) {
        fixP = false;
        break;
      }
    }
    if (fixP) {
      IntArgs pp(p.size());
      for (int i=p.size(); i--;)
        pp[i] = p[i].val();
      cumulative(home,c,s,pp,u,icl);
    } else {
      int nonOptionals = 0;
      for (unsigned int i=u.size(); i--;)
        if (u[i]>0) nonOptionals++;
      TaskArray<ManFlexTask> t(home,nonOptionals);
      int cur = 0;
      for (int i=0; i<s.size(); i++)
        if (u[i]>0)
          t[cur++].init(s[i],p[i],e[i],u[i]);
      GECODE_ES_FAIL((ManProp<ManFlexTask,Cap>::post(home,c,t)));
    }
  }
예제 #6
0
  void
  cumulative(Home home, Cap c, const IntVarArgs& s, const IntVarArgs& p,
             const IntVarArgs& e, const IntArgs& u, const BoolVarArgs& m, 
             IntConLevel icl) {
    using namespace Gecode::Int;
    using namespace Gecode::Int::Cumulative;
    if ((s.size() != p.size()) || (s.size() != u.size()) ||
        (s.size() != e.size()) || (s.size() != m.size()))
      throw Int::ArgumentSizeMismatch("Int::cumulative");
    for (int i=p.size(); i--; ) {
      rel(home, p[i], IRT_GQ, 0);
    }
    long long int w = 0;
    for (int i=p.size(); i--; ) {
      Limits::nonnegative(u[i],"Int::cumulative");
      Limits::check(static_cast<long long int>(s[i].max()) + p[i].max(),
                    "Int::cumulative");
      mul_check(p[i].max(),u[i]);
      w += s[i].width();
    }
    mul_check(c.max(),w,s.size());
    if (home.failed()) return;

    bool allMandatory = true;
    for (int i=m.size(); i--;) {
      if (!m[i].one()) {
        allMandatory = false;
        break;
      }
    }
    if (allMandatory) {
      cumulative(home,c,s,p,e,u,icl);
    } else {
      int nonOptionals = 0;
      for (unsigned int i=u.size(); i--;)
        if (u[i]>0) nonOptionals++;
      TaskArray<OptFlexTask> t(home,nonOptionals);
      int cur = 0;
      for (int i=s.size(); i--; )
        if (u[i]>0)
          t[cur++].init(s[i],p[i],e[i],u[i],m[i]);
      GECODE_ES_FAIL((OptProp<OptFlexTask,Cap>::post(home,c,t)));
    }
  }
예제 #7
0
forceinline ExecStatus
timetabling(Space& home, Propagator& p, Cap c, TaskArray<Task>& t) {
    int ccur = c.max();
    int cmax = ccur;
    int cmin = ccur;

    // Sort tasks by decreasing capacity
    TaskByDecCap<Task> tbdc;
    Support::quicksort(&t[0], t.size(), tbdc);

    Region r(home);

    bool assigned;
    if (Event* e = Event::events(r,t,assigned)) {
        // Set of current but not required tasks
        Support::BitSet<Region> tasks(r,static_cast<unsigned int>(t.size()));

        // Process events, use ccur as the capacity that is still free
        do {
            // Current time
            int time = e->time();

            // Process events for completion of required part
            for ( ; (e->type() == Event::LRT) && (e->time() == time); e++)
                if (t[e->idx()].mandatory()) {
                    tasks.set(static_cast<unsigned int>(e->idx()));
                    ccur += t[e->idx()].c();
                }
            // Process events for completion of task
            for ( ; (e->type() == Event::LCT) && (e->time() == time); e++)
                tasks.clear(static_cast<unsigned int>(e->idx()));
            // Process events for start of task
            for ( ; (e->type() == Event::EST) && (e->time() == time); e++)
                tasks.set(static_cast<unsigned int>(e->idx()));
            // Process events for zero-length task
            for ( ; (e->type() == Event::ZRO) && (e->time() == time); e++) {
                ccur -= t[e->idx()].c();
                if (ccur < cmin) cmin=ccur;
                if (ccur < 0)
                    return ES_FAILED;
                ccur += t[e->idx()].c();
            }

            // norun start time
            int nrstime = time;
            // Process events for start of required part
            for ( ; (e->type() == Event::ERT) && (e->time() == time); e++)
                if (t[e->idx()].mandatory()) {
                    tasks.clear(static_cast<unsigned int>(e->idx()));
                    ccur -= t[e->idx()].c();
                    if (ccur < cmin) cmin=ccur;
                    nrstime = time+1;
                    if (ccur < 0)
                        return ES_FAILED;
                } else if (t[e->idx()].optional() && (t[e->idx()].c() > ccur)) {
                    GECODE_ME_CHECK(t[e->idx()].excluded(home));
                }

            // Exploit that tasks are sorted according to capacity
            for (Iter::Values::BitSet<Support::BitSet<Region> > j(tasks);
                    j() && (t[j.val()].c() > ccur); ++j)
                // Task j cannot run from zltime to next time - 1
                if (t[j.val()].mandatory())
                    GECODE_ME_CHECK(t[j.val()].norun(home, nrstime, e->time() - 1));
        } while (e->type() != Event::END);

        GECODE_ME_CHECK(c.gq(home,cmax-cmin));
    }

    if (assigned)
        return home.ES_SUBSUMED(p);
    return ES_NOFIX;
}
예제 #8
0
  ExecStatus
  basic(Space& home, bool& subsumed, Cap c, TaskArray<Task>& t) {
    subsumed = false;
    int ccur = c.max();
    int cmax = ccur;
    int cmin = ccur;
    // Sort tasks by decreasing capacity
    TaskByDecCap<Task> tbdc;
    Support::quicksort(&t[0], t.size(), tbdc);

    Region r(home);

    Event* e = r.alloc<Event>(4*t.size()+1);

    // Initialize events
    bool assigned=true;
    {
      bool required=false;
      int n=0;
      for (int i=t.size(); i--; ) 
        if (t[i].assigned()) {
          // Only add required part
          if (t[i].pmin() > 0) {
            required = true;
            e[n++].init(Event::ERT,t[i].lst(),i);
            e[n++].init(Event::LRT,t[i].ect(),i);
          } else if (t[i].pmax() == 0) {
            required = true;
            e[n++].init(Event::ZRO,t[i].lst(),i);
          }
        } else {
          assigned = false;
          e[n++].init(Event::EST,t[i].est(),i);
          e[n++].init(Event::LCT,t[i].lct(),i);
          // Check whether task has required part
          if (t[i].lst() < t[i].ect()) {
            required = true;
            e[n++].init(Event::ERT,t[i].lst(),i);
            e[n++].init(Event::LRT,t[i].ect(),i);
          }
        }
      
      // Check whether no task has a required part
      if (!required) {
        subsumed = assigned;
        return ES_FIX;
      }
      
      // Write end marker
      e[n++].init(Event::END,Int::Limits::infinity,-1);
      
      // Sort events
      Support::quicksort(e, n);
    }

    // Set of current but not required tasks
    Support::BitSet<Region> tasks(r,static_cast<unsigned int>(t.size()));

    // Process events, use ccur as the capacity that is still free
    while (e->e != Event::END) {
      // Current time
      int time = e->t;

      // Process events for completion of required part
      for ( ; (e->t == time) && (e->e == Event::LRT); e++) 
        if (t[e->i].mandatory()) {
          tasks.set(static_cast<unsigned int>(e->i)); ccur += t[e->i].c();
        }
      // Process events for completion of task
      for ( ; (e->t == time) && (e->e == Event::LCT); e++)
        tasks.clear(static_cast<unsigned int>(e->i));
      // Process events for start of task
      for ( ; (e->t == time) && (e->e == Event::EST); e++)
        tasks.set(static_cast<unsigned int>(e->i));
      // Process events for zero-length task
      for ( ; (e->t == time) && (e->e == Event::ZRO); e++) {
        ccur -= t[e->i].c();
        if (ccur < cmin) cmin=ccur;
        if (ccur < 0)
          return ES_FAILED;
        ccur += t[e->i].c();
      }

      // norun start time for 0-length tasks
      int zltime = time;
      // Process events for start of required part
      for ( ; (e->t == time) && (e->e == Event::ERT); e++) 
        if (t[e->i].mandatory()) {
          tasks.clear(static_cast<unsigned int>(e->i)); 
          ccur -= t[e->i].c();
          if (ccur < cmin) cmin=ccur;
          zltime = time+1;
          if (ccur < 0)
            return ES_FAILED;
        } else if (t[e->i].optional() && (t[e->i].c() > ccur)) {
          GECODE_ME_CHECK(t[e->i].excluded(home));
        }
      
      // Exploit that tasks are sorted according to capacity
      for (Iter::Values::BitSet<Support::BitSet<Region> > j(tasks); 
           j() && (t[j.val()].c() > ccur); ++j) 
        // Task j cannot run from time to next time - 1
        if (t[j.val()].mandatory()) {
          if (t[j.val()].pmin() > 0) {
            GECODE_ME_CHECK(t[j.val()].norun(home, time, e->t - 1));
          } else {
            GECODE_ME_CHECK(t[j.val()].norun(home, zltime, e->t - 1));
          }
        }
    }

    GECODE_ME_CHECK(c.gq(home,cmax-cmin));

    subsumed = assigned;
    return ES_NOFIX;
  }