public override Data Build()
        {
            IState <int> state = new StateInteger(Variables.Values, Constraints);

            state.StartSearch(out StateOperationResult result);

            if (result == StateOperationResult.Unsatisfiable)
            {
                throw new InvalidOperationException();
            }

            var data = new Data();

            foreach (var variable in Variables)
            {
                if (variable.Key.PropertyType == typeof(DateTime))
                {
                    variable.Key.SetValue(data, DateHelper.ToDateTime(variable.Value.Value));
                }
                else
                {
                    variable.Key.SetValue(data, variable.Value.Value);
                }
            }

            return(data);
        }
Exemple #2
0
 public void Search()
 {
     //	Search
     State = new StateInteger(Variables, Constraints);
     State.StartSearch(out StateOperationResult searchResult, out IList <IDictionary <string, IVariable <int> > > solutions);
     Solutions = solutions;
 }
Exemple #3
0
        public void Search()
        {
            State = new StateInteger(Variables.SelectMany(s => s.Select(a => a)), Constraints);

            StateOperationResult searchResult;

            State.StartSearch(out searchResult);
        }
Exemple #4
0
        static void Main(string[] args)
        {
            var numberOfQueens = (args.Length >= 1) ? Int32.Parse(args[0]) : 8;

            // Model
            var variables = new VariableInteger[numberOfQueens];

            for (var i = 0; i < variables.Length; ++i)
            {
                variables[i] = new VariableInteger(i.ToString(CultureInfo.CurrentCulture), 0, numberOfQueens - 1);
            }

            //	Constraints
            var constraints = new List <IConstraint> {
                new AllDifferentInteger(variables)
            };

            for (var i = 0; i < variables.Length - 1; ++i)
            {
                for (var j = i + 1; j < variables.Length; ++j)
                {
                    constraints.Add(new ConstraintInteger(variables[i] - variables[j] != j - i));
                    constraints.Add(new ConstraintInteger(variables[i] - variables[j] != i - j));
                }
            }

            //	Search
            IState <int> state = new StateInteger(variables, constraints);

            StateOperationResult searchResult;
            IList <IDictionary <string, IVariable <int> > > solutions;

            state.StartSearch(out searchResult, out solutions);

            foreach (var solution in solutions)
            {
                for (var i = 0; i < variables.Length; ++i)
                {
                    for (var j = 0; j < variables.Length; ++j)
                    {
                        Console.Write(solution[i.ToString(CultureInfo.CurrentCulture)].InstantiatedValue == j ? "Q" : ".");
                    }

                    Console.WriteLine();
                }

                Console.WriteLine();
            }

            Console.WriteLine("Runtime:\t{0}\nBacktracks:\t{1}", state.Runtime, state.Backtracks);
            Console.WriteLine("Solutions:\t{0}", state.NumberOfSolutions);

            Console.ReadKey();
        }
Exemple #5
0
        public static void Main()
        {
            var a        = new VariableInteger("a", 0, 9);
            var b        = new VariableInteger("b", 0, 9);
            var c        = new VariableInteger("c", 0, 9);
            var d        = new VariableInteger("d", 0, 9);
            var e        = new VariableInteger("e", 0, 9);
            var f        = new VariableInteger("f", 0, 9);
            var g        = new VariableInteger("g", 0, 9);
            var h        = new VariableInteger("h", 0, 9);
            var optimise = new VariableInteger("optimise", 0, 72);

            var array = new ConstrainedArray(new int[] { 0, 23, 52, 62, 75, 73, 47, 20, 87, 27 });

            var constraints = new List <IConstraint>
            {
                new AllDifferentInteger(new [] { a, b, c, d }),
                new AllDifferentInteger(new [] { e, f, g, h }),
                new ConstraintInteger(a + b < 10),
                new ConstraintInteger(c + d > 15),
                new ConstraintInteger(h > e),
                new ConstraintInteger(array[a] < 40),
                new ConstraintInteger(optimise == a + b + c + d + e + f + g + h)
            };

            var          variables = new[] { a, b, c, d, e, f, g, h, optimise };
            IState <int> state     = new StateInteger(variables, constraints);

            StateOperationResult searchResult;
            var solution = default(IDictionary <string, IVariable <int> >);

            state.StartSearch(out searchResult, optimise, out solution, 2);

            Console.WriteLine("a: {0}", solution["a"]);
            Console.WriteLine("b: {0}", solution["b"]);
            Console.WriteLine("c: {0}", solution["c"]);
            Console.WriteLine("d: {0}", solution["d"]);
            Console.WriteLine("e: {0}", solution["e"]);
            Console.WriteLine("f: {0}", solution["f"]);
            Console.WriteLine("g: {0}", solution["g"]);
            Console.WriteLine("h: {0}\n", solution["h"]);

            Console.WriteLine("Optimised Variable: {0}\n", solution["optimise"]);

            Console.WriteLine("Runtime:\t{0}\nBacktracks:\t{1}\n", state.Runtime, state.Backtracks);
            Console.ReadKey();
        }
