Esempio n. 1
0
        private void SwapGenes(Chromosome childToMutate)
        {
            CrossoverData data = CreateCrossoverData(childToMutate.Genes.Count);

            for (int i = 0; i < Interval; i++)
            {
                Gene g1 = childToMutate.Genes[data.Points[0] + i];
                Gene g2 = childToMutate.Genes[data.Points[1] + i];

                childToMutate.Genes[data.Points[0] + i] = g2;
                childToMutate.Genes[data.Points[1] + i] = g1;
            }
        }
Esempio n. 2
0
        //handles the crossover procedure, taking into account the crossover probability. uses random selection? roulette wheel selection?
        protected void Process()
        {
            int num1 = 100;
            int num2 = 0;

            this._evaluations = 0;
            if (this._replacementMethodS == ReplacementMethod.DeleteLast)
            {
                this._newPopulation.Solutions.Clear();
                this._newPopulation.Solutions.AddRange((IEnumerable <Chromosome>) this._currentPopulation.Solutions);
            }
            else
            {
                List <Chromosome> elites = this._currentPopulation.GetElites();
                num2 = Enumerable.Count <Chromosome>((IEnumerable <Chromosome>)elites);
                if (elites != null && num2 > 0)
                {
                    this._newPopulation.Solutions.AddRange((IEnumerable <Chromosome>)elites);
                }
            }
            this._currentPopulationSize      = this._currentPopulation.Solutions.Count;
            this._numberOfChildrenToGenerate = this._currentPopulationSize - num2;
            while (this._numberOfChildrenToGenerate > 0)
            {
                --num1;
                if (num1 <= 0)
                {
                    break;
                }
                Chromosome        c1              = (Chromosome)null;
                Chromosome        c2              = (Chromosome)null;
                List <Chromosome> list            = this._currentPopulation.SelectParents();
                Chromosome        p1              = list[0];
                Chromosome        p2              = list[1];
                CrossoverData     crossoverData   = this.CreateCrossoverData(p1.Genes.Count, this.CrossoverShape);
                CrossoverData     crossoverResult = this.PerformCrossover(p1, p2, this.CrossoverProbability, this.CrossoverShape, crossoverData, out c1, out c2);
                if (this.OnCrossoverComplete != null)
                {
                    this.OnCrossoverComplete((object)this, new CrossoverEventArgs(crossoverResult));
                }
                if (this.AddChild(c1))
                {
                    --this._numberOfChildrenToGenerate;
                }
                if (this._numberOfChildrenToGenerate > 0 && this.AddChild(c2))
                {
                    --this._numberOfChildrenToGenerate;
                }
            }
        }
Esempio n. 3
0
        internal CrossoverData CreateCrossoverData(int chromosomeLength)
        {
            var result = new CrossoverData();

            int point1;
            int point2;

            do
            {
                point2 = RandomProvider.GetThreadRandom().Next(1, chromosomeLength / Interval) * Interval;
                point1 = RandomProvider.GetThreadRandom().Next(1, chromosomeLength / Interval) * Interval;
            } while (point2 == point1);

            result.Points.Add(System.Math.Min(point2, point1));
            result.Points.Add(System.Math.Max(point2, point1));

            return(result);
        }
Esempio n. 4
0
        internal CrossoverData CreateCrossoverData(int chromosomeLength, CrossoverType crossoverType)
        {
            var result = new CrossoverData();

            //this is like double point except that the values are all taken from one parent
            //first the centre section of the parent selection is taken to the child
            //the remaining values of the same parent are passed to the child in the order in
            //which they appear in the second parent. If the second parent does not include the value
            //an exception is thrown.

            //these can bring back the same number, this is ok as the values will be both inclusive
            //so if crossoverPoint1 and crossoverPoint2 are the same, one gene will form the center section.
            switch (crossoverType)
            {
            case CrossoverType.SinglePoint:
                //0 is invalid, range for single point is 1 to [length]
                result.Points.Add(RandomProvider.GetThreadRandom().Next(1, chromosomeLength / Index) * Index);
                break;

            case CrossoverType.DoublePoint:
            case CrossoverType.DoublePointOrdered:
                //0 is invalid, range for double needs to leave room for right segment and is 1 to [length]

                int point1;
                int point2;
                do
                {
                    point2 = RandomProvider.GetThreadRandom().Next(1, chromosomeLength / Index) * Index;
                    point1 = RandomProvider.GetThreadRandom().Next(1, chromosomeLength / Index) * Index;
                } while (point2 == point1);

                result.Points.Add(System.Math.Min(point2, point1));
                result.Points.Add(System.Math.Max(point2, point1));

                break;
            }

            return(result);
        }
