I am trying to solve a MILP supply network optimization problem using R's OMPR package. I need to define a 3D binary variable (x[i,j,q]) in the model to map Customers (i) to DC (j) by each SKU (q). Does anyone know how I can do that?
With my current code, I am getting the
Error - in as.data.frame.default(x[[i]], optional = TRUE) :
cannot coerce class ‘structure("LinearVariableCollection", package = "ompr")’ to a data.frame
I am no longer getting this error but the model is not giving the right output (verified against excel's open solver). There seems to be some issue with the constraint #4. It looks like the multiplication between VCustDemand and the variable x[i,j,q] is not happening in the right order.
model <- MILPModel() %>%
add_variable(y[j], j = 1:n, type = "binary")%>% #1: if warehouse j is opened
add_variable(x[i, j, q], i = 1:m, j =1:n, q=1:r , type = "binary")%>% #2: if i gets assigned to warehouse j for Product q
add_variable(z[p, j], p = 1:o, j = 1:n, type = "binary") %>% # 3 for selection of DC of a specific size
add_variable(aa[l,j,q], l = 1:k, j =1:n, q=1:r, type = "integer",lb = 0, ub = 500000) %>% # 4 for plant getting mapped to a warehouse for product q
set_objective(
sum_expr(colwise(Vsec_log[i+(j-1)*m*r+(q-1)*m]) * x[i, j, q] * colwise(VCustDemand[i+(q-1)*32]) , i = 1:m ,j = 1:n, q=1:r) + #Secondary shipments total
sum_expr(colwise(Vfix_fac[p+o*(j-1)]) * z[p, j] , p = 1:o, j = 1:n ) + #DC Fixed costs
sum_expr(colwise(VCustDemand[i+(q-1)*32]) * x[i,j,q] * colwise(Vvar_fac_storage[q+(j-1)*r]), i = 1:m , j = 1:n, q=1:r ) + #Varilable storage costs
sum_expr(colwise(VCustDemand[i+(q-1)*32]) * x[i,j,q] * colwise(Vvar_fac_handling[q+(j-1)*r]), i = 1:m , j = 1:n, q=1:r ) + #DC Variable handling costs
sum_expr(colwise(Vprimary_log[l+(j-1)*k*r+(q-1)*k]) * aa[l,j,q] , l = 1:k, j = 1:n, q=1:r), # + #Primary logistics costs
# sum_expr(aa[l,j,q]*colwise(Vplant_var[l+(q-1)*k]) , l = 1:k, j = 1:n, q = 1:r), #Plant variable costs
sense = "min") %>%
add_constraint(sum_expr(y[j] , j = 1:n) == 6)%>% #1. No. of open DCs
add_constraint(sum_expr(x[i, j, q], j = 1:n) == 1, i = 1:m, q=1:r) %>% #2. Each Customer is mapped to one DCs for 1 SKU
add_constraint((sum_expr(x[i, j, q], i = 1:m, q=1:r)/999) <= y[j], j = 1:n) %>% #3. Grouping constraint connecting #1 & #2
add_constraint(aa[l,j,q] >= 0, l = 1:k, j = 1:n, q = 1:r) %>% #4. Positive outflow from Plant s
add_constraint(sum_expr(aa[l,j,q], l = 1:k) == sum_expr(colwise(VCustDemand[i+(q-1)*32]) * x[i,j,q], i = 1:m), j = 1:n, q = 1:r)%>% #4 plant outflow should be equal to DC inflow for each SKU
add_constraint(sum_expr(aa[l,j,q], j = 1:n) <= Vtbl_plant_capacity[l+(q-1)*k], l = 1:k, q = 1:r) %>% ##5 Constraint on plant capacity for every SKU
add_constraint(sum_expr(aa[l,j,q], j = 1:n, q = 1:r) <= Vtbl_Total_plant_capacity[l], l = 1:k) %>%##6 Constraint on overall plant capacity across SKUs
add_constraint(sum_expr(z[p,j], p = 1:o) == y[j], j = 1:n) %>% #7. Select one facility per capacity size
add_constraint(sum_expr(colwise(Vfix_fac_cap[p]) * z[p,j], p = 1:o ) >=
sum_expr(colwise(VCustDemand[1:(m*r)]) * x[i,j,q], i = 1:m, q =1:r), j = 1:n) #8. Total DC outflow should be <= Total DC capacity
'''
If I replace the constraint by
add_constraint(sum_expr(aa[l,j,q], l = 1:2) == sum_expr(colwise(VCustDemand[i+(1-1)*32]) * x[i,j,q], i = 1:m), j = 1:n, q = 1) %>%
add_constraint(sum_expr(aa[l,j,q], l = 1:2) == sum_expr(colwise(VCustDemand[i+(2-1)*32]) * x[i,j,q], i = 1:m), j = 1:n, q = 2) %>%
add_constraint(sum_expr(aa[l,j,q], l = 1:2) == sum_expr(colwise(VCustDemand[i+(3-1)*32]) * x[i,j,q], i = 1:m), j = 1:n, q = 3) %>%
'''
The code seems to work
VCustDemand is a 2D data containing customer demand in the following format -
ProductLine CustomerCity Demand
SKU1 Agra 1755
SKU1 Ahemdabad 7279
SKU1 Delhi 1830
SKU2 Agra 1408
SKU2 Ahemdabad 9111
SKU2 Delhi 4970
SKU3 Agra 1469
SKU3 Ahemdabad 414
SKU3 Delhi 229