IBM ILOG Scheduler User's Manual > Integrated Applications > Scheduling with State Resources: the Trolley Problem, with Transition Times and Limited Capacity > Representing State Resource with Limited Capacity > Jobs and Activities

An item occupies the trolley from the moment it is loaded on the trolley until the moment it is unloaded. As a consequence, three activities _onTrolleyA1, _onTrolley12, and _onTrolley2S, corresponding to the occupation of the trolley by the item, are added to the Job class.

class Job {
private:
  const char* _name;
  IloActivity _loadA;
  IloActivity _unload1;
  IloActivity _process1;
  IloActivity _load1;
  IloActivity _unload2;
  IloActivity _process2;
  IloActivity _load2;
  IloActivity _unloadS;
  IloInt      _area1;
  IloInt      _area2;
  IloUnaryResource _machine1;
  IloUnaryResource _machine2;
public:
  Job(IloEnv env,
      const char*,
      IloNum loadDuration,
      IloUnaryResource machine1, IloNum duration1, IloInt area1,
      IloUnaryResource machine2, IloNum duration2, IloInt area2);
  void addToModel(IloModel model,
                  IloStateResource trolley,
                  IloNumVar makespan,
                  IloDiscreteResource trolleyCapacity,
                  IloTransitionParam transitionParam);
  ~Job();
  void printSolution(IlcScheduler scheduler, ILOSTD(ostream)& out);
  const char* getName() const { return  _name;}
 
  IloActivity getLoadA() const { return _loadA;}
  IloActivity getUnload1() const { return _unload1;}
  IloActivity getProcess1() const { return _process1;}
  IloActivity getLoad1() const { return _load1;}
  IloActivity getUnload2() const { return _unload2;}
  IloActivity getProcess2() const { return _process2;}
  IloActivity getLoad2() const { return _load2;}
  IloActivity getUnloadS() const { return _unloadS;}
 
};
 

In the constructor of a Job, we specify that the trolley is occupied by the item for the interval between the start of the load activity and the end of the corresponding unload activity. The activities _onTrolley require one unit of trolley capacity each.

Job::Job(IloEnv env,
   const char* name,
   IloNum loadDuration,
   IloUnaryResource machine1, IloNum duration1, IloInt area1,
   IloUnaryResource machine2, IloNum duration2, IloInt area2)
  : _name(name),
    _loadA(      env,loadDuration),
    _unload1(    env,loadDuration),
    _process1(   env,duration1),
    _load1(      env,loadDuration),
    _unload2(    env,loadDuration),
    _process2(   env,duration2),
    _load2(      env,loadDuration),
    _unloadS(    env,loadDuration),
    _area1(area1),
    _area2(area2),
    _machine1(machine1),
    _machine2(machine2)
{
 char buffer[256];
 
  sprintf(buffer, "arrival_load_%s", name);
  _loadA.setName(buffer);
 
  sprintf(buffer, "area%ld_unload_%s", area1, name);
  _unload1.setName(buffer);
 
  sprintf(buffer, "machine%ld_%s", area1, name);
  _process1.setName(buffer);
 
  sprintf(buffer, "area%ld_load_%s", area1, name);
  _load1.setName(buffer);
 
  sprintf(buffer, "area%ld_unload_%s", area2, name);
  _unload2.setName(buffer);
 
  sprintf(buffer, "machine%ld_%s", area2, name);
  _process2.setName(buffer);
 
  sprintf(buffer, "area%ld_load_%s", area2, name);
  _load2.setName(buffer);
  
  sprintf(buffer, "stock_load_%s", name);
  _unloadS.setName(buffer);
 
  /* ADD TRANSITION TYPE  */
  _loadA.setTransitionType(AREAA - 1);
  _unload1.setTransitionType(area1 - 1);
  _load1.setTransitionType(area1 - 1);
  _unload2.setTransitionType(area2 - 1);
  _load2.setTransitionType(area2 - 1);
  _unloadS.setTransitionType(AREAS - 1);
 
}
 
void Job::addToModel(IloModel model,
                     IloStateResource trolley,
                     IloNumVar makespan,
                     IloDiscreteResource trolleyCapacity,
                     IloTransitionParam transitionParam)
{
 
  /* ADD MACHINE REQUIREMENT CONSTRAINTS */
  model.add(_process1.requires(_machine1));
  model.add(_process2.requires(_machine2));
 
  /* ADD TEMPORAL CONSTRAINTS BETWEEN ACTIVITIES */
 
  model.add(_unload1.startsAfterEnd(_loadA));
  model.add(_process1.startsAfterEnd(_unload1));
  model.add(_load1.startsAfterEnd(_process1));
  model.add(_unload2.startsAfterEnd(_load1));
  model.add(_process2.startsAfterEnd(_unload2));
  model.add(_load2.startsAfterEnd(_process2));
  model.add(_unloadS.startsAfterEnd(_load2));
 
  
  /* ADD TROLLEY POSITION REQUIREMENTS  */
  model.add(_loadA.requires(trolley,(IloAny)AREAA));
  model.add(_unload1.requires(trolley,(IloAny)_area1));
  model.add(_load1.requires(trolley,(IloAny)_area1));
  model.add(_unload2.requires(trolley,(IloAny)_area2));
  model.add(_load2.requires(trolley,(IloAny)_area2));
  model.add(_unloadS.requires(trolley,(IloAny)AREAS));
 
  /* ADD TROLLEY CAPACITY REQUIREMENTS  */
  IloNum delay = transitionParam.getValue((IloInt)_loadA.getTransitionType(),
                                          (IloInt)_unload1.getTransitionType());
  IloIntVar durationA1(model.getEnv(), 
                       2*(IloInt)loadDuration + (IloInt)delay,
                       (IloInt)makespan.getUB());
  IloActivity onTrolleyA1(model.getEnv(), durationA1);
  onTrolleyA1.shareStartWithStart(_loadA);
  onTrolleyA1.shareEndWithEnd(_unload1);
  model.add(onTrolleyA1.requires(trolleyCapacity));
  delay = transitionParam.getValue((IloInt)_load1.getTransitionType(),
                                   (IloInt)_unload2.getTransitionType());
  IloIntVar duration12(model.getEnv(), 
                       2*(IloInt)loadDuration + (IloInt)delay,
                       (IloInt)makespan.getUB());
  IloActivity onTrolley12(model.getEnv(), duration12);
  onTrolley12.shareStartWithStart(_load1);
  onTrolley12.shareEndWithEnd(_unload2);
  model.add(onTrolley12.requires(trolleyCapacity));
  delay = transitionParam.getValue((IloInt)_load2.getTransitionType(),
                                   (IloInt)_unloadS.getTransitionType());
  IloIntVar duration2S(model.getEnv(), 
                       2*(IloInt)loadDuration + (IloInt)delay,
                       (IloInt)makespan.getUB());
  IloActivity onTrolley2S(model.getEnv(), duration2S);
  onTrolley2S.shareStartWithStart(_load2);
  onTrolley2S.shareEndWithEnd(_unloadS);
  model.add(onTrolley2S.requires(trolleyCapacity));
  
  /* ADD MAKESPAN CONSTRAINT */
  model.add(_unloadS.endsBefore(makespan));
}
 
  

The same trade-off between efficiency of computation time and quality of the solution is made as for the previous version of the trolley example.