Esempio n. 5
0
        internal CrossoverData PerformCrossover(Chromosome p1, Chromosome p2, double crossoverProbability, Crossover2DShape crossoverShape, CrossoverData crossoverData, out Chromosome c1, out Chromosome c2)
        {
            CrossoverData crossoverData1 = new CrossoverData();
            int           count1         = p1.Genes.Count;

            if (count1 != p2.Genes.Count)
            {
                throw new ArgumentException("Parent chromosomes are not the same length.");
            }
            if (crossoverData == null)
            {
                throw new ArgumentException("The CrossoverData parameter is null.");
            }
            List <Gene> source1 = ListClone(p1.Genes); // new List<Gene>();
            List <Gene> source2 = ListClone(p2.Genes); // new List<Gene>();

            if (RandomProvider.GetThreadRandom().NextDouble() <= crossoverProbability)
            {
                //iterate all the replacement points
                foreach (int point in crossoverData.Points)
                {
                    var tmpG = source1[point].DeepClone();
                    source1[point] = source2[point].DeepClone();
                    source2[point] = tmpG;
                }

                //APIClass.CountNeighbours(source1);
                //APIClass.CountNeighbours(source2);
            }

            if (source1.Count != count1 || source1.Count != count1)
            {
                throw new ChromosomeCorruptException("Chromosome is corrupt!");
            }
            c1 = new Chromosome((IEnumerable <Gene>)source1);
            c2 = new Chromosome((IEnumerable <Gene>)source2);
            return(crossoverData1);
        }
Esempio n. 6
0
        /// <summary>
        /// Crossover data represents the points (int) where the crossover will be performed, in this case, we want to switch several points between parents
        /// </summary>
        /// <param name="chromosomeLength"></param>
        /// <param name="crossoverShape"></param>
        /// <returns></returns>
        internal CrossoverData CreateCrossoverData(int chromosomeLength, Crossover2DShape crossoverShape)
        {
            CrossoverData crossoverData = new CrossoverData();

            switch (crossoverShape)
            {
            case Crossover2DShape.TwoByTwoSquare:
            {
                int rx, ry;
                //do
                //{
                rx = RandomProvider.GetThreadRandom().Next(0, MAP_WIDTH - 1 - 2);
                ry = RandomProvider.GetThreadRandom().Next(0, MAP_HEIGHT - 1 - 2);
                //}
                //while (rx > 30 || ry > 30);

                for (int yOffset = 0; yOffset < 2; yOffset++)
                {
                    for (int xOffset = 0; xOffset < 2; xOffset++)
                    {
                        crossoverData.Points.Add((MAP_HEIGHT * (ry + yOffset) + (rx + xOffset)));
                    }
                }
            }
            break;

            case Crossover2DShape.ThreeByThreeSquare:
            {
                int rx, ry;
                //do
                //{
                rx = RandomProvider.GetThreadRandom().Next(0, MAP_WIDTH - 1 - 3);
                ry = RandomProvider.GetThreadRandom().Next(0, MAP_HEIGHT - 1 - 3);
                //}
                //while (rx > 29 || ry > 29);

                for (int yOffset = 0; yOffset < 3; yOffset++)
                {
                    for (int xOffset = 0; xOffset < 3; xOffset++)
                    {
                        crossoverData.Points.Add((MAP_HEIGHT * (ry + yOffset) + (rx + xOffset)));
                    }
                }
            }
            break;

            case Crossover2DShape.FourByFourSquare:
            {
                int rx, ry;
                //do
                //{
                rx = RandomProvider.GetThreadRandom().Next(0, MAP_WIDTH - 1 - 4);
                ry = RandomProvider.GetThreadRandom().Next(0, MAP_HEIGHT - 1 - 4);
                //}
                //while (rx > 28 || ry > 28);

                for (int yOffset = 0; yOffset < 4; yOffset++)
                {
                    for (int xOffset = 0; xOffset < 4; xOffset++)
                    {
                        crossoverData.Points.Add((MAP_HEIGHT * (ry + yOffset) + (rx + xOffset)));
                    }
                }
            }
            break;

            case Crossover2DShape.FourByFourCircle:
            {
                int rx, ry;
                do
                {
                    rx = RandomProvider.GetThreadRandom().Next(0, MAP_WIDTH - 1);
                    ry = RandomProvider.GetThreadRandom().Next(1, MAP_HEIGHT - 1);
                }while (rx > 28 || ry > 28);

                for (int yOffset = 0; yOffset < 4; yOffset++)
                {
                    for (int xOffset = 0; xOffset < 4; xOffset++)
                    {
                        if ((yOffset == 0 && xOffset == 0) || (yOffset == 0 && xOffset == 3) || (yOffset == 3 && xOffset == 0) || (yOffset == 3 && xOffset == 3))
                        {
                            continue;
                        }
                        else
                        {
                            crossoverData.Points.Add((MAP_HEIGHT * (ry + yOffset) + (rx + xOffset)));
                        }
                    }
                }
            }
            break;

            case Crossover2DShape.Triangle:     //size??

                break;

            case Crossover2DShape.Dispersion:

                break;

            default:
            {
                int rx, ry;
                //do
                //{
                rx = RandomProvider.GetThreadRandom().Next(0, MAP_WIDTH - 1 - 4);
                ry = RandomProvider.GetThreadRandom().Next(0, MAP_HEIGHT - 1 - 4);
                //}
                //while (rx > 28 || ry > 28);

                for (int yOffset = 0; yOffset < 4; yOffset++)
                {
                    for (int xOffset = 0; xOffset < 4; xOffset++)
                    {
                        crossoverData.Points.Add((MAP_HEIGHT * (ry + yOffset) + (rx + xOffset)));
                    }
                }
            }
            break;
            }


            return(crossoverData);
        }
