Esempio n. 1
0
        public SecretSantaDraw MakeNextDraw(List<Person> people, List<SecretSantaDraw> previousDraws)
        {
            //Only adults are included
            string[] AllNames = GetNamesOfAdults(people);
            List<Person> AllPeople = GetAdults(people);

            Solver solver = new Solver("XmasDraw");

            int n = AllNames.Count();
            IEnumerable<int> RANGE = Enumerable.Range(0, n);

            //
            // Decision variables
            //
            IntVar[] santas = solver.MakeIntVarArray(n, 0, n - 1, "santas");

            //
            // Constraints
            //
            solver.Add(santas.AllDifferent());

            foreach (int i in RANGE)
            {
                string currentPerson = AllNames[i];

                //Can't buy for yourself
                solver.Add(santas[i] != i);

                //Can't buy for people in same family group
                foreach (string familyMember in GetFamilyGroupMembers(currentPerson, AllPeople))
                {
                    solver.Add(CantBuyFor(currentPerson, familyMember, AllNames, santas));
                }

                //Constraints based on history
                foreach (SecretSantaDraw previousDraw in previousDraws)
                {
                    if (previousDraw.Draw.ContainsKey(currentPerson))
                    {
                        string previousRecipient = previousDraw.Draw[currentPerson];

                        //Can't buy for who you previously bought for
                        solver.Add(CantBuyFor(currentPerson, previousRecipient, AllNames, santas));

                        //Your partner(s) can't buy for previousRecipient
                        foreach (string partner in GetImmediateFamilyMembers(currentPerson, AllPeople))
                        {
                            solver.Add(CantBuyFor(partner, previousRecipient, AllNames, santas));
                        }

                        //Can't buy for previousRecipient's partner(s)
                        foreach (string partner in GetImmediateFamilyMembers(previousRecipient, AllPeople))
                        {
                            solver.Add(CantBuyFor(currentPerson, partner, AllNames, santas));
                        }

                    }

                }

                //Constraints based on potential solutions

                //TODO - Partners don't buy for other partners

            }

            solver.Add(solver.MakeCircuit(santas));

            ////Custom constraints
            //solver.Add(CantBuyFor("Homer", "Fred", AllNames, santas));
            //solver.Add(CantBuyFor("Homer", "Peter", AllNames, santas));

            //solver.Add(CantBuyFor("Peter", "Homer", AllNames, santas));
            //solver.Add(CantBuyFor("Peter", "Fred", AllNames, santas));

            //solver.Add(CantBuyFor("Fred", "Homer", AllNames, santas));
            //solver.Add(CantBuyFor("Fred", "Peter", AllNames, santas));

            //
            // Search
            //
            DecisionBuilder db = solver.MakePhase(santas,
                                                Solver.INT_VAR_SIMPLE,
                                                Solver.INT_VALUE_SIMPLE);

            solver.NewSearch(db);

            if (solver.NextSolution())
            {

                Dictionary<string, string> result = new Dictionary<string, string>();

                foreach (int i in RANGE)
                {
                    result[AllNames[i]] = AllNames[santas[i].Value()];
                }

                return new SecretSantaDraw("Result:" + DateTime.Now.Ticks, result);

            }
            else
            {
                return null;
            }
        }