def optimize( self, n: int, max_exposure: Optional[float] = None, randomness: bool = False, with_injured: bool = False, exposure_strategy: Type[BaseExposureStrategy] = TotalExposureStrategy, ) -> Generator[Lineup, None, None]: players = [player for player in self.players if player.max_exposure is None or player.max_exposure > 0] context = OptimizationContext( total_lineups=n, players=players, max_exposure=max_exposure, randomness=randomness, with_injured=with_injured, exposure_strategy=exposure_strategy, ) rules = self._rules.copy() rules.update(self.settings.extra_rules) if randomness: show_deprecation_warning('Randomness parameter is deprecated and will be removed in 3.6, ' 'use set_fantasy_points_strategy instead') self.set_fantasy_points_strategy(RandomFantasyPointsStrategy(self._min_deviation, self._max_deviation)) rules.add(Objective) if with_injured: rules.remove(RemoveInjuredRule) base_solver = self._solver_class() base_solver.setup_solver() players_dict = OrderedDict( [(player, base_solver.add_variable('Player_%d' % i)) for i, player in enumerate(players)]) variables_dict = {v: k for k, v in players_dict.items()} constraints = [constraint(self, players_dict, context) for constraint in rules] for constraint in constraints: constraint.apply(base_solver) previous_lineup = None for _ in range(n): solver = base_solver.copy() # type: Solver for constraint in constraints: constraint.apply_for_iteration(solver, previous_lineup) try: solved_variables = solver.solve() lineup_players = [] variables_names = [] for solved_variable in solved_variables: player = variables_dict.get(solved_variable) if player: lineup_players.append(player) variables_names.append(solved_variable.name) lineup = self._build_lineup(lineup_players, context) previous_lineup = lineup context.add_lineup(lineup) yield lineup if self.total_players and len(self.locked_players) == self.total_players: return for constraint in constraints: constraint.post_optimize(variables_names) except SolverInfeasibleSolutionException as solver_exception: raise GenerateLineupException(solver_exception.get_user_defined_constraints()) self.last_context = context
def test_randomness_with_player_deviation(self): for player in self.player_pool.all_players: player.min_deviation = 0 player.max_deviation = 0 optimized_lineup = next(self.lineup_optimizer.optimize(1)) self.lineup_optimizer.set_fantasy_points_strategy(RandomFantasyPointsStrategy()) random_lineup = next(self.lineup_optimizer.optimize(1)) self.assertEqual(optimized_lineup.players, random_lineup.players)
def test_randomness(self): optimized_lineup = next(self.lineup_optimizer.optimize(1)) self.lineup_optimizer.set_fantasy_points_strategy(RandomFantasyPointsStrategy()) random_lineup = next(self.lineup_optimizer.optimize(1)) self.assertTrue(optimized_lineup.fantasy_points_projection >= random_lineup.fantasy_points_projection) self.assertTrue( random_lineup.fantasy_points_projection > (1 - self.lineup_optimizer._max_deviation) * optimized_lineup.fantasy_points_projection )
def test_player_fppg_range(self): test_player = Player( player_id='1', first_name='test', last_name='test', positions=['PG'], team='Test', salary=2000, fppg=0, fppg_ceil=10000, fppg_floor=10000, ) self.player_pool.extend_players([test_player]) self.lineup_optimizer.set_fantasy_points_strategy(RandomFantasyPointsStrategy()) random_lineup = next(self.lineup_optimizer.optimize(1)) self.assertIn(test_player, random_lineup.players)
def test_random_strategy(self): player1 = Player('1', '1', '1', ['P'], 'test', 5000, 20, min_deviation=0.1, max_deviation=0.2) player2 = Player('2', '2', '2', ['P'], 'test', 8000, 40) strategy = RandomFantasyPointsStrategy(0.05, 0.1) player1_fppg = strategy.get_player_fantasy_points(player1) if player1_fppg < 16 or 18 < player1_fppg < 22 or player1_fppg > 24: self.fail('Incorrect generated points') player2_fppg = strategy.get_player_fantasy_points(player2) if player2_fppg < 36 or 38 < player2_fppg < 42 or player2_fppg > 44: self.fail('Incorrect generated points') strategy.set_previous_lineup(Lineup([LineupPlayer(player1, 'P')])) player1_fppg = strategy.get_player_fantasy_points(player1) if player1_fppg < 16 or 18 < player1_fppg < 22 or player1_fppg > 24: self.fail('Incorrect generated points') player2_fppg = strategy.get_player_fantasy_points(player2) if player2_fppg < 36 or 38 < player2_fppg < 42 or player2_fppg > 44: self.fail('Incorrect generated points')
def optimize_lineups( self, lineups: List[Lineup], max_exposure: Optional[float] = None, randomness: bool = False, with_injured: bool = None, exposure_strategy: Type[BaseExposureStrategy] = TotalExposureStrategy ): if with_injured is not None: show_deprecation_warning('with_injured parameter is deprecated, use player_pool.with_injured instead') self.player_pool.with_injured = with_injured players = self.player_pool.filtered_players context = OptimizationContext( total_lineups=len(lineups), players=players, existed_lineups=lineups, max_exposure=max_exposure, randomness=randomness, exposure_strategy=exposure_strategy ) rules = self._rules.copy() rules.update(self.settings.extra_rules) if randomness: show_deprecation_warning('Randomness parameter is deprecated and will be removed in 3.6, ' 'use set_fantasy_points_strategy instead') self.set_fantasy_points_strategy(RandomFantasyPointsStrategy(self._min_deviation, self._max_deviation)) rules.add(Objective) rules.add(LateSwapRule) rules.remove(PositionsRule) base_solver = self._solver_class() base_solver.setup_solver() players_dict = OrderedDict( [(player, base_solver.add_variable(base_solver.build_player_var_name(player, str(i)))) for i, player in enumerate(players)]) variables_dict = {v: k for k, v in players_dict.items()} constraints = [constraint(self, players_dict, context) for constraint in rules] for constraint in constraints: constraint.apply(base_solver) previous_lineup = None for lineup in lineups: if len(lineup.get_unswappable_players()) == self.total_players: yield lineup continue solver = base_solver.copy() # type: Solver for constraint in constraints: constraint.apply_for_iteration(solver, previous_lineup) try: solved_variables = solver.solve() unswappable_players = lineup.get_unswappable_players() lineup_players = [] variables_names = [] for solved_variable in solved_variables: player = variables_dict.get(solved_variable) if player: lineup_players.append(player) variables_names.append(solved_variable.name) generated_lineup = self._build_lineup(lineup_players, context, unswappable_players) previous_lineup = generated_lineup context.add_lineup(generated_lineup) yield generated_lineup for constraint in constraints: constraint.post_optimize(variables_names) except SolverInfeasibleSolutionException as solver_exception: raise GenerateLineupException(solver_exception.get_user_defined_constraints()) self.last_context = context
def optimize( self, n: int, max_exposure: Optional[float] = None, randomness: bool = False, with_injured: Optional[bool] = None, exposure_strategy: Type[BaseExposureStrategy] = TotalExposureStrategy, exclude_lineups: Optional[Iterable[Lineup]] = None, ) -> Generator[Lineup, None, None]: start = time.time() if with_injured is not None: show_deprecation_warning('with_injured parameter is deprecated, use player_pool.with_injured instead') self.player_pool.with_injured = with_injured players = self.player_pool.filtered_players context = OptimizationContext( total_lineups=n, players=players, max_exposure=max_exposure, randomness=randomness, exposure_strategy=exposure_strategy, exclude_lineups=exclude_lineups or [], ) rules = self._rules.copy() rules.update(self.settings.extra_rules) if randomness: show_deprecation_warning('Randomness parameter is deprecated and will be removed in 3.6, ' 'use set_fantasy_points_strategy instead') self.set_fantasy_points_strategy(RandomFantasyPointsStrategy(self._min_deviation, self._max_deviation)) rules.add(Objective) base_solver = self._solver_class() base_solver.setup_solver() players_dict = OrderedDict( [(player, base_solver.add_variable(base_solver.build_player_var_name(player, str(i)))) for i, player in enumerate(players)]) variables_dict = {v: k for k, v in players_dict.items()} constraints = [constraint(self, players_dict, context) for constraint in rules] for constraint in constraints: constraint.apply(base_solver) previous_lineup = None print(f'setup took {time.time() - start}s') for i in range(n): iter_start = time.time() solver = base_solver.copy() # type: Solver for constraint in constraints: constraint.apply_for_iteration(solver, previous_lineup) try: sub_iter_start = time.time() solved_variables = solver.solve() print(f'\tsolving took {time.time() - sub_iter_start}s') sub_iter_start = time.time() lineup_players = [] variables_names = [] for solved_variable in solved_variables: player = variables_dict.get(solved_variable) if player: lineup_players.append(player) variables_names.append(solved_variable.name) lineup = self._build_lineup(lineup_players, context) previous_lineup = lineup context.add_lineup(lineup) yield lineup total_players = self.player_pool.total_players if total_players and len(self.player_pool.locked_players) == total_players: return for constraint in constraints: constraint.post_optimize(variables_names) print(f'iteration {i+1} took {time.time() - iter_start}s') except SolverInfeasibleSolutionException as solver_exception: raise GenerateLineupException(solver_exception.get_user_defined_constraints()) self.last_context = context