IBM ILOG Scheduler User's Manual > Advanced Concepts > Scheduling with Unary Resources: the Job-Shop Problem > Complete Program and Output

You can see the entire program jobshopm.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};
 
IloInt 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};
 
IloInt 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};
 
IloInt 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};
///////////////////////////////////////////////////////////////////////////////
//
// DEFINITION OF THE JOB CLASS
//
///////////////////////////////////////////////////////////////////////////////
 
class Job {
private:
  char* _name;
  IloInt _index;
  IloArray<IloActivity> _inShops;
  IloArray<IloUnaryResource> _machines;
public:
  Job(IloEnv env, 
      IloInt index, 
      IloInt size,
      IloInt* durations,
      IloInt* resourceNumbers,
      IloUnaryResource* resources);
  const char* getName() const { return _name;}
  IloInt getIndex() const { return _index;}
  IloInt getSize() const { return _inShops.getSize();}
  IloActivity getActivity(IloInt i) const {
    IloAssert(i >= 0, "bad index range");
    IloAssert(i < _inShops.getSize(), "bad index range");
    return _inShops[i];
  }
  IloInt getShop(IloActivity act) const;
  void addToModel(IloModel model, IloIntVar makespan);
  void display(ILOSTD(ostream)& out) const {
    out << "Job<" << _name 
        << " ," << _index 
        << ", " << _inShops.getSize() << ">";
  }
};
Job::Job(IloEnv env, 
         IloInt index, 
         IloInt size,
         IloInt* durations,
         IloInt* resourceNumbers,
         IloUnaryResource* resources)
  :_index(index)
{
  char buffer[128];
  sprintf(buffer, "J%ld", index);
  IlcInt len = strlen(buffer);
  _name =  new (env) char[len+1];
  strcpy(_name, buffer);
  IloArray<IloActivity> inShops(env, size);
  IloArray<IloUnaryResource> machines(env, size);
  IlcInt i;
  for(i = 0; i < size; i++) {
    sprintf(buffer, "J%ldS%ldR%ld", index, i, resourceNumbers[i]);
    IloActivity act(env, durations[i], buffer);
    act.setObject(this);
    inShops[i] = act;
    machines[i] = resources[resourceNumbers[i]];
  }
  _inShops = inShops;
  _machines = machines;
}
 
IloInt Job::getShop(IloActivity act) const {
  IloArray<IloActivity> inShops = _inShops;
  IloInt size = inShops.getSize();
  IloInt i;
  for(i = 0; i < size; i++) {
    if (inShops[i].getImpl() == act.getImpl())
      return i;
  }
  return -1;
}
 
void Job::addToModel(IloModel model, IloIntVar makespan) {
  IloArray<IloActivity> inShops = _inShops;
  IloInt size = inShops.getSize();
  IloInt i;
  for(i = 1; i < size; i++) 
    model.add(inShops[i].startsAfterEnd(inShops[i-1]));
  model.add(inShops[size - 1].endsBefore(makespan));
  IloArray<IloUnaryResource> machines = _machines;
  for(i = 0; i < size; i++) 
    model.add(inShops[i].requires(machines[i]));
}
 
 
///////////////////////////////////////////////////////////////////////////////
//
// PROBLEM DEFINITION
//
///////////////////////////////////////////////////////////////////////////////
 
#if defined(ILO_SDXLOUTPUT)
#include "sdxljssp.h"
#endif
 
