简体   繁体   中英

ompr MILPModel : non-numeric argument to binary operator

I am familiar with how to use ompr::MIPModel but am trying to learn how to use MILPModel to take advantage of the model build speed. A simplified version of my model is below. I have two decision variables, x and y, binary and of equal length. I have constraints on the sum of all the x decision variables, and the sum of all the y decision variables. So far so good with MILPModel, I can build the model and solve it fast.

The problem is when I try to use the next constraint. The LHS of this constraint multiplies the x binary decision variables by a numeric column in a dataframe of the same length, then multiplies that by a matrix where the rows are equal to the length of x. Similar story in the RHS with the y variable. I then iterate this constraint 20 times to represent all the columns of the matrix.

I've used constraints similar to this many times using MIPModel, but now when I try this I get an error message, non-numeric argument to binary operator . I assume this has something to do with the colwise function, but I am unfamiliar with how to approach this, even after reading up on the ompr github site. Thanks in advance for any help.

add_variable(x[i], i=1:10, type='binary') %>%
add_variable(y[i], i=1:10, type='binary') %>%
add_constraint(sum_expr(x[i],i=1:10) <= 5) %>%
add_constraint(sum_expr(y[i],i=1:10) <= 3) %>%

#model builds and solves until this point...
add_constraint( 
sum_expr( x[i]* df$numeric_column[i] * matrix_a[i,j],i=1:10) <= 
sum_expr(  2* y[i]* df$numeric_column[i] * df$other_numeric_column[i] * matrix_a[i,j],i=1:10), 
j=1:20) 

Figured it out. To use matrix algebra in a constraint requires a little bit of acrobatics. Good luck figuring out how to use matrix algebra in the objective function, should you need to.

Example comparing MIPModel to MILPModel is below.

library(tidyverse)
library(magrittr)
library(ompr)
library(ompr.roi)
library(ROI.plugin.glpk)

rm(list=ls())

numvec1 <- runif(10)
numvec2 <- runif(10)
matrix_a <- matrix(nrow=10,ncol=20,data=runif(10*20))

my_mip_model <- MIPModel() %>%
  
  add_variable(x[i], i=1:10, type='binary') %>%
  add_variable(y[i], i=1:10, type='binary') %>%
  add_constraint(sum_expr(numvec1[i]*x[i],i=1:10) <= 5) %>%
  add_constraint(sum_expr(2*y[i],i=1:10) <= 3) %>%
  
  add_constraint( 
    sum_expr( x[i]* numvec1[i] * matrix_a[i,j],i=1:10) <= 
      sum_expr(  2* y[i]* numvec1[i] * numvec2[i] * matrix_a[i,j],i=1:10), 
    j=1:20) %>%
  set_objective( sum_expr(3*x[i]*numvec1[i],i=1:10),sense='max')

my_mip_model_solve <- my_mip_model %>% solve_model(with_ROI(solver='glpk'))



#functionally equivalent using MILPmodel----

my_milp_model <- MILPModel() %>%
  
  add_variable(x[i], i=1:10, type='binary') %>%
  add_variable(y[i], i=1:10, type='binary') %>%
  add_constraint(sum_expr( colwise(numvec1[i]) * x[i],i=1:10) <= 5) %>%
  add_constraint(sum_expr( colwise(2) * y[i],i=1:10) <= 3)  %>%
  set_objective(sum_expr( colwise(3*numvec1[i]) * x[i],i=1:10),sense='max')

#now to add the matrix constraints, add a loop on the matrix column index j.
#with MIPModel we could just iterate on j in a single constraint, but here it appears
#we need to add the same constraint multiple times, and use the value of j to
#calculate the indices in as.numeric(matrix_a) that we want to use.
for(j in 1:ncol(matrix_a)){
  
  my_milp_model %<>% add_constraint(
    
    sum_expr( x[i]* colwise(numvec1[i] *
      as.numeric(matrix_a)[(i + (nrow(matrix_a)*j -nrow(matrix_a)))]),i=1:10) <= 
        sum_expr(  y[i]* colwise(2* numvec1[i] * numvec2[i] * 
    as.numeric(matrix_a)[(i + (nrow(matrix_a)*j -nrow(matrix_a)))]) ,i=1:10) ) 
    
}

my_milp_model_solve <- my_milp_model %>% solve_model(with_ROI(solver='glpk'))

#objective value and results should be equal...
my_mip_model_solve
my_milp_model_solve

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM