IBM ILOG Scheduler User's Manual > Getting Started with Scheduler > Adding Alternative Resources > Complete Program and Output--Example 8

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

#include <ilsched/iloscheduler.h>
 
ILOSTLBEGIN
 
#if defined(ILO_SDXLOUTPUT)
#include "sdxloutput.h"
#endif
 
///////////////////////////////////////////////////////////////////////////////
//
// PROBLEM DEFINITION
//
///////////////////////////////////////////////////////////////////////////////
const char* WorkerNames [] = {
  "joe",
  "jim1",
  "jim2",
  "jack"};
IloNum durationsDesign1 [] = { 7, 3,  8, 3, 1, 2, 1, 2, 1, 1};
IloNum durationsDesign2 [] = {12, 5, 10, 5, 2, 5, 2, 3, 2, 1};
IloNum durationsDesign3 [] = {15, 3, 10, 6, 2, 3, 2, 3, 2, 1};
void MakeHouse(IloModel model,
               const IloNum* dur,
               const IloNum startMin,
               const IloNum endMax,
               const IloUnaryResourceArray workers,
               const IloAltResSet altres,
               const IloNumVar makespan) 
{ 
  IloEnv env = model.getEnv();
 
  /* CREATE THE ACTIVITIES. */
  IloActivity masonry(env,   dur[0], "masonry   ");
  IloActivity carpentry(env, dur[1], "carpentry ");
  IloActivity plumbing(env,  dur[2], "plumbing  ");
  IloActivity ceiling(env,   dur[3], "ceiling   ");
  IloActivity roofing(env,   dur[4], "roofing   ");
  IloActivity painting(env,  dur[5], "painting  ");
  IloActivity windows(env,   dur[6], "windows   ");
  IloActivity facade(env,    dur[7], "facade    ");
  IloActivity garden(env,    dur[8], "garden    ");
  IloActivity moving(env,    dur[9], "moving    ");
  
  /* SET STARTMIN AND ENDMAX. */
  model.add(masonry.startsAfter(startMin));
  model.add(moving.endsBefore(endMax));
  
  /* POST THE TEMPORAL CONSTRAINTS. */
  model.add(carpentry.startsAfterEnd(masonry));
  model.add(plumbing.startsAfterEnd(masonry));
  model.add(ceiling.startsAfterEnd(masonry));
  model.add(roofing.startsAfterEnd(carpentry));
  model.add(painting.startsAfterEnd(ceiling));
  model.add(windows.startsAfterEnd(roofing));
  model.add(facade.startsAfterEnd(roofing));
  model.add(facade.startsAfterEnd(plumbing));
  model.add(garden.startsAfterEnd(roofing));
  model.add(garden.startsAfterEnd(plumbing));
  model.add(moving.startsAfterEnd(windows));
  model.add(moving.startsAfterEnd(facade));
  model.add(moving.startsAfterEnd(garden));
  model.add(moving.startsAfterEnd(painting));
 
  model.add(moving.endsBefore(makespan));
 
  /* POST THE RESOURCE CONSTRAINTS. */ 
  model.add(carpentry.requires(workers[0]));
  model.add(ceiling.requires(workers[0]));
  model.add(roofing.requires(workers[0]));
  model.add(windows.requires(workers[0]));
  model.add(facade.requires(workers[0]));
 
  model.add(masonry.requires(altres));
  model.add(plumbing.requires(altres));
  
  model.add(garden.requires(workers[3]));
  model.add(painting.requires(workers[3]));
  model.add(moving.requires(workers[3]));
}
 
