ompr MILPModel : нечисловой аргумент бинарного оператора

Я знаком с тем, как использовать ompr::MIPModel, но пытаюсь научиться использовать MILPModel, чтобы воспользоваться преимуществами скорости построения модели. Упрощенная версия моей модели ниже. У меня есть две переменные решения, x и y, двоичные и одинаковой длины. У меня есть ограничения на сумму всех переменных решения x и сумму всех переменных решения y. Пока все хорошо с MILPModel, я могу быстро построить модель и решить ее.

Проблема в том, что я пытаюсь использовать следующее ограничение. LHS этого ограничения умножает x двоичных переменных решения на числовой столбец в кадре данных той же длины, а затем умножает это на матрицу, в которой строки равны длине x. Аналогичная история в RHS с переменной y. Затем я повторяю это ограничение 20 раз, чтобы представить все столбцы матрицы.

Я использовал подобные ограничения много раз, используя MIPModel, но теперь, когда я пытаюсь это сделать, я получаю сообщение об ошибке, non-numeric argument to binary operator. Я предполагаю, что это как-то связано с функцией colwise, но я не знаю, как к этому подойти, даже после прочтения на сайте ompr github. Заранее благодарю за любую помощь.

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) 

person Ralph Asher    schedule 07.08.2020    source источник


Ответы (1)


Догадаться. Чтобы использовать матричную алгебру в ограничении, требуется немного акробатики. Удачи вам в выяснении того, как использовать матричную алгебру в целевой функции, если вам это нужно.

Ниже приведен пример сравнения MIPModel с MILPModel.

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

person Ralph Asher    schedule 09.08.2020