Exemple #6
0
        public static void Main()
        {
            var s  = new VariableInteger("s", 0, 9);
            var e  = new VariableInteger("e", 0, 9);
            var n  = new VariableInteger("n", 0, 9);
            var d  = new VariableInteger("d", 0, 9);
            var m  = new VariableInteger("m", 1, 9);
            var o  = new VariableInteger("o", 0, 9);
            var r  = new VariableInteger("r", 0, 9);
            var y  = new VariableInteger("y", 0, 9);
            var c0 = new VariableInteger("c0", 0, 1);
            var c1 = new VariableInteger("c1", 0, 1);
            var c2 = new VariableInteger("c2", 0, 1);
            var c3 = new VariableInteger("c3", 0, 1);

            var constraints = new List <IConstraint>
            {
                new AllDifferentInteger(new [] { s, e, n, d, m, o, r, y }),
                new ConstraintInteger(d + e == (10 * c0) + y),
                new ConstraintInteger(n + r + c0 == (10 * c1) + e),
                new ConstraintInteger(e + o + c1 == (10 * c2) + n),
                new ConstraintInteger(s + m + c2 == (10 * c3) + o),
                new ConstraintInteger(c3 == m)
            };

            var          variables = new [] { c0, c1, c2, c3, s, e, n, d, m, o, r, y };
            IState <int> state     = new StateInteger(variables, constraints);

            StateOperationResult searchResult;

            state.StartSearch(out searchResult);

            Console.WriteLine("Runtime:\t{0}\nBacktracks:\t{1}\n", state.Runtime, state.Backtracks);

            Console.WriteLine("    {0} {1} {2} {3} ", s, e, n, d);
            Console.WriteLine("  + {0} {1} {2} {3} ", m, o, r, e);
            Console.WriteLine("  ---------");
            Console.WriteLine("  {0} {1} {2} {3} {4} ", m, o, n, e, y);

            Console.ReadKey();
        }
Exemple #7
0
        private bool _Solve(IEnumerable <VariableInteger> vars, IEnumerable <ExpressionInteger> cl)
        {
            var constraints = cl.Select(e => new ConstraintInteger(e == 1));

            StateOperationResult searchResult;

            IState <int> state = new StateInteger(vars, constraints);

            state.StartSearch(out searchResult);
            if (Config.Debug)
            {
                if (searchResult == StateOperationResult.Solved)
                {
                    Console.WriteLine("**Solution***");
                    foreach (var v in vars)
                    {
                        Console.WriteLine("{0} {1}", v.Name, v);
                    }
                }
            }
            return(searchResult == StateOperationResult.Solved);
        }
