예제 #1
0
        private void NextGeneration()
        {
            if (population.Count >= 2)
            {
                //Go through and populate most of our next generation with new children
                while (nextPopulation.Count() < (populationSize - 2))
                {
                    RCT2RideData parent1 = SelectCandidate();
                    RCT2RideData parent2;
                    //Make sure the parents aren't the same
                    do
                    {
                        parent2 = SelectCandidate();
                    } while (parent2 == parent1);

                    //Crossover to create children
                    List <RCT2RideData> children = Crossover(parent1, parent2);

                    //Mutate the children
                    children[0] = Mutation(children[0]);
                    children[1] = Mutation(children[1]);

                    //Add them to the next population
                    nextPopulation.AddRange(children);
                }

                //Now add the best from this population as a form of Elitism
                RCT2RideData elitism1        = population[0];
                int          elitism1Fitness = CalculateFitness(elitism1);
                RCT2RideData elitism2        = population[1];
                int          elitism2Fitness = CalculateFitness(elitism2);

                for (int i = 0; i < population.Count; i++)
                {
                    int curFitness = CalculateFitness(population[i]);

                    if (curFitness > elitism1Fitness)
                    {
                        elitism1        = population[i];
                        elitism1Fitness = curFitness;
                    }
                    else if (curFitness > elitism2Fitness)
                    {
                        elitism2        = population[i];
                        elitism2Fitness = curFitness;
                    }
                }

                nextPopulation.Add(elitism1);
                nextPopulation.Add(elitism2);
            }
            else
            {
                Console.WriteLine("ERROR: Population Size must be at least 2");
            }
        }
예제 #2
0
        private int CalculateFitness(RCT2RideData candidate)
        {
            int fitness = 0;

            //Get Displacement to End & Max Y Displacement
            Vector3 prevWorldPos         = new Vector3(0.0f, 0.0f, 0.0f);
            int     worldDirectionChange = 0;
            double  maxVarianceFromStart = 0;
            int     maxYVariance         = 0;

            for (int i = 0; i < candidate.TrackData.TrackData.Count; i++)
            {
                RCT2TrackElements.RCT2TrackElement currentElement = candidate.TrackData.TrackData[i].TrackElement;
                RCT2TrackElementProperty           property       = RCT2TrackElements.TrackElementPropertyMap[currentElement];

                Vector3 worldDisplacement = candidate.TrackData.LocalDisplacementToWorld(property.Displacement, worldDirectionChange);

                //Update World Position Changes
                prevWorldPos += worldDisplacement;

                if (prevWorldPos.Y >= maxYVariance)
                {
                    maxYVariance = (int)prevWorldPos.Y;
                }

                if (prevWorldPos.Length() >= maxVarianceFromStart)
                {
                    maxVarianceFromStart = prevWorldPos.Length();
                }

                //Update World Direction Changes
                worldDirectionChange = candidate.TrackData.UpdateRotation(worldDirectionChange, property.DirectionChange);
            }
            maxYVariance         -= (int)prevWorldPos.Y;
            maxVarianceFromStart -= prevWorldPos.Length();
            Vector3 displacementToEnd = new Vector3(0, 0, 0);

            displacementToEnd.X = Math.Abs(prevWorldPos.X);
            displacementToEnd.Y = Math.Abs(prevWorldPos.Y);
            displacementToEnd.Z = Math.Abs(prevWorldPos.Z);

            //Console.WriteLine(maxYDisplacement);

            double displacementToEndLength = displacementToEnd.Length();

            fitness = (int)(((candidate.ExcitementTimesTen / (1 + candidate.NauseaTimesTen)) + /*maxVarianceFromStart*/ +maxYVariance) * 1000);

            return(fitness);
        }
