/// <summary>
        /// Finds related users for every user in a instance source.
        /// The subset of users who will be returned as related for a particular user is restricted:
        /// it is guaranteed that all the related users have rated at least <paramref name="minCommonRatingCount"/> items in common with the query user
        /// in the dataset.
        /// </summary>
        /// <typeparam name="TFeatureSource">The type of a feature source used by the recommendation engine.</typeparam>
        /// <param name="recommender">The recommendation engine.</param>
        /// <param name="instanceSource">The instance source.</param>
        /// <param name="maxRelatedUserCount">Maximum number of related users to return.</param>
        /// <param name="minCommonRatingCount">Minimum number of items that the query user and the related user should have rated in common.</param>
        /// <param name="minRelatedUserPoolSize">
        /// If a user has less than <paramref name="minRelatedUserPoolSize"/> possible related users,
        /// it will be skipped.
        /// </param>
        /// <param name="featureSource">The source of features.</param>
        /// <returns>The list of related users for every user in <paramref name="instanceSource"/>.</returns>
        public IDictionary <TUser, IEnumerable <TUser> > FindRelatedUsersWhoRatedSameItems <TFeatureSource>(
            IRecommender <TInstanceSource, TUser, TItem, TPredictedRating, TPredictedRatingDist, TFeatureSource> recommender,
            TInstanceSource instanceSource,
            int maxRelatedUserCount,
            int minCommonRatingCount,
            int minRelatedUserPoolSize,
            TFeatureSource featureSource = default(TFeatureSource))
        {
            if (recommender == null)
            {
                throw new ArgumentNullException("recommender");
            }

            if (maxRelatedUserCount <= 0)
            {
                throw new ArgumentOutOfRangeException("maxRelatedUserCount", "The maximum number of related users should be positive.");
            }

            if (minCommonRatingCount <= 0)
            {
                throw new ArgumentOutOfRangeException("minCommonRatingCount", "The minimum number of common ratings should be positive.");
            }

            if (minRelatedUserPoolSize <= 0)
            {
                throw new ArgumentOutOfRangeException("minRelatedUserPoolSize", "The minimum size of the related users pool should be positive.");
            }

            return(FindRelatedEntitiesWhichRatedTheSame(
                       this.mapping.GetUsers(instanceSource),
                       user => this.mapping.GetUsersWhoRatedSameItems(instanceSource, user),
                       (user, userSubset) =>
            {
                recommender.UserSubset = userSubset;
                return recommender.GetRelatedUsers(user, maxRelatedUserCount, featureSource);
            },
                       minCommonRatingCount,
                       minRelatedUserPoolSize));
        }