Exemple #8
0
        internal static void SelectStartingFormation(IDictionary <int, Player> formation, Team team, Team opposition)
        {
            var templateFormation = SelectTeamFormation(team, opposition);

            var domains = templateFormation.
                          Select(c => team.Players.
                                 OrderByDescending(p => RatingForPosition(p, c)).
                                 Take(5).
                                 Select(p => p.Number).
                                 ToList()
                                 ).ToList();

            var variables = Enumerable.Range(0, 10).
                            Select(i => i.ToString(CultureInfo.InvariantCulture)).
                            Zip(domains, (l, d) => new VariableInteger(l, d)).
                            Cast <IVariable <int> >().
                            ToList();

            var constraints = new List <IConstraint>
            {
                new AllDifferentInteger(variables.Cast <VariableInteger>())
            };

            IState <int> state = new StateInteger(variables, constraints);

            StateOperationResult searchResult;

            state.StartSearch(out searchResult);

            foreach (var playerIndex in variables.Select((v, i) => new { Index = i, Player = team.Players.Single(p => p.Number == v.InstantiatedValue) }))
            {
                formation[playerIndex.Index]            = playerIndex.Player;
                formation[playerIndex.Index].Location.X = templateFormation[playerIndex.Index].X;
                formation[playerIndex.Index].Location.Y = templateFormation[playerIndex.Index].Y;
            }
        }
        static void Main(string[] args)
        {
            #region Model

            var leagueSize = (args.Length >= 1) ? Int32.Parse(args[0]) : 20;

            var variables = new VariableInteger[leagueSize - 1][];

            for (var i = 0; i < variables.Length; ++i)
            {
                variables[i] = new VariableInteger[i + 1];
            }

            for (var i = 0; i < variables.Length; ++i)
            {
                for (var j = 0; j < variables[i].Length; ++j)
                {
                    variables[i][j] = new VariableInteger(string.Format("{0} v {1}", i, j), 1, leagueSize - 1);
                }
            }

            for (var week = 1; week < leagueSize; ++week)
            {
                var i = week - 1;
                var j = 0;

                do
                {
                    variables[i][j] = new VariableInteger(string.Format("{0} v {1}", i, j), week, week);
                    --i;
                    ++j;
                } while (i >= j);
            }

            #endregion

            #region Constraints

            var constraints = new List <IConstraint>();

            for (int row = -1; row < leagueSize - 1; ++row)
            {
                var j = 0;
                var i = row;

                var allDifferentRow = new List <VariableInteger>();

                while (i >= j)
                {
                    allDifferentRow.Add(variables[i][j++]);
                }

                ++i;

                while (i < leagueSize - 1)
                {
                    allDifferentRow.Add(variables[i++][j]);
                }

                constraints.Add(new AllDifferentInteger(allDifferentRow));
            }

            #endregion

            #region Search

            IState <int> state = new StateInteger(variables.SelectMany(s => s.Select(a => a)), constraints);

            StateOperationResult searchResult;
            state.StartSearch(out searchResult);

            for (var i = 0; i < variables.Length; ++i)
            {
                for (var j = 0; j < variables[i].Length; ++j)
                {
                    Console.Write(string.Format("{0,2}", variables[i][j]) + " ");
                }

                Console.WriteLine();
            }

            Console.WriteLine();
            Console.WriteLine("Runtime:\t{0}\nBacktracks:\t{1}", state.Runtime, state.Backtracks);
            Console.WriteLine("Solutions:\t{0}", state.NumberOfSolutions);

            /*
             *	Create a full, random home and away schedule from the solved CSP.
             *
             *
             * var random = new Random();
             * var map = Enumerable.Range(1, (leagueSize - 1) * 2).
             *      OrderBy(i => random.Next()).
             *      Select((e, i) => Tuple.Create(i + 1, e)).
             *      ToDictionary(t => t.Item1, t => t.Item2);
             *
             * var fixtureWeeks = new int[leagueSize][];
             * for (var i = 0; i < fixtureWeeks.Length; ++i)
             *      fixtureWeeks[i] = new int[leagueSize];
             *
             * for (int i = 0; i < variables.Length; ++i)
             *      for (int j = 0; j < variables[i].Length; ++j)
             *      {
             *              fixtureWeeks[i + 1][j] = map[variables[i][j].Value];
             *              fixtureWeeks[j][i + 1] = map[variables[i][j].Value + leagueSize - 1];
             *      }
             *
             * for (var i = 0; i < fixtureWeeks.Length; ++i)
             * {
             *      for (var j = 0; j < fixtureWeeks[i].Length; ++j)
             *              Console.Write(string.Format("{0,2}", fixtureWeeks[i][j]) + " ");
             *
             *      Console.WriteLine();
             * }
             */

            Console.ReadKey();

            #endregion
        }
