IBM ILOG Scheduler User's Manual > Integrated Applications > Extending Transition Cost Usage > Complete Program and Output

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

#include <ilsched/iloscheduler.h>
 
ILOSTLBEGIN
 
#if defined(ILO_SDXLOUTPUT)
#include "sdxloutput.h"
#endif
 
const IloInt Horizon = 10000;
const IloInt NumberOfJobs = 6;
const IloInt NumberOfResources = 6;
const IloInt NumberOfWorkers = 5;
const IloInt NumberOfTypes = 4;
 
IloInt ResourceNumbers [] = {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 ProcessingTimes [] = { 10,  30,  60,  70,  30,  60,
                              80,  50, 100, 100, 100,  40,
                              50,  40,  80,  90,  10,  70,
                              50,  50,  50,  30,  80,  90,
                              90,  30,  50,  40,  30,  10,
                              30,  30,  90, 100,  40,  10};
 
IloInt Types [] = { 0, 1, 2, 2, 0, 3,
                    1, 3, 2, 3, 3, 0,
                    2, 3, 1, 1, 0, 1,
                    2, 1, 0, 0, 1, 1,
                    3, 3, 2, 0, 1, 1,
                    3, 1, 2, 0, 3, 3};
 
IloInt TableDurations [] = { 0, 16, 14, 19,
                             12, 0, 8, 15,
                             15, 10, 0, 14,
                             16, 15, 17, 0};
 
IloInt SetupDurations [] = { 7, 0, 6, 7};
 
IloInt TableCapacities [] = { 0, 2, 3, 1,
                              2, 0, 4, 2,
                              3, 3, 0, 2,
                              1, 2, 3, 0};
 
IloInt SetupCapacities [] = { 2, 1, 1, 1};
 
///////////////////////////////////////////////////////////////////////////////
//
// PROBLEM DEFINITION
//
///////////////////////////////////////////////////////////////////////////////
 
class StartTCostObjectIlcI : public IlcTransitionCostObjectI {
public:
  StartTCostObjectIlcI();
  ~StartTCostObjectIlcI();
  virtual IlcInt getTransitionCostMax(const IlcResourceConstraint srct1,
                                      const IlcResourceConstraint srct2)
    const;
  virtual IlcInt getTransitionCostMin(const IlcResourceConstraint srct1,
                                      const IlcResourceConstraint srct2)
    const;
  virtual IlcInt getSetupCostMin(const IlcResourceConstraint srct1) const;
  virtual IlcInt getSetupCostMax(const IlcResourceConstraint srct1) const;
  virtual IlcInt getTeardownCostMin(const IlcResourceConstraint srct1)
    const;
  virtual IlcInt getTeardownCostMax(const IlcResourceConstraint srct1)
    const;
};
 
StartTCostObjectIlcI::StartTCostObjectIlcI()
  :IlcTransitionCostObjectI(IlcTrue)
{}
 
StartTCostObjectIlcI::~StartTCostObjectIlcI() {}
 
IlcInt
StartTCostObjectIlcI::getTransitionCostMax(const IlcResourceConstraint,
                                           const IlcResourceConstraint srct2)
  const {
  return srct2.getActivity().getStartMax();
}
 
IlcInt
StartTCostObjectIlcI::getTransitionCostMin(const IlcResourceConstraint,
                                           const IlcResourceConstraint srct2)
  const {
  return srct2.getActivity().getStartMin();
}
 
IlcInt
StartTCostObjectIlcI::getSetupCostMin(const IlcResourceConstraint srct1)
  const {
  return srct1.getActivity().getStartMin();
}
 
IlcInt
StartTCostObjectIlcI::getSetupCostMax(const IlcResourceConstraint srct1)
  const {
  return srct1.getActivity().getStartMax();
}
 
IlcInt
StartTCostObjectIlcI::getTeardownCostMin(const IlcResourceConstraint srct1)
  const {
  return srct1.getActivity().getEndMin();
}
 
IlcInt
StartTCostObjectIlcI::getTeardownCostMax(const IlcResourceConstraint srct1)
  const {
  return srct1.getActivity().getEndMax();
}
 
ILOTRANSITIONCOSTOBJECT0(StartTCostObject, solver) {
  return new (solver.getHeap()) StartTCostObjectIlcI();
}
 
/* CREATION OF A MACHINE */
IloUnaryResource
MakeMachine(IloModel model, const char* name) {
  IloUnaryResource machine(model.getEnv(), name);
  machine.setCapacityEnforcement(IloHigh);
  return machine;
}
 
/* CREATION OF A TASK */
IloActivity
MakeTask(IloModel model,
         IloUnaryResource machine,
         IloInt type,
         IloInt procTime,
         IloInt setupTime,
         const char* name,
         IloResourceConstraint& rct) {
  IloActivity act(model.getEnv(), procTime, type, name);
  act.setStartMin(setupTime);
  rct = act.requires(machine);
  model.add(rct);
  return act;
}
 
IloActivity
MakeMaintenanceTask(IloModel model,
                    IloResourceConstraint rct,
                    IloDiscreteResource workers,
                    IloTransitionCost durTCost,
                    IloTransitionCost capTCost,
                    const char* name) {
  IloEnv env = model.getEnv();
  IloNumVar ptVar(env, 0, IloInfinity, ILOINT);
  IloActivity act(env, ptVar);  
  model.add(ptVar == durTCost.getNextCostExpr(rct));
  act.setName(name);   
  model.add(act.startsAfterEnd(rct.getActivity()));
  IloNumVar capVar(env, 0, IloInfinity, ILOINT);
  model.add(act.requires(workers, capVar));
  model.add(capVar == capTCost.getNextCostExpr(rct));
  // Mark maintenance activity
  act.setObject((IloAny)1);
  return act;
}
 
IloActivity
MakeSetupTask(IloModel model,
              IloDiscreteResource workers,
              IloTransitionCost durTCost,
              IloTransitionCost capTCost,
              const char* name) {
  IloEnv env = model.getEnv();
  IloNumVar ptVar(env, 0, IloInfinity, ILOINT);
  IloActivity act(env, ptVar);
  model.add(ptVar == durTCost.getSetupCostExpr());
  act.setName(name);
  // Mark maintenance activity
  act.setObject((IloAny)1);
  IloNumVar capVar(env, 0, IloInfinity, ILOINT);
  model.add(act.requires(workers, capVar));
  model.add(capVar == capTCost.getSetupCostExpr());
  return act;
}
 
void DefineProblem(IloModel model,
                   IloInt horizon,
                   IloInt numberOfJobs,
                   IloInt numberOfResources,
                   IloInt numberOfWorkers,
                   IloInt numberOfTypes,
                   IloInt* resourceNumbers,
                   IloInt* processingTimes,
                   IloInt* types,
                   IloInt* tableDurations,
                   IloInt* tableCapacities,
                   IloInt* setupDurations,
                   IloInt* setupCapacities,
                   IloNumVar& makespan,
                   IloTransitionParam& enerTParam,
                   IloDiscreteResource& workers) {
  /* CREATE THE MAKESPAN VARIABLE. */
  IloEnv env = model.getEnv();
  makespan = IloNumVar(env, 0, horizon, IloNumVar::Int);
 
  IloUnaryResource* machines =
    new (env) IloUnaryResource[NumberOfResources];
  
  char buffer[128];
  IloInt i, j, k;
  
  /* CREATE THE TRANSITION FUNCTIONS. */
  enerTParam = IloTransitionParam(env, numberOfTypes);
  IloTransitionParam durTParam(env, numberOfTypes);
  IloTransitionParam capTParam(env, numberOfTypes);
  IloTransitionCostObject startTCostObj =
    StartTCostObject(env);
 
  for (i = 0; i < numberOfTypes; ++i) {
    durTParam.setSetup(i, setupDurations[i]);
    capTParam.setSetup(i, setupCapacities[i]);
    enerTParam.setSetup(i, setupDurations[i] * setupCapacities[i]);
    IloInt index = i * numberOfTypes;
    for(j = 0 ; j < numberOfTypes; ++j) {
      durTParam.setValue(i, j, tableDurations[index]);
      capTParam.setValue(i, j, tableCapacities[index]);
      enerTParam.setValue(i, j, tableDurations[index] *
                          tableCapacities[index]);
      ++index;
    }
  }
 
  /* CREATE THE WORKERS RESOURCE. */
  workers = IloDiscreteResource(env, numberOfWorkers, "Workers");
  
  /* CREATE THE RESOURCES AND SETUP TASKS. */
  IloTransitionCost* costs =
    new (env) IloTransitionCost[3 * NumberOfResources];
  for (j = 0; j < numberOfResources; j++) {
    sprintf(buffer, "Machine%ld", j);
    machines[j] = MakeMachine(model, buffer);
    IloTransitionTime durTTime(machines[j], durTParam);
    costs[j] = 
      IloTransitionCost(machines[j], durTParam);
    costs[j+NumberOfResources] =
      IloTransitionCost(machines[j], capTParam);
    costs[j+2*NumberOfResources] =
      IloTransitionCost(machines[j], startTCostObj);
 
    sprintf(buffer, "Setup%ld", j);
    IloActivity stask = MakeSetupTask(model,
                                      workers,
                                      costs[j],
                                      costs[j+NumberOfResources],
                                      buffer);
    IloTransitionCost cost = costs[j+2*numberOfResources];
    IloNumVar delayVar(env, 0, IloInfinity, ILOINT);
    model.add(stask.endsBefore(delayVar));
    model.add(delayVar == cost.getSetupCostExpr());
  }
  
  /* CREATE THE ACTIVITIES, THE TEMPORAL CONSTRAINTS 
     AND MAINTENANCE TASKS. */
  k = 0;
  for (i = 0; i < numberOfJobs; i++) {
    IloActivity previousTask;
    for (j = 0; j < numberOfResources; j++) {
      IloInt number = resourceNumbers[k];
      sprintf(buffer, "J%ldS%ldR%ldT%ld", i, j, number, types[k]);
      IloResourceConstraint rct;
      IloActivity task = MakeTask(model,
                                  machines[number],
                                  types[k],
                                  processingTimes[k],
                                  setupDurations[types[k]],
                                  buffer,
                                  rct);
      if (0 != j)
        model.add(task.startsAfterEnd(previousTask));
      previousTask = task;
 
      IloActivity mtask = MakeMaintenanceTask(model,
                                              rct,
                                              workers,
                                              costs[number],
                                              costs[number+numberOfResources],
                                              buffer);
      
      IloTransitionCost cost = costs[number+2*numberOfResources];
      IloNumVar delayVar(env, 0, IloInfinity, ILOINT);
      model.add(mtask.endsBefore(delayVar));
      model.add(delayVar == cost.getNextCostExpr(rct));
      k++;
    }
    model.add(previousTask.endsBefore(makespan));;
  }
 
  model.add(IloMinimize(env, makespan));
}
 
///////////////////////////////////////////////////////////////////////////////
//
// PRINTING OF SOLUTION
//
///////////////////////////////////////////////////////////////////////////////
 
void PrintSolution(IloSolver& solver,
                   IloDiscreteResource workers) {
  IlcScheduler scheduler(solver);
  for(IlcUnaryResourceIterator iter(scheduler); iter.ok(); ++iter) {
    IlcUnaryResource machine = *iter;
    solver.out() << endl << "Machine : " << machine << endl;
    IlcInt index = machine.getSetupVar().getValue();
    IlcInt sink = machine.getTeardownIndex();
    while(index != sink) {
      IlcResourceConstraint rct = machine.getSequenceRC(index);
      solver.out() << "\t" << rct.getActivity() << endl;
      index = rct.getNextVar().getValue();
    }
  }
  solver.out() << endl;
  solver.out() << workers << endl;
  for(IlcResourceConstraintIterator iter2(scheduler.getResource(workers));
      iter2.ok(); ++iter2) {
    solver.out() <<  "\t" << (*iter2).getActivity() << endl;
  }
}
 
///////////////////////////////////////////////////////////////////////////////
//
// SOLVING PROBLEM
//
///////////////////////////////////////////////////////////////////////////////
 
/* CREATE A SELECTOR FOR THE ACTIVITIES ON THE WORKERS RESOURCE. */
 
ILOPREDICATE0(MaintenanceTaskPredicate, IlcActivity, act) {
  return (act.getObject() != 0);
}
 
/* CREATE SEARCH GOAL. */
ILCGOAL2(SolveIlc,
         IlcIntVar, makespan,
         IlcTransitionCostObject, enerTCostObjIlc) {
  IloSolver solver = getSolver();
  IlcScheduler scheduler (solver);
 
  IloPredicate<IlcActivity> predA = !IlcActivityStartVarBoundPredicate(solver) 
    && !IlcActivityPostponedPredicate(solver)
    && MaintenanceTaskPredicate(solver);
  IloComparator<IlcActivity> compA = 
    IloComposeLexical(IlcActivityStartMinEvaluator(solver).makeLessThanComparator(),
		      IlcActivityEndMaxEvaluator(solver).makeLessThanComparator());
 
  IloSelector<IlcActivity,IlcSchedule> maintenanceTaskSelector =
    IloBestSelector<IlcActivity,IlcSchedule>(predA, compA);
 
  IloEvaluator<IlcResourceConstraint> eval = 
    IlcResourceConstraintNextTransitionCostEvaluator(solver,enerTCostObjIlc);
  IloTranslator<IlcActivity, IlcResourceConstraint> ac = 
    IlcActivityResourceConstraintTranslator(solver);
 
  IloSelector<IlcResourceConstraint,IlcResourceConstraint> selector =
    IloBestSelector<IlcResourceConstraint,IlcResourceConstraint>(
       IloComposeLexical((IlcActivityStartMinEvaluator(solver) << ac).makeLessThanComparator(),
			 eval.makeLessThanComparator(),
			 (IlcActivityEndMaxEvaluator(solver) << ac).makeLessThanComparator()));
 
  return IlcAnd(IlcSequence(scheduler, selector),
                IlcSetTimes(scheduler, makespan,
                            maintenanceTaskSelector));
}
 
ILOCPGOALWRAPPER2(Solve, solver,
                  IloNumVar, makespan,
                  IloTransitionParam, enerTParam) {
  IlcScheduler scheduler(solver);
  return SolveIlc(solver, 
                  solver.getIntVar(makespan),
                  scheduler.getTransitionCostObject(enerTParam));
}
 
int main() {
  try {
    IloEnv env;
    IloModel model(env);
    IloNumVar makespan;
    IloTransitionParam enerTParam;
    IloDiscreteResource workers;
    DefineProblem(model,
                  Horizon,
                  NumberOfJobs,
                  NumberOfResources,
                  NumberOfWorkers,
                  NumberOfTypes,
                  ResourceNumbers,
                  ProcessingTimes,
                  Types,
                  TableDurations,
                  TableCapacities,
                  SetupDurations,
                  SetupCapacities,
                  makespan,
                  enerTParam,
                  workers);
 
    IloSolver solver(model);
    if (solver.solve(Solve(env, makespan, enerTParam))) {
 
      env.out() << " Solution with makespan : "
                << solver.getIntVar(makespan) << endl;
      PrintSolution(solver, workers);
 
#if defined(ILO_SDXLOUTPUT)
      IloSDXLOutput output(env);
      ofstream outFile("maintain.xml");
      output.write(IlcScheduler(solver), outFile, solver.getIntVar(makespan));
      outFile.close();
#endif
    } else
      env.out() << "No solution " << endl;
    env.end();
  } catch (IloException& exc) {
    cout << exc << endl;
  }
  return 0;
}