1 year anniversary and Secret Santa problem II
Exactly one year ago, I started this blog. Little did I
know what to expect. Through this blog and its accompanying pages - I have met many very interesting persons that has learned me much in my pursuit of learning constraint programming. I am very grateful for your help and inspiration! And thanks to all my (other) readers.
I hope the following year will be as rewarding as this last.
The problem formulation is from Maple Primes forum Secret Santa Graph Theory:
This is a more traditional linear programming problem compared to Secret Santa I, using a distance matrix for maximizing the "Secret Santa Distance".
The
I hope the following year will be as rewarding as this last.
Secret Santa problem II
As an anniversary gift, here is another Secret Santa problem (compare with Merry Christmas: Secret Santas Problem) with a slightly different touch.The problem formulation is from Maple Primes forum Secret Santa Graph Theory:
Every year my extended family does a "secret santa" gift exchange. Each person draws another person at random and then gets a gift for them. At first, none of my siblings were married, and so the draw was completely random. Then, as people got married, we added the restriction that spouses should not draw each others names. This restriction meant that we moved from using slips of paper on a hat to using a simple computer program to choose names. Then people began to complain when they would get the same person two years in a row, so the program was modified to keep some history and avoid giving anyone a name in their recent history. This year, not everyone was participating, and so after removing names, and limiting the number of exclusions to four per person, I had data something like this:I have interpreted the problem as follows:
Name: Spouse, Recent Picks
Noah: Ava. Ella, Evan, Ryan, John
Ava: Noah, Evan, Mia, John, Ryan
Ryan: Mia, Ella, Ava, Lily, Evan
Mia: Ryan, Ava, Ella, Lily, Evan
Ella: John, Lily, Evan, Mia, Ava
John: Ella, Noah, Lily, Ryan, Ava
Lily: Evan, John, Mia, Ava, Ella
Evan: Lily, Mia, John, Ryan, Noah
- one cannot be a Secret Santa of one's spouse nor of oneself
- one cannot be a Secret Santa for somebody two years in a row
- objective: maximize the "Secret Santa distance", i.e. the number of years since the last assignment of the same person
This is a more traditional linear programming problem compared to Secret Santa I, using a distance matrix for maximizing the "Secret Santa Distance".
M
is a "large" number (number of persons + 1) for coding that there have been no previous Secret Santa assignment.
rounds = array2d(1..n, 1..n, [ %N A R M El J L Ev 0, M, 3, M, 1, 4, M, 2, % Noah M, 0, 4, 2, M, 3, M, 1, % Ava M, 2, 0, M, 1, M, 3, 4, % Ryan M, 1, M, 0, 2, M, 3, 4, % Mia M, 4, M, 3, 0, M, 1, 2, % Ella 1, 4, 3, M, M, 0, 2, M, % John M, 3, M, 2, 4, 1, 0, M, % Lily 4, M, 3, 1, M, 2, M, 0 % Evan ]);The original problem don't say anything about single persons, i.e. those without spouses. In this model, singleness (no-spouseness) is coded as spouse = 0, and the no-spouse-Santa constraint has been adjusted to takes care of this.
The
constraint
part is the following, where n
is the number of persons:
constraint all_different(santas) /\ % no Santa for one self or the spouse forall(i in 1..n) ( santas[i] != i /\ if spouses[i] > 0 then santas[i] != spouses[i] else true endif ) /\ % the "santa distance" ( forall(i in 1..n) ( santa_distance[i] = rounds[i,santas[i]] ) /\ % cannot be a Secret Santa for the same person two years in a row. forall(i in 1..n) ( let { var 1..n: j } in rounds[i,j] = 1 /\ santas[i] != j ) /\ z = sum(santa_distance)
Solution
This model gives - when usingsolve satisfy
and the constraint z >= 67
- the following 8 solutions with a total of Secret Santa distance of 67 (sum(santa_distance)
). If all Secret Santa assignments where new it would have been a total of n*(n+1) = 8*9 = 72
. As we can see there is always one Santa with a previous existing assignment. (With one Single person and the data I faked, we can get all brand new Secret Santas. See the model for this.)
santa_distance: 9 9 4 9 9 9 9 9 santas : 7 5 8 6 1 4 3 2 santa_distance: 9 9 4 9 9 9 9 9 santas : 7 5 8 6 3 4 1 2 santa_distance: 9 9 9 4 9 9 9 9 santas : 7 5 6 8 1 4 3 2 santa_distance: 9 9 9 4 9 9 9 9 santas : 7 5 6 8 3 4 1 2 santa_distance: 9 9 9 9 4 9 9 9 santas : 4 7 1 6 2 8 3 5 santa_distance: 9 9 9 9 4 9 9 9 santas : 4 7 6 1 2 8 3 5 santa_distance: 9 9 9 9 9 9 4 9 santas : 4 7 1 6 3 8 5 2 santa_distance: 9 9 9 9 9 9 4 9 santas : 4 7 6 1 3 8 5 2