public static int Dijkstra(Vertex from, Vertex to, Graph graph) { HashSet<Vertex> visited = new HashSet<Vertex>(); Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes = new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>(); FibonacciHeap<int, Vertex> labels = new FibonacciHeap<int, Vertex>(); // Initialize labels. foreach (var vertex in graph.Vertices) { var n = labels.Add(vertex == from ? 0 : int.MaxValue, vertex); nodes.Add(vertex, n); } int currentLabel = int.MaxValue; while (!visited.Contains(to)) { var currentNode = labels.ExtractMin(); var current = currentNode.Value; currentLabel = currentNode.Key; // Consider all edges ending in unvisited neighbours var edges = graph.GetEdgesForVertex(current).Where(x => !visited.Contains(x.Other(current))); // Update labels on the other end. foreach (var edge in edges) { if (currentNode.Key + edge.Cost < nodes[edge.Other(current)].Key) labels.DecreaseKey(nodes[edge.Other(current)], currentNode.Key + edge.Cost); } visited.Add(current); } return currentLabel; }
private Graph(int nbVertices) : this() { _vertices = new HashSet<Vertex>(); Vertices = new List<Vertex>(nbVertices); // Create the vertices for (int i = 0; i < nbVertices; i++) { var v = new Vertex(i + 1); //Start counting at 1. AddVertex(v); } }
public static Path DijkstraPath(Vertex from, Vertex to, Graph graph) { HashSet<Vertex> visited = new HashSet<Vertex>(); Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes = new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>(); Dictionary<Vertex, Edge> comingFrom = new Dictionary<Vertex, Edge>(); FibonacciHeap<int, Vertex> labels = new FibonacciHeap<int, Vertex>(); // Initialize labels. foreach (var vertex in graph.Vertices) { var n = labels.Add(vertex == from ? 0 : int.MaxValue, vertex); nodes.Add(vertex, n); comingFrom.Add(vertex, null); } while (!visited.Contains(to)) { var currentNode = labels.ExtractMin(); var current = currentNode.Value; // Consider all edges ending in unvisited neighbours var edges = graph.GetEdgesForVertex(current).Where(x => !visited.Contains(x.Other(current))); // Update labels on the other end. foreach (var edge in edges) { if (currentNode.Key + edge.Cost < nodes[edge.Other(current)].Key) { labels.DecreaseKey(nodes[edge.Other(current)], currentNode.Key + edge.Cost); comingFrom[edge.Other(current)] = edge; } } visited.Add(current); } // Now travel back, to find the actual path List<Edge> pathEdges = new List<Edge>(); Vertex pathVertex = to; while (pathVertex != from) { pathEdges.Add(comingFrom[pathVertex]); pathVertex = comingFrom[pathVertex].Other(pathVertex); } pathEdges.Reverse(); Path path = new Path(from); path.Edges.AddRange(pathEdges); return path; }
public Graph RemoveVertexAndReconnect(Graph currentSolution, Graph problemInstance, Vertex remove) { var workingSolution = currentSolution.Clone(); foreach (var vertex in problemInstance.Vertices) if (!workingSolution.ContainsVertex(vertex)) workingSolution.AddVertex(vertex); foreach (var edge in workingSolution.GetEdgesForVertex(remove).ToList()) workingSolution.RemoveEdge(edge); IEnumerable<Vertex> degreeOne; while ((degreeOne = workingSolution.Vertices.Except(problemInstance.Terminals) .Where(x => workingSolution.GetDegree(x) == 1)).Any()) { foreach (var degreeZeroSteiner in degreeOne.ToList()) foreach (var edge in workingSolution.GetEdgesForVertex(degreeZeroSteiner).ToList()) workingSolution.RemoveEdge(edge, false); } ReconnectTerminals(workingSolution, problemInstance); return workingSolution; }
public static IEnumerable<IEnumerable<Vertex>> BFS(Graph graph, HashSet<Vertex> visited, Vertex end, Vertex expand) { if (graph.Terminals.All(visited.Contains) || visited.Count == graph.NumberOfVertices - 1) yield break; List<Vertex> nodes = graph.GetNeighboursForVertex(expand); //for (int i = 0; i < nodes.Count; i++ ) //{ // foreach (var combination in new Combinations<Vertex>(nodes, i + 1)) // { // if (combination.Any(x => visited.Contains(x))) // continue; // if (combination.Contains(end)) // { // foreach (var n in combination) // visited.Add(n); // foreach (var n in combination) // foreach (var bfs in BFS(graph, visited, end, n)) // yield return bfs; // foreach (var n in combination) // visited.Remove(n); // break; // } // } //} foreach (var node in nodes) { if (visited.Contains(node)) continue; if (node == end) { visited.Add(node); yield return visited; visited.Remove(node); break; } } //for (int i = 0; i < nodes.Count; i++) //{ // if (visited.Count + i == graph.NumberOfVertices - 1) // break; // Adding i+1 results in all nodes, which is useless. // foreach (var combination in new Combinations<Vertex>(nodes, i + 1)) // { // if (combination.Any(visited.Contains)) // || combination.Contains(end)) // continue; // foreach (var n in combination) // visited.Add(n); // foreach (var n in combination) // foreach (var bfs in BFS(graph, visited, end, n)) // yield return bfs; // foreach (var n in combination) // visited.Remove(n); // } //} foreach (var node in nodes) { if (visited.Contains(node) || node == end) continue; visited.Add(node); foreach (var bfs in BFS(graph, visited, end, node)) yield return bfs; visited.Remove(node); } }
public int GetVoronoiRadiusForTerminal(Vertex vertex) { if (!Terminals.Contains(vertex)) throw new ArgumentException("The given vertex should be a terminal."); if (_voronoiRadius.ContainsKey(vertex)) return _voronoiRadius[vertex]; ComputeVoronoiRegions(); return _voronoiRadius[vertex]; }
/// <summary> /// Method to get the neighbours of a given vertex. /// </summary> /// <param name="v">The vertex of which to get all the neighbours.</param> /// <returns>A list containing all the neighbours of the given vertex.</returns> public List<Vertex> GetNeighboursForVertex(Vertex v) { if (_adjacencies.ContainsKey(v)) return _adjacencies[v].Select(x => x.Other(v)).ToList(); throw new ArgumentException("The given vertex is not in this graph."); }
/// <summary> /// Method to get the degree of a vertex in the graph. /// </summary> /// <param name="v">The vertex of which to get the degree.</param> /// <returns>The degree of the given vertex.</returns> public int GetDegree(Vertex v) { if (!_adjacencies.ContainsKey(v)) throw new ArgumentException("The given vertex v is not contained in this graph."); return _adjacencies[v].Count; }
/// <summary> /// Method to check if the graph contains a given vertex in constant time. /// </summary> /// <param name="vertex"></param> /// <returns>Boolean indicating whether the given vertex is present in the graph.</returns> public bool ContainsVertex(Vertex vertex) { return _vertices.Contains(vertex); }
/// <summary> /// Method to peek at the next vertex to apply interleaving Dijkstra on. /// </summary> /// <returns>The vertex on which to apply interleaving Dijkstra next.</returns> public Vertex PeekNextVertex() { // Find the next vertex if (_currentlyLowestLabelUnusedVertex == null) _currentlyLowestLabelUnusedVertex = GetLowestLabelUnusedVertex(); return _currentlyLowestLabelUnusedVertex; }
/// <summary> /// Method to get the next vertex to apply interleaving Dijkstra on. /// </summary> /// <returns>The vertex on which to apply interleaving Dijkstra.</returns> public Vertex GetNextVertex() { // Find the next vertex if (_currentlyLowestLabelUnusedVertex == null) _currentlyLowestLabelUnusedVertex = GetLowestLabelUnusedVertex(); _currentlyUsingVertex = _currentlyLowestLabelUnusedVertex; _currentlyLowestLabelUnusedVertex = null; return _currentlyUsingVertex; }
/// <summary> /// Get the vertex of which the current Dijkstra procedure's lowest label is lowest of all procedures. /// </summary> /// <returns>The vertex for which the Dijkstra procedure currently has the lowest label.</returns> public Vertex GetLowestLabelUnusedVertex() { if (_currentlyLowestLabelUnusedVertex != null) return _currentlyLowestLabelUnusedVertex; int value = int.MaxValue; Vertex vertex = null; foreach (var kvPair in _dictLabels) { if (kvPair.Key == _currentlyUsingVertex) continue; var fibonacciHeap = kvPair.Value; if (fibonacciHeap.IsEmpty()) continue; var node = fibonacciHeap.Peek(); if (node.Key <= value) { vertex = kvPair.Key; value = node.Key; } } _currentlyLowestLabelUnusedVertex = vertex; return _currentlyLowestLabelUnusedVertex; }
public List<Path> FindPathsEndingInThisVertex(Vertex end) { List<Path> paths = new List<Path>(); foreach (var kvPair in _dictPathsfound) { var pathsDictionary = kvPair.Value; if (pathsDictionary.ContainsKey(end)) paths.Add(pathsDictionary[end]); } return paths; }
public void AddVertexToInterleavingDijkstra(Vertex vertex, Graph graph) { if (_verticesInSearch.Contains(vertex)) throw new InvalidOperationException("Can not add the vertex, because it is already added."); _verticesInSearch.Add(vertex); var labels = new FibonacciHeap<int, Vertex>(); var nodes = new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>(); // Initialize labels. foreach (var v in graph.Vertices) { var node = labels.Add(v == vertex ? 0 : int.MaxValue, v); nodes.Add(v, node); } _dictLabels.Add(vertex, labels); _dictNodes.Add(vertex, nodes); _dictVisited.Add(vertex, new HashSet<Vertex>()); _dictPathsfound.Add(vertex, new Dictionary<Vertex, Path>()); _dictComingFrom.Add(vertex, new Dictionary<Vertex, Edge>()); _dictComponent.Add(vertex, ++_internalNewComponentCount); // All vertices start in a different component. }
public static IEnumerable<IEnumerable<Vertex>> GetBFS(Graph graph, Vertex root) { yield return new[] { root }; foreach (var end in graph.Vertices.Except(new [] { root })) { HashSet<Vertex> visited = new HashSet<Vertex>(); visited.Add(root); foreach (var bfs in BFS(graph, visited, end, root)) yield return bfs; } }
/// <summary> /// Method to add an edge to the graph. /// </summary> /// <param name="from">Vertex from which the edge starts.</param> /// <param name="to">Vertex at which the edge ends.</param> /// <param name="cost">The cost of the edge.</param> public void AddEdge(Vertex from, Vertex to, int cost) { var edge = new Edge(from, to, cost); AddEdge(edge); }
public void AddVertex(Vertex vertex) { if (_vertices.Contains(vertex)) return; Vertices.Add(vertex); _vertices.Add(vertex); _adjacencies.Add(vertex, new List<Edge>()); _terminalDistance = null; }
public static Dictionary<Vertex, Path> DijkstraPathToAll(Vertex from, Graph graph) { return DijkstraPathToAll(from, graph, false); }
/// <summary> /// Do a Depth First traversal on the graph, starting with a given vertex. /// </summary> /// <param name="start">The vertex from which to start the depth first traversal.</param> /// <returns>A depth first traversal from the given start vertex.</returns> public IEnumerable<Vertex> DepthFirstTraversal(Vertex start, bool ltr = true) { var visited = new HashSet<Vertex>(); var stack = new Stack<Vertex>(); stack.Push(start); while (stack.Count != 0) { var current = stack.Pop(); if (!visited.Add(current)) continue; yield return current; var neighbours = this.GetNeighboursForVertex(current) .Where(n => !visited.Contains(n)); foreach (var neighbour in ltr ? neighbours.Reverse() : neighbours) stack.Push(neighbour); } }
public static Dictionary<Vertex, Path> DijkstraPathToAllTerminals(Vertex from, Graph graph) { return DijkstraPathToAll(from, graph, true); }
/// <summary> /// Method to get the edges that are connected to a given vertex. /// </summary> /// <param name="v">The vertex to get all the edges for.</param> /// <returns>A list containing all the edges that the given vertex is connected to.</returns> public List<Edge> GetEdgesForVertex(Vertex v) { if (_adjacencies.ContainsKey(v)) return _adjacencies[v]; throw new ArgumentException("The given vertex is not in this graph."); }
public static Path NearestTerminal(Vertex from, Graph graph) { return NearestTerminals(from, graph, 1).FirstOrDefault(); }
/// <summary> /// Method to get an IEnumerable with the non-terminal vertices in the Veronoi region of /// a certain terminal. /// </summary> /// <param name="terminal">The terminal to determine the Veronoi region.</param> /// <returns>List of non-terminals in the Veronoi region</returns> public IEnumerable<Vertex> GetVerticesInVoronoiRegion(Vertex terminal) { foreach (var vertex in Vertices) { if (GetVoronoiRegionForVertex(vertex) == terminal) yield return vertex; } }
public static List<Path> NearestTerminals(Vertex from, Graph graph, int n) { List<Path> foundPaths = new List<Path>(); HashSet<Vertex> visited = new HashSet<Vertex>(); Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes = new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>(); FibonacciHeap<int, Vertex> labels = new FibonacciHeap<int, Vertex>(); Dictionary<Vertex, Edge> comingFrom = new Dictionary<Vertex, Edge>(); if (graph.Terminals.Contains(from)) foundPaths.Add(new Path(from)); // Initialize labels. foreach (var vertex in graph.Vertices) { var node = labels.Add(vertex == from ? 0 : int.MaxValue, vertex); nodes.Add(vertex, node); comingFrom.Add(vertex, null); } while (!labels.IsEmpty() && foundPaths.Count < n) { var currentNode = labels.ExtractMin(); var current = currentNode.Value; // Consider all edges ending in unvisited neighbours var edges = graph.GetEdgesForVertex(current).Where(x => !visited.Contains(x.Other(current))); // Update labels on the other end. foreach (var edge in edges) { if (currentNode.Key + edge.Cost < nodes[edge.Other(current)].Key) { labels.DecreaseKey(nodes[edge.Other(current)], currentNode.Key + edge.Cost); comingFrom[edge.Other(current)] = edge; } } visited.Add(current); if (graph.Terminals.Contains(current) && current != from) { // Now travel back, to find the actual path List<Edge> pathEdges = new List<Edge>(); Vertex pathVertex = current; while (pathVertex != from) { pathEdges.Add(comingFrom[pathVertex]); pathVertex = comingFrom[pathVertex].Other(pathVertex); } pathEdges.Reverse(); Path path = new Path(from); path.Edges.AddRange(pathEdges); foundPaths.Add(path); } } return foundPaths; }
/// <summary> /// Method to get the Terminal for which the given vertex belongs to its Veronoi region. /// </summary> /// <param name="vertex">The vertex for which to get the Veronoi region.</param> /// <returns>The terminal in which the vertex is in the Veronoi region.</returns> public Vertex GetVoronoiRegionForVertex(Vertex vertex) { if (Terminals.Contains(vertex)) return vertex; if (_voronoiRegions.ContainsKey(vertex)) return _voronoiRegions[vertex]; ComputeVoronoiRegions(); return _voronoiRegions[vertex]; }
private static bool ExistsPath(Vertex v1, Vertex v2, Graph graph, List<Vertex> visited) { foreach (var edge in graph.GetEdgesForVertex(v1)) { if (edge.Other(v1) == v2) { return true; } if (!visited.Contains(edge.Other(v1))) { var visited2 = visited.ToList(); visited2.Add(v1); if (ExistsPath(edge.Other(v1), v2, graph, visited2)) return true; } } return false; }
/// <summary> /// Method to remove a vertex from this graph. /// Also removes all the edges that this vertex was connected to. /// </summary> /// <param name="vertex">The vertex to remove.</param> public void RemoveVertex(Vertex vertex) { if (!_vertices.Contains(vertex)) return; _vertices.Remove(vertex); Vertices.Remove(vertex); foreach (var edge in _adjacencies[vertex].ToList()) RemoveEdge(edge); _terminalDistance = null; _adjacencies.Remove(vertex); }
public static Dictionary<Vertex, Path> DijkstraPathToAll(Vertex from, Graph graph, bool onlyTerminals) { Dictionary<Vertex, Edge> comingFrom = new Dictionary<Vertex, Edge>(); HashSet<Vertex> visited = new HashSet<Vertex>(); Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node> nodes = new Dictionary<Vertex, FibonacciHeap<int, Vertex>.Node>(); Dictionary<Vertex, Path> paths = new Dictionary<Vertex, Path>(); FibonacciHeap<int, Vertex> labels = new FibonacciHeap<int, Vertex>(); // Initialize labels. foreach (var vertex in graph.Vertices) { var n = labels.Add(vertex == from ? 0 : int.MaxValue, vertex); nodes.Add(vertex, n); } while (paths.Count < (onlyTerminals ? graph.Terminals.Count - 1 : graph.NumberOfVertices - 1)) { var currentNode = labels.ExtractMin(); var current = currentNode.Value; // Consider all edges ending in unvisited neighbours var edges = graph.GetEdgesForVertex(current).Where(x => !visited.Contains(x.Other(current))); // Update labels on the other end. foreach (var edge in edges) { if (currentNode.Key + edge.Cost < nodes[edge.Other(current)].Key) { labels.DecreaseKey(nodes[edge.Other(current)], currentNode.Key + edge.Cost); comingFrom[edge.Other(current)] = edge; } } visited.Add(current); if (current != from && (!onlyTerminals || graph.Terminals.Contains(current))) { // Travel back the path List<Edge> pathEdges = new List<Edge>(); Vertex pathVertex = current; while (pathVertex != from) { pathEdges.Add(comingFrom[pathVertex]); pathVertex = comingFrom[pathVertex].Other(pathVertex); } pathEdges.Reverse(); Path path = new Path(from); path.Edges.AddRange(pathEdges); paths[current] = path; } } return paths; }
public Path(Vertex start) { Edges = new List<Edge>(); Start = start; }
public static IEnumerable<IEnumerable<Vertex>> GetAllConnectedCombinations(Graph graph, Vertex start) { var visited = new HashSet<Vertex>(); var terminals = new HashSet<Vertex>(graph.Terminals); var stack = new Stack<Vertex>(); Dictionary<Vertex, Vertex> childParentDictionary = new Dictionary<Vertex, Vertex>(); stack.Push(start); childParentDictionary.Add(start, null); while (stack.Count != 0) { var current = stack.Pop(); if (!visited.Add(current)) continue; var neighbours = graph.GetNeighboursForVertex(current) .Where(n => !visited.Contains(n)) .ToList(); // Travel left to right neighbours.Reverse(); foreach (var neighbour in neighbours) { stack.Push(neighbour); childParentDictionary.Add(neighbour, current); } if (!neighbours.Any() || neighbours.All(visited.Contains)) { List<Vertex> vertices = new List<Vertex>(); Vertex parentNode = current; do { vertices.Add(parentNode); } while ((parentNode = childParentDictionary[parentNode]) != null); yield return vertices; } } }