예제 #1
0
파일: Program.cs 프로젝트: Donovancm/GA_DS
        public static void RunExampleOnce()
        {
            List <Person>       population        = new List <Person>();
            List <double>       coefficient       = new List <double>();
            List <CoupleParent> coupleParents     = new List <CoupleParent>();
            List <string>       crossoverChildren = new List <string>();

            FileReader.CoefficientRead(coefficient);
            FileReader.ReadFile(population, 5);
            Fitness.CalculateSSE(population);
            Fitness.CalculateCoefSSE(coefficient, population);

            //Stap 1 t/m 5
            RouletteWheel.DoCalculation(population);

            //Crossover Methods
            //SinglePointCrossover.DoCrossover(coupleParents, crossoverChildren);
            TwoPointCrossover.DoCrossover(coupleParents, crossoverChildren, crossOverPercentage, population);

            //Mutation
            Mutation.MutationChildren(crossoverChildren);

            //Recalculate Fitness for Childrens
            List <Person> childrenPopulation = Fitness.CalculateCoefSSEChild(coefficient, crossoverChildren);

            //Elitism best solution
            var bestPerson = Elitism.ChildHighestFit(childrenPopulation, crossOverPercentage);

            Console.ReadKey();
        }
예제 #2
0
    void Start()
    {
        ActionNode gettingWoodNight = new ActionNode(() =>
        {
            Debug.Log("ROULETTE OPTION 1: Im getting wood at night");
            EnviromentData.Instance.wood    += 5;
            EnviromentData.Instance.stamina -= 4;
            GetWood();
        });
        ActionNode harvestingNight = new ActionNode(() =>
        {
            Debug.Log("ROULETTE OPTION 2: Im getting food at night");
            EnviromentData.Instance.food    += 2;
            EnviromentData.Instance.stamina -= 4;
            GetFood();
        });
        ActionNode buildHouseNight = new ActionNode(() =>
        {
            Debug.Log("ROULETTE OPTION 3: Im sleeping at night");
            EnviromentData.Instance.stamina += 2;
            GoToSleep();
        });

        roulette = new RouletteWheel <ActionNode>();

        roulette.options.Add(gettingWoodNight);
        roulette.options.Add(harvestingNight);
        roulette.options.Add(buildHouseNight);
    }
예제 #3
0
        static void Main(string[] args)
        {
            var get = new DataReader();
            //fitness
            Fitness fitness = new Fitness(get.DataPregnant(), get.Data());// insert the data from DataReader for the population creation.
            //selection
            var        highestFitness = 1;
            var        lowestFitness  = 2;
            ISelection roulette       = new RouletteWheel();
            ISelection ranking        = new Ranking(highestFitness);

            //crossover
            var        crossoverProbability = 0.6;
            ICrossover onePointCrosseover   = new OnePointCrossover();
            ICrossover twoPointCrosseover   = new TwoPointCrossover();
            //mutation
            var Mutation     = (chanceMutation : 0.01, min : -1, max : 1);
            var RandomLimits = (min : -1, max : 1);
            //population
            var populationSize = 60;
            // create a new population
            var population = fitness.GenerateNewPopulation(populationSize, RandomLimits);

            var ga = new GeneticAlgorithm(population, fitness, 100, onePointCrosseover, crossoverProbability, Mutation, roulette);

            System.Collections.Generic.List <double> predict = get.Data()[400];

            Console.WriteLine("prediction for value " + 400 + " : " + new Prediction().Predict(ga.BestSeed.DNA, predict));
            Console.ReadLine();
        }
예제 #4
0
        public void DoNotSelectFirstCandidateWhenHasZeroAptitudeEvenWithZeroRouletteValue()
        {
            var itemSelector = new RouletteWheel();
            var array        = new Single[] { 0F, 1F, 1F, 1F, 1F };

            var selected = itemSelector.SelectItem(array, 0F);

            Assert.That(selected, Is.Not.EqualTo(0));
        }
예제 #5
0
        public void ShouldConstructorInitializeDaySlotAndAptitudes()
        {
            var itemSelector = new RouletteWheel();
            var allState     = new AllocationState(10, 15, new Single[] { 1.5F, 2.5F, 3.5F, 4.5F, 5.5F }, itemSelector);

            Assert.That(allState.Day, Is.EqualTo(10));
            Assert.That(allState.Slot, Is.EqualTo(15));
            Assert.That(allState.InitialAptitudes.Length, Is.EqualTo(allState.CurrentAptitudes.Length));
        }