IloModel
DefineModel(const IloEnv& env,
            IloInt numberOfJobs,
            IloInt numberOfResources,        
            IloInt* resourceNumbers,
            IloInt* durations,
            IloNumVar& makespan,
            IloAnyArray& jobs)
{
  IloModel model(env);
 
  /* CREATE THE MAKESPAN VARIABLE. */
  IloInt numberOfActivities = numberOfJobs * numberOfResources;
  IloInt 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);
 
  IloInt j;
  IloUnaryResource *resources = 
    new IloUnaryResource[numberOfResources];
  char buffer[128];
  for (j = 0; j < numberOfResources; j++) {
    sprintf(buffer, "R%ld", j); 
    resources[j] = IloUnaryResource(env, buffer);
  }
  /* CREATE THE ACTIVITIES. */
  k = 0;
  IloInt i;
  jobs = IloAnyArray(env, numberOfJobs);
  for (i = 0; i < numberOfJobs; i++) {
    IlcInt j = i*numberOfResources;
    Job* job = new (env) Job(env, i, numberOfResources,
                             &durations[j], 
                             &resourceNumbers[j],
                             resources);
    job->addToModel(model, makespan);
    jobs[i] = job;
  }
  /* RETURN THE MODEL. */
  delete [] resources;
  return model;
}
///////////////////////////////////////////////////////////////////////////////
//
// PRINTING OF SOLUTIONS
//
///////////////////////////////////////////////////////////////////////////////
 
void
PrintSolution(IloSolver solver,
              IloAnyArray jobs,
              IloIntVar makespan)
{
  solver.out() << " Solution for Makespan " 
               << solver.getValue(makespan) << endl;
  IlcScheduler scheduler(solver);
  IloEnv env = solver.getEnv();
  IloInt numberOfJobs = jobs.getSize();
  IloInt i;
  for(i = 0; i < numberOfJobs; i++) {
    Job* job = (Job*) jobs[i];
    job->display(solver.out());
    solver.out() << endl;
    IloInt size = job->getSize();
    IloInt j;
    for(j = 0; j < size; j++) {
      IloActivity act = job->getActivity(j);
      solver.out() << "\t" << scheduler.getActivity(act) << endl;
    }
  }
 
#if defined(ILO_SDXLOUTPUT)
  IloSDXLJobShopOutput output(env);
  ofstream outFile("jobshopm.xml");
  output.writeJobShop(scheduler, outFile, jobs, makespan);
  outFile.close();
#endif
}
 
///////////////////////////////////////////////////////////////////////////////
//
// MAIN FUNCTION
//
///////////////////////////////////////////////////////////////////////////////
void
InitParameters(int argc,
               char** argv,
               IloInt& numberOfJobs,
               IloInt& numberOfResources,                    
               IloInt*& resourceNumbers,
               IloInt*& durations)
{
  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;
    }
  }
}
 
int main(int argc, char** argv)
{
  try {
    IloEnv env;
    
    IloInt numberOfJobs = 6;
    IloInt numberOfResources = 6;
    IloInt* resourceNumbers = ResourceNumbers06;
    IloInt* durations = Durations06;
    InitParameters(argc,
                   argv,
                   numberOfJobs,
                   numberOfResources,
                   resourceNumbers,
                   durations);
    IloNumVar makespan;
    IloAnyArray jobs;
    IloModel model = DefineModel(env,
                                 numberOfJobs,
                                 numberOfResources,
                                 resourceNumbers,
                                 durations,
                                 makespan,
                                 jobs);
    model.add(IloMinimize(env, makespan));
    
    IloSolver solver(model);
    IloGoal goal = IloRankForward(env,
                                  makespan, 
                                  IloSelResMinGlobalSlack,
                                  IloSelFirstRCMinStartMax);
 
    if (solver.solve(goal)) 
      PrintSolution(solver, jobs, makespan);
    else {
      solver.out() << " Failure for Makespan " 
                   << solver.getMax(makespan) << endl;
    }
 
    solver.printInformation();
    env.end();
 
  } catch (IloException& exc) {
    cout << exc << endl;
  }
  return 0;
}
 
///////////////////////////////////////////////////////////////////////////////
//
// RESULTS
//
///////////////////////////////////////////////////////////////////////////////
 
