Beispiel #1
0
    def build_best_formation_model(self,
                                   players,
                                   n_weeks,
                                   budget,
                                   existing_team,
                                   n_free_transf,
                                   n_max_transf=15):

        self.players = players

        model = ConcreteModel()

        model.W = RangeSet(0, n_weeks - 1)  #Time index
        model.I = RangeSet(0, len(self.players) - 1)  #Player index
        model.I_gkp = Set(initialize=[
            i for i, p in enumerate(self.players) if p.position == "gkp"
        ])  #Goalkeeper index
        model.I_def = Set(initialize=[
            i for i, p in enumerate(self.players) if p.position == "def"
        ])  #Defender index
        model.I_mid = Set(initialize=[
            i for i, p in enumerate(self.players) if p.position == "mid"
        ])  #Midfielder index
        model.I_fwd = Set(initialize=[
            i for i, p in enumerate(self.players) if p.position == "fwd"
        ])  #Forward index
        model.J = RangeSet(0, 7)  #Formation index
        model.T = Set(initialize=list(set([p.team for p in self.players
                                           ])))  #Team index
        model.P = Set(initialize=list(set([p.position for p in self.players
                                           ])))  #Position index

        def init_formations(m, j):
            if j == 0:
                return (3, 5, 2)
            if j == 1:
                return (3, 4, 3)
            if j == 2:
                return (4, 5, 1)
            if j == 3:
                return (4, 4, 2)
            if j == 4:
                return (4, 3, 3)
            if j == 5:
                return (5, 4, 1)
            if j == 6:
                return (5, 3, 2)
            if j == 7:
                return (5, 2, 3)

        model.Formations = Param(model.J,
                                 initialize=init_formations,
                                 within=Any)

        def init_req_per_pos(m, p):
            if p == "gkp":
                return 2
            if p == "fwd":
                return 3
            return 5

        model.ReqPos = Param(model.P, initialize=init_req_per_pos)

        def init_cost(m, i):
            return self.players[i].cost

        model.Cost = Param(model.I, initialize=init_cost)

        def init_score(m, i, w):
            return self.players[i].score[w]

        model.Score = Param(model.I, model.W, initialize=init_score)

        def init_weight(m, w):
            return 0.5**w

        model.Weight = Param(model.W, initialize=init_weight)

        def init_existing_team(m, i):
            p = self.players[i]
            if p in existing_team:
                return 1
            return 0

        model.ExistingTeam = Param(model.I, initialize=init_existing_team)

        model.in_squad = Var(model.I, model.W,
                             within=Binary)  #Players in squad (15)
        model.on_pitch = Var(
            model.I, model.J, model.W,
            within=Binary)  #Players on the pitch in formation j
        model.cap = Var(model.I, model.W, within=Binary)  #Captain
        model.form_points = Var(model.J, model.W,
                                within=Reals)  #Points in formation j
        model.best_form = Var(
            model.J, model.W,
            within=Binary)  #The best formation to use (max points)
        model.n_changes = Var(model.W, bounds=(
            0, n_max_transf))  #The number of changes from the previous team
        model.n_free = Var(model.W,
                           bounds=(0,
                                   15))  #The number of free changes this round
        model.n_costly = Var(
            model.W, bounds=(0, 15))  #The number of costly changes this round
        model.u = Var(
            model.W, within=Binary
        )  #1 if more than 1 change is made this round, 0 otherwise
        model.subbed_in = Var(model.I, model.W,
                              bounds=(0, 1))  #Player subbed into team
        model.subbed_out = Var(model.I, model.W,
                               bounds=(0, 1))  #Player subbed out of team

        def cost_constraint(m, w):
            return sum(m.Cost[i] * m.in_squad[i, w] for i in m.I) <= budget

        model.MaxCost = Constraint(model.W, rule=cost_constraint)

        def max_per_team_constraint(m, t, w):
            return sum(m.in_squad[i, w]
                       for i in m.I if self.players[i].team == t) <= 3

        model.MaxPerTeam = Constraint(model.T,
                                      model.W,
                                      rule=max_per_team_constraint)

        def req_per_pos(m, p, w):
            return sum(m.in_squad[i, w] for i in m.I
                       if self.players[i].position == p) == m.ReqPos[p]

        model.ReqPosConstr = Constraint(model.P, model.W, rule=req_per_pos)

        def on_pitch_bounds(m, i, j, w):
            return m.on_pitch[i, j, w] <= m.in_squad[i, w]

        model.OnPitchBounds = Constraint(model.I,
                                         model.J,
                                         model.W,
                                         rule=on_pitch_bounds)

        def pick_gkp(m, j, w):
            return sum(m.on_pitch[i, j, w] for i in m.I_gkp) == 1

        model.Pickgkp = Constraint(model.J, model.W, rule=pick_gkp)

        def pick_def(m, j, w):
            n_def, n_mid, n_fwd = m.Formations[j]
            return sum(m.on_pitch[i, j, w] for i in m.I_def) == n_def

        model.Pickdef = Constraint(model.J, model.W, rule=pick_def)

        def pick_mid(m, j, w):
            n_def, n_mid, n_fwd = m.Formations[j]
            return sum(m.on_pitch[i, j, w] for i in m.I_mid) == n_mid

        model.Pickmid = Constraint(model.J, model.W, rule=pick_mid)

        def pick_fwd(m, j, w):
            n_def, n_mid, n_fwd = m.Formations[j]
            return sum(m.on_pitch[i, j, w] for i in m.I_fwd) == n_fwd

        model.Pickfwd = Constraint(model.J, model.W, rule=pick_fwd)

        def cap_bounds(m, i, j, w):
            return m.cap[i, w] <= m.on_pitch[i, j, w]

        model.CapBounds = Constraint(model.I,
                                     model.J,
                                     model.W,
                                     rule=cap_bounds)

        def pick_cap(m, w):
            return sum(m.cap[i, w] for i in m.I) == 1

        model.PickCap = Constraint(model.W, rule=pick_cap)

        def pick_formation(m, w):
            return sum(m.best_form[j, w] for j in m.J) == 1

        model.PickFormation = Constraint(model.W, rule=pick_formation)

        def form_point_bound(m, j, w):
            return m.form_points[j, w] <= sum(
                m.Score[i, w] * m.on_pitch[i, j, w] for i in model.I)

        model.FormationPointBound = Constraint(model.J,
                                               model.W,
                                               rule=form_point_bound)

        def form_pick_bound(m, j, w):
            big_m = 15 * max([p.score[w] for p in self.players])
            return m.form_points[j, w] <= big_m * m.best_form[j, w]

        model.FormationPickBounds = Constraint(model.J,
                                               model.W,
                                               rule=form_pick_bound)

        def sub_rule(m, i, w):
            if w == 0:
                prev_selection = m.ExistingTeam[i]
            else:
                prev_selection = m.in_squad[i, w - 1]

            return m.subbed_in[i, w] - m.subbed_out[i, w] == m.in_squad[
                i, w] - prev_selection

        model.SubRule = Constraint(model.I, model.W, rule=sub_rule)

        def total_changes_rule(m, w):
            return m.n_changes[w] == sum(m.subbed_in[i, w] for i in m.I)

        model.TotalChanges = Constraint(model.W, rule=total_changes_rule)

        def costly_changes_rule(m, w):
            return m.n_costly[w] >= m.n_changes[w] - m.n_free[w]

        model.CostlyChanges = Constraint(model.W, rule=costly_changes_rule)

        def free_changes_rule(m, w):
            if w == 0:
                return m.n_free[w] == n_free_transf

            return m.n_free[w] == 2 - m.u[w]

        model.FreeChanges = Constraint(model.W, rule=free_changes_rule)

        def remove_free_change_rule(m, w):
            if w == 0:
                return m.u[w] == 0

            return 15 * m.u[w] >= m.n_changes[w - 1]  #- 1

        model.RemoveFreeChange = Constraint(model.W,
                                            rule=remove_free_change_rule)

        def objective_rule(m):
            cap_score = sum(m.Weight[w] * m.Score[i, w] * m.cap[i, w]
                            for i in m.I for w in m.W)
            form_score = sum(m.Weight[w] * m.form_points[j, w] for j in m.J
                             for w in m.W)
            bench_score = sum(m.Weight[w] * m.Score[i, w] *
                              (m.in_squad[i, w] - m.on_pitch[i, j, w])
                              for i in m.I for j in m.J
                              for w in m.W) / len(m.J)
            change_ramping = sum(m.n_changes[w] for w in m.W) / len(m.W)
            #smoothing_score = 0.05*sum(m.Score[i]*m.in_squad[i] for i in m.I)/15

            return cap_score + 0.99 * form_score + 0.01 * bench_score - 4 * sum(
                m.n_costly[w] for w in m.W) - 0.1 * change_ramping

        model.OBJ = Objective(rule=objective_rule, sense=maximize)

        self.model = model