Esempio n. 7
0
        internal CrossoverData PerformCrossover(Chromosome p1, Chromosome p2, double crossoverProbability, CrossoverType crossoverType, CrossoverData crossoverData, out Chromosome c1, out Chromosome c2)
        {
            var result           = new CrossoverData();
            var chromosomeLength = p1.Genes.Count;

            if (chromosomeLength != p2.Genes.Count)
            {
                throw new ArgumentException("Parent chromosomes are not the same length.");
            }

            if (crossoverData == null)
            {
                throw new ArgumentException("The CrossoverData parameter is null.");
            }

            List <Gene> cg1 = new List <Gene>();
            List <Gene> cg2 = new List <Gene>();

            //check probability by generating a random number between zero and one and if
            //this number is less than or equal to the given crossover probability
            //then crossover takes place."
            var rd = RandomProvider.GetThreadRandom().NextDouble();

            if (rd <= crossoverProbability)
            {
                switch (crossoverType)
                {
                case CrossoverType.SinglePoint:
                {
                    if (crossoverData.Points == null || crossoverData.Points.Count < 1)
                    {
                        throw new ArgumentException(
                                  "The CrossoverData.Points property is either null or is missing the required crossover points.");
                    }

                    var crossoverPoint1 = crossoverData.Points[0];
                    result.Points.Add(crossoverPoint1);

                    //create the two children
                    cg1.AddRangeCloned(p1.Genes.Take(crossoverPoint1).ToList());
                    //cg1.AddRange(p2.Genes.Skip(crossoverPoint1).Take(chromosomeLength - crossoverPoint1));
                    cg1.AddRangeCloned(p2.Genes.Skip(crossoverPoint1).Take(chromosomeLength - crossoverPoint1));

                    cg2.AddRangeCloned(p2.Genes.Take(crossoverPoint1).ToList());
                    cg2.AddRangeCloned(p1.Genes.Skip(crossoverPoint1).Take(chromosomeLength - crossoverPoint1));

                    break;
                }

                case CrossoverType.DoublePoint:
                {
                    if (crossoverData.Points == null || crossoverData.Points.Count < 2)
                    {
                        throw new ArgumentException(
                                  "The CrossoverData.Points property is either null or is missing the required crossover points.");
                    }

                    var firstPoint  = crossoverData.Points[0];
                    var secondPoint = crossoverData.Points[1];

                    result.Points.Add(firstPoint);
                    result.Points.Add(secondPoint);

                    //first child
                    //first part of Parent 1
                    cg1.AddRangeCloned(p1.Genes.Take(firstPoint).ToList());
                    //middle part pf Parent 2
                    cg1.AddRangeCloned(p2.Genes.Skip(firstPoint).Take(secondPoint - firstPoint));
                    //last part of Parent 1
                    cg1.AddRangeCloned(p1.Genes.Skip(secondPoint).Take(chromosomeLength - secondPoint));

                    //second child
                    //first part of Parent 2
                    cg2.AddRangeCloned(p2.Genes.Take(firstPoint).ToList());
                    //middle part pf Parent 1
                    cg2.AddRangeCloned(p1.Genes.Skip(firstPoint).Take(secondPoint - firstPoint));
                    //last part of Parent 2
                    cg2.AddRangeCloned(p2.Genes.Skip(secondPoint).Take(chromosomeLength - secondPoint));

                    break;
                }

                case CrossoverType.DoublePointOrdered:
                {
                    if (crossoverData.Points == null || crossoverData.Points.Count < 2)
                    {
                        throw new ArgumentException(
                                  "The CrossoverData.Points property is either null or is missing the required crossover points.");
                    }

                    //this is like double point except that the values are all taken from one parent
                    //first the centre section of the parent selection is taken to the child
                    //the remaining values of the same parent are passed to the child in the order in
                    //which they appear in the second parent. If the second parent does not include the value
                    //an exception is thrown.

                    //these can bring back the same number, this is ok as the values will be both inclusive
                    //so if crossoverPoint1 and crossoverPoint2 are the same, one gene will form the center section.
                    var firstPoint  = crossoverData.Points[0];
                    var secondPoint = crossoverData.Points[1];

                    result.Points.Add(firstPoint);
                    result.Points.Add(secondPoint);

                    //pass the middle part of Parent 1 to child 1
                    cg1.AddRangeCloned(p1.Genes.Skip(firstPoint).Take(secondPoint - firstPoint));         //+1 make this exclusive e.g. 4-6 include 3 genes.

                    //pass the middle part of Parent 2 to child 2
                    cg2.AddRangeCloned(p2.Genes.Skip(firstPoint).Take(secondPoint - firstPoint));

                    //create hash sets for parent1 and child1
                    var p1Hash  = new HashSet <object>();
                    var cg1Hash = new HashSet <object>();

                    //populate the parent hash set with object values (not the gene itself)
                    foreach (var gene in p1.Genes)
                    {
                        p1Hash.Add(gene.ObjectValue);
                    }

                    //populate the child hash set with object values (not the gene itself)
                    //at this point only the center section of P1 will be in C1
                    foreach (var gene in cg1)
                    {
                        cg1Hash.Add(gene.ObjectValue);
                    }

                    //run through the P2 adding to C1 those that exist in P1 but not yet in C1
                    //add them in the order found in P2. This has to be done by value as the first parent
                    //is used but the order id determined by the second parent. Can't use Guid as the second
                    //parent has a different set of genes guids.
                    foreach (var gene in p2.Genes)
                    {
                        //if we have the value in P1 and it is not already in C1, then add it.
                        bool existsInP1  = p1Hash.Contains(gene.ObjectValue);
                        bool existsInCg1 = cg1Hash.Contains(gene.ObjectValue);

                        if (existsInP1 && !existsInCg1)
                        {
                            cg1.AddCloned(gene);
                        }
                    }

                    var p2Hash  = new HashSet <object>();
                    var cg2Hash = new HashSet <object>();

                    foreach (var gene in p2.Genes)
                    {
                        p2Hash.Add(gene.ObjectValue);
                    }

                    foreach (var gene in cg2)
                    {
                        cg2Hash.Add(gene.ObjectValue);
                    }


                    //run through the P1 adding to C2 those that exist in P2 but not yet in C2
                    //add them in the order found in P1. This has to be done by value as the first parent
                    //is used but the order id determined by the second parent. Can't use Guid as the second
                    //parent has a different set of genes (guids)
                    foreach (var gene in p1.Genes)
                    {
                        //if we have the value in P1 and it is not already in C1, then add it.
                        bool existsInP2  = p2Hash.Contains(gene.ObjectValue);
                        bool existsInCg2 = cg2Hash.Contains(gene.ObjectValue);

                        if (existsInP2 && !existsInCg2)
                        {
                            cg2.AddCloned(gene);
                        }
                    }

                    //if at this point we do not have a complete child, raise an exception
                    if (cg1.Count != p1.Count || cg2.Count != p2.Count)
                    {
                        throw new CrossoverTypeIncompatibleException("The parent Chromosomes were not suitable for Ordered Crossover as they do not contain the same set of values. Consider using a different crossover type, or ensure all solutions are build with the same set of values.");
                    }

                    break;
                }
                }
            }
            else
            {
                //crossover probaility dictates that these pass through to the next generation untouched (except for an ID change.
                //get the existing parent genes and treat them as the new children
                cg1.AddRangeCloned(p1.Genes);
                cg2.AddRangeCloned(p2.Genes);
            }

            if (cg1.Count != chromosomeLength || cg1.Count != chromosomeLength)
            {
                throw new ChromosomeCorruptException("Chromosome is corrupt!");
            }
            c1 = new Chromosome(cg1);
            c2 = new Chromosome(cg2);

            return(result);
        }