예제 #3
0
        public void PerformAlgorithm()
        {
            InitialiseParameters();

            Logger.Log("==================");
            Logger.Log("Initial Population");
            Logger.Log("==================");

            InitialPopulationGeneration();

            Logger.Log("==================");
            Logger.Log("Generation Start");
            Logger.Log("==================");

            for (int i = 0; i < generationCount; i++)
            {
                Logger.Log($"Generation Number {i}");
                //Generate the next generation
                NextGeneration();

                //Swap over the populations
                population.Clear();
                population.AddRange(nextPopulation);
                nextPopulation.Clear();

                //Find the best fitness from this new generation and display it
                //Now add the best from this population as a form of Elitism
                RCT2RideData bestCoaster  = population[0];
                int          bestFitness  = CalculateFitness(bestCoaster);
                int          totalFitness = 0;

                for (int j = 0; j < population.Count; j++)
                {
                    int curFitness = CalculateFitness(population[j]);
                    totalFitness += curFitness;

                    if (curFitness > bestFitness)
                    {
                        bestCoaster = population[j];
                        bestFitness = curFitness;
                    }
                }
                Logger.Log($"\tSuccessful Mutations: {successfulMutations}");
                Logger.Log($"\tSuccessful Crossovers: {successfulCrossovers}");
                Logger.Log($"\tBest Fitness: {bestFitness}");
                Logger.Log($"\tAverage Fitness: {totalFitness / populationSize}");

                totalSuccessfulMutations  += successfulMutations;
                successfulMutations        = 0;
                totalSuccessfulCrossovers += successfulCrossovers;
                successfulCrossovers       = 0;
            }
            Logger.Log("==================");
            Logger.Log("Evolution Complete");
            Logger.Log("==================");

            //Find the best one of the final generation
            RCT2RideData bestCoasterMyDude = population[0];
            int          bestFitnessMyDude = CalculateFitness(bestCoasterMyDude);

            for (int i = 0; i < populationSize; i++)
            {
                int currentFitness = CalculateFitness(population[i]);
                if (currentFitness > bestFitnessMyDude)
                {
                    bestCoasterMyDude = population[i];
                    bestFitnessMyDude = currentFitness;
                }
            }

            Logger.Log("==================");
            Logger.Log($"Best Member - Fitness: {bestFitnessMyDude}");
            Logger.Log("==================");

            //Print the best candidate
            for (int i = 0; i < bestCoasterMyDude.TrackData.TrackData.Count; i++)
            {
                Logger.Log(bestCoasterMyDude.TrackData.TrackData[i].TrackElement.ToString());
            }
        }
예제 #4
0
        private RCT2RideData Mutation(RCT2RideData candidate)
        {
            //Console.WriteLine("------------");
            //foreach (var track in candidate.TrackData.TrackData)
            //{
            //    Console.WriteLine(track.TrackElement.ToString());
            //}
            bool hasExtraPiece = false;

            for (int i = 2; i < candidate.TrackData.TrackData.Count(); i++)
            {
                if (random.NextDouble() <= mutationRate)
                {
                    //Get possible candidates
                    RCT2RideData candidateCopy = new RCT2RideData(candidate);
                    List <RCT2TrackElements.RCT2TrackElement> candidateReplacements = RCT2TrackElements.FindValidSuccessors(whitelistedTracks, candidate.TrackData.TrackData[i - 1].TrackElement);
                    bool redo = false;

                    do
                    {
                        //If we're out of possible replacements
                        if (candidateReplacements.Count <= 0)
                        {
                            //Console.WriteLine("/////////////");
                            //foreach (var track in candidate.TrackData.TrackData)
                            //{
                            //    Console.WriteLine(track.TrackElement.ToString());
                            //}
                            return(candidate);
                        }

                        //Construct our random element
                        RCT2TrackPiece randomElement = new RCT2TrackPiece();
                        randomElement.TrackElement = candidateReplacements[random.Next(candidateReplacements.Count)];
                        candidateReplacements.Remove(randomElement.TrackElement);
                        RCT2TrackElementProperty property = RCT2TrackElements.TrackElementPropertyMap[randomElement.TrackElement];
                        if (property.InputTrackDegree == RCT2TrackElementProperty.RCT2TrackDegree.Up25 ||
                            property.InputTrackDegree == RCT2TrackElementProperty.RCT2TrackDegree.Up60 ||
                            property.InputTrackDegree == RCT2TrackElementProperty.RCT2TrackDegree.Up90)
                        {
                            randomElement.Qualifier = new RCT2Qualifier()
                            {
                                IsChainLift             = true,
                                TrackColourSchemeNumber = 0,
                                TrackRotation           = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero,
                                AtTerminalStation       = false,
                                StationNumber           = 0
                            };
                        }
                        else
                        {
                            randomElement.Qualifier = new RCT2Qualifier()
                            {
                                IsChainLift             = false,
                                TrackColourSchemeNumber = 0,
                                TrackRotation           = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero,
                                AtTerminalStation       = false,
                                StationNumber           = 0
                            };
                        }

                        //Replace the existing element at that location with this
                        if (hasExtraPiece)
                        {
                            candidateCopy.TrackData.TrackData.RemoveAt(i + 1);
                            hasExtraPiece = false;
                        }
                        candidateCopy.TrackData.TrackData.RemoveAt(i);

                        if (randomElement.TrackElement == RCT2TrackElements.RCT2TrackElement.FlatToIncline25 ||
                            randomElement.TrackElement == RCT2TrackElements.RCT2TrackElement.Incline25)
                        {
                            candidateCopy.TrackData.TrackData.Insert(i, randomElement);
                            RCT2TrackPiece bridgeElement = new RCT2TrackPiece();
                            bridgeElement.TrackElement = RCT2TrackElements.RCT2TrackElement.Incline25ToFlat;
                            bridgeElement.Qualifier    = new RCT2Qualifier()
                            {
                                IsChainLift             = true,
                                TrackColourSchemeNumber = 0,
                                TrackRotation           = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero,
                                AtTerminalStation       = false,
                                StationNumber           = 0
                            };
                            candidateCopy.TrackData.TrackData.Insert(i + 1, bridgeElement);

                            //Console.WriteLine($"\tAttempted to Mutate into {randomElement.TrackElement.ToString()}");
                            hasExtraPiece = true;
                        }
                        else if (randomElement.TrackElement == RCT2TrackElements.RCT2TrackElement.FlatToDecline25 ||
                                 randomElement.TrackElement == RCT2TrackElements.RCT2TrackElement.Decline25)
                        {
                            candidateCopy.TrackData.TrackData.Insert(i, randomElement);
                            RCT2TrackPiece bridgeElement = new RCT2TrackPiece();
                            bridgeElement.TrackElement = RCT2TrackElements.RCT2TrackElement.Decline25ToFlat;
                            bridgeElement.Qualifier    = new RCT2Qualifier()
                            {
                                IsChainLift             = false,
                                TrackColourSchemeNumber = 0,
                                TrackRotation           = RideData.RCT2Qualifier.RCT2QualifierRotation.Zero,
                                AtTerminalStation       = false,
                                StationNumber           = 0
                            };
                            candidateCopy.TrackData.TrackData.Insert(i + 1, bridgeElement);

                            //Console.WriteLine($"\tAttempted to Mutate into {randomElement.TrackElement.ToString()}");
                            hasExtraPiece = true;
                        }
                        else
                        {
                            candidateCopy.TrackData.TrackData.Insert(i, randomElement);
                        }

                        //If it makes the track invalid, try again
                        if (candidateCopy.TrackData.CheckValidity() != RCT2TrackData.InvalidityCode.Valid)
                        {
                            redo = true;
                        }
                        else
                        {
                            redo = false;
                            successfulMutations++;
                            hasExtraPiece = false;
                        }
                    } while (redo);
                }
            }

            return(candidate);
        }
