Exemplo n.º 1
0
        /// <summary>
        /// Checks whether target graph can contain euler cycles
        /// </summary>
        /// <param name="graph">Target graph</param>
        private bool IsEulerGraph(TGraph graph)
        {
            var isAnyOddVertexDeg        = graph.Vertices.Any(v => graph.GetVertexDeg(v) % 2 != 0);
            var connectedComponentsCount = _connectedComponentsCounter.Execute(graph);

            return(!isAnyOddVertexDeg && connectedComponentsCount < 2);
        }
Exemplo n.º 2
0
        public IEnumerable <Edge <TVertex> > Execute(TGraph graph)
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }
            if (_connectedComponentsCounter.Execute(graph) > 1)
            {
                throw new InvalidOperationException("For Prim's algorithm graph cannot contain more than one connected component");
            }
            if (!graph.Vertices.Any() || !graph.Weights.Any())
            {
                return(Enumerable.Empty <Edge <TVertex> >());
            }

            var initialConsideredVertices = new List <TVertex>()
            {
                graph.Vertices.First()
            };
            // Vertices that are already included in spanning tree
            var consideredVertices = new HashSet <TVertex>(initialConsideredVertices, _verticesComparer);
            // Edges that are already included in spanning tree
            var spanningTreeEdges = new HashSet <Edge <TVertex> >();

            while (graph.Vertices.Any(v => !consideredVertices.Contains(v)))
            {
                // For each considered vertex algorithm tries to find an edge of minimal weight
                // which is not included in spanning tree and doesn't create cycle
                var minWeight = Int32.MaxValue;
                var edgeToIncludeToSpanningTree = default(Edge <TVertex>);

                foreach (var sourceVertex in consideredVertices)
                {
                    foreach (var destinationVertex in graph.AdjacencyLists[sourceVertex])
                    {
                        var edge   = new Edge <TVertex>(sourceVertex, destinationVertex);
                        var weight = graph.Weights[edge];

                        if (IsEdgeValid(edge, consideredVertices, spanningTreeEdges) && weight < minWeight)
                        {
                            minWeight = weight;
                            edgeToIncludeToSpanningTree = edge;
                        }
                    }
                }

                consideredVertices.Add(edgeToIncludeToSpanningTree.Destination);
                spanningTreeEdges.Add(edgeToIncludeToSpanningTree);
            }

            return(spanningTreeEdges);
        }
Exemplo n.º 3
0
        public IEnumerable <TVertex> Execute(TGraph graph, TVertex startVertex, TVertex endVertex)
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }
            if (startVertex == null)
            {
                throw new ArgumentNullException(nameof(startVertex));
            }
            if (endVertex == null)
            {
                throw new ArgumentNullException(nameof(endVertex));
            }
            if (!graph.AdjacencyLists.ContainsKey(startVertex))
            {
                throw new ArgumentException($"Start vertex = '{startVertex}' doesn't exist in graph");
            }
            if (!graph.AdjacencyLists.ContainsKey(endVertex))
            {
                throw new ArgumentException($"End vertex = '{endVertex}' doesn't exist in graph");
            }
            if (_connectedComponentsCounter.Execute(graph) > 1)
            {
                throw new InvalidOperationException("For Lee algorithm graph should be highly connected");
            }

            #region Algorithm description

            // The algorithm is using the "waves" term.
            // Wave is an integer value describing the number of edges needed to go from one vertex to another.
            // Start vertex has the wave value of 0.

            // The algorithm is divided into 2 stages:

            // 1. Calculating the waves
            // Each vertex (starting from initial one) is viewed.
            // For each its neighbour, that has unset wave value, wave is calculated as current vertex's wave + 1.

            // 2. Finding the path itself
            // To find the path from start to end vertex itself, graph traversal is started from end vertex,
            // passing through the vertices in which the value of the wave decreases by 1 until it reaches start vertex.

            #endregion

            var waves        = CalculateWaves(graph, startVertex);
            var shortestPath = FindShortestPath(graph, startVertex, endVertex, waves);

            return(shortestPath);
        }
