R OMPR package - Limiting the number of unique variable components chosen

344 views Asked by At

I'm using the ompr package for creating and solving an integer programming problem. For simplicity's sake, I will use NFL football fantasy players as my example.

I want to maximize the number of points scored across the 2 games, while only playing 1 player at each position per game. (For simplicity's sake, here assume that any player can play any position.)

The part I'm having trouble with is that of the 25 possible players, I want to limit the total number of players chosen across the two games to 15. The i component of the added ompr variable represents the player indices, but I'm not sure how to add a constraint that limits the total unique i's chosen.

Any help would be greatly appreciated!

n_players = 25
n_positions = 11
n_games = 2

# Points each player will score at each position per game
points_game1 = matrix(runif(25*11), nrow = 25, ncol = 11)
points_game2 = matrix(runif(25*11), nrow = 25, ncol = 11)
points_array <- array(c(points_game1, points_game2), dim = c(n_players, n_positions, 2))

mip <- ompr::MIPModel() %>% 
  
  # Initialize player/position set of binary options
  ompr::add_variable(x[i, j, k], i = 1:n_players, j = 1:n_positions, k = 1:n_games, type = 'binary') %>%
  
  # Every player/game can only be 0 or 1 across all positions
  ompr::add_constraint(sum_expr(x[i, j, k], j = 1:n_positions) <= 1, i = 1:n_players, k = 1:n_games) %>% 
  
  # Every position/game has to be exactly 1 across all players
  ompr::add_constraint(sum_expr(x[i, j, k], i = 1:n_players) == 1, j = 1:n_positions, k = 1:2) %>%
  
  # ****** Limit to 15 players total ??? ****
  
  # Objective is to maximize points
  ompr::set_objective(sum_expr(x[i, j, k] * points_array[i, j, k], i = 1:n_players, j = 1:n_positions, k = 1:n_players), 'max') %>% 

  # Solve model
  ompr::solve_model(with_ROI(solver = 'symphony', verbosity = -2))

1

There are 1 answers

1
cookesd On BEST ANSWER

You can add a set of binary variables indexed across the players that tracks whether or not a player is used in any postition in any game. Then you can limit the sum of those variables to your limit (15). This lets you only count a player once even if they get used in both games. Then you can add a big M constraint that forces the new binary variables to be 1 if a player is used in any position in any game, but lets the variable be 0 if the player is not used. Since we have two games and a player can be in at most 1 position in each game, we can set the big M to be 2 for all players

ompr::add_variable(is_used[i], i = 1:n_players, type = 'binary') %>%
ompr::add_constraint(sum_expr(is_used[i],i = 1:n_players) <= 15) %>%
# big M constraint ensuring that is_used is 1 if a player is used
ompr::add_constraint(2*is_used[i] >= sum_expr(x[i,j,k],j = 1:n_positions, k = 1:2), i = 1:n_players) %>%