/********************************************* * OPL 12.9.0.0 Model * Author: harry * Creation Date: 28 jun. 2020 at 14:00:22 *********************************************/ string paramsread=...; // Tiempo L1 string paramsread2=...; // Tiempo L2 string paramsread3=...; // Tupla Task string paramsread4=...; // Tupla PredTask string paramsread5=...; // Tiempo LCM string paramsread6=...; // Envio Tiempo computacion string paramsread7=...; // Envio tamaño buffer ah[1] string paramsread8=...; // Envio tamaño buffer ah[2] string paramsread9=...; // Envio tamaño buffer zh[1] string paramsread10=...; // Envio tamaño buffer zh[2] int tiempo_L1=...; int tiempo_L2=...; int tiempo_LCM=...; int ah1; // Envio ah[1] int ah2; // Envio ah[2] int zh1; // Envio zh[1] int zh2; // Envio zh[2] float before; // Envio el tiempo de computacion /******* GAP = 0.9999 *******/ int nbL=...; // número de líneas range H = 1..nbL; // Conjunto de lineas int cth[H]=[tiempo_L1,tiempo_L2]; // Tiempo de ciclo de linea h para todo H. execute{ writeln("cth: "+ cth); } int LCM = tiempo_LCM; // LCM de las líneas {float} qh[h in H]= {LCM/cth[h]}; // Número undiades a producir durante el tiempo LCM /**** Se convierte el valor float de qh[h] a int, para linea 1 y linea 2 ****/ {float} qh_1 = qh[1]; float qh__1 = item(qh_1,0); int qh1 = ftoi(qh__1); {float} qh_2 = qh[2]; float qh__2 = item(qh_2,0); int qh2 = ftoi(qh__2); /**** Se obtiene el número de unidades, para linea 1 y linea 2 ****/ range ciclo1 = 1..qh1; /// Rango utilizado para las uniades y el ciclo de la línea 1 {int} Ciclo1 = asSet(ciclo1); // crea un conjunto de un rango { 1 , 2 , .. ,4} range ciclo2 = 1..qh2; /// Rango utilizado para las uniades y el ciclo de la línea 2 {int} Ciclo2 = asSet(ciclo2); // crea un conjunto de un rango int maxciclo = maxl(qh1,qh2); range maxCiclo = 1..maxciclo; {int} q[H] = [Ciclo1, /// // Número undiades a producir (rango) durante el tiempo LCM Ciclo2]; //////////////////////////////////////////////////////////// Tareas //////////////////////////////////////////////////////////////// tuple task{ int h; // Línea núm int i; // tarea i int tt; //task time int taskP; // Predecesoras tarea int taskS; // Sucesoras tarea int refH; // referencia para Línea int j; // tareas j } {task} Task=...; tuple predtask{ int h; // Línea núm int i; // task int tt; //task time int taskP; // Predecesoras task int taskS; // Sucesoras task int refH; // referencia para Línea int j; // tareas j } {predtask} PredTask=...; ////////////////////////////////////////// Conjunto tareas asignadas a la estación del producto de la línea h c H //////////////////////////////////////////////// {task} Th = { | h in H, e in Task : e.refH == h }; execute{ writeln("Th: "+Th); } {int} conjuntoTareas [h in H] = { e.i | e in Task : h == e.h} ; ////***** Mejora***///// execute{ //writeln("conjuntoTareas: "+conjuntoTareas); } int cardTaskL1 = card(conjuntoTareas[1]); /// Para saber el número de tareas asignadas a la línea 1 int cardTaskL2 = card(conjuntoTareas[2]); /// Para saber el número de tareas asignadas a la línea 2 int cardTaskMax = maxl(cardTaskL1,cardTaskL2); /// La línea con más tareas ; range tareasRango = 1..cardTaskMax; /// tareasRango {int} cardTaskTot[H] = [{cardTaskL1},{cardTaskL2}]; /////////////////////////////////////// Tiempo de proceso de la tarea i del producto de la linea h; h c H ; i c Th. /////////////////////////////////////////// tuple tiempoProcesoTarea{ int h; //Línea núm int i; // task int tt; //task time } {int} conjuntoTiempos [h in H, i in tareasRango] = { e.tt | e in Th : h == e.h && i == e.i } ; {tiempoProcesoTarea} indice_phi = { | h in H, e in Th : e.h == h }; execute{ //writeln("conjuntoTiempos: "+conjuntoTiempos); } execute{ //writeln("indice_phi: "+indice_phi); } ///////////////////////// Conjunto de las predecesoras inmediatas de la tarea i del produco de la línea h; h c H; i c Th. //////////////////////////////// tuple conjuntoPrecedesoras{ int h; // linea núm int i; // task int taskP; // task predecesora int taskP; } {int} conjuntoPred [h in H, i in tareasRango] = { e.i | e in PredTask : h == e.h && i == e.taskS } ; {conjuntoPrecedesoras} indice_IPhi = { | h in H, e in PredTask : e.h ==h }; execute{ //writeln("conjunto_IPhi: "+conjuntoPred); } execute{ //writeln("indice_IPhi: "+indice_IPhi); } ///////////////////////// Conjunto de las sucesoras inmediatas de la tarea i del produco de la línea h; h c H; i c Th. //////////////////////////////// tuple conjuntoSucesoras{ int h; // Línea num int i; //task int taskS; // task sucesora int taskS; } {int} conjuntoSuce [h in H, i in tareasRango] = { e.i | e in PredTask : h == e.h && i == e.taskP } ; {conjuntoSucesoras} indice_IShi = { | h in H, e in PredTask : e.h ==h }; execute{ //writeln("conjunto_IShi: "+conjuntoSuce); } execute{ //writeln("indice_IShi: "+indice_IShi); } ///////////////////////////// Conjunto de las predecesoras totales de la tarea i del producto de la linea h: Phi = IPhi U(U Phj); h c H; i c Th. //////////////////////////////// //{int} conjuntoPredTot1 [h in H, i in tareasRango, j in tareasRango] = {e.i| e in PredTask : h == e.h && j == e.taskS && j <= i } ; //{int} conjuntoPredTot [h in H, i in tareasRango] = union (j in tareasRango)conjuntoPredTot1 [h,i,j]; /** El código anterior no realizaba correctamente el conjunto de predecesoras totales **/ sorted {int} pred1 [h in H, i in tareasRango] = union (j in tareasRango) { e.i | e in PredTask : h == e.h && i == e.taskS } ; /*sorted {int} pred2 [h in H, i in tareasRango] = pred1[h,i] union union (i2 in pred1[h,i] ,j in tareasRango) { e.i | e in PredTask : h == e.h && i2 == e.taskS } ; sorted {int} pred3 [h in H, i in tareasRango] = pred2[h,i] union union (i2 in pred2[h,i] ,j in tareasRango) { e.i | e in PredTask : h == e.h && i2 == e.taskS } ; ... ... ... sorted {int} pred14 [h in H, i in tareasRango] = pred13[h,i] union union (i2 in pred13[h,i] ,j in tareasRango) { e.i | e in PredTask : h == e.h && i2 == e.taskS } ; */ /*** El siguiente código sustituye al anterior ** Para este nuevo código se utiliza pred1 ***/ sorted{int} pred[h in H, i in tareasRango]; execute{ //write("Pred: ") } execute{ function adjust(h,i,s1,s){ for(var e in s1){ s.add(e); adjust(h,i,pred1[h][e],s); } } for(var h in H) for(var i in tareasRango) adjust(h,i,pred1[h][i],pred[h][i]); // writeln(pred) } tuple conjuntoPredecesorasTotales{ int h; // Línea num int i; //task int taskPT; // task predecesora } {conjuntoPredecesorasTotales} indice_PThi = { | h in H , i in conjuntoTareas[h], taskPT in pred[h][i] : taskPT != 0 }; execute{ // writeln("indice_PThi: "+indice_PThi); } ////////////////////// Conjunto de las parejas de tareas del producto de la línea h entre las que no hay relaciones de precedencia. //////////////////////////////// tuple conjuntoph{ int h; // Línea num int i; //task i int j; //task j } {conjuntoph} indice_PH = { | h in H , e in Th, r in Th : h==e.h && e.i < r.j && e.i not in pred[h] [r.j] && r.j not in pred[h][e.i] && e.i<= item(cardTaskTot[h],0) && r.j<= item(cardTaskTot[h],0) }; execute{ // writeln("indice_PH: "+indice_PH); } ////////////////////// Conjunto de las sucesoras totales de la tarea i del producto de la linea h: Shi = {j c Th | i c Phj}; h c H; i c Th //////////////////////////////// tuple conjuntoSucesorasTotales{ int h; // Línea num int i; //task i int j; //task j } {int} conjuntoSuceTot [h in H, i in tareasRango] = { e.j | e in Th : h == e.h && i in pred[h][e.j] } ; {conjuntoSucesorasTotales} indice_SThi = { | h in H , e in Th, r in Th : h==e.h && e.i in pred[h] [r.j] && e.i<= item(cardTaskTot[h],0) && r.j<= item(cardTaskTot[h],0) }; execute{ // writeln("conjuntoSuceTot: "+conjuntoSuceTot); } execute{ // writeln("indice_SThi: "+indice_SThi); } ////////////////////// Cota inferior del primer ciclo en que se podría tratar la u-ésima unidad del producto de la línea h //////////////////////////////// int EChu [h in H, i in maxCiclo]= 0; int sumEChu =0; execute { for(var h in H){ for(var u in q[h]){ for(var e in Th){ // para la tarea i en Th if(e.h == h){ sumEChu = sumEChu + Opl.item(conjuntoTiempos[h][e.i],0); // Sumatorio ( p ) } } EChu[h][u] = Opl.ftoi(Opl.ceil((u * sumEChu)/cth[h])); sumEChu =0; } } } execute{ // writeln("EChu: " + EChu); } ////////////////////// Cota superior del prime ciclo en que se podría tratar la u-ésima unidad del producto de la línea h //////////////////////////////// int LChu [h in H, i in maxCiclo]= 0; int sumLChu =0; execute { for(var h in H){ for(var u in q[h]){ for(var e in Th){ // para la tarea i en Th if(e.h == h){ sumLChu = sumLChu + Opl.item(conjuntoTiempos[h][e.i],0); // Sumatorio ( p ) } } LChu[h][u] = (Opl.item(qh[h],0) + 1 - Opl.ftoi(Opl.ceil( ( ( (Opl.item(qh[h],0) - u + 1) * sumLChu ) /cth[h] ))) ) ; sumLChu =0; } } } execute{ // writeln("LChu: " + LChu); } ////////////////////// Conjunto de las unidades del producto de la línea h que podrían producirse en el ciclo c //////////////////////////////// {int} conjuntoUhc [h in H , c in maxCiclo] = {u | u in q[h] : EChu[h][u] <= c <= LChu[h][u] }; execute{ // writeln("conjuntoUhc: " + conjuntoUhc); } ////////////////////// Cota inferior del primer instante enque se podría comenzar a realizar la tarea i de la u-ésima unidad tratada del producto de la línea h //////////////////////////////// int ESThui [h in H, u in maxCiclo, e in Th] = 0; int sumESThui = 0; execute { for(var h in H){ for(var u in q[h]){ for(var i in Th){ if (i.h == h){ for(var j in pred[h][i.i]){ sumESThui = sumESThui + Opl.item(conjuntoTiempos[h][j],0); // Sumatorio ( p ) } ESThui[h][u][i] = cth[h] * ( EChu[h][u] - 1) + sumESThui ; } sumESThui = 0; } } } } execute{ // writeln("ESThui: " + ESThui); } ////////////////////// Cota supeiror del primer instante enque se podría comenzar a realizar la tarea i de la u-ésima unidad tratada del producto de la línea h //////////////////////////////// int LSThui [h in H, u in maxCiclo, e in Th] = 0; int sumLSThui = 0; execute { for(var h in H){ for(var u in q[h]){ for(var i in Th){ if (i.h == h){ for(var j in conjuntoSuceTot[h][i.i]){ sumLSThui = sumLSThui + Opl.item(conjuntoTiempos[h][j],0); } LSThui[h][u][i] = cth[h] * LChu[h][u] - Opl.item(conjuntoTiempos[h][i.i],0) - sumLSThui ; } sumLSThui = 0; } } } } execute{ // writeln("LSThui: " + LSThui); } /********************************************************************** VARIABLES ************************************************************************* ***********************************************************************************************************************************************************/ //////////////////////////////// Xhuc: 1 si la u-esima unidad del producto de la linea h es tratada en el ciclo c; h c H, u=1..qh, c=1..qh ///////////////////////// tuple conjuntoXhuc{ int h; // Línea num int u; // u-esima unidad producto int c; // ciclo } {conjuntoXhuc} indice_Xhuc = { | h in H, u in q[h], c in EChu[h][u]..LChu[h][u] }; execute{ //writeln("indice_Xhuc: "+indice_Xhuc); } dvar boolean x [indice_Xhuc]; //////////////////////////////////// Yhuij: 1 si tarea i se realiza antes de la tarea j u-esima unidad tratada del producto de la linea h. //////////////////////////// tuple conjuntoYhuij{ int h; // Línea num int u; // u-esima unidad producto int i; // tarea i int j; // tarea j } {conjuntoYhuij} indice_Yhuij = { | h in H, u in q[h], e in indice_PH : h == e.h }; execute{ //writeln("indice_Yhuij: "+indice_Yhuij); } dvar boolean y [indice_Yhuij]; //////////////////////////// Wuivj: 1 si la tarea i de la u-esima unidad tratada del producto de la línea 1 se realiza antes que la tarea j //////////////////////////////// tuple conjuntoWuivj{ int u; // u-esima unidad producto int i; // tarea i int v; // v-esima unidad producto int j; // tarea j } {conjuntoWuivj} indice_Wuivj = {< u, e.i, v, r.j> | u in q[1], e in Th, v in q[2], r in Th : e.h == 1 && r.h ==2 && ESThui[1][u][e] < LSThui[2][v][r]+ item(conjuntoTiempos[2][r.j],0) && LSThui[1][u][e] + item(conjuntoTiempos[1][e.i],0) > ESThui[2][v][r] }; execute{ //writeln("indice_Wuivj: "+indice_Wuivj); } dvar boolean w [indice_Wuivj]; //////////////////// SThui: Instante que comienza a realizarse la tarea i de la u-esima unidad tratada del producto de la línea h; h c H, u=1,...,qh, i c Th. //////////////////////// tuple conjuntoSThui{ int h; // Línea num int u; // u-esima unidad producto int i; // tarea i } {conjuntoSThui} indice_SThui = { | h in H, u in q[h], e in Th : e.i <= item(cardTaskTot[h],0)}; execute{ //writeln("indice_SThui: "+indice_SThui); } dvar float+ ST [indice_SThui]; ////////////////////////// Número de unidades del producto de la línea h que hay inicialmente en el buffer, h c H. /////////////////////////////////// dvar int+ zh[H]; ////////////////////////////// Máximo número de unidades del producto de la línea h que hay en el buffer, h c H. ////////////////////////////////////// dvar int+ ah[H]; /********************************************************************** FUNCION OBJETIVO ****************************************************************** ***********************************************************************************************************************************************************/ //int cotaBufferAh[H] = [3,1]; ////** Se impone el valor del buffer **// //int cotaBufferZh[H] = [0,1]; execute{ cplex.tilim = 1500; } // minimizar el tamaño total de los buffers minimize sum(h in H) ah[h] /* + sum(h in H) zh[h] */ ; /********************************************************************** RESTRICCIONES ********************************************************************** ***********************************************************************************************************************************************************/ subject to{ // Determina el número máximo de unidades de cada producto en el buffer /* forall (h in H) ah[h] == cotaBufferAh[h]; forall (h in H) zh[h] == cotaBufferZh[h]; */ forall (h in H, c in q[h]) ah[h] >= zh[h] + sum(t in 1..c)( sum(u in conjuntoUhc[h][t]) x[] - 1 ) ; // Ec.(2) forall (h in H, c in q[h]) zh[h] + sum(t in 1..c)( sum(u in conjuntoUhc[h][t]) x[] - 1 ) >= 0; // Ec.(3) // Todas las tareas de una unidad se realizan durante el mismo tiempo de ciclo, y relacionan las variables Xhuc y SThui. forall (h in H, u in q[h], i in conjuntoTareas[h] : card(conjuntoPred[h][i]) == 0 ) ST[] >= cth[h] * sum(c in EChu[h][u]..LChu[h][u] )(c-1) * x[] ; // (4) forall (h in H, u in q[h], i in conjuntoTareas[h] : card(conjuntoSuce[h][i]) == 0 ) ST[] + item(conjuntoTiempos [h][i],0) <= cth[h] * sum(c in EChu[h][u]..LChu[h][u] )c * x[]; // (5) // Se respetan las relaciones de precedencias forall (h in H, u in q[h], i in conjuntoTareas[h], j in conjuntoPred[h][i] /*: j] >= ST[] + item(conjuntoTiempos[h][j],0); // (6) // Dos tareas de la misma unidad no se pueden realizar simultaneamente forall (h in H, u in q[h], e in indice_PH : e.h == h) ST [] >= ST [] + item(conjuntoTiempos[h][e.j],0) - LCM * y[] ; // (7) item(indice_phi,e.j).tt forall (h in H, u in q[h], e in indice_PH: e.h == h ) ST [] >= ST [] + item(conjuntoTiempos[h][e.i],0) - LCM * (1- y[]) ; // (8) item(indice_phi,e.i).tt // Dos tareas de productos diferentes no se pueden realizar simultaneamente forall (u in q[1], i in Th, v in q[2], j in Th : i.h==1 && j.h==2 && ESThui[1][u][i] < LSThui[2][v][j] + item(conjuntoTiempos[2][j.j],0) && LSThui[1][u][i] + item(conjuntoTiempos[1][i.i],0) >ESThui[2][v][j] ) ST [<1,u,i.i>] >= ST [<2,v,j.j>] + item(conjuntoTiempos[2][j.j],0) - LCM * w[] ; // (9) forall (u in q[1], i in Th, v in q[2], j in Th : i.h==1 && j.h==2 && ESThui[1][u][i] < LSThui[2][v][j] + item(conjuntoTiempos[2][j.j],0) && LSThui[1][u][i] + item(conjuntoTiempos[1][i.i],0) >ESThui[2][v][j] ) ST [<2,v,j.j>] >= ST [<1,u,i.i>] + item(conjuntoTiempos[1][i.i],0) - LCM * (1 - w[]) ; // (10) // Una unidad de un producto no puede comenzar a tratarse hasta que no haya acabado de tratarse la unidad anterior de ese producto forall (h in H, u in q[h], i in conjuntoTareas[h], j in conjuntoTareas[h] : card(conjuntoSuce[h][i]) == 0 && card(conjuntoPred[h][j]) == 0 && u >= 2) ST [] >= ST [] + item(conjuntoTiempos[h][i],0); // (11) // Alberto Extra forall(h in H, u in q[h]) sum(c in EChu[h][u]..LChu[h][u]) x[] == 1; // (12) // Acotaciones extra Alberto // para ST[]; forall (h in H, u in q[h], e in Th : e.h==h) ESThui[h][u][e] <= ST[]; forall (h in H, u in q[h], e in Th : e.h==h) LSThui[h][u][e] >= ST[]; } execute{ writeln("ah:" + ah); ah1 = ah[1]; ah2 = ah[2]; writeln("ah1: " + ah1); writeln("ah2: " + ah2); writeln("zh: " + zh); zh1 = zh[1]; zh2 = zh[2]; writeln("zh1: " + zh1); writeln("zh2: " + zh2); before = cplex.getSolvedTime(); writeln("tiempo: "+before); }