IloModel DefineModel(const IloEnv env, IloNumVar& makespan)
{
  IloModel model(env);
 
  /* CREATE THE MAKESPAN VARIABLE */
  IloNum horizon = 91;
  makespan = IloNumVar(env, 0, horizon, IloNumVar::Int);
  /* SET UP THE SHARED ResourceParam */
  IloSchedulerEnv schedEnv(env);
  schedEnv.getResourceParam().setCapacityEnforcement(IloMediumHigh);  
 
  /* CREATE THE RESOURCES. */
  IloInt nbOfWorkers = 4;
  IloUnaryResourceArray workers(env, nbOfWorkers);
  for (IloInt k = 0; k < nbOfWorkers; k++)
    workers[k] = IloUnaryResource(env, WorkerNames[k]);
  IloAltResSet altres(env, 2, workers[1], workers[2]);
 
  /* CREATE THE ACTIVITIES AND CONSTRAINTS FOR THE HOUSES. */
  MakeHouse(model, durationsDesign1, 0, horizon, workers, altres, makespan);
  MakeHouse(model, durationsDesign1, 0, horizon, workers, altres, makespan);
  MakeHouse(model, durationsDesign2, 5, 57, workers, altres, makespan);
  MakeHouse(model, durationsDesign2, 5, 57, workers, altres, makespan);
  MakeHouse(model, durationsDesign3, 0, horizon, workers, altres, makespan);
  /* SET THE OBJECTIVE */
  model.add(IloMinimize(env, makespan));  
  /* RETURN THE CREATED MODEL. */
  return model;
}
 
///////////////////////////////////////////////////////////////////////////////
//
// PRINTING OF SOLUTIONS
//
///////////////////////////////////////////////////////////////////////////////
 
void PrintSolution(const IloSolver solver, const IloNumVar makespan)
{
  IlcScheduler scheduler(solver);
  IloEnv env = solver.getEnv();
  env.out() << "Solution with makespan " 
            << solver.getIntVar(makespan).getMin() << endl;
 
  for(IloIterator<IloResourceConstraint> rctIter(env);
      rctIter.ok(); ++rctIter) {
    IloResourceConstraint rct = *rctIter;
    if (scheduler.hasAlternative(rct)) {
      IlcAltResConstraint ilcAltRct = scheduler.getAltResConstraint(rct);  
      env.out() << ilcAltRct.getActivity() << "\tuses "
		<< ilcAltRct.getSelected() << endl;
    }
    else {
      IlcResourceConstraint ilcRct = scheduler.getResourceConstraint(rct);
      env.out() << ilcRct.getActivity() << "\tuses "
		<< ilcRct.getResource() << endl;
    }
  }
 
  solver.printInformation();
}
 
///////////////////////////////////////////////////////////////////////////////
//
// MAIN FUNCTION
//
///////////////////////////////////////////////////////////////////////////////
 
int main()
{
  try {
    IloEnv env;
 
    IloNumVar makespan;
    IloModel model = DefineModel(env, makespan);
 
    IloSolver solver(model);   
    IloGoal goal = IloAssignAlternative(env) && IloRankForward(env, makespan);
 
    if (solver.solve(goal)) {
      PrintSolution(solver,makespan);
#if defined(ILO_SDXLOUTPUT)
      IloSDXLOutput output(env);
      ofstream outFile("gsAlt.xml");
      output.write(IlcScheduler(solver), outFile);
      outFile.close();
#endif
    }
    else 
      solver.out() << "No Solution" << endl;
 
    env.end();
    
  } catch (IloException& exc) {
    cout << exc << endl;
  }
  return 0;
}
 
 
///////////////////////////////////////////////////////////////////////////////
//
// RESULTS
//
///////////////////////////////////////////////////////////////////////////////
 