Exemple #10
0
        public static void Main()
        {
            #region Model

            var numberOfTeachers = 3;

            var hours = Enumerable.Range(0, 8).ToList();

            var Monday    = new List <VariableInteger>();
            var Tuesday   = new List <VariableInteger>();
            var Wednesday = new List <VariableInteger>();
            var Thursday  = new List <VariableInteger>();
            var Friday    = new List <VariableInteger>();
            var Saturday  = new List <VariableInteger>();

            foreach (var period in hours)
            {
                Monday.Add(new VariableInteger(string.Format("Monday {0}", period), 1, numberOfTeachers));
                Tuesday.Add(new VariableInteger(string.Format("Tuesday {0}", period), 1, numberOfTeachers));
                Wednesday.Add(new VariableInteger(string.Format("Wednesday {0}", period), 1, numberOfTeachers));
                Thursday.Add(new VariableInteger(string.Format("Thursday {0}", period), 1, numberOfTeachers));
                Friday.Add(new VariableInteger(string.Format("Friday {0}", period), 1, numberOfTeachers));

                if (period < 5)
                {
                    Saturday.Add(new VariableInteger(string.Format("Saturday {0}", period), 1, numberOfTeachers));
                }
            }

            var Weekdays = new[] { Monday, Tuesday, Wednesday, Thursday, Friday }.ToList();
            var Days = new[] { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday }.ToList();
            var Week = Days.SelectMany(x => x).ToList();

            #endregion

            #region Constraints

            var constraints = new List <IConstraint>();

            // No teacher teaches more than 5 hours per weekday
            foreach (var teacher in Enumerable.Range(1, numberOfTeachers))
            {
                foreach (var day in Weekdays)
                {
                    constraints.Add(new ConstraintInteger(day.
                                                          Select(x => x == teacher).
                                                          Aggregate((x, y) => x + y) <= 5));
                }
            }

            // No teacher teaches for more than two consecutive hours
            foreach (var day in Days)
            {
                for (var window = 0; window < day.Count - 2; ++window)
                {
                    var threeHourWindow = day.Skip(window).Take(3).ToList();

                    constraints.Add(new ConstraintInteger(
                                        threeHourWindow[0] != threeHourWindow[1] |
                                        threeHourWindow[0] != threeHourWindow[2] |
                                        threeHourWindow[1] != threeHourWindow[2])
                                    );
                }
            }

            // No teacher teaches more than 27 hours per week
            foreach (var teacher in Enumerable.Range(1, numberOfTeachers))
            {
                constraints.Add(new ConstraintInteger(Week.
                                                      Select(x => x == teacher).
                                                      Aggregate((x, y) => x + y) <= 27));
            }

            #endregion

            #region Search

            IState <int> state = new StateInteger(Week, constraints);

            state.StartSearch(out StateOperationResult searchResult);

            foreach (var period in Week)
            {
                Console.WriteLine("{0}: {1}", period.Name, period.Value);
            }

            Console.WriteLine("Runtime:\t{0}\nBacktracks:\t{1}\n", state.Runtime, state.Backtracks);

            #endregion
        }
