( The OPL model and the Lindo model are in the code box ) I need some help with this problem. My goal is to organize which trucks will be shipped from origin to destination each week (week 1, 2, 3 and 4). In this example, there are a total of 6 trucks, and at least one must be shipped per week. Each shipment has an associated cost, and the goal is to minimize the cost in the first week, then the second, third and fourth. It's a lexicographic goal programming problem. I made the extended model in other software (Lindo) and it worked, but I am having difficulty writing in OPL. Could someone help me please?
Xijt, i= pickup point (1,2,3,4,5) , j= destination (1,2), t = weeks (1,2,3,4)
! My code in Lindo:
MIN p4
subject to
p1 = 10
p2 = 10
p3 = 100
! Cost
0 X111 + 0 X211 + 90 X311+ 0 X411 + 10 X511 + 0 X121 + 100 X221 + 0 X321 + 50 X421 + 10 X521 -p1 + n1 = 0 ! Week 1
0 X112 + 0 X212 + 90 X312+ 0 X412 + 10 X512 + 0 X122 + 100 X222 + 0 X322 + 50 X422 + 10 X522 -p2 + n2 = 0 ! Week 2
0 X113 + 0 X213 + 90 X313+ 0 X413 + 10 X513 + 0 X123 + 100 X223 + 0 X323 + 50 X423 + 10 X523 -p3 + n3 = 0 ! Week 3
0 X114 + 0 X214 + 90 X314+ 0 X414 + 10 X514 + 0 X124 + 100 X224 + 0 X324 + 50 X424 + 10 X524 -p4 + n4 = 0 ! Week 4
! Number of trucks
X311 + X312 + X313 + X314 = 1 !In 4 weeks, there is 1 truck from pickup point 3 to destination 1
X511 + X512 + X513 + X514 = 1
X221 + X222 + X223 + X224 = 2
X421 + X422 + X423 + X424 = 1
X521 + X522 + X523 + X524 = 1
! Week restriction
!At least one truck must be used per week
X311 + X511 + X221 + X421 + X521 >=1
X312 + X512 + X222 + X422 + X522 >=1
X313 + X513 + X223 + X423 + X523 >=1
X314 + X514 + X224 + X424 + X524 >=1
END
INT X311
INT X312
INT X313
INT X314
INT X511
INT X512
INT X513
INT X514
INT X221
INT X222
INT X223
INT X224
INT X421
INT X422
INT X423
INT X424
INT X521
INT X522
INT X523
INT X524
---------------------------------------------------
// CPLEX
using CP;
// decision variables
{string} Pickup = {"A","B","C","D","E"};
{string} Destination = {"D1" , "D2"};
{string} Weeks = {"W1", "W2", "W3", "W4"};
int Trucks [Pickup][Destination]= [[0,0],[0,2],[1,0],[0,1],[1,1]];
int Cost [Pickup]=[140,100,90,50,10];
//Decision Variables
dvar int Delivered [Forest][Destination][Weeks]; //not sure if it is right
//Expressions
dexpr int Week1 = sum (u in Pickup, c in Destination, W1 in Weeks) Trucks[u][c] * Cost [u] * Delivered[u][c][W1];
dexpr int Week2 = sum (u in Pickup, c in Destination, W2 in Weeks) Trucks[u][c] * Cost [u] * Delivered[u][c][W2];
dexpr int Week3 = sum (u in Pickup, c in Destination, W3 in Weeks) Trucks[u][c] * Cost [u] * Delivered[u][c][W3];
dexpr int Week4 = sum (u in Pickup, c in Destination, W4 in Weeks) Trucks[u][c] * Cost [u] * Delivered[u][c][W4];
//Objective Function
minimize staticLex (Week1,Week2,Week3,Week4);
//Constraint
subject to {
forall (u in Pickup)
forall (c in Destination)
sum (W1 in Weeks)
Trucks [u][c] >= 1;
forall (u in Forest)
forall (c in Destination)
sum (W2 in Weeks)
Trucks [u][c] >= 1;
forall (u in Pickup)
forall (c in Destination)
sum (W3 in Weeks)
Trucks [u][c] >= 1;
forall (u in Pickup)
forall (c in Destination)
sum (W4 in Weeks)
Trucks [u][c] >= 1;
}
execute Output {
writeln ("Delivered Plan")
for (var t in Trucks)
for (var u in Pickup)
for (var c in Destination)
for (var w in Weeks)
if (Delivered [t][u][c][w]>0) {
writeln (Delivered [t][u][c][w] + '' + " number of trucks " + '' + t + '' + " delivered from pickup poit " + '' + u +" to destination " +''+ c + " in the week "+''+ w);
}
}
This looks fishy:
//Expressions
dexpr int Week1 = sum (u in Pickup, c in Destination, W1 in Weeks) Trucks[u][c] * Freshness [u] * Delivered[u][c][W1];
dexpr int Week2 = sum (u in Pickup, c in Destination, W2 in Weeks) Trucks[u][c] * Freshness [u] * Delivered[u][c][W2];
dexpr int Week3 = sum (u in Pickup, c in Destination, W3 in Weeks) Trucks[u][c] * Freshness [u] * Delivered[u][c][W3];
dexpr int Week4 = sum (u in Pickup, c in Destination, W4 in Weeks) Trucks[u][c] * Freshness [u] * Delivered[u][c][W4];
//Objective Function
minimize staticLex (Week1,Week2,Week3,Week4);
In the expression for a single week you are summing variables for all weeks. I guess what you want instead is this:
//Expressions
dexpr int Week1 = sum (u in Pickup, c in Destination) Trucks[u][c] * Freshness [u] * Delivered[u][c]["W1"];
dexpr int Week2 = sum (u in Pickup, c in Destination) Trucks[u][c] * Freshness [u] * Delivered[u][c]["W2"];
dexpr int Week3 = sum (u in Pickup, c in Destination) Trucks[u][c] * Freshness [u] * Delivered[u][c]["W3"];
dexpr int Week4 = sum (u in Pickup, c in Destination) Trucks[u][c] * Freshness [u] * Delivered[u][c]["W4"];
Note that the last index for Delivered
is now constant in each expression. Each expression now only sums the variables for one single week.
Update: And there are other issues with your model: First of all, all the four constraints are exactly the same. You could just write them as a single constraint:
forall (u in Pickup)
forall (c in Destination)
sum (w in Weeks)
Trucks [u][c] >= 1;
Then these constraints look strange since you sum over w in Weeks
but the quantity you sum over (Trucks
) is not indexed by weeks. And Trucks
is not a decision variable either. So you are not really stating a constraint here but are just summing up constant values.
The next issue is that your decision variable Delivered
does not appear in any constraint. So there is not much to optimize here.
You may want to go back and review what exactly should be optimized. What are the things the optimizer is allowed to change or must decide, what are the constraints, etc. For example, in your LINDO model I don't see anything that looks related to the Delivered
decision variables or the Freshness
or Forest
things. Instead in the LINDO model it seems that Trucks
are the decision variables and are also indexed over weeks.
Here is an OPL model that should be equivalent to your LINDO model (without fixing things for weeks 1, 2, 3:
{string} Pickup = {"A","B","C","D","E"};
{string} Destination = {"D1" , "D2"};
{string} Weeks = {"W1", "W2", "W3", "W4"};
// In the LINDO model not all variables are used. For example, variable
// X111 (which means going from pickup 1 to destination 1 in week 1) is
// never used. We use a tuple and a tuple set to list all the
// pickup/destination combinations that are actually used.
tuple P {
string pickup; // Pickup location
string destination; // Destination location
}
{P} Pairs = { <"C", "D1">, // 31
<"E", "D1">, // 51
<"B", "D2">, // 22
<"D", "D2">, // 42
<"E", "D2"> // 52
};
int PickupCost[Pickup] = [ 140, 100, 90, 50, 10 ];
//Decision Variables
dvar int+ Trucks[Pairs][Weeks];
//Expressions
dexpr int Week1 = sum(p in Pairs) Trucks[p]["W1"] * PickupCost[p.pickup];
dexpr int Week2 = sum(p in Pairs) Trucks[p]["W2"] * PickupCost[p.pickup];
dexpr int Week3 = sum(p in Pairs) Trucks[p]["W3"] * PickupCost[p.pickup];
dexpr int Week4 = sum(p in Pairs) Trucks[p]["W4"] * PickupCost[p.pickup];
//Objective Function
minimize staticLex (Week1, Week2, Week3, Week4);
//Constraint
subject to {
// Number of trucks
forall(p in Pairs)
sum(w in Weeks) Trucks[p][w] >= 1;
// Week restriction
// At least one truck must be used per week
forall(w in Weeks)
sum(p in Pairs) Trucks[p][w] >= 1;
}