Decision Optimization

View Only

IloFunction

• 1.  IloFunction

Posted Mon December 27, 2021 04:31 PM

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
------------------------------

• 2.  RE: IloFunction

Posted Tue December 28, 2021 01:29 PM
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
------------------------------

• 3.  RE: IloFunction Best Answer

Posted Wed December 29, 2021 09:33 AM
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]
------------------------------

• 4.  RE: IloFunction

Posted Sun January 02, 2022 03:22 AM
Nice!! It's working good with your idea. Thanks a lot

------------------------------
javier rodrigo
------------------------------

• 5.  RE: IloFunction

Posted Mon January 03, 2022 02:47 PM
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
------------------------------

• 6.  RE: IloFunction

Posted Tue March 15, 2022 11:28 AM
Thanks working great.

------------------------------
Ricky Martin
------------------------------

• 7.  RE: IloFunction

Posted Sun January 02, 2022 03:21 AM
In minizinc I was able to construct a function for this matter, so I was just looking around for a way...

------------------------------
javier rodrigo
------------------------------