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

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

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

Can Cplex prioritize some variables so that they're likely to be chosen together?

So my problem contains a vehicle that moves from one node to the next. I have a bunch of nodes that may or may not be related to each other. I want the nodes that are similar to each other to be visited by the vehicle as much as possbible.
Is there any possible ways that i can prioritize the related nodes so that they're more likely to be grouped together? I thought to create sets or tuples that represent the different groups, and to have a variable X[i][j] = 1 if the vehicle moves from node i to node j, but i'm stuck at the "prioritize i and j if they come from the same set" part. Is it the boolean value that makes it impossible to render that? Should I modify my formulations somehow?
This is my code for the problem for now, i still haven't come out with the priority part
int nNode = 20;
range N = 1..nNode; //set of locations to visit
range V = 0..nNode; //set of locations plus the depot
range Vehicle = 1..6; //there are six vehicles
range boxType = 1..3; //three types of boxes to be transported
int demand[V][boxType] =...; //demand for a location in terms of different boxes
int timeBox[boxType] =...; //time associated with the actions on a type of box
dvar int+ totalLoad[Vehicle];
dvar int+ load[Vehicle][boxType]; //load in terms of box type
dvar boolean X[V][V][Vehicle]; /*1 if the vehicle Vehicle goes from node V to the
next node, 0 if not*/
dvar int+ t[Vehicle]; //total time a vehicle spends
dvar int time[Vehicle]; /*equals |t[vehicle] - target cycle time|, this is to make sure
each vehicle spends as close to target cycle time as possible*/
minimize sum (v in Vehicle)time[v];
subject to
{
forall (i in V)
sum (j in V, k in Vehicle)X[i][j][k] == 1; /* so that each starting node will have
exactly one destination node, i.e it will belong to exactly 1 route only*/
forall (j in V)
sum (i in V, k in Vehicle)X[i][j][k] == 1; // similar but for ending node
forall (k in Vehicle)
totalLoad[k] == sum(i in V, j in V)X[i][j][k]* (sum(b in boxType)demand[j][b]); /*total
load of a vehicle equals the total boxes collected at each stop on its path */
forall (b in boxType, k in Vehicle)
load[k][b] == sum(i in V, j in V) X[i][j][k]*(sum(j in Vehicle)demand[j][b]); /* calculate
separate number of boxes for each route*/
forall (k in Vehicle)
{
time[k] >= t[k] - 1.5;
time[k] >= - t[k] + 1.5;
time[k] <= t[k] + 1.5;
time[k] <= 2 - t[k] - 1.5; // breakdown of time[k] = |t[k]-1.5|, 1.5 is target cycle time
t[k] == sum(b in boxType) load[k][b]*timeBox[b]; // calculate the total time involved in a route
}
}
You could try adding a term into your objective that penalises giving different values to those sets of variables. Easy enough if there are only two of them but more fiddly if there are bigger subsets and/or lots of subsets to coordinate.
I would do something along the lines of what Tim suggested. Here is a little bit more meat on the bones:
x[i,j,k]=1 => L[g] ≤ k ∀i∈g, ∀j,k A lowerbound on the route k for group g
x[i,j,k]=1 => U[g] ≥ k ∀i∈g, ∀j,k An upperbound on the route k for group g
U[g]-L[g] ≥ 1 => δ[g]=1 δ[g]=1 if g is on different routes
min sum(g,δ[g]) objective
δ[g] ∈ {0,1} δ[g] is a binary variable
One way to implement the first 3 equations is:
L[g] ≤ k⋅x[i,j,k] + M(1-x[i,j,k]) ∀i ∈ g, ∀j,k
U[g] ≥ k⋅x[i,j,k] ∀i ∈ g, ∀j,k
M⋅δ[g] ≥ U[g]-L[g]
here g indicates a group. This makes the problem a multi-objective problem, so you can choose from a few possible approaches for that.
you could use priorities if you do not want to change the model from a logical point of view.
See https://github.com/AlexFleischerParis/zooopl/blob/master/zoopriorities.mod
int nbKids=300;
float costBus40=500;
float costBus30=400;
dvar int+ nbBus40;
dvar int+ nbBus30;
execute
{
nbBus40.priority=100;
nbBus30.priority=0;
}
minimize
costBus40*nbBus40 +nbBus30*costBus30;
subject to
{
40*nbBus40+nbBus30*30>=nbKids;
}
in Making optimization Simple
If you want to change the model from a logical point of view you can change the objective or add a second objective
int nbKids=350;
float costBus40=400;
float costBus30=300;
dvar int+ nbBus40;
dvar int+ nbBus30;
dexpr float absdistancebetweennumbers=abs(nbBus40-nbBus30);
minimize
staticLex(costBus40*nbBus40 +nbBus30*costBus30,absdistancebetweennumbers);
subject to
{
40*nbBus40+nbBus30*30>=nbKids;
}

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

Cplex optimization--"No Value" for my decision variable

