Originally posted by: SystemAdmin
Hello,
This is how I would model your problem with OPL using CP Optimizer.
I would create an integer decision variable (nbProducts[p]) to represent the quantity of each product and an interval decision variable (ops[p][w]) for each operation of the jobs.
Then, the constraints would:
(1) Link the operation durations with the number of products to produce
(2) Define precedence constraints between operations of the same job (endBeforeStart)
(3) Model limited number of resources. Here for each work, we can use a cumul function (machineUsage[w]) that counts the number of operations simultaneously performing work w at a given time and constrain this cumul function to be lower than the number of machines available to perform this work (NumberOfMachines[w]).
Here is the full OPL model. Note that I generated some values for the product revenues as these values where not given in your question. I chose values in such a way that the products are more or less equivalent when considering the ratio revenue/duration. I'm also changing the values of some parameters for the search to improve the performances. In particular, I'm using here a search phase to tell the engine to first work on the variables nbProducts.
using CP;
int NbWorks = 3; range Works = 1..NbWorks;
int NumberOfMachines[Works] = [2, 1, 3];
int NbProducts = 7; range Products = 1..NbProducts;
float Revenue[Products] = [550, 600, 1000, 1100, 990, 700, 720];
int WorkingTime[Works][Products] = [ [120, 125, 180, 230, 230, 120, 120], [ 80, 95, 110, 150, 150, 90, 90], [ 50, 45, 190, 100, 100, 130, 130] ];
int Horizon = 8*60*60;
// 8h shift in seconds (28800)
// Max number of products
int MaxNbProducts[p in Products] = Horizon div (sum(w in Works) WorkingTime[w][p]);
// Decision variables dvar
int nbProducts[p in Products] in 0..MaxNbProducts[p]; dvar interval ops[Products][Works] in 0..Horizon; cumulFunction machineUsage[w in Works] = sum(p in Products) pulse(ops[p][w], 1); execute
{ cp.param.TimeLimit = 10; cp.param.CumulFunctionInferenceLevel =
"Extended"; cp.setSearchPhases(cp.factory.searchPhase(nbProducts));
} maximize sum(p in Products) nbProducts[p]*Revenue[p]; subject to
{ forall(p in Products)
{ forall (w in Works)
{ nbProducts[p] == sizeOf(ops[p][w]) div WorkingTime[w][p];
// Constraint (1)
if (1<w) endBeforeStart(ops[p][w-1], ops[p][w]);
// Constraint (2)
}
} forall(w in Works) machineUsage[w] <= NumberOfMachines[w];
// Constraint (3)
};
After 10s, the best solution found is looking like the one attached in the gif file.
Hope it helps,
Philippe
#ConstraintProgramming-General#DecisionOptimization