How to code Epsilon constraint method in CPLEX - optimization

How to solve a bi-/multi-objective problem by the Epsilon constraint method in CPLEX using OPL?
Thanks!

In OPL CPLEX you can directly use multiobjective
int nbKids=200;
float costBus40=500;
float costBus30=400;
float costBus50=625;
dvar int+ nbBus40;
dvar int+ nbBus30;
dvar int+ nbBus50;
dvar float cost;
dvar float co2emission;
minimize
staticLex(cost,co2emission);
subject to
{
cost==costBus40*nbBus40 +nbBus30*costBus30+nbBus50*costBus50;
co2emission==nbBus50+nbBus40*1.1+nbBus30*1.2;
40*nbBus40+nbBus30*30+nbBus50*50>=nbKids;
}
execute DISPLAY_After_SOLVE
{
writeln("The minimum cost is ",cost);
writeln("CO2 emission is ",co2emission);
writeln("We will use ",nbBus40," 40 seats buses ",nbBus30,
" 30 seats buses and ", nbBus50," buses 50 seats");
}
but if you prefer to use flow control you can write
int nbKids=200;
float costBus40=500;
float costBus30=400;
float costBus50=625;
dvar int+ nbBus40;
dvar int+ nbBus30;
dvar int+ nbBus50;
dvar float cost;
dvar float co2emission;
minimize
cost+co2emission;
subject to
{
cost==costBus40*nbBus40 +nbBus30*costBus30+nbBus50*costBus50;
co2emission==nbBus50+nbBus40*1.1+nbBus30*1.2;
40*nbBus40+nbBus30*30+nbBus50*50>=nbKids;
}
execute DISPLAY_After_SOLVE
{
writeln("The minimum cost is ",cost);
writeln("CO2 emission is ",co2emission);
writeln("We will use ",nbBus40," 40 seats buses ",nbBus30,
" 30 seats buses and ", nbBus50," buses 50 seats");
}
main
{
var epsilon=0.01;
thisOplModel.generate();
// remove co2emission from the objective by setting coef 0
cplex.setObjCoef(thisOplModel.co2emission,0);
cplex.solve();
thisOplModel.postProcess();
var cost=thisOplModel.cost.solutionValue;
// add a new constraint that cost should not move up too much
thisOplModel.cost.UB=cost*(1+epsilon);
// keep only CO2 emission in the objective
cplex.setObjCoef(thisOplModel.co2emission,1);
cplex.setObjCoef(thisOplModel.cost,0);
cplex.solve();
thisOplModel.postProcess();
}
or if you want to update bounds on a constraint
int nbKids=200;
float costBus40=500;
float costBus30=400;
float costBus50=625;
dvar int+ nbBus40;
dvar int+ nbBus30;
dvar int+ nbBus50;
dvar float cost;
dvar float co2emission;
minimize
cost+co2emission;
subject to
{
cost==costBus40*nbBus40 +nbBus30*costBus30+nbBus50*costBus50;
co2emission==nbBus50+nbBus40*1.1+nbBus30*1.2;
40*nbBus40+nbBus30*30+nbBus50*50>=nbKids;
ctMaxCost:cost<=maxint;
}
execute DISPLAY_After_SOLVE
{
writeln("The minimum cost is ",cost);
writeln("CO2 emission is ",co2emission);
writeln("We will use ",nbBus40," 40 seats buses ",nbBus30,
" 30 seats buses and ", nbBus50," buses 50 seats");
}
main
{
var epsilon=0.01;
thisOplModel.generate();
// remove co2emission from the objective by setting coef 0
cplex.setObjCoef(thisOplModel.co2emission,0);
cplex.solve();
thisOplModel.postProcess();
var cost=thisOplModel.cost.solutionValue;
// add a new constraint that cost should not move up too much
thisOplModel.ctMaxCost.UB=cost*(1+epsilon);
// keep only CO2 emission in the objective
cplex.setObjCoef(thisOplModel.co2emission,1);
cplex.setObjCoef(thisOplModel.cost,0);
cplex.solve();
thisOplModel.postProcess();
}