Exemple #11
0
        public async Task Solve()
        {
            await Task.Run(() =>
            {
                crewCount    = names.Count;
                flightsCount = crewRequirements.Count;

                VariableInteger[,] flightsToPersons = new VariableInteger[flightsCount, crewCount];
                for (int i = 0; i < flightsCount; i++)
                {
                    for (int j = 0; j < crewCount; j++)
                    {
                        flightsToPersons[i, j] = new VariableInteger("crew" + i.ToString() + j.ToString(), 0, 1);
                    }
                }
                var variables = flightsToPersons.Cast <VariableInteger>().ToList();


                // Constraints
                var constraints = new List <ConstraintInteger>();

                // create constraints for each flight
                for (int f = 0; f < flightsCount; f++)
                {
                    // size of crew for each flight must be equal to input value
                    var crewForFlight = new ExpressionInteger[crewCount];
                    for (int p = 0; p < crewCount; p++)
                    {
                        crewForFlight[p] = flightsToPersons[f, p];
                    }
                    var flightCrewCount = crewForFlight.Aggregate((a, b) => a + b);
                    var crewSizesEqual  = (flightCrewCount == crewRequirements[f][0]);
                    constraints.Add(new ConstraintInteger(crewSizesEqual));

                    // person attributes (is steward, is hostess, speaks french, speaks spanish, speaks german)
                    // sum of persons with each attribute must be greater than or equal to input value
                    for (int a = 0; a < 5; a++)
                    {
                        crewForFlight = new ExpressionInteger[crewCount];
                        for (int p = 0; p < crewCount; p++)
                        {
                            crewForFlight[p] = (flightsToPersons[f, p] * personsAttributes[p][a]);
                        }
                        var sum = crewForFlight.Aggregate((x, y) => x + y);
                        var attributesGreaterOrEqual = sum >= crewRequirements[f][a + 1];
                        constraints.Add(new ConstraintInteger(attributesGreaterOrEqual));
                    }
                }

                // crew member needs to have 2 flights break after his flight
                for (int f = 0; f < flightsCount - 2; f++)
                {
                    for (int i = 0; i < crewCount; i++)
                    {
                        var cs = ((flightsToPersons[f, i] + flightsToPersons[f + 1, i] + flightsToPersons[f + 2, i]) <= 1);
                        constraints.Add(new ConstraintInteger(cs));
                    }
                }

                // search for solution

                IVariable <int> optimiser = new VariableInteger("optimiser", 1, 100);
                IState <int> state        = new StateInteger(variables, constraints);
                state.StartSearch(out StateOperationResult searchResult, optimiser, out IDictionary <string, IVariable <int> > solution, 10);
                if (searchResult == StateOperationResult.Unsatisfiable || searchResult == StateOperationResult.TimedOut)
                {
                    MessageBox.Show("The result is timed out or unsatisfiable", "Crew Allocation Problem",
                                    MessageBoxButton.OK, MessageBoxImage.Error);
                }

                flightsToNames = new string[flightsCount, maxCrewSize];
                for (int i = 0; i < flightsCount; i++)
                {
                    try
                    {
                        int count = 0;
                        for (int j = 0; j < crewCount; j++)
                        {
                            if (flightsToPersons[i, j].Value == 1)
                            {
                                flightsToNames[i, count] = names[j];
                                count++;
                            }
                        }
                    }
                    catch { }
                }
            });
        }
Exemple #12
0
        static void Main(string[] args)
        {
            #region Model

            var leagueSize = (args.Length >= 1) ? Int32.Parse(args[0]) : 20;

            var variables = new VariableInteger[leagueSize - 1][];

            for (var i = 0; i < variables.Length; ++i)
            {
                variables[i] = new VariableInteger[i + 1];
            }

            for (var i = 0; i < variables.Length; ++i)
            {
                for (var j = 0; j < variables[i].Length; ++j)
                {
                    variables[i][j] = new VariableInteger(string.Format("{0} v {1}", i, j), 1, leagueSize - 1);
                }
            }

            for (var week = 1; week < leagueSize; ++week)
            {
                var i = week - 1;
                var j = 0;

                do
                {
                    variables[i][j] = new VariableInteger(string.Format("{0} v {1}", i, j), week, week);
                    --i;
                    ++j;
                } while (i >= j);
            }

            #endregion

            #region Constraints

            var constraints = new List <IConstraint>();

            for (int row = -1; row < leagueSize - 1; ++row)
            {
                var j = 0;
                var i = row;

                var allDifferentRow = new List <VariableInteger>();

                while (i >= j)
                {
                    allDifferentRow.Add(variables[i][j++]);
                }

                ++i;

                while (i < leagueSize - 1)
                {
                    allDifferentRow.Add(variables[i++][j]);
                }

                constraints.Add(new AllDifferentInteger(allDifferentRow));
            }

            #endregion

            #region Search

            IState <int> state = new StateInteger(variables.SelectMany(s => s.Select(a => a)), constraints);

            StateOperationResult searchResult;
            state.StartSearch(out searchResult);

            for (var i = 0; i < variables.Length; ++i)
            {
                for (var j = 0; j < variables[i].Length; ++j)
                {
                    Console.Write(string.Format("{0,2}", variables[i][j]) + " ");
                }

                Console.WriteLine();
            }

            Console.WriteLine();
            Console.WriteLine("Runtime:\t{0}\nBacktracks:\t{1}", state.Runtime, state.Backtracks);
            Console.WriteLine("Solutions:\t{0}", state.NumberOfSolutions);

            Console.ReadKey();

            #endregion
        }
