views:

115

answers:

3

What I am hoping to achieve is the ability to generate 'teams' of users. I will have x amount of men, weighted (decimal skill weight, like 75.23) and y amount of women (also with a skill weight value).

Given that list of users, I would then take for input the number of teams to make (let us say, 6 teams). Then, I go through the list of x's and y's and organize them so that the best average possible weighted teams are created. I would like to keep the teams balanced (women and men ratio)

I don't want 'stacked' teams, (best skilled in one team). I would like an even distribution of weight.

Curious how I could achieve this in PHP? I'd be using a MySQL database to fetch users with weight values. I would know ahead of time how many users I would have, also how many teams I would want to generate.

I would appreciate any suggestions, or links to a solution if anyone has found something similar like this. I'm just not a math wiz, so I don't know what formula would apply here.

Thanks. I appreciate any input!

EDIT

After reviewing the answers, maybe I was not clear enough, so hopefully this helps a little more.

  1. I want the teams to be roughly equally-sized
  2. I want the average (mean) skill score for each team to be roughly equal
  3. I want the ratio of men to women in each team to be roughly equal (that is to say, if by division, we get a distribution, of 5 men and 3 women per team, I would like to keep that roughly the same). Not really an issue if I sort men first, and women second (or vise-versa).
  4. I don't want a linear approach (team 1 gets highest, team 2, sec highest, team 3.. so on). Tim's method of taking (if 6 teams) 6 people and randomizing and then distributing via linear fashion seems to work out fine.
A: 

If the number of people in each group (x,y) is relatively even, and the total number of people is relatively high random sampling should work quite well. See here on how to select random rows from a MySQL database: http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_rand

Slight edit, to ensure fairness personally I'd do something like this. Say you know you want n members per team. Then create a local variable which is n*mean where mean is the average skill level per person. Then when your randomly selecting your team members do so within that limit.

E.g.

while(new random record){

if(team_skill+random person skill > n*mean){
 next;
}

if(team_skill+random person skill < n*mean && selected team members =n){
team + random person;
break;
}
}
dangerstat
+2  A: 

This is similar to "maximum/minimum weight perfect matching", just that the matching is for more than two elements (note that this is a different weight from what you have (the skill weight), namely, you would assign a weight to a matching (a matching would be a proposed 'team')).

The known algorithms for the perfect matching above (e.g., Edmond's algorithm) might not be adaptable to the group case. I would perhaps look into some simulated annealing technique or a simple genetic algorithm.

Svante
On these sort of things, a genetic algorithm is probably the best choice, but it is often true that a genetic algorithm is more difficult to do well than a simulated annealing algorithm. So if the person is not skilled at these methods, I'd go for the simulated annealing option.
woodchips
+3  A: 

I'm not entirely clear what you're after here, so I'll recap on what I understand you to be asking. If this is not right, you can clarify your requirements by editing your question:

You have a list of a certain number of men and a certain number of women. Each person has a known skill score. You want to divide these into a certain number of teams, with the following aims:

  • you want the teams to be roughly equally-sized
  • you want the average (mean) skill score for each team to be roughly equal
  • you want the ratio of men to women in each team to be roughly equal

I would have thought that a simple method to achieve this would be:

  1. Create a list of all the men in decreasing order of skill score.
  2. Create a list of all the women in decreasing order of skill score.
  3. Add the list of women to the end of the list of men.
  4. Start at the beginning of the combined list, and allocated each person in turn to a team in a round-robin fashion. (That is to say, allocate the first person to team number one, the second to team number two, and so on until you have allocated one person to each of the teams you wish to create. Then start again with team one, allocating people to each team in order, and so on.)

With this approach, you will be guaranteed the following outcomes:

  • If possible (i.e. if the number of teams divides the total number of people), the teams will all have the same number of people.
  • If the teams are not all the same size, the largest team will have exactly one more person than the smallest team.
  • If possible the teams will all have the same number of men.
  • If the teams do not have the same number of men, the team with the most men exactly one more man than the team with the least men.
  • If possible the teams will all have the same number of women.
  • If the teams do not have the same number of women, the team with the most women exactly one more man than the team with the least women.
  • Each team will have men with a range of skill scores, from near the top of the range to near the bottom of the range.
  • Each team will have women with a range of skill scores, from near the top of the range to near the bottom of the range.
  • With sensible data, the mean skill score for each team will be roughly equal (although team one will have a slightly higher mean score than team two, and so on - there are ways of correcting this).

If this simple approach doesn't meet your requirements, please let us know what else you had in mind.

Tim
This round-robin approach would mean that team one always has a higher skill sum than the last team. This effect might cancel out if you go backwards on even rounds, but this would depend on the skill range being linearly distributed.
Svante
@Svante Indeed, as mentioned. Taking batches from the list of size equal to the number of teams wanted and then shuffling the batch before distributing to the teams would address this, and would introduce a degree of randomness. This is the sort of thing I had in mind earlier, but figured that the answer was long enough already.... :-)
Tim
Are you aware of any php example code to get me started? Just curious, I get a gist of your idea behind it, and that is somewhat how I foreseen it myself. I was just curious if there was a better way to handle this which would take into account previous members of a team, etc..
Jakub
I'm not aware of any existing PHP code for this, I'm afraid. If you're happy with the approach, accept the answer and have a go at writing the code yourself: start with an outline design, work out what needs to happen where, and then convert that design into PHP. If you've had a good go at it and get stuck, come back here, start a new question and show us how far you've got. There are plenty of people here who would be able to help. :-) Good luck!
Tim