How to solve this variation of kirkkmans schoolgirls - algorithm

I am trying to implement an app which assigns s students to l labs in g lab groups. The constraints are:
1:students shall work with new students for every lab.
2:all students shall be lab leader once.
2 is not solvable if the students can't be divided evenly in the lab groups. Therfore it is acceptable if the "odd" students never get to be lab leader.
I have tried two approaches but I am not happy yet.:
Tabu search, which solves 1 but has problems solving 2 ( I actually first solve 1 and then try to solve 2, which might be the wrong approach, any suggestions)
A simple solution where I divide the students in the #labs in an array [0..6][7..14][15..21] and then rotate(with 0,1,2 inc) and transpose the matrix, repeat this for #labs times with incremented rotation (1,2,4) and (2,4,6). For 21 students in 3 labs with lab groups of 7 the result looks like this:
lab 1: [0, 7, 14], [1, 8, 15], [2, 9, 16], [3, 10, 17], [4, 11, 18], [5, 12, 19], [6, 13, 20]
lab 2: [6,12, 18], [0, 13, 19], [1, 7, 20], [2, 8, 14], [3, 9, 15], [4, 10, 16], [5, 11, 17]
lab 3: [5, 10, 15], [6, 11, 16], [0, 12, 17], [1, 13, 18], [2, 7, 19], [3, 8, 20], [4, 9, 14]
the lab leaders are the first column for lab 1, the second for lab 2 ...
This solution works decent but for instance fails for 12 students in 3 labs or 150 students in 6 labs. Any suggestions?
2 seems to handle the same number of cases or combinations, and is lightning fast compared to 1. Maybe I should get a noble price :-)

Constraint #1 alone is usually referred to as the social golfer problem. (Let parameters g be the number of groups and s be the size of each group and w be the number of weeks. A grouping is a partition of g * s golfers into g groups of size s. Determine whether w groupings can be found such that each pair of golfers are grouped together at most once.) The social golfer problem has been studied in the combinatorial optimization literature, and the approaches are of three types (you can use your favorite search engine to find the research articles):
Local search. This is effective when w is well below its maximum feasible value. Dotú and Van Hentenryck have a paper applying tabu search to the social golfer problem.
Complete search. This is necessary when w is above or just below its maximum feasible value but it does not scale very well.
Algebraic constructions. This is how the notorious g=8 s=4 w=10 instance was solved. Unfortunately, for many parameter sets there is no construction known.
To assign lab leaders, compute a maximum matching between students and lab groups, where there is an edge between a student and a lab group if that student belongs to that lab group.

Related

How to solve combinations in card game for n people in r rounds (just one encounter)

