Gene[] GetGenes(int sum, Dictionary <int, List <Gene> > proportionalPopulation)
        {
            var result = new Gene[2];

            for (int i = 0; i < 2; i++)
            {
                if (i == 0)
                {
                    result[i] = RouletteWheelSelection(sum, proportionalPopulation);
                }
                else
                {
                    result[i] = RouletteWheelSelection(sum, proportionalPopulation, result[0]);
                }
            }

            return(result);
        }
        /// <summary>
        /// Returns the offspring genes resulting from a single point crossover chosen at random
        /// </summary>
        public Gene[] SinglePointCrossover(Gene parent1, Gene parent2)
        {
            var crossoverPosition = UnityEngine.Random.Range(0, _geneSize);

            var offspring1 = new List <Action>();
            var offspring2 = new List <Action>();

            for (int chromosome = 0; chromosome < _geneSize; chromosome++)
            {
                var p1 = parent1[chromosome];
                var p2 = parent2[chromosome];

                var swap = crossoverPosition >= chromosome;
                if (swap)
                {
                    offspring2.Add(p1);
                    offspring1.Add(p2);
                }
                else
                {
                    offspring1.Add(p1);
                    offspring2.Add(p2);
                }
            }

            var child1 = new Gene(offspring1);
            var child2 = new Gene(offspring2);

            if (!child1.IsValid() || !child2.IsValid())
            {
                return(SinglePointCrossover(parent1, parent2));
            }

            return(new Gene[]
            {
                child1,
                child2
            });
        }
        /// <summary>
        /// Returns 2 offsprings using Uniform UniformCrossover, by default using 0.5 ratio
        /// </summary>
        public Gene[] UniformCrossover(Gene parent1, Gene parent2, float crossoverRatio = 0.5f)
        {
            var offspring1 = new List <Action>();
            var offspring2 = new List <Action>();

            for (int chromosome = 0; chromosome < _geneSize; chromosome++)
            {
                var p1 = parent1[chromosome];
                var p2 = parent2[chromosome];

                var swap = Utility.CheckProbability(crossoverRatio);
                if (swap)
                {
                    offspring2.Add(p1);
                    offspring1.Add(p2);
                }
                else
                {
                    offspring1.Add(p1);
                    offspring2.Add(p2);
                }
            }

            var child1 = new Gene(offspring1);
            var child2 = new Gene(offspring2);

            if (!child1.IsValid() || !child2.IsValid())
            {
                return(UniformCrossover(parent1, parent2, crossoverRatio));
            }

            return(new Gene[]
            {
                child1,
                child2
            });
        }
 protected bool Equals(Gene other)
 {
     return(FitnessValue.Equals(other.FitnessValue) && ActionsExecuted == other.ActionsExecuted);
 }
 public Gene(Gene other)
 {
     ActionsExecuted = other.ActionsExecuted;
     FitnessValue    = other.FitnessValue;
     AddRange(other.ToList());
 }
        /// <summary>
        /// Selects a gene using roulette wheel selection
        /// </summary>
        Gene RouletteWheelSelection(int sum, Dictionary <int, List <Gene> > proportionalPopulation, Gene except = null)
        {
            var roll     = Utility.GetRandomInt(0, sum);
            var previous = 0;

            foreach (var rank in proportionalPopulation)
            {
                if (roll >= previous && roll <= rank.Key + previous)
                {
                    var random = Utility.SelectRandom(rank.Value);
                    return(random.Equals(except) ? RouletteWheelSelection(sum, proportionalPopulation, except) : random);
                }
                previous += rank.Key;
            }
            return(null);
        }