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

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

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

CPLEX Optimization Studio - No feasible solution - Quadratic Constraints

I try to implement a Vehicle Routing Problem with two vehicles.
One vehicle is a carrier, the other one is a drone which can start from the carrier.
Both vehicles start at the point (0/0). Then both vehicles move to a point where the drone should start from the carrier an visit some target locations consecutively. In the beginning I only assume two targets located at t1(2/8) and t2(5/8). After visiting the targets the drone should land on the carrier and both vehicles shoul go back to the starting point (0/0).
So the points where the drone launches and lands on the carrier are to choose optimally to minimze the tour of the carrier.
I have a visualization of the problem here: visualization
My Code looks like this:
//Data
int start[1..2]=[0,0]; //start
int R=10; //max drone flight time
int a=2; //speed of drone
int z1A1[1..2]=[2,8]; //target1
int z2A1[1..2]=[7,8]; //target2
float intraDist1=sqrt(((z2A1[1]-z1A1[1])^2)+(z2A1[2]-z1A1[2])^2); //distance between targets
float intraFlugDist1;
float wegFlugDist1;
float hinFlugDist1;
float kombiniertZeit0;
float kombiniertZeit1;
float getrenntZeit1;
//Dvar
dvar int+ sA1[1..2];
dvar int+ lA1[1..2];
//Model
minimize kombiniertZeit0+getrenntZeit1+kombiniertZeit1;
subject to{
E1:
kombiniertZeit0>=0;
(((sA1[1]-start[1])^2)+(sA1[2]-start[2])^2)<=kombiniertZeit0^2;
E2:
getrenntZeit1>=0;
(((lA1[1]-sA1[1])^2)+(lA1[2]-sA1[2])^2)<=getrenntZeit1^2;
E3:
kombiniertZeit1>=0;
(((start[1]-lA1[1])^2)+(start[2]-lA1[2])^2)<=kombiniertZeit1^2;
E4:
wegFlugDist1>=0;
(((z1A1[1]-sA1[1])^2)+(z1A1[2]-sA1[2])^2)<=wegFlugDist1^2;
E5:
hinFlugDist1>=0;
(((lA1[1]-z2A1[1])^2)+(lA1[2]-z2A1[2])^2)<=hinFlugDist1^2;
E6:
intraDist1<=intraFlugDist1;
E7:
(wegFlugDist1+intraFlugDist1+hinFlugDist1)/a<=getrenntZeit1;
E8:
R>=getrenntZeit1;
}
E1 ensures that kombiniertZeit0 is at least as large as the distance from the start to the launch point of the drone.
E2 ensures that getrenntZeit1 is at least as large as the distance from the launch point to the land point of the drone.
E3 ensures that kombiniertZeit1 is at least as large as the distance from the land point of the drone to the start.
E4 ensures that wegFlugDist1 is at least as large as the distance from the launch point of the drone to the first target.
E5 ensures that hinFlugDist1 is at least as large as the distance from the last target to the land point of drone.
E7 ensures that getrenntZeit1 is at least as large as the sum of hinFlugDist1, intraFlugDist1 and wegFlugDist1 divided by the speed of the drone a.
E8 ensures that getrenntZeit1 is not larger than the max flight time of the drone R.
When I debug the programm I get no feasible solution and I can`t figure out why.
I am very thankful for every hint! Thanks in Advance!
Sven
I ported your problem to MiniZinc and added some domain limits for distances and times:
array[1..2] of int: start = [0,0]; % start location
int: R=10; % max drone flight time
int: vDrone=2; % speed of drone
int: vCarrier=1; % speed of carrier
float: minDist = 0.0;
float: maxDist = 100.0;
float: minTime = 0.0;
float: maxTime = 20.0;
array[1..2] of int: z1A1=[2,8]; % target1
array[1..2] of int: z2A1=[7,8]; % target2
function var float: sqr(float: x) = x * x;
function var float: sqr(var float: x) = x * x;
function var int: sqr(var int: x) = x * x;
float: intraDist1=sqrt((z2A1[1]-z1A1[1])*(z2A1[1]-z1A1[1]) +
(z2A1[2]-z1A1[2])*(z2A1[2]-z1A1[2])); % distance between targets
var minDist .. maxDist: intraFlugDist1;
var minDist .. maxDist: wegFlugDist1;
var minDist .. maxDist: hinFlugDist1;
var minTime .. maxTime: kombiniertZeit0;
var minTime .. maxTime: kombiniertZeit1;
var minTime .. maxTime: getrenntZeit1;
array[1..2] of var 0..100: sA1;
array[1..2] of var 0..100: sA2;
solve minimize kombiniertZeit0 + getrenntZeit1 + kombiniertZeit1;
% E1:
constraint ((sqr(sA1[1]-start[1])+sqr(sA1[2]-start[2])) <= sqr(kombiniertZeit0)*vCarrier);
% E2:
constraint ((sqr(sA1[1]-sA2[1]) + sqr(sA1[2]-sA2[2])) <= sqr(getrenntZeit1)*vCarrier);
% E3:
constraint ((sqr(start[1]-sA2[1]) + sqr(start[2]-sA2[2])) <= sqr(kombiniertZeit1)*vCarrier);
% E4:
constraint ((sqr(z1A1[1]-sA1[1]) + sqr(z1A1[2]-sA1[2])) <= sqr(wegFlugDist1)*vDrone);
% E5:
constraint ((sqr(sA2[1]-z2A1[1]) + sqr(sA2[2]-z2A1[2])) <= sqr(hinFlugDist1)*vDrone);
% E6:
constraint (intraDist1 <= intraFlugDist1);
% E7:
constraint ((wegFlugDist1 + intraFlugDist1 + hinFlugDist1) <= getrenntZeit1*vDrone);
% E8:
constraint (R >= getrenntZeit1);
This leads to the following:
intraFlugDist1 = 5.0;
wegFlugDist1 = 5.8309518948453;
hinFlugDist1 = 7.51664818918645;
kombiniertZeit0 = 0.0;
kombiniertZeit1 = 0.0;
getrenntZeit1 = 9.173800042015881;
sA1 = array1d(1..2, [0, 0]);
sA2 = array1d(1..2, [0, 0]);
This means that the carrier stays in the start position and the drone travels all alone. The constraints have to be modified to enforce a less trivial behaviour. R = 6 is an easy way to prevent the drone from a solo.

multi-capacities Knapsack in CPLEX

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.

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