/** * Get the mean rating for an item. * @param item The item. * @return The item's mean rating, or {@link Double#NaN} if the item is absent. */ public double getItemMean(long item) { int idx = itemIndex.tryGetIndex(item); return idx >= 0 ? itemOffsets[idx] + globalMean : Double.NaN; }
/** * Get the item's average offset from global mean. * @param item The item. * @return The item's average offset from the global mean rating, or 0 if the item is missing */ public double getItemOffset(long item) { int idx = itemIndex.tryGetIndex(item); return idx >= 0 ? itemOffsets[idx] : 0; }
double getDeviation(long item) { int idx = items.tryGetIndex(item); if (idx >= 0) { return deviations[idx]; } else { return Double.NaN; } }
int getCoratings(long item) { int idx = items.tryGetIndex(item); if (idx >= 0) { return coratings[idx]; } else { return 0; } } }
/** * Query whether this set contains the specified key in its domain. * @param key The key. * @return {@code true} if the key is in the domain. */ @Override public boolean containsKey(long key) { int idx = tryGetIndex(key); return idx >= lowerBound && idx < upperBound; }
/** * Get the number of ratings for the item. */ public int getItemRatingCount(long item) { int idx = itemIndex.tryGetIndex(item); return idx >= 0 ? itemCounts[idx] : 0; }
/** * Get the number of interactions for an item. * @param item The item. * @return The number of interactions for `item`. */ public int getInteractionCount(long item) { int idx = items.tryGetIndex(item); if (idx >= 0) { return interactionCounts[idx]; } else { return 0; } }
/** * Get the upper bound, the first index whose key is greater than the specified key. * * @param key The key to search for. * @return The index of the first key greater than the specified key, or {@link #getUpperBound()} if the key * is the last key in the domain. */ public int findUpperBound(long key) { int index = tryGetIndex(key); if (index >= 0) { // the key is there, advance by 1 return index + 1; } else { // the key is not there, the insertion point is > key return -index - 1; } }
/** * Get the lower bound, the first index whose key is greater than or equal to the specified key. * This method is paired with {@link #findUpperBound(long)}; the interval * {@code [findLowerBound(k),findUpperBound(k))} contains the index of {@code k}, if the key is in the * domain, and is empty if the key is not in the domain. * * @param key The key to search for. * @return The index of the first key greater than or equal to {@code key}; will be {@link #getLowerBound()} if * {@code key} is less than or equal to the lowest key. */ public int findLowerBound(long key) { int index = tryGetIndex(key); if (index >= 0) { // the key is there, first index is >= return index; } else { // the key is not there, the insertion point is > key return -index - 1; } }
@Override public int getIndex(long key) { int idx = tryGetIndex(key); if (idx < 0) { throw new IllegalArgumentException("key " + key + " is not in the key index"); } return idx; }
@Override @Nonnull public Long2DoubleMap getNeighbors(long item) { int idx = itemDomain.tryGetIndex(item); if (idx < 0) { return Long2DoubleMaps.EMPTY_MAP; } else { return neighborhoods.get(idx); } }
/** * Get a user vector normalized for score computations. * @param user The user ID. * @return The normalized user rating vector (with {@link ScoreNormalizer}). */ public Long2DoubleMap getUserVector(long user) { int idx = users.tryGetIndex(user); Preconditions.checkArgument(idx >= 0, "invalid user " + user); return vectors.get(idx); }
/** * Get a user vector normalized for similarity computations. * * @return The normalized user rating vector (with {@link SimilarityNormalizer}). */ public Long2DoubleMap getNormalizedUserVector(long user) { int idx = users.tryGetIndex(user); Preconditions.checkArgument(idx >= 0, "invalid user " + user); return normedVectors.get(idx); }
/** * Get the rating vector for an item. Rating vectors contain normalized ratings, * using the applicable user-vector normalizer on the user rating vectors. * * @param item The item to query. * @return The rating vector for {@code item}. * @throws IllegalArgumentException if {@code item} is not a valid item. */ @Nonnull public Long2DoubleSortedMap itemVector(long item) { int idx = items.tryGetIndex(item); Preconditions.checkArgument(idx >= 0, "unknown item"); return itemVectors[idx]; }
@Override public double get(long l) { int idx = keys.tryGetIndex(l); if (idx >= 0) { return values[idx]; } else { return defaultReturnValue(); } }
@Override public boolean contains(Object o) { if (o instanceof Map.Entry) { Map.Entry<?,?> e = (Map.Entry) o; long key = e instanceof Entry ? ((Entry) e).getLongKey() : (Long) e.getKey(); int idx = keys.tryGetIndex(key); if (idx >= 0) { return e.getValue().equals(values[idx]); } } return false; }
@SuppressWarnings("deprecation") private void testRatingIntegrity(SortedKeyIndex items, Long2DoubleMap[] trueRatings, ItemItemBuildContext context) { for (long itemId : context.getItems()) { assertEquals(trueRatings[items.tryGetIndex(itemId)], context.itemVector(itemId)); } } }
@Theory public void testABunch(KeyData data) { long[] rawKeys = data.getKeys(10); List<Long> keyList = new LongArrayList(rawKeys); SortedKeyIndex keys = SortedKeyIndex.wrap(rawKeys, rawKeys.length); assertThat(keys.size(), equalTo(10)); assertThat(keys.size(), equalTo(10)); assertThat(keys.getKeyList(), contains(keyList.toArray())); assertThat(keys.keySet(), contains(keyList.toArray())); assertThat(keys.tryGetIndex(data.getLow()), lessThan(0)); for (int i = 0; i < 10; i++) { assumeThat(keys.tryGetIndex(rawKeys[i]), equalTo(i)); assertThat(keys.tryGetIndex(data.getAfter(i)), lessThan(0)); } } }
@Theory public void testSingleton(KeyData data) { assumeThat(data, notNullValue()); long key = data.getKey(); // key to use long low = data.getLow(); // unused low key long high = data.getAfter(1); // unused high key long[] rawKeys = {key}; SortedKeyIndex keys = SortedKeyIndex.wrap(rawKeys, 1); assertThat(keys.size(), equalTo(1)); assertThat(keys.size(), equalTo(1)); assertThat(keys.keySet(), hasSize(1)); assertThat(keys.tryGetIndex(key), equalTo(0)); assertThat(keys.tryGetIndex(low), lessThan(0)); assertThat(keys.tryGetIndex(high), lessThan(0)); assertThat(keys.getKeyList(), contains(key)); }
@Test public void testEmptyArray() { long[] rawKeys = {}; SortedKeyIndex keys = SortedKeyIndex.wrap(rawKeys, 0); assertThat(keys.size(), equalTo(0)); assertThat(keys.size(), equalTo(0)); assertThat(keys.keySet(), hasSize(0)); assertThat(keys.getKeyList(), hasSize(0)); assertThat(keys.tryGetIndex(42), lessThan(0)); }