I am new to Cplex optimization.
I am trying to implement an optimization problem with some scenarios. it is a two-stage stochastic model with 5 scenarios and the probabilty of occurrence the scenarios.
I wrote my model with 5 scenarios, parameters, and variables, and constraints. I get the following message "No Value" for my decision variable. I think my model does not work and I do not know what should I change in my Codes?. Is there somebody to help me? Thank you very much.
--Parameter--
int NbWarehause=3;
int NbRegion=138;
int NbSchool=631;
int NbScenario=5;
range Warehouse=1..NbWarehause;
range Region=1..NbRegion;
range School=1..NbSchool;
range Scenario=1..NbScenario;
int TravelDistanceWarehouseRegion[Warehouse][Region]=...;
int CapacitySchool[School] =...;
int ScenarioDemandMatrix[Scenario][Region]=...;
int Fixedcost1 = 14232;
float Transportcost1perkm=1.40;
int Fixedcost2 = 14232;
float Transportcost2perkm=3;
int Unusedcostperitem=50;
int Depriviationcost[Region]=...;
int Penaltycost=100;
float ProbabilityScenario[Scenario]=...;
--Decision variables---
dvar boolean open1[School][Region];
dvar int Allocated1[School][Region];
dvar boolean open2[School][Region];
dvar int Allocated2[School][Region];
dvar int UnusedInventory[School][Region];
dvar int LateSatisfiedDemand[Region];
dvar int UnSatisfiedDemand[Region];
--Objective function--
minimize --the first stage--
sum(j in School, r in Region) Fixedcost1 * open1[j][r] +
sum( j in School, w in Warehouse, r in Region) Allocated1[j][r] *
TravelDistanceWarehouseRegion[w][r]*Transportcost1perkm +
--the second stage--
sum(s in Scenario) ProbabilityScenario[s]*(
sum(j in School,r in Region)Fixedcost2 *open2[j][r]
+sum( j in School, w in Warehouse,r in Region) Allocated2[j]
[r]*TravelDistanceWarehouseRegion[w][r]*Transportcost2perkm
+sum( j in School,r in Region)UnusedInventory[j][r]*Unusedcostperitem
+sum(r in Region) Depriviationcost[r]*LateSatisfiedDemand[r]+
sum(r in Region)UnSatisfiedDemand[r]*Penaltycost );
--Constraint--
subject to
{
//C1: capacity of each school in its region//
forall (r in Region ) sum (j in School) (Allocated1[j]
[r]+Allocated2[j] [r]+UnusedInventory[j][r])== sum (j in
School)CapacitySchool[j];
//C2: Demand of each region //
forall (s in Scenario,r in Region) sum (j in School)(Allocated1[j]
[r]+Allocated2[j][r])+LateSatisfiedDemand[r]+UnSatisfiedDemand[r] ==
ScenarioDemandMatrix[s][r];
//C3: open a school maximal one time //
sum (j in School,r in Region ) (open1[j][r]+open2[j][r]) <= 1;
//C4: school can not supply more than its capacity in the second
stage I dont know how do I write under scenario //
forall (j in School,r in Region)Allocated2[j][r]<=CapacitySchool[j] -
Allocated1[j][r]*(open1[j][r]+open2[j][r]);
//C5: Sum of all probability is equal 1
sum (s in Scenario)ProbabilityScenario[s]==1;
// C6: Nonnegative Constraint
forall (r in Region ,j in School) Allocated1[j][r]>=0;
forall (r in Region ,j in School)Allocated2[j][r]>=0;
forall (r in Region ,j in School)UnusedInventory[j][r]>=0;
forall (r in Region)LateSatisfiedDemand[r]>=0;
forall (r in Region) UnSatisfiedDemand[r]>=0;
}
I guess your model is not feasible.
To understand why you could name your constraints and then CPLEX will provide you with some relaxations and conclicts.
As a start you could change
//C3: open a school maximal one time //
sum (j in School,r in Region ) (open1[j][r]+open2[j][r]) <= 1;
into
//C3: open a school maximal one time //
C3:sum (j in School,r in Region ) (open1[j][r]+open2[j][r]) <= 1;
And then rely on
https://www.ibm.com/support/pages/display-full-indices-or-real-map-item-name-variables-and-constraints
to get the real indexes

LP / MILP formulation with OR logic

I'm solving a LP / MILP problem using ILOG CPLEX.
int n = ...;
range time =1..n;
dvar float+ c[time] in 0..0.3;
dvar float+ d[time] in 0..0.3;
dvar float+ x[time];
int beta[time]=...;
float pc[time]=...;
float pd[time]=...;
//Expressions
dexpr float funtion = sum(t in time) (d[t]*pd[t]-c[t]*pc[t]);
//Model
maximize function;
subject to {
x[1] == 0.5;
c[1] == 0;
d[1] == 0;
forall(t in time)
const1:
x[t] <= 1;
forall(t in time: t!=1)
const2:
(x[t] == x[t-1] + c[t] - d[t]);
forall(t in time: t!=1)
const3:
( d[t] <= 0) || (c[t] <= 0);
As you can see I've forced c[t] and d[t] to never be bigger than 0 at the same time with "const3".
My question is, how would this constraint be represented in a LP/MILP mathematical formulation?
Is adding this new variable enough? :
y[t]≤c[t]+d[t]
y[t]≥c[t]
y[t]≥d[t]
0≤y[t]≤M (M is the maximum value of both c or d)
As far as I can tell, the constraints you suggested would allow this setting:
c[t] = 0.1
d[t] = 0.1
y[t] = 0.2
Which has c and d different from 0 simultaneously.
I can see these options to formulate your condition without logical constraints:
1) Use an SOS constraint that contains just c[t] and d[t]. By definition of SOS only one of the two can be non-zero in any feasible solution.
2) Use a boolean variable y[t] and add constraints
c[t] <= M * y[t]
d[t] <= M * (1 - y[t])
3) Again, use boolean y[t] and then indicator constraints
(y[t] == 0) => (c[t] == 0);
(y[t] == 1) => (d[t] == 0);
4) You can just state c[t] * d[t] == 0 but that will make the model non-linear.
In any case, a solver will probably be able to reduce your original formulation to either 2 or 3. So reformulating the constraint may not make things faster but only more obscure.