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;
}