/// <summary> /// Generate an initial population of individuals /// </summary> /// <param name="individuals">An empty list to populate with the individuals</param> public void Populate(ArrayList individuals) { while (individuals.Count < populationSize) { RoadNetwork network = new RoadNetwork(map); int startIndex = network.AddVertexUnique(map.Start); int endIndex = network.AddVertexUnique(map.End); Vertex start = network.GetVertex(startIndex); Vertex end = network.GetVertex(endIndex); int nPaths = random.Next(10); for (int i = 0; i < nPaths; i++) { int midpointIndex = network.AddVertexUnique(random.Next(map.Width), random.Next(map.Height)); Vertex midpoint = network.GetVertex(midpointIndex); StepMutator.StepPath(network, start, midpoint); StepMutator.StepPath(network, midpoint, end); } int nCross = random.Next(10); for (int i = 0; i < nCross; i++) { Vertex startPoint = network.GetVertex(random.Next(network.VertexCount)); Vertex endPoint = network.GetVertex(random.Next(network.VertexCount)); StepMutator.StepPath(network, startPoint, endPoint); } network.SetEnd(endIndex); individuals.Add(network); } }
/// <summary> /// Generate an initial population of individuals /// </summary> /// <param name="individuals">An empty list to populate with the individuals</param> public void Populate(ArrayList individuals) { RoadNetwork original = new RoadNetwork(map); int startIndex = original.AddVertexUnique(map.Start); int endIndex = original.AddVertexUnique(map.End); Vertex start = original.GetVertex(startIndex); Vertex end = original.GetVertex(endIndex); StepMutator.StepPath(original, start, end); original.SetEnd(endIndex); individuals.Add(original); while (individuals.Count < populationSize) { individuals.Add(StepMutator.Mutate((RoadNetwork)individuals[random.Next(individuals.Count)])); } }
/// <summary> /// Make a path between two vertices in a RoadNetwork out of a number of edges connecting adjacent points. /// </summary> /// <param name="network">The RoadNetwork to make the path in</param> /// <param name="start">The start Vertex of the path</param> /// <param name="end">The end Vertex of the path</param> public static void StepPath(RoadNetwork network, Vertex start, Vertex end) { int dX = end.Coordinates.X - start.Coordinates.X; int dY = end.Coordinates.Y - start.Coordinates.Y; int xStep = 1; if (dX < 0) { dX = -dX; xStep = -1; } int yStep = 1; if (dY < 0) { dY = -dY; yStep = -1; } int x = start.Coordinates.X; int y = start.Coordinates.Y; Vertex startVertex = start; while (dX > 1 || dY > 1) { if (dX > dY) { x += xStep; dX--; } else if (dY > dX) { y += yStep; dY--; } else { x += xStep; dX--; y += yStep; dY--; } int index = network.AddVertexUnique(x, y); Vertex endVertex = network.GetVertex(index); network.AddEdge(startVertex, endVertex); startVertex = endVertex; } network.AddEdge(startVertex, end); }
/// <summary> /// Randomly alter a RoadNetwork to Produce a slightly different RoadNetwork /// </summary> /// <param name="source">The RoadNetwork to mutate</param> /// <returns>The mutated RoadNetwork</returns> public static RoadNetwork Mutate(RoadNetwork source) { Map map = source.Map; int mapWidth = map.Width; int mapHeight = map.Height; int maxXChange = 1 + mapWidth / 10; int maxYChange = 1 + mapHeight / 10; source.ClearCopies(); source.SetVisited(false); source.SetBroken(true); RoadNetwork destination = new RoadNetwork(map); int endVertexIndex = -1; LinkedList<Vertex> vertexStack = new LinkedList<Vertex>(); source.Start.Visited = true; vertexStack.AddFirst(source.Start); while (vertexStack.Count > 0) { Vertex vertex = vertexStack.First(); vertexStack.RemoveFirst(); List<Vertex> nextVertices = new List<Vertex>(); for (int i = 0; i < vertex.EdgeCount; i++) { Edge edge = vertex.GetEdge(i); Vertex nextVertex = edge.End; if (!nextVertex.Visited) { edge.Broken = false; nextVertex.Visited = true; nextVertices.Add(nextVertex); } } //If this vertex is a leaf of the tree and not the end vertex it has a 25% chance of //begin removed. if (nextVertices.Count > 0 || vertex == source.End || random.Next(4) > 0) { Coordinates coordinates = vertex.Coordinates; if (vertex != source.Start && vertex != source.End && random.Next(4) == 0) { coordinates = RandomAdjacentPoint(vertex.Coordinates); } int index = destination.AddVertexUnique(vertex.Coordinates); vertex.Copy = destination.GetVertex(index); if (vertex == source.End) { endVertexIndex = index; } } //Shuffle Vertices for (int n = nextVertices.Count - 1; n > 0; n--) { int m = random.Next(n + 1); Vertex temp = nextVertices[m]; nextVertices[m] = nextVertices[n]; nextVertices[n] = temp; } //Push vertices onto stack in shiffled order. foreach (Vertex nextVertex in nextVertices) { vertexStack.AddFirst(nextVertex); } } for (int i = 0; i < source.EdgeCount; i++) { Edge edge = source.GetEdge(i); if ((!edge.Broken || random.Next(4) > 0) && edge.Start.Copy != null && edge.End.Copy != null) { StepPath(destination, edge.Start.Copy, edge.End.Copy); } } int newVertices = random.Next(20); for (int i = 0; i < newVertices; i++) { Vertex startVertex = destination.GetVertex(random.Next(destination.VertexCount)); int index = destination.AddVertexUnique(RandomAdjacentPoint(startVertex.Coordinates)); Vertex endVertex = destination.GetVertex(index); destination.AddEdge(startVertex, endVertex); } if (endVertexIndex == -1) { throw new Exception("End vertex not found."); } else { destination.SetEnd(endVertexIndex); } return destination; }