/*
   Solution with makespan 78
   carpentry  [10 -- 3 --> 13]        uses joe [1]
   ceiling    [16 -- 3 --> 19]        uses joe [1]
   roofing    [68 -- 1 --> 69]        uses joe [1]
   windows    [76 -- 1 --> 77]        uses joe [1]
   facade     [71 -- 2 --> 73]        uses joe [1]
   garden     [69..73 -- 1 --> 70..74]        uses jack [1]
   painting   [19..39 -- 2 --> 21..41]        uses jack [1]
   moving     [77 -- 1 --> 78]        uses jack [1]
   carpentry  [7 -- 3 --> 10]        uses joe [1]
   ceiling    [13 -- 3 --> 16]        uses joe [1]
   roofing    [53 -- 1 --> 54]        uses joe [1]
   windows    [75 -- 1 --> 76]        uses joe [1]
   facade     [73 -- 2 --> 75]        uses joe [1]
   garden     [72..75 -- 1 --> 73..76]        uses jack [1]
   painting   [16..37 -- 2 --> 18..39]        uses jack [1]
   moving     [76 -- 1 --> 77]        uses jack [1]
   carpentry  [34 -- 5 --> 39]        uses joe [1]
   ceiling    [29 -- 5 --> 34]        uses joe [1]
   roofing    [41 -- 2 --> 43]        uses joe [1]
   windows    [51 -- 2 --> 53]        uses joe [1]
   facade     [46 -- 3 --> 49]        uses joe [1]
   garden     [43..53 -- 2 --> 45..55]        uses jack [1]
   painting   [34..46 -- 5 --> 39..51]        uses jack [1]
   moving     [53..56 -- 1 --> 54..57]        uses jack [1]
   carpentry  [24 -- 5 --> 29]        uses joe [1]
   ceiling    [19 -- 5 --> 24]        uses joe [1]
   roofing    [39 -- 2 --> 41]        uses joe [1]
   windows    [49 -- 2 --> 51]        uses joe [1]
   facade     [43 -- 3 --> 46]        uses joe [1]
   garden     [41..51 -- 2 --> 43..53]        uses jack [1]
   painting   [24..41 -- 5 --> 29..46]        uses jack [1]
   moving     [51..55 -- 1 --> 52..56]        uses jack [1]
   carpentry  [60 -- 3 --> 63]        uses joe [1]
   ceiling    [54 -- 6 --> 60]        uses joe [1]
   roofing    [63 -- 2 --> 65]        uses joe [1]
   windows    [69 -- 2 --> 71]        uses joe [1]
   facade     [65 -- 3 --> 68]        uses joe [1]
   garden     [65..71 -- 2 --> 67..73]        uses jack [1]
   painting   [60..68 -- 3 --> 63..71]        uses jack [1]
   moving     [71..74 -- 1 --> 72..75]        uses jack [1]
   masonry    [0 -- 7 --> 7]        uses jim2 [1]
   plumbing   [19..63 -- 8 --> 27..71]        uses jim2 [1]
   masonry    [0 -- 7 --> 7]        uses jim1 [1]
   plumbing   [64..65 -- 8 --> 72..73]        uses jim1 [1]
   masonry    [7 -- 12 --> 19]        uses jim2 [1]
   plumbing   [19 -- 10 --> 29]        uses jim1 [1]
   masonry    [7 -- 12 --> 19]        uses jim1 [1]
   plumbing   [29 -- 10 --> 39]        uses jim1 [1]
   masonry    [39 -- 15 --> 54]        uses jim1 [1]
   plumbing   [54..55 -- 10 --> 64..65]        uses jim1 [1]
*/
 

The start and end times of some activities are fixed, while others have variable start and end dates. The total time to complete the project is 78 days.

The results can be interpreted as follows:

ceiling [54 -- 6 --> 60] uses joe [1] This ceiling activity has a start time of 54, a duration of 6, and a completion time of 60. It is performed by joe who has a capacity of 1.

plumbing [54..55 -- 10 --> 64..65] uses jim1 [1] This plumbing activity has an earliest start time of 54, a latest start time of 55, a processing time of 10, an earliest completion time of 64, and a latest completion time of 65. It is performed by jim1 who has a capacity of 1.

Figure 8.1 provides a graphic display of the solution to our problem. Activities with variable start and end times are positioned at their earliest start times.

alternativeResourcesae.gif

Figure 8.1 Building Houses with Alternative Resources