How to define 3D variable in OMPR package of R?

111 views Asked by At

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
0

There are 0 answers