Create balanced tennis rounds - python

We are a group of 20 people and we like to go play 2 vs 2 tennis matches. Each of us plays one match each round and we do 5 rounds in total, so everyone plays 5 matches. Matches have two restrictions:
Everyone has a different level (from 1 to 5), so the matches must be balanced: two players with levels 5 and 5 shoulnd't be matched with two levels 1. So between the two teams, the difference in level must be lower or equal to 1.5.
Ej.: level 1.5 and level 2 vs level 2 and level 2.5. The difference in level between teams is 1 so the match is accepted.
If two players play together in one match, they must not play toghether again in the following rounds.
I managed to create a python script that does the specified above, but it takes about 20 minutes to finish depending on the level of the people :/. What I do is shuffle the list with every one in it, break it into 5 lists of 4 people, check if conditions are satisfied and repeat for every round.
I tried modeling the problem to solve it with linear programming (LP) but I don't know which is my function to optimize to begin with... Any ideas on how to do this with or without LP?
Thanks in advance!

You could use a dummy objective or even try to minimize the max of the difference in levels.
My MIP model is not completely trivial, but it solves quite fast (about a second or so using a commercial solver).
The results look ok at first sight:
I assumed two players cannot be in the same team more than once. I.e. not just in the same game. That is in my case you can play against another player more than once.
A more complex example can be found here.

Related

Persons Matching program or algorithm

In a networking event there is a pool of persons. Each person should meet all other persons in a 5 person setting for 10 minutes.
For example if the pool is having 60 persons. Each person should meet other 4 persons in the same table for 10 minutes. after some time this person should have met all other 59 persons.
Is there any ready-made algorithm/program in Python or Excel that one can input the pool and have the output as a list of 5 persons-lists that is satisfy the condition: each person has met the whole pool with minimal repetitions?
Thanks
There is no general algorithm for this.
As https://www.dmgordon.org/cover/ explains, this is called a covering design. Optimal covering designs for the problem you are interested in, 5 element sets covering all 2 element sets, are known for many number of vertices, v. See https://ljcr.dmgordon.org/cover.php?vopt=%3C%3D&v=100&kopt=%3D&k=5&topt=%3D&t=2&sizeopt=%3D&size=&creator=&method=&time=A&submit=search for a list, and when they were discovered. The variety of different sources for that list, including papers within the last 20 years, should demonstrate that this is a hard problem in general.

Filtering sequences of events in django

My django app stores the actions that players do during a game. One of the models is called Event, and it contains a list of all actions by players. It has the following 4 columns: game_id, player_name, action, turn. Turn is the number of the turn in which the action takes place.
Now I want to count how often players behave in certain patterns. For example, I want to know how often a player takes decision A in turn 2 and that same player takes decision B in turn 3. I'm breaking my head over how I can do this. Can someone help?
Note: Ideally the queries should be efficient, bearing in mind that some related queries are following. For example, after the above query I would want to know how often a player takes decision C in turn 4, after doing A and B in turns 2 and 3. (The goal is to predict the likelihood of each action, given the actions in the past.)

Add Solver Constraint For Non-Mutually Exclusive Ranges

