/// <summary>
        /// Get cross combined off-spring pair
        /// </summary>
        /// <returns></returns>
        public OffSpringPair <int> GetCrossCombinedOffSpringPair(ChromosomeSegment segment, ParentPair <int> parentPair)
        {
            var parentA = GetChildCrossParent(parentPair.ParentB, parentPair.ParentA, segment);
            var parentB = GetChildCrossParent(parentPair.ParentA, parentPair.ParentB, segment);

            return(new OffSpringPair <int>(parentA, parentB));
        }
        protected virtual int[] GetChildCrossParent(int[] parentA, int[] parentB, ChromosomeSegment segment)
        {
            int[] child = new int[_number];

            int segmentLengh = segment.SegmentIndexB - segment.SegmentIndexA + 1;

            Array.Copy(parentA, segment.SegmentIndexA, child, segment.SegmentIndexA, segmentLengh);
            var segmentChildATabuList       = new HashSet <int>(child.Skip(segment.SegmentIndexA).Take(segmentLengh));
            var outerSegmentParentATabuList = new HashSet <int>(parentB.OuterSegments(segment.SegmentIndexA, segment.SegmentIndexB));

            Action <int> fillChild = (i) =>
            {
                if (!segmentChildATabuList.Contains(parentB[i]))
                {
                    child[i] = parentB[i];
                }
                else
                {
                    for (int indexFirst = 0; indexFirst < segment.SegmentIndexA; indexFirst++)
                    {
                        if (!outerSegmentParentATabuList.Contains(parentA[indexFirst]))
                        {
                            child[i] = parentA[indexFirst];
                            outerSegmentParentATabuList.Add(parentA[indexFirst]);

                            return;
                        }
                    }

                    for (int indexSecond = segment.SegmentIndexB + 1; indexSecond < _number; indexSecond++)
                    {
                        if (!outerSegmentParentATabuList.Contains(parentA[indexSecond]))
                        {
                            child[i] = parentA[indexSecond];
                            outerSegmentParentATabuList.Add(parentA[indexSecond]);

                            return;
                        }
                    }
                }
            };

            for (int index = 0; index < segment.SegmentIndexA; index++)
            {
                fillChild(index);
            }

            for (int index = segment.SegmentIndexB + 1; index < _number; index++)
            {
                fillChild(index);
            }

            return(child);
        }
Example #3
0
        public override void Start(CancellationToken token, Action <double> action)
        {
            _token = token;

            if (_config.UseBigValleySearch)
            {
                OptimizerInfo.OnNext("Starting Genetic Optimizer with Big-Valley-Search");
            }
            else
            {
                OptimizerInfo.OnNext("Starting Genetic Optimizer without Big-Valley-Search");
            }

            _action = action;
            double[] distances = new double[_population];
            MinTour = Enumerable.Range(0, _number).ToArray();
            int[,] chromosomePool = new int[_population, _number];

            SetPopulationPool(chromosomePool, distances);

            if (!token.IsCancellationRequested)
            {
                OptimizerInfo.OnNext("Starting genetic optimization");
            }

            while (!token.IsCancellationRequested)
            {
                // Forcing delay for visualization
                if (_config.UseDelay)
                {
                    Thread.Sleep(_config.DelayTime);
                }

                if (_random.NextDouble() < _rate)
                {
                    int   i, j, parent1, parent2;
                    int[] p1 = new int[_number];
                    int[] p2 = new int[_number];

                    i = _random.Next(_population);
                    j = _random.Next(_population);

                    if (distances[i] < distances[j])
                    {
                        parent1 = i;
                    }

                    else
                    {
                        parent1 = j;
                    }

                    i = _random.Next(_population);
                    j = _random.Next(_population);

                    if (distances[i] < distances[j])
                    {
                        parent2 = i;
                    }

                    else
                    {
                        parent2 = j;
                    }

                    for (i = 0; i < _number; i++)
                    {
                        p1[i] = chromosomePool[parent1, i];
                        p2[i] = chromosomePool[parent2, i];
                    }

                    int cp1 = -1, cp2 = -1;

                    do
                    {
                        cp1 = _random.Next(_number);
                        cp2 = _random.Next(_number);
                    } while (cp1 == cp2 || cp1 > cp2);

                    ChromosomeSegment segment = new ChromosomeSegment(cp1, cp2);
                    var offSpringPair         = _partiallyMappedCrossover.GetCrossCombinedOffSpringPair(segment, new ParentPair <int>(p1, p2));

                    int[] o1 = offSpringPair.ChildA;
                    int[] o2 = offSpringPair.ChildB;

                    double o1Fitness = TourDistance(o1);
                    double o2Fitness = TourDistance(o2);

                    if (o1Fitness < distances[parent1])
                    {
                        for (i = 0; i < _number; i++)
                        {
                            chromosomePool[parent1, i] = o1[i];
                        }
                    }

                    if (o2Fitness < distances[parent2])
                    {
                        for (i = 0; i < _number; i++)
                        {
                            chromosomePool[parent2, i] = o2[i];
                        }
                    }

                    for (int p = 0; p < _population; p++)
                    {
                        if (distances[p] < MinDistance)
                        {
                            MinDistance = distances[p];

                            for (int n = 0; n < _number; n++)
                            {
                                MinTour[n] = chromosomePool[p, n];
                            }
                        }
                    }
                }
                else
                {
                    int   p;
                    int[] child = new int[_number];

                    int i = _random.Next(_population);
                    int j = _random.Next(_population);

                    if (distances[i] < distances[j])
                    {
                        p = i;
                    }

                    else
                    {
                        p = j;
                    }

                    for (int n = 0; n < _number; n++)
                    {
                        child[n] = chromosomePool[p, n];
                    }


                    child = DoMutation(child);

                    double childDistance = TourDistance(child);

                    int    maxIndex    = int.MaxValue;
                    double maxDistance = double.MinValue;

                    for (int q = 0; q < _population; q++)
                    {
                        if (distances[q] >= maxDistance)
                        {
                            maxIndex    = q;
                            maxDistance = distances[q];
                        }
                    }

                    int[] index = new int[_population];
                    int   count = 0;

                    for (int q = 0; q < _population; q++)
                    {
                        if (distances[q] == maxDistance)
                        {
                            index[count++] = q;
                        }
                    }

                    maxIndex = index[_random.Next(count)];

                    if (childDistance < distances[maxIndex])
                    {
                        distances[maxIndex] = childDistance;

                        for (int n = 0; n < _number; n++)
                        {
                            chromosomePool[maxIndex, n] = child[n];
                        }

                        if (childDistance < MinDistance)
                        {
                            MinDistance = childDistance;

                            for (int n = 0; n < _number; n++)
                            {
                                MinTour[n] = child[n];
                            }
                        }
                    }
                }
            }

            _optimalSequence.OnCompleted();
            OptimizerInfo.OnNext("Genetic optimization terminated with distance: " + MinDistance.ToString() + " LU");
        }