There is a famous card game in Germany called "Doppelkopf".
Usually, you play "Doppelkopf" with 4 players, but you can also play it with a table of 5 players, where one player is just watching.
(Where everyone "has the cards" once in a round, meaning everyone has the right to play the first card once every round.)
Every year, my family organizes a "Doppelkopf" tournament with 3 rounds (r).
Depending on the availabilty of my relatives, every year the number of participants varies.
Expecting a minimun of participant of 16 people, the number (n) in this experiment can rise up unlimited (as does the number of rounds r).
Naturally, my relatives do not want to be paired with someone twice, since they want to exchange gossip most efficiently!
There we have:
n - Participants
r- Rounds
t_total = n // 4 # Total Tables (round down of n)
t_5 = n % 4 # Tables of 5s
t_4 = t_total - t_5 # Tables of 4s
pos_pair = n * (n - 1) / 2 # possible pairs (n over 2)
nec_pair = (t_5 * 10 + t_4 * 6) * r # necessary pairs
I was instructed with the aim to minimize the encounters (if possible to set encounters == 1 for everyone)!
Since, I do not want to solve the problem for P{n={16, ..., 32}, r=3} (which I did for some cases), but to solve it with any given P{n∈N, r∈N} , there is a discrepancy between my abilities and the requirements for a solution!
Therefore, I would like to ask the community to help me with this problem, to solve it for any given P{n∈N, r∈N}!
And also to prove, if this problem is not solvable for any P{n∈N, r∈N}, which is given "if pos_pair < nec_pair".
Here are two solutions for P{n=20, r=3}:
which very much solves my "Doppelkopf" tournament problem:
('Best result was ', [[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]], [[16, 12, 8, 18], [13, 1, 5, 9], [15, 4, 17, 6], [2, 19, 7, 10], [3, 11, 20, 14]], [[14, 9, 17, 7], [13, 20, 8, 2], [5, 4, 12, 19], [6, 16, 11, 1], [15, 18, 10, 3]]])
('Best result was ', [[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]], [[19, 11, 13, 3], [2, 15, 9, 8], [1, 16, 18, 6], [14, 7, 17, 10], [4, 12, 20, 5]], [[17, 8, 3, 12], [20, 9, 16, 7], [15, 11, 6, 4], [2, 13, 10, 18], [1, 19, 14, 5]]])
But in order to solve this problem with an arbitrary n and r I have come to no conclusion.
In my opinion, there are three ways to go about this problem in a computational solution or approximation.
First, you can iterate about rounds, and assign every player to a
table without having collision, remembering pairs and appeareances
in total (not to exeed total rounds)
Secondly, you can iterate about tables, which seems to be helpful with participants, that are a multiple of 2 (see for P{n=16, r=5}
https://matheplanet.com/default3.html?call=viewtopic.php?topic=85206&ref=https%3A%2F%2Fwww.google.com%2F)
also remeber pairs and appearances, but mainly follow a certain
patters as described in the link, which I somehow can not scale to
other numbers!!
There is somehow a mathemathical way to descibe this procedure and conclude a solution
Even though, this is more of a mathematical question (and I don't know where to ask those questions), I am interested in the algorithmic solution!

Simple, non-trivial bin-packing instance

Bin packing problem is to find the minimal number of bins of size v, which can contain all objects of size [s_1, s_2, s_3, ..., s_n]
I'm searching for a simple, non-trivial instance of the bin-packing problem.
A simple instance is an instance which can be solved with no more than 5 bins.
A non-trivial instance is an instance, which can't be solved by the best-fit-decreasing heuristic algorithm, but can be solved with complete search.
For example, the instance v = 20, objects = [15, 7, 14, 3, 14, 7, 9] is simple, but not non-trivial, because complete search proves that the minimal number of bins is 5:
[[15, 3], [7, 7], [14], [14], [9]]
however, best-fit heuristic also produces a 5-bin packing:
[[15], [14], [14], [9, 7, 3], [7]]
Does a simple, non-trivial instance of bin packing exist?
Indeed, such instance exists, namely:
v = 20, objects = [11, 7, 7, 6, 5, 3, 1]
Best-fit-decreasing heuristic gives:
[[11, 7], [7, 6, 5, 1], [3]]
Optimal packing is:
[[11, 6, 3], [7, 7, 5, 1]]

Concurrent database MVCC timestamp generation method

I need to generate database timestamps for MVCC Snapshot isolation. The typical method utilized:
"Transactional actions are implemented in SI-TM as follows.
TM BEGIN: A logical snapshot for the transaction is generated
by obtaining a unique timestamp using an atomic increment
to the global timestamp counter."
The problem with using this approach in a system with hundreds of cores is that it doesn't scale. There is a hardware limit of 10M atomic increments per second on a contested memory location.
Any ideas?
Here are two simple ideas, and a paper reference:
1) Instead of incrementing the counter by 1, increment it by N, giving clients effectively a range of transaction identifiers [c, c+N). For instance, if N=5, and the initial value of the counter is 1, then clients A, B, and C would get the following:
A: [1, 2, 3, 4, 5]
B: [6, 7, 8, 9, 10]
C: [11, 12, 13, 14, 15]
While this reduces the pressure on the atomic counter, as we can see from this example some clients (like client C) will get a relatively high range of ids while others get lower ranges (client A), and this will lead to higher abort rates in the system.
2) Use ranges of interleaved transaction identifiers. This is like 1, but we've added a step variable, S. Here's a simple example: If N=5 and S=3, and the initial value of the counter is 1, then clients A B and C would get the following:
A: [1, 4, 7, 10, 13]
B: [2, 5, 8, 11, 14]
C: [3, 6, 9, 12, 15]
This seems to have solved the problem of 1, but consider client D:
D: [16, 19, 22, 25, 28]
Now we're back to the same problem that solution #1 had. Tricks must be played with this technique to "get it right".
3) An interesting, but more complex, decentralized way of assigning transaction IDs is described here:
Tu, Stephen, Wenting Zheng, Eddie Kohler, Barbara Liskov, and Samuel Madden. "Speedy transactions in multicore in-memory databases." In Proceedings of the Twenty-Fourth ACM Symposium on Operating Systems Principles, pp. 18-32. ACM, 2013.

efficiently finding overlapping segments from a set of lists

