コード例 #1
0
        public void Ctor_ShouldInitializeAdjacencyLists()
        {
            var graph = new MixedGraph <int>();

            Assert.NotNull(graph.AdjacencyLists);
            Assert.Empty(graph.AdjacencyLists);
        }
コード例 #2
0
        public void Ctor_ShouldInitializeAdjacencyListsWithVerticesAndEdges()
        {
            var vertices = new List <int> {
                0, 1, 2, 3
            };
            var directedEdges = new List <Edge <int> >
            {
                new Edge <int>(0, 1),
            };
            var undirectedEdges = new List <Edge <int> >
            {
                new Edge <int>(1, 2),
                new Edge <int>(0, 2)
            };
            var expectedAdjacencyLists = new Dictionary <int, IReadOnlyList <int> >()
            {
                [0] = new List <int>()
                {
                    1, 2
                },
                [1] = new List <int>()
                {
                    2
                },
                [2] = new List <int>()
                {
                    1, 0
                },
                [3] = new List <int>(),
            };

            var graph = new MixedGraph <int>(vertices, directedEdges, undirectedEdges);

            Assert.Equal(expectedAdjacencyLists, graph.AdjacencyLists);
        }
コード例 #3
0
        public void RemoveUndirectedEdge_ShouldRemoveConnectedVertexFromAdjacencyLists_WhenExistingKeysSpecified(
            MixedGraph <int> graph,
            int sourceToRemove,
            int destinationToRemove,
            Dictionary <int, IReadOnlyList <int> > expectedAdjacencyLists)
        {
            graph.RemoveUndirectedEdge(sourceToRemove, destinationToRemove);

            Assert.Equal(expectedAdjacencyLists, graph.AdjacencyLists);
        }
コード例 #4
0
        /// <summary>
        /// Starts depth-first search from an initial vertex, orienting each visited edge against its direction
        /// </summary>
        /// <param name="graph">Target graph</param>
        /// <param name="initialVertex">Initial vertex for DFS</param>
        /// <param name="passedVertices">Passed vertices queue</param>
        /// <returns>Modified (mixed) graph with each visited edge oriented against its direction</returns>
        private MixedGraph <TVertex> PrepareToSearchForEdgeDoubleConnectivityComponents(TGraph graph, TVertex initialVertex, out Queue <TVertex> passedVertices)
        {
            var graphClone = new MixedGraph <TVertex>(
                graph.Vertices,
                Enumerable.Empty <Edge <TVertex> >(),
                graph.ReducedEdges);
            var visitedVertices = new HashSet <TVertex>(new TVertex[] { initialVertex }, _verticesComparer);

            DfsGraphAndRemoveVisitedEdges(graphClone, initialVertex, visitedVertices);
            passedVertices = new Queue <TVertex>(visitedVertices);
            visitedVertices.Clear();
            return(graphClone);
        }
コード例 #5
0
        public void Ctor_ShouldInitializeAdjacencyListsWithVertices()
        {
            var vertices = new List <int> {
                0, 1, 2, 3
            };

            var graph = new MixedGraph <int>(vertices);

            Assert.Equal(vertices, graph.AdjacencyLists.Keys);
            Assert.All(graph.AdjacencyLists.Values, list =>
            {
                Assert.Empty(list);
            });
        }
