public void Union_ThrowsOnElementsInTheSameSet2() { var sets = new DisjointSets <int>(new int[] { 1, 2, 3, 4 }); sets.Union(4, 3); sets.Union(3, 2); sets.Union(2, 1); Assert.That(() => sets.Union(1, 4), Throws.ArgumentException); }
public void GetSet_TypicalCase2() { var sets = new DisjointSets <int>(new int[] { 1, 2, 3, 4, 5, 6 }); sets.Union(1, 2); sets.Union(1, 6); sets.Union(3, 4); Assert.That(sets.GetSet(1), Is.EquivalentTo(new HashSet <int>(new int[] { 1, 2, 6 }))); Assert.That(sets.GetSet(2), Is.EquivalentTo(new HashSet <int>(new int[] { 1, 2, 6 }))); Assert.That(sets.GetSet(6), Is.EquivalentTo(new HashSet <int>(new int[] { 1, 2, 6 }))); Assert.That(sets.GetSet(3), Is.EquivalentTo(new HashSet <int>(new int[] { 3, 4 }))); Assert.That(sets.GetSet(4), Is.EquivalentTo(new HashSet <int>(new int[] { 3, 4 }))); Assert.That(sets.GetSet(5), Is.EquivalentTo(new HashSet <int>(new int[] { 5 }))); }
public List <Edge> GetMST(Graph graph) { List <Edge> mst = new List <Edge>(); // Sort the edges in ascending order of their weights List <Edge> sortedEdges = graph.AllEdges.OrderBy(e => e.Weight).ToList(); int totalNumOfVertices = graph.AllVertices.Count(); DisjointSets <int> ds = new DisjointSets <int>(); foreach (Edge e in sortedEdges) { if (mst.Count() >= totalNumOfVertices) { // total number of edges in an mst will be total number of vertices in a graph -1 break; } if (!ds.Find(e.StId, e.EndId)) { // the stId and endId vertex of the edge are not in the same set // hence adding this edge wont create a cycle ds.Union(e.StId, e.EndId); mst.Add(e); } } return(mst); }
public static List <Edge> MinimumSpanningTree(IGraph g) { var result = new List <Edge>(); var edges = g.Edges().OrderBy(e => e.weight).ToArray(); var vertexCount = g.VertexesCount(); var sets = new DisjointSets <int>(); foreach (var edge in edges) { if (sets.ItemCount == vertexCount) { break; } var setFrom = sets.MakeSet(edge.from); var setTo = sets.MakeSet(edge.to); if (setFrom != setTo) { sets.Union(setFrom, setTo); result.Add(edge); } } return(result); }
public KruskalMST(Graph g) { BinaryHeapPQ <Edge> pq = new BinaryHeapPQ <Edge>(); for (int v = 0; v < g.V; v++) { for (int i = 0; i < g.Deg(v); i++) { pq.Insert(new Edge() { U = v, V = g.AdjV(v, i), W = g.AdjW(v, i) }); } } DisjointSets ds = new DisjointSets(g.V); while (pq.Count > 0 && mst.Count < g.V - 1) { Edge e = pq.ExtractMin(); int v = e.U; int w = e.V; if (ds.FindSet(v) != ds.FindSet(w)) { ds.Union(v, w); mst.Add(e); } } }
public static bool DetectCycleinUndirectedGraphUsingDisjointSets <T>(this Graph <T> g, out long v1, out long v2) { DisjointSets ds = new DisjointSets(); v1 = Int32.MaxValue; v2 = Int32.MaxValue; //Step 1: Make a set for all nodes in graph foreach (var v in g.AllVertex.Values) { ds.MakeSet(v.Id); } //For all edges, findset each vertex. // If the findset does not match, do union else you have found a cycle foreach (var edge in g.AllEdges) { var n1 = ds.FindSet(edge.V1.Id); var n2 = ds.FindSet(edge.V2.Id); if (n1 == n2) { v1 = edge.V1.Id; v2 = edge.V2.Id; return(true); } ds.Union(edge.V1.Id, edge.V2.Id); } return(false); }
/// <summary> /// Compute comparability for a method's parameters based on the types of the parameters. Two parameters /// are considered comparable if one can be assigned to the other. /// </summary> /// <param name="parameters">the parameters</param> /// <seealso cref="TypeHelper.TypesAreAssignmentCompatible"/> /// <returns>comparability sets for the parameters</returns> public static HashSet <HashSet <string> > ParameterTypeComparability(IEnumerable <IParameterDefinition> parameters) { Contract.Requires(parameters != null); Contract.Ensures(Contract.Result <HashSet <HashSet <string> > >() != null); Dictionary <IParameterDefinition, int> ids = new Dictionary <IParameterDefinition, int>(); DisjointSets cmp = new DisjointSets(); foreach (var p in parameters) { ids.Add(p, cmp.AddElement()); } foreach (var lhs in parameters) { Contract.Assume(ids.ContainsKey(lhs), "Error tracking parameter " + lhs.Name); foreach (var rhs in parameters) { Contract.Assume(ids.ContainsKey(rhs), "Error tracking parameter " + rhs.Name); if (TypeHelper.TypesAreAssignmentCompatible(lhs.Type.ResolvedType, rhs.Type.ResolvedType, true)) { cmp.Union(cmp.FindSet(ids[lhs]), cmp.FindSet(ids[rhs])); } } } var result = new HashSet <HashSet <string> >(ids.Keys.GroupBy(p => cmp.FindSet(ids[p])).Select(g => new HashSet <string>(g.Select(p => p.Name.Value)))); return(result); }
public void DisjoinSetsPerformanceTest() { #region Arrange var numElements = 1000000; var djs = new DisjointSets(numElements); #endregion #region Act var firstRoot = 0; var secondRoot = numElements / 2; djs.CreateSet(firstRoot); djs.CreateSet(secondRoot); for (int i = 0; i < numElements; i++) { if (i != firstRoot && i != secondRoot) { if (i < secondRoot) { djs.AddToSet(firstRoot, i); } else { djs.AddToSet(secondRoot, i); } } } djs.Union(firstRoot, secondRoot); #endregion #region Assert Assert.AreEqual(1, djs.SetsCount); for (int i = 0; i < numElements; i++) { Assert.AreEqual(0, djs.GetIncludingSetId(i)); } #endregion }
public void Union_TypicalCase() { var sets = new DisjointSets <int>(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); sets.Union(1, 2); sets.Union(2, 3); sets.Union(3, 4); sets.Union(5, 6); sets.Union(3, 7); foreach (int i in new int[] { 1, 2, 3, 4, 5, 6, 7 }) { Assert.That(new int[] { sets.FindSet(i) }, Is.SubsetOf(new int[] { 1, 2, 3, 4, 5, 6, 7 })); // Sort of hacky; Is.MemberOf would be better } foreach (int i in new int[] { 8, 9, 10 }) { Assert.That(sets.FindSet(i), Is.EqualTo(i)); } }
// Complete the maxRegion function below. static int maxRegion(int[][] matrix) { var xOffset = new[] { -1, 0, 1, -1 }; var yOffset = new[] { -1, -1, -1, 0 }; var ds = new DisjointSets(); var rows = matrix.Length; var cols = matrix[0].Length; var max = 0; Func <int, int, bool> isValid = (int x, int y) => { return(x >= 0 && x < cols && y >= 0 && y < rows); }; for (int y = 0; y < rows; y++) { for (int x = 0; x < cols; x++) { if (matrix[y][x] == 0) { continue; } var current = new CellKey(x, y); ds.AddNew(current); max = Math.Max(max, 1); for (int index = 0; index < xOffset.Length; index++) { var ox = x + xOffset[index]; var oy = y + yOffset[index]; if (!isValid(ox, oy)) { continue; } if (matrix[oy][ox] == 0) { continue; } var offset = new CellKey(ox, oy); if (ds.Find(current) != ds.Find(offset)) { max = Math.Max(max, ds.Union(current, offset)); } } } } return(max); }
public void RunTest() { DisjointSets ds = new DisjointSets(_numElements); int[] e2set = new int[_numElements]; HashSet <int>[] sets = new HashSet <int> [_numSets]; for (int i = 0; i < _numSets; i++) { sets[i] = new HashSet <int>(); } Random rnd = new Random(); for (int i = 0; i < _numElements; i++) { int nset = rnd.Next(_numSets); e2set[i] = nset; sets[nset].Add(i); } foreach (HashSet <int> set in sets) { Queue <int> q = new Queue <int>(set); if (q.Count == 0) { continue; } int last = q.Dequeue(); while (q.Count > 0) { int cur = q.Dequeue(); ds.Union(ds.FindSet(last), ds.FindSet(cur)); last = cur; } } int[] reps = new int[_numSets]; for (int i = 0; i < _numSets; i++) { reps[i] = -1; } for (int i = 0; i < _numElements; i++) { int rep = ds.FindSet(i); int nset = e2set[i]; if (reps[nset] == -1) { reps[nset] = rep; } else if (reps[nset] != rep) { throw new TestFailedException("Test with " + _numElements + " elements and " + _numSets + " sets: wrong representant"); } } }
public void Union() { var sets = new DisjointSets <int>(new int[] { 1, 2, 3, 4, 5, 6 }); sets.Union(1, 2); Assert.That(sets.FindSet(1), Is.EqualTo(1).Or.EqualTo(2)); Assert.That(sets.FindSet(2), Is.EqualTo(1).Or.EqualTo(2)); foreach (int i in new int[] { 3, 4, 5, 6 }) { Assert.That(sets.FindSet(i), Is.EqualTo(i)); } }
static void Main(string[] args) { DisjointSets ds = new DisjointSets(); ds.MakeSet(1); ds.MakeSet(2); ds.MakeSet(3); ds.MakeSet(4); ds.MakeSet(5); ds.MakeSet(6); ds.MakeSet(7); ds.Union(1, 2); ds.Union(2, 3); ds.Union(4, 5); ds.Union(6, 7); ds.Union(5, 6); ds.Union(3, 7); Console.WriteLine(ds.FindSet(1).Data); Console.WriteLine(ds.FindSet(2).Data); Console.WriteLine(ds.FindSet(3).Data); Console.WriteLine(ds.FindSet(4).Data); Console.WriteLine(ds.FindSet(5).Data); Console.WriteLine(ds.FindSet(6).Data); Console.WriteLine(ds.FindSet(7).Data); }
public void Test01NonGeneric() { for (var i = 1; i <= ElementsNumber; i += 1 + i / (10 + _random.Next(0, 10))) { Console.WriteLine($"i = {i}"); var djs = new DisjointSets(ElementsNumber); foreach (var el in RandomShuffle(_seq)) { djs.Union(el, el % i); } VerifySets(djs, i); } }
/// <summary> /// Mark the expressions with the given ids as being in the same comparability set. /// </summary> /// <param name="idsToMark">the expression ids</param> /// <seealso cref="ids"/> /// <returns><c>true</c> if any changes to comparability were made</returns> private bool Mark(IEnumerable <int> idsToMark) { bool modified = false; int? last = null; foreach (var id in idsToMark) { if (last != null) { modified |= comparability.Union(comparability.FindSet(last.Value), comparability.FindSet(id)); } last = id; } return(modified); }
public void Test02Generic() { for (var i = 1; i <= ElementsNumber; i += 1 + i / (10 + _random.Next(0, 10))) { Console.WriteLine($"i = {i}"); var rs = RandomShuffle(_seq).ToList(); var djs = new DisjointSets <int>(rs); foreach (var el in rs) { djs.Union(el, el % i); } VerifySets(djs, i); for (var j = 0; j < ElementsNumber; ++j) { Assert.That(djs[j], Is.EqualTo(rs[j])); } } }
// Complete the maxCircle function below. static int[] maxCircle(int[][] queries) { var ds = new DisjointSets(); var result = new int[queries.Length]; var max = 0; for (int index = 0; index < queries.Length; index++) { var left = ds.FindOrAdd(queries[index][0]); var right = ds.FindOrAdd(queries[index][1]); max = Math.Max(max, ds.Union(left, right)); result[index] = max; } return(result); }
public static int[] Solve(int[][] queries) { DisjointSets userMap = new DisjointSets(); int[] result = new int[queries.Length]; for (int i = 0; i < queries.Length; i++) { int a = queries[i][0]; int b = queries[i][1]; userMap.Union(a, b); result[i] = userMap.MaxSetSize; } return(result); }
public void DisjoinSetsBaseScenarioTest() { var djs = new DisjointSets(4); Assert.AreEqual(0, djs.SetsCount); var setId = djs.CreateSet(0); Assert.AreEqual(0, setId); Assert.AreEqual(1, djs.SetsCount); djs.AddToSet(setId, 1); Assert.AreEqual(setId, djs.GetIncludingSetId(1)); var setId1 = djs.CreateSet(2); Assert.AreEqual(2, djs.SetsCount); djs.Union(setId, setId1); Assert.AreEqual(1, djs.SetsCount); Assert.AreEqual(setId, djs.GetIncludingSetId(2)); }
/// <summary> /// /**https://en.wikipedia.org/wiki/Kruskal%27s_algorithm * KRUSKAL(G): * 1 A = ∅ * 2 foreach v ∈ G.V: * 3 MAKE-SET(v) * 4 foreach (u, v) in G.E ordered by weight(u, v), increasing: * 5 if FIND-SET(u) ≠ FIND-SET(v): * 6 A = A ∪ {(u, v)} * 7 UNION(u, v) * 8 return A * **/ /// </summary> /// <typeparam name="T"></typeparam> /// <param name="g"></param> /// <returns></returns> public static List <Edge <T> > GetMSTUsingKruskal <T>(this Graph <T> g) { EdgeComparer <T> comparer = new EdgeComparer <T>(); List <Edge <T> > result = new List <Edge <T> >(); //First sort the edges g.AllEdges.Sort(comparer); Console.WriteLine("Edes in Sorted Order"); foreach (var e in g.AllEdges) { Console.WriteLine(e.ToString()); } DisjointSets disjointSet = new DisjointSets(); //Create Set for each vertex foreach (var v in g.AllVertex.Values) { disjointSet.MakeSet(v.Id); } //For each edge, check if vertex is already in SET. //1. If yes, ignore //2. If not, Union and add it to result of edge foreach (var e in g.AllEdges) { var n1 = disjointSet.FindSet(e.V1.Id); var n2 = disjointSet.FindSet(e.V2.Id); if (n1 == n2) { continue; } else { result.Add(e); disjointSet.Union(e.V1.Id, e.V2.Id); } } return(result); }
public void RunTest() { DisjointSets ds = new DisjointSets(_numElements); int[] e2set = new int[_numElements]; HashSet<int>[] sets = new HashSet<int>[_numSets]; for (int i = 0; i < _numSets; i++) { sets[i] = new HashSet<int>(); } Random rnd = new Random(); for (int i = 0; i < _numElements; i++) { int nset = rnd.Next(_numSets); e2set[i] = nset; sets[nset].Add(i); } foreach (HashSet<int> set in sets) { Queue<int> q = new Queue<int>(set); if (q.Count == 0) continue; int last = q.Dequeue(); while (q.Count > 0) { int cur = q.Dequeue(); ds.Union(ds.FindSet(last), ds.FindSet(cur)); last = cur; } } int[] reps = new int[_numSets]; for (int i = 0; i < _numSets; i++) reps[i] = -1; for (int i = 0; i < _numElements; i++) { int rep = ds.FindSet(i); int nset = e2set[i]; if (reps[nset] == -1) reps[nset] = rep; else if (reps[nset] != rep) throw new TestFailedException("Test with " + _numElements + " elements and " + _numSets + " sets: wrong representant"); } }
public TypeSummary(string assemblyQualifiedName, NameBuilder names, IEnumerable <MethodVisitor> methods) { Contract.Requires(!string.IsNullOrEmpty(assemblyQualifiedName)); Contract.Requires(names != null); Contract.Requires(methods != null); Contract.Ensures(ids.Keys.SetEquals(names.ThisNames())); this.AssemblyQualifiedName = assemblyQualifiedName; // give a union-find id to each instance expression name foreach (var name in names.ThisNames()) { ids.Add(name, comparability.AddElement()); } // union the sets, according to each method's opinion foreach (var name in names.ThisNames()) { HashSet <string> indexOpinion = new HashSet <string>(); foreach (var method in methods) { var opinion = method.ComparabilitySet(name).Intersect(ids.Keys); string last = null; foreach (var other in opinion) { if (last != null) { comparability.Union(comparability.FindSet(ids[last]), comparability.FindSet(ids[name])); } last = other; } indexOpinion.UnionWith(method.IndexComparabilityOpinion(name).Intersect(names.ThisNames())); } if (indexOpinion.Count > 0) { arrayIndexes.Add(name, indexOpinion); } } }
/* * Complete the 'kruskals' function below. * * The function is expected to return an INTEGER. * The function accepts WEIGHTED_INTEGER_GRAPH g as parameter. */ /* * For the weighted graph, <name>: * * 1. The number of nodes is <name>Nodes. * 2. The number of edges is <name>Edges. * 3. An edge exists between <name>From[i] and <name>To[i]. The weight of the edge is <name>Weight[i]. * */ public static int kruskals(int gNodes, List <int> gFrom, List <int> gTo, List <int> gWeight) { var ds = new DisjointSets(gNodes); var edges = new Edge[gFrom.Count]; for (var index = 0; index < gFrom.Count; index++) { edges[index] = new Edge { From = gFrom[index], To = gTo[index], Weight = gWeight[index] }; } Array.Sort(edges); var edgesUsed = 0; var sum = 0; foreach (var edge in edges) { if (edgesUsed == gNodes - 1) { break; } if (ds.Find(edge.From) == ds.Find(edge.To)) { continue; } edgesUsed++; sum += edge.Weight; ds.Union(edge.From, edge.To); } return(sum); }
public MST <V> Execute() { var mst = new MST <V>(); var orderedEdges = _g.AllEdges().OrderBy(e => e.Weight); var ds = new DisjointSets <Node <V> >(); foreach (var edge in orderedEdges) { var head = ds.Find(edge.Head); var tail = ds.Find(edge.Tail); if (!head.Equals(tail)) { mst.Edges.Add(edge); ds.Union(head, tail); } } return(mst); }
public void Union_ThrowsOnSecondElementNonExistent() { var sets = new DisjointSets <int>(new int[] { 1, 2 }); Assert.That(() => sets.Union(1, 3), Throws.ArgumentException); }
/// <summary> /// Unifies two set elements. /// </summary> /// <param name="e1">a set element</param> /// <param name="e2">another set element</param> public void Union(T e1, T e2) { _impl.Union(_impl.FindSet(_index[e1]), _impl.FindSet(_index[e2])); _repShuffle[_impl.FindSet(_index[e2])] = _index[e2]; }
/// <summary> /// Procedurally generates the 2-dimensional data for a maze with the dimensions set by the /// <see cref="MazeGenerator(int, int)"/> constructor.<para /> /// Calling this method consecutively will always generate an entirely new maze but of same Rows by Cols /// dimensions of the given object instance. To change the dimensions, a new object must be instantiated. /// </summary> public void GenerateMaze() { int visitedCells = 1; int currCell = rand.Next(CellNum); int adjCell; bool adjacentFound; // Index - 0: above, 1: below, 2: left, 3: right // If adjacentCells[Index] = -1 then that adjacent cell does not exist. int[] adjCells = new int[Max_Adjacency]; Stack <int> cellStack = new Stack <int>(); while (visitedCells < CellNum) { adjCell = -1; adjacentFound = false; if (currCell < Cols) { adjCells[0] = -1; } else { adjCells[0] = currCell - Cols; } if (currCell >= (CellNum - Cols)) { adjCells[1] = -1; } else { adjCells[1] = currCell + Cols; } if (currCell % Cols == 0) { adjCells[2] = -1; } else { adjCells[2] = currCell - 1; } if ((currCell + 1) % Cols == 0) { adjCells[3] = -1; } else { adjCells[3] = currCell + 1; } for (int i = 0; i < adjCells.Length; ++i) { if (adjCells[i] >= 0 && (sets.Find(currCell) != sets.Find(adjCells[i]))) { adjacentFound = true; } else { adjCells[i] = -1; } } if (adjacentFound) { int wallIndex; do { wallIndex = rand.Next(Max_Adjacency); adjCell = adjCells[wallIndex]; }while (adjCell < 0); sets.Union(currCell, adjCell); // Adjacent cell is - 0: above, 1: below, 2: left, 3: right switch (wallIndex) { case 0: // Connect currentCell with adjacentCell above. grid[currCell] = new Cell(false, grid[currCell].belowWall, grid[currCell].leftWall, grid[currCell].rightWall); grid[adjCell] = new Cell(grid[adjCell].aboveWall, false, grid[adjCell].leftWall, grid[adjCell].rightWall); break; case 1: // Connect currentCell with adjacentCell below. grid[currCell] = new Cell(grid[currCell].aboveWall, false, grid[currCell].leftWall, grid[currCell].rightWall); grid[adjCell] = new Cell(false, grid[adjCell].belowWall, grid[adjCell].leftWall, grid[adjCell].rightWall); break; case 2: // Connect currentCell with adjacentCell on left. grid[currCell] = new Cell(grid[currCell].aboveWall, grid[currCell].belowWall, false, grid[currCell].rightWall); grid[adjCell] = new Cell(grid[adjCell].aboveWall, grid[adjCell].belowWall, grid[adjCell].leftWall, false); break; case 3: // Connect currentCell with adjacentCell on right. grid[currCell] = new Cell(grid[currCell].aboveWall, grid[currCell].belowWall, grid[currCell].leftWall, false); grid[adjCell] = new Cell(grid[adjCell].aboveWall, grid[adjCell].belowWall, false, grid[adjCell].rightWall); break; default: Debug.LogError ("GenerateMaze() error: invalid wallIndex value."); break; } cellStack.Push(currCell); currCell = adjCell; ++visitedCells; } else { if (cellStack.Count > 0) { currCell = cellStack.Pop(); } } } }
/// <summary> /// Calculates minimal spanning tree using Kruskal algo. /// Edges are required to be sorted by weigth. /// </summary> /// <param name="numNodes">Count of nodes</param> /// <param name="edges">Edges data</param> /// <returns>Array of indicies of edges in minimal spanning tree</returns> public static int[] CalcKruskal(int numNodes, GraphEdge[] edges) { int[] result = new int[numNodes - 1]; var ds = new DisjointSets(numNodes); var connectedNodesCount = 0; var currResultEdge = 0; // for each edge try to include it in minimal spanning tree for (int i = 0; i < edges.Length; i++) { var set1 = ds.GetIncludingSetId(edges[i].Node1); var set2 = ds.GetIncludingSetId(edges[i].Node2); if (set1 == set2 && set1 != -1) { // this edge will introduce cycle, skip it // it already connects two nodes which are // already in the same region continue; } else { // edge connects two edges which are not in the same region // so this edge can be included into MST result[currResultEdge] = i; currResultEdge++; if (set1 != -1 && set2 != -1) { // edge connects two distinct regions - union them ds.Union(set1, set2); } else if (set1 != -1 && set2 == -1) { // node 2 is single, add to gerion of node 1 ds.AddToSet(set1, edges[i].Node2); connectedNodesCount += 1; } else if (set2 != -1 && set1 == -1) { // node 1 is single, add to gerion of node 2 ds.AddToSet(set2, edges[i].Node1); connectedNodesCount += 1; } else { // both nodes are singe // create region and add them into it var newSet = ds.CreateSet(edges[i].Node1); ds.AddToSet(newSet, edges[i].Node2); connectedNodesCount += 2; } // if all nodes are connected and in the single region // then MST is built if (connectedNodesCount == numNodes && ds.SetsCount == 1) { return(result); } } } return(result); }