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
Related
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;
}
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.
I'm trying write in OPL this sum:
I did this, but it is not exactly what I need.
forall (n in cont, t in tempo, o in portos)
sum(i in colunap, j in linhap)b[i][j][n][t] + v[n][t] == 1;
I should be something like, but opl does not accept it:
forall (n in cont[o], t in tempo[o], o in portos)
sum(i in colunap[o], j in linhap[o])b[i][j][n][t] + v[n][t] == 1;
This should work:
int P=3;
int H[1..P-1] = [1 , 2];
range linhap=1..max(o in 1..P-1) H[o];
I came cross Knapsack problem, where the maximum number of multiple items from a set of items need to be placed into one bin by minimizing the cost. I am able to solve the optimization problem in CPLEX.
However, I am finding difficulties in implementing in CPLEX, when the problem consists of two bins (with different capacities).
The problem:
Bin = [B1, B2]
Capacity = [7,5]
Item = [I1, I2, I3, I4]
Weight = [6,3,1,4]
Price = [2,8,2,4]
The objective is to place the maximum number of items and to minimize the total price.
How can I implement this objective problem in CPLEX?
Below is my code snippet:
// ITEMS
int n=4; // no of items
range items = 1..n; // range of items
int p[items] = [2,8,2,6]; //price
int w[items] = [6,3,1,4]; //weight
// BINS
int m=2; // no of bins
range bins=1..m; // range of bin
int capacity[bins] = [7,5]; // capacity of each bin
dvar boolean x[items][bins];
// model ; max the profit
maximize sum(i in items, j in bins) p[i]*x[i][j];
subject to {
forall (j in bins)
cons1 : sum(i in items) w[i]*x[i][j] <= capacity[j];
forall (i in items)
cons2 : sum(j in bins) x[i][j] == 1;
}
-Thanks
If you add
assert sum(i in items) w[i]<=sum(b in bins) capacity[b];
then this assert is violated and this explains why you do not get a solution. You do not have enough bin capacity.
But then if you turn:
int capacity[bins] = [7,5]; // capacity of each bin
into
int capacity[bins] = [7,7]; // capacity of each bin
then you'll get a solution.
You can find a knapsack example in CPLEX_Studio1271\opl\examples\opl\knapsack.
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;
}