I use or-tools to optimize my fantasy baseball team. My setup very much resembles the program described here. The only difference in my particular case is that players can actually be eligible for a number of different positions. So, I end up with 1 player in a list for a specific position type, and the same player in another list for another position type. I am trying to avoid having the solver select the same player for multiple positions (which wouldn't be realistic).
Is there any way to modify the aforementioned program to constrain the use of a player to a single position even while they are technically eligible for many? Please let me know if I can clarify any further & thanks for your input.

Assign most people their first choice based on a list of preferred choices

Given a list of choices (say 100), each person in a list (say 30) has to choose 5 choices in the order they would like them to be assigned. How would I assign each person a choice making sure as many people as possible got their first choice (or highest preferred choice)?
Each choice has a variable limit on how many times it can be chosen e.g. choice 1 might be available to 3 people, choice 2 available to 1, choice 3 to 5 etc.
I am using Python to write the code but I'm interested in which algorithm I should use. I found some suggesting Stable Marriage Problem but this requires that both sides have a preference and in my case only the people have a preference. Another I found was the Assignment Problem but this required there to be an equal number of people to choices with each choice going to 1 person and again my problem has more choices than people with the added problem that 1 choice can potentially be available to more than 1 person
This seems similar to, but not quite the stable marriage problem. Maybe that algorithm would work or could be adapted: http://rosettacode.org/wiki/Stable_marriage_problem
(Loads of code in different languages).
You can model this as a network flow problem. Build a network with
a source node, a sink node, nodes for each person and nodes for each choice.
an edge between the source and each person (with capacity 1)
an edge between each person and the each choice she chooses with a capacity of 1
an edge between each choice and the sink with a capacity equal to the maximum number of times the choice can be selected.
Then assign weights to all the edges
weights of 0 for all the edges between the source and each person
weights of 0 for all the edges between the each choice and the sink
for each edge between a person p and any of her choices c, set the weights as follows: n^(5-rank(p,c)) where rank(p,c) is the position of c on p's ordered list.
Finally find a maximum cost maximum flow in the resulting network.
If your only restriction is that:
as many people as possible got their first choice (or highest preferred choice)
My suggestion would be a simple sorting operation.
You could sort by popularity # requests for a choice - # of available spots in their first choice, then the same for second choice and third, and so on. Go through each user and assign first choice if it is available, then flag them or remove them from the list. Repeat for second choice, third choice etc for all users who haven't been selected yet.
This approach would be advantageous because it accounts for uneven distributions of choice by giving preference to those who have chosen really popular or overpopulated choices. This bias would increase the likely-hood that as many people as possible get at least one of their choices. People who select the top 5 choices, for example will be practically ensured to get at least one choice where otherwise they might not have a chance. People who have a couple of unpopular choices (# requests for a choice - # of available spots) <= 0 will likely be pushed into one of those unpopular choices, but at least they will get one of their preferred choices. People who have all unpopular choices will get what they want.
You can use the Assignment Problem formulation if e.g. for a choice that is available 5 times you add 5 copies of it, and moreover add dummy persons such that the number of persons and choices is equal.

Calculating a game's high score table

I need to create a function/method ( in python) which calculates a high score "leaderboard". Each player will have played any number of rounds of the game, recieving a score for each round. I want to know what's the best way to sort the top ranking players (accounting for score AND number of rounds played). The possible scores for each round are F, D-, D, D+, C-, C, C+, B-, B, B+, A-, and A.
Obviously a simple average won't work because it doesn't take into account number of rounds played. Whats the best way to set up a fair sorting function?
EDIT: I've been reading some of the really great answers here and I want to try to clear up my question a bit. I want both the players score AND the number of rounds they've played to count towards their ranking in a way that's fair. Meaning a player with 20 B's should be of a higher rank than a player with 5 A's. Basically the high score should reflect general effort and skill, "the number of rounds played PLUS their score" means the higher their ranking should be.
EDIT 2: After reading the answers, I think the best way to do it is a simple total sum of the players points across all rounds. I'm not sure which answer to assign the green check to because you were all correct.
There are many ways that you could do this. Try this for example, let F-A be 0-11 (you can make your own; however try to take difficulty into account), so each score is one higher than the previous. For every game you play, you receive a score (from 0-11). Create a total score and add the game score every time to the total score. That way, if a person receives 7 A's, that's 77, while a person that receives 7 A-'s gets a score of 70, then simply sort them accordingly. Each function has its drawbacks of course. This function is not the "best", consider getting 20 B's would exceed 7 A's even though, 7 A's is a much better score. if you can give me more details about how you want to rank them, then it will be much easier to get the algorithm down.
What you are asking is essentially how we define "good" players and it's not an easy problem. As you mentioned, a simple average score or picking-the-highest-score will not be an ideal answer depending on your game design.
I'd like to recommend that you read about ELO rating system for Chess and other modified versions of it before you design your own player rating system.
One simple and possible way is you can set a window (like 10 most recent games) and use average score from the window. Players who play less games than this window would be "in placement" state. Again, it's not an easy problem and heavily depends on what your game is. Good Luck!
[UPDATE]
I assumed that your game is player vs. player. If not, this is another story. Most games just keep the highest score no matter how many times you play the game and that's going to be your entry in the leaderboard. Since you don't say anything about your game, I have no idea why it wouldn't be fair. As I mentioned earlier, you could set a window for avg. score or the highest score. You can even reset your leaderboard every month or remove players who haven't played for a week. It all depends on your game and what you want. Please remember that no matter what you do, make it sure that the rules are crystal clear for players otherwise they would be easily upset and frustrated.

Categories

Resources