예제 #6
0
        static Dictionary <string, PasswordInfo> morphEnglish(Dictionary <string, PasswordInfo> english, double[] digitProbs, double[] posProbs, int minLength = 0)
        {
            Dictionary <string, PasswordInfo> results = new Dictionary <string, PasswordInfo>();

            FastRandom random = new FastRandom();

            Console.WriteLine("Probs sum: {0}", digitProbs.Sum());
            RouletteWheelLayout digitLayout = new RouletteWheelLayout(digitProbs);
            RouletteWheelLayout posLayout   = new RouletteWheelLayout(posProbs);
            int alreadyNumbered             = 0;

            foreach (string s in english.Keys)
            {
                bool numbered = false;
                for (int i = 0; i < s.Length; i++)
                {
                    if (s[i] >= '0' && s[i] <= '9')
                    {
                        alreadyNumbered++;
                        numbered = true;
                        break;
                    }
                }
                string morphedPassword = s;
                while (!numbered || morphedPassword.Length < minLength)
                {
                    int toAdd = RouletteWheel.SingleThrow(digitLayout, random);
                    int pos   = RouletteWheel.SingleThrow(posLayout, random);

                    if (pos == 0)
                    {
                        break;
                    }
                    else if (pos == 1)
                    {
                        morphedPassword = toAdd + morphedPassword;
                    }
                    else if (pos == 2)
                    {
                        morphedPassword = morphedPassword + toAdd;
                    }
                    else
                    {
                        pos             = random.Next(morphedPassword.Length);
                        morphedPassword = morphedPassword.Substring(0, pos) + toAdd + morphedPassword.Substring(pos, morphedPassword.Length - pos);
                    }
                    numbered = true;
                }
                PasswordInfo val;
                if (!results.TryGetValue(morphedPassword, out val))
                {
                    results.Add(morphedPassword, new PasswordInfo(1, 1));
                }
            }
            Console.WriteLine("Had numbers already: {0}", alreadyNumbered);
            return(results);
        }
예제 #7
0
        public void SelectFourthItemWhenRouletteFallsOnTheLeftBoundaryOfTheFourthSector()
        {
            var itemSelector = new RouletteWheel();
            var array        = new Single[] { 1F, 1F, 0.1F, 1F, 1F };

            //third/fourth boundary is 2.1 / 4.1 = 0.5121951
            int?selItem = itemSelector.SelectItem(array, .5122F);

            Assert.That(selItem, Is.EqualTo(3));
        }
예제 #8
0
        public void SelectThirdItemWhenRouletteFallsOnTheLeftBoundaryOfTheThirdSector()
        {
            var itemSelector = new RouletteWheel();
            var array        = new Single[] { 1F, 1F, 0.1F, 1F, 1F };

            //second/third boundary is 2 / 4.1 = 0.4878048
            int?selItem = itemSelector.SelectItem(array, .4879F);

            Assert.That(selItem, Is.EqualTo(2));
        }
예제 #9
0
        public void ShouldResetCorrectlyInitializeState()
        {
            var itemSelector = new RouletteWheel();
            var allState     = new AllocationState(10, 15, new Single[] { 1.5F, 2.5F, 3.5F, 4.5F, 5.5F }, itemSelector);

            allState.Reset();
            Assert.That(allState.Processed, Is.False);
            Assert.That(allState.Forced, Is.False);
            Assert.That(allState.ChosenItem, Is.Null);
            Assert.That(allState.InitialAptitudes, Is.EquivalentTo(allState.CurrentAptitudes));
        }
예제 #10
0
        public void TestForce()
        {
            var itemSelector = new RouletteWheel();
            var allState     = new AllocationState(10, 15, new Single[] { 1.5F, 2.5F, 3.5F, 4.5F, 5.5F }, itemSelector);

            allState.Reset();
            allState.Force(2);
            Assert.That(allState.Processed, Is.True);
            Assert.That(allState.Forced, Is.True);
            Assert.That(allState.ChosenItem, Is.EqualTo(2));
        }
 public ClassicRoulette(List <Player> players, IInputManager inputManager, IOutputManager outputManager, CancellationToken cancellationToken)
 {
     _players           = players;
     _inputManager      = inputManager;
     _outputManager     = outputManager;
     _strategyProcessor = new StrategyProcessor();
     _strategyManager   = new StrategyManager(_players);
     _cancellationToken = cancellationToken;
     _rouletteWheel     = new RouletteWheel();
     _numberStore       = new NumberStore();
 }
예제 #12
0
        public void RouletteWheelTest_NormalPopWithFixedFitness_ShouldPass()
        {
            var rd      = DefaultResearchParameters.GetDefaultResearchDefinitions();
            var testPop = Fitness.FixedFitPop(
                Chromosome.NewRandomPopulation(rd, rd.Population));
            var outputTestPop = new RouletteWheel().DrawChromosomes(testPop);

            var fitnessSumTestPop       = testPop.Sum(x => x.Fitness);
            var fitnessSumOutputTestPop = outputTestPop.Sum(x => x.Fitness);

            Assert.True(fitnessSumTestPop != fitnessSumOutputTestPop);
        }
예제 #13
0
        public string RedBlack(int a)
        {
            RouletteWheel wheel = new RouletteWheel();

            if (a > 0) // Red or Black
            {
                return(RouletteWheel.Colors[a]);
            }
            else //0 or 00
            {
                return("Neither Red nor Black colors because it was 0 or 00, which are green.");
            }
        }
        public IntelligentAiPlayerController(IPlayerState initialState)
        {
            _neuromonRouletteWheels = new Dictionary<Neuromon, RouletteWheel<Move>>();

            foreach (var neuromon in initialState.AllNeuromon)
            {
                var rouletteWheel = CreateMoveRouletteWheel(neuromon);
                _neuromonRouletteWheels.Add(neuromon, rouletteWheel);
            }

            _turnTypeRouletteWheel = CreateTurnTypeRouletteWheel();

            _supportedTurnTypes = new[] { TurnType.Attack, TurnType.SwitchActiveNeuromon };
        }
