I am trying to improve the model. I coded your suggestion like this:
IloArray<IloIntVarArray> numTAs(env, simu.plantilla.size());
IloArray<IloIntVarArray> numTAs2(env, simu.plantilla.size());
for (i = 0; i < simu.plantilla.size(); i++) {
numTAs[i] = IloIntVarArray(env, simu.numDiasTurnero+1, 0, 6); //valores entre 0 y 6 como máximo de turnos aeronáuticos por ciclo
numTAs2[i] = IloIntVarArray(env, simu.numDiasTurnero+1, -1, 5); //valores entre -1 y 5 como máximo de turnos aeronáuticos por ciclo, así se prohiben 6 TAs con descanso de 48h
model.add(numTAs[i][simu.numDiasTurnero] == 0); //inicializa numTAs(ultimodia) a 0
model.add(numTAs2[i][simu.numDiasTurnero] == -1); //inicializa numTAs2(ultimodia) a -1 asuminedo descanso de 54h en último día
for (d = simu.numDiasTurnero-1; d >=0; d--) {
numTAs[i][d] = IloIntVar(env, 0, 6);
numTAs2[i][d] = IloIntVar(env, -1, 5);
model.add(IloIfThen(env, Ciclos[i][d] != 0, numTAs[i][d] == 0));
model.add(IloIfThen(env, Ciclos[i][d] == 0, numTAs[i][d] == numTAs[i][d + 1] + (TurneroCalculado[i][d] != l && TurneroCalculado[i][d] != o)));
model.add(IloIfThen(env, Ciclos[i][d] != 0, numTAs2[i][d] == -Ciclos[i][d] + 1)); //inicializa numTAs2 = -1 los ciclos con 54h de descanso y a 0 los de 48h. Así los ciclos que tengas 6 TAs con descanso de 54h, su suma dará 5TAs pero los de 48h darán 6TAs
model.add(IloIfThen(env, Ciclos[i][d] == 0, numTAs2[i][d] == numTAs2[i][d + 1] + (TurneroCalculado[i][d] != l && TurneroCalculado[i][d] != o)));
}
}
however, it is taking very long (taking from 3875 variables to 5859 and 9841 constraits to 13747)
In OPL I implemented this one that takes less time
forall (i in Plantilla, d in 0..NumDiasTurnero-2, d1 in d+1..NumDiasTurnero-1)
(Ciclos[i][d] * Ciclos[i][d1] > 0 && (sum(dx in d+1..d1) (Ciclos[i][dx] > 0))==1 =>
(sum(dx2 in d+1..d1, t in tipoDeTurno : t.Tipo != "l") TurneroCalculado[i][dx2][t]) <= 6 && //número de turnos aeronáuticos consecutivos <=6
(sum(dx2 in d+1..d1, t in tipoDeTurno : t.Tipo == "m" || t.Tipo == "m1" || t.Tipo == "im") TurneroCalculado[i][dx2][t]) <= 5 && //número de mañanas (m, m1, im) seguidas <=5
(sum(dx2 in d+1..d1, t in tipoDeTurno : t.Tipo == "im" || t.Tipo == "it" || t.Tipo == "ino") TurneroCalculado[i][dx2][t]) <= 2 ); //máximo de dos imaginarias por ciclo
forall (i in Plantilla, d in 0..NumDiasTurnero-2, d1 in d+1..NumDiasTurnero-1)
((Ciclos[i][d] * Ciclos[i][d1] > 0 && (sum(dx in d+1..d1) (Ciclos[i][dx] > 0))==1 &&
(sum(dx2 in d+1..d1, t in tipoDeTurno : t.Tipo != "l" && t.Tipo != "o") TurneroCalculado[i][dx2][t]) == 6) => Ciclos[i][d1] == 2); //después de 6 días aeronáuticos, descanso >= 54h
but I don´t know how to translate it into C++ API. The sum(...) is giving me headaches.
I worked it out as well using minizing running cplex as solver and it is much faster (I don´t know why). This part of the code in minizic is like this:
constraint forall (i in Plantilla, d in 0..NumDiasTurnero-2 where Ciclos[i,d] != 0)
(let {var int: d1 = min([dx | dx in d+1..NumDiasTurnero-1 where Ciclos[i,dx] != 0 ]++[NumDiasTurnero]),
var int: turnosAeronauticos = sum([1 | dx2 in d+1..d1 where TurneroCalculado[i,dx2,l] == 0 /\ TurneroCalculado[i,dx2,o] == 0])} in (
((d1 >= d+7) -> (turnosAeronauticos <= 6)) /\ %número de turnos aeronáuticos consecutivos <=6
((d1 >= d+6) -> (sum([1 | dx2 in d+1..d1 where TurneroCalculado[i,dx2,m] == 1 \/ TurneroCalculado[i,dx2,m1] == 1 \/ TurneroCalculado[i,dx2,im] == 1]) <= 5)) /\ %número de mañanas (m, m1) seguidas <=5
((d1 >= d+7 /\ turnosAeronauticos == 6 -> Ciclos[i,d1] == 2)) /\ %después de 6 días aeronáuticos, descanso >= 54h
(sum([1 | dx2 in d+1..d1 where TurneroCalculado[i,dx2,im] == 1 \/ TurneroCalculado[i,dx2,it] == 1 \/ TurneroCalculado[i,dx2,ino] == 1]) <=2) %máximo de dos imaginarias por ciclo
));
Because in minizinc you can define local variables (d1 and turnosAeronauticos) that are used below several times, it might save time.
Thanks
------------------------------
javier rodrigo
------------------------------
Original Message:
Sent: Sun January 02, 2022 03:21 AM
From: javier rodrigo
Subject: IloFunction
Nice!! It's working good with your idea. Thanks a lot
------------------------------
javier rodrigo
Original Message:
Sent: Wed December 29, 2021 09:33 AM
From: ALEX FLEISCHER
Subject: IloFunction
Hi,
you could also count in your constraints.
For instance with OPL you could write
range r=1..30;int xval[r]=[0,0,0,0,1,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1 ];int max6=3;dvar int x[r] in 0..2;dvar int+ y[r] in 0..10;dvar int+ nb6[r] in 0..max6;maximize sum(i in r) (y[i]==6);subject to{ forall(i in r) x[i]==xval[i]; forall(i in r) (x[i]!=0)=>(nb6[i]==0); forall(i in r) (x[i]!=0)=>(y[i]!=6); forall(i in r:i!=1) (x[i]==0) => (nb6[i]==nb6[i-1]+(y[i]==6));}
which gives
y = [6 6 6 6 0 6 6 5 5 5 5 6 5 0 6 6 0 0 0 6 0 6 6 6 0 0 0 0 0 0];x = [0 0 0 0 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1];nb6 = [0 1 2 3 0 1 2 2 2 2 2 3 3 0 1 2 2 2 2 3 0 1 2 3 3 3 3 3 3 0];
I wrote that in OPL but you can do the same with all APIs and with MIP and CPOptimizer
------------------------------
[Alex] [Fleischer]
[EMEA CPLEX Optimization Technical Sales]
[IBM]
Original Message:
Sent: Tue December 28, 2021 01:28 PM
From: Christiane Bracchi
Subject: IloFunction
Hello Javier,
IloFunction was in ILOG Solver API which isn't available any more
How would you have liked to use it?
Regards,
------------------------------
Christiane Bracchi
Original Message:
Sent: Mon December 27, 2021 04:30 PM
From: javier rodrigo
Subject: IloFunction
Hello
I am trying to find an example using the IloFunction but I can't find anything clear enough for me in the documentation. I found the following Decision Optimization post but I cannot find the example "in the user manual at section "Advanced Modeling with Set Variables".
My original problem is the following: I have a two dimensional integer var array of 0,1,2 and another two dimensional var array with integer. What I need is to be able to count a specific number between two consecutives 1/2. Example of single row:
000010000000020000001000000001 (the position/index of the 0,1,2 could change)
000006666000600007700770000000 (the position of the numbers could change)
Between the first 1 to 2 the number of 6s is 5. The idea is to build a constraint that limit the number of 6s between two consecutives 1 or 2 to whatever I need.
Hope it's clear
Regards
------------------------------
javier rodrigo
------------------------------
#DecisionOptimization