Exemple #13
0
        static void Main(string[] args)
        {
            var refF   = 26;
            var pllOut = 142;

            if (args.Length == 2)
            {
                refF   = Int32.Parse(args[0]);
                pllOut = Int32.Parse(args[1]);
            }

            //	Model
            var f1 = new VariableInteger("f1", 1, 256);
            var f2 = new VariableInteger("f2", 1, 256);
            var r1 = new VariableInteger("r1", 1, 64);
            var r2 = new VariableInteger("r2", 1, 64);
            var q1 = new VariableInteger("q1", Enumerable.Range(1, 8).Select(i => (int)Math.Pow(2, i)).ToList());
            var q2 = new VariableInteger("q2", Enumerable.Range(1, 8).Select(i => (int)Math.Pow(2, i)).ToList());


            //	Constraints
            const int divrMin = 10;
            const int divrMax = 1000;
            const int vcoMin  = 1600;
            const int vcoMax  = 3200;
            const int refMin  = 25;
            const int refMax  = 600;

            var constraints = new List <IConstraint>
            {
                new ConstraintInteger(pllOut * r1 * r2 * q1 * q2 == refF * f1 * f2),
                new ConstraintInteger(refF >= divrMin * r1),
                new ConstraintInteger(refF <= divrMax * r1),
                new ConstraintInteger(refF * f1 >= vcoMin * r1),
                new ConstraintInteger(refF * f1 <= vcoMax * r1),
                new ConstraintInteger(refF * f1 >= refMin * r1 * q1),
                new ConstraintInteger(refF * f1 <= refMax * r1 * q1),
                new ConstraintInteger(refF * f1 >= divrMin * r2 * r1 * q1),
                new ConstraintInteger(refF * f1 <= divrMax * r2 * r1 * q1),
                new ConstraintInteger(refF * f1 * f2 >= vcoMin * r2 * r1 * q1),
                new ConstraintInteger(refF * f1 * f2 <= vcoMax * r2 * r1 * q1),
            };


            //	Search
            IState <int> state = new StateInteger(new[] { f1, f2, r1, r2, q1, q2 }, constraints);

            StateOperationResult searchResult;

            state.StartSearch(out searchResult);

            Console.WriteLine("Runtime:\t{0}\nBacktracks:\t{1}\n", state.Runtime, state.Backtracks);

            if (searchResult == StateOperationResult.Solved)
            {
                var tmp = (double)(refF * f1.Value) / (r1.Value * q1.Value);

                Console.WriteLine("refF: {0}\tpllOut: {1}", refF, pllOut);
                Console.WriteLine();
                Console.WriteLine("tmp == (refF * f1) / (r1 * q1)");
                Console.WriteLine("{0} == ({1} * {2}) / ({3} * {4})", tmp, refF, f1, r1, q1);
                Console.WriteLine();
                Console.WriteLine("pllout == (tmp * f2) / (r2 * q2)");
                Console.WriteLine("{0} == ({1} * {2}) / ({3} * {4})", pllOut, tmp, f2, r2, q2);
                Console.WriteLine();
            }
            else
            {
                Console.WriteLine("No solution found.");
                Console.WriteLine();
            }

            Console.ReadKey();
        }