Suppose I have the following lists:
[1, 2, 3, 20, 23, 24, 25, 32, 31, 30, 29]
[1, 2, 3, 20, 23, 28, 29]
[1, 2, 3, 20, 21, 22]
[1, 2, 3, 14, 15, 16]
[16, 17, 18]
[16, 17, 18, 19, 20]
Order matters here. These are the nodes resulting from a depth-first search in a weighted graph. What I want to do is break down the lists into unique paths (where a path has at least 2 elements). So, the above lists would return the following:
[1, 2, 3]
[20, 23]
[24, 25, 32, 31, 30, 29]
[28, 29]
[20, 21, 22]
[14, 15, 16]
[16, 17, 18]
[19, 20]
The general idea I have right now is this:
Look through all pairs of lists to create a set of lists of overlapping segments at the beginning of the lists. For example, in the above example, this would be the output:
[1, 2, 3, 20, 23]
[1, 2, 3, 20]
[1, 2, 3]
[16, 17, 18]
The next output would be this:
[1, 2, 3]
[16, 17, 18]
Once I have the lists from step 2, I look through each input list and chop off the front if it matches one of the lists from step 2. The new lists look like this:
[20, 23, 24, 25, 32, 31, 30, 29]
[20, 23, 28, 29]
[20, 21, 22]
[14, 15, 16]
[19, 20]
I then go back and apply step 1 to the truncated lists from step 3. When step 1 doesn't output any overlapping lists, I'm done.
Step 2 is the tricky part here. What's silly is it's actually equivalent to solving the original problem, although on smaller lists.
What's the most efficient way to solve this problem? Looking at all pairs obviously requires O(N^2) time, and step 2 seems wasteful since I need to run the same procedure to solve these smaller lists. I'm trying to figure out if there's a smarter way to do this, and I'm stuck.
Seems like the solution is to modify a Trie to serve the purpose. Trie compression gives clues, but the kind of compression that is needed here won't yield any performance benefits.
The first list you add becomes it's own node (rather than k nodes). If there is any overlap, nodes split but never get smaller than holding two elements of the array.
A simple example of the graph structure looks like this:
insert (1,2,3,4,5)
graph: (1,2,3,4,5)->None
insert (1,2,3)
graph: (1,2,3)->(4,5), (4,5)->None
insert (3,2,3)
graph: (1,2,3)->(4,5), (4,5)->None, (3,32)->None
segments
output: (1,2,3), (4,5), (3,32)
The child nodes should also be added as an actual Trie, at least when there are enough of them to avoid a linear search when adding/removing from the data structure and potentially increasing the runtime by a factor of N. If that is implemented, then the data structure has the same big O performance as a Trie with a somewhat higher hidden constants. Meaning that it takes O(L*N), where L is the average size of the list and N is the number of lists. Obtaining the segments is linear in the number of segments.
The final data structure, basically a directed graph, for your example would looks like below, with the start node at the bottom.
Note that this data structure can be built as you run the DFS rather than afterwords.
I ended up solving this by thinking about the problem slightly differently. Instead of thinking about sequences of nodes (where an edge is implicit between each successive pair of nodes), I'm thinking about sequences of edges. I basically use the algorithm I posted originally. Step 2 is simply an iterative step where I repeatedly identify prefixes until there are no more prefixes left to identify. This is pretty quick, and dealing with edges instead of nodes really simplified everything.
Thanks for everyone's help!

algorithm needed for decentralized message broadcasting in an offline enviorment (by phone)

The system should allow a fast, reliable and decentralized way to broadcast a message by phone (voice or text) to a preregistered community. Messages are forwarded between members according to predefined rules and contact lists.
The preparation phase is online:
the "broadcaster" is opening a "mailing list"
people join by registering with their phone number (and security phrase)
each get a contact list of 2-4 numbers of other members (together with their security phrases).
The broadcaster initiate a message by calling his contact list.
The broadcast rule is simple: when you get a call (and hear your security phrase) you listen to the message and forward it to your contact list in the same way.
My question is - how to link the members (meaning how to build their contact lists) in a way that will be optimized to:
distribute the message quick (minimum levels of the tree)
not more then 4 contacts in each list (better 2 or 3)
some level of redundancy (so if a member is not available it won't cut the whole branch).
Simple answer, branch out a tree, and then have the "leaves" on each branch connect up with all of the non-leaves on the other branches.
Let me offer more explanation. Suppose that you have 15 people. Then start them off as follows:
{
1: [2, 3],
2: [4, 5],
3: [6, 7],
4: [8, 9],
5: [10, 11],
6: [12, 13],
7: [14, 15],
Then the leaves below 2 are 8, 9, 10, 11 and the leaves below 3 are 12, 13, 14, 15. So now you connect them up with:
8: [3, 6],
9: [7, 12],
10: [13, 14],
11: [15],
12: [2, 4],
13: [5, 8],
14: [9, 10],
15: [11]
}
So you have a tree below 2, and a tree below 3. And if anything is missing on the one side, it is connected to on the other.
If you increase the branching factor then you increase the portion of the tree that are leaves, which makes it even easier to make everything be multiply connected. (It also decreases the distance from root to any element.)

Resources