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

You can see the entire program bridge.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
//
///////////////////////////////////////////////////////////////////////////////
void NameVariable(IloNumExpr& var,
                  const char* actName, const char* varName) {
  char* s = new char [strlen(actName) + strlen(varName) + 1];
  sprintf(s,"%s%s", actName, varName);
  var.setName(s);
  delete [] s;
}
 
IloActivity
MakeActivity(IloModel model,
             const char* name,
             IloInt duration)
{
  IloEnv env = model.getEnv();
  IloActivity activity(env, duration, 0, name);
  IloNumExpr startVar = activity.getStartExpr();
  IloNumExpr endVar   = activity.getEndExpr();
  NameVariable(startVar, name, "start");
  NameVariable(endVar,   name, "end");
  return activity;
}
void
MakeResource(IloModel model,
             const char* name,
             IloInt numberOfActivities,
             IloActivityArray activities)
{
  IloEnv env = model.getEnv();
  IloUnaryResource resource(env, name);
  for (IloInt i = 0; i < numberOfActivities; i++)
    model.add(activities[i].requires(resource));
}
IloModel
DefineModel(IloEnv env, IloNumVar& makespan)
{
  IloModel model(env);
  IloSchedulerEnv schedEnv(env);
  schedEnv.getResourceParam().setCapacityEnforcement(IloMediumHigh);
  IloInt horizon = 365;
  schedEnv.setHorizon(horizon);
 
  /* CREATE ACTIVITIES AND RESOURCES: EXCAVATIONS. */
  IloActivity A1 = MakeActivity(model, "A1", 4);
  IloActivity A2 = MakeActivity(model, "A2", 2);
  IloActivity A3 = MakeActivity(model, "A3", 2);
  IloActivity A4 = MakeActivity(model, "A4", 2);
  IloActivity A5 = MakeActivity(model, "A5", 2);
  IloActivity A6 = MakeActivity(model, "A6", 5);
  IloActivityArray A(env,6);
  A[0]=A1; A[1]=A2; A[2]=A3; A[3]=A4; A[4]=A5; A[5]=A6;
  MakeResource(model, "EXCAVATOR", 6, A);
  
  /* CREATE ACTIVITIES AND RESOURCES: FOUNDATIONS. */
  IloActivity P1 = MakeActivity(model, "P1", 20);
  IloActivity P2 = MakeActivity(model, "P2", 13);
  IloActivityArray P(env,2);
  P[0]=P1; P[1]=P2;
  MakeResource(model, "PILE DRIVER", 2, P);
 
  /* CREATE ACTIVITIES AND RESOURCES: FORMWORKS. */
  IloActivity S1 = MakeActivity(model, "S1", 8);
  IloActivity S2 = MakeActivity(model, "S2", 4);
  IloActivity S3 = MakeActivity(model, "S3", 4);
  IloActivity S4 = MakeActivity(model, "S4", 4);
  IloActivity S5 = MakeActivity(model, "S5", 4);
  IloActivity S6 = MakeActivity(model, "S6", 10);
  IloActivityArray S(env,6);
  S[0]=S1; S[1]=S2; S[2]=S3; S[3]=S4; S[4]=S5; S[5]=S6;
  MakeResource(model, "CARPENTRY", 6, S);
 
  /* CREATE ACTIVITIES AND RESOURCES: CONCRETE FOUNDATIONS. */
  IloActivity B1 = MakeActivity(model, "B1", 1);
  IloActivity B2 = MakeActivity(model, "B2", 1);
  IloActivity B3 = MakeActivity(model, "B3", 1);
  IloActivity B4 = MakeActivity(model, "B4", 1);
  IloActivity B5 = MakeActivity(model, "B5", 1);
  IloActivity B6 = MakeActivity(model, "B6", 1);
  IloActivityArray B(env,6);
  B[0]=B1; B[1]=B2; B[2]=B3; B[3]=B4; B[4]=B5; B[5]=B6;
  MakeResource(model, "CONCRETE MIXER", 6, B);
 
  /* CREATE ACTIVITIES AND RESOURCES: CONCRETE SETTING TIMES. */
  IloActivity AB1 = MakeActivity(model, "AB1", 1);
  IloActivity AB2 = MakeActivity(model, "AB2", 1);
  IloActivity AB3 = MakeActivity(model, "AB3", 1);
  IloActivity AB4 = MakeActivity(model, "AB4", 1);
  IloActivity AB5 = MakeActivity(model, "AB5", 1);
  IloActivity AB6 = MakeActivity(model, "AB6", 1);
  IloActivityArray AB(env,6);
  AB[0]=AB1; AB[1]=AB2; AB[2]=AB3; AB[3]=AB4; AB[4]=AB5; AB[5]=AB6;
  
  /* CREATE ACTIVITIES AND RESOURCES: MASONRY. */
  IloActivity M1 = MakeActivity(model, "M1", 16);
  IloActivity M2 = MakeActivity(model, "M2", 8);
  IloActivity M3 = MakeActivity(model, "M3", 8);
  IloActivity M4 = MakeActivity(model, "M4", 8);
  IloActivity M5 = MakeActivity(model, "M5", 8);
  IloActivity M6 = MakeActivity(model, "M6", 20);
  IloActivityArray M(env,6);
  M[0]=M1; M[1]=M2; M[2]=M3; M[3]=M4; M[4]=M5; M[5]=M6;
  MakeResource(model, "BRICKLAYING", 6, M);
 
  /* CREATE ACTIVITIES: POSITIONING. */
  IloActivity T1 = MakeActivity(model, "T1", 12);
  IloActivity T2 = MakeActivity(model, "T2", 12);
  IloActivity T3 = MakeActivity(model, "T3", 12);
  IloActivity T4 = MakeActivity(model, "T4", 12);
  IloActivity T5 = MakeActivity(model, "T5", 12);
  IloActivityArray T(env,5);
  T[0]=T1; T[1]=T2; T[2]=T3; T[3]=T4; T[4]=T5;
  MakeResource(model, "CRANE", 5, T);
 
  /* CREATE ACTIVITIES: FILLING. */
  IloActivity V1 = MakeActivity(model, "V1", 15);
  IloActivity V2 = MakeActivity(model, "V2", 10);
  IloActivityArray V(env,2);
  V[0]=V1; V[1]=V2;
  MakeResource(model, "CATERPILLAR", 2, V);
 
  /* CREATE ACTIVITIES: DELIVERY OF THE PREFORMED BEARERS. */
  IloActivity L = MakeActivity(model, "L",  2);
 
  /* CREATE ACTIVITIES: REMOVAL OF THE TEMPORARY HOUSINGS. */
  IloActivity UE = MakeActivity(model, "UE", 10);
  IloActivity UA = MakeActivity(model, "UA", 10);
  /* CREATE ACTIVITIES: PROJECT END. THE makespan POINTER IS SET TO
     THE END-TIME VARIABLE OF THE PROJECT END. */
  IloActivity PE = MakeActivity(model, "PE", 0);
  makespan = IloNumVar(env, 0, IloInfinity, ILOINT);
  model.add(PE.endsAt(makespan));
 
 
  /* DELIVERY OF THE PREFORMED BEARERS OCCURS EXACTLY 30 DAYS AFTER
     THE BEGINNING OF THE PROJECT. */
  L.setStartMin(30);
 
  IloInt k;
  for(k = 0; k < 5; k++) {
    /* POSITIONING STARTS AFTER THE DELIVERY OF THE PREFORMED BEARERS. */
    model.add(T[k].startsAfterEnd(L));
    /* MASONRY WORKS M[k] AND M[k + 1] PRECEDE POSITIONING T[k]. */
    model.add(T[k].startsAfterEnd(M[k]));
    model.add(T[k].startsAfterEnd(M[k + 1]));
  }
 
  for(k = 0; k < 6; k++) {
    /* FORMWORKS Sk PRECEDE CONCRETE FOUNDATIONS Bk. */
    model.add(B[k].startsAfterEnd(S[k]));
    /* CONCRETE FOUNDATIONS Bk PRECEDE CONCRETE SETTING TIMES ABk. */
    model.add(AB[k].startsAfterEnd(B[k]));
    /* CONCRETE SETTING TIMES ABk PRECEDE MASONRIES Mk. */
    model.add(M[k].startsAfterEnd(AB[k]));
    /* THE TIME BETWEEN THE COMPLETION OF A FORMWORK Sk AND THE
       COMPLETION OF ITS CORRESPONDING CONCRETE FOUNDATION Bk IS AT
       MOST 4 DAYS. */
    model.add(S[k].endsAfterEnd(B[k], -4));
    /* FORMWORKS Sk MUST BEGIN AT LEAST SIX DAYS AFTER THE BEGINNING
       OF ERECTION OF TEMPORARY HOUSING UE. */
    model.add(S[k].startsAfterStart(UE, 6));
    /* THE REMOVAL OF THE TEMPORARY HOUSING UA CAN START TWO DAYS
       BEFORE THE END OF THE LAST MASONRY WORK. */
    model.add(UA.startsAfterEnd(M[k], -2));
  }
 
  /* EXCAVATIONS PRECEDE FOUNDATIONS. */
  model.add(P1.startsAfterEnd(A3));
  model.add(P2.startsAfterEnd(A4));
 
  /* EXCAVATIONS AND FOUNDATIONS PRECEDE FORMWORKS. */
  model.add(S1.startsAfterEnd(A1));
  model.add(S2.startsAfterEnd(A2));
  model.add(S3.startsAfterEnd(P1));
  model.add(S4.startsAfterEnd(P2));
  model.add(S5.startsAfterEnd(A5));
  model.add(S6.startsAfterEnd(A6));
  /* POSITIONING OF BEARERS PRECEDE FILLING. */
  model.add(V1.startsAfterEnd(T1));
  model.add(V2.startsAfterEnd(T5));
 
  /* THERE ARE AT MOST THREE DAYS BEFORE THE END OF A PARTICULAR
     EXCAVATION (OR FOUNDATION PILES) AND THE BEGINNING OF THE
     CORRESPONDING FORMWORK. */
  model.add(A1.endsAfterStart(S1, -3));
  model.add(A2.endsAfterStart(S2, -3));
  model.add(P1.endsAfterStart(S3, -3));
  model.add(P2.endsAfterStart(S4, -3));
  model.add(A5.endsAfterStart(S5, -3));
  model.add(A6.endsAfterStart(S6, -3));
 
  /* PROJECT END. */
  model.add(PE.startsAfterEnd(V1));
  model.add(PE.startsAfterEnd(T2));
  model.add(PE.startsAfterEnd(T3));
  model.add(PE.startsAfterEnd(T4));
  model.add(PE.startsAfterEnd(V2));
  model.add(PE.startsAfterEnd(UA));
 
  /* RETURN THE CREATED MODEL. */
  return model;
}
 
