Example #1
0
        public static IWeightedGraph <TV, TW> FindShortestPath <TV, TW>(IWeightedGraph <TV, TW> graph,
                                                                        IVertex <TV> source,
                                                                        IVertex <TV> target,
                                                                        TW zeroValue,
                                                                        TW maxValue,
                                                                        Func <TW, TW, TW> combineCosts) where TV : IEquatable <TV> where TW : IComparable
        {
            HashSet <IVertex <TV> >           visitedVerteces = new HashSet <IVertex <TV> >();
            IPriorityQueue <IVertex <TV>, TW> vertecesToVisit = new NaivePriorityQueue <IVertex <TV>, TW>();
            Dictionary <IVertex <TV>, IWeightedEdge <TV, TW> > predecessor = new Dictionary <IVertex <TV>, IWeightedEdge <TV, TW> >();

            // Initialize queue and predecessor map
            foreach (IVertex <TV> vertex in graph.GetAllVerteces())
            {
                vertecesToVisit.Enqueue(vertex, maxValue);
                predecessor.Add(vertex, null);
            }
            vertecesToVisit.UpdatePriority(source, zeroValue);

            // Continue as long as there are verteces to visit
            IVertex <TV> currentVertex = null;
            TW           currentCosts  = zeroValue;

            while (!vertecesToVisit.Empty)
            {
                // Get the closest next vertex
                (currentVertex, currentCosts) = vertecesToVisit.Dequeue();

                // Check whether we reached our target
                if (currentVertex == target)
                {
                    break;
                }
                visitedVerteces.Add(currentVertex);

                // If not, discover the next verteces that can be visited
                foreach (IWeightedEdge <TV, TW> edge in graph.GetEdgesOfVertex(currentVertex))
                {
                    if (edge.Weight.CompareTo(zeroValue) < 0)
                    {
                        throw new NegativeEdgeWeightException();
                    }
                    IVertex <TV> connectedVertex = edge.ConnectedVertex(currentVertex);
                    if (!visitedVerteces.Contains(connectedVertex))
                    {
                        TW newCosts = combineCosts(currentCosts, edge.Weight);
                        if (newCosts.CompareTo(vertecesToVisit.GetPriorityOf(connectedVertex)) < 0)
                        {
                            vertecesToVisit.UpdatePriority(connectedVertex, newCosts);
                            predecessor[connectedVertex] = edge;
                        }
                    }
                }
            }

            // If we reached the target vertex, build result graph
            if (currentVertex == target)
            {
                GraphBuilder <TV, TW> builder = new GraphBuilder <TV, TW>(true).AddVertex(target.Value);
                while (currentVertex != source)
                {
                    IWeightedEdge <TV, TW> pathEdge       = predecessor[currentVertex];
                    IVertex <TV>           previousVertex = pathEdge.ConnectedVertex(currentVertex);
                    builder
                    .AddVertex(previousVertex.Value)
                    .AddEdge(previousVertex.Value, currentVertex.Value, pathEdge.Weight);
                    currentVertex = previousVertex;
                }
                return(builder.Build());
            }
            else
            {
                throw new VertexNotReachableException <TV>(target);
            }
        }
Example #2
0
        /// <summary>
        /// Builds the minimum spanning tree of a given graph.
        /// </summary>
        /// <typeparam name="TV">Type of the graph vertex values.</typeparam>
        /// <typeparam name="TW">Type of the graph edge weights.</typeparam>
        /// <param name="graph">The graph got which to build the minimum spanning tree.</param>
        /// <returns>Returns the minimum spanning tree of the given graph.</returns>
        public static IWeightedGraph <TV, TW> FindMinimumSpanningTree <TV, TW>(IWeightedGraph <TV, TW> graph, TW min, TW max)
            where TV : IEquatable <TV>
            where TW : IComparable
        {
            // Builder used to incrementally build the target minimum spanning tree
            GraphBuilder <TV, TW> builder = new GraphBuilder <TV, TW>();

            // Get all verteces and edges of graph
            IEnumerable <IVertex <TV> >           verteces = graph.GetAllVerteces();
            IEnumerable <IWeightedEdge <TV, TW> > edges    = graph.GetAllEdges();

            // TODO: replace with more performant priority queue implementation
            // Track minimum known cost to connect to target vertex
            IPriorityQueue <TV, TW> vertexCosts = new NaivePriorityQueue <TV, TW>();

            // Track target vertex and edge connecting to target vertex with minimum known cost
            Dictionary <TV, IVertex <TV> >           vertexValue = new Dictionary <TV, IVertex <TV> >();
            Dictionary <TV, IWeightedEdge <TV, TW> > vertexEdges = new Dictionary <TV, IWeightedEdge <TV, TW> >();

            // Initialize vertex costs with all costs set to max
            foreach (IVertex <TV> vertex in verteces)
            {
                vertexCosts.Enqueue(vertex.Value, max);
                vertexValue.Add(vertex.Value, vertex);
                vertexEdges.Add(vertex.Value, null);
            }

            // Set starting vertex
            vertexCosts.UpdatePriority(verteces.First().Value, min);

            // While there are verteces left to add, select vertex with smallest cost
            while (!vertexCosts.Empty)
            {
                // Get and remove vertex with smallest cost
                TV minCost = vertexCosts.Dequeue().Item1;

                // For easier handling, get vertex and edge
                IVertex <TV>           vertex = vertexValue[minCost];
                IWeightedEdge <TV, TW> edge   = vertexEdges[minCost];

                // Add vertex and edge to target MST
                builder.AddVertex(vertex.Value);
                if (edge != null)
                {
                    builder.AddEdge(vertex.Value, edge.ConnectedVertex(vertex.Value).Value, edge.Weight);
                }

                // Update vertex cost for adjacent verteces and store edges
                foreach (IWeightedEdge <TV, TW> connectedEdge in graph.GetEdgesOfVertex(vertex))
                {
                    // Ignore edges leading to verteces already added to the MST
                    IVertex <TV> targetVertex = connectedEdge.ConnectedVertex(vertex);
                    if (vertexCosts.Contains(targetVertex.Value) &&
                        connectedEdge.Weight.CompareTo(vertexCosts.GetPriorityOf(targetVertex.Value)) < 0)
                    {
                        vertexCosts.UpdatePriority(targetVertex.Value, connectedEdge.Weight);
                        vertexEdges[targetVertex.Value] = connectedEdge;
                    }
                }
            }

            // All verteces added to MST - done!
            return(builder.Build());
        }