예제 #15
0
        public void SelectionGivesLastElementWhenRouletteValueIsGreaterThanOne()
        {
            var itemSelector = new RouletteWheel();
            var elems        = rnd.Next(100) + 2;
            var array        = new Single[elems];

            for (int i = 0; i < elems; i++)
            {
                array[i] = 1F;
            }

            var selected = itemSelector.SelectItem(array, 1.0001F);

            Assert.That(selected, Is.EqualTo(elems - 1));
        }
예제 #16
0
        public void ShouldSelectNoItemsWhenAptitudeAreAllZero()
        {
            var itemSelector = new RouletteWheel();
            var array        = new Single[1 + rnd.Next(10)];

            for (int i = 0; i < array.Length; i++)
            {
                array[i] = 0F;
            }
            var rouletteValue = (float)rnd.NextDouble();

            int?selItem = itemSelector.SelectItem(array, rouletteValue);

            Assert.That(selItem, Is.Null);
        }
예제 #17
0
        public void ShouldSelectAnItem()
        {
            var itemSelector = new RouletteWheel();
            var array        = new Single[1 + rnd.Next(10)];

            for (int i = 0; i < array.Length; i++)
            {
                array[i] = 1F;
            }
            var rouletteValue = (float)rnd.NextDouble();

            int?selItem = itemSelector.SelectItem(array, rouletteValue);

            Assert.That(selItem, Is.GreaterThanOrEqualTo(0).And.LessThanOrEqualTo(array.Length));
        }
예제 #18
0
    public void InitializeRouletteWheel()
    {
        roulette = new RouletteWheel();

        //Agrego las acciones al diccionario que se va a pasar cuando se llame a la ruleta.
        rouletteActions.Add(_cooldownReduction, cooldownReductionWeight);
        rouletteActions.Add(_extraSpeed, extraSpeedWeight);
        rouletteActions.Add(_extraDamage, extraDamageWeight);
        rouletteActions.Add(_extraHealth, extraHealthWeight);

        //Agrego los métodos que se van a ejecutar según lo que devuelva la ruleta.
        _rouletteExecute.Add(_cooldownReduction, ReduceCooldown);
        _rouletteExecute.Add(_extraSpeed, ExtraSpeed);
        _rouletteExecute.Add(_extraDamage, ExtraDamage);
        _rouletteExecute.Add(_extraHealth, ExtraHealth);
    }
예제 #19
0
        /// <summary>
        /// Move the prey. The prey moves by a simple set of stochastic rules that make it more likely to move away from
        /// the agent, and moreso when it is close.
        /// </summary>
        public void MovePrey()
        {
            // Determine if prey will move in this timestep. (Speed is simulated stochastically)
            if (_rng.NextDouble() > _preySpeed)
            {
                return;
            }

            // Determine position of agent relative to prey.
            PolarPoint relPolarPos = PolarPoint.FromCartesian(_agentPos - _preyPos);

            // Calculate probabilities of moving in each of the four directions. This stochastic strategy is taken from:
            // Incremental Evolution Of Complex General Behavior, Faustino Gomez and Risto Miikkulainen (1997)
            // (http://nn.cs.utexas.edu/downloads/papers/gomez.adaptive-behavior.pdf)
            // Essentially the prey moves randomply but we bias the movements so the prey moves away from the agent, and thus
            // generally avoids getting eaten through stupidity.
            double T = MovePrey_T(relPolarPos.Radial);

            double[] probs = new double[4];
            probs[0] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, Math.PI / 2.0) / Math.PI) * T * 0.33);  // North.
            probs[1] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, 0) / Math.PI) * T * 0.33);              // East.
            probs[2] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, Math.PI * 1.5) / Math.PI) * T * 0.33);  // South.
            probs[3] = Math.Exp((CalcAngleDelta(relPolarPos.Theta, Math.PI) / Math.PI) * T * 0.33);        // West.

            RouletteWheelLayout rwl = new RouletteWheelLayout(probs);
            int action = RouletteWheel.SingleThrow(rwl, _rng);

            switch (action)
            {
            case 0:      // Move north.
                _preyPos._y = Math.Min(_preyPos._y + 1, _gridSize - 1);
                break;

            case 1:     // Move east.
                _preyPos._x = Math.Min(_preyPos._x + 1, _gridSize - 1);
                break;

            case 2:     // Move south.
                _preyPos._y = Math.Max(_preyPos._y - 1, 0);
                break;

            case 3:     // Move west (is the best?)
                _preyPos._x = Math.Max(_preyPos._x - 1, 0);
                break;
            }
        }
예제 #20
0
        public void TestForceAndResetForced()
        {
            var itemSelector = new RouletteWheel();
            var allState     = new AllocationState(10, 15, new Single[] { 1.5F, 2.5F, 3.5F, 4.5F, 5.5F }, itemSelector);

            allState.Reset();
            allState.Force(2);
            //Overwrites currentaptitudes
            for (int i = 0; i < allState.InitialAptitudes.Length; i++)
            {
                allState.CurrentAptitudes[i] = 0;
            }

            allState.Reset();
            Assert.That(allState.Processed, Is.False);
            Assert.That(allState.Forced, Is.False);
            Assert.That(allState.ChosenItem, Is.Null);
        }