Beispiel #2
0
    def build_best_formation_model(self,
                                   players,
                                   budget=100.0,
                                   bench_boost=False):

        self.players = players

        model = ConcreteModel()

        model.I = RangeSet(0, len(self.players) - 1)
        model.I_gkp = Set(initialize=[
            i for i, p in enumerate(self.players) if p.position == "gkp"
        ])
        model.I_def = Set(initialize=[
            i for i, p in enumerate(self.players) if p.position == "def"
        ])
        model.I_mid = Set(initialize=[
            i for i, p in enumerate(self.players) if p.position == "mid"
        ])
        model.I_fwd = Set(initialize=[
            i for i, p in enumerate(self.players) if p.position == "fwd"
        ])
        model.J = RangeSet(0, 7)

        model.T = Set(initialize=list(set([p.team for p in self.players])))
        model.P = Set(initialize=list(set([p.position for p in self.players])))

        def init_formations(m, j):
            if j == 0:
                return (3, 5, 2)
            if j == 1:
                return (3, 4, 3)
            if j == 2:
                return (4, 5, 1)
            if j == 3:
                return (4, 4, 2)
            if j == 4:
                return (4, 3, 3)
            if j == 5:
                return (5, 4, 1)
            if j == 6:
                return (5, 3, 2)
            if j == 7:
                return (5, 2, 3)

        model.Formations = Param(model.J,
                                 initialize=init_formations,
                                 within=Any)

        def init_req_per_pos(m, p):
            if p == "gkp":
                return 2
            if p == "fwd":
                return 3
            return 5

        model.ReqPos = Param(model.P, initialize=init_req_per_pos)

        def init_cost(m, i):
            return self.players[i].cost

        model.Cost = Param(model.I, initialize=init_cost)

        def init_score(m, i):
            return self.players[i].score

        model.Score = Param(model.I, initialize=init_score)

        model.in_squad = Var(model.I, within=Binary)  #Players in squad (15)
        model.on_pitch = Var(
            model.I, model.J,
            within=Binary)  #Players on the pitch in formation j
        model.cap = Var(model.I, within=Binary)  #Captain
        model.form_points = Var(model.J, within=Reals)  #Points in formation j
        model.best_form = Var(
            model.J, within=Binary)  #The best formation to use (max points)
        model.n_keep = Var(within=Integers, bounds=(
            0,
            15))  #The number of players kept from the existing team (if given)
        model.n_changes = Var(within=Integers, bounds=(
            0, 15))  #The number of changes from the existing team (if given)

        def cost_constraint(m):
            return sum(m.Cost[i] * m.in_squad[i] for i in m.I) <= budget

        model.MaxCost = Constraint(rule=cost_constraint)

        def max_per_team_constraint(m, t):
            return sum(m.in_squad[i]
                       for i in m.I if self.players[i].team == t) <= 3

        model.MaxPerTeam = Constraint(model.T, rule=max_per_team_constraint)

        def req_per_pos(m, p):
            return sum(m.in_squad[i] for i in m.I
                       if self.players[i].position == p) == m.ReqPos[p]

        model.ReqPosConstr = Constraint(model.P, rule=req_per_pos)

        def y_bounds(m, i, j):
            return m.on_pitch[i, j] <= m.in_squad[i]

        model.gkpBounds = Constraint(model.I, model.J, rule=y_bounds)

        def pick_gkp(m, j):
            return sum(m.on_pitch[i, j] for i in m.I_gkp) == 1

        model.Pickgkp = Constraint(model.J, rule=pick_gkp)

        def pick_def(m, j):
            n_def, n_mid, n_fwd = m.Formations[j]
            return sum(m.on_pitch[i, j] for i in m.I_def) == n_def

        model.Pickdef = Constraint(model.J, rule=pick_def)

        def pick_mid(m, j):
            n_def, n_mid, n_fwd = m.Formations[j]
            return sum(m.on_pitch[i, j] for i in m.I_mid) == n_mid

        model.Pickmid = Constraint(model.J, rule=pick_mid)

        def pick_fwd(m, j):
            n_def, n_mid, n_fwd = m.Formations[j]
            return sum(m.on_pitch[i, j] for i in m.I_fwd) == n_fwd

        model.Pickfwd = Constraint(model.J, rule=pick_fwd)

        def cap_bounds(m, i, j):
            return m.cap[i] <= m.on_pitch[i, j]

        model.CapBounds = Constraint(model.I, model.J, rule=cap_bounds)

        def pick_cap(m):
            return sum(m.cap[i] for i in m.I) == 1

        model.PickCap = Constraint(rule=pick_cap)

        def pick_formation(m):
            return sum(m.best_form[j] for j in m.J) == 1

        model.PickFormation = Constraint(rule=pick_formation)

        def form_point_bound(m, j):
            return m.form_points[j] <= sum(m.Score[i] * m.on_pitch[i, j]
                                           for i in model.I)

        model.FormationPointBound = Constraint(model.J, rule=form_point_bound)

        def form_pick_bound(m, j):
            big_m = 15 * max([p.score for p in self.players])
            return m.form_points[j] <= big_m * m.best_form[j]

        model.FormationPickBounds = Constraint(model.J, rule=form_pick_bound)

        def objective_rule(m):
            cap_score = sum(m.Score[i] * m.cap[i] for i in model.I)
            form_score = sum(m.form_points[j] for j in model.J)
            bench_score = sum(m.Score[i] * (m.in_squad[i] - m.on_pitch[i, j])
                              for i in model.I for j in model.J) / len(model.J)
            #smoothing_score = 0.05*sum(m.Score[i]*m.in_squad[i] for i in model.I)/15

            if bench_boost:
                return cap_score + form_score + bench_score - 4 * m.n_changes
            else:
                return cap_score + 0.99 * form_score + 0.01 * bench_score - 4 * m.n_changes

        model.OBJ = Objective(rule=objective_rule, sense=maximize)

        self.model = model