You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mahout.apache.org by sr...@apache.org on 2010/07/31 16:15:11 UTC

svn commit: r981062 - in /mahout/trunk/core/src: main/java/org/apache/mahout/cf/taste/impl/model/ main/java/org/apache/mahout/cf/taste/impl/recommender/ main/java/org/apache/mahout/cf/taste/impl/recommender/knn/ main/java/org/apache/mahout/cf/taste/imp...

Author: srowen
Date: Sat Jul 31 14:15:10 2010
New Revision: 981062

URL: http://svn.apache.org/viewvc?rev=981062&view=rev
Log:
MAHOUT-445

Added:
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AllUnknownItemsCandidateItemsStrategy.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/PreferredItemsNeighborhoodCandidateItemsStrategy.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/SamplingCandidateItemsStrategy.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/CandidateItemsStrategy.java
    mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/AllUnknownItemsCandidateItemsStrategyTest.java
    mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/PreferredItemsNeighborhoodCandidateItemsStrategyTest.java
    mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/SamplingCandidateItemsStrategyTest.java
Modified:
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUserPreferenceArray.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AbstractRecommender.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericItemBasedRecommender.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/knn/KnnItemBasedRecommender.java
    mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/svd/SVDRecommender.java

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUserPreferenceArray.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUserPreferenceArray.java?rev=981062&r1=981061&r2=981062&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUserPreferenceArray.java (original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUserPreferenceArray.java Sat Jul 31 14:15:10 2010
@@ -73,7 +73,7 @@ public final class GenericUserPreference
     this.id = id;
     this.values = values;
   }
