IBM ILOG Scheduler User's Manual > Integrated Applications > Scheduling with Alternative Resources: Interleaving Resource Allocation and Scheduling Decisions > Complete Program and Output

You can see the entire program alttext.cpp here or view it online in the standard distribution.

#include <ilsched/iloscheduler.h>
 
ILOSTLBEGIN
 
IloInt ResourceNumbers06 [] = {2, 0, 1, 3, 5, 4,
                               1, 2, 4, 5, 0, 3,
                               2, 3, 5, 0, 1, 4,
                               1, 0, 2, 3, 4, 5,
                               2, 1, 4, 5, 0, 3,
                               1, 3, 5, 0, 4, 2};
 
IloNum Durations06 [] = { 1,  3,  6,  7,  3,  6,
                          8,  5, 10, 10, 10,  4,
                          5,  4,  8,  9,  1,  7,
                          5,  5,  5,  3,  8,  9,
                          9,  3,  5,  4,  3,  1,
                          3,  3,  9, 10,  4,  1};
 
IloInt ResourceNumbers10 [] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
                               0, 2, 4, 9, 3, 1, 6, 5, 7, 8,
                               1, 0, 3, 2, 8, 5, 7, 6, 9, 4,
                               1, 2, 0, 4, 6, 8, 7, 3, 9, 5,
                               2, 0, 1, 5, 3, 4, 8, 7, 9, 6,
                               2, 1, 5, 3, 8, 9, 0, 6, 4, 7,
                               1, 0, 3, 2, 6, 5, 9, 8, 7, 4,
                               2, 0, 1, 5, 4, 6, 8, 9, 7, 3,
                               0, 1, 3, 5, 2, 9, 6, 7, 4, 8,
                               1, 0, 2, 6, 8, 9, 5, 3, 4, 7};
 
IloNum Durations10 [] = {29, 78,  9, 36, 49, 11, 62, 56, 44, 21,
                         43, 90, 75, 11, 69, 28, 46, 46, 72, 30,
                         91, 85, 39, 74, 90, 10, 12, 89, 45, 33,
                         81, 95, 71, 99,  9, 52, 85, 98, 22, 43,
                         14,  6, 22, 61, 26, 69, 21, 49, 72, 53,
                         84,  2, 52, 95, 48, 72, 47, 65,  6, 25,
                         46, 37, 61, 13, 32, 21, 32, 89, 30, 55,
                         31, 86, 46, 74, 32, 88, 19, 48, 36, 79,
                         76, 69, 76, 51, 85, 11, 40, 89, 26, 74,
                         85, 13, 61,  7, 64, 76, 47, 52, 90, 45};
 
IloInt ResourceNumbers20 [] = {0, 1, 2, 3, 4,
                               0, 1, 3, 2, 4,
                               1, 0, 2, 4, 3,
                               1, 0, 4, 2, 3,
                               2, 1, 0, 3, 4,
                               2, 1, 4, 0, 3,
                               1, 0, 2, 3, 4,
                               2, 1, 0, 3, 4,
                               0, 3, 2, 1, 4,
                               1, 2, 0, 3, 4,
                               1, 3, 0, 4, 2,
                               2, 0, 1, 3, 4,
                               0, 2, 1, 3, 4,
                               2, 0, 1, 3, 4,
                               0, 1, 4, 2, 3,
                               1, 0, 3, 4, 2,
                               0, 2, 1, 3, 4,
                               0, 1, 4, 2, 3,
                               1, 2, 0, 3, 4,
                               0, 1, 2, 3, 4};
 
IloNum Durations20 [] = {29,  9, 49, 62, 44,
                         43, 75, 69, 46, 72,
                         91, 39, 90, 12, 45,
                         81, 71,  9, 85, 22,
                         14, 22, 26, 21, 72,
                         84, 52, 48, 47,  6,
                         46, 61, 32, 32, 30,
                         31, 46, 32, 19, 36,
                         76, 76, 85, 40, 26,
                         85, 61, 64, 47, 90,
                         78, 36, 11, 56, 21,
                         90, 11, 28, 46, 30,
                         85, 74, 10, 89, 33,
                         95, 99, 52, 98, 43,
                          6, 61, 69, 49, 53,
                          2, 95, 72, 65, 25,
                         37, 13, 21, 89, 55,
                         86, 74, 88, 48, 79,
                         69, 51, 11, 89, 74,
                         13,  7, 76, 52, 45};
 
 
