Reputation: 71
I'm using the ompr
package for solving integer program. I wanted to include a constraint that based on the average value of another binary variable.
In the example below, I have some food and I want to find at least 5 items and minimize the cost. I would like the average calorie count to be above some minimum. In the code below, the first constraint is that the sum of the calories is above min_avg_cal
. Can this be rewritten so the constraint is that the average calorie of the chosen food is above min_avg_cal
?
library(dplyr)
library(ROI)
library(ROI.plugin.glpk)
library(ompr)
library(ompr.roi)
n <- 20
cost <- runif(n, 0, 10)
calories <- runif(n, 100, 200)
min_avg_cal <- 140
model <- MIPModel() %>%
add_variable(x[i], i =1:n, type = "binary") %>%
set_objective(sum_expr(cost[i] * x[i], i = 1:n), "min") %>%
add_constraint(sum_expr(calories[i] * x[i], i = 1:n) >= min_avg_cal) %>%
add_constraint(sum_expr(x[i], i = 1:n) >= 5)
result <- solve_model(model, with_ROI(solver = "glpk", verbose = TRUE))
result$solution
Upvotes: 0
Views: 1431
Reputation: 71
Based on a Sascha's suggestion, the mean can be rewritten as a sum of variable products by rearranging the constraint. In particular, you can change this constraint:
add_constraint(sum_expr(calories[i] * x[i], i = 1:n) >= min_avg_cal)
into
add_constraint(sum_expr(calories[i] * x[i] - x[i] * min_avg_cal, i = 1:n) >= 0)
which is just a rearrangement of the definition of the mean.
The full solution is the same as the original code with that single constraint replaced:
library(dplyr)
library(ROI)
library(ROI.plugin.glpk)
library(ompr)
library(ompr.roi)
n <- 20
cost <- runif(n, 0, 10)
calories <- runif(n, 100, 200)
min_avg_cal <- 140
model <- MIPModel() %>%
add_variable(x[i], i =1:n, type = "binary") %>%
set_objective(sum_expr(cost[i] * x[i], i = 1:n), "min") %>%
add_constraint(sum_expr(calories[i] * x[i] - x[i]*min_avg_cal , i = 1:n) >= 0) %>%
add_constraint(sum_expr(x[i], i = 1:n) >= 5)
result <- solve_model(model, with_ROI(solver = "glpk", verbose = TRUE))
calories[as.logical(result$solution)]
Upvotes: 0
Reputation: 33532
If you want some constraint:
mean(cal_0 * x_0 + cal_1 * x_1 + cal_2 * x_2 ...) >= min_avg_cal
where cal_x
are constants, x_x
are binary-variables,
reform it to:
cal_0 * x_0 + cal_1 * x_1 + cal_2 * x_2 ... >= min_avg_cal
-------------------------------------------
x_0 + x_1 + x_2 + ...
and:
cal_0 * x_0 + cal_1 * x_1 + cal_2 * x_2 ... >=
min_avg_cal * x_0 +
min_avg_cal * x_1 +
min_avg_cal * x_2 ...
The latter is a form your modelling-tool should support. It only containts sums of constant-variable products.
Upvotes: 1