예제 #21
0
        public void ShouldSelectTheOnlyItemWithNonZeroAptitude()
        {
            var itemSelector = new RouletteWheel();
            var array        = new Single[1 + rnd.Next(10)];

            for (int i = 0; i < array.Length; i++)
            {
                array[i] = 0F;
            }
            var nonZeroItemIndex = rnd.Next(array.Length);

            array[nonZeroItemIndex] = 1F;
            var rouletteValue = (float)rnd.NextDouble();

            int?selItem = itemSelector.SelectItem(array, rouletteValue);

            Assert.That(selItem, Is.EqualTo(nonZeroItemIndex));
        }
예제 #22
0
        /// <summary>
        /// Activates the Markov chain once and returns the resulting string.
        /// </summary>
        public string Activate()
        {
            int    stateIdx = 1;
            string s        = "";

            for (int i = 0; i < _stepsPerActivation; i++)
            {
                if (_rouletteWheels[stateIdx].Probabilities.Length == 0)
                {
                    return(s);
                }
                stateIdx = _nodes[stateIdx].TransitionDestinations[RouletteWheel.SingleThrow(_rouletteWheels[stateIdx], _random)];
                if (_nodes[stateIdx].State != null)
                {
                    s += _nodes[stateIdx].State;
                }
            }

            return(s);
        }
예제 #23
0
        /*
         *  var functionUnderStudy = new Func<double, double>(x => 0.2 * Math.Pow(x, 3) + 0.1 * Math.Pow(x, 2) - 8 * x);
         *  var fitFunction = new Func<double, double>(x => -(0.2 * Math.Pow(x, 3) + 0.1 * Math.Pow(x, 2) - 8 * x));
         *
         *  var functionUnderStudy = new Func<double, double>(x => x - Math.Pow(x, 2) + Math.Pow(x, 3));
         *  var fitFunction = functionUnderStudy;
         *
         *  var functionUnderStudy = new Func<double, double>(Math.Sin);
         *  var fitFunction = functionUnderStudy;
         */
        public static void Main(string[] args)
        {
            var iterations         = 1000;
            var functionUnderStudy = new Func <double[], double>(x => 0.2 * Math.Pow(x[0], 3) + 0.1 * Math.Pow(x[0], 2) - 8 * x[0]);
            var fitFunction        = new Func <double[], double>(x => Math.Sin(x[0]));
            var cd = new ChromosomeDefinition(10);
            var fc = new Function(functionUnderStudy, fitFunction, -7, 7);
            var rd = new ResearchDefinitions(cd, fc, 100, 0.1, 0.5);
            var listOfMediumAbsFitness = new List <double>();

            var startPop = Fitness.FitPop(
                Chromosome.NewRandomPopulation(
                    rd,
                    rd.Population));

            listOfMediumAbsFitness.Add(startPop.Sum(x => x.Fitness) / startPop.Count);

            var preselectedPop = new RouletteWheel().DrawChromosomes(startPop);

            var nextGenPop     = Fitness.FitPop(PostSelection.CreateNewPopulation(preselectedPop, rd.CrossChance, rd.MutationChance));
            var bestChromosome = new BestChromosome()
            {
                bestChromosome = nextGenPop.Max(x => x),
                generation     = 1
            };

            listOfMediumAbsFitness.Add(nextGenPop.Sum(x => x.Fitness) / nextGenPop.Count);

            for (int i = 1; i < iterations; i++)
            {
                nextGenPop = Fitness.FitPop(PostSelection.CreateNewPopulation(nextGenPop, rd.CrossChance, rd.MutationChance));
                if (bestChromosome.bestChromosome.AbsFitness < nextGenPop.Max(x => x.AbsFitness))
                {
                    bestChromosome.bestChromosome = nextGenPop.FirstOrDefault(x => x.AbsFitness == nextGenPop.Max(y => y.AbsFitness));
                    bestChromosome.generation     = i + 1;
                }
                listOfMediumAbsFitness.Add(nextGenPop.Sum(x => x.Fitness) / nextGenPop.Count);
            }

            listOfMediumAbsFitness.ForEach(Console.WriteLine);
        }