///////////////////////////////////////////////////////////////////////////////
//
// PRINTING OF SOLUTIONS
//
///////////////////////////////////////////////////////////////////////////////
 
void
PrintSolution(const IloSolver& solver)
{
  IlcScheduler scheduler(solver);
  IloEnv env = solver.getEnv();
  for(IloIterator<IloActivity> ite(env); ite.ok(); ++ite)
    solver.out() << scheduler.getActivity(*ite) << endl;
}
 
///////////////////////////////////////////////////////////////////////////////
//
// MAIN FUNCTION
//
///////////////////////////////////////////////////////////////////////////////
 
int main()
{
  try {
    IloEnv env;
 
    // Model
    IloNumVar makespan;
    IloModel model = DefineModel(env, makespan);
    model.add(IloMinimize(env, makespan));
 
    IloSolver solver(model);
    IloGoal goal = IloRankForward(env, makespan);
 
    if (solver.solve(goal)) {
      PrintSolution(solver);
      solver.printInformation();
      
#if defined(ILO_SDXLOUTPUT)
      IloSDXLOutput output(env);
      ofstream outFile("bridge.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
//
///////////////////////////////////////////////////////////////////////////////
 
/*
  A1 [4..6 -- 4 --> 8..10]
  A2 [2..4 -- 2 --> 4..6]
  A3 [8..24 -- 2 --> 10..26]
  A4 [0..2 -- 2 --> 2..4]
  A5 [17..28 -- 2 --> 19..30]
  A6 [19..31 -- 5 --> 24..36]
  P1 [15..26 -- 20 --> 35..46]
  P2 [2..13 -- 13 --> 15..26]
  S1 [10 -- 8 --> 18]
  S2 [6 -- 4 --> 10]
  S3 [36..46 -- 4 --> 40..50]
  S4 [18..26 -- 4 --> 22..30]
  S5 [22..30 -- 4 --> 26..34]
  S6 [26..36 -- 10 --> 36..46]
  B1 [18 -- 1 --> 19]
  B2 [10 -- 1 --> 11]
  B3 [40..50 -- 1 --> 41..51]
  B4 [22..33 -- 1 --> 23..34]
  B5 [26..34 -- 1 --> 27..35]
  B6 [36..49 -- 1 --> 37..50]
  AB1 [19 -- 1 --> 20]
  AB2 [11 -- 1 --> 12]
  AB3 [41..51 -- 1 --> 42..52]
  AB4 [23..43 -- 1 --> 24..44]
  AB5 [27..35 -- 1 --> 28..36]
  AB6 [37..59 -- 1 --> 38..60]
  M1 [20 -- 16 --> 36]
  M2 [12 -- 8 --> 20]
  M3 [52 -- 8 --> 60]
  M4 [44 -- 8 --> 52]
  M5 [36 -- 8 --> 44]
  M6 [60 -- 20 --> 80]
  T1 [36..44 -- 12 --> 48..56]
  T2 [92 -- 12 --> 104]
  T3 [64..68 -- 12 --> 76..80]
  T4 [52..56 -- 12 --> 64..68]
  T5 [80 -- 12 --> 92]
  V1 [48..79 -- 15 --> 63..94]
  V2 [92..94 -- 10 --> 102..104]
  L [30..42 -- 2 --> 32..44]
  UE [0 -- 10 --> 10]
  UA [78..94 -- 10 --> 88..104]
  PE [104 -- 0 --> 104]
  Number of fails               : 83
  Number of choice points       : 102
  Number of variables           : 129
  Number of constraints         : 170
  Reversible stack (bytes)      : 20124
  Solver heap (bytes)           : 56304
  Solver global heap (bytes)    : 112696
  And stack (bytes)             : 4044
  Or stack (bytes)              : 4044
  Search Stack (bytes)          : 4044
  Constraint queue (bytes)      : 11144
  Total memory used (bytes)     : 212400
  Elapsed time since creation   : 0.681
*/
 

The output shows each activity, identified by its name, followed by information about its place in the schedule. This information is enclosed in square brackets. It consists of three items: start time, duration, and end time of the activity. Each item can be represented either as a single value or as an interval. If the item is represented as an interval, it appears as two integers separated by two dots.

For example, activity A1 can begin during the interval day 4 to day 6; it lasts four days, and terminates in the interval day 8 to day 10.