1

I am working on a Fantasy Football program and having an issue with a constraint. A fantasy team is made up of 1QB, 2RBs 3WRs 1TE, 1DEF and 1FLEX (which can be a RB, WR or TE)

My output is duplicating players. So, For example, if John Doe fills the RB position, I need him to not fill the FLEX position. I am at a loss of how to get this constraint done. Maybe a name comparison to ensure names don't equal each other?

Any advice would be greatly appreciated!

Here is some sample data:

| position | displayName         | Roster   | Position | salary | points |
|----------+---------------------+----------+----------+--------+--------|
| RB       | Christian McCaffrey | 15033483 | RB/FLEX  | 10000  | 30.95  |
| WR       | Michael Thomas      | 15033799 | WR/FLEX  | 9000   | 24.62  |
| QB       | Lamar Jackson       | 15033397 | QB       | 8100   | 29.85  |
| RB       | Dalvin Cook         | 15033485 | RB/FLEX  | 7900   | 21.62  |
# Set constraints
##################################################################
salaries = {}
points = {}

for pos in availables.position.unique():
    available_pos = availables[availables.position == pos]
    salary = list(available_pos[["displayName","salary"]].set_index("displayName").to_dict().values())[0]
    point = list(available_pos[["displayName","points"]].set_index("displayName").to_dict().values())[0]
    salaries[pos] = salary
    points[pos] = point

pos_num_available = {
    "QB": 1,
    "RB": 2,
    "WR": 3,
    "TE": 1,
    "FLEX": 1,
    "DST": 1
}


pos_flex = {
    "QB": 0,
    "RB": 1,
    "WR": 1,
    "TE": 1,
    "FLEX": 0,
    "DST": 0
}


pos_flex_available = 3
SALARY_CAP = 50000

_vars = {k: LpVariable.dict(k, v, cat="Binary") for k, v in points.items()}
##################################################################
# Problem Definition
##################################################################

prob = LpProblem("Fantasy", LpMaximize)
rewards = []
costs = []
position_constraints = []


for k, v in _vars.items():
     costs += lpSum([salaries[k][i] * _vars[k][i] for i in v])
     rewards += lpSum([points[k][i] * _vars[k][i] for i in v])
     prob += lpSum([_vars[k][i] for i in v]) <= pos_num_available[k]
     prob += lpSum([pos_flex[k] * _vars[k][i] for i in v]) <= pos_flex_available

prob += lpSum(rewards)
prob += lpSum(costs) <= SALARY_CAP
prob.solve()
0

1 Answer 1

0

I've cleaned up your code a bit for readability. The structure is exactly the same, it's just some syntax things.

Consider the following:

import pulp as pl
import pandas as pd

availables = pd.DataFrame(
    [
        ["RB", "Christian McCaffrey", 15033483, "RB/FLEX", 10000, 30.95],
        ["WR", "Michael Thomas", 15033799, "WR/FLEX", 9000, 24.62],
        ["QB", "Lamar Jackson", 15033397, "QB", 8100, 29.85],
        ["RB", "Dalvin Cook", 15033485, "RB/FLEX", 7900, 21.62]
    ],
    columns=["position", "displayName", "Roster", "Position", "salary", "points"]
)

##################################################################
# Set constraints
##################################################################
salaries = {}
points = {}
players = {}

for position in availables.position.unique():
    available_for_position = availables[availables.position == position]
    players[position] = list(available_for_position.Roster.values)

    salaries[position] = {
        player_roster: salary for player_roster, salary in
        zip(players[position], available_for_position.salary.values)
    }
    points[position] = {
        player_roster: _points for player_roster, _points in
        zip(players[position], available_for_position.points.values)
    }

positions_available = {
    "QB": 1,
    "RB": 2,
    "WR": 3,
    "TE": 1,
    "FLEX": 1,
    "DST": 1
}

flexible_positions = ("RB", "WR", "TE")

SALARY_CAP = 50000

# Player variables['QB'][15033483] denotes whether Lamar Jackson is selected
variables = {position: pl.LpVariable.dict(position, players[position], cat="Binary")
             for position in players}

##################################################################
# Problem Definition
##################################################################

prob = pl.LpProblem("Fantasy", pl.LpMaximize)
rewards = []
costs = []
number_of_selected_players = []

for position, players in variables.items():
    for player, player_selected in players.items():
        # If this player is selected, he will add salaries and points
        costs += salaries[position][player] * player_selected
        rewards += points[position][player] * player_selected
        number_of_selected_players += player_selected

    # Of this position, if it does not support FLEX, at most `positions_available`
    # are supported. If it does support FLEX, increment that by
    # `flexible_positions_available`
    if position not in flexible_positions:
        prob += pl.lpSum(players.values()) == positions_available[position]
    else:
        # We need at least `positions_available` players on this position and at
        # most`positions_available + flexible_positions_available` players
        prob += pl.lpSum(players.values()) >= positions_available[position]
        prob += (pl.lpSum(players.values())
                          <= positions_available[position] + positions_available["FLEX"])

# In total, we need exactly `positions_available` players
prob += pl.lpSum(number_of_selected_players) == sum(positions_available.values())

prob += pl.lpSum(rewards)
prob += pl.lpSum(costs) <= SALARY_CAP
prob.solve()

You keep track per player whether he has been selected. Then, you allow for at most positions_available players in that position, unless it's a "flexible" position, then you allow for between positions_available and positions_available + positions_available['FLEX'].

Because you require exactly 9 players in total, the only degree of freedom for the problem is to select one of the flexible players to fill that final flexible slot.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.