public void Mutation(Solution solution, ISolutionInitializer initializer) { if (RandomMutationChance > RandomGenerator.NextDouble()) { _randomMutation.Mutation(solution, initializer); } else { _shiftMutation.Mutation(solution, initializer); } }
public void Mutation(Solution solution, ISolutionInitializer initializer) { if (AlphaMutationChance > RandomGenerator.NextDouble()) { _mutationAlpha.Mutation(solution, initializer); } else { _mutationBeta.Mutation(solution, initializer); } }
public void Mutation(Solution solution, ISolutionInitializer initializer) { var path = solution.Paths[RandomGenerator.Next(solution.Paths.Length)]; var segments = path.Segments; var index = RandomGenerator.Next(segments.Count); // pick segment var startPoint = segments[index].StartPoint; var endPoint = segments[index].EndPoint; // remove original segment segments.RemoveAt(index); // create new random sub-path var h = solution.Problem.BoardHeight; var w = solution.Problem.BoardWidth; var tmpProblem = new PcbProblem(w, h, new List <(Point startPoint, Point endPoint)>() { (startPoint, endPoint) }); var newSegments = initializer.GeneratePath(tmpProblem, 0).Segments; // insert new sub-path in place of old one segments.InsertRange(index, newSegments); var lastIndex = index + newSegments.Count; // merge segments if in the same direction if (index - 1 >= 0 && segments[index - 1].Direction == segments[index].Direction) { segments[index - 1].Length += segments[index].Length; segments.RemoveAt(index); lastIndex--; } if (lastIndex + 1 >= segments.Count || segments[lastIndex].Direction != segments[lastIndex + 1].Direction) { return; } segments[lastIndex].Length += segments[lastIndex + 1].Length; segments.RemoveAt(lastIndex + 1); }
public Experiment UseInitializer(ISolutionInitializer solutionInitializer) { this.Initializer = solutionInitializer; return(this); }
public void Mutation(Solution solution, ISolutionInitializer initializer) { solution.ResetSolution(initializer); }
public void Mutation(Solution solution, ISolutionInitializer initializer) { // select random segment var path = solution.Paths[RandomGenerator.Next(solution.Paths.Length)]; var index = RandomGenerator.Next(path.Segments.Count); var segment = path.Segments[index]; // random draw new segment length var len = RandomGenerator.Next(1, segment.Length); // calculate offset var offset = RandomGenerator.Next(0, (segment.Length - len) + 1); // split selected segment var(sx, sy) = segment.StartPoint; var(dx, dy) = segment.Direction.CoefficientTuple(); var start = new Point(sx + dx * offset, sy + dy * offset); var end = new Point(start.X + len * dx, start.Y + len * dy); var pointsQuery = new[] { segment.StartPoint, segment.EndPoint, start, end }.Distinct(); Point[] points; if (segment.Direction.GeneralDirection() == Direction.Vertical) { points = segment.Direction == Direction.Up ? pointsQuery.OrderByDescending(p => p.Y).ToArray() : pointsQuery.OrderBy(p => p.Y).ToArray(); } else { points = segment.Direction == Direction.Left ? pointsQuery.OrderByDescending(p => p.X).ToArray() : pointsQuery.OrderBy(p => p.X).ToArray(); } // create new tmp solution with start and end in selected segment var splitSegments = new List <Segment>(); Segment modifiedSegment = null; var modifiedIndex = 0; for (var i = 0; i < points.Length - 1; i++) { var tmp = new Segment(points[i], segment.Direction, (int)Point.Distance(points[i], points[i + 1])); if (tmp.StartPoint == start) { modifiedSegment = tmp; modifiedIndex = i; } splitSegments.Add(tmp); } // apply shiftMutationAlpha to tmp solution var tmpPath = new Path(start, end); tmpPath.Segments.Add(modifiedSegment?.Clone()); var tmpSol = new Solution(solution.Problem, new Path[] { tmpPath }); _mutationAlpha.Mutation(tmpSol, initializer); // append path of tmp solution splitSegments.InsertRange(modifiedIndex, tmpPath.Segments); splitSegments.RemoveAt(modifiedIndex + tmpPath.Segments.Count); path.Segments.InsertRange(index, splitSegments); path.Segments.RemoveAt(index + splitSegments.Count); // fix overlapping neighbors // previous if (index - 1 > 0) { var prev = path.Segments[index - 1]; if (prev.Direction.OppositeDirection() == path.Segments[index].Direction) { var tmpLen = prev.Length - path.Segments[index].Length; switch (tmpLen) { case > 0: prev.Length = tmpLen; path.Segments.RemoveAt(index); --index; break; case 0: path.Segments.RemoveAt(index - 1); path.Segments.RemoveAt(index - 1); index -= 2; break; default: prev.Length = -tmpLen; prev.Direction = prev.Direction.OppositeDirection(); path.Segments.RemoveAt(index); --index; break; } } } // next if (index + splitSegments.Count < path.Segments.Count) { var testedIndex = index + splitSegments.Count - 1; var next = path.Segments[index + splitSegments.Count]; if (next.Direction.OppositeDirection() == path.Segments[testedIndex].Direction) { var tmpLen = next.Length - path.Segments[testedIndex].Length; switch (tmpLen) { case > 0: next.Length = tmpLen; next.StartPoint = path.Segments[testedIndex].StartPoint; path.Segments.RemoveAt(testedIndex); break; case 0: path.Segments.RemoveAt(testedIndex); path.Segments.RemoveAt(testedIndex); break; default: next.Length = -tmpLen; next.Direction = next.Direction.OppositeDirection(); next.StartPoint = path.Segments[testedIndex].StartPoint; path.Segments.RemoveAt(testedIndex); break; } } } // repair the path ShiftMutationAlpha.RepairPath(path); }