the idea is to add a new interval, cleanupTasks[i] following each intervalVar tasks[i] in the sequence var associated with the resource. Then the length of cleanupTasks[i] is constrained to be the transition time between tasks[i] and the next task in the sequence, or to be 0 if tasks[i] is the last task of the sequence.
Original Message:
Sent: Fri January 10, 2025 08:53 PM
From: Ross Dye
Subject: Using Docplex CP and Python
Hi Olivier
and I'm not fluent in C++ ! !
Could you simply describe the methodology please, then I will implement it in my code.
You say you are creating "an intervalVar associated with each transition". Do you mean:
a) one for every gap between production activities (intervalVar), or
b) one where there is a transition created by the transition matrix between intervalVars with different types
Thanks
Ross
------------------------------
Ross Dye
------------------------------
Original Message:
Sent: Fri January 10, 2025 06:21 AM
From: Olivier Lhomme
Subject: Using Docplex CP and Python
Hello,
it suffices to add an objective to minimize the sum of the transition tasks lengths.
First, create an intervalVar associated with each transition.
Then add a constraint to set the length of this interval. This is the tricky part as it depends on the two tasks around it.
Also the case of the last task has to be handled, what can be done by introducing a fake type 0.
You get:
#include <ilcp/cp.h>IloInt NbTypes = 3; // real types are in [1..NbTypes-1], the additional type 0 is used for handling the last taskIloInt Distances[] = { 0, 0, 0, 0, 0, 22, 0, 20, 20};IloInt NbTasks = 2;IloInt TaskDur[] = { 3, 5};IloInt TaskType[] = { 1, 2};IloInt StartMin[] = { 10, 20};IloInt EndMax[] = { 50, 1000};int main(int, const char*[]) { IloEnv env; try { IloModel model(env); IloTransitionDistance distances(env, NbTypes); for (IloInt i = 0; i < NbTypes; ++i) { for (IloInt j = 0; j < NbTypes; ++j) { distances.setValue(i, j, Distances[NbTypes*i+j]); } } IloIntArray distancesArray(env, NbTypes*NbTypes); for (IloInt i = 0; i < NbTypes; ++i) { for (IloInt j = 0; j < NbTypes; ++j) { distancesArray[i*NbTypes+j]= Distances[NbTypes*i+j]; } } IloIntArray tp(env, NbTasks); IloIntervalVarArray tasks(env, NbTasks); IloIntervalVarArray cleanupTasks(env, NbTasks); IloIntervalVarArray alltasks(env); IloIntExprArray transitionLengths(env); char name[100]; for (IloInt i = 0; i < NbTasks; ++i) { IloInt type = TaskType[i]; IloInt d = TaskDur[i]; tp[i] = type; sprintf(name, "tasks%ld_TP%ld", (long)i, (long)type); tasks[i] = IloIntervalVar(env, d, name); tasks[i].setStartMin(StartMin[i]); tasks[i].setEndMax(EndMax[i]); sprintf(name, "cleanup-%ld", (long)i); cleanupTasks[i] = IloIntervalVar(env, name); model.add(IloStartAtEnd(env, cleanupTasks[i], tasks[i])); alltasks.add(tasks[i]); alltasks.add(cleanupTasks[i]); transitionLengths.add(IloLengthOf(cleanupTasks[i])); } IloIntervalSequenceVar s1(env, tasks, tp); model.add(IloNoOverlap(env, s1, distances, IloTrue)); IloIntervalSequenceVar s2(env, alltasks); model.add(IloNoOverlap(env, s2)); for (IloInt i = 0; i < NbTasks; ++i) { model.add(IloLengthOf(cleanupTasks[i]) == distancesArray[NbTypes*tp[i] + IloTypeOfNext(s1, tasks[i], 0)]); } model.add(IloMinimize(env, IloSum(transitionLengths))); IloCP cp(model); if (cp.solve()) { IloIntervalVar act; for (act = cp.getFirst(s2); act.getImpl() != 0; act = cp.getNext(s2, act)) cp.out() << cp.domain(act) << std::endl; } 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