R: ompr package constraints

579 views Asked by At

I am using ompr package in R to solve an omptimization problem. The optimization problem in written looks like this:

Min wi * xi

xi ϵ {0,1}

xi ≤ xj , j follower of i

i is a follower of j if in the distance matrix (distmatrix) a value is available. If the value is inf there is no connection possible from i to j

The goal is to analyze a Bill of Material, to make my example a bit easier I have created a more simple example with less materials in it.

vertices_undef <- data.frame(matrix(ncol=3, nrow=5))
vertices_undef$X1 <- c("3","5","9","7","2")
vertices_undef$X3 <- c(12, -8, 8, 3, -9)

rownames(vertices_undef) <- vertices_undef$X1

distMatrix <- data.frame(matrix(ncol=5, nrow=5))
rownames(distMatrix) <- vertices_undef$X1
colnames(distMatrix) <- vertices_undef$X1
distMatrix$`3` <- c("inf", 0.7, "inf", "inf", 0.3)
distMatrix$`5` <- c(3, "inf", "inf", "inf", 0.3)
distMatrix$`9` <- c("inf", 0.7, "inf", 0, 3)
distMatrix$`7` <- c("inf", "inf", "inf", 0.3, "inf")
distMatrix$`2` <- c("inf", 7, "inf", "inf", 0.3)


w <- vertices_undef$X3
w <- t(w)
colnames(w)<- vertices_undef$ID
w <- t(w)

    result <- MIPModel() %>%
      add_variable(x[i], type = "binary", i = as.integer(as.character(vertices_undef$X1))) %>%
      set_objective(sum_expr(x[i]*w[i,1], i = as.integer(as.character(vertices_undef$X1))), "min") %>%
      add_constraint(x[i]<=x[j], i = as.integer(as.character(vertices_undef$X1)), j = as.integer(as.character(vertices_undef$X1)), is.finite(distMatrix[i,j])==TRUE)%>%
      solve_model(with_ROI(solver = "glpk"))

    get_solution(result, x[i])

If I cross out the constraint I am getting the result I would expext (considered that the constraint is not used). How can I adress within the constraint the i and the j separately?

1

There are 1 answers

0
DirkS On BEST ANSWER

The filter condition in your add_constraint call produces an error. The i and j are vectors and indexing a matrix using vectors does not produce a single logical vector as required by add_constraint, but another matrix. Also, some i/j combinations are not part of your distMatrix matrix.

What happens internally is essentially this:

x <- expand.grid(i = as.integer(as.character(vertices_undef$X1)),
                 j = as.integer(as.character(vertices_undef$X1)))
is.finite(distMatrix[x$i, x$j])

The filter condition (i.e. the expression is.finite(distMatrix[i,j])==TRUE) needs to return a logical vector with the length of i/j that indicates which row should be included in the model and which should not be included.