public TResult RecommendItem <TResult>(string itemId, IResultBuilderFactory <TResult> resultBuilderFactory)
        {
            if (itemId == null)
            {
                throw new ArgumentNullException(nameof(itemId));
            }

            if (!this.itemMap.ContainsKey(itemId))
            {
                return(resultBuilderFactory.CreateEmpty());
            }

            var yi = this.itemFactors.Row(this.itemMap[itemId]);
            var yj = Vector <double> .Build.Dense(this.factors);

            var resultBuilder = resultBuilderFactory.CreateBuilder(maximumCapacity: this.itemMap.Count);

            foreach (var item in this.itemMap)
            {
                var j = item.Value;

                this.itemFactors.Row(j, yj);

                resultBuilder.Append(item.Key, yi.DotProduct(yj) / this.ItemNorms[j]);
            }

            return(resultBuilder.ToResult());
        }
        public TResult RankUsers <TResult>(UserFeatures user, List <KeyValuePair <string, UserFeatures> > users, IResultBuilderFactory <TResult> resultBuilderFactory)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            if (users == null)
            {
                throw new ArgumentNullException(nameof(users));
            }

            var xu = user.Vector;

            var resultBuilder = resultBuilderFactory.CreateBuilder(maximumCapacity: users.Count);

            foreach (var pair in users)
            {
                var xv    = pair.Value.Vector;
                var norm  = pair.Value.Norm;
                var score = xu.DotProduct(xv) / norm;

                resultBuilder.Append(pair.Key, score);
            }

            return(resultBuilder.ToResult());
        }
        public TResult RecommendUser <TResult>(UserFeatures user, IResultBuilderFactory <TResult> resultBuilderFactory)
        {
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            var xu = user.Vector;
            var yi = Vector <double> .Build.Dense(this.factors);

            var resultBuilder = resultBuilderFactory.CreateBuilder(maximumCapacity: this.itemMap.Count);

            foreach (var item in this.itemMap)
            {
                this.itemFactors.Row(item.Value, yi);

                resultBuilder.Append(item.Key, xu.DotProduct(yi));
            }

            return(resultBuilder.ToResult());
        }