IBM ILOG Scheduler User's Manual > Local Search in Scheduler > Tabu Search for the Jobshop Problem with Alternatives > Solving the Problem > Creating the RelocateRC Move

The RelocateRC move represents the movement of a resource constraint from one resource in its alternative resource set to another and the insertion of the resource constraint between two other resource constraints on the latter resource. The class represents the resource constraint that is relocated (_relocated), the resource to which it is moved to (_to), and the resource constraint that it is next to on the new resource (_beforeInsertion).

Accessors are defined for the data members and the class as a whole inherits from LSMove.

class RelocateRC : public LSMove {
  // This class represents the data to perform a relocate of _and
  // _after in the sequence
private:
  IloResourceConstraint _relocated;
  IloResource _to;
  IloResourceConstraint _beforeInsertion;

public:
  RelocateRC() : _relocated(0),_to(0),_beforeInsertion(0) {}
  RelocateRC(IloResourceConstraint rc,
         IloResource to,
         IloResourceConstraint before) 
    : _relocated(rc), _to(to), _beforeInsertion(before) {} 
  virtual ~RelocateRC() {}

  IloResourceConstraint getRC() const { return _relocated; }
  IloResource getTo() const { return _to; }

  void setRC(IloResourceConstraint rc) { _relocated = rc; }
  void setTo(IloResource res) { _to = res; }

  void setBeforeInsertion(IloResourceConstraint before) { 
    _beforeInsertion = before; 
  }

  virtual IloBool isReverseMove(IloSolution delta) const {
    IloSchedulerSolution schedDelta(delta);
    return (schedDelta.contains(_relocated) &&
            (schedDelta.getSelected(_relocated).getImpl() != _to.getImpl()));
  }

  virtual IloSolution createDelta(IloEnv, IloSchedulerSolution);
  static RelocateRC* findRelocateFromDelta(IloSolver, 
                                           IloSolution, IloSchedulerSolution);
};

The isReverseMove method returns IloTrue if the delta solution places the _relocated resource constraint on a resource other than _to.

Two additional functions are defined:

Recall that the createDelta function creates an IloSchedulerSolution object that represents the changes necessary to implement a move. In detail, we do the following in the createDelta method.

First, we reassign the selected resource of the _relocated resource constraint and unset its next pointer if it has one in the current solution.

  relocateDelta.add(_relocated, current.getRestorable(_relocated));
  relocateDelta.setSelected(_relocated, _to);
  if (current.hasNextRC(_relocated)) 
    relocateDelta.unsetNext(_relocated, current.getNextRC(_relocated));

We then set the next pointer of _relocated to be either the setup resource constraint on the _to resource or to the resource constraint that is next after _beforeInsertion in the current solution.

  IloResourceConstraint afterInsertion;
  if (_beforeInsertion.getImpl() == 0)
    // insert _relocated as the first rc on _to
    afterInsertion = current.getSetupRC(_to);
  else
    afterInsertion = current.getNextRC(_beforeInsertion);

  if (afterInsertion.getImpl() != 0) 
    relocateDelta.setNext(_relocated, afterInsertion);

It is possible that _relocated will have no next resource constraint in the case where it is inserted as the last resource constraint on the _to resource.

We then add the _beforeInsertion resource constraint to the delta solution and set its next to be _relocated. Again, it is possible that _beforeInsertion does not exist when _relocated is inserted as the first resource constraint on the _to resource.

  if (_beforeInsertion.getImpl() != 0) {
    relocateDelta.add(_beforeInsertion, 
                      current.getRestorable(_beforeInsertion));
		relocateDelta.getSolution().copy(_beforeInsertion, current);
    if (relocateDelta.hasNextRC(_beforeInsertion))
      relocateDelta.unsetNext(_beforeInsertion,
                              current.getNextRC(_beforeInsertion));
    relocateDelta.setNext(_beforeInsertion, _relocated);
  }

The final step is to change the resource constraint that comes before _relocated in the current solution. If it exists, we need to change its next pointer to point to the resource constraint that comes after _relocated in the current solution.

  IloResourceConstraint oldBefore = 
    current.getPrevRC(_relocated);
  if (oldBefore.getImpl() != 0) {
    relocateDelta.add(oldBefore, 
                      current.getRestorable(oldBefore));
		relocateDelta.getSolution().copy(oldBefore, current);
    relocateDelta.unsetNext(oldBefore, _relocated);
    if (current.hasNextRC(_relocated))
      relocateDelta.setNext(oldBefore, current.getNextRC(_relocated));
  }

The RelocateRC::findRelocateFromDelta creates an instance of RelocateRC from a corresponding IloSchedulerSolution. If the IloSchedulerSolution does not actually represent a RelocateRC a NULL pointer is returned.

This method first finds a resource constraint whose assigned resource has been changed in the delta solution and then finds the resource constraint that is not next to any of the resource constraints in the delta. By comparing these two resource constraints, it is possible to recreate the RelocateRC move.

RelocateRC* RelocateRC::findRelocateFromDelta(IloSolver solver,
                                  IloSolution delta,
                                  IloSchedulerSolution current) {
  // Try to generate a RelocateRC move from the information in delta.
  // This may fail as delta does not necessarily represent a SwapRC
  // move
  IloSchedulerSolution solution(delta);
  IloResourceConstraint resChange;
  for(IloSchedulerSolution::ResourceConstraintIterator iter2(solution);
      iter2.ok() && (resChange.getImpl() == 0); ++iter2) {
    resChange = *iter2;
    if (solution.getSelected(resChange).getImpl() == 
        current.getSelected(resChange).getImpl())
      resChange = 0;
  }
 
  if (0 == resChange.getImpl())
    return 0;
 
  // find the element that is not next of any element in the delta
  IloResourceConstraint first;
  for(IloSchedulerSolution::ResourceConstraintIterator iter(solution);
      iter.ok() && (0 == first.getImpl()); ++iter) {
    first = *iter;
    for(IloSchedulerSolution::ResourceConstraintIterator iter3(solution);
        iter3.ok() && (0 != first.getImpl()); ++iter3) {
      IloResourceConstraint rc = *iter3;
      if (rc.getImpl() != first.getImpl()) {
        if (solution.hasNextRC(rc) && 
            (solution.getNextRC(rc).getImpl() == first.getImpl()))
          first = 0;
      }
    }
  }
 
  assert(0 != first.getImpl());
 
  if (first.getImpl() == resChange.getImpl())
    return new (solver.getEnv()) RelocateRC(first, 
                                            solution.getSelected(first),
                                            0);
  else
    return new (solver.getEnv()) RelocateRC(resChange, 
                                            solution.getSelected(resChange),
                                            first); 
}