-  
+
   @Override
   public int length() {
     return ids.length;

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AbstractRecommender.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AbstractRecommender.java?rev=981062&r1=981061&r2=981062&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AbstractRecommender.java (original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AbstractRecommender.java Sat Jul 31 14:15:10 2010
@@ -17,13 +17,12 @@
 
 package org.apache.mahout.cf.taste.impl.recommender;
 
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
 import java.util.List;
 
 import org.apache.mahout.cf.taste.common.TasteException;
 import org.apache.mahout.cf.taste.impl.common.FastIDSet;
-import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
 import org.apache.mahout.cf.taste.model.DataModel;
-import org.apache.mahout.cf.taste.model.PreferenceArray;
 import org.apache.mahout.cf.taste.recommender.RecommendedItem;
 import org.apache.mahout.cf.taste.recommender.Recommender;
 import org.slf4j.Logger;
@@ -34,14 +33,24 @@ public abstract class AbstractRecommende
   private static final Logger log = LoggerFactory.getLogger(AbstractRecommender.class);
   
   private final DataModel dataModel;
+  private final CandidateItemsStrategy candidateItemsStrategy;
   
-  protected AbstractRecommender(DataModel dataModel) {
+  protected AbstractRecommender(DataModel dataModel, CandidateItemsStrategy candidateItemsStrategy) {
     if (dataModel == null) {
       throw new IllegalArgumentException("dataModel is null");
     }
     this.dataModel = dataModel;
+    this.candidateItemsStrategy = candidateItemsStrategy;
   }
-  
+
+  protected AbstractRecommender(DataModel dataModel) {
+    this(dataModel, getDefaultCandidateItemsStrategy());
+  }
+
+  protected static CandidateItemsStrategy getDefaultCandidateItemsStrategy() {
+    return new PreferredItemsNeighborhoodCandidateItemsStrategy();
+  }
+
   /**
    * <p>
    * Default implementation which just calls
@@ -99,19 +108,7 @@ public abstract class AbstractRecommende
    *           if an error occurs while listing items
    */
   protected FastIDSet getAllOtherItems(long theUserID) throws TasteException {
-    FastIDSet possibleItemsIDs = new FastIDSet();
-    FastIDSet itemIDs = dataModel.getItemIDsFromUser(theUserID);
-    LongPrimitiveIterator itemIDIterator = itemIDs.iterator();
-    while (itemIDIterator.hasNext()) {
-      long itemID = itemIDIterator.next();
-      PreferenceArray prefs2 = dataModel.getPreferencesForItem(itemID);
-      int size2 = prefs2.length();
-      for (int j = 0; j < size2; j++) {
-        possibleItemsIDs.addAll(dataModel.getItemIDsFromUser(prefs2.getUserID(j)));
-      }
-    }
-    possibleItemsIDs.removeAll(itemIDs);
-    return possibleItemsIDs;
+    return candidateItemsStrategy.getCandidateItems(theUserID, dataModel);
   }
   
 }

Added: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AllUnknownItemsCandidateItemsStrategy.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AllUnknownItemsCandidateItemsStrategy.java?rev=981062&view=auto
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AllUnknownItemsCandidateItemsStrategy.java (added)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AllUnknownItemsCandidateItemsStrategy.java Sat Jul 31 14:15:10 2010
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.recommender;
+
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.impl.common.FastIDSet;
+import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
+import org.apache.mahout.cf.taste.model.DataModel;
+
+/**
+ * returns all items the user has not rated yet
+ */
+public final class AllUnknownItemsCandidateItemsStrategy implements CandidateItemsStrategy {
+
+  @Override
+  public FastIDSet getCandidateItems(long userID, DataModel dataModel) throws TasteException {
+    FastIDSet possibleItemIDs = new FastIDSet(dataModel.getNumItems());
+    LongPrimitiveIterator allItemIDs = dataModel.getItemIDs();
+    while (allItemIDs.hasNext()) {
+      possibleItemIDs.add(allItemIDs.nextLong());
+    }
+    possibleItemIDs.removeAll(dataModel.getItemIDsFromUser(userID));
+    return possibleItemIDs;
+  }
+
+}

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericItemBasedRecommender.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericItemBasedRecommender.java?rev=981062&r1=981061&r2=981062&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericItemBasedRecommender.java (original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericItemBasedRecommender.java Sat Jul 31 14:15:10 2010
@@ -17,6 +17,7 @@
 
 package org.apache.mahout.cf.taste.impl.recommender;
 
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -69,8 +70,10 @@ public class GenericItemBasedRecommender
   private final RefreshHelper refreshHelper;
   private EstimatedPreferenceCapper capper;
 
-  public GenericItemBasedRecommender(DataModel dataModel, ItemSimilarity similarity) {
-    super(dataModel);
+  public GenericItemBasedRecommender(DataModel dataModel,
+                                     ItemSimilarity similarity,
+                                     CandidateItemsStrategy candidateItemsStrategy) {
+    super(dataModel, candidateItemsStrategy);
     if (similarity == null) {
       throw new IllegalArgumentException("similarity is null");
     }
@@ -80,7 +83,12 @@ public class GenericItemBasedRecommender
     refreshHelper.addDependency(similarity);
     capper = buildCapper();
   }
-  
+
+  public GenericItemBasedRecommender(DataModel dataModel,
+                                     ItemSimilarity similarity) {
+    this(dataModel, similarity, AbstractRecommender.getDefaultCandidateItemsStrategy());
+  }
+
   public ItemSimilarity getSimilarity() {
     return similarity;
   }

Added: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/PreferredItemsNeighborhoodCandidateItemsStrategy.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/PreferredItemsNeighborhoodCandidateItemsStrategy.java?rev=981062&view=auto
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/PreferredItemsNeighborhoodCandidateItemsStrategy.java (added)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/PreferredItemsNeighborhoodCandidateItemsStrategy.java Sat Jul 31 14:15:10 2010
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.recommender;
+
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.impl.common.FastIDSet;
+import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
+import org.apache.mahout.cf.taste.model.DataModel;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+
+/**
+ * returns all items that have not been rated by the user and that were preferred by another user
+ * that has preferred at least one item that the current user has preferred too
+ */
+public final class PreferredItemsNeighborhoodCandidateItemsStrategy implements CandidateItemsStrategy {
+
+  @Override
+  public FastIDSet getCandidateItems(long userID, DataModel dataModel) throws TasteException {
+    FastIDSet possibleItemsIDs = new FastIDSet();
+    FastIDSet itemIDs = dataModel.getItemIDsFromUser(userID);
+    LongPrimitiveIterator itemIDIterator = itemIDs.iterator();
+    while (itemIDIterator.hasNext()) {
+      long itemID = itemIDIterator.next();
+      PreferenceArray prefs2 = dataModel.getPreferencesForItem(itemID);
+      int size2 = prefs2.length();
+      for (int j = 0; j < size2; j++) {
+        possibleItemsIDs.addAll(dataModel.getItemIDsFromUser(prefs2.getUserID(j)));
+      }
+    }
+    possibleItemsIDs.removeAll(itemIDs);
+    return possibleItemsIDs;
+  }
+  
+}

Added: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/SamplingCandidateItemsStrategy.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/SamplingCandidateItemsStrategy.java?rev=981062&view=auto
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/SamplingCandidateItemsStrategy.java (added)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/SamplingCandidateItemsStrategy.java Sat Jul 31 14:15:10 2010
@@ -0,0 +1,89 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.recommender;
+
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.impl.common.FastIDSet;
+import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
+import org.apache.mahout.cf.taste.model.DataModel;
+import org.apache.mahout.cf.taste.model.Preference;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
+import org.apache.mahout.common.iterator.FixedSizeSamplingIterator;
+
+import java.util.Iterator;
+
+/**
+ * <p>returns all items that have not been rated by the user and that were preferred by another user
+ * that has preferred at least one item that the current user has preferred too</p>
+ *
+ * <p>this strategy uses sampling in a way that only a certain amount of preferences per item is considered
+ * <pre>
+ * max(defaultMaxPrefsPerItemConsidered, userItemCountFactor * log(max(N_users, N_items)))
+ * </pre></p>
+ */
+public class SamplingCandidateItemsStrategy implements CandidateItemsStrategy {
+
+  private final int defaultMaxPrefsPerItemConsidered;
+  private final int userItemCountMultiplier;
+
+  /**
+   * uses defaultMaxPrefsPerItemConsidered = 100 and userItemCountMultiplier = 20 as default values
+   * 
+   * @see SamplingCandidateItemsStrategy#SamplingCandidateItemsStrategy(int, int)
+   */
+  public SamplingCandidateItemsStrategy() {
+    this(100, 20);
+  }
+
+  /**
+   * <p>the maximum number of prefs considered per item will be computed like this:
+   * <pre>
+   *   max(defaultMaxPrefsPerItemConsidered, userItemCountFactor * log(max(N_users, N_items)))
+   * </pre>
+   * </p>
+   *
+   * @param defaultMaxPrefsPerItemConsidered
+   * @param userItemCountMultiplier
+   */
+  public SamplingCandidateItemsStrategy(int defaultMaxPrefsPerItemConsidered, int userItemCountMultiplier) {
+    this.defaultMaxPrefsPerItemConsidered = defaultMaxPrefsPerItemConsidered;
+    this.userItemCountMultiplier = userItemCountMultiplier;
+  }
+
+  @Override
+  public FastIDSet getCandidateItems(long userID, DataModel dataModel) throws TasteException {
+    int maxPrefsPerItemConsidered = (int) Math.max(defaultMaxPrefsPerItemConsidered,
+        userItemCountMultiplier * Math.log(Math.max(dataModel.getNumUsers(), dataModel.getNumItems())));
+    FastIDSet possibleItemsIDs = new FastIDSet();
+    FastIDSet itemIDs = dataModel.getItemIDsFromUser(userID);
+    LongPrimitiveIterator itemIDIterator = itemIDs.iterator();
+    while (itemIDIterator.hasNext()) {
+      long itemID = itemIDIterator.next();
+      PreferenceArray prefs = dataModel.getPreferencesForItem(itemID);
+      int prefsConsidered = Math.min(prefs.length(), maxPrefsPerItemConsidered);
+      Iterator<Preference> sampledPrefs = new FixedSizeSamplingIterator(prefsConsidered, prefs.iterator());
+      while (sampledPrefs.hasNext()) {
+        possibleItemsIDs.addAll(dataModel.getItemIDsFromUser(sampledPrefs.next().getUserID()));
+      }
+    }
+    possibleItemsIDs.removeAll(itemIDs);
+    return possibleItemsIDs;
+  }
+
+}

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/knn/KnnItemBasedRecommender.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/knn/KnnItemBasedRecommender.java?rev=981062&r1=981061&r2=981062&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/knn/KnnItemBasedRecommender.java (original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/knn/KnnItemBasedRecommender.java Sat Jul 31 14:15:10 2010
@@ -26,6 +26,7 @@ import org.apache.mahout.cf.taste.impl.r
 import org.apache.mahout.cf.taste.impl.recommender.TopItems;
 import org.apache.mahout.cf.taste.model.DataModel;
 import org.apache.mahout.cf.taste.model.PreferenceArray;
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
 import org.apache.mahout.cf.taste.recommender.RecommendedItem;
 import org.apache.mahout.cf.taste.recommender.Rescorer;
 import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
@@ -45,11 +46,19 @@ public final class KnnItemBasedRecommend
   public KnnItemBasedRecommender(DataModel dataModel,
                                  ItemSimilarity similarity,
                                  Optimizer optimizer,
+                                 CandidateItemsStrategy candidateItemsStrategy,
                                  int neighborhoodSize) {
-    super(dataModel, similarity);
+    super(dataModel, similarity, candidateItemsStrategy);
     this.optimizer = optimizer;
     this.neighborhoodSize = neighborhoodSize;
   }
+
+  public KnnItemBasedRecommender(DataModel dataModel,
+                                 ItemSimilarity similarity,
+                                 Optimizer optimizer,
+                                 int neighborhoodSize) {
+    this(dataModel, similarity, optimizer, getDefaultCandidateItemsStrategy(), neighborhoodSize);
+  }
   
   private List<RecommendedItem> mostSimilarItems(long itemID,
                                                  LongPrimitiveIterator possibleItemIDs,

Modified: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/svd/SVDRecommender.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/svd/SVDRecommender.java?rev=981062&r1=981061&r2=981062&view=diff
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/svd/SVDRecommender.java (original)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/svd/SVDRecommender.java Sat Jul 31 14:15:10 2010
@@ -38,6 +38,7 @@ import org.apache.mahout.cf.taste.impl.r
 import org.apache.mahout.cf.taste.impl.recommender.TopItems;
 import org.apache.mahout.cf.taste.model.DataModel;
 import org.apache.mahout.cf.taste.model.Preference;
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
 import org.apache.mahout.cf.taste.recommender.IDRescorer;
 import org.apache.mahout.cf.taste.recommender.RecommendedItem;
 import org.apache.mahout.common.RandomUtils;
@@ -70,8 +71,11 @@ public final class SVDRecommender extend
    * @param initialSteps
    *          number of initial training steps
    */
-  public SVDRecommender(DataModel dataModel, int numFeatures, int initialSteps) throws TasteException {
-    super(dataModel);
+  public SVDRecommender(DataModel dataModel,
+                        CandidateItemsStrategy candidateItemsStrategy,
+                        int numFeatures,
+                        int initialSteps) throws TasteException {
+    super(dataModel, candidateItemsStrategy);
     
     this.numFeatures = numFeatures;
     
@@ -112,6 +116,12 @@ public final class SVDRecommender extend
     
     train(initialSteps);
   }
+
+  public SVDRecommender(DataModel dataModel,
+                        int numFeatures,
+                        int initialSteps) throws TasteException {
+    this(dataModel, getDefaultCandidateItemsStrategy(), numFeatures, initialSteps);
+  }
   
   private void recachePreferences() throws TasteException {
     cachedPreferences.clear();

Added: mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/CandidateItemsStrategy.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/CandidateItemsStrategy.java?rev=981062&view=auto
==============================================================================
--- mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/CandidateItemsStrategy.java (added)
+++ mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/CandidateItemsStrategy.java Sat Jul 31 14:15:10 2010
@@ -0,0 +1,34 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.recommender;
+
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.impl.common.FastIDSet;
+import org.apache.mahout.cf.taste.model.DataModel;
+
+/**
+ * Used to retrieve all items that could possibly be recommended to the user
+ */
+public interface CandidateItemsStrategy {
+
+  /**
+   * #return IDs of all items that could be recommended to the user
+   */
+  FastIDSet getCandidateItems(long userID, DataModel dataModel) throws TasteException;
+  
+}

Added: mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/AllUnknownItemsCandidateItemsStrategyTest.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/AllUnknownItemsCandidateItemsStrategyTest.java?rev=981062&view=auto
==============================================================================
--- mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/AllUnknownItemsCandidateItemsStrategyTest.java (added)
+++ mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/AllUnknownItemsCandidateItemsStrategyTest.java Sat Jul 31 14:15:10 2010
@@ -0,0 +1,56 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.recommender;
+
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.impl.TasteTestCase;
+import org.apache.mahout.cf.taste.impl.common.FastIDSet;
+import org.apache.mahout.cf.taste.model.DataModel;
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
+import org.easymock.classextension.EasyMock;
+
+/**
+ * Tests {@link AllUnknownItemsCandidateItemsStrategyTest}
+ */
+public final class AllUnknownItemsCandidateItemsStrategyTest extends TasteTestCase {
+
+  public void testStrategy() throws TasteException {
+    FastIDSet allItemIDs = new FastIDSet();
+    allItemIDs.addAll(new long[] { 1L, 2L, 3L });
+
+    FastIDSet preferredItemIDs = new FastIDSet(1);
+    preferredItemIDs.add(2L);
+    
+    DataModel dataModel = EasyMock.createMock(DataModel.class);
+    EasyMock.expect(dataModel.getNumItems()).andReturn(3);
+    EasyMock.expect(dataModel.getItemIDs()).andReturn(allItemIDs.iterator());
+    EasyMock.expect(dataModel.getItemIDsFromUser(123L)).andReturn(preferredItemIDs);
+
+    CandidateItemsStrategy strategy = new AllUnknownItemsCandidateItemsStrategy();
+
+    EasyMock.replay(dataModel);
+
+    FastIDSet candidateItems = strategy.getCandidateItems(123L, dataModel);
+    assertEquals(2, candidateItems.size());
+    assertTrue(candidateItems.contains(1L));
+    assertTrue(candidateItems.contains(3L));
+
+    EasyMock.verify(dataModel);
+  }
+
+}

Added: mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/PreferredItemsNeighborhoodCandidateItemsStrategyTest.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/PreferredItemsNeighborhoodCandidateItemsStrategyTest.java?rev=981062&view=auto
==============================================================================
--- mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/PreferredItemsNeighborhoodCandidateItemsStrategyTest.java (added)
+++ mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/PreferredItemsNeighborhoodCandidateItemsStrategyTest.java Sat Jul 31 14:15:10 2010
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.recommender;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.impl.TasteTestCase;
+import org.apache.mahout.cf.taste.impl.common.FastIDSet;
+import org.apache.mahout.cf.taste.impl.model.GenericItemPreferenceArray;
+import org.apache.mahout.cf.taste.impl.model.GenericPreference;
+import org.apache.mahout.cf.taste.model.DataModel;
+import org.apache.mahout.cf.taste.model.Preference;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
+import org.easymock.EasyMock;
+
+/**
+ * Tests {@link PreferredItemsNeighborhoodCandidateItemsStrategy}
+ */
+public final class PreferredItemsNeighborhoodCandidateItemsStrategyTest extends TasteTestCase {
+
+  public void testStrategy() throws TasteException {
+    FastIDSet itemIDsFromUser123 = new FastIDSet();
+    itemIDsFromUser123.add(1L);
+
+    FastIDSet itemIDsFromUser456 = new FastIDSet();
+    itemIDsFromUser456.add(1L);
+    itemIDsFromUser456.add(2L);
+
+    List<Preference> prefs = new ArrayList<Preference>();
+    prefs.add(new GenericPreference(123L, 1L, 1.0f));
+    prefs.add(new GenericPreference(456L, 1L, 1.0f));
+    PreferenceArray preferencesForItem1 = new GenericItemPreferenceArray(prefs);
+
+    DataModel dataModel = EasyMock.createMock(DataModel.class);
+    EasyMock.expect(dataModel.getItemIDsFromUser(123L)).andReturn(itemIDsFromUser123);
+    EasyMock.expect(dataModel.getPreferencesForItem(1L)).andReturn(preferencesForItem1);
+    EasyMock.expect(dataModel.getItemIDsFromUser(123L)).andReturn(itemIDsFromUser123);
+    EasyMock.expect(dataModel.getItemIDsFromUser(456L)).andReturn(itemIDsFromUser456);
+
+    CandidateItemsStrategy strategy = new PreferredItemsNeighborhoodCandidateItemsStrategy();
+
+    EasyMock.replay(dataModel);
+
+    FastIDSet candidateItems = strategy.getCandidateItems(123L, dataModel);
+    assertEquals(1, candidateItems.size());
+    assertTrue(candidateItems.contains(2L));
+
+    EasyMock.verify(dataModel);
+  }
+  
+}

Added: mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/SamplingCandidateItemsStrategyTest.java
URL: http://svn.apache.org/viewvc/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/SamplingCandidateItemsStrategyTest.java?rev=981062&view=auto
==============================================================================
--- mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/SamplingCandidateItemsStrategyTest.java (added)
+++ mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/SamplingCandidateItemsStrategyTest.java Sat Jul 31 14:15:10 2010
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.mahout.cf.taste.impl.recommender;
+
+import org.apache.mahout.cf.taste.common.TasteException;
+import org.apache.mahout.cf.taste.impl.TasteTestCase;
+import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
+import org.apache.mahout.cf.taste.impl.common.FastIDSet;
+import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
+import org.apache.mahout.cf.taste.impl.model.GenericPreference;
+import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
+import org.apache.mahout.cf.taste.model.DataModel;
+import org.apache.mahout.cf.taste.model.Preference;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+import org.apache.mahout.cf.taste.recommender.CandidateItemsStrategy;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests {@link SamplingCandidateItemsStrategy}
+ */
+public final class SamplingCandidateItemsStrategyTest extends TasteTestCase {
+
+  public void testStrategy() throws TasteException {
+    List<Preference> prefsOfUser123 = new ArrayList<Preference>();
+    prefsOfUser123.add(new GenericPreference(123L, 1L, 1.0f));
+
+    List<Preference> prefsOfUser456 = new ArrayList<Preference>();
+    prefsOfUser456.add(new GenericPreference(456L, 1L, 1.0f));
+    prefsOfUser456.add(new GenericPreference(456L, 2L, 1.0f));
+
+    List<Preference> prefsOfUser789 = new ArrayList<Preference>();
+    prefsOfUser456.add(new GenericPreference(789L, 1L, 0.5f));
+    prefsOfUser456.add(new GenericPreference(789L, 3L, 1.0f));
+
+    FastByIDMap<PreferenceArray> userData = new FastByIDMap<PreferenceArray>();
+    userData.put(123L, new GenericUserPreferenceArray(prefsOfUser123));
+    userData.put(456L, new GenericUserPreferenceArray(prefsOfUser456));
+    userData.put(789L, new GenericUserPreferenceArray(prefsOfUser789));
+
+    DataModel dataModel = new GenericDataModel(userData);
+
+    CandidateItemsStrategy strategy = new SamplingCandidateItemsStrategy(1, 1);
+
+    FastIDSet candidateItems = strategy.getCandidateItems(123L, dataModel);
+    /* result can be either item2 or item3 or empty */
+    assertTrue(candidateItems.size() <= 1);
+    assertFalse(candidateItems.contains(1L));
+  }
+}