Hello Andy,
an idea is to introduce an interval of length 24 starting at the start of each task A, and then enforce that over this interval, there is no more than 10 hours used. You can use overlapLength to get the length of the overlapping between this new interval and another task. Then by summing the length of the task A and the overlapping lengths of all the other tasks sharing the same resource, you have the usage of the resource on this 24h interval.
Modifying the sched_openshop.cpp example we get the code below.
Regards
#include <ilcp/cp.h>
#define WINDOW 24
#define LIMIT 10
class FileError: public IloException {
public:
FileError() : IloException("Cannot open data file") {}
};
int main(int argc, const char* argv[]) {
IloEnv env;
try {
const char* filename = "../../../examples/data/jobshop_default.data";
if (argc > 1)
filename = argv[1];
std::ifstream file(filename);
if (!file) {
env.out() << "usage: " << argv[0] << " <file>" << std::endl;
throw FileError();
}
IloModel model(env);
IloInt nbJobs, nbMachines;
file >> nbJobs;
file >> nbMachines;
IloIntervalVarArray2 machines(env, nbMachines);
for (IloInt j = 0; j < nbMachines; j++)
machines[j] = IloIntervalVarArray(env);
IloIntExprArray ends(env);
IloInt totald = 0;
for (IloInt i = 0; i < nbJobs; i++) {
IloIntervalVar prec;
for (IloInt j = 0; j < nbMachines; j++) {
IloInt m, d;
file >> m;
file >> d;
totald += d;
IloIntervalVar ti(env, d);
machines[m].add(ti);
if (0 != prec.getImpl())
model.add(IloEndBeforeStart(env, prec, ti));
prec = ti;
}
ends.add(IloEndOf(prec));
}
for (IloInt j = 0; j < nbMachines; j++)
model.add(IloNoOverlap(env, machines[j]));
IloObjective objective = IloMinimize(env, IloMax(ends));
model.add(objective);
// Sliding window energy limit
for (IloInt m = 0; m < nbMachines; m++) {
for (IloInt t = 0; t < machines[m].getSize(); t++) {
IloIntervalVar itv = machines[m][t];
IloIntervalVar shadow(env, WINDOW);
model.add(IloStartAtStart(env, shadow, itv));
IloIntExpr over(env, 0);
for (IloInt other = 0; other < machines[m].getSize(); other++) {
if (other != t) {
over += IloOverlapLength(env, machines[m][other], shadow);
}
}
model.add(IloLengthOf(itv) + over <= LIMIT);
}
}
IloCP cp(model);
cp.out() << "Instance \t: " << filename << std::endl;
cp.out() << "Total duration \t: " << totald << std::endl;
if (cp.solve()) {
cp.out() << "Makespan \t: " << cp.getObjValue() << std::endl;
IloInt ms = (IloInt)cp.getObjValue();
// Check energy limit
for (IloInt m = 0; m < nbMachines; m++) {
cp.out() << "Machine " << m << std::endl;
IloIntArray igral(env, ms);
for (IloInt k = 0; k < ms; k++)
igral[k] = 0;
for (IloInt t = 0; t < machines[m].getSize(); t++) {
IloIntervalVar itv = machines[m][t];
IloInt s = cp.getStart(itv);
IloInt e = cp.getEnd(itv);
for (IloInt k = s; k < e; k++)
igral[k] += k - s + 1;
for (IloInt k = e; k < ms; k++)
igral[k] += (e - s);
}
for (IloInt k = WINDOW; k < ms; k++) {
if (igral[k] - igral[k-WINDOW] > LIMIT) {
cp.out() << "VIOLATION on machine " << m << " in window [" << k - 24 << ", " << k << ")" << std::endl;
}
}
igral.end();
}
}
else {
cp.out() << "No solution found." << std::endl;
}
cp.end();
}
catch (IloException& ex) {
env.out() << "Caught: " << ex << std::endl;
}
env.end();
return 0;
}
------------------------------
Olivier Lhomme
------------------------------