public IDMultisetItemList PotentialFriendsPLinq(SubscriberID id, int maxCandidates)
        {
            var candidates =
                subscribers[id].Friends.AsParallel()                                    // Map
                .SelectMany(friend => subscribers[friend].Friends)
                .Where(foaf => foaf != id && !(subscribers[id].Friends.Contains(foaf))) // remove self, own friends
                .GroupBy(foaf => foaf)                                                  // Reduce
                .Select(foafGroup => new IDMultisetItem(foafGroup.Key, foafGroup.Count()));

            return(Multiset.MostNumerous(candidates, maxCandidates)); // postprocess results of Reduce
        }
        public IDMultisetItemList PotentialFriendsParallel(SubscriberID id, int maxCandidates)
        {
            object     locker     = new object();
            IDMultiset candidates = new IDMultiset();

            Parallel.ForEach(subscribers[id].Friends,                             // Map over friends
                             () => Multiset.Create(new HashSet <SubscriberID>()), // init thread-local state localFoafs with empty Multiset
                             (friend, loopState, localFoafs) =>
            {
                var foafs = subscribers[friend].FriendsCopy();
                foafs.RemoveWhere(foaf => foaf == id || subscribers[id].Friends.Contains(foaf));                    // remove self, own friends
                return(Multiset.Union(localFoafs, Multiset.Create(foafs)));                                         // Reduce, thread-local
            },
                             localFoafs => { lock (locker) candidates = Multiset.Union(localFoafs, candidates); }); // Reduce, among threads
            return(Multiset.MostNumerous(candidates, maxCandidates));                                               // postprocess results of Reduce
        }
        public IDMultisetItemList PotentialFriendsSequential(SubscriberID id, int maxCandidates)
        {
            // Map
            var foafsList = new List <IDMultiset>();

            foreach (SubscriberID friend in subscribers[id].Friends)
            {
                var foafs = subscribers[friend].FriendsCopy();
                foafs.RemoveWhere(foaf => foaf == id || subscribers[id].Friends.Contains(foaf)); // remove self, own friends
                foafsList.Add(Multiset.Create(foafs));
            }

            // Reduce
            IDMultiset candidates = new IDMultiset();

            foreach (IDMultiset foafs in foafsList)
            {
                candidates = Multiset.Union(foafs, candidates);
            }

            // Postprocess
            return(Multiset.MostNumerous(candidates, maxCandidates));
        }
Esempio n. 4
0
        /// <summary>
        /// Usage: SocialNework subscriberCount maxFriends
        /// Both arguments are optional, defaults are 1000 and 10.
        /// </summary>
        static void Main(string[] args)
        {
            Console.WriteLine("Social Network Sample\n");
#if DEBUG
            Console.WriteLine("For most accurate timing results, use Release build.\n");
#endif

            Random random = new Random(1);  // seed for random but reproducible runs

            // Defaults for data generation, may override some on command line
            int subscriberCount = 10000;
            int maxFriends      = 2000;

            // Defaults for printed table of results
            const int maxRows       = 16;
            const int maxCols       = 8;
            const int maxCandidates = maxRows;

            // Optionally override some defaults on command line
            if (args.Length > 0)
            {
                subscriberCount = Int32.Parse(args[0], CultureInfo.CurrentCulture);
            }
            if (args.Length > 1)
            {
                maxFriends = Int32.Parse(args[1], CultureInfo.CurrentCulture);
            }

            Console.WriteLine("Creating data...");
            // Allocate subscribers, assign friends for timing tests
            SubscriberRepository subscribers = new SubscriberRepository(subscriberCount);
            subscribers.AssignRandomFriends(maxFriends, random);

            // Print a few subscribers and a summary
            Console.WriteLine();
            Console.WriteLine("Some subscribers and some of their friends");
            subscribers.Print(maxRows, maxCols);
            Console.WriteLine();
            Console.WriteLine("{0} subscribers in all, with up to {1} friends or even more  ", subscriberCount, maxFriends);

            // Choose a subscriber seeking friends
            const SubscriberID id = 0;
            var subscriber        = subscribers.GetSubscriber(id);
            Console.WriteLine();
            Console.WriteLine("Find potential friends for this subscriber, with these friends:");
            Console.Write("{0,10:D}", id);
            subscriber.Print(subscriber.Friends.Count);
            Console.WriteLine();

            // Sequential for
            var candidates = new IDMultisetItemList(); // to sort, must use list of Multiset items not Multiset itself
            SampleUtilities.TimedRun(() =>
            {
                candidates = subscribers.PotentialFriendsSequential(id, maxCandidates);
                return(candidates.Count);
            },
                                     "  Sequential for");
            Console.WriteLine();

            int rows = Math.Min(maxRows, candidates.Count);
            Console.WriteLine("{0} potential friends for this subscriber, and the number of mutual friends", rows);
            Multiset.Print(candidates);
            Console.WriteLine();

            // Parallel.ForEach
            SampleUtilities.TimedRun(() =>
            {
                candidates = subscribers.PotentialFriendsParallel(id, maxCandidates);
                return(candidates.Count);
            },
                                     "Parallel.ForEach");
            Console.WriteLine();

            rows = Math.Min(maxRows, candidates.Count);
            Console.WriteLine("{0} potential friends for this subscriber, and the number of mutual friends", rows);
            Multiset.Print(candidates);
            Console.WriteLine();

            // Sequential LINQ
            SampleUtilities.TimedRun(() =>
            {
                candidates = subscribers.PotentialFriendsLinq(id, maxCandidates);
                return(candidates.Count);
            },
                                     " Sequential LINQ");
            Console.WriteLine();

            rows = Math.Min(maxRows, candidates.Count);
            Console.WriteLine("{0} potential friends for this subscriber, and the number of mutual friends", rows);
            Multiset.Print(candidates);
            Console.WriteLine();

            // PLINQ
            SampleUtilities.TimedRun(() =>
            {
                candidates = subscribers.PotentialFriendsPLinq(id, maxCandidates);
                return(candidates.Count);
            },
                                     "           PLINQ");
            Console.WriteLine();

            rows = Math.Min(maxRows, candidates.Count);
            Console.WriteLine("{0} potential friends for this subscriber, and the number of mutual friends", rows);
            Multiset.Print(candidates);

            Console.WriteLine("\nRun complete... press enter to finish.");
            Console.ReadLine();
        }