Related

CPLEX, replace variable with a constant

I already have a CPLEX model with variables x[0], x[1],...,x[n-1]. In order to create heuristics, I need to insert constants instead of all but one variable.
Say, I will keep x[0] and instead of x[i] I will insert constants a[i] (i=1,...,n-1).
One way to do this is to create a new model where variables will be replaced by constants manually. The model is big and I would need go through entire code to do this.
Is there another way?
What if I insert additional constraints: x[i]==a[i] (i=1,...,n-1) into the model? Will x[i] be converted to constants at the very beginning or the model with n variables (x[i], i=0,...,n-1) will be solved?
You can set Upper bound and lower bound on any decision variable to make it a constant.
For instance, with the zoo example , in OPL you can write
int nbKids=300;
float costBus40=500;
float costBus30=400;
float costBus50=700;
dvar int+ nbBus40;
dvar int+ nbBus30;
dvar int+ nbBus50;
minimize
costBus40*nbBus40 +nbBus30*costBus30+nbBus50*costBus50;
subject to
{
ctKids:40*nbBus40+nbBus30*30+nbBus50*50>=nbKids;
}
execute
{
writeln(nbBus30," ",nbBus40," ",nbBus50, " buses");
}
main
{
thisOplModel.generate();
cplex.solve();
thisOplModel.postProcess();
thisOplModel.nbBus50.UB=2;
thisOplModel.nbBus50.LB=2;
cplex.solve();
thisOplModel.postProcess();
}
that gives
2 6 0 buses
0 5 2 buses

cplex error: cos float doesnot exists i.e,showing error while typing cos and sin functions

error correction. I have to include cos and sin functions in my model.But it is showing error.I have tried the expression Math.cos and Opl.cos But both won't work. The error is after the forall statement,and iam facing this error after including the cos function.
float c1[0..3]=[50,0,0,50];
float c2[0..3]=[351,0,0,389];
float c3[0..3]=[44.6,0,0,40.6];
float pd[0..3]=[50,170,200,80];
float qd[0..3]=[10,20,30,40];
float V[0..3]=[1.0,1.0,1.0,1.0];
float del[0..3]=[0,0,0,0];
/*float pg[1..4]=[10,0,0,10];*/
float p[0..3];
float q[0..3];
int i=0;
float G[0..3][0..3]=[ [5.724138, -1.724138,0,-4],
[-1.724138,4.224138,-2.5,0],
[0,-2.5,4.386792,-1.886792],
[-4,0,-1.886792,5.886792]];
float B[0..3][0..3]=[ [-12.31034,4.310345,0,8],
[4.310345,-11.810340,7.5,0],
[0,7.5,-14.10377,6.603774],
[8,0,6.603774,-14.603770]];
dvar float+ pg[0..3];
dvar float+ Qg[0..3];
minimize sum(i in 0..3)(c1[i]*pg[i]^2 + c2[i]*pg[i] + c3[i]);
subject to
{forall(i in 0..3)
p[i]==V[i]*(sum(j in 0..3)(V[j]*(G[i][j]*cos(del[i]-del[j]))));
p[i]-pg[i]+pd[i]==0;
forall(i in 0..3)
q[i]==V[i]*(sum(j in 0..3)(V[j]*(G[i][j])));
q[i]-Qg[i]+qd[i]==0;
//forall(i in 0..3)
// pg[i]<=30;
}
cos is not linear so you cannot use cos in a MIP model within CPLEX.
If you need non linear function you could either use:
CPOptimizer within CPLEX
approximate with a piecewise linear function
But in your case you use cos of data so you can write the following model that works fine:
float c1[0..3]=[50,0,0,50];
float c2[0..3]=[351,0,0,389];
float c3[0..3]=[44.6,0,0,40.6];
float pd[0..3]=[50,170,200,80];
float qd[0..3]=[10,20,30,40];
float V[0..3]=[1.0,1.0,1.0,1.0];
float del[0..3]=[0,0,0,0];
/*float pg[1..4]=[10,0,0,10];*/
float p[0..3];
float q[0..3];
int i=0;
float deltacos[0..3][0..3];
range r=0..3;
execute fill_deltacos
{
for(var i in r) for (var j in r) deltacos[i][j]=Math.cos(del[i]-del[j]);
}
float G[0..3][0..3]=[ [5.724138, -1.724138,0,-4],
[-1.724138,4.224138,-2.5,0],
[0,-2.5,4.386792,-1.886792],
[-4,0,-1.886792,5.886792]];
float B[0..3][0..3]=[ [-12.31034,4.310345,0,8],
[4.310345,-11.810340,7.5,0],
[0,7.5,-14.10377,6.603774],
[8,0,6.603774,-14.603770]];
dvar float+ pg[0..3];
dvar float+ Qg[0..3];
minimize sum(i in 0..3)(c1[i]*pg[i]^2 + c2[i]*pg[i] + c3[i]);
subject to
{forall(i in 0..3)
p[i]==V[i]*(sum(j in 0..3)(V[j]*(G[i][j]*deltacos[i][j])));
p[i]-pg[i]+pd[i]==0;
forall(i in 0..3)
q[i]==V[i]*(sum(j in 0..3)(V[j]*(G[i][j])));
q[i]-Qg[i]+qd[i]==0;
//forall(i in 0..3)
// pg[i]<=30;
}

