예제 #1
0
파일: Algorithms.cs 프로젝트: MadMatt25/STP
        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;
        }
예제 #2
0
파일: Graph.cs 프로젝트: MadMatt25/STP
        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);
            }
        }
예제 #3
0
파일: Algorithms.cs 프로젝트: MadMatt25/STP
        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;
        }
예제 #4
0
파일: BLS.cs 프로젝트: MadMatt25/STP
        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;
        }
예제 #5
0
파일: LPSolver.cs 프로젝트: MadMatt25/STP
        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);
            }
        }
예제 #6
0
파일: Graph.cs 프로젝트: MadMatt25/STP
        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];
        }
예제 #7
0
파일: Graph.cs 프로젝트: MadMatt25/STP
        /// <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.");
        }
예제 #8
0
파일: Graph.cs 프로젝트: MadMatt25/STP
 /// <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;
 }
예제 #9
0
파일: Graph.cs 프로젝트: MadMatt25/STP
 /// <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);
 }
예제 #10
0
 /// <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;
 }
예제 #11
0
            /// <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;
            }
예제 #12
0
            /// <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;
            }
예제 #13
0
 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;
 }
예제 #14
0
            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.
            }
예제 #15
0
파일: LPSolver.cs 프로젝트: MadMatt25/STP
        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;
            }
        }
예제 #16
0
파일: Graph.cs 프로젝트: MadMatt25/STP
 /// <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);
 }
예제 #17
0
파일: Graph.cs 프로젝트: MadMatt25/STP
        public void AddVertex(Vertex vertex)
        {
            if (_vertices.Contains(vertex))
                return;

            Vertices.Add(vertex);
            _vertices.Add(vertex);
            _adjacencies.Add(vertex, new List<Edge>());
            _terminalDistance = null;
        }
예제 #18
0
파일: Algorithms.cs 프로젝트: MadMatt25/STP
 public static Dictionary<Vertex, Path> DijkstraPathToAll(Vertex from, Graph graph)
 {
     return DijkstraPathToAll(from, graph, false);
 }
예제 #19
0
파일: Graph.cs 프로젝트: MadMatt25/STP
        /// <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);
            }
        }
예제 #20
0
파일: Algorithms.cs 프로젝트: MadMatt25/STP
 public static Dictionary<Vertex, Path> DijkstraPathToAllTerminals(Vertex from, Graph graph)
 {
     return DijkstraPathToAll(from, graph, true);
 }
예제 #21
0
파일: Graph.cs 프로젝트: MadMatt25/STP
        /// <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.");
        }
예제 #22
0
파일: Algorithms.cs 프로젝트: MadMatt25/STP
 public static Path NearestTerminal(Vertex from, Graph graph)
 {
     return NearestTerminals(from, graph, 1).FirstOrDefault();
 }
예제 #23
0
파일: Graph.cs 프로젝트: MadMatt25/STP
 /// <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;
     }
 }
예제 #24
0
파일: Algorithms.cs 프로젝트: MadMatt25/STP
        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;
        }
예제 #25
0
파일: Graph.cs 프로젝트: MadMatt25/STP
        /// <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];
        }
예제 #26
0
파일: Algorithms.cs 프로젝트: MadMatt25/STP
        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;
        }
예제 #27
0
파일: Graph.cs 프로젝트: MadMatt25/STP
        /// <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);
        }
예제 #28
0
파일: Algorithms.cs 프로젝트: MadMatt25/STP
        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;
        }
예제 #29
0
파일: Path.cs 프로젝트: MadMatt25/STP
 public Path(Vertex start)
 {
     Edges = new List<Edge>();
     Start = start;
 }
예제 #30
0
파일: LPSolver.cs 프로젝트: MadMatt25/STP
        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;
                }
            }
        }