/* jobshopm 6
   Solution for Makespan 55
   J0S0R2 [5..7 -- 1 --> 6..8]
   J0S1R0 [6..11 -- 3 --> 9..14]
   J0S2R1 [16 -- 6 --> 22]
   J0S3R3 [30..36 -- 7 --> 37..43]
   J0S4R5 [42..43 -- 3 --> 45..46]
   J0S5R4 [49 -- 6 --> 55]
   J1S0R1 [0 -- 8 --> 8]
   J1S1R2 [8 -- 5 --> 13]
   J1S2R4 [13..15 -- 10 --> 23..25]
   J1S3R5 [28..29 -- 10 --> 38..39]
   J1S4R0 [38..40 -- 10 --> 48..50]
   J1S5R3 [48..50 -- 4 --> 52..54]
   J2S0R2 [0..2 -- 5 --> 5..7]
   J2S1R3 [5..7 -- 4 --> 9..11]
   J2S2R5 [9..11 -- 8 --> 17..19]
   J2S3R0 [18..19 -- 9 --> 27..28]
   J2S4R1 [27..41 -- 1 --> 28..42]
   J2S5R4 [42 -- 7 --> 49]
   J3S0R1 [8 -- 5 --> 13]
   J3S1R0 [13..14 -- 5 --> 18..19]
   J3S2R2 [22 -- 5 --> 27]
   J3S3R3 [27 -- 3 --> 30]
   J3S4R4 [30 -- 8 --> 38]
   J3S5R5 [45..46 -- 9 --> 54..55]
   J4S0R2 [13 -- 9 --> 22]
   J4S1R1 [22 -- 3 --> 25]
   J4S2R4 [25 -- 5 --> 30]
   J4S3R5 [38..39 -- 4 --> 42..43]
   J4S4R0 [48..51 -- 3 --> 51..54]
   J4S5R3 [52..54 -- 1 --> 53..55]
   J5S0R1 [13 -- 3 --> 16]
   J5S1R3 [16 -- 3 --> 19]
   J5S2R5 [19 -- 9 --> 28]
   J5S3R0 [28 -- 10 --> 38]
   J5S4R4 [38 -- 4 --> 42]
   J5S5R2 [42..54 -- 1 --> 43..55]
*/
 
