protected override float doEstimatePreference(long theUserID, PreferenceArray preferencesFromUser, long itemID) { DataModel dataModel = getDataModel(); int size = preferencesFromUser.length(); FastIDSet possibleItemIDs = new FastIDSet(size); for (int i = 0; i < size; i++) { possibleItemIDs.add(preferencesFromUser.getItemID(i)); } possibleItemIDs.remove(itemID); List <RecommendedItem> mostSimilar = mostSimilarItems(itemID, possibleItemIDs.GetEnumerator(), neighborhoodSize, null); long[] theNeighborhood = new long[mostSimilar.Count() + 1]; theNeighborhood[0] = -1; List <long> usersRatedNeighborhood = new List <long>(); int nOffset = 0; foreach (RecommendedItem rec in mostSimilar) { theNeighborhood[nOffset++] = rec.getItemID(); } if (mostSimilar.Count != 0) { theNeighborhood[mostSimilar.Count] = itemID; for (int i = 0; i < theNeighborhood.Length; i++) { PreferenceArray usersNeighborhood = dataModel.getPreferencesForItem(theNeighborhood[i]); int size1 = usersRatedNeighborhood.Count == 0 ? usersNeighborhood.length() : usersRatedNeighborhood.Count; for (int j = 0; j < size1; j++) { if (i == 0) { usersRatedNeighborhood.Add(usersNeighborhood.getUserID(j)); } else { if (j >= usersRatedNeighborhood.Count) { break; } long index = usersRatedNeighborhood[j]; if (!usersNeighborhood.hasPrefWithUserID(index) || index == theUserID) { usersRatedNeighborhood.Remove(index); j--; } } } } } double[] weights = null; if (mostSimilar.Count != 0) { weights = getInterpolations(itemID, theNeighborhood, usersRatedNeighborhood); } int n = 0; double preference = 0.0; double totalSimilarity = 0.0; foreach (long jitem in theNeighborhood) { float?pref = dataModel.getPreferenceValue(theUserID, jitem); if (pref != null) { double weight = weights[n]; preference += pref.Value * weight; totalSimilarity += weight; } n++; } return(totalSimilarity == 0.0 ? float.NaN : (float)(preference / totalSimilarity)); }