Operator not available for dvar float+ * float[][range]

int NbPeriods = ...; range Periods = 1..NbPeriods;
int NbParts = ...; range Parts = 1..NbParts;
int NbSuppliers = ...; range Suppliers = 1..NbSuppliers;
int NbProcesses = ...; range Processes = 1..NbProcesses;
int NbPS[1..NbParts, 1..NbProcesses*NbSuppliers] = ...;
float Demand[Parts][Periods] = ...;
float BOH[Parts] = ...;
float Capacity[Suppliers][Processes] = ...;
float ProcessMapping[s in 1..NbSuppliers, pr in 1..NbProcesses, p in 1..NbParts] = NbPS[p, pr+NbProcesses*(s-1)];
float Price[Parts][Suppliers] = ...;
dvar float+ Supply[1..NbParts, 1..NbPeriods*NbSuppliers];
dvar float+ EOH[Parts][Periods];
dvar float+ Util[1..NbProcesses, 1..NbPeriods*NbSuppliers];
minimize
sum( t in Periods ) DOIDelta[t] ;
subject to {
forall(p in Parts)
EOH[p][0] == BOH[p];
forall(p in Parts)
forall( t in Periods)
EOH[p][t] == EOH[p][t-1] + sum(s in Suppliers) Supply[p,t+NbPeriods*(s-1)] ;
forall(t in Periods)
forall(pr in Processes)
forall(s in Suppliers)
Util[pr,t+NbPeriods*(s-1)] == sum(p in Parts) (Supply[p,t+NbPeriods*(s-1)] * ProcessMapping[p, pr+NbProcesses*(s-1)] );
}
The error message is for the last Util line: Operator not available for dvar float+ * float[][range]. I have checked other posts on this topic and the issues are on parenthesis. Even adding the parenthesis the error remains. Appreciate your help.
processMapping is a 3D array not a 2D array
forall(t in Periods)
forall(pr in Processes)
forall(s in Suppliers)
Util[pr,t+NbPeriods*(s-1)] == sum(p in Parts) (Supply[p,t+NbPeriods*(s-1) * ftoi(ProcessMapping[s,p, pr+NbProcesses*(s-1)])] );
will work better

How to include if-statement with decision variables in cplex which have summation function

