/// <summary> /// Creates the vertices in the level graph and fills the level matrix and connected /// subgraph dictionary with them. /// </summary> private void CreateVertices() { for (int row = 0; row < _rows; row++) { for (int column = 0; column < _columns; column++) { var vertex = new Vertex(row, column); _levelMatrix[row, column] = vertex; _connectedSubgraphs[vertex] = new ConnectedSubgraph(vertex); _availableVertices.Add(vertex); } } }
/// <summary> /// Attempts to remove an edge entering a specific vertex from the strongly connected /// portion of a specific connected subgraph and replace it with another edge towards an /// edge from a weakly connected portion of the connected subgraph, thus expanding the /// strongly connected portion. /// </summary> /// <param name="connectedSubgraph">The connected subgraph which contains a weakly /// connected portion.</param> /// <param name="vertex">The vertex from the strongly connected portion of the connected /// subgraph.</param> /// <returns><see langword="true"/> if the edge was successfully added.</returns> private bool AddStronglyConnectingEdgeEnteringVertex( ConnectedSubgraph connectedSubgraph, Vertex vertex) { Vertex otherVertex = null; List<Vertex> adjacentVertices = GetAdjacentVertices(vertex); while (adjacentVertices.Count > 0) { int vertexIndex = _random.Next(adjacentVertices.Count); Vertex adjacentVertex = adjacentVertices[vertexIndex]; if (!vertex.IsConnectedToVertex(adjacentVertex) && connectedSubgraph.ContainsVertex(adjacentVertex) && !connectedSubgraph.IsVertexStronglyConnected(adjacentVertex)) { if (connectedSubgraph.CheckWillConnectStrongly(vertex, adjacentVertex)) { if (!CheckCanConnectVertices(vertex, adjacentVertex)) { // If the two vertices cannot be connected without causing an // intersection, remove the other edge Vertex crossVertex1 = _levelMatrix[vertex.Row, adjacentVertex.Column]; Vertex crossVertex2 = _levelMatrix[adjacentVertex.Row, vertex.Column]; RemoveEdgeBetweenVertices(crossVertex1, crossVertex2); } // Check if the other vertex has the maximum number of edges entering it // and if so, remove a random edge entering it if (adjacentVertex.ConnectedVertexCount == _maxEdges) RemoveEdgeEnteringVertex(adjacentVertex); otherVertex = adjacentVertex; break; } } adjacentVertices.RemoveAt(vertexIndex); } // If no suitable other vertex was found, give up if (otherVertex == null) return false; // Check if the specified vertex has the maximum number of edges entering it and if so, // remove a random edge entering it if (vertex.ConnectedVertexCount == _maxEdges) RemoveEdgeEnteringVertex(vertex); // Add the edge to the level graph AddEdgeBetweenVertices(vertex, otherVertex); return true; }
/// <summary> /// Adjusts the connected subgraph assignment for a specific vertex. /// </summary> /// <param name="vertex">The vertex whose connected subgraph should be adjusted. /// </param> /// <param name="recalculateCurrent">Specifies whether the vertex's currently assigned /// connected subgraph should be recalculated before adjusting the assignment.</param> private void AdjustConnectedSubgraphs(Vertex vertex, bool recalculateCurrent) { ConnectedSubgraph currentGraph = _connectedSubgraphs[vertex]; // Recalculate the currently assigned connected subgraph if needed if (recalculateCurrent) currentGraph.RecalculateConnectedVertices(); // If the specified vertex does not belong to its currently assigned connected // subgraph, create a new connected subgraph object using the specified vertex as a // main vertex for it and then assign it to all vertices that belong to it if (!currentGraph.ContainsVertex(vertex)) { var newGraph = new ConnectedSubgraph(vertex); foreach (Vertex connectedVertex in newGraph.ConnectedVertices) { _connectedSubgraphs[connectedVertex] = newGraph; } } }
/// <summary> /// Attempts to remove an edge entering a specific vertex in a specific connected subgraph /// and replace it with another edge towards a different connected subgraph, thus merging /// the two connected subgraphs. /// </summary> /// <param name="connectedSubgraph">The connected subgraph which should be merged with /// another one.</param> /// <param name="vertex">The vertex from the strongly connected portion of the connected /// subgraph.</param> /// <returns><see langword="true"/> if the edge was successfully added.</returns> private bool AddExternalEdgeEnteringVertex( ConnectedSubgraph connectedSubgraph, Vertex vertex) { // Attempt to find another vertex from a different connected subgraph that can be // connected to the specified vertex; if an edge prevents the two vertices from being // connected, remove it Vertex otherVertex = null; List<Vertex> adjacentVertices = GetAdjacentVertices(vertex); while (adjacentVertices.Count > 0) { int vertexIndex = _random.Next(adjacentVertices.Count); Vertex adjacentVertex = adjacentVertices[vertexIndex]; if (!connectedSubgraph.ContainsVertex(adjacentVertex)) { if (!CheckCanConnectVertices(vertex, adjacentVertex)) { // If the two vertices cannot be connected without causing an intersection, // remove the other edge Vertex crossVertex1 = _levelMatrix[vertex.Row, adjacentVertex.Column]; Vertex crossVertex2 = _levelMatrix[adjacentVertex.Row, vertex.Column]; RemoveEdgeBetweenVertices(crossVertex1, crossVertex2); } // Check if the other vertex has the maximum number of edges entering it and if // so, remove a random edge entering it if (adjacentVertex.ConnectedVertexCount == _maxEdges) RemoveEdgeEnteringVertex(adjacentVertex); otherVertex = adjacentVertex; break; } adjacentVertices.RemoveAt(vertexIndex); } // If no suitable other vertex was found, give up if (otherVertex == null) return false; // Check if the specified vertex has the maximum number of edges entering it and if so, // remove a random edge entering it if (vertex.ConnectedVertexCount == _maxEdges) RemoveEdgeEnteringVertex(vertex); // Add the edge to the level graph AddEdgeBetweenVertices(vertex, otherVertex); return true; }