public void FindSet() { FindSetTest(1, 2); FindSetTest( new TestVertex("1"), new TestVertex("2")); FindSetTest( new EquatableTestVertex("1"), new EquatableTestVertex("2")); #region Local function void FindSetTest <TValue>(TValue value1, TValue value2) { var set = new ForestDisjointSet <TValue>(); AssertSetSizes(set, 0, 0); set.MakeSet(value1); AssertSetSizes(set, 1, 1); AssertEqual(value1, set.FindSet(value1)); set.MakeSet(value2); AssertSetSizes(set, 2, 2); AssertEqual(value1, set.FindSet(value1)); AssertEqual(value2, set.FindSet(value2)); set.Union(value1, value2); AssertSetSizes(set, 1, 2); AssertEqual(value1, set.FindSet(value1)); AssertEqual(value1, set.FindSet(value2)); } #endregion }
public void FindSet_Throws() { var vertex = new TestVertex(); var set = new ForestDisjointSet <TestVertex>(); // ReSharper disable ReturnValueOfPureMethodIsNotUsed // ReSharper disable once AssignNullToNotNullAttribute Assert.Throws <ArgumentNullException>(() => set.FindSet(null)); Assert.Throws <KeyNotFoundException>(() => set.FindSet(vertex)); // ReSharper restore ReturnValueOfPureMethodIsNotUsed }
/// <summary> /// Gets a copy of the connected components. Key is the number of components, /// Value contains the vertex -> component index map. /// </summary> /// <returns>Number of components associated to components vertex mapping.</returns> public KeyValuePair <int, IDictionary <TVertex, int> > GetComponents() { if (_sets is null) { throw new InvalidOperationException("Run the algorithm before."); } var representatives = new Dictionary <TVertex, int>(_sets.SetCount); if (_components is null) { _components = new Dictionary <TVertex, int>(VisitedGraph.VertexCount); } foreach (TVertex vertex in VisitedGraph.Vertices) { TVertex representative = _sets.FindSet(vertex); // ReSharper disable once AssignNullToNotNullAttribute, Justification: All graph vertices are in a set if (!representatives.TryGetValue(representative, out int index)) { representatives[representative] = index = representatives.Count; } _components[vertex] = index; } Debug.Assert(_sets.SetCount == ComponentCount); Debug.Assert(_components.Count == VisitedGraph.VertexCount); return(new KeyValuePair <int, IDictionary <TVertex, int> >(_sets.SetCount, _components)); }
/// <inheritdoc /> protected override void InternalCompute() { if (!TryGetRootVertex(out TVertex root)) { throw new InvalidOperationException("Root vertex not set."); } if (_pairs is null) { throw new InvalidProgramException("Pairs not set."); } var graph = _pairs.ToAdjacencyGraph(); var disjointSet = new ForestDisjointSet <TVertex>(); var verticesAncestors = new Dictionary <TVertex, TVertex>(); var dfs = new DepthFirstSearchAlgorithm <TVertex, TEdge>( this, VisitedGraph, new Dictionary <TVertex, GraphColor>(VisitedGraph.VertexCount)); dfs.InitializeVertex += vertex => disjointSet.MakeSet(vertex); dfs.DiscoverVertex += vertex => verticesAncestors[vertex] = vertex; dfs.TreeEdge += edge => { disjointSet.Union(edge.Source, edge.Target); // ReSharper disable once AssignNullToNotNullAttribute // Justification: must be in the set because unioned just before. verticesAncestors[disjointSet.FindSet(edge.Source)] = edge.Source; }; dfs.FinishVertex += vertex => { foreach (SEquatableEdge <TVertex> edge in graph.OutEdges(vertex)) { if (dfs.VerticesColors[edge.Target] == GraphColor.Black) { SEquatableEdge <TVertex> pair = edge.ToVertexPair(); // ReSharper disable once AssignNullToNotNullAttribute // Justification: must be present in the set. Ancestors[pair] = verticesAncestors[disjointSet.FindSet(edge.Target)]; } } }; // Run DFS dfs.Compute(root); }
protected override void InternalCompute() { var cancelManager = this.Services.CancelManager; TVertex root; if (!this.TryGetRootVertex(out root)) { throw new InvalidOperationException("root vertex not set"); } if (this.pairs == null) { throw new InvalidOperationException("pairs not set"); } var gpair = GraphExtensions.ToAdjacencyGraph(this.pairs); var disjointSet = new ForestDisjointSet <TVertex>(); var vancestors = new Dictionary <TVertex, TVertex>(); var dfs = new DepthFirstSearchAlgorithm <TVertex, TEdge>(this, this.VisitedGraph, new Dictionary <TVertex, GraphColor>(this.VisitedGraph.VertexCount)); dfs.InitializeVertex += v => disjointSet.MakeSet(v); dfs.DiscoverVertex += v => vancestors[v] = v; dfs.TreeEdge += edge => { disjointSet.Union(edge.Source, edge.Target); vancestors[disjointSet.FindSet(edge.Source)] = edge.Source; }; dfs.FinishVertex += v => { foreach (var e in gpair.OutEdges(v)) { if (dfs.VertexColors[e.Target] == GraphColor.Black) { this.ancestors[EdgeExtensions.ToVertexPair <TVertex, SEquatableEdge <TVertex> >(e)] = vancestors[disjointSet.FindSet(e.Target)]; } } }; // go! dfs.Compute(root); }