///////////////////////////////////////////////////////////////////
//
// TEXTURE CHOICE POINT FOR SCHEDULING WITH ALTERNATIVES
//
///////////////////////////////////////////////////////////////////
 
class AltTextureGoalI : public IlcGoalI {
private:
  IlcSchedule _schedule;
 
protected:
  IlcResourceTexture chooseResource();
  IlcBool choosePair(IlcResourceTexture,
                     IlcResourceConstraint&,
                     IlcResourceConstraint&, IlcFloat&);
  IlcBool chooseSequence(IlcResourceConstraint&,
                         IlcResourceConstraint&,
                         IlcResourceConstraint,
                         IlcResourceConstraint);
  IlcBool calcBiasedSlack(IlcResourceConstraint,
                          IlcResourceConstraint,
                          IlcFloat&, IlcFloat&);
  IlcBool chooseAlternative(IlcResourceTexture,
                            IlcResourceConstraint&, IlcFloat&);
 
public:
  AltTextureGoalI(IlcSchedule s) 
    : IlcGoalI(s.getSolver()), _schedule(s) {}
  ~AltTextureGoalI() {}
 
  virtual IlcGoal execute();
};
 
IlcGoal AltTextureGoalI::execute() {
 
  IlcResourceTexture selectedTexture = chooseResource();
  while(0 != selectedTexture.getImpl()) {
 
    IlcResourceConstraint rctA, rctB, rctC;
    IlcFloat maxPairCriticality = 0;
    IlcFloat altCriticality = 0;
    IlcBool pairFound = choosePair(selectedTexture, 
                                   rctA, rctB, maxPairCriticality);
    IlcBool altFound = chooseAlternative(selectedTexture, 
                                         rctC, altCriticality);
 
    if (!pairFound && !altFound) {
      // If neither a pair nor an alternative is found, then
      // there are no commitments that this goal can make at
      // the critical point.
      selectedTexture.setNoCommitmentsAtCriticalPoint();
      selectedTexture = chooseResource();
    }
    else {
      if (!pairFound || 
          (altFound && (maxPairCriticality <= altCriticality))) 
        return IlcAnd(IlcTryNotPossible(rctC.getResource(), 
                                        rctC.getAlternative()),
                      this);
      else {
        IlcResourceConstraint before, after;
        IlcBool sequenceOK = chooseSequence(before, after,
                                            rctA, rctB);
        assert(sequenceOK);
 
        return IlcAnd(IlcTrySetSuccessor(before, after), this);
      }
    }
  }
 
  return 0;
}
 
 
IlcResourceTexture AltTextureGoalI::chooseResource() {
 
  IlcResourceTexture selectedTexture = 0;
  IlcFloat criticality = 0;
 
  for(IlcResourceIterator iter(_schedule); iter.ok(); ++iter) {
    if ((*iter).isDiscreteResource()) {
      IlcDiscreteResource res = (IlcDiscreteResource) (*iter);
      IlcResourceTexture texture = res.getTextureMeasurement();
      
      if (texture.getMaxCriticality() > criticality) {
        selectedTexture = texture;
        criticality = texture.getMaxCriticality();
      }
    }
  }
 
  return selectedTexture;
}
 
IlcBool AltTextureGoalI::choosePair(IlcResourceTexture texture,
                                    IlcResourceConstraint& rctA,
                                    IlcResourceConstraint& rctB,
                                    IlcFloat& maxCriticality) {
 
  IlcRCTextureArray rcTextures = 
    texture.getCriticalityOrderedRCTextures();
  IlcInt nbRCTextures = rcTextures.getSize();
 
  IlcInt i;
  for(i = 0; i < nbRCTextures - 1;  ++i) {
 
    IlcFloat c = rcTextures[i].getCriticalContribution();
    if (c == 0)
      return IlcFalse;
 
    if (!rcTextures[i].hasAlternatives()) {
      rctA = rcTextures[i].getResourceConstraint();
      maxCriticality = c;
 
      IlcInt j;
      for(j = i+1;
          (j < nbRCTextures) &&
           (rcTextures[j].getCriticalContribution() > 0); ++j) {
 
        if (!rcTextures[j].hasAlternatives()) {
          rctB = rcTextures[j].getResourceConstraint();
 
        if (!rctA.isSucceededBy(rctB) && 
            !rctB.isSucceededBy(rctA)) {
            // found the pair to sequence
            return IlcTrue;
          }
        }
      }
    }
  }
 
  return IlcFalse;
}
 