How can i convert If statement in constraint part which have decision variable. The costvship is the variable cost of shipment which needs to be included only when sum(m in M)x[m][n]*h[p][n]*weight[m] is greater than threshold Weight. Here x[m][n] and h[p][n] are binary variables.
forall(p in P, n in N){costship[p][n] == costfship*z[p][n] + costvship*(sum(m in M)(x[m][n]*h[m][p]*weight[m])- Weight);
}
You may use a logical constraint to add an additional cost if a constraint is true.
Let me change the zoo example to show that:
int nbKids=300;
float costBus40=500;
float costBus30=400;
int penalty=1000;
dvar int+ nbBus40;
dvar int+ nbBus30;
minimize
costBus40*nbBus40 +nbBus30*costBus30 + (nbBus40+nbBus30<=8)*penalty;
subject to
{
40*nbBus40+nbBus30*30>=nbKids;
}
that you can also write with sum
int nbKids=300;
{int} sizes={40,30};
float costBus[sizes]=[500,400];
int penalty=1000;
dvar int+ nbBus[sizes];
minimize
sum(s in sizes)costBus[s]*nbBus[s] + (sum(s in sizes) nbBus[s]<=8)*penalty;
subject to
{
sum(s in sizes)s*nbBus[s]>=nbKids;
}

How is a conditional summation possible in Cplex? like sumifs in Excel?

I want to sum all used resources among times in my model (it's rcpsp model)
how can I do it in CPLEX?
at first I wrote this:
forall(k in K)
forall(t in 1..f[nAct])
sum(i in I:f[i]-d[i]<=t-1 && t<=f[i]) r[i,k] <= aR[k];
(note: K is a range for resources, nAct is number of activities, f[i] is an array dvar and indicates finishing time of activity i, d[i] is duration of i,r[i,k] is required resource of k for activity i and aR[k] is available resources of k.)
The problem is that the cplex doesn't accept decision variable in sum's condition.
I changed it to:
forall(k in K)
forall(t in 1..f[nAct])
sum(i in I) (f[i]-d[i]<=t-1 && t<=f[i])*r[i,k] <= aR[k];
But it didn't work. it made True constraints in Problem Browser after run(I don't know why) and it made this constraint ineffective.
Any Idea how to fix it?
There are several ways to put your problem into an integer programming framework. There are books written on this subject. I think this is the simplest formulation.
I assume that in your problem, r[i,k] and d[i] are known and that the time horizon is broken into discrete time periods.
on[i,t] indicator that activity i is active at time t
start[i,t] indicator that activity i starts at the start of period t
end[i,t] indicator that activity i finishes at the end of period t
So in[i,t] replaces the condition f[i]-d[i]<=t-1 && t<=f[i])*r[i,k]
Your constraint becomes
forall(k in K)
forall(t in 1..f[nAct])
sum(i in I : r[i,k] = 1) on[i,t] <= aR[k];
You also need to add constraints to enforce the definition of on, start and off.
forall(t in 2..f[nAct])
forall(i in I)
on[i,t-1] - on[i,t] = end[i,t-1] - start[i,t];
forall(i in I)
on[i,0] = start[i,0];
forall(i in I)
sum(t in 1..f[nAct]) start[i,t] = 1;
forall(i in I)
sum(t in 1..f[nAct]) end[i,t] = 1;
forall(i in I)
sum(t in 1..f[nAct]) on[i,t] = d[i];
You can use dexpr for manipulating decision variables. Here is an example from the same resource IBM Knowledge Center.
Without dexpr
dvar int x in 0..20;
dvar int y in 0..20;
dvar int d;
dvar int s;
maximize (d);
subject to {
d==x-y;
s==x+y;
s<=15;
s<=x-2*y;
d>=2;
d<=y+8;
1<=d;
}
With dexpr
dvar int x in 0..20;
dvar int y in 0..20;
dexpr int d=x-y;
dexpr int s=x+y;
maximize (d);
subject to {
s<=15;
s<=x-2*y;
d>=2;
d<=y+8;
1<=d;
}