dirkschumacher / ompr

R package to model Mixed Integer Linear Programs
https://dirkschumacher.github.io/ompr/
Other
268 stars 35 forks source link

Define/Use Sparse Matrices #330

Closed sbmack closed 2 years ago

sbmack commented 3 years ago

I am trying to define a "sparse" variable set. I.e., not all multi-index combinations are feasible. E.g.

plant <- 1:4
machine <- 1:8
product <- 1:3
month <- 1:4

vars <- expand.grid(plant, machine, product, month)
names(vars) <- c('plant', 'machine', 'product', 'month')
produce <- arrange(vars, by = plant, machine, product, month) 

So that is the exhaustive variable set for produce However the plant, machine, product index set is restricted to this data frame:

data <- structure(list(plant = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 
3L, 3L, 4L, 4L, 4L), machine = c(1L, 1L, 2L, 3L, 4L, 4L, 5L, 
6L, 6L, 7L, 7L, 8L, 8L, 8L), product = c(1L, 2L, 3L, 3L, 1L, 
3L, 2L, 1L, 3L, 1L, 2L, 1L, 2L, 3L), cost = c(73.3, 52.9, 65.4, 
47.6, 79, 66.8, 52, 75.8, 50.9, 79.9, 52.1, 82.7, 63.3, 53.8), 
    rate = c(500L, 450L, 550L, 350L, 550L, 450L, 300L, 450L, 
    300L, 400L, 350L, 550L, 400L, 350L)), row.names = c(NA, -14L
), class = "data.frame")

I can reduce the size of the produce data_frame with an inner_join

produce <- inner_join(vars, data, by = c('plant', 'machine', 'product'))

The question then is how to declare that sparse variable set to MILPModel/MIPModel?

model <- MILPModel %>%
  add_variable(produce[plant, machine, product, month] for plant, machine, product, month in data)???

From a comment in an earlier issue thread: https://github.com/dirkschumacher/ompr/issues/234#issuecomment-427889671

When you talk about sparse matrix, I understand that you mean that not every combination of p and t would exist, right?

If so, you can filter when creating the variables: add_constraint(buy[p,t], p = 1:n_product m = 1:n_months, filter = my_filter(p,m))

So hugolarzabal refers to a filter function filter = my_filter(p, m) Can somebody explain the specifics of what the function is and it's return value? I.e. in my case I would have filter = my_filter(plant, machine, product) and my_filter would be what?

Thanks for the assistance. SteveM

dirkschumacher commented 2 years ago

You can use filter functions or simple conditions to restrict the combinations of indexes being generated:

add_constraint(buy[p, t] == 1, p = 1:n, m = 1:n, my_filter(p, m)) would add a constraint only if my_filter(p, m) is true for the combination of the indexes. But you can also add any type of condition that evaluates to TRUE/FALSE. In the case of the current master version on Github, my_filter takes scalar (length 1) values and has to return either TRUE or FALSE.

E.g. add_variable(x[a, b], a = 1:n, b = 1:n, a <= b, a %% 2 == 0)

Does that help?