/// <summary> /// Merges the sets represented by this node and the other node into a single set. /// Returns whether or not the nodes were disjoint before the union operation (i.e. if the operation had an effect). /// </summary> /// <returns>True when the union had an effect, false when the nodes were already in the same set.</returns> public bool Union(UnionFindNode other) { if (other == null) { throw new ArgumentNullException("other"); } var root1 = this.Find(); var root2 = other.Find(); if (ReferenceEquals(root1, root2)) { return(false); } if (root1.NodeId < root2.NodeId) { root2._parent = root1; } else { root1._parent = root2; } /* * if (root1._rank < root2._rank) { * root1._parent = root2; * } else if (root1._rank > root2._rank) { * root2._parent = root1; * } else { * root2._parent = root1; * root1._rank++; * } */ return(true); }
private List <List <Transaction> > GroupParallelizables(List <TransactionWithResourceInfo> txsWithResources) { var resourceUnionSet = new Dictionary <int, UnionFindNode>(); var transactionResourceHandle = new Dictionary <Transaction, int>(); var groups = new List <List <Transaction> >(); foreach (var txWithResource in txsWithResources) { UnionFindNode first = null; var transaction = txWithResource.Transaction; var transactionResourceInfo = txWithResource.TransactionResourceInfo; // Add resources to disjoint-set, later each resource will be connected to a node id, which will be our group id foreach (var resource in transactionResourceInfo.Paths.Select(p => p.GetHashCode())) { if (!resourceUnionSet.TryGetValue(resource, out var node)) { node = new UnionFindNode(); resourceUnionSet.Add(resource, node); } if (first == null) { first = node; transactionResourceHandle.Add(transaction, resource); } else { node.Union(first); } } } var grouped = new Dictionary <int, List <Transaction> >(); foreach (var txWithResource in txsWithResources) { var transaction = txWithResource.Transaction; if (!transactionResourceHandle.TryGetValue(transaction, out var firstResource)) { continue; } // Node Id will be our group id var gId = resourceUnionSet[firstResource].Find().NodeId; if (!grouped.TryGetValue(gId, out var gTransactions)) { gTransactions = new List <Transaction>(); grouped.Add(gId, gTransactions); } // Add transaction to its group gTransactions.Add(transaction); } groups.AddRange(grouped.Values); return(groups); }
/// <summary> /// Determines whether or not this node and the other node are in the same set. /// </summary> public bool IsUnionedWith(UnionFindNode other) { if (other == null) { throw new ArgumentNullException("other"); } return(ReferenceEquals(Find(), other.Find())); }
/// <summary> /// Returns the current representative of the set this node is in. /// Note that the representative is only accurate untl the next Union operation. /// </summary> public UnionFindNode Find() { if (!ReferenceEquals(_parent, this)) { _parent = _parent.Find(); } return(_parent); }
/// <summary> /// Creates a new disjoint node, representative of a set containing only the new node. /// </summary> public UnionFindNode() { _parent = this; NodeId = Interlocked.Increment(ref _nextId); }