IlcBool AltTextureGoalI::chooseSequence(
                  IlcResourceConstraint& selectedRct1,
                  IlcResourceConstraint& selectedRct2,
                  IlcResourceConstraint rctA,
                  IlcResourceConstraint rctB) {
 
  IlcFloat biasedSlackBA, biasedSlackAB;
  if (!calcBiasedSlack(rctA, rctB,
                       biasedSlackAB, biasedSlackBA))
    return IlcFalse;
 
  selectedRct1 = rctA;
  selectedRct2 = rctB;
 
  // pick sequence that preserves the most slack
  if (biasedSlackAB < biasedSlackBA) {
    selectedRct1 = rctB;
    selectedRct2 = rctA;
  }
    
  return IlcTrue;
}
 
IlcBool AltTextureGoalI::calcBiasedSlack(
                        IlcResourceConstraint rctA,
                        IlcResourceConstraint rctB,
                        IlcFloat& biasedSlackAB,
                        IlcFloat& biasedSlackBA)
{
  // The PCPSlack sequencing calculation from:
  // @InProceedings{Cheng93,
  //   author = "Smith, S. F. and Cheng, C. C.",
  //   title = "Slack-based heuristics for constraint satisfaction
  //           scheduling", 
  //   key = "scheduling",
  //   year = "1993",
  //   pages = "139--144",
  //   booktitle = "Proceedings of the Eleventh National 
  //                Conference on Artificial Intelligence
  //                (AAAI-93)",
  // }
 
  // Returns IlcTrue if the pair has a valid biasedSlack value.
  // IlcFalse means there is no valid value for this pair (for
  // example, because they do not overlap). 
 
  IlcActivity actA = rctA.getActivity();
  IlcActivity actB = rctB.getActivity();
 
  IlcInt estA = actA.getStartMin();
  IlcInt lftA = actA.getEndMax();
  IlcInt estB = actB.getStartMin();
  IlcInt lftB = actB.getEndMax();
 
  if ((lftA <= estB) || (lftB <= estA))
    // Activities  already sequenced
    return IlcFalse;
 
  IlcInt lambda = lftA - estB;
  IlcInt mu = lftB - estA;
  IlcInt delta = actA.getProcessingTimeMin() + 
    actB.getProcessingTimeMin();
 
  IlcFloat slackAB = mu - delta;
  IlcFloat slackBA = lambda - delta;
  IlcFloat rtS;
  
  // Either (or both) of slackAB and slackBA might be 0!
  // Assign to 0.1 (note that lambda, delta, and mu are
  // all integral it is not possible for slackAB or
  // slackBA to actually be 0.1 by themselves)
  if (mu == delta)
    slackAB = 0.1;
 
  if (lambda == delta)
    slackBA = 0.1;
 
  if (slackAB < slackBA)
    rtS = sqrt(slackAB / slackBA);
  else
    rtS = sqrt(slackBA / slackAB);
 
  biasedSlackAB = slackAB / rtS;
  biasedSlackBA = slackBA / rtS;
 
  return IlcTrue;
}
 
IlcBool AltTextureGoalI::chooseAlternative(
                            IlcResourceTexture texture,
                            IlcResourceConstraint& altRC,
                            IlcFloat& criticality) {
 
  IlcRCTextureArray rcTextures =
    texture.getCriticalityOrderedRCTextures();
  IlcInt nbRCTextures = rcTextures.getSize();
 
  for(IlcInt i = 0; i < nbRCTextures; ++i) {
    IlcFloat c = rcTextures[i].getCriticalContribution();
    if (c == 0)
      return IlcFalse;
    if (rcTextures[i].hasAlternatives()) {
      // rcTextures is sorted in descending order of
      // criticality so the first rct we find with
      // alternatives is the one with the highest crit.
      altRC = rcTextures[i].getResourceConstraint();
      criticality = c;
      return IlcTrue;
    }
  }
 
  return IlcFalse;
}
 
 
ILOCPGOALWRAPPER1(AltTextureIloGoal, solver, IloNumVar, cost) {
  IlcScheduler scheduler(solver);
  return IlcAnd(IlcGoal(new (solver.getHeap()) 
                                AltTextureGoalI(scheduler)),
                IlcInstantiate(solver.getIntVar(cost)));
}
 