예제 #5
0
        private List <RCT2RideData> Crossover(RCT2RideData parent1, RCT2RideData parent2)
        {
            List <RCT2RideData> children = new List <RCT2RideData>();
            int  crossoverPoint          = length;
            int  redoCount = 0;
            bool redo      = false;

            RCT2TrackData.InvalidityCode parent1Invalidity = parent1.TrackData.CheckValidity();
            RCT2TrackData.InvalidityCode parent2Invalidity = parent2.TrackData.CheckValidity();

            //Create crossover point
            if (random.NextDouble() <= crossoverRate)
            {
                crossoverPoint = random.Next(length);
            }

            do
            {
                if (redoCount >= crossoverAttempts)
                {
                    crossoverPoint = length;
                }

                //Add first halves to each child
                RCT2TrackData child1Track = new RCT2TrackData();
                RCT2TrackData child2Track = new RCT2TrackData();
                for (int i = 0; i < crossoverPoint; i++)
                {
                    child1Track.TrackData.Add(parent1.TrackData.TrackData[i]);
                    child2Track.TrackData.Add(parent2.TrackData.TrackData[i]);
                }

                //Add second halves to each child
                for (int i = crossoverPoint; i < parent2.TrackData.TrackData.Count(); i++)
                {
                    child1Track.TrackData.Add(parent2.TrackData.TrackData[i]);
                }
                for (int i = crossoverPoint; i < parent1.TrackData.TrackData.Count(); i++)
                {
                    child2Track.TrackData.Add(parent1.TrackData.TrackData[i]);
                }

                RCT2RideData child1 = new RCT2RideData(parent1);
                RCT2RideData child2 = new RCT2RideData(parent2);
                child1.TrackData = child1Track;
                child2.TrackData = child2Track;

                //If the created children are invalid, keep trying
                //Wont cause an infinite loop as we will eventually crossover at point 0
                //Which acts as if we never crossed over at all
                RCT2TrackData.InvalidityCode child1Invalidity = child1.TrackData.CheckValidity();
                RCT2TrackData.InvalidityCode child2Invalidity = child2.TrackData.CheckValidity();
                if (child1Invalidity != RCT2TrackData.InvalidityCode.Valid ||
                    child2Invalidity != RCT2TrackData.InvalidityCode.Valid)
                {
                    redo = true;
                    redoCount++;
                    crossoverPoint = random.Next(length);
                }
                else
                {
                    redo = false;
                    children.Add(child1);
                    children.Add(child2);
                    if (crossoverPoint != length)
                    {
                        successfulCrossovers++;
                    }
                }
            } while (redo);

            return(children);
        }