Esempio n. 1
0
        protected override List <Individual.Individual> InitRandomPopulation(int amountOfIndividuals)
        {
            var population = new List <Individual.Individual>();

            // If there is an odd amount of teams, add a break event to every round.
            bool addBreakRound         = _amountOfTeams % 2 == 1;
            int  eventsPerRound        = addBreakRound ? _amountOfTeams / 2 + 1 : _amountOfTeams / 2;
            int  regularEventsPerRound = addBreakRound ? eventsPerRound - 1 : eventsPerRound;

            Console.WriteLine($"-> Creating {amountOfIndividuals} schedules with {eventsPerRound} events per round.");
            for (int i = 0; i < amountOfIndividuals; i++)
            {
                population.Add(BallStarsSchedule.Random(
                                   _amountOfTeams, eventsPerRound, regularEventsPerRound, _amountOfRounds, _matchPool, addBreakRound,
                                   _avgPlayersPerTeam, _predefinedMatchUps
                                   ));
            }

            return(population);
        }
Esempio n. 2
0
        public void RunSimulatedAnnealing(double initialTemperature = 10, double alpha = 0.9999)
        {
            // Start off with a randomised schedule for an even amount of teams
            int eventsPerRound = _amountOfTeams / 2;
            BallStarsSchedule currentSchedule = BallStarsSchedule.Random(
                _amountOfTeams, eventsPerRound, eventsPerRound, _amountOfRounds, _matchPool, false,
                _avgPlayersPerTeam, _predefinedMatchUps
                );
            BallStarsSchedule bestSchedule           = currentSchedule;
            double            bestFitness            = currentSchedule.Evaluate();
            double            currentScheduleFitness = bestFitness;

            double minimumTemp = 0.000000001;
            double temperature = initialTemperature;
            int    iters       = 0;

            while (iters < 100000)
            {
                if (iters % 1000 == 0)
                {
                    Console.WriteLine($"Running iteration {iters}.");
                }

                // Pick a neighbour by cloning and mutating
                BallStarsSchedule neighbour = currentSchedule.Clone();
                neighbour.LocalSearchMutate(_matchPool);
                neighbour.Evaluate();

                // Always accept better solutions
                if (neighbour.Fitness < currentScheduleFitness)
                {
                    // Update currently tracking schedule and fitness
                    currentScheduleFitness = neighbour.Fitness;
                    currentSchedule        = neighbour;

                    // Update best found schedule and fitness if they improved
                    if (currentScheduleFitness < bestFitness)
                    {
                        bestFitness  = currentScheduleFitness;
                        bestSchedule = currentSchedule.Clone();

                        Console.WriteLine($"New best fitness: {bestFitness} (found in iteration {iters})");
                    }
                }
                else
                {
                    // Accept worse solutions often when starting out, but not as much near termination
                    double diff           = neighbour.Fitness - currentSchedule.Fitness;
                    double acceptanceProb = 1 / (1 + Math.Exp(diff / temperature));
                    if (Globals.Rand.NextDouble() < acceptanceProb)
                    {
                        currentSchedule        = neighbour;
                        currentScheduleFitness = neighbour.Fitness;
                    }
                }

                temperature *= alpha;
                iters++;
                // TODO: Maybe add a temperature reset to get out of a local minimum
            }

            Console.WriteLine($"Algorithm finished. The best schedule is as follows:\n{bestSchedule}");
        }