dirkschumacher / ompr

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

Error message in MILPModel #229

Closed Krut11 closed 6 years ago

Krut11 commented 6 years ago

Hi Dirk,

Thank you for a great package. Been most useful.

I'm experiencing some trouble, when using the MILPModel instead of MIP.

The following model works fine with MIP, but in the MILP version an error message on the objective function: "Error in DistanceMatrix[p, j] * h[p, j, v, t] : non-numeric argument to binary operator"

Part of code: Model <- MILPModel() %>%

# we create a variable that is 1 if we travel from station p to j with v in t
add_variable(h[p, j, v, t], p = 1:P, j = 1:P, v = 1:V, t = 1:T, type = "integer", lb = 0, ub = 1) %>%
# minimize travel distance (Object function)
set_objective(sum_expr(DistanceMatrix[p, j] * h[p, j, v, t], p = 1:P, j = 1:P, v = 1:V,  t = 1:T), "min")

DistanceMatrix is numeric and there are no issues, when running the above in a MIPModel. I have tried using the colwise() function, but this did not correct the error. Do you have any suggestions?

Thanks in advance.. /Kristian

hugolarzabal commented 6 years ago

MILP models do not accept matrix as parameters. You need to create a function which return a single vector with the values of DistanceMatrix for every combination of p,j,v,t like described here: https://dirkschumacher.github.io/ompr/dev/articles/milp-modelling.html#coefficients-and-colwise

hugolarzabal commented 6 years ago

In the error "Error in DistanceMatrix[p, j] * h[p, j, v, t] : non-numeric argument to binary operator", it is p and j which are non numeric arguments because the MILP model use p and j as vectors.

That means, it tries to evaluate DistanceMatrix[1:P, 1:P]

hugolarzabal commented 6 years ago

I think that something like that should work:

matrix_fun <- function(i,j){

  result <- c()
  for (i1 in i){
    for (j1 in j)
      result <- c(result, DistanceMatrix[i1,j1])
  }
  return(result)

}

distance_fun <- function(p, j, v, t) {

  df_Distance <- expand.grid(p=p,j=j,v=v,t=t)

  colwise(matrix_fun(df_Distance$p,df_Distance$j))

}

Then you should write your objective like that: set_objective(sum_expr(distance_fun(1:P, 1:P, 1:V, 1:T) * h[p, j, v, t], p = 1:P, j = 1:P, v = 1:V, t = 1:T), "min")

Krut11 commented 6 years ago

Thank you very much. Much appreciated.