///////////////////////////////////////////////////////////////////
//
// PRINTING OF SOLUTIONS
//
///////////////////////////////////////////////////////////////////
 
void PrintRange(IloEnv& env, IloNum min, IloNum max) {
  if (min == max)
    env.out() << (IlcInt)min;
  else
    env.out() << (IlcInt)min << ".." << (IlcInt)max;
}
 
void PrintSolution(IloEnv& env, 
                   const IloSchedulerSolution solution,
                   const IloNumVar makespan)
{
  env.out() << "Solution with makespan ["
            << solution.getMin(makespan) << ".." 
            << solution.getMax(makespan) << "]" << endl;
 
  for (IloSchedulerSolution::ResourceConstraintIterator
	 iter(solution);
       iter.ok();
       ++iter) 
  {
    IloResourceConstraint rc = *iter;
    if (!solution.isResourceSelected(rc))
      IloSchedulerException("No resource assigned!");
 
    IloActivity activity = rc.getActivity();
    env.out() << activity.getName() << "[";
    PrintRange(env, 
               solution.getStartMin(activity),  
               solution.getStartMax(activity));
    env.out() << " -- ";
    PrintRange(env, 
               solution.getDurationMin(activity),
               solution.getDurationMax(activity));
    env.out() << " --> ";
    PrintRange(env, 
               solution.getEndMin(activity),
               solution.getEndMax(activity));
    env.out() << "]: " << solution.getSelected(rc).getName()
              << endl;
  }
}
 
////////////////////////////////////////////////////////////////////
//
// SOLVE THE MODEL USING TEXTURE-BASED HEURISTIC
//
////////////////////////////////////////////////////////////////////
IloBool SolveModel(IloModel model, IloNumVar makespan,
                   IloSchedulerSolution solution) {
 
  IloEnv env = model.getEnv();
  IloSolver solver(model);
  IlcScheduler scheduler(solver);
  IloBool solved = IloFalse;
 
  IloNum timeLimit = 200;
  IloGoal goal = AltTextureIloGoal(env, makespan);
  IloGoal limitedGoal = IloLimitSearch(env, goal,
                                       IloTimeLimit(env,
                                                    timeLimit));
 
  solver.startNewSearch(limitedGoal);
  while(solver.next()) {
    solver.out() << "Solution with makespan: " 
                 << solver.getIntVar(makespan).getValue() << endl;
    solution.store(scheduler);
    solved = IloTrue;
  }
 
  solver.endSearch();
 
  solver.printInformation();
  solver.end();
  return solved;
}
 
