/// <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); }
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"); }