def run_solver(all_players, depth):
    solver = pywraplp.Solver('FD',
                             pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)
    '''
	Setup Binary Player variables
	'''
    variables = []
    for player in all_players:
        variables.append(solver.IntVar(0, 1, player.code))
    '''
	Setup Maximization over player point projections
	'''
    objective = solver.Objective()
    objective.SetMaximization()
    for i, player in enumerate(all_players):
        objective.SetCoefficient(variables[i], player.proj)
    '''
	Add Salary Cap Constraint
	'''
    salary_cap = solver.Constraint(SALARY_CAP - 1000, SALARY_CAP)
    for i, player in enumerate(all_players):
        salary_cap.SetCoefficient(variables[i], player.cost)
    '''
	Add Player Position constraints including flex position
	'''
    flex_rb = solver.IntVar(0, 1, 'Flex_RB')
    flex_wr = solver.IntVar(0, 1, 'Flex_WR')
    flex_te = solver.IntVar(0, 1, 'Flex_TE')

    solver.Add(flex_rb + flex_wr + flex_te == 1)

    for position, limit in POSITION_LIMITS_FLEX:
        ids, players_by_pos = zip(*filter(lambda (x, _): x.pos in position,
                                          zip(all_players, variables)))
        if position == 'WR':
            solver.Add(solver.Sum(players_by_pos) == limit + flex_wr)
        elif position == 'RB':
            solver.Add(solver.Sum(players_by_pos) == limit + flex_rb)
        elif position == 'TE':
            solver.Add(solver.Sum(players_by_pos) == limit + flex_te)
        else:
            solver.Add(solver.Sum(players_by_pos) == limit)
    '''
	Add min number of different teams players must be drafted from constraint (draftkings == 2)
	'''
    team_names = set([o.team for o in all_players])
    teams = []
    for team in team_names:
        teams.append(solver.IntVar(0, 1, team))
    solver.Add(solver.Sum(teams) >= 2)

    for idx, team in enumerate(team_names):
        ids, players_by_team = zip(*filter(lambda (x, _): x.team in team,
                                           zip(all_players, variables)))
        solver.Add(teams[idx] <= solver.Sum(players_by_team))
    '''
	Add Defence cant play against any offense's player team constraint
	'''
    o_players = filter(lambda x: x.pos in ['QB', 'WR', 'RB', 'TE'],
                       all_players)
    opps_team_names = set([o.opps_team for o in o_players])
    teams_obj = filter(lambda x: x.pos == 'DST', all_players)
    teams = set([o.team for o in teams_obj])
    for opps_team in team_names:
        if opps_team in teams:
            ids, players_by_opps_team = zip(*filter(
                lambda (x, _): x.pos in ['QB', 'WR', 'RB', 'TE'] and x.
                opps_team in opps_team, zip(all_players, variables)))
            idxs, defense = zip(
                *filter(lambda (x, _): x.pos == 'DST' and x.team in opps_team,
                        zip(all_players, variables)))
            for player in players_by_opps_team:
                solver.Add(player <= 1 - defense[0])
    '''
	Add QB stacking (at least 1 wr on same team as QB) constraint
	'''
    offense_team_names = set([o.team for o in o_players])
    for o_team in offense_team_names:
        ids, players_by_team = zip(
            *filter(lambda (x, _): x.pos in ['WR'] and x.team == o_team,
                    zip(all_players, variables)))
        idxs, qb = zip(
            *filter(lambda (x, _): x.pos == 'QB' and x.team == o_team,
                    zip(all_players, variables)))
        solver.Add(solver.Sum(players_by_team) >= solver.Sum(qb))
    '''
	Add Max of 1 qb wr te or rb per team constraint, NOT TO BE USED WITH QB STACKING
	'''
    # 	for team in list(team_names):
    # 		ids, players_by_team = zip(*filter(lambda (x,_): x.team in team and x.pos in ['WR','TE','RB','QB'], zip(all_players, variables)))
    # 		solver.Add(solver.Sum(players_by_team)<=1)
    '''
	Add Max of 2 qb wr te or rb per game constraint, spread risk
	'''
    #for team in list(team_names):
    #	team_players = filter(lambda x: x.team in team, all_players)
    #	ids, players_by_game = zip(*filter(lambda (x,_): x.team in team or x.team in team_players[0].opps_team and x.pos in ['WR','TE','RB','QB'], zip(all_players, variables)))
    #	solver.Add(solver.Sum(players_by_game)<=2)
    '''
	Add remove previous solutions constraint and loop to generate X rosters
	'''
    rosters = []
    for x in xrange(depth):
        if rosters:
            ids, players_from_roster = zip(
                *filter(lambda (x, _): x in rosters[-1].sorted_players(),
                        zip(all_players, variables)))
            ids, players_not_from_roster = zip(
                *filter(lambda (x, _): x not in rosters[-1].sorted_players(),
                        zip(all_players, variables)))
            solver.Add(
                solver.Sum(players_not_from_roster) +
                solver.Sum(1 - x for x in players_from_roster) >= 9)
        solution = solver.Solve()
        if solution == solver.OPTIMAL:
            roster = Roster()
            for i, player in enumerate(all_players):
                if variables[i].solution_value() == 1:
                    roster.add_player(player)
            rosters.append(roster)
            print "Optimal roster: %s" % x
            print roster
        else:
            raise Exception('No solution error')
    return rosters