////////////////////////////////////////////////////////////////////
//
// DEFINE THE MODEL WITH ALTERNATIVE RESOURCES
//
////////////////////////////////////////////////////////////////////
IloModel
DefineModel(IloEnv& env,
            IloInt numberOfJobs,
            IloInt numberOfResources,        
            IloInt* resourceNumbers,
            IloNum* durations,
            IloRandom randomGenerator,
            IloSchedulerSolution solution,
            IloNumVar& makespan)
{
  IloModel model(env);
 
  /* CREATE THE MAKESPAN VARIABLE. */
  IloInt numberOfActivities = numberOfJobs * numberOfResources;
  IloNum horizon = 0;
  IloInt k;
 
  for (k = 0; k < numberOfActivities; k++)
    horizon += durations[k];
 
  makespan = IloNumVar(env, 0, horizon, ILOINT);
 
  /* CREATE THE RESOURCES. */
  IloSchedulerEnv schedEnv(env);
  schedEnv.getResourceParam().
    setCapacityEnforcement(IloMediumHigh);
  schedEnv.getResourceParam().
    setPrecedenceEnforcement(IloMediumHigh);
 
  IloRCTextureFactory rcFactory = IloRCTextureProbabilisticFactory(env);
  schedEnv.getTextureParam().setRCTextureFactory(rcFactory);
 
  IloTextureCriticalityCalculator critCalc =
    IloProbabilisticCriticalityCalculator(env);
  schedEnv.getTextureParam().setCriticalityCalculator(critCalc);
 
  char buffer[128];
  IloInt j;
  IloUnaryResource *resources = 
    new (env) IloUnaryResource[numberOfResources];
  for (j = 0; j < numberOfResources; j++) {
    sprintf(buffer, "R%ld", j);
    resources[j] = IloUnaryResource(env, buffer);
  }
 
  /* CREATE THE ALTERNATIVE RESOURCE SETS */
  env.out() << "Creating resource sets" << endl;
  IloInt *altResourceNumbers = new (env) IloInt[numberOfResources];
  IloAltResSet *altResSets = 
    new (env) IloAltResSet[numberOfResources];
  for (j = 0; j < numberOfResources; j++) {
    altResSets[j] = IloAltResSet(env);
    altResSets[j].add(resources[j]);
 
    // RANDOMLY PICK ANOTHER RESOURCE TO BE IN THE SET
    assert(numberOfResources > 1);
    IloInt index = randomGenerator.getInt(numberOfResources);
    while(index == j)
      index = randomGenerator.getInt(numberOfResources);
 
    altResSets[j].add(resources[index]);
    altResourceNumbers[j] = index;
    env.out() << "Set #" << j << ":\t" << resources[j].getName()
              << " " << resources[index].getName() << endl;
  }
 
  /* CREATE THE ALTERNATIVE DURATIONS */
  IloNum *altDurations = new (env) IloNum[numberOfActivities];
  for(k = 0; k < numberOfActivities; k++) {
    IloNum multiplier = 1.0 + (randomGenerator.getFloat() / 2.0);
    altDurations[k] = IloCeil(multiplier * durations[k]);
  }
 
  /* CREATE THE ACTIVITIES. */
  env.out() << "Setting alternative processing times" << endl;
  k = 0;
  IloInt i;
  for (i = 0; i < numberOfJobs; i++) {
    IloActivity previousActivity;
    for (j = 0; j < numberOfResources; j++) {
 
      IloNum ptMin = IloMin(durations[k], altDurations[k]);
      IloNum ptMax = IloMax(durations[k], altDurations[k]);
      IloNumVar ptVar(env, ptMin, ptMax, ILOINT);
 
      IloActivity activity(env, ptVar);
 
      sprintf(buffer, "J%ldS%ldR%ld", i, j, resourceNumbers[k]);
      activity.setName(buffer);
      solution.add(activity);
 
      IloResourceConstraint rc =
        activity.requires(altResSets[resourceNumbers[k]]);
      
      // SET THE DIFFERENT DURATIONS DEPENDING ON 
      // RESOURCE SELECTION 
      rc.setProcessingTimeMax(resources[resourceNumbers[k]],
			      durations[k]);
      rc.setProcessingTimeMin(resources[resourceNumbers[k]],
			      durations[k]);
 
      rc.setProcessingTimeMax(
             resources[altResourceNumbers[resourceNumbers[k]]],
             altDurations[k]);
      rc.setProcessingTimeMin(
             resources[altResourceNumbers[resourceNumbers[k]]],
             altDurations[k]);
 
      model.add(rc);
 
      solution.add(rc);
      env.out() << activity.getName() 
                << ":\tProcessing Time(" 
                << resources[resourceNumbers[k]].getName()
                << "): " << durations[k]
                << "\n\tProcessing Time(" 
                << resources[altResourceNumbers[
                                    resourceNumbers[k]]].getName()
                << "): " << altDurations[k]
                << endl;
 
 
      if (j != 0)
        model.add(activity.startsAfterEnd(previousActivity));
      previousActivity = activity;
      k++;
    }
    model.add(previousActivity.endsBefore(makespan));
  }
 
  model.add(IloMinimize(env, makespan));
  solution.getSolution().add(makespan);
 
  /* RETURN THE MODEL. */
  return model;
}
 
 
/////////////////////////////////////////////////////////////////
//
// INITIALIZE THE PROGRAM ARGUMENTS
//
/////////////////////////////////////////////////////////////////
void
InitParameters(int argc,
               char** argv,
               IloInt& numberOfJobs,
               IloInt& numberOfResources,
               IloInt*& resourceNumbers,
               IloNum*& durations)
{
  numberOfJobs = 6;
  numberOfResources = 6;
  resourceNumbers = ResourceNumbers06;
  durations = Durations06;
 
  if (argc > 1) {
    IloInt number = atol(argv[1]);
    if (number == 10) {
      numberOfJobs = 10;
      numberOfResources = 10;
      resourceNumbers = ResourceNumbers10;
      durations = Durations10;
    }
    else if (number == 20) {
      numberOfJobs = 20;
      numberOfResources = 5;
      resourceNumbers = ResourceNumbers20;
      durations = Durations20;
    }
  }
}
 
