static void evaluate() { XmlTextReader reader = new XmlTextReader("network.xml"); reader.MoveToContent(); RoadNetwork network = new RoadNetwork(reader); Console.WriteLine("Dimensions: " + network.Map.Width + " x " + network.Map.Height); Console.WriteLine("Start:" + network.Map.Start.X + ", " + network.Map.Start.Y); Console.WriteLine("End:" + network.Map.End.X + ", " + network.Map.End.Y); for (int i = 0; i < network.Map.TownCount; i++) { Coordinates town = network.Map.GetTown(i); Console.WriteLine("Town:" + town.X + "," + town.Y); } for (int i = 0; i < network.EdgeCount; i++) { Edge edge = network.GetEdge(i); Console.WriteLine("Edge:" + edge.Start.Coordinates.X + "," + edge.Start.Coordinates.Y + " - " + edge.End.Coordinates.X + "," + edge.End.Coordinates.Y); } IEvaluator evaluator = new Evaluator(null); uint fitness = evaluator.Evaluate(network); float v = FitnessConverter.ToFloat(fitness); Console.WriteLine("Fitness: " + fitness); Console.WriteLine("Floating Point Fitness: " + v + " " + 1 / v); }
/// <summary> /// Generate two child RoadNetworks by recombining halves of two parent RoadNetworks. /// </summary> /// <param name="parent1">The first parent RoadNetwork</param> /// <param name="parent2">The second parent RoadNetwork</param> /// <param name="child1">The first child RoadNetwork</param> /// <param name="child2">The second child RoadNetwork</param> public static void Conjugate(RoadNetwork parent1, RoadNetwork parent2, out RoadNetwork child1, out RoadNetwork child2) { Cut(parent1); Cut(parent2); List<Vertex> startVertexPartition1 = new List<Vertex>(); List<Vertex> endVertexPartition1 = new List<Vertex>(); List<Vertex> startVertexPartition2 = new List<Vertex>(); List<Vertex> endVertexPartition2 = new List<Vertex>(); List<Edge> startEdgePartition1 = new List<Edge>(); List<Edge> endEdgePartition1 = new List<Edge>(); List<Edge> startEdgePartition2 = new List<Edge>(); List<Edge> endEdgePartition2 = new List<Edge>(); List<Edge> brokenEdgePartition1 = new List<Edge>(); List<Edge> brokenEdgePartition2 = new List<Edge>(); parent1.PartitionVertices(startVertexPartition1, endVertexPartition1); parent2.PartitionVertices(startVertexPartition2, endVertexPartition2); parent1.PartitionEdges(startEdgePartition1, endEdgePartition1, brokenEdgePartition1); parent2.PartitionEdges(startEdgePartition2, endEdgePartition2, brokenEdgePartition2); child1 = new RoadNetwork(parent1.Map); child2 = new RoadNetwork(parent2.Map); child1.CopyVertices(startVertexPartition1); child1.CopyEdges(startEdgePartition1); child1.CopyVertices(endVertexPartition2); child1.CopyEdges(endEdgePartition2); child2.CopyVertices(startVertexPartition2); child2.CopyEdges(startEdgePartition2); child2.CopyVertices(endVertexPartition1); child2.CopyEdges(endEdgePartition1); ShuffleEdges(brokenEdgePartition1); ShuffleEdges(brokenEdgePartition2); int nEdges = Math.Max(brokenEdgePartition1.Count, brokenEdgePartition2.Count); for (int i = 0; i < nEdges; i++) { Vertex start1; Vertex end1; Vertex start2; Vertex end2; GetStartAndEnd(brokenEdgePartition1, i, endVertexPartition1, startVertexPartition1, out start1, out end1); GetStartAndEnd(brokenEdgePartition2, i, endVertexPartition2, startVertexPartition2, out start2, out end2); if (start1 != null && start2 != null) { child2.AddEdge(start1.Copy, end2.Copy); child1.AddEdge(start2.Copy, end1.Copy); } } }
/// <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> /// Perform mutations on the network /// </summary> /// <param name="ent">Network to mutate</param> public RoadNetwork Mutate(RoadNetwork ent) { RoadNetwork ret = new RoadNetwork(ent.Map); ent.Start.Copy = ret.AddVertex(ent.Start.Coordinates); // Copy over verticies for (int ii = 1; ii < ent.VertexCount - 1; ii++) { Vertex v = ent.GetVertex(ii); v.Copy = null; // Only move the vertex if a random number succeeds if (random.NextDouble() < chance_delete_vertex) continue; else if (random.NextDouble() < chance_move_vertex) v.Copy = MoveVertex(ret, v); else v.Copy = ret.AddVertex(v.Coordinates); } // Create some new verticies int num_new_verts = ent.EdgeCount; if (num_new_verts < min_vertex_base) num_new_verts = min_vertex_base; num_new_verts = (int)(num_new_verts * max_new_verticies * random.NextDouble()); for( int ii = 0; ii < num_new_verts; ii ++ ) { AddVertex(ret); } ent.End.Copy = ret.AddVertex(ent.End.Coordinates); // Copy over edges for (int ii = 0; ii < ent.EdgeCount; ii++) { Edge e = ent.GetEdge(ii); if (random.NextDouble() < chance_delete_edge) continue; else if (e.Start.Copy == null || e.End.Copy == null) continue; else ret.AddEdge(e.Start.Copy, e.End.Copy); } // Create some new edges int num_new_edges = ent.EdgeCount; if(num_new_edges < min_edge_base) num_new_edges = min_edge_base; num_new_edges = (int)(num_new_edges * max_new_edges * random.NextDouble()); for( int ii = 0; ii < num_new_edges; ii ++ ) { AddEdge(ret); } RepairMesh(ret); return ret; }
/// <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); original.AddEdge(original.AddVertex(map.Start), original.AddVertex(map.End)); individuals.Add(original); while (individuals.Count < populationSize) { individuals.Add(Mutator.Mutate((RoadNetwork)individuals[random.Next(individuals.Count)])); } }
/// <summary> /// Initialise an RoadNetwork with map, edges and vertices identical to another RoadNetwork /// </summary> /// <param name="network">The network to copy from</param> /// <param name="keepEdges">Copy the edges from the network</param> /// <param name="keepVertices">Copy the vertices from the network</param> public RoadNetwork(RoadNetwork network, bool keepEdges = true, bool keepVertices = true) { map = network.map; if (keepVertices) { CopyVertices(network.vertices); } if (keepEdges) { CopyEdges(network.edges); } }
/// <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)])); } }
static void mutate() { XmlTextReader reader = new XmlTextReader("network.xml"); reader.MoveToContent(); RoadNetwork network = new RoadNetwork(reader); MutationOperator mutator = new MutationOperator(null); RoadNetwork mutated = mutator.Mutate(network); XmlTextWriter writer = new XmlTextWriter("mutant.xml", Encoding.ASCII); writer.Formatting = Formatting.Indented; mutated.WriteXml(writer); writer.Flush(); writer.Close(); }
/// <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; }
/// <summary> /// Split a RoadNetwork into two paritions by repeatedly breaking one edge along /// the shortest path between the start and end until the start and end are /// no longer connected. /// </summary> /// <param name="network">The RoadNetwork to split</param> public static void Cut(RoadNetwork network) { network.SetBroken(false); List<Edge> edges; while ((edges = network.FindPath()) != null) { edges[random.Next(edges.Count)].Broken = true; } }
public void TestD5() { AllInOneOperator AIOO = new AllInOneOperator(null); AATreeGeneration generation = new AATreeGeneration(); ArrayList individuals = new ArrayList(); //Populate with identical entries. RoadNetwork theRoad; Vertex[] theVertices = new Vertex[5]; Map theMap = Map.FromFile("map.xml"); ArrayList RN = new ArrayList(); for (int i = 0; i < 10; i++) { theRoad = new RoadNetwork(theMap); RN.Add(theRoad); //RN[i] = new RoadNetwork(theMap); theVertices[0] = ((RoadNetwork)RN[i]).AddVertex(0, 0); theVertices[1] = ((RoadNetwork)RN[i]).AddVertex(10, 0); theVertices[2] = ((RoadNetwork)RN[i]).AddVertex(5, 5); theVertices[3] = ((RoadNetwork)RN[i]).AddVertex(0, 10); theVertices[4] = ((RoadNetwork)RN[i]).AddVertex(10, 10); ((RoadNetwork)RN[i]).AddEdge(theVertices[0], theVertices[1]); ((RoadNetwork)RN[i]).AddEdge(theVertices[0], theVertices[3]); ((RoadNetwork)RN[i]).AddEdge(theVertices[3], theVertices[4]); ((RoadNetwork)RN[i]).AddEdge(theVertices[1], theVertices[4]); ((RoadNetwork)RN[i]).AddEdge(theVertices[0], theVertices[2]); ((RoadNetwork)RN[i]).AddEdge(theVertices[1], theVertices[2]); ((RoadNetwork)RN[i]).AddEdge(theVertices[3], theVertices[2]); ((RoadNetwork)RN[i]).AddEdge(theVertices[4], theVertices[2]); //Add vertex and add edge generation.Insert(RN[i], 1); } AIOO.Operate(generation, individuals); //Ensure population is made up of valid roadnetworks. //Ensure all are not the same. Boolean passed = false; for (int i = 0; i < individuals.Count; i++) { for (int j = 0; j < individuals.Count; j++) { //Cross check each of the 5 vertices for (int k = 0; k < ((RoadNetwork)individuals[i]).VertexCount; k++) { for (int l = 0; l < ((RoadNetwork)individuals[j]).VertexCount; l++) { if (((RoadNetwork)individuals[i]).GetVertex(k).Coordinates.X != ((RoadNetwork)individuals[j]).GetVertex(l).Coordinates.X) { passed = true; } } } } } Assert.IsTrue(passed); }
static RoadNetwork RandomNetwork(Map map) { Random random = new Random(); RoadNetwork network = new RoadNetwork(map); network.AddVertex(map.Start); network.AddVertex(map.End); Vertex start = network.Start; Vertex end = network.End; for (int i = 0; i < 2; i++) { Vertex startPoint = start; for (int j = 0; j < 10; j++) { Vertex endPoint = network.AddVertex(random.Next(map.Width), random.Next(map.Height)); network.AddEdge(startPoint, endPoint); startPoint = endPoint; } network.AddEdge(startPoint, end); } for (int k = 0; k < 80; k++) { Vertex startPoint = network.GetVertex(random.Next(network.VertexCount)); Vertex endPoint = network.AddVertex(random.Next(map.Width), random.Next(map.Height)); network.AddEdge(startPoint, endPoint); } for (int l = 0; l < 20; l++) { Vertex startPoint = network.GetVertex(random.Next(network.VertexCount)); Vertex endPoint = network.GetVertex(random.Next(network.VertexCount)); network.AddEdge(startPoint, endPoint); } network.SetEnd(1); return network; }
private void RepairMesh(RoadNetwork network) { network.SetVisited(false); int num_unknown = network.VertexCount; LinkedList<Vertex> to_check = new LinkedList<Vertex>(); to_check.AddLast( network.Start ); while( num_unknown > 0 ) { Vertex v = null; // While there's still unchecked nodes in this group while(to_check.Count > 0) { v = to_check.First.Value; to_check.RemoveFirst(); v.Visited = true; num_unknown --; for( int i = 0; i < v.EdgeCount; i ++ ) { Vertex next = v.GetEdge(i).End; if (next.Visited) continue; to_check.AddLast(next); } } // If there are still unreached verticies, pick the first and connect if( num_unknown > 0 ) { Vertex end = null; // Find the first non-visited vertex for (int i = 0; i < network.VertexCount; i++) { if (!network.GetVertex(i).Visited) { end = network.GetVertex(i); break; } } // Make an edge from this vertex to the last checked network.AddEdge(v, end); to_check.AddLast(end); } } }
private Vertex MoveVertex(RoadNetwork network, Vertex template) { double x = (double)template.Coordinates.X * (0.5 + random.NextDouble()); double y = (double)template.Coordinates.Y * (0.5 + random.NextDouble()); // Clip values if (x >= network.Map.Width) x = network.Map.Width; if (y >= network.Map.Height) y = network.Map.Height; return network.AddVertex( new Coordinates((int)x, (int)y) ); }
private void DeleteVertex(RoadNetwork network, int VertexID) { //Vertex v = network.GetVertex(VertexID); // TODO: Need to be able to delete verticies and edges from the network }
private void AddVertex(RoadNetwork network) { Vertex prev = null; Vertex next = null; int x = (int)( random.NextDouble() * network.Map.Width ); int y = (int)( random.NextDouble() * network.Map.Height ); if (network.VertexCount >= 2) { // Create new links int prev_idx = (int)(random.NextDouble() * (network.VertexCount)); int next_idx = (int)(random.NextDouble() * (network.VertexCount - 1)); prev = network.GetVertex(prev_idx); // Get the next vertex, and make sure it's not the previous if (next_idx == prev_idx) next_idx = (next_idx + 1) % network.VertexCount; next = network.GetVertex(next_idx); } Vertex v = network.AddVertex(new Coordinates(x, y)); if(network.VertexCount >= 2) { // Create two edges for it network.AddEdge(prev, v); network.AddEdge(v, next); } }
/// <summary> /// Add a random edge to the network /// </summary> /// <param name="network"></param> /// <returns> /// False if the edge was not created (due to a collision), true if it was /// </returns> private bool AddEdge(RoadNetwork network) { // Get two verticies (-1 creates a smaller pool) int start_idx = (int)(random.NextDouble() * network.VertexCount); int end_idx = (int)(random.NextDouble() * (network.VertexCount - 1)); // Handle collision if(end_idx >= start_idx) end_idx ++; Vertex start = network.GetVertex(start_idx); Vertex end = network.GetVertex(end_idx); // Make sure this isn't making a duplicate (or reverse duplicate) for( int i = 0; i < network.EdgeCount; i ++ ) { Edge edge = network.GetEdge(i); if( edge.Start == start && edge.End == end ) return false; if( edge.End == start && edge.Start == end ) return false; } network.AddEdge(start, end); return true; }
/// <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> /// Process a Network, breaking up all edges into small steps so that edges /// only join adjacent points. /// </summary> /// <param name="network">The RoadNetwork to process</param> /// <returns>The resulting RoadNetwork</returns> public static RoadNetwork MakeStepped(RoadNetwork network) { RoadNetwork result = new RoadNetwork(network, false, true); int endVertexIndex = result.VertexCount - 1; for (int i = 0; i < network.EdgeCount; i++) { Edge edge = network.GetEdge(i); Vertex start = edge.Start.Copy; Vertex end = edge.End.Copy; Coordinates startCoordinates = start.Coordinates; Coordinates endCoordinates = end.Coordinates; int dX = endCoordinates.X - startCoordinates.X; int dY = endCoordinates.Y - startCoordinates.Y; int xStep = 1; if (dX < 0) { dX = -dX; xStep = -1; } int yStep = 1; if (dY < 0) { dY = -dY; yStep = -1; } int x = startCoordinates.X; int y = startCoordinates.Y; Vertex startPoint = 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--; } Vertex endPoint = result.AddVertex(x, y); result.AddEdge(startPoint, endPoint); startPoint = endPoint; } result.AddEdge(startPoint, end); } result.SetEnd(endVertexIndex); return result; }
static void Save() { Random random = new Random(); Map map = Map.FromFile("map.xml"); IOutputter outputter = new RoadNetworkXmlOutputter("c:\\cits3200test\\roadnetworks.xml"); outputter.OpenOutput(); for (int g = 0; g < 10; g++) { AATreeGeneration generation = new AATreeGeneration(); for (int i = 0; i < 20; i++) { RoadNetwork network = new RoadNetwork(map); for (int v = 0; v < 100; v++) { network.AddVertex(random.Next(100), random.Next(100)); } for (int e = 0; e < 1000; e++) { network.AddEdge(network.GetVertex(random.Next(100)), network.GetVertex(random.Next(100))); } generation.Insert(network, (uint)i); } outputter.OutputGeneration(generation, g); } outputter.CloseOutput(); }
public void TestF1() { RoadNetworkXmlOutputter RNO = new RoadNetworkXmlOutputter("map.xml"); Map theMap; theMap = Map.FromFile("map.xml"); Vertex[] theVertices = new Vertex[4]; RoadNetwork RN1 = new RoadNetwork(theMap); theVertices[0] = ((RoadNetwork)RN1).AddVertex(0, 0); theVertices[1] = ((RoadNetwork)RN1).AddVertex(10, 0); ((RoadNetwork)RN1).AddEdge(theVertices[0], theVertices[1]); RoadNetwork RN2 = new RoadNetwork(theMap); theVertices[2] = ((RoadNetwork)RN2).AddVertex(5, 5); theVertices[3] = ((RoadNetwork)RN2).AddVertex(10, 10); ((RoadNetwork)RN2).AddEdge(theVertices[2], theVertices[3]); AATreeGeneration generation = new AATreeGeneration(); generation.Insert(RN1, 1); generation.Insert(RN2, 2); XmlWriter writer1 = XmlWriter.Create("test1xml.xml"); XmlWriter writer2 = XmlWriter.Create("test2xml.xml"); //Output individuals/generation somehow. RN1.WriteXml(writer1); writer1.Close(); RN2.WriteXml(writer2); writer2.Close(); XmlTextReader reader1 = new XmlTextReader("test1xml.xml"); XmlTextReader reader2= new XmlTextReader("test2xml.xml"); RoadNetworkReader rnr = new RoadNetworkReader(); RoadNetwork RNL1 = (RoadNetwork)rnr.ReadIndividual(reader1); RoadNetwork RNL2 = (RoadNetwork)rnr.ReadIndividual(reader2); Assert.AreEqual(RNL1.GetVertex(0).Coordinates.X, 0); Assert.AreEqual(RNL1.GetVertex(0).Coordinates.Y, 0); Assert.AreEqual(RNL1.GetVertex(1).Coordinates.X, 10); Assert.AreEqual(RNL1.GetVertex(1).Coordinates.Y, 0); Assert.AreEqual(RNL2.GetVertex(0).Coordinates.X, 5); Assert.AreEqual(RNL2.GetVertex(0).Coordinates.Y, 5); Assert.AreEqual(RNL2.GetVertex(1).Coordinates.X, 10); Assert.AreEqual(RNL2.GetVertex(1).Coordinates.Y, 10); Assert.AreEqual(RNL1.GetEdge(0).Start.Coordinates.X, 0); Assert.AreEqual(RNL1.GetEdge(0).Start.Coordinates.Y, 0); Assert.AreEqual(RNL1.GetEdge(0).End.Coordinates.X, 10); Assert.AreEqual(RNL1.GetEdge(0).End.Coordinates.Y, 0); Assert.AreEqual(RNL2.GetEdge(0).Start.Coordinates.X, 5); Assert.AreEqual(RNL2.GetEdge(0).Start.Coordinates.Y, 5); Assert.AreEqual(RNL2.GetEdge(0).End.Coordinates.X, 10); Assert.AreEqual(RNL2.GetEdge(0).End.Coordinates.Y, 10); }
/// <summary> /// Initialise a new Vertex /// </summary> /// <param name="network">The RoadNetwork this Vertex belongs to.</param> /// <param name="coordinates">The location of the Vertex.</param> public Vertex(RoadNetwork network, Coordinates coordinates) { this.network = network; this.coordinates = coordinates; this.edges = new List<Edge>(); }
/// <summary> /// Determine if this Vertex belongs to a certain RoadNetwork /// </summary> /// <param name="network">The RoadNetwork to test</param> /// <returns>True iff this vertex belongs to network</returns> public bool BelongsToNetwork(RoadNetwork network) { return this.network == network; }
/// <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) { if (vertex == source.End) { endVertexIndex = destination.VertexCount; } if (vertex == source.Start || vertex == source.End || random.Next(10) > 0) { destination.CopyVertex(vertex); } else { int x = vertex.Coordinates.X + random.Next(2 * maxXChange+1) - maxXChange; int y = vertex.Coordinates.Y + random.Next(2 * maxYChange + 1) - maxYChange; x = Math.Max(0, Math.Min(x, map.Width - 1)); y = Math.Max(0, Math.Min(y, map.Height - 1)); vertex.Copy = destination.AddVertex(x, y); } } //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) { destination.CopyEdge(edge); } } int verticesToAdd = random.Next(10); for (int i = 0; i < verticesToAdd; i++) { Vertex startVertex = destination.GetVertex(random.Next(destination.VertexCount)); Vertex endVertex = destination.AddVertex(random.Next(mapWidth), random.Next(mapHeight)); destination.AddEdge(startVertex, endVertex); } int edgesToAdd = random.Next(destination.VertexCount/2); for (int i = 0; i < edgesToAdd; i++) { Vertex startVertex = destination.GetVertex(random.Next(destination.VertexCount)); Vertex endVertex = destination.GetVertex(random.Next(destination.VertexCount)); if (startVertex != endVertex) { destination.AddEdge(startVertex, endVertex); } } if (endVertexIndex == -1) { throw new Exception("End vertex not found."); } else { destination.SetEnd(endVertexIndex); } return destination; }