Exemple #14
0
        static void Main(string[] args)
        {
            var badnessFactor = 3;
            var teams         = new[]
            {
                new Team(0, 3, 1, 0, 0, 0),
                new Team(1, 2, 0, 1, 0, 0),
                new Team(2, 1, 0, 0, 1, 0),
                new Team(3, 0, 0, 0, 0, 1),
                new Team(4, 3, 0, 0, 0, 1),
                new Team(5, 2, 0, 0, 1, 0),
                new Team(6, 1, 0, 1, 0, 0),
                new Team(7, 0, 1, 0, 0, 0)
            };

            Array.Sort(teams, (x, y) => y.Score.CompareTo(x.Score)); //High to low
            var rooms = teams.Length / 4;

            //Positions[room * position] = TeamId
            var positions = new List <VariableInteger>(teams.Length);

            for (var i = 0; i < teams.Length; i++)
            {
                positions.Add(new VariableInteger($"Team_{i}", 0, teams.Length - 1));
            }

            //Scores[teamId] = current score
            var scores = new ConstrainedArray(teams.Select(x => x.Score));

            //Optimise positions
            var firstProp  = new ConstrainedArray(teams.Select(x => x.FirstProp * badnessFactor));
            var secondProp = new ConstrainedArray(teams.Select(x => x.SecondProp * badnessFactor));
            var firstOpp   = new ConstrainedArray(teams.Select(x => x.FirstOpp * badnessFactor));
            var secondOpp  = new ConstrainedArray(teams.Select(x => x.SecondOpp * badnessFactor));
            var maxBadness = firstProp.Union(secondProp).Union(firstOpp).Union(secondOpp).Max() * teams.Length;
            var optimise   = new VariableInteger("optimise", 0, maxBadness);

            //TODO Change optimise to look at the bound and stop if best reached
            var variables = new List <VariableInteger>(positions);

            variables.Add(optimise);
            var constraints = new List <IConstraint> {
                new AllDifferentInteger(positions)
            };

            for (var i = 0; i < rooms - 1; i++)
            {
                for (var j = 0; j < 4; j++)
                {
                    var x = positions[i * 4 + j];

                    for (var k = 0; k < 4; k++)
                    {
                        var y = positions[(i + 1) * 4 + k];
                        constraints.Add(new ConstraintInteger(scores[x] >= scores[y]));
                    }
                }
            }

            constraints.Add(new ConstraintInteger(optimise == maxBadness -
                                                  firstProp[positions[0]] - firstOpp[positions[1]] - secondProp[positions[2]] - secondOpp[positions[3]]
                                                  ));

            IState <int>         state = new StateInteger(variables, constraints);
            StateOperationResult searchResult;
            IDictionary <string, IVariable <int> > solution;

            state.StartSearch(out searchResult, optimise, out solution, 2);

            if (searchResult == StateOperationResult.Unsatisfiable)
            {
                Console.WriteLine("Could not find a solution");
                Console.ReadKey();
                return;
            }
            if (searchResult == StateOperationResult.TimedOut)
            {
                Console.WriteLine("Search timed out before a solution could be found");
                Console.ReadKey();
                return;
            }

            Console.WriteLine("Runtime:\t{0}\nBacktracks:\t{1}\nSolutions:\t{2}", state.Runtime, state.Backtracks, state.NumberOfSolutions);
            Console.WriteLine("Badness:\t{0}", solution[optimise.Name].InstantiatedValue);

            Console.WriteLine("Room | 1P | 1O | 2P | 2O | Scores ");
            for (var i = 0; i < rooms; i++)
            {
                var fp = solution[positions[i * 4].Name].InstantiatedValue;
                var sp = solution[positions[i * 4 + 1].Name].InstantiatedValue;
                var fo = solution[positions[i * 4 + 2].Name].InstantiatedValue;
                var so = solution[positions[i * 4 + 3].Name].InstantiatedValue;

                Console.WriteLine("{0,-5}|{1,3} |{2,3} |{3,3} |{4,3} | {5} {6} {7} {8}", i, fp, sp, fo, so, scores[fp], scores[sp], scores[fo], scores[so]);
            }

            Console.ReadKey();
        }