예제 #24
0
파일: Program.cs 프로젝트: Donovancm/GA_DS
 public static void RunGeneticAlgorithm()
 {
     for (int i = 0; i < iterations; i++)
     {
         List <Person> population        = new List <Person>();
         List <double> coefficient       = new List <double>();
         List <string> crossoverChildren = new List <string>();
         FileReader.CoefficientRead(coefficient);
         FileReader.ReadFile(population, populationAmount);
         List <CoupleParent> coupleParents = new List <CoupleParent>();
         Fitness.CalculateSSE(population);
         Fitness.CalculateCoefSSE(coefficient, population);
         RouletteWheel.DoCalculation(population);
         RunCrossOver(coupleParents, crossoverChildren, population);
         Mutation.MutationChildren(crossoverChildren);
         //Recalculate Fitness for Childrens
         List <Person> childrenPopulation = Fitness.CalculateCoefSSEChild(coefficient, crossoverChildren);
         //Elitism best solution
         RunElitism(i, childrenPopulation);
     }
 }
        /// <summary>
        /// Cross specie mating.
        /// </summary>
        /// <param name="rwl">RouletteWheelLayout for selectign genomes in teh current specie.</param>
        /// <param name="rwlArr">Array of RouletteWheelLayout objects for genome selection. One for each specie.</param>
        /// <param name="rwlSpecies">RouletteWheelLayout for selecting species. Based on relative fitness of species.</param>
        /// <param name="currentSpecieIdx">Current specie's index in _specieList</param>
        /// <param name="genomeList">Current specie's genome list.</param>
        private TGenome CreateOffspring_CrossSpecieMating(RouletteWheelLayout rwl,
                                                          RouletteWheelLayout[] rwlArr,
                                                          RouletteWheelLayout rwlSpecies,
                                                          int currentSpecieIdx,
                                                          IList <TGenome> genomeList)
        {
            // Select parent from current specie.
            int parent1Idx = RouletteWheel.SingleThrow(rwl, _rng);

            // Select specie other than current one for 2nd parent genome.
            RouletteWheelLayout rwlSpeciesTmp = rwlSpecies.RemoveOutcome(currentSpecieIdx);
            int specie2Idx = RouletteWheel.SingleThrow(rwlSpeciesTmp, _rng);

            // Select a parent genome from the second specie.
            int parent2Idx = RouletteWheel.SingleThrow(rwlArr[specie2Idx], _rng);

            // Get the two parents to mate.
            TGenome parent1 = genomeList[parent1Idx];
            TGenome parent2 = _specieList[specie2Idx].GenomeList[parent2Idx];

            return(parent1.CreateOffspring(parent2, _currentGeneration));
        }
예제 #26
0
        public void ShouldNotSelectAnItemWithZeroAptitude()
        {
            var itemSelector = new RouletteWheel();
            var array        = new Single[2 + rnd.Next(10)];

            for (int i = 0; i < array.Length; i++)
            {
                array[i] = 1F;
            }
            var zeroItemIndex = rnd.Next(array.Length);

            array[zeroItemIndex] = 0F;
            var rouletteValue = (float)rnd.NextDouble();

            int?selItem = itemSelector.SelectItem(array, rouletteValue);

            Assert.That(selItem,
                        Is.GreaterThanOrEqualTo(0)
                        .And
                        .LessThanOrEqualTo(array.Length)
                        .And.Not.EqualTo(zeroItemIndex));
        }
예제 #27
0
        public ShiftMatrix(int days, int slots, int items, Single defaultAptitude)
        {
            this.days  = days;
            this.slots = slots;
            this.items = items;
            var itemSelector = new RouletteWheel();

            matrix = new AllocationState[Days, Slots];
            for (int day = 0; day < matrix.GetLength(0); day++)
            {
                for (int slot = 0; slot < matrix.GetLength(1); slot++)
                {
                    var apts = new Single[Items];
                    for (int i = 0; i < apts.Length; i++)
                    {
                        apts[i] = defaultAptitude;
                    }
                    matrix[day, slot] = new AllocationState(day, slot, apts, itemSelector);
                }
            }

            Reset();
        }