コード例 #6
0
        /// <summary>
        /// Performs depth-first search on single graph's edge double-connectivity component and marks this component's vertices with component's id
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="sourceVertex">Current vertex</param>
        /// <param name="visitedVertices">Visited vertices</param>
        /// <param name="edgeDoubleConnectivityComponents">Vertex to edge double-connectivity component mapping dictionary</param>
        /// <param name="curEdgeDoubleConnectivityComponentId">Current edge double-connectivity component's ID</param>
        private void DfsEdgeDoubleConnectivityComponent(MixedGraph <TVertex> graph, TVertex sourceVertex, ISet <TVertex> visitedVertices, IDictionary <TVertex, int?> edgeDoubleConnectivityComponents, int curEdgeDoubleConnectivityComponentId)
        {
            var notVisitedNeighbourVertices = graph.AdjacencyLists[sourceVertex].ToList();

            foreach (var neighbourVertex in notVisitedNeighbourVertices)
            {
                if (!visitedVertices.Contains(neighbourVertex) && !edgeDoubleConnectivityComponents[neighbourVertex].HasValue)
                {
                    visitedVertices.Add(neighbourVertex);
                    edgeDoubleConnectivityComponents[neighbourVertex] = curEdgeDoubleConnectivityComponentId;
                    DfsEdgeDoubleConnectivityComponent(graph, neighbourVertex, visitedVertices, edgeDoubleConnectivityComponents, curEdgeDoubleConnectivityComponentId);
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// Performs depth-first search on graph, orienting each visited edge against its direction
        /// </summary>
        /// <param name="graph">Graph</param>
        /// <param name="sourceVertex">Current vertex</param>
        /// <param name="visitedVertices">Visited vertices</param>
        private void DfsGraphAndRemoveVisitedEdges(MixedGraph <TVertex> graph, TVertex sourceVertex, ISet <TVertex> visitedVertices)
        {
            var notVisitedNeighbourVertices = graph.AdjacencyLists[sourceVertex].ToList();

            foreach (var neighbourVertex in notVisitedNeighbourVertices)
            {
                if (!visitedVertices.Contains(neighbourVertex))
                {
                    visitedVertices.Add(neighbourVertex);
                    graph.RemoveDirectedEdge(sourceVertex, neighbourVertex);
                    DfsGraphAndRemoveVisitedEdges(graph, neighbourVertex, visitedVertices);
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Finds edges that connect vertices of different edge double-connectivity components
        /// </summary>
        /// <param name="graphClone">Modified graph</param>
        /// <param name="edgeDoubleConnectivityComponents">Vertex to edge double-connectivity component mapping dictionary</param>
        /// <returns>Edges that connect vertices of different edge double-connectivity components</returns>
        private IEnumerable <Edge <TVertex> > FindBridges(MixedGraph <TVertex> graphClone, IDictionary <TVertex, int?> edgeDoubleConnectivityComponents)
        {
            var bridges = new List <Edge <TVertex> >();

            foreach (var edge in graphClone.ReducedEdges)
            {
                var sourceComponentId      = edgeDoubleConnectivityComponents[edge.Source];
                var destinationComponentId = edgeDoubleConnectivityComponents[edge.Destination];

                if (sourceComponentId != destinationComponentId)
                {
                    bridges.Add(edge);
                }
            }

            return(bridges);
        }
コード例 #9
0
        /// <summary>
        /// Finds edge double-connectivity components for graph
        /// </summary>
        /// <param name="graphClone">Modified graph from previous stage</param>
        /// <param name="passedVertices">Passed vertices queue from previous stage</param>
        /// <returns>Dictionary where keys are vertices and values are edge double-connectivity component's id, which corresponding key vertex belongs to
        /// </returns>
        private IDictionary <TVertex, int?> FindEdgeDoubleConnectivityComponents(MixedGraph <TVertex> graphClone, Queue <TVertex> passedVertices)
        {
            var curEdgeDoubleConnectivityComponentId = 0;
            var edgeDoubleConnectivityComponents     = graphClone.Vertices.ToDictionary(v => v, v => new int?());

            while (passedVertices.Any())
            {
                var curVertex = passedVertices.Dequeue();

                if (edgeDoubleConnectivityComponents[curVertex].HasValue)
                {
                    continue;
                }

                var visitedVertices = new HashSet <TVertex>(new TVertex[] { curVertex }, _verticesComparer);
                edgeDoubleConnectivityComponents[curVertex] = curEdgeDoubleConnectivityComponentId;
                DfsEdgeDoubleConnectivityComponent(graphClone, curVertex, visitedVertices, edgeDoubleConnectivityComponents, curEdgeDoubleConnectivityComponentId);
                curEdgeDoubleConnectivityComponentId++;
            }

            return(edgeDoubleConnectivityComponents);
        }
コード例 #10
0
 public void RemoveUndirectedEdge_ShouldThrowKeyNotFoundException_WhenNotExistingKeySpecified(MixedGraph <int> graph, int source, int destination)
 {
     Assert.Throws <KeyNotFoundException>(() =>
     {
         graph.RemoveUndirectedEdge(source, destination);
     });
 }
コード例 #11
0
 public void AddUndirectedEdge_ShouldThrowInvalidOperationException_WhenEdgeCreatesLoopOrMultipleEdge(MixedGraph <int> graph, int source, int destination)
 {
     Assert.Throws <InvalidOperationException>(() =>
     {
         graph.AddUndirectedEdge(source, destination);
     });
 }