2

I am new to Pulp and therefore have been encountering a problem when trying to make a conditional constraint. I have made a fantasy football optimizer that picks the optimal selection of 9 players, my solver fully works currently with position constraints, salary constraints, and more.

The last thing I need to add is a constraint that makes it so out of the 9 players it picks, there need to be 8 unique team names of the players. For example: there is a Quarterback and a WR/TE going to be on the same team given this constraint in my code ###Stack QB with 2 teammates. and therefore everyone else should be on a different team than each other to have 8 unique team names.

Below is the the code i have tried to use to make this constraint, the head of the excel file being optimized and my code that works so far without the constraint I want to add of 8 unique team names in the 9 players selected.

I have currently tried this but it doesn't work! Would really appreciate any help!

list_of_teams = raw_data['Team'].unique()
team_vars = pulp.LpVariable.dicts('team', list_of_teams, cat = 'Binary')

for team in list_of_teams:
  prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Team'][i] == team] + [-9*team_vars[team]]) <= 0

prob += pulp.lpSum([team_vars[t] for t in list_of_teams]) >= 8

CSV File with player data

file_name = 'C:/Users/Michael Arena/Desktop/Football/Simulation.csv'
raw_data = pd.read_csv(file_name,engine="python",index_col=False, header=0, delimiter=",", quoting = 3)


player_ids = raw_data.index
player_vars = pulp.LpVariable.dicts('player', player_ids, cat='Binary')

prob = pulp.LpProblem("DFS Optimizer", pulp.LpMaximize)

prob += pulp.lpSum([raw_data['Projection'][i]*player_vars[i] for i in player_ids])

##Total Salary upper:
prob += pulp.lpSum([raw_data['Salary'][i]*player_vars[i] for i in player_ids]) <= 50000

##Total Salary lower:
prob += pulp.lpSum([raw_data['Salary'][i]*player_vars[i] for i in player_ids]) >= 49900

##Exactly 9 players:
prob += pulp.lpSum([player_vars[i] for i in player_ids]) == 9

##2-3 RBs:
prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Position'][i] == 'RB']) >= 2
prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Position'][i] == 'RB']) <= 3

##1 QB:
prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Position'][i] == 'QB']) == 1
##3-4 WRs:
prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Position'][i] == 'WR']) >= 3
prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Position'][i] == 'WR']) <= 4

##1-2 TE's:
prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Position'][i] == 'TE']) >= 1
# prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Position'][i] == 'TE']) <= 2

##1 DST:
prob += pulp.lpSum([player_vars[i] for i in player_ids if raw_data['Position'][i] == 'DST']) == 1


###Stack QB with 2 teammates
for qbid in player_ids:
    if raw_data['Position'][qbid] == 'QB':
        prob += pulp.lpSum([player_vars[i] for i in player_ids if 
                          (raw_data['Team'][i] == raw_data['Team'][qbid] and 
                            raw_data['Position'][i] in ('WR', 'TE'))] + 
                            [-1*player_vars[qbid]]) >= 0

###Don't stack with opposing DST:
for dstid in player_ids:
    if raw_data['Position'][dstid] == 'DST':
        prob += pulp.lpSum([player_vars[i] for i in player_ids if
                            raw_data['Team'][i] == raw_data['Opponent'][dstid]] +
                            [8*player_vars[dstid]]) <= 8



###Stack QB with 1 opposing player:
for qbid in player_ids:
    if raw_data['Position'][qbid] == 'QB':
        prob += pulp.lpSum([player_vars[i] for i in player_ids if
                            (raw_data['Team'][i] == raw_data['Opponent'][qbid] and 
                            raw_data['Position'][i] in ('WR', 'TE'))]+
                            [-1*player_vars[qbid]]) >= 0


prob.solve()

1 Answer 1

2

In Linear Programming terms

Let x_i = 1 if the i^th player is chosen, and 0 otherwise, i = 1....I.
Let t_i be the team of the i^th player, which is a constant.
Let t_j be the j^th unique team, also a constant, j = 1....T.
And let t_{ij} = 1 if t_i == t_j, and 0 otherwise. This is also a constant.

Then you can say that the total number of players selected from team t_j is (t_{1j}*x_1 + t_{1j}*x_2 + ... + t_{Ij}*x_I), which takes a value between 0 and I, logically.


Now, you can let the binary variable y_j = 1 if any selected players come from team t_j, and 0 otherwise, like this:

(t_{1j}*x_1 + t_{1j}*x_2 + ... + t_{Ij}*x_I) >= y_j

This gives you the following situation:

  • If (t_{1j}*x_1 + t_{1j}*x_2 + ... + t_{Ij}*x_I) = 0, then y_j is 0;
  • If (t_{1j}*x_1 + t_{1j}*x_2 + ... + t_{Ij}*x_I) > 0, then y_j can be 0 or 1.

And now, if you add a constraint (y_1 + y_2 + ... + y_T) >= 8, that implies that (t_{1j}*x_1 + t_{1j}*x_2 + ... + t_{Ij}*x_I) > 0 for at least 8 different teams t_j.


In PULP terms (something like this, wasn't able tot test it)

If player_vars is a binary variable equivalent to x_i

teams = raw_data['Team']  # t_i
unique_teams = teams.unique()  # t_j
player_in_team = teams.str.get_dummies()  # t_{ij}

# Example output for `teams = pd.Series(['A', 'B', 'C', 'D', 'E', 'F', 'A', 'C', 'E'])`:
#    A  B  C  D  E  F
# 0  1  0  0  0  0  0
# 1  0  1  0  0  0  0
# 2  0  0  1  0  0  0
# 3  0  0  0  1  0  0
# 4  0  0  0  0  1  0
# 5  0  0  0  0  0  1
# 6  1  0  0  0  0  0
# 7  0  0  1  0  0  0
# 8  0  0  0  0  1  0

team_vars = pulp.LpVariable.dicts('team', unique_teams, cat='Binary')  # y_j

for team in unique_teams:
  prob += pulp.lpSum(
      [player_in_team[team][i] * player_vars[i] for i in player_ids]
  ) >= team_vars[team]

prob += pulp.lpSum([team_vars[t] for t in unique_teams]) >= 8
Sign up to request clarification or add additional context in comments.

5 Comments

First off I want to say, thank you for taking the time to read and respond to my question. I really appreciate it. I’m still pretty confused when looking at your code right now though (I am not the most advanced coder). Would you be able to put out the solution of code I would need to implement? Would make it easier for me to follow along with how it works. Thanks so much!
I've added a Python implementation, but I wasn't able to test it. Hope it helps you wrap your mind around it
Thank you for taking the time to implement it, I wanted to see if it worked and then understand it but I'm getting some errors with the code. in the for team in unique_teams loop I am getting a NameError as i is not defined. and for the for team in team_vars loop I'm getting a syntax issue that I cant figure out how to fix. Any corrections or suggestions to me would be really appreciated
Hi Ruben, I've been trying many different ways to make this code work and I've been struggling to make it happen. Would really appreciate a follow up!
Awesome! I got it working now, i really appreciate your help!!! really nice of you to take the time. All the best

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.