Yo,
Im running into a small issue. I have a selection of "Players" I am trying to run some probability predictions on. There is 112 players. Of these players the following is true:
- 64 can bat.
- 66 can bowl.
- 10 can be wicket keepers
- Any player can be able to do up too any two of bowl/bat/wicket keep but at least one.
A Team is made up of:
- 7 players that can bat.
- 7 players that can bowl.
- 2 players that can wicket keepers.
- There cannot be duplicate players in a team.
- A player may only fulfill one role even if they are capable of two.( a batter / bowler must bat or bowl not both)
Now to the problem
I Have the following code.
var allBattingCombos = new Combinations<int>(players.Where(player => player.inRoundCanBat).Select(player => player.fantasyID).ToList(), 7);
var allBowlingCombos = new Combinations<int>(players.Where(player => player.inRoundCanBowl).Select(player => player.fantasyID).ToList(), 7);
var allWKTCombos = new Combinations<int>(players.Where(player => player.inRoundCanWkt).Select(player => player.fantasyID).ToList(), 2);
var allCombos = new List<Combinations<int>>() { allBowlingCombos , allBowlingCombos, allWKTCombos };
var allTeamCombos = allCombos.CartesianProduct().ToList();
Where CartesianProduct(from Finding all combinations from sets of possibilities) =
public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
{
// Default object
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] { item }));
}
I get the following values:
allBattingCombos count = 621216192
allBowlingCombos count = 778789440
allWKTCombos count = 45
All team combos locks my pc and eventually it dies as I run out of memory. While I was waiting for my calculation to run I did some maths. According to Memory size of a list of int 4 bytes min per int in the list so thats:
4 bytes *
15 member ids in a team *
621216192 batting combos *
778789440 bowling combos *
45 wkt combos
= 1.34E+21 bytes
or 13400000000000 gigaBytes
Yikes, ain't nobody got ram like dat.
What makes it more scary is I need to run it 9 times, 1 for each round.
Once I have my team possibilities I need to run something like this on each team.
Team highestScoringTeam = null;
foreach (var team in allTeamCombos)
{
var teamobj = new Team();
teamobj.BattersList = team[0].ToList();
teamobj.BowlersList = team[1].ToList();
teamobj.WktKeepersList = team[2].ToList();
if (highestScoringTeam == null)
{
highestScoringTeam = teamobj;
}
else if (teamobj.TeamIsValid && teamobj.TotalScoreForRound > highestScoringTeam.TotalScoreForRound)
{
highestScoringTeam = teamobj;
}
}
Does anyone know how I can get around my ram issue / see a better way of achieving my goals?
----Update 1----
After some thinking I don't need the whole list object at any point I can just use it during the Cartesian calculation. In place of allTeamCombos I use the following.
foreach (var battingCombo in allBattingCombos)
{
foreach (var bowlingCombo in allBowlingCombos)
{
foreach (var WktCombo in allWKTCombos)
{
var team = new Team();
team.BattersList = battingCombo.Select(id => players.First(p => p.fantasyID == id)).ToList();
team.BowlersList = bowlingCombo.Select(id => players.First(p => p.fantasyID == id)).ToList();
team.WktKeepersList = WktCombo.Select(id => players.First(p => p.fantasyID == id)).ToList();
if (highestScoringTeam == null)
{
highestScoringTeam = team;
}
else if (team.TeamIsValid && team.TotalScoreForRound > highestScoringTeam.TotalScoreForRound)
{
highestScoringTeam = team;
Console.WriteLine("new highScore = " + team.TotalScoreForRound);
}
combinationsParsed++;
if(combinationsParsed % 10000 == 0)
Console.WriteLine("combinationsParsed = " + combinationsParsed);
}
}
I'm thinking that this solves the question of the ram issue, I'm also thinking I should maybe close the question.