/////////////////////////////////////////////////////////////////
//
// MAIN FUNCTION
//
/////////////////////////////////////////////////////////////////
 
int main(int argc, char** argv)
{
  IloInt numberOfJobs;
  IloInt numberOfResources;
  IloInt* resourceNumbers;
  IloNum* durations;
 
  InitParameters(argc,
                 argv,
                 numberOfJobs,
                 numberOfResources,
                 resourceNumbers,
                 durations);
 
  try {
 
    IloEnv env;
    IloNumVar makespan;
    IloRandom randGen(env, 8975324);
    IloSchedulerSolution solution(env);
    IloModel model = DefineModel(env,
                                 numberOfJobs,
                                 numberOfResources,
                                 resourceNumbers,
                                 durations,
                                 randGen,
                                 solution,
                                 makespan);
 
    IloBool solved = SolveModel(model, makespan, solution);
    if (!solved)
      throw IloSchedulerException( "No solution found" );
 
    PrintSolution(env, solution, makespan);
    env.end();
 
  }
  catch (IloSchedulerException& exc) {
    cout << exc << endl;
  }
  catch (IloException& exc) {
    cout << exc << endl;
  }
 
  return 0;
}
 
/*
% alttext
Creating resource sets
Set #0: R0 R5
Set #1: R1 R2
Set #2: R2 R3
Set #3: R3 R0
Set #4: R4 R1
Set #5: R5 R2
Setting alternative processing times
J0S0R2: Processing Time(R2): 1
        Processing Time(R3): 2
J0S1R0: Processing Time(R0): 3
        Processing Time(R5): 4
J0S2R1: Processing Time(R1): 6
        Processing Time(R2): 9
J0S3R3: Processing Time(R3): 7
        Processing Time(R0): 9
J0S4R5: Processing Time(R5): 3
        Processing Time(R2): 5
J0S5R4: Processing Time(R4): 6
        Processing Time(R1): 7
J1S0R1: Processing Time(R1): 8
        Processing Time(R2): 9
J1S1R2: Processing Time(R2): 5
        Processing Time(R3): 7
J1S2R4: Processing Time(R4): 10
        Processing Time(R1): 14
J1S3R5: Processing Time(R5): 10
        Processing Time(R2): 11
J1S4R0: Processing Time(R0): 10
        Processing Time(R5): 13
J1S5R3: Processing Time(R3): 4
        Processing Time(R0): 6
J2S0R2: Processing Time(R2): 5
        Processing Time(R3): 6
J2S1R3: Processing Time(R3): 4
        Processing Time(R0): 6
J2S2R5: Processing Time(R5): 8
        Processing Time(R2): 11
J2S3R0: Processing Time(R0): 9
        Processing Time(R5): 12
J2S4R1: Processing Time(R1): 1
        Processing Time(R2): 2
J2S5R4: Processing Time(R4): 7
        Processing Time(R1): 8
J3S0R1: Processing Time(R1): 5
        Processing Time(R2): 7
J3S1R0: Processing Time(R0): 5
        Processing Time(R5): 6
J3S2R2: Processing Time(R2): 5
        Processing Time(R3): 6
J3S3R3: Processing Time(R3): 3
        Processing Time(R0): 4
J3S4R4: Processing Time(R4): 8
        Processing Time(R1): 9
J3S5R5: Processing Time(R5): 9
        Processing Time(R2): 11
J4S0R2: Processing Time(R2): 9
        Processing Time(R3): 14
J4S1R1: Processing Time(R1): 3
        Processing Time(R2): 4
J4S2R4: Processing Time(R4): 5
        Processing Time(R1): 8
J4S3R5: Processing Time(R5): 4
        Processing Time(R2): 6
J4S4R0: Processing Time(R0): 3
        Processing Time(R5): 4
J4S5R3: Processing Time(R3): 1
        Processing Time(R0): 2
J5S0R1: Processing Time(R1): 3
        Processing Time(R2): 4
J5S1R3: Processing Time(R3): 3
        Processing Time(R0): 5
J5S2R5: Processing Time(R5): 9
        Processing Time(R2): 11
J5S3R0: Processing Time(R0): 10
        Processing Time(R5): 11
J5S4R4: Processing Time(R4): 4
        Processing Time(R1): 6
J5S5R2: Processing Time(R2): 1
        Processing Time(R3): 2
ILOG Scheduler 5.000, licensed to "ILOG Gentilly".
ILOG Solver 5.000, licensed to "ILOG Gentilly", options: LS 
Solution with makespan: 61
Solution with makespan: 59
Solution with makespan: 58
Solution with makespan: 57
Solution with makespan: 56
Solution with makespan: 54
Solution with makespan: 53
Solution with makespan: 51
Solution with makespan: 50
Solution with makespan: 49
Solution with makespan: 48
Number of fails               : 260
Number of choice points       : 270
Number of variables           : 146
Number of constraints         : 0
Reversible stack (bytes)      : 88464
Solver heap (bytes)           : 172884
Solver global heap (bytes)    : 237204
And stack (bytes)             : 4044
Or stack (bytes)              : 8064
Search Stack (bytes)          : 4044
Constraint queue (bytes)      : 11144
Total memory used (bytes)     : 525848
Running time since creation   : 0.73
Solution with makespan [48..48]
J0S0R2[0 -- 2 --> 2]: R3
J0S1R0[2 -- 4 --> 6]: R5
J0S2R1[8..19 -- 6 --> 14..25]: R1
J0S3R3[25 -- 7 --> 32]: R3
J0S4R5[32 -- 5 --> 37]: R2
J0S5R4[37..41 -- 7 --> 44..48]: R1
J1S0R1[0 -- 9 --> 9]: R2
J1S1R2[9 -- 5 --> 14]: R2
J1S2R4[14 -- 10 --> 24]: R4
J1S3R5[24 -- 10 --> 34]: R5
J1S4R0[34 -- 10 --> 44]: R0
J1S5R3[44 -- 4 --> 48]: R3
J2S0R2[6 -- 6 --> 12]: R3
J2S1R3[12 -- 4 --> 16]: R3
J2S2R5[16 -- 8 --> 24]: R5
J2S3R0[25 -- 9 --> 34]: R0
J2S4R1[34..40 -- 1 --> 35..41]: R1
J2S5R4[37..41 -- 7 --> 44..48]: R4
J3S0R1[3..5 -- 5 --> 8..10]: R1
J3S1R0[8..10 -- 5 --> 13..15]: R0
J3S2R2[16 -- 6 --> 22]: R3
J3S3R3[22 -- 3 --> 25]: R3
J3S4R4[25..29 -- 8 --> 33..37]: R4
J3S5R5[37 -- 11 --> 48]: R2
J4S0R2[14..18 -- 9 --> 23..27]: R2
J4S1R1[23..27 -- 3 --> 26..30]: R1
J4S2R4[26..30 -- 8 --> 34..38]: R1
J4S3R5[34..38 -- 4 --> 38..42]: R5
J4S4R0[38..42 -- 4 --> 42..46]: R5
J4S5R3[44..46 -- 2 --> 46..48]: R0
J5S0R1[0 -- 3 --> 3]: R1
J5S1R3[3 -- 3 --> 6]: R3
J5S2R5[6 -- 9 --> 15]: R5
J5S3R0[15 -- 10 --> 25]: R0
J5S4R4[33..37 -- 4 --> 37..41]: R4
J5S5R2[37..42 -- 2 --> 39..44]: R3
*/