예제 #28
0
        public void geneticSolve()
        {
            Stopwatch timer = new Stopwatch();

            timer.Start();

            //ToDo: Set the limit for running the genetic algorithm, to quit with best found limit
            //Assuming the limit is a time (seconds)
            int limit = 180

                        while (timer != limit)
            {
                //This will call advance in finding the best path iteratively by leveraging the Roulette Wheel
                RouletteWheel wheel = RouletteWheel(cities)
                                      int psuedoRandomNumber = wheel.getRandomMember()

                                                               //ToDo: Add other function calls here to get the best path guesses
                                                               //Then we pass this city into ..
            }



            timer.Stop();
        }
        /// <summary>
        /// Create the required number of offspring genomes, using specieStatsArr as the basis for selecting how
        /// many offspring are produced from each species.
        /// </summary>
        private List <TGenome> CreateOffspring(SpecieStats[] specieStatsArr, int offspringCount)
        {
            // Build a RouletteWheelLayout for selecting species for cross-species reproduction.
            // While we're in the loop we also pre-build a RouletteWheelLayout for each specie;
            // Doing this before the main loop means we have RouletteWheelLayouts available for
            // all species when performing cross-specie matings.
            int specieCount = specieStatsArr.Length;

            double[] specieFitnessArr    = new double[specieCount];
            RouletteWheelLayout[] rwlArr = new RouletteWheelLayout[specieCount];

            // Count of species with non-zero selection size.
            // If this is exactly 1 then we skip inter-species mating. One is a special case because for 0 the
            // species all get an even chance of selection, and for >1 we can just select normally.
            int nonZeroSpecieCount = 0;

            for (int i = 0; i < specieCount; i++)
            {
                // Array of probabilities for specie selection. Note that some of these probabilites can be zero, but at least one of them won't be.
                SpecieStats inst = specieStatsArr[i];
                specieFitnessArr[i] = inst._selectionSizeInt;
                if (0 != inst._selectionSizeInt)
                {
                    nonZeroSpecieCount++;
                }

                // For each specie we build a RouletteWheelLayout for genome selection within
                // that specie. Fitter genomes have higher probability of selection.
                List <TGenome> genomeList    = _specieList[i].GenomeList;
                double[]       probabilities = new double[inst._selectionSizeInt];
                for (int j = 0; j < inst._selectionSizeInt; j++)
                {
                    probabilities[j] = genomeList[j].EvaluationInfo.Fitness;
                }
                rwlArr[i] = new RouletteWheelLayout(probabilities);
            }

            // Complete construction of RouletteWheelLayout for specie selection.
            RouletteWheelLayout rwlSpecies = new RouletteWheelLayout(specieFitnessArr);

            // Produce offspring from each specie in turn and store them in offspringList.
            List <TGenome> offspringList = new List <TGenome>(offspringCount);

            for (int specieIdx = 0; specieIdx < specieCount; specieIdx++)
            {
                SpecieStats    inst       = specieStatsArr[specieIdx];
                List <TGenome> genomeList = _specieList[specieIdx].GenomeList;

                // Get RouletteWheelLayout for genome selection.
                RouletteWheelLayout rwl = rwlArr[specieIdx];

                // --- Produce the required number of offspring from asexual reproduction.
                for (int i = 0; i < inst._offspringAsexualCount; i++)
                {
                    int     genomeIdx = RouletteWheel.SingleThrow(rwl, _rng);
                    TGenome offspring = genomeList[genomeIdx].CreateOffspring(_currentGeneration);
                    offspringList.Add(offspring);
                }
                _stats._asexualOffspringCount += (ulong)inst._offspringAsexualCount;

                // --- Produce the required number of offspring from sexual reproduction.
                // Cross-specie mating.
                // If nonZeroSpecieCount is exactly 1 then we skip inter-species mating. One is a special case because
                // for 0 the  species all get an even chance of selection, and for >1 we can just select species normally.
                int crossSpecieMatings = nonZeroSpecieCount == 1 ? 0 :
                                         (int)Utilities.ProbabilisticRound(_eaParams.InterspeciesMatingProportion
                                                                           * inst._offspringSexualCount, _rng);
                _stats._sexualOffspringCount       += (ulong)(inst._offspringSexualCount - crossSpecieMatings);
                _stats._interspeciesOffspringCount += (ulong)crossSpecieMatings;

                // An index that keeps track of how many offspring have been produced in total.
                int matingsCount = 0;
                for (; matingsCount < crossSpecieMatings; matingsCount++)
                {
                    TGenome offspring = CreateOffspring_CrossSpecieMating(rwl, rwlArr, rwlSpecies, specieIdx, genomeList);
                    offspringList.Add(offspring);
                }

                // For the remainder we use normal intra-specie mating.
                // Test for special case - we only have one genome to select from in the current specie.
                if (1 == inst._selectionSizeInt)
                {
                    // Fall-back to asexual reproduction.
                    for (; matingsCount < inst._offspringSexualCount; matingsCount++)
                    {
                        int     genomeIdx = RouletteWheel.SingleThrow(rwl, _rng);
                        TGenome offspring = genomeList[genomeIdx].CreateOffspring(_currentGeneration);
                        offspringList.Add(offspring);
                    }
                }
                else
                {
                    // Remainder of matings are normal within-specie.
                    for (; matingsCount < inst._offspringSexualCount; matingsCount++)
                    {
                        // Select parents. SelectRouletteWheelItem() guarantees parent2Idx!=parent1Idx
                        int     parent1Idx = RouletteWheel.SingleThrow(rwl, _rng);
                        TGenome parent1    = genomeList[parent1Idx];

                        // Remove selected parent from set of possible outcomes.
                        RouletteWheelLayout rwlTmp = rwl.RemoveOutcome(parent1Idx);
                        if (0.0 != rwlTmp.ProbabilitiesTotal)
                        {   // Get the two parents to mate.
                            int     parent2Idx = RouletteWheel.SingleThrow(rwlTmp, _rng);
                            TGenome parent2    = genomeList[parent2Idx];
                            TGenome offspring  = parent1.CreateOffspring(parent2, _currentGeneration);
                            offspringList.Add(offspring);
                        }
                        else
                        {   // No other parent has a non-zero selection probability (they all have zero fitness).
                            // Fall back to asexual reproduction of the single genome with a non-zero fitness.
                            TGenome offspring = parent1.CreateOffspring(_currentGeneration);
                            offspringList.Add(offspring);
                        }
                    }
                }
            }

            _stats._totalOffspringCount += (ulong)offspringCount;
            return(offspringList);
        }
        /// <summary>
        /// Calculate statistics for each specie. This method is at the heart of the evolutionary algorithm,
        /// the key things that are achieved in this method are - for each specie we calculate:
        ///  1) The target size based on fitness of the specie's member genomes.
        ///  2) The elite size based on the current size. Potentially this could be higher than the target
        ///     size, so a target size is taken to be a hard limit.
        ///  3) Following (1) and (2) we can calculate the total number offspring that need to be generated
        ///     for the current generation.
        /// </summary>
        private SpecieStats[] CalcSpecieStats(out int offspringCount)
        {
            double totalMeanFitness = 0.0;

            // Build stats array and get the mean fitness of each specie.
            int specieCount = _specieList.Count;

            SpecieStats[] specieStatsArr = new SpecieStats[specieCount];
            for (int i = 0; i < specieCount; i++)
            {
                SpecieStats inst = new SpecieStats();
                specieStatsArr[i] = inst;
                inst._meanFitness = _specieList[i].CalcMeanFitness();
                totalMeanFitness += inst._meanFitness;
            }

            // Calculate the new target size of each specie using fitness sharing.
            // Keep a total of all allocated target sizes, typically this will vary slightly from the
            // overall target population size due to rounding of each real/fractional target size.
            int totalTargetSizeInt = 0;

            if (0.0 == totalMeanFitness)
            {   // Handle specific case where all genomes/species have a zero fitness.
                // Assign all species an equal targetSize.
                double targetSizeReal = (double)_populationSize / (double)specieCount;

                for (int i = 0; i < specieCount; i++)
                {
                    SpecieStats inst = specieStatsArr[i];
                    inst._targetSizeReal = targetSizeReal;

                    // Stochastic rounding will result in equal allocation if targetSizeReal is a whole
                    // number, otherwise it will help to distribute allocations evenly.
                    inst._targetSizeInt = (int)Utilities.ProbabilisticRound(targetSizeReal, _rng);

                    // Total up discretized target sizes.
                    totalTargetSizeInt += inst._targetSizeInt;
                }
            }
            else
            {
                // The size of each specie is based on its fitness relative to the other species.
                for (int i = 0; i < specieCount; i++)
                {
                    SpecieStats inst = specieStatsArr[i];
                    inst._targetSizeReal = (inst._meanFitness / totalMeanFitness) * (double)_populationSize;

                    // Discretize targetSize (stochastic rounding).
                    inst._targetSizeInt = (int)Utilities.ProbabilisticRound(inst._targetSizeReal, _rng);

                    // Total up discretized target sizes.
                    totalTargetSizeInt += inst._targetSizeInt;
                }
            }

            // Discretized target sizes may total up to a value that is not equal to the required overall population
            // size. Here we check this and if there is a difference then we adjust the specie's targetSizeInt values
            // to compensate for the difference.
            //
            // E.g. If we are short of the required populationSize then we add the required additional allocation to
            // selected species based on the difference between each specie's targetSizeReal and targetSizeInt values.
            // What we're effectively doing here is assigning the additional required target allocation to species based
            // on their real target size in relation to their actual (integer) target size.
            // Those species that have an actual allocation below there real allocation (the difference will often
            // be a fractional amount) will be assigned extra allocation probabilistically, where the probability is
            // based on the differences between real and actual target values.
            //
            // Where the actual target allocation is higher than the required target (due to rounding up), we use the same
            // method but we adjust specie target sizes down rather than up.
            int targetSizeDeltaInt = totalTargetSizeInt - _populationSize;

            if (targetSizeDeltaInt < 0)
            {
                // Check for special case. If we are short by just 1 then increment targetSizeInt for the specie containing
                // the best genome. We always ensure that this specie has a minimum target size of 1 with a final test (below),
                // by incrementing here we avoid the probabilistic allocation below followed by a further correction if
                // the champ specie ended up with a zero target size.
                if (-1 == targetSizeDeltaInt)
                {
                    specieStatsArr[_bestSpecieIdx]._targetSizeInt++;
                }
                else
                {
                    // We are short of the required populationSize. Add the required additional allocations.
                    // Determine each specie's relative probability of receiving additional allocation.
                    double[] probabilities = new double[specieCount];
                    for (int i = 0; i < specieCount; i++)
                    {
                        SpecieStats inst = specieStatsArr[i];
                        probabilities[i] = Math.Max(0.0, inst._targetSizeReal - (double)inst._targetSizeInt);
                    }

                    // Use a built in class for choosing an item based on a list of relative probabilities.
                    RouletteWheelLayout rwl = new RouletteWheelLayout(probabilities);

                    // Probabilistically assign the required number of additional allocations.
                    // ENHANCEMENT: We can improve the allocation fairness by updating the RouletteWheelLayout
                    // after each allocation (to reflect that allocation).
                    // targetSizeDeltaInt is negative, so flip the sign for code clarity.
                    targetSizeDeltaInt *= -1;
                    for (int i = 0; i < targetSizeDeltaInt; i++)
                    {
                        int specieIdx = RouletteWheel.SingleThrow(rwl, _rng);
                        specieStatsArr[specieIdx]._targetSizeInt++;
                    }
                }
            }
            else if (targetSizeDeltaInt > 0)
            {
                // We have overshot the required populationSize. Adjust target sizes down to compensate.
                // Determine each specie's relative probability of target size downward adjustment.
                double[] probabilities = new double[specieCount];
                for (int i = 0; i < specieCount; i++)
                {
                    SpecieStats inst = specieStatsArr[i];
                    probabilities[i] = Math.Max(0.0, (double)inst._targetSizeInt - inst._targetSizeReal);
                }

                // Use a built in class for choosing an item based on a list of relative probabilities.
                RouletteWheelLayout rwl = new RouletteWheelLayout(probabilities);

                // Probabilistically decrement specie target sizes.
                // ENHANCEMENT: We can improve the selection fairness by updating the RouletteWheelLayout
                // after each decrement (to reflect that decrement).
                for (int i = 0; i < targetSizeDeltaInt;)
                {
                    int specieIdx = RouletteWheel.SingleThrow(rwl, _rng);

                    // Skip empty species. This can happen because the same species can be selected more than once.
                    if (0 != specieStatsArr[specieIdx]._targetSizeInt)
                    {
                        specieStatsArr[specieIdx]._targetSizeInt--;
                        i++;
                    }
                }
            }

            // We now have Sum(_targetSizeInt) == _populationSize.
            Debug.Assert(SumTargetSizeInt(specieStatsArr) == _populationSize);

            // TODO: Better way of ensuring champ species has non-zero target size?
            // However we need to check that the specie with the best genome has a non-zero targetSizeInt in order
            // to ensure that the best genome is preserved. A zero size may have been allocated in some pathological cases.
            if (0 == specieStatsArr[_bestSpecieIdx]._targetSizeInt)
            {
                specieStatsArr[_bestSpecieIdx]._targetSizeInt++;

                // Adjust down the target size of one of the other species to compensate.
                // Pick a specie at random (but not the champ specie). Note that this may result in a specie with a zero
                // target size, this is OK at this stage. We handle allocations of zero in PerformOneGeneration().
                int idx = RouletteWheel.SingleThrowEven(specieCount - 1, _rng);
                idx = idx == _bestSpecieIdx ? idx + 1 : idx;

                if (specieStatsArr[idx]._targetSizeInt > 0)
                {
                    specieStatsArr[idx]._targetSizeInt--;
                }
                else
                {   // Scan forward from this specie to find a suitable one.
                    bool done = false;
                    idx++;
                    for (; idx < specieCount; idx++)
                    {
                        if (idx != _bestSpecieIdx && specieStatsArr[idx]._targetSizeInt > 0)
                        {
                            specieStatsArr[idx]._targetSizeInt--;
                            done = true;
                            break;
                        }
                    }

                    // Scan forward from start of species list.
                    if (!done)
                    {
                        for (int i = 0; i < specieCount; i++)
                        {
                            if (i != _bestSpecieIdx && specieStatsArr[i]._targetSizeInt > 0)
                            {
                                specieStatsArr[i]._targetSizeInt--;
                                done = true;
                                break;
                            }
                        }
                        if (!done)
                        {
                            throw new SharpNeatException("CalcSpecieStats(). Error adjusting target population size down. Is the population size less than or equal to the number of species?");
                        }
                    }
                }
            }

            // Now determine the eliteSize for each specie. This is the number of genomes that will remain in a
            // specie from the current generation and is a proportion of the specie's current size.
            // Also here we calculate the total number of offspring that will need to be generated.
            offspringCount = 0;
            for (int i = 0; i < specieCount; i++)
            {
                // Special case - zero target size.
                if (0 == specieStatsArr[i]._targetSizeInt)
                {
                    specieStatsArr[i]._eliteSizeInt = 0;
                    continue;
                }

                // Discretize the real size with a probabilistic handling of the fractional part.
                double eliteSizeReal = _specieList[i].GenomeList.Count * _eaParams.ElitismProportion;
                int    eliteSizeInt  = (int)Utilities.ProbabilisticRound(eliteSizeReal, _rng);

                // Ensure eliteSizeInt is no larger than the current target size (remember it was calculated
                // against the current size of the specie not its new target size).
                SpecieStats inst = specieStatsArr[i];
                inst._eliteSizeInt = Math.Min(eliteSizeInt, inst._targetSizeInt);

                // Ensure the champ specie preserves the champ genome. We do this even if the targetsize is just 1
                // - which means the champ genome will remain and no offspring will be produced from it, apart from
                // the (usually small) chance of a cross-species mating.
                if (i == _bestSpecieIdx && inst._eliteSizeInt == 0)
                {
                    Debug.Assert(inst._targetSizeInt != 0, "Zero target size assigned to champ specie.");
                    inst._eliteSizeInt = 1;
                }

                // Now we can determine how many offspring to produce for the specie.
                inst._offspringCount = inst._targetSizeInt - inst._eliteSizeInt;
                offspringCount      += inst._offspringCount;

                // While we're here we determine the split between asexual and sexual reproduction. Again using
                // some probabilistic logic to compensate for any rounding bias.
                double offspringAsexualCountReal = (double)inst._offspringCount * _eaParams.OffspringAsexualProportion;
                inst._offspringAsexualCount = (int)Utilities.ProbabilisticRound(offspringAsexualCountReal, _rng);
                inst._offspringSexualCount  = inst._offspringCount - inst._offspringAsexualCount;

                // Also while we're here we calculate the selectionSize. The number of the specie's fittest genomes
                // that are selected from to create offspring. This should always be at least 1.
                double selectionSizeReal = _specieList[i].GenomeList.Count * _eaParams.SelectionProportion;
                inst._selectionSizeInt = Math.Max(1, (int)Utilities.ProbabilisticRound(selectionSizeReal, _rng));
            }

            return(specieStatsArr);
        }
예제 #31
0
 static public Roulette <T> Deconstruct <T>(RouletteWheel <T> item)
 {
     return(item.GetRoulette());
 }