/* jobshopm 10
   Solution for Makespan 930
   J0S0R0 [119 -- 29 --> 148]
   J0S1R1 [445..448 -- 78 --> 523..526]
   J0S2R2 [523..526 -- 9 --> 532..535]
   J0S3R3 [532..540 -- 36 --> 568..576]
   J0S4R4 [568..595 -- 49 --> 617..644]
   J0S5R5 [640..644 -- 11 --> 651..655]
   J0S6R6 [651..655 -- 62 --> 713..717]
   J0S7R7 [721 -- 56 --> 777]
   J0S8R8 [792..856 -- 44 --> 836..900]
   J0S9R9 [893..909 -- 21 --> 914..930]
   J1S0R0 [76 -- 43 --> 119]
   J1S1R2 [224..244 -- 90 --> 314..334]
   J1S2R4 [355 -- 75 --> 430]
   J1S3R9 [430..467 -- 11 --> 441..478]
   J1S4R3 [568..576 -- 69 --> 637..645]
   J1S5R1 [637..689 -- 28 --> 665..717]
   J1S6R6 [713..717 -- 46 --> 759..763]
   J1S7R5 [759..767 -- 46 --> 805..813]
   J1S8R7 [813 -- 72 --> 885]
   J1S9R8 [885..900 -- 30 --> 915..930]
   J2S0R1 [308..311 -- 91 --> 399..402]
   J2S1R0 [408..411 -- 85 --> 493..496]
   J2S2R3 [493..496 -- 39 --> 532..535]
   J2S3R2 [532..535 -- 74 --> 606..609]
   J2S4R8 [609 -- 90 --> 699]
   J2S5R5 [699 -- 10 --> 709]
   J2S6R7 [709 -- 12 --> 721]
   J2S7R6 [759..763 -- 89 --> 848..852]
   J2S8R9 [848..852 -- 45 --> 893..897]
   J2S9R4 [893..897 -- 33 --> 926..930]
   J3S0R1 [0..6 -- 81 --> 81..87]
   J3S1R2 [84..90 -- 95 --> 179..185]
   J3S2R0 [185 -- 71 --> 256]
   J3S3R4 [256 -- 99 --> 355]
   J3S4R6 [355..370 -- 9 --> 364..379]
   J3S5R8 [364..379 -- 52 --> 416..431]
   J3S6R7 [416..431 -- 85 --> 501..516]
   J3S7R3 [637..645 -- 98 --> 735..743]
   J3S8R9 [766..830 -- 22 --> 788..852]
   J3S9R5 [805..887 -- 43 --> 848..930]
   J4S0R2 [210..230 -- 14 --> 224..244]
   J4S1R0 [269..272 -- 6 --> 275..278]
   J4S2R1 [286..289 -- 22 --> 308..311]
   J4S3R5 [308..313 -- 61 --> 369..374]
   J4S4R3 [370..404 -- 26 --> 396..430]
   J4S5R4 [430 -- 69 --> 499]
   J4S6R8 [499 -- 21 --> 520]
   J4S7R7 [530..541 -- 49 --> 579..590]
   J4S8R9 [593..657 -- 72 --> 665..729]
   J4S9R6 [848..877 -- 53 --> 901..930]
   J5S0R2 [0..3 -- 84 --> 84..87]
   J5S1R1 [84..87 -- 2 --> 86..89]
   J5S2R5 [86..90 -- 52 --> 138..142]
   J5S3R3 [138..142 -- 95 --> 233..237]
   J5S4R8 [233..244 -- 48 --> 281..292]
   J5S5R9 [281..292 -- 72 --> 353..364]
   J5S6R0 [361..364 -- 47 --> 408..411]
   J5S7R6 [420..445 -- 65 --> 485..510]
   J5S8R4 [499..510 -- 6 --> 505..516]
   J5S9R7 [505..516 -- 25 --> 530..541]
   J6S0R1 [86..89 -- 46 --> 132..135]
   J6S1R0 [148 -- 37 --> 185]
   J6S2R3 [233..237 -- 61 --> 294..298]
   J6S3R2 [375..395 -- 13 --> 388..408]
   J6S4R6 [388..408 -- 32 --> 420..440]
   J6S5R5 [421..440 -- 21 --> 442..461]
   J6S6R9 [442..478 -- 32 --> 474..510]
   J6S7R8 [520 -- 89 --> 609]
   J6S8R7 [668..679 -- 30 --> 698..709]
   J6S9R4 [698..740 -- 55 --> 753..795]
   J7S0R2 [179..199 -- 31 --> 210..230]
   J7S1R0 [275..278 -- 86 --> 361..364]
   J7S2R1 [399..402 -- 46 --> 445..448]
   J7S3R5 [445..461 -- 74 --> 519..535]
   J7S4R4 [519..535 -- 32 --> 551..567]
   J7S5R6 [557..567 -- 88 --> 645..655]
   J7S6R8 [699..710 -- 19 --> 718..729]
   J7S7R9 [718..729 -- 48 --> 766..777]
   J7S8R7 [777 -- 36 --> 813]
   J7S9R3 [813..851 -- 79 --> 892..930]
   J8S0R0 [0 -- 76 --> 76]
   J8S1R1 [217..220 -- 69 --> 286..289]
   J8S2R3 [294..298 -- 76 --> 370..374]
   J8S3R5 [370..374 -- 51 --> 421..425]
   J8S4R2 [421..425 -- 85 --> 506..510]
   J8S5R9 [506..510 -- 11 --> 517..521]
   J8S6R6 [517..527 -- 40 --> 557..567]
   J8S7R7 [579..590 -- 89 --> 668..679]
   J8S8R4 [668..714 -- 26 --> 694..740]
   J8S9R8 [718..782 -- 74 --> 792..856]
   J9S0R1 [132..135 -- 85 --> 217..220]
   J9S1R0 [256..259 -- 13 --> 269..272]
   J9S2R2 [314..334 -- 61 --> 375..395]
   J9S3R6 [375..401 -- 7 --> 382..408]
   J9S4R8 [416..435 -- 64 --> 480..499]
   J9S5R9 [517..521 -- 76 --> 593..597]
   J9S6R5 [593..597 -- 47 --> 640..644]
   J9S7R3 [735..743 -- 52 --> 787..795]
   J9S8R4 [787..795 -- 90 --> 877..885]
   J9S9R7 [885 -- 45 --> 930]
*/