dirkschumacher / ompr

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

How to set_bounds for a vector of bounds? #365

Closed sbmack closed 2 years ago

sbmack commented 2 years ago

I just started playing with ompr again after a long layoff. So have to reacquaint with the syntax. This simple model fails at the set_bounds statement:

library(ompr)
library(magrittr)
obj <- c(.05, .08)
con1 <- c(.1, .2)
upbnd <- c(8000, 5000)
rhs <- 1400

model <- MIPModel() %>%
      add_variable(product[i], i = 1:2, type = "continuous", lb = 0) %>%
      set_objective(sum_expr(obj[i] * product[i], i = 1:2), "max") %>%
      add_constraint(sum_expr(con1[i] * product[i], i = 1:2) <= rhs) %>%
      set_bounds(product[i], ub = upbnd, i = 1:2)
Error in set_bounds.linear_optimization_model(., product[i], ub = upbnd,  : 
  length(ub) == 1 is not TRUE

All of the examples I've seen have the bound for an indexed variable set as a constant. I can't figure out the syntax of the set_bounds statement to index the bound over the index of the variable. Advice appreciated, SteveM

dirkschumacher commented 2 years ago

set_bounds currently only supports length 1 values. You can use add_constraint(product[i] <= upbnd[i], i = 1:2) to set the bounds as constraints at the moment or loop through the indexes and set the bounds 1 by 1.

library(ompr)
obj <- c(.05, .08)
con1 <- c(.1, .2)
upbnd <- c(8000, 5000)
rhs <- 1400

model <- MIPModel() |>
  add_variable(product[i], i = 1:2, type = "continuous", lb = 0) |>
  set_objective(sum_expr(obj[i] * product[i], i = 1:2), "max") |>
  add_constraint(sum_expr(con1[i] * product[i], i = 1:2) <= rhs)
for (i in 1:2) {
  model <- set_bounds(model, product[i], ub = upbnd[i])
}
model
#> Mixed integer linear optimization problem
#> Variables:
#>   Continuous: 2 
#>   Integer: 0 
#>   Binary: 0 
#> Model sense: maximize 
#> Constraints: 1

I will however think about a new set_bounds interface similar to add_constraints so that you can say:

set_bounds(product[i] <= upbnd[i], i = 1:2) # or even
set_bounds(0 <= product[i] <= upbnd[i], i = 1:2)
dirkschumacher commented 2 years ago

Ok, 0 <= x <= 10 is not possible as it is not valid R syntax, but set_bounds(x <= 10) will work.

dirkschumacher commented 2 years ago

With PR #368 merged, you can now write:

library(ompr)
obj <- c(.05, .08)
con1 <- c(.1, .2)
upbnd <- c(8000, 5000)
rhs <- 1400

model <- MIPModel() |>
  add_variable(product[i], i = 1:2, type = "continuous", lb = 0) |>
  set_objective(sum_expr(obj[i] * product[i], i = 1:2), "max") |>
  add_constraint(sum_expr(con1[i] * product[i], i = 1:2) <= rhs) |> 
  set_bounds(product[i] <= upbnd[i], i = 1:2)
model
#> Mixed integer linear optimization problem
#> Variables:
#>   Continuous: 2 
#>   Integer: 0 
#>   Binary: 0 
#> Model sense: maximize 
#> Constraints: 1
variable_bounds(model)
#> $lower
#> [1] 0 0
#> 
#> $upper
#> [1] 8000 5000

Created on 2022-01-10 by the reprex package (v2.0.1)