public virtual string ToSvg(IGraphDescriptor graphDescriptor, IUndirectedGraph<IContent, IUndirectedEdge<IContent>> graph, Action<GraphvizAlgorithm<IContent, IUndirectedEdge<IContent>>> initialization)
        {
            //var stringBuilder = new StringBuilder();
            //using (var xmlWriter = XmlWriter.Create(stringBuilder))
            //{
            //    // This may also need attributes on models, see: http://quickgraph.codeplex.com/wikipage?title=GraphML%20Serialization&referringTitle=Documentation
            //    graph.SerializeToGraphML<TNode, IUndirectedEdge<TNode>, IUndirectedGraph<TNode, IUndirectedEdge<TNode>>>(
            //        xmlWriter,
            //        node => node.Label,
            //        edge => edge.Source.ContentItem.Id.ToString() + edge.Target.ContentItem.Id.ToString());
            //}
            //var graphML = stringBuilder.ToString();

            // Sadly graph.GetHashCode() gives different results on different requests, therefore only the dot hash
            // is reliable. Fortunately it's quite fast.
            var dotData = graph.ToGraphviz(algorithm =>
            {
                initialization(algorithm);
            });

            var filePath = "_AssociativyModules/Frontends/GraphImages/" + graphDescriptor.Name + "/" + dotData.GetHashCode() + ".svg";
            var cacheKey = "Associativy.Frontends.Graphviz.GraphImages." + filePath;

            return _cacheService.GetMonitored(graphDescriptor, cacheKey, () =>
                {
                    using (var lockFile = _lockManager.TryAcquireLock(cacheKey))
                    {
                        return RetrieveImage(dotData, filePath);
                    }
                });
        }
 public UndirectedDijkstraShortestPathAlgorithm(
     IUndirectedGraph <TVertex, TEdge> visitedGraph,
     Func <TEdge, double> weights,
     IDistanceRelaxer distanceRelaxer
     )
     : this(null, visitedGraph, weights, distanceRelaxer)
 {
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UndirectedDijkstraShortestPathAlgorithm{TVertex,TEdge}"/> class.
 /// </summary>
 /// <param name="host">Host to use if set, otherwise use this reference.</param>
 /// <param name="visitedGraph">Graph to visit.</param>
 /// <param name="edgeWeights">Function that computes the weight for a given edge.</param>
 /// <param name="distanceRelaxer">Distance relaxer.</param>
 public UndirectedDijkstraShortestPathAlgorithm(
     [CanBeNull] IAlgorithmComponent host,
     [NotNull] IUndirectedGraph <TVertex, TEdge> visitedGraph,
     [NotNull] Func <TEdge, double> edgeWeights,
     [NotNull] IDistanceRelaxer distanceRelaxer)
     : base(host, visitedGraph, edgeWeights, distanceRelaxer)
 {
 }
Ejemplo n.º 4
0
 public PrimMinimumSpanningTreeAlgorithm(
     IUndirectedGraph <TVertex, TEdge> visitedGraph,
     IDictionary <TEdge, double> edgeWeights
     )
     : base(visitedGraph)
 {
     this.edgeWeights = edgeWeights;
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="KruskalMinimumSpanningTreeAlgorithm{TVertex,TEdge}"/> class.
 /// </summary>
 /// <param name="host">Host to use if set, otherwise use this reference.</param>
 /// <param name="visitedGraph">Graph to visit.</param>
 /// <param name="edgeWeights">Function that computes the weight for a given edge.</param>
 /// <exception cref="T:System.ArgumentNullException"><paramref name="visitedGraph"/> is <see langword="null"/>.</exception>
 /// <exception cref="T:System.ArgumentNullException"><paramref name="edgeWeights"/> is <see langword="null"/>.</exception>
 public KruskalMinimumSpanningTreeAlgorithm(
     [CanBeNull] IAlgorithmComponent host,
     [NotNull] IUndirectedGraph <TVertex, TEdge> visitedGraph,
     [NotNull] Func <TEdge, double> edgeWeights)
     : base(host, visitedGraph)
 {
     _edgeWeights = edgeWeights ?? throw new ArgumentNullException(nameof(edgeWeights));
 }
Ejemplo n.º 6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ConnectedComponentsAlgorithm{TVertex,TEdge}"/> class.
 /// </summary>
 /// <param name="host">Host to use if set, otherwise use this reference.</param>
 /// <param name="visitedGraph">Graph to visit.</param>
 /// <param name="components">Graph components.</param>
 public ConnectedComponentsAlgorithm(
     IAlgorithmComponent host,
     IUndirectedGraph <TVertex, TEdge> visitedGraph,
     IDictionary <TVertex, int> components)
     : base(host, visitedGraph)
 {
     Components = components ?? throw new ArgumentNullException(nameof(components));
 }
 public UndirectedBreadthFirstSearchAlgorithm(
     IUndirectedGraph <TVertex, TEdge> visitedGraph,
     IQueue <TVertex> vertexQueue,
     IDictionary <TVertex, GraphColor> vertexColors
     )
     : this(null, visitedGraph, vertexQueue, vertexColors)
 {
 }
        public void ClusterOneDataObject()
        {
            var nj = new NeighborJoiningClusterer <char>((o1, o2) => 0);
            IUndirectedGraph <Cluster <char>, ClusterEdge <char> > tree = nj.GenerateClusters(new[] { 'A' });

            Assert.That(tree.VertexCount, Is.EqualTo(1));
            Assert.That(tree.IsEdgesEmpty);
        }
 public UndirectedDijkstraShortestPathAlgorithm(
     IUndirectedGraph <TVertex, TEdge> visitedGraph,
     IDictionary <TEdge, double> weights,
     IDistanceRelaxer distanceRelaxer
     )
     : base(visitedGraph, weights, distanceRelaxer)
 {
 }
Ejemplo n.º 10
0
        public static ICollection <TVertex> TopologicalSort <TVertex, TEdge>(
            IUndirectedGraph <TVertex, TEdge> visitedGraph)
            where TEdge : IEdge <TVertex>
        {
            List <TVertex> vertices = new List <TVertex>(visitedGraph.VertexCount);

            TopologicalSort(visitedGraph, vertices);
            return(vertices);
        }
Ejemplo n.º 11
0
 public static TVertex GetFirstVertex <TVertex, TEdge>(IUndirectedGraph <TVertex, TEdge> g)
     where TEdge : IEdge <TVertex>
 {
     foreach (var v in g.Vertices)
     {
         return(v);
     }
     return(default(TVertex));
 }
Ejemplo n.º 12
0
        public static Cluster <T> GetCenter <T>(this IUndirectedGraph <Cluster <T>, ClusterEdge <T> > tree)
        {
            ClusterEdge <T> midpointEdge;
            double          pointOnEdge;
            Cluster <T>     firstCluster;

            GetMidpoint(tree, out midpointEdge, out pointOnEdge, out firstCluster);
            return(pointOnEdge < midpointEdge.Length - pointOnEdge ? firstCluster : midpointEdge.GetOtherVertex(firstCluster));
        }
Ejemplo n.º 13
0
 public static void IsAdjacentEdgesEmpty([PexAssumeUnderTest] IUndirectedGraph <T, E> g)
 {
     foreach (T v in g.Vertices)
     {
         Assert.AreEqual(
             g.IsAdjacentEdgesEmpty(v),
             g.AdjacentDegree(v) == 0);
     }
 }
Ejemplo n.º 14
0
 public UndirectedDijkstraShortestPathAlgorithm(
     IAlgorithmComponent host,
     IUndirectedGraph <TVertex, TEdge> visitedGraph,
     Func <TEdge, double> weights,
     IDistanceRelaxer distanceRelaxer
     )
     : base(host, visitedGraph, weights, distanceRelaxer)
 {
 }
Ejemplo n.º 15
0
        public UndirectedTopologicalSortAlgorithm(
            IUndirectedGraph <TVertex, TEdge> g,
            IList <TVertex> vertices)
            : base(g)
        {
            Contract.Requires(vertices != null);

            this.vertices = vertices;
        }
Ejemplo n.º 16
0
        public void Compute <TVertex, TEdge>([PexAssumeNotNull] IUndirectedGraph <TVertex, TEdge> g)
            where TEdge : IEdge <TVertex>
        {
            var topo =
                new UndirectedFirstTopologicalSortAlgorithm <TVertex, TEdge>(g);

            topo.AllowCyclicGraph = true;
            topo.Compute();
        }
Ejemplo n.º 17
0
        private static void AssertIsEulerian(
            bool expectedEulerian,
            [NotNull] IUndirectedGraph <int, UndirectedEdge <int> > graph)
        {
            var algorithm = new IsEulerianGraphAlgorithm <int, UndirectedEdge <int> >(graph);

            Assert.AreEqual(expectedEulerian, algorithm.IsEulerian());
            Assert.AreEqual(expectedEulerian, IsEulerianGraphAlgorithm.IsEulerian(graph));
        }
Ejemplo n.º 18
0
        private void Compute <TVertex, TEdge>(IUndirectedGraph <TVertex, TEdge> g)
            where TEdge : IEdge <TVertex>
        {
            var topo =
                new UndirectedFirstTopologicalSortAlgorithm <TVertex, TEdge>(g);

            topo.AllowCyclicGraph = true;
            topo.Compute();
        }
Ejemplo n.º 19
0
 protected void Initialize(IUndirectedGraph <TVertex, TEdge> graph)
 {
     this.graph = graph;
     vertexColors.Clear();
     foreach (TVertex u in graph.Vertices)
     {
         vertexColors.Add(u, VertexColor.White);
     }
 }
Ejemplo n.º 20
0
        public void GraphWithSelfEdges(IUndirectedGraph <string, Edge <string> > graph)
        {
            List <string> vertices = new List <string>(graph.Vertices);

            foreach (string v in vertices)
            {
                Search(graph, v);
            }
        }
        public static IDictionary <string, double> Get(IUndirectedGraph <string, TaggedEdge <string, string> > graph, string root)
        {
            Func <TaggedEdge <string, string>, double> Weights = e => double.Parse(e.Tag);

            var algorithm = new UndirectedDijkstraShortestPathAlgorithm <string, TaggedEdge <string, string> >(graph, Weights);

            algorithm.Compute(root);
            return(algorithm.Distances);
        }
        public static IDictionary <int, double> Get(IUndirectedGraph <int, Edge <int> > graph, int root)
        {
            Func <Edge <int>, double> Weights = e => 1.0;

            var algorithm = new UndirectedDijkstraShortestPathAlgorithm <int, Edge <int> >(graph, Weights);

            algorithm.Compute(root);
            return(algorithm.Distances);
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Creates an immutable array undirected graph from the input graph
        /// </summary>
        /// <typeparam name="TVertex">type of the vertices</typeparam>
        /// <typeparam name="TEdge">type of the edges</typeparam>
        /// <param name="graph"></param>
        /// <returns></returns>
        public static ArrayUndirectedGraph <TVertex, TEdge> ToArrayUndirectedGraph <TVertex, TEdge>(
            this IUndirectedGraph <TVertex, TEdge> graph
            )
            where TEdge : IEdge <TVertex>
        {
            Contract.Requires(graph != null);

            return(new ArrayUndirectedGraph <TVertex, TEdge>(graph));
        }
Ejemplo n.º 24
0
        public ConnectedComponentsAlgorithm(
            IAlgorithmComponent host,
            IUndirectedGraph <TVertex, TEdge> visitedGraph,
            IDictionary <TVertex, int> components)
            : base(host, visitedGraph)
        {
            Contract.Requires(components != null);

            this.components = components;
        }
Ejemplo n.º 25
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UndirectedShortestPathAlgorithmBase{TVertex,TEdge}"/> class.
 /// </summary>
 /// <param name="host">Host to use if set, otherwise use this reference.</param>
 /// <param name="visitedGraph">Graph to visit.</param>
 /// <param name="edgeWeights">Function that computes the weight for a given edge.</param>
 /// <param name="distanceRelaxer">Distance relaxer.</param>
 /// <exception cref="T:System.ArgumentNullException"><paramref name="visitedGraph"/> is <see langword="null"/>.</exception>
 /// <exception cref="T:System.ArgumentNullException"><paramref name="edgeWeights"/> is <see langword="null"/>.</exception>
 /// <exception cref="T:System.ArgumentNullException"><paramref name="distanceRelaxer"/> is <see langword="null"/>.</exception>
 protected UndirectedShortestPathAlgorithmBase(
     [CanBeNull] IAlgorithmComponent host,
     [NotNull] IUndirectedGraph <TVertex, TEdge> visitedGraph,
     [NotNull] Func <TEdge, double> edgeWeights,
     [NotNull] IDistanceRelaxer distanceRelaxer)
     : base(host, visitedGraph)
 {
     Weights         = edgeWeights ?? throw new ArgumentNullException(nameof(edgeWeights));
     DistanceRelaxer = distanceRelaxer ?? throw new ArgumentNullException(nameof(distanceRelaxer));
 }
Ejemplo n.º 26
0
 private static void GenerateRootedTree <T>(IUndirectedGraph <Cluster <T>, ClusterEdge <T> > unrootedTree, Cluster <T> parent, Cluster <T> node, BidirectionalGraph <Cluster <T>, ClusterEdge <T> > rootedTree)
 {
     foreach (ClusterEdge <T> edge in unrootedTree.AdjacentEdges(node).Where(e => e.GetOtherVertex(node) != parent))
     {
         Cluster <T> otherCluster = edge.GetOtherVertex(node);
         rootedTree.AddVertex(otherCluster);
         rootedTree.AddEdge(new ClusterEdge <T>(node, otherCluster, edge.Length));
         GenerateRootedTree(unrootedTree, node, otherCluster, rootedTree);
     }
 }
Ejemplo n.º 27
0
        public void Prim<TVertex, TEdge>([PexAssumeNotNull]IUndirectedGraph<TVertex, TEdge> g)
             where TEdge : IEdge<TVertex>
        {
            var distances = new Dictionary<TEdge, double>();
            foreach (var e in g.Edges)
                distances[e] = g.AdjacentDegree(e.Source) + 1;

            var edges = AlgorithmExtensions.MinimumSpanningTreePrim(g, e => distances[e]);
            AssertSpanningTree(g, edges);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="BidirectionalDepthFirstSearchAlgorithm{TVertex,TEdge}"/> class.
 /// </summary>
 /// <param name="host">Host to use if set, otherwise use this reference.</param>
 /// <param name="visitedGraph">Graph to visit.</param>
 /// <param name="verticesColors">Vertices associated to their colors (treatment states).</param>
 /// <param name="adjacentEdgesFilter">
 /// Delegate that takes the enumeration of out-edges and filters/reorders
 /// them. All vertices passed to the method should be enumerated once and only once.
 /// </param>
 public UndirectedDepthFirstSearchAlgorithm(
     [CanBeNull] IAlgorithmComponent host,
     [NotNull] IUndirectedGraph <TVertex, TEdge> visitedGraph,
     [NotNull] IDictionary <TVertex, GraphColor> verticesColors,
     [NotNull] Func <IEnumerable <TEdge>, IEnumerable <TEdge> > adjacentEdgesFilter)
     : base(host, visitedGraph)
 {
     VerticesColors      = verticesColors ?? throw new ArgumentNullException(nameof(verticesColors));
     AdjacentEdgesFilter = adjacentEdgesFilter ?? throw new ArgumentNullException(nameof(adjacentEdgesFilter));
 }
Ejemplo n.º 29
0
        public void Kruskal<TVertex,TEdge>([PexAssumeNotNull]IUndirectedGraph<TVertex, TEdge> g)
            where TEdge : IEdge<TVertex>
        {
            var distances = new Dictionary<TEdge, double>();
            foreach(var e in g.Edges)
                distances[e] = g.AdjacentDegree(e.Source) + 1;

            var kruskal = new KruskalMinimumSpanningTreeAlgorithm<TVertex, TEdge>(g, e => distances[e]);
            AssertMinimumSpanningTree<TVertex, TEdge>(g, kruskal);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="UndirectedBreadthFirstSearchAlgorithm{TVertex,TEdge}"/> class.
 /// </summary>
 /// <param name="host">Host to use if set, otherwise use this reference.</param>
 /// <param name="visitedGraph">Graph to visit.</param>
 /// <param name="vertexQueue">Queue of vertices to treat.</param>
 /// <param name="verticesColors">Vertices associated to their colors (treatment states).</param>
 public UndirectedBreadthFirstSearchAlgorithm(
     [CanBeNull] IAlgorithmComponent host,
     [NotNull] IUndirectedGraph <TVertex, TEdge> visitedGraph,
     [NotNull] IQueue <TVertex> vertexQueue,
     [NotNull] IDictionary <TVertex, GraphColor> verticesColors)
     : base(host, visitedGraph)
 {
     VerticesColors = verticesColors ?? throw new ArgumentNullException(nameof(verticesColors));
     _vertexQueue   = vertexQueue ?? throw new ArgumentNullException(nameof(vertexQueue));
 }
Ejemplo n.º 31
0
        public void Compute([PexAssumeNotNull] IUndirectedGraph <string, Edge <string> > g)
        {
            UndirectedTopologicalSortAlgorithm <string, Edge <string> > topo =
                new UndirectedTopologicalSortAlgorithm <string, Edge <string> >(g);

            topo.AllowCyclicGraph = true;
            topo.Compute();

            Display(topo);
        }
Ejemplo n.º 32
0
        public static bool PathExistsInGraph(IUndirectedGraph<int, IUndirectedEdge<int>> graph, IEnumerable<IContent> path)
        {
            var pathList = path.ToList();
            if (!graph.ContainsVertex(pathList[0].Id)) return false;

            var nextIndex = 1;
            var node = pathList[0].Id;
            while (node != pathList.Last().Id)
            {
                var nextNode = pathList[nextIndex].Id;
                if (!graph.AdjacentEdges(node).Any(edge => edge.Target == nextNode || edge.Source == nextNode)) return false;
                node = nextNode;
                nextIndex++;
            }

            return true;
        }
Ejemplo n.º 33
0
        public virtual IUndirectedGraph<IContent, IUndirectedEdge<IContent>> MakeContentGraph(IUndirectedGraph<int, IUndirectedEdge<int>> idGraph)
        {
            var nodes = GetQuery().ForContentItems(idGraph.Vertices).List().ToDictionary(node => node.Id);

            var graph = _graphEditor.GraphFactory<IContent>();
            graph.AddVertexRange(nodes.Values);

            foreach (var edge in idGraph.Edges)
            {
                // Since the query can be modified in an event handler and it could have removed items, this check is necessary
                if (nodes.ContainsKey(edge.Source) && nodes.ContainsKey(edge.Target))
                {
                    graph.AddEdge(new UndirectedEdge<IContent>(nodes[edge.Source], nodes[edge.Target]));
                }
            }

            return graph;
        }
        public void Compute(IUndirectedGraph<string, Edge<string>> g)
        {
            Dictionary<Edge<string>, double> distances = new Dictionary<Edge<string>,double>();
            foreach(Edge<string> edge in g.Edges)
                distances.Add(edge, 1);
            PrimMinimumSpanningTreeAlgorithm<string, Edge<string>> prim = new PrimMinimumSpanningTreeAlgorithm<string, Edge<string>>(g, distances);

            VertexPredecessorRecorderObserver<string, Edge<string>> predecessors = new VertexPredecessorRecorderObserver<string, Edge<string>>();
            predecessors.Attach(prim);
            prim.Compute();

            foreach (string v in g.Vertices)
            {
                Edge<string> edge;
                if (predecessors.VertexPredecessors.TryGetValue(v, out edge))
                    Console.WriteLine("{0}: {1}", v, edge);
                else
                    Console.WriteLine("{0}", v);
            }
        }
Ejemplo n.º 35
0
 private static IBidirectionalGraph<HierarchicalGraphVertex, HierarchicalGraphEdge> BuildHierarchicalGraph(IUndirectedGraph<Cluster<Variety>, ClusterEdge<Variety>> tree)
 {
     var graph = new BidirectionalGraph<HierarchicalGraphVertex, HierarchicalGraphEdge>();
     var root = new HierarchicalGraphVertex(0);
     graph.AddVertex(root);
     GenerateHierarchicalVertices(graph, root, tree, null, tree.GetCenter());
     return graph;
 }
        public void GraphWithSelfEdges(IUndirectedGraph<string,Edge<string>> graph)
        {
            List<string> vertices = new List<string>(graph.Vertices);

            foreach (string v in vertices)
                Search(graph, v);
        }
 private dynamic LastStepsWithPaging(IExecutionParams parameters, IUndirectedGraph<int, IUndirectedEdge<int>> graph, string cacheName, IPathFinderSettings settings)
 {
     return QueryableGraphHelper.LastStepsWithPaging(new LastStepParams
     {
         CacheService = _pathFinderAuxiliaries.CacheService,
         GraphEditor = _pathFinderAuxiliaries.GraphEditor,
         GraphDescriptor = _graphDescriptor,
         ExecutionParameters = parameters,
         Graph = graph,
         BaseCacheKey = MakeCacheKey(cacheName, settings)
     });
 }
Ejemplo n.º 38
0
 protected dynamic LastSteps(IExecutionParams parameters, IUndirectedGraph<int, IUndirectedEdge<int>> graph, string cacheName, IMindSettings settings)
 {
     return QueryableGraphHelper.LastSteps(new LastStepParams
     {
         CacheService = _cacheService,
         GraphEditor = _graphEditor,
         GraphDescriptor = _graphDescriptor,
         ExecutionParameters = parameters,
         Graph = graph,
         BaseCacheKey = MakeCacheKey(cacheName, settings)
     });
 }
Ejemplo n.º 39
0
        private static void GenerateHierarchicalVertices(BidirectionalGraph<HierarchicalGraphVertex, HierarchicalGraphEdge> graph, HierarchicalGraphVertex vertex,
			IUndirectedGraph<Cluster<Variety>, ClusterEdge<Variety>> tree, Cluster<Variety> parent, Cluster<Variety> cluster)
        {
            foreach (ClusterEdge<Variety> edge in tree.AdjacentEdges(cluster).Where(e => e.GetOtherVertex(cluster) != parent))
            {
                Cluster<Variety> target = edge.GetOtherVertex(cluster);
                double depth = vertex.Depth + edge.Length;
                var newVertex = target.DataObjects.Count == 1 ? new HierarchicalGraphVertex(target.DataObjects.First(), depth) : new HierarchicalGraphVertex(depth);
                graph.AddVertex(newVertex);
                graph.AddEdge(new HierarchicalGraphEdge(vertex, newVertex, edge.Length));
                GenerateHierarchicalVertices(graph, newVertex, tree, cluster, target);
            }
        }
        private void Search(IUndirectedGraph<string,Edge<string>> graph, string rootVertex)
        {
            Console.WriteLine(rootVertex);
            algo = new UndirectedBreadthFirstSearchAlgorithm<string,Edge<string>>(graph);
            try
            {
                algo.InitializeVertex += new VertexEventHandler<string>(this.InitializeVertex);
                algo.DiscoverVertex += new VertexEventHandler<string>(this.DiscoverVertex);
                algo.ExamineVertex += new VertexEventHandler<string>(this.ExamineVertex);
                algo.TreeEdge += new EdgeEventHandler<string,Edge<string>>(this.TreeEdge);
                algo.NonTreeEdge += new EdgeEventHandler<string,Edge<string>>(this.NonTreeEdge);
                algo.GrayTarget += new EdgeEventHandler<string,Edge<string>>(this.GrayTarget);
                algo.BlackTarget += new EdgeEventHandler<string,Edge<string>>(this.BlackTarget);
                algo.FinishVertex += new VertexEventHandler<string>(this.FinishVertex);

                parents.Clear();
                distances.Clear();
                currentDistance = 0;
                sourceVertex = rootVertex;

                foreach (string v in this.algo.VisitedGraph.Vertices)
                {
                    distances[v] = int.MaxValue;
                    parents[v] = v;
                }
                distances[sourceVertex] = 0;
                algo.Compute(sourceVertex);

                CheckBfs();
            }
            finally
            {
                algo.InitializeVertex -= new VertexEventHandler<string>(this.InitializeVertex);
                algo.DiscoverVertex -= new VertexEventHandler<string>(this.DiscoverVertex);
                algo.ExamineVertex -= new VertexEventHandler<string>(this.ExamineVertex);
                algo.TreeEdge -= new EdgeEventHandler<string,Edge<string>>(this.TreeEdge);
                algo.NonTreeEdge -= new EdgeEventHandler<string,Edge<string>>(this.NonTreeEdge);
                algo.GrayTarget -= new EdgeEventHandler<string,Edge<string>>(this.GrayTarget);
                algo.BlackTarget -= new EdgeEventHandler<string,Edge<string>>(this.BlackTarget);
                algo.FinishVertex -= new VertexEventHandler<string>(this.FinishVertex);
            }
        }
        public static void ContainsEdgeAssertions(IUndirectedGraph<int, IEdge<int>> g,
            IEdge<int> e12,
            IEdge<int> f12,
            IEdge<int> e21,
            IEdge<int> f21)
        {
            Assert.AreEqual(1, g.AdjacentDegree(1));
            Assert.AreEqual(1, g.AdjacentDegree(2));
            Assert.AreEqual(1, g.AdjacentEdges(1).Count());
            Assert.AreEqual(1, g.AdjacentEdges(2).Count());

            // e12 must be present in u, because we added it.
            Assert.IsTrue(g.ContainsEdge(e12));

            // f12 is also in u, because e12 == f12.
            Assert.IsTrue(g.ContainsEdge(f12));

            // e21 and f21 are not in u, because ContainsEdge has semantics that 
            // if it returns true for an edge, that edge must be physically present in 
            // the collection of edges inside u.
            if (e21 != null) Assert.IsFalse(g.ContainsEdge(e21));
            if (f21 != null) Assert.IsFalse(g.ContainsEdge(f21));

            // there must be an edge between vertices 1, 2.
            Assert.IsTrue(g.ContainsEdge(1, 2));

            // there is also an edge between vertices 2, 1, because the graph is undirected.
            Assert.IsTrue(g.ContainsEdge(2, 1));

            // obviously no edge between vertices 1, 3, as vertex 3 is not even present in the graph.
            Assert.IsFalse(g.ContainsEdge(1, 3));
        }