Exemplo n.º 4
0
        public IEnumerable <TVertex> Execute(TGraph graph)
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }
            if (_connectedComponentsCounter.Execute(graph) > 1)
            {
                throw new InvalidOperationException("Target graph should be highly connected for searching articulation points in it");
            }

            var foundArticulationPoints = new List <TVertex>();

            // Cloning graph to save the original one
            var graphClone    = new UndirectedGraph <TVertex>(graph.Vertices, graph.ReducedEdges) as TGraph;
            var graphVertices = graphClone.Vertices.ToList();

            foreach (var vertex in graphVertices)
            {
                var sourceEdges      = graphClone.Edges.Where(e => e.Source.CompareTo(vertex) == 0);
                var destinationEdges = graphClone.Edges.Where(e => e.Destination.CompareTo(vertex) == 0);
                graphClone.RemoveVertex(vertex);

                if (_connectedComponentsCounter.Execute(graphClone) > 1)
                {
                    foundArticulationPoints.Add(vertex);
                }

                graphClone.AddVertex(vertex);
                foreach (var edge in sourceEdges)
                {
                    graphClone.AddUndirectedEdge(edge.Source, edge.Destination);
                }
            }

            return(foundArticulationPoints);
        }
Exemplo n.º 5
0
        public IEnumerable <Edge <TVertex> > Execute(TGraph graph)
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }
            if (_connectedComponentsCounter.Execute(graph) > 1)
            {
                throw new InvalidOperationException("Target graph should be highly connected for searching bridges in it");
            }
            if (!graph.Vertices.Any())
            {
                return(Enumerable.Empty <Edge <TVertex> >());
            }

            #region Algorithm description

            // The algorithm is divided into 3 stages:

            // 1. Preparing graph for searching edge double-connectivity components.
            // Starts the depth-first search from an initial vertex.
            // In the process of walking along the edge [A -> B], it is "oriented" against the direction of movement.
            // When a new (unvisited) vertex is found, it is put at the end of the queue.

            // 2. Finding edge double-connectivity components.
            // The loop is started until the queue is empty.
            // The first vertex from the queue is retrieved, and if this vertex is unvisited, then depth-first search is started from this vertex.
            // In this case, the next component of the edge double-connectivity is formed.
            // As a result, when the queue is empty, components of edge double-connectivity will be formed.

            // 3. Finding those edges that connect vertices of different edge double-connectivity components.
            // Those edges are bridges.

            #endregion

            var initialVertex = graph.Vertices.First();
            var graphClone    = PrepareToSearchForEdgeDoubleConnectivityComponents(graph, initialVertex, out var passedVertices);
            var edgeDoubleConnectivityComponents = FindEdgeDoubleConnectivityComponents(graphClone, passedVertices);
            var bridges = FindBridges(graphClone, edgeDoubleConnectivityComponents);

            return(bridges);
        }
Exemplo n.º 6
0
        public IEnumerable <Edge <TVertex> > Execute(TGraph graph)
        {
            if (graph == null)
            {
                throw new ArgumentNullException(nameof(graph));
            }
            if (_connectedComponentsCounter.Execute(graph) > 1)
            {
                throw new InvalidOperationException("For Kruskal's algorithm graph cannot contain more than one connected component");
            }

            var edges = graph.ReducedEdges;
            var sortedEdgeWeightEntries = graph.Weights.Where(w => edges.Contains(w.Key))
                                          .OrderBy(w => w.Value)
                                          .ToList();

            var graphCopy         = new UndirectedWeightedGraph <TVertex, int>(graph.Vertices) as TGraph;
            var spanningTreeEdges = new List <Edge <TVertex> >();

            foreach (var edgeWeightEntry in sortedEdgeWeightEntries)
            {
                var edge   = edgeWeightEntry.Key;
                var weight = edgeWeightEntry.Value;

                graphCopy.AddUndirectedEdge(edge.Source, edge.Destination, weight);

                if (IsAnyCycleDetected(graphCopy))
                {
                    graphCopy.RemoveUndirectedEdge(edge.Source, edge.Destination);
                }
                else
                {
                    spanningTreeEdges.Add(new Edge <TVertex>(edge.Source, edge.Destination));
                }
            }

            return(spanningTreeEdges);
        }