range I = 1..4; // crops
range J = 1..4; // farms
range A = 1..40; // trays
range T = 1..10; // periods
// Parameter
int demand_lower[I][T] = ...;
int demand_upper[I][T] = ...;
int initial_avail_tray[J][A] = ...;
int plots[J][A] = ...;
float yield_crop[I][J] = ...;
float yield_mult_normal = ...;
float yield_mult_early = ...;
float yield_mult_late = ...;
int max_vehicle_cap = ...;
int min_load_trans = ...;
int sprout_cost[I] = ...;
int fertilizer_cost[J][A] = ...;
int harvest_cost = ...;
int transport_cost[J] = ...;
int selling_price[I] = ...;
// Decision Variable
dvar float+ total_harvest[J][T];
dvar float+ total_harvest_early[I][J][A][T];
dvar float+ total_harvest_normal[I][J][A][T];
dvar float+ total_harvest_late[I][J][A][T];
dvar boolean availability_of_tray[J][A][T];
dvar int+ tray_harvested[J][T];
dvar boolean plant_decision[I][J][A][T];
dvar boolean harvest_early_decision[I][J][A][T];
dvar boolean harvest_normal_decision[I][J][A][T];
dvar boolean harvest_late_decision[I][J][A][T];
dvar boolean transport_decision[J][T];
// Objective
maximize
sum(i in I, j in J, a in A, t in T)
(
selling_price[i] * (
total_harvest_early[i][j][a][t] +
total_harvest_normal[i][j][a][t] +
total_harvest_late[i][j][a][t])
) // Revenue Harvest
- sum(i in I, j in J, a in A, t in T)
(
sprout_cost[i] * plant_decision[i][j][a][t] * plots[j][a]
) // Sprout Cost
- sum(i in I, j in J, a in A, t in T)
(
fertilizer_cost[j][a] * plant_decision[i][j][a][t]
) // Fertilizer Cost
- sum(j in J, t in T)
(
harvest_cost * tray_harvested[j][t]
) // Harvest Cost
- sum(j in J, t in T)
(
transport_cost[j] * transport_decision[j][t]
); //Transport Cost
//Constrains
subject to {
// Demand lower bound
forall(i in I, t in T)
sum(j in J, a in A)
(total_harvest_early[i][j][a][t] +
total_harvest_normal[i][j][a][t] +
total_harvest_late[i][j][a][t]) >= demand_lower[i][t];
// Demand upper bound
forall(i in I, t in T)
sum(j in J, a in A)
(total_harvest_early[i][j][a][t] +
total_harvest_normal[i][j][a][t] +
total_harvest_late[i][j][a][t]) <= demand_upper[i][t];
// Constrain Plant and Harvest Link
forall(j in J, a in A, t in 1..7)
harvest_early_decision[1][j][a][t+1] +
harvest_normal_decision[1][j][a][t+2] +
harvest_late_decision[1][j][a][t+3] == plant_decision[1][j][a][t];
forall(j in J, a in A, t in 1..7)
harvest_early_decision[2][j][a][t+1] +
harvest_normal_decision[2][j][a][t+2] +
harvest_late_decision[2][j][a][t+3] == plant_decision[2][j][a][t];
forall(j in J, a in A, t in 1..6)
harvest_early_decision[3][j][a][t+2] +
harvest_normal_decision[3][j][a][t+3] +
harvest_late_decision[3][j][a][t+4] == plant_decision[3][j][a][t];
forall(j in J, a in A, t in 1..6)
harvest_early_decision[4][j][a][t+2] +
harvest_normal_decision[4][j][a][t+3] +
harvest_late_decision[4][j][a][t+4] == plant_decision[4][j][a][t];
// Quantification
forall(i in I, j in J, a in A, t in T)
total_harvest_early[i][j][a][t] ==
harvest_early_decision[i][j][a][t] * plots[j][a] * yield_crop[i][j] * yield_mult_early;
forall(i in I, j in J, a in A, t in T)
total_harvest_normal[i][j][a][t] ==
harvest_normal_decision[i][j][a][t] * plots[j][a] * yield_crop[i][j] * yield_mult_normal;
forall(i in I, j in J, a in A, t in T)
total_harvest_late[i][j][a][t] ==
harvest_late_decision[i][j][a][t] * plots[j][a] * yield_crop[i][j] * yield_mult_late;
// Tray Capacity
forall(j in J, a in A)
availability_of_tray[j][a][1] == initial_avail_tray[j][a];
forall(j in J, a in A, t in T: t > 1)
availability_of_tray[j][a][t] ==
availability_of_tray[j][a][t-1] -
sum(i in I) plant_decision[i][j][a][t] +
sum(i in I) (harvest_early_decision[i][j][a][t] +
harvest_normal_decision[i][j][a][t] +
harvest_late_decision[i][j][a][t]);
// Total harvest
forall(j in J, t in T)
total_harvest[j][t] ==
sum(i in I, a in A)
(
total_harvest_early[i][j][a][t] +
total_harvest_normal[i][j][a][t] +
total_harvest_late[i][j][a][t]
);
// Transport Cost
forall(j in J, t in T)
{
total_harvest[j][t] <= max_vehicle_cap * transport_decision[j][t];
total_harvest[j][t] >= min_load_trans * transport_decision[j][t];
}
// Tray Harvested
forall(j in J, t in T)
tray_harvested[j][t] ==
sum(i in I, a in A)
(
harvest_early_decision[i][j][a][t] +
harvest_normal_decision[i][j][a][t] +
harvest_late_decision[i][j][a][t]
);
};
And here's the .dat file:
demand_lower = [
[0, 0, 0, 0, 0, 30, 30, 30, 30, 30], // GO
[0, 0, 0, 0, 0, 30, 30, 30, 30, 30], // BC
[0, 0, 0, 0, 0, 20, 20, 20, 20, 20], // RO
[0, 0, 0, 0, 0, 30, 30, 30, 30, 30] // C
];
demand_upper = [
[0, 0, 0, 0, 0, 120, 120, 120, 120, 120], // GO
[0, 0, 0, 0, 0, 120, 120, 120, 120, 120], // BC
[0, 0, 0, 0, 0, 80, 80, 80, 80, 80], // RO
[0, 0, 0, 0, 0, 120, 120, 120, 120, 120] // C
];
initial_avail_tray = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //KK 1
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //KK 2
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0], //KS 1
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] //KS 5
];
plots = [
[15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //KK 1
[15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //KK 2
[15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 0, 0, 0, 0, 0], //KS 1
[15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], //KS 5
];
yield_crop = [
[0.25, 0.25, 0.30, 0.20], //GO
[0.20, 0.20, 0.15, 0.15], //BC
[0.25, 0.20, 0.20, 0.30], //RO
[0.25, 0.20, 0.25, 0.30] //C
];
yield_mult_normal = 1.0;
yield_mult_early = 0.8;
yield_mult_late = 1.0;
max_vehicle_cap = 100;
min_load_trans = 20;
fertilizer_cost = [
[200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 0, 0, 0, 0, 0],
[200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350, 350],
];
harvest_cost = 30;
sprout_cost = [10, 10, 15, 12];
transport_cost = [1000, 1000, 1500, 1500];
selling_price = [220, 220, 380, 210];
It has been running for 20 hours, and the remaining nodes keep increasing while the incumbent value stays the same. Is there something wrong with how I modeled it in CPLEX that is causing it to run so slowly?
Note: I still don’t know how to include the dummy period in my model, so I set the demand for the first five weeks to zero. I also tried to reduce the problem size by using only 4 farms and 10 periods.