Пример #1
0
        public void Union_Test()
        {
            var n1 = new UnionFindNode();
            var n2 = new UnionFindNode();
            var n3 = new UnionFindNode();
            var n4 = new UnionFindNode();
            var n5 = new UnionFindNode();

            Assert.True(n1.Union(n2));
            Assert.True(n2.Union(n3));
            Assert.False(n3.Union(n1));

            Assert.True(n4.Union(n5));
            Assert.False(n5.Union(n4));

            Assert.True(n1.IsUnionedWith(n1));
            Assert.True(n2.IsUnionedWith(n2));
            Assert.True(n1.IsUnionedWith(n2));
            Assert.True(n1.IsUnionedWith(n3));

            Assert.False(n4.IsUnionedWith(n1));
            Assert.False(n5.IsUnionedWith(n2));

            Assert.True(n4.IsUnionedWith(n5));
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        public void TestTrivial()
        {
            var n1 = new UnionFindNode();
            var n2 = new UnionFindNode();

            Assert.True(n1.IsUnionedWith(n1));
            Assert.False(n1.IsUnionedWith(n2));
        }
Пример #4
0
 /// <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()));
 }
Пример #5
0
 /// <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);
 }
Пример #6
0
        public void Trivial_Test()
        {
            var n1 = new UnionFindNode();
            var n2 = new UnionFindNode();

            Assert.True(n1.IsUnionedWith(n1));
            Assert.False(n1.IsUnionedWith(n2));

            Assert.Throws <ArgumentNullException>(() => n1.Union(null));
            Assert.Throws <ArgumentNullException>(() => n1.IsUnionedWith(null));
        }
Пример #7
0
        //TODO: for testnet we only have a single chain, thus grouper only take care of txList in one chain (hence Process has chainId as parameter)
        public async Task <Tuple <List <List <Transaction> >, Dictionary <Transaction, Exception> > > ProcessNaive(int chainId, List <Transaction> transactions)
        {
            var txResourceHandle = new Dictionary <Transaction, string>();
            var failedTxs        = new Dictionary <Transaction, Exception>();

            if (transactions.Count == 0)
            {
                return(new Tuple <List <List <Transaction> >, Dictionary <Transaction, Exception> >(new List <List <Transaction> >(), failedTxs));
            }

            Dictionary <string, UnionFindNode> resourceUnionSet = new Dictionary <string, UnionFindNode>();

            //set up the union find set as the representation of graph and the connected components will be the resulting groups
            foreach (var tx in transactions)
            {
                UnionFindNode first = null;
                List <string> resources;
                try
                {
                    resources = (await _resourceUsageDetectionService.GetResources(tx)).ToList();
                }
                catch (Exception e)
                {
                    failedTxs.Add(tx, e);
                    continue;
                }

                //Logger.LogDebug(string.Format("tx {0} have resource [{1}]", tx.From, string.Join(" ||| ", resources)));
                foreach (var resource in resources)
                {
                    if (!resourceUnionSet.TryGetValue(resource, out var node))
                    {
                        node = new UnionFindNode();
                        resourceUnionSet.Add(resource, node);
                    }
                    if (first == null)
                    {
                        first = node;
                        txResourceHandle.Add(tx, resource);
                    }
                    else
                    {
                        node.Union(first);
                    }
                }
            }

            Dictionary <int, List <Transaction> > grouped = new Dictionary <int, List <Transaction> >();
            List <List <Transaction> >            result  = new List <List <Transaction> >();

            foreach (var tx in transactions)
            {
                if (txResourceHandle.TryGetValue(tx, out var firstResource))
                {
                    int nodeId = resourceUnionSet[firstResource].Find().NodeId;
                    if (!grouped.TryGetValue(nodeId, out var group))
                    {
                        group = new List <Transaction>();
                        grouped.Add(nodeId, group);
                    }
                    group.Add(tx);
                }
                else
                {
                    if (!failedTxs.ContainsKey(tx))
                    {
                        //each "resource-free" transaction have its own group
                        result.Add(new List <Transaction>()
                        {
                            tx
                        });
                    }
                }
            }
            result.AddRange(grouped.Values);

            Logger.LogInformation(string.Format(
                                      "Grouper on chainId \"{0}\" group [{1}] transactions into [{2}] groups with sizes [{3}], There are also {4} transactions failed retriving resource", ChainHelpers.ConvertChainIdToBase58(chainId),
                                      transactions.Count, result.Count, string.Join(", ", result.Select(a => a.Count)), failedTxs.Count));

            return(new Tuple <List <List <Transaction> >, Dictionary <Transaction, Exception> >(result, failedTxs));
        }
Пример #8
0
 /// <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);
 }