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 2009/08/04 02:06:50 UTC

svn commit: r800634 [1/7] - in /lucene/mahout/trunk: core/src/main/java/org/apache/mahout/cf/taste/hadoop/ core/src/main/java/org/apache/mahout/cf/taste/impl/common/ core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/ core/src/main/java/org...

Author: srowen
Date: Tue Aug  4 00:06:46 2009
New Revision: 800634

URL: http://svn.apache.org/viewvc?rev=800634&view=rev
Log:
Remove User/Item abstractions. Preference values are now floats. Lots of API changes to reflect and rationalize these changes. Replace Preference[] with PreferenceArray implementations for memory efficiency.

Added:
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanItemPreferenceArray.java
      - copied, changed from r797487, lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreferenceArray.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanUserPreferenceArray.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanPrefDataModel.java
      - copied, changed from r797487, lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanUserDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericItemPreferenceArray.java
      - copied, changed from r800080, lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreferenceArray.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUserPreferenceArray.java
      - copied, changed from r800080, lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreferenceArray.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericBooleanPrefUserBasedRecommender.java
      - copied, changed from r797487, lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/BooleanUserGenericUserBasedRecommender.java
Removed:
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanPrefUser.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/ByItemPreferenceComparator.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/ByUserPreferenceComparator.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/ByValuePreferenceComparator.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanUserDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreferenceArray.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericUser.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/SettableUserPreference.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/BooleanUserGenericUserBasedRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/BooleanLogLikelihoodSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/BooleanTanimotoCoefficientSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/model/User.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/bookcrossing/BookCrossingUser.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/bookcrossing/GeoUserSimilarity.java
Modified:
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/ItemItemWritable.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/ItemPrefWritable.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/RecommendedItemsWritable.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOneDiffsToAveragesJob.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOneDiffsToAveragesReducer.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsJob.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsMapper.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsReducer.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FastMap.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FastSet.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FileLineIterator.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RandomUtils.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RefreshHelper.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/AbstractJDBCComponent.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AverageAbsoluteDifferenceRecommenderEvaluator.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/GenericRecommenderIRStatsEvaluator.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/LoadEvaluator.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/RMSRecommenderEvaluator.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanPreference.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreference.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractBooleanPrefJDBCDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/AbstractJDBCDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/ConnectionPoolDataSource.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/GenericJDBCDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/MySQLBooleanPrefJDBCDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/jdbc/MySQLJDBCDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/neighborhood/CachingUserNeighborhood.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/neighborhood/NearestNUserNeighborhood.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/neighborhood/ThresholdUserNeighborhood.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/AbstractRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/CachingRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ClusterSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/FarthestNeighborClusterSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericItemBasedRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericRecommendedItem.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/GenericUserBasedRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemAverageRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/ItemUserAverageRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/NearestNeighborClusterSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/NullRescorer.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/SimilarUser.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TopItems.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommender2.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/knn/KnnItemBasedRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/MemoryDiffStorage.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/SlopeOneRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/jdbc/AbstractJDBCDiffStorage.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/jdbc/MySQLJDBCDiffStorage.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/recommender/svd/SVDRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/AbstractSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/AveragingPreferenceInferrer.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/CachingUserSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/EuclideanDistanceSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/GenericUserSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/LogLikelihoodSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/PearsonCorrelationSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/SpearmanCorrelationSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/TanimotoCoefficientSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/AbstractJDBCItemSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/similarity/jdbc/MySQLJDBCItemSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/transforms/InverseUserFrequency.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/transforms/ZScore.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/model/DataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/model/JDBCDataModel.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/model/Preference.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/model/PreferenceArray.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/neighborhood/UserNeighborhood.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/ClusteringRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/ItemBasedRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/RecommendedItem.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/Recommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/Rescorer.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/UserBasedRecommender.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/recommender/slopeone/DiffStorage.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/similarity/ItemSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/similarity/PreferenceInferrer.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/similarity/UserSimilarity.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/transforms/PreferenceTransform.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/transforms/SimilarityTransform.java
    lucene/mahout/trunk/core/src/main/java/org/apache/mahout/clustering/kmeans/KMeansDriver.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/LoadTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/TasteTestCase.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/model/file/FileDataModelTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/neighborhood/DummySimilarity.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/neighborhood/NearestNNeighborhoodTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/neighborhood/ThresholdNeighborhoodTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/GenericItemBasedRecommenderTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/GenericUserBasedRecommenderTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/MockRecommender.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/NullRescorerTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/TreeClusteringRecommenderTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/MemoryDiffStorageTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/recommender/slopeone/SlopeOneRecommenderTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/AveragingPreferenceInferrerTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/EuclideanDistanceSimilarityTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/GenericItemSimilarityTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/LogLikelihoodSimilarityTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/PearsonCorrelationSimilarityTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/SpearmanCorrelationSimilarityTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/similarity/TanimotoCoefficientSimilarityTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/transforms/InverseUserFrequencyTest.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/transforms/TransformTestCase.java
    lucene/mahout/trunk/core/src/test/java/org/apache/mahout/cf/taste/impl/transforms/ZScoreTest.java
    lucene/mahout/trunk/examples/   (props changed)
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/ejb/RecommenderEJB.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/ejb/RecommenderEJBBean.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/ejb/RecommenderEJBLocal.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/bookcrossing/BookCrossingDataModel.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/bookcrossing/BookCrossingRecommender.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/grouplens/GroupLensDataModel.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/grouplens/GroupLensRecommender.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/jester/JesterDataModel.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/jester/JesterRecommender.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/netflix/NetflixDataModel.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/netflix/NetflixFileDataModel.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/netflix/NetflixRecommender.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/netflix/NetflixRecommenderEvaluatorRunner.java
    lucene/mahout/trunk/examples/src/main/java/org/apache/mahout/cf/taste/example/netflix/TransposeToByUser.java
    lucene/mahout/trunk/taste-web/src/main/java/org/apache/mahout/cf/taste/web/RecommenderServlet.java

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/ItemItemWritable.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/ItemItemWritable.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/ItemItemWritable.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/ItemItemWritable.java Tue Aug  4 00:06:46 2009
@@ -23,7 +23,7 @@
 import java.io.DataOutput;
 import java.io.IOException;
 
-/** A {@link WritableComparable} encapsulating two {@link org.apache.mahout.cf.taste.model.Item}s. */
+/** A {@link WritableComparable} encapsulating two items. */
 public final class ItemItemWritable implements WritableComparable<ItemItemWritable> {
 
   private String itemAID;

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/ItemPrefWritable.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/ItemPrefWritable.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/ItemPrefWritable.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/ItemPrefWritable.java Tue Aug  4 00:06:46 2009
@@ -23,17 +23,17 @@
 import java.io.DataOutput;
 import java.io.IOException;
 
-/** A {@link Writable} encapsulating a {@link org.apache.mahout.cf.taste.model.Item} and a preference value. */
+/** A {@link Writable} encapsulating an item and a preference value. */
 public final class ItemPrefWritable implements Writable {
 
   private String itemID;
-  private double prefValue;
+  private float prefValue;
 
   public ItemPrefWritable() {
     // do nothing
   }
 
-  public ItemPrefWritable(String itemID, double prefValue) {
+  public ItemPrefWritable(String itemID, float prefValue) {
     this.itemID = itemID;
     this.prefValue = prefValue;
   }
@@ -46,20 +46,20 @@
     return itemID;
   }
 
-  public double getPrefValue() {
+  public float getPrefValue() {
     return prefValue;
   }
 
   @Override
   public void write(DataOutput out) throws IOException {
     out.writeUTF(itemID);
-    out.writeDouble(prefValue);
+    out.writeFloat(prefValue);
   }
 
   @Override
   public void readFields(DataInput in) throws IOException {
     itemID = in.readUTF();
-    prefValue = in.readDouble();
+    prefValue = in.readFloat();
   }
 
   public static ItemPrefWritable read(DataInput in) throws IOException {

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/RecommendedItemsWritable.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/RecommendedItemsWritable.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/RecommendedItemsWritable.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/RecommendedItemsWritable.java Tue Aug  4 00:06:46 2009
@@ -52,7 +52,7 @@
   public void write(DataOutput out) throws IOException {
     for (RecommendedItem item : recommended) {
       out.writeUTF(item.getItemID().toString());
-      out.writeDouble(item.getValue());
+      out.writeFloat(item.getValue());
     }
 
   }
@@ -63,7 +63,7 @@
     try {
       do {
         String itemID = in.readUTF();
-        double value = in.readDouble();
+        float value = in.readFloat();
         RecommendedItem recommendedItem = new GenericRecommendedItem(itemID, value);
         recommended.add(recommendedItem);
       } while (true);

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOneDiffsToAveragesJob.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOneDiffsToAveragesJob.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOneDiffsToAveragesJob.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOneDiffsToAveragesJob.java Tue Aug  4 00:06:46 2009
@@ -20,7 +20,7 @@
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.io.DoubleWritable;
+import org.apache.hadoop.io.FloatWritable;
 import org.apache.hadoop.mapreduce.InputFormat;
 import org.apache.hadoop.mapreduce.Job;
 import org.apache.hadoop.mapreduce.Mapper;
@@ -64,11 +64,11 @@
 
     jobConf.setClass("mapred.mapper.class", Mapper.class, Mapper.class);
     jobConf.setClass("mapred.mapoutput.key.class", ItemItemWritable.class, Object.class);
-    jobConf.setClass("mapred.mapoutput.value.class", DoubleWritable.class, Object.class);
+    jobConf.setClass("mapred.mapoutput.value.class", FloatWritable.class, Object.class);
 
     jobConf.setClass("mapred.reducer.class", SlopeOneDiffsToAveragesReducer.class, Reducer.class);
     jobConf.setClass("mapred.output.key.class", ItemItemWritable.class, Object.class);
-    jobConf.setClass("mapred.output.value.class", DoubleWritable.class, Object.class);
+    jobConf.setClass("mapred.output.value.class", FloatWritable.class, Object.class);
 
     jobConf.setClass("mapred.output.format.class", TextOutputFormat.class, OutputFormat.class);
     jobConf.set("mapred.output.dir", StringUtils.escapeString(outputPathPath.toString()));

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOneDiffsToAveragesReducer.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOneDiffsToAveragesReducer.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOneDiffsToAveragesReducer.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOneDiffsToAveragesReducer.java Tue Aug  4 00:06:46 2009
@@ -17,24 +17,24 @@
 
 package org.apache.mahout.cf.taste.hadoop;
 
-import org.apache.hadoop.io.DoubleWritable;
+import org.apache.hadoop.io.FloatWritable;
 import org.apache.hadoop.mapreduce.Reducer;
 
 import java.io.IOException;
 
 public final class SlopeOneDiffsToAveragesReducer
-    extends Reducer<ItemItemWritable, DoubleWritable, ItemItemWritable, DoubleWritable> {
+    extends Reducer<ItemItemWritable, FloatWritable, ItemItemWritable, FloatWritable> {
 
   @Override
-  protected void reduce(ItemItemWritable key, Iterable<DoubleWritable> values, Context context)
+  protected void reduce(ItemItemWritable key, Iterable<FloatWritable> values, Context context)
       throws IOException, InterruptedException {
     int count = 0;
     double total = 0.0;
-    for (DoubleWritable value : values) {
+    for (FloatWritable value : values) {
       total += value.get();
       count++;
     }
-    context.write(key, new DoubleWritable((total / count)));
+    context.write(key, new FloatWritable((float) (total / count)));
   }
 
 }
\ No newline at end of file

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsJob.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsJob.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsJob.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsJob.java Tue Aug  4 00:06:46 2009
@@ -20,7 +20,7 @@
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.io.DoubleWritable;
+import org.apache.hadoop.io.FloatWritable;
 import org.apache.hadoop.io.Text;
 import org.apache.hadoop.mapreduce.InputFormat;
 import org.apache.hadoop.mapreduce.Job;
@@ -69,7 +69,7 @@
 
     jobConf.setClass("mapred.reducer.class", SlopeOnePrefsToDiffsReducer.class, Reducer.class);
     jobConf.setClass("mapred.output.key.class", ItemItemWritable.class, Object.class);
-    jobConf.setClass("mapred.output.value.class", DoubleWritable.class, Object.class);
+    jobConf.setClass("mapred.output.value.class", FloatWritable.class, Object.class);
 
     jobConf.setClass("mapred.output.format.class", SequenceFileOutputFormat.class, OutputFormat.class);
     jobConf.set("mapred.output.dir", StringUtils.escapeString(outputPathPath.toString()));

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsMapper.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsMapper.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsMapper.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsMapper.java Tue Aug  4 00:06:46 2009
@@ -33,7 +33,7 @@
     String[] tokens = line.split(",");
     String userID = tokens[0];
     String itemID = tokens[1];
-    double prefValue = Double.parseDouble(tokens[2]);
+    float prefValue = Float.parseFloat(tokens[2]);
     context.write(new Text(userID), new ItemPrefWritable(itemID, prefValue));
   }
 

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsReducer.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsReducer.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsReducer.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/hadoop/SlopeOnePrefsToDiffsReducer.java Tue Aug  4 00:06:46 2009
@@ -17,7 +17,7 @@
 
 package org.apache.mahout.cf.taste.hadoop;
 
-import org.apache.hadoop.io.DoubleWritable;
+import org.apache.hadoop.io.FloatWritable;
 import org.apache.hadoop.io.Text;
 import org.apache.hadoop.mapreduce.Reducer;
 
@@ -27,7 +27,7 @@
 import java.util.List;
 
 public final class SlopeOnePrefsToDiffsReducer
-    extends Reducer<Text, ItemPrefWritable, ItemItemWritable, DoubleWritable> {
+    extends Reducer<Text, ItemPrefWritable, ItemItemWritable, FloatWritable> {
 
   @Override
   protected void reduce(Text key, Iterable<ItemPrefWritable> values, Context context)
@@ -41,12 +41,12 @@
     for (int i = 0; i < size; i++) {
       ItemPrefWritable first = prefs.get(i);
       String itemAID = first.getItemID();
-      double itemAValue = first.getPrefValue();
+      float itemAValue = first.getPrefValue();
       for (int j = i + 1; j < size; j++) {
         ItemPrefWritable second = prefs.get(j);
         String itemBID = second.getItemID();
-        double itemBValue = second.getPrefValue();
-        context.write(new ItemItemWritable(itemAID, itemBID), new DoubleWritable(itemBValue - itemAValue));
+        float itemBValue = second.getPrefValue();
+        context.write(new ItemItemWritable(itemAID, itemBID), new FloatWritable(itemBValue - itemAValue));
       }
     }
   }

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FastMap.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FastMap.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FastMap.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FastMap.java Tue Aug  4 00:06:46 2009
@@ -42,6 +42,7 @@
 public final class FastMap<K, V> implements Map<K, V>, Serializable, Cloneable {
 
   public static final int NO_MAX_SIZE = Integer.MAX_VALUE;
+  private static final double ALLOWED_LOAD_FACTOR = 1.5;
 
   /** Dummy object used to represent a key that has been removed. */
   private static final Object REMOVED = new Object();
@@ -63,25 +64,32 @@
     this(size, NO_MAX_SIZE);
   }
 
+  public FastMap(Map<K,V> other) {
+    this(other.size());
+    putAll(other);
+  }
+
   /**
    * Creates a new {@link FastMap} whose capacity can accommodate the given number of entries without rehash.</p>
    *
    * @param size    desired capacity
    * @param maxSize max capacity
-   * @throws IllegalArgumentException if size is less than 1 or at least half of {@link RandomUtils#MAX_INT_SMALLER_TWIN_PRIME}
+   * @throws IllegalArgumentException if size is less than 0, maxSize is less than 1,
+   *  or at least half of {@link RandomUtils#MAX_INT_SMALLER_TWIN_PRIME}
    */
   @SuppressWarnings("unchecked")
   public FastMap(int size, int maxSize) {
-    if (size < 1) {
-      throw new IllegalArgumentException("size must be at least 1");
+    if (size < 0) {
+      throw new IllegalArgumentException("size must be at least 0");
     }
-    if (size >= RandomUtils.MAX_INT_SMALLER_TWIN_PRIME >> 1) {
-      throw new IllegalArgumentException("size must be less than " + (RandomUtils.MAX_INT_SMALLER_TWIN_PRIME >> 1));
+    int max = (int) (RandomUtils.MAX_INT_SMALLER_TWIN_PRIME / ALLOWED_LOAD_FACTOR);
+    if (size >= max) {
+      throw new IllegalArgumentException("size must be less than " + max);
     }
     if (maxSize < 1) {
       throw new IllegalArgumentException("maxSize must be at least 1");
     }
-    int hashSize = RandomUtils.nextTwinPrime(2 * size);
+    int hashSize = RandomUtils.nextTwinPrime((int) (ALLOWED_LOAD_FACTOR * size));
     keys = (K[]) new Object[hashSize];
     values = (V[]) new Object[hashSize];
     this.maxSize = maxSize;
@@ -170,9 +178,9 @@
       throw new NullPointerException();
     }
     // If less than half the slots are open, let's clear it up
-    if (numSlotsUsed >= keys.length >> 1) {
+    if (numSlotsUsed * ALLOWED_LOAD_FACTOR >= keys.length) {
       // If over half the slots used are actual entries, let's grow
-      if (numEntries >= numSlotsUsed >> 1) {
+      if (numEntries * ALLOWED_LOAD_FACTOR >= numSlotsUsed) {
         growAndRehash();
       } else {
         // Otherwise just rehash to clear REMOVED entries and don't grow
@@ -275,14 +283,14 @@
   }
 
   public void rehash() {
-    rehash(RandomUtils.nextTwinPrime(numEntries << 1));
+    rehash(RandomUtils.nextTwinPrime((int) (ALLOWED_LOAD_FACTOR * numEntries)));
   }
 
   private void growAndRehash() {
-    if (keys.length >= RandomUtils.MAX_INT_SMALLER_TWIN_PRIME >> 1) {
+    if (keys.length * ALLOWED_LOAD_FACTOR >= RandomUtils.MAX_INT_SMALLER_TWIN_PRIME) {
       throw new IllegalStateException("Can't grow any more");
     }
-    rehash(RandomUtils.nextTwinPrime(keys.length << 1));
+    rehash(RandomUtils.nextTwinPrime((int) (ALLOWED_LOAD_FACTOR * keys.length)));
   }
 
   @SuppressWarnings("unchecked")

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FastSet.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FastSet.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FastSet.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FastSet.java Tue Aug  4 00:06:46 2009
@@ -41,6 +41,8 @@
  */
 public final class FastSet<K> implements Set<K>, Serializable, Cloneable {
 
+  private static final double ALLOWED_LOAD_FACTOR = 1.5;
+
   /** Dummy object used to represent a key that has been removed. */
   private static final Object REMOVED = new Object();
 
@@ -60,13 +62,14 @@
 
   @SuppressWarnings("unchecked")
   public FastSet(int size) {
-    if (size < 1) {
-      throw new IllegalArgumentException("size must be at least 1");
+    if (size < 0) {
+      throw new IllegalArgumentException("size must be at least 0");
     }
-    if (size >= RandomUtils.MAX_INT_SMALLER_TWIN_PRIME >> 1) {
-      throw new IllegalArgumentException("size must be less than " + (RandomUtils.MAX_INT_SMALLER_TWIN_PRIME >> 1));
+    int max = (int) (RandomUtils.MAX_INT_SMALLER_TWIN_PRIME / ALLOWED_LOAD_FACTOR);
+    if (size >= max) {
+      throw new IllegalArgumentException("size must be less than " + max);
     }
-    int hashSize = RandomUtils.nextTwinPrime(2 * size);
+    int hashSize = RandomUtils.nextTwinPrime((int) (ALLOWED_LOAD_FACTOR * size));
     keys = (K[]) new Object[hashSize];
   }
 
@@ -118,9 +121,9 @@
       throw new NullPointerException();
     }
     // If less than half the slots are open, let's clear it up
-    if (numSlotsUsed >= keys.length >> 1) {
+    if (numSlotsUsed * ALLOWED_LOAD_FACTOR >= keys.length) {
       // If over half the slots used are actual entries, let's grow
-      if (numEntries >= numSlotsUsed >> 1) {
+      if (numEntries * ALLOWED_LOAD_FACTOR >= numSlotsUsed) {
         growAndRehash();
       } else {
         // Otherwise just rehash to clear REMOVED entries and don't grow
@@ -235,14 +238,14 @@
   }
 
   private void growAndRehash() {
-    if (keys.length >= RandomUtils.MAX_INT_SMALLER_TWIN_PRIME >> 1) {
+    if (keys.length * ALLOWED_LOAD_FACTOR >= RandomUtils.MAX_INT_SMALLER_TWIN_PRIME) {
       throw new IllegalStateException("Can't grow any more");
     }
-    rehash(RandomUtils.nextTwinPrime(keys.length << 1));
+    rehash(RandomUtils.nextTwinPrime((int) (ALLOWED_LOAD_FACTOR * keys.length)));
   }
 
   public void rehash() {
-    rehash(RandomUtils.nextTwinPrime(numEntries << 1));
+    rehash(RandomUtils.nextTwinPrime((int) (ALLOWED_LOAD_FACTOR * numEntries)));
   }
 
   @SuppressWarnings("unchecked")

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FileLineIterator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FileLineIterator.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FileLineIterator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/FileLineIterator.java Tue Aug  4 00:06:46 2009
@@ -78,6 +78,10 @@
     }
   }
 
+  public String peek() {
+    return nextLine;
+  }
+
   @Override
   public boolean hasNext() {
     return nextLine != null;

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RandomUtils.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RandomUtils.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RandomUtils.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RandomUtils.java Tue Aug  4 00:06:46 2009
@@ -51,6 +51,10 @@
     return (int) (bits ^ (bits >>> 32));
   }
 
+  public static int hashFloat(float value) {
+    return Float.floatToIntBits(value);
+  }
+
   /**
    * <p>Finds next-largest "twin primes": numbers p and p+2 such that both are prime. Finds the smallest such p such
    * that the smaller twin, p, is greater than or equal to n. Returns p+2, the larger of the two twins.</p>
@@ -59,7 +63,7 @@
     if (n > MAX_INT_SMALLER_TWIN_PRIME) {
       throw new IllegalArgumentException();
     }
-    if (n <= 2) {
+    if (n <= 3) {
       return 3;
     }
     int next = nextPrime(n);

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RefreshHelper.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RefreshHelper.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RefreshHelper.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/RefreshHelper.java Tue Aug  4 00:06:46 2009
@@ -93,7 +93,7 @@
    * @return an empty {@link FastSet} if the method param was <code>null</code> or the unmodified method param.
    */
   public static Collection<Refreshable> buildRefreshed(Collection<Refreshable> currentAlreadyRefreshed) {
-    return currentAlreadyRefreshed == null ? new FastSet<Refreshable>(3) : currentAlreadyRefreshed;
+    return currentAlreadyRefreshed == null ? new FastSet<Refreshable>(2) : currentAlreadyRefreshed;
   }
 
   /**

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/AbstractJDBCComponent.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/AbstractJDBCComponent.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/AbstractJDBCComponent.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/common/jdbc/AbstractJDBCComponent.java Tue Aug  4 00:06:46 2009
@@ -17,14 +17,14 @@
 
 package org.apache.mahout.cf.taste.impl.common.jdbc;
 
+import org.apache.mahout.cf.taste.common.TasteException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.mahout.cf.taste.common.TasteException;
 
-import javax.sql.DataSource;
 import javax.naming.Context;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
+import javax.sql.DataSource;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AbstractDifferenceRecommenderEvaluator.java Tue Aug  4 00:06:46 2009
@@ -24,10 +24,9 @@
 import org.apache.mahout.cf.taste.impl.common.RandomUtils;
 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.GenericUser;
 import org.apache.mahout.cf.taste.model.DataModel;
 import org.apache.mahout.cf.taste.model.Preference;
-import org.apache.mahout.cf.taste.model.User;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
 import org.apache.mahout.cf.taste.recommender.Recommender;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -71,17 +70,18 @@
     log.info("Beginning evaluation using " + trainingPercentage + " of " + dataModel);
 
     int numUsers = dataModel.getNumUsers();
-    Collection<User> trainingUsers = new ArrayList<User>(1 + (int) (trainingPercentage * (double) numUsers));
-    Map<User, Collection<Preference>> testUserPrefs =
-        new FastMap<User, Collection<Preference>>(1 + (int) ((1.0 - trainingPercentage) * (double) numUsers));
+    Map<Comparable<?>, Collection<Preference>> trainingUsers =
+            new FastMap<Comparable<?>, Collection<Preference>>(1 + (int) (trainingPercentage * (double) numUsers));
+    Map<Comparable<?>, Collection<Preference>> testUserPrefs =
+            new FastMap<Comparable<?>, Collection<Preference>>(1 + (int) ((1.0 - trainingPercentage) * (double) numUsers));
 
-    for (User user : dataModel.getUsers()) {
+    for (Comparable<?> userID : dataModel.getUserIDs()) {
       if (random.nextDouble() < evaluationPercentage) {
-        processOneUser(trainingPercentage, trainingUsers, testUserPrefs, user);
+        processOneUser(trainingPercentage, trainingUsers, testUserPrefs, userID, dataModel);
       }
     }
 
-    DataModel trainingModel = new GenericDataModel(trainingUsers);
+    DataModel trainingModel = new GenericDataModel(GenericDataModel.toPrefArrayValues(trainingUsers, true));
 
     Recommender recommender = recommenderBuilder.buildRecommender(trainingModel);
 
@@ -91,14 +91,16 @@
   }
 
   private void processOneUser(double trainingPercentage,
-                              Collection<User> trainingUsers,
-                              Map<User, Collection<Preference>> testUserPrefs,
-                              User user) {
+                              Map<Comparable<?>, Collection<Preference>> trainingUsers,
+                              Map<Comparable<?>, Collection<Preference>> testUserPrefs,
+                              Comparable<?> userID,
+                              DataModel dataModel) throws TasteException {
     List<Preference> trainingPrefs = new ArrayList<Preference>();
     List<Preference> testPrefs = new ArrayList<Preference>();
-    Preference[] prefs = user.getPreferencesAsArray();
-    for (Preference pref : prefs) {
-      Preference newPref = new GenericPreference(null, pref.getItemID(), pref.getValue());
+    PreferenceArray prefs = dataModel.getPreferencesFromUser(userID);
+    int size = prefs.length();
+    for (int i = 0; i < size; i++) {
+      Preference newPref = new GenericPreference(userID, prefs.getItemID(i), prefs.getValue(i));
       if (random.nextDouble() < trainingPercentage) {
         trainingPrefs.add(newPref);
       } else {
@@ -108,16 +110,14 @@
     log.debug("Training against {} preferences", trainingPrefs.size());
     log.debug("Evaluating accuracy of {} preferences", testPrefs.size());
     if (!trainingPrefs.isEmpty()) {
-      Comparable<?> id = user.getID();
-      User trainingUser = new GenericUser(id, trainingPrefs);
-      trainingUsers.add(trainingUser);
+      trainingUsers.put(userID, trainingPrefs);
       if (!testPrefs.isEmpty()) {
-        testUserPrefs.put(trainingUser, testPrefs);
+        testUserPrefs.put(userID, testPrefs);
       }
     }
   }
 
-  abstract double getEvaluation(Map<User, Collection<Preference>> testUserPrefs, Recommender recommender)
+  abstract double getEvaluation(Map<Comparable<?>, Collection<Preference>> testUserPrefs, Recommender recommender)
       throws TasteException;
 
 }

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AverageAbsoluteDifferenceRecommenderEvaluator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AverageAbsoluteDifferenceRecommenderEvaluator.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AverageAbsoluteDifferenceRecommenderEvaluator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/AverageAbsoluteDifferenceRecommenderEvaluator.java Tue Aug  4 00:06:46 2009
@@ -23,7 +23,6 @@
 import org.apache.mahout.cf.taste.impl.common.FullRunningAverage;
 import org.apache.mahout.cf.taste.impl.common.RunningAverage;
 import org.apache.mahout.cf.taste.model.Preference;
-import org.apache.mahout.cf.taste.model.User;
 import org.apache.mahout.cf.taste.recommender.Recommender;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -42,23 +41,23 @@
   private static final Logger log = LoggerFactory.getLogger(AverageAbsoluteDifferenceRecommenderEvaluator.class);
 
   @Override
-  double getEvaluation(Map<User, Collection<Preference>> testUserPrefs,
+  double getEvaluation(Map<Comparable<?>, Collection<Preference>> testUserPrefs,
                        Recommender recommender)
       throws TasteException {
     RunningAverage average = new FullRunningAverage();
-    for (Map.Entry<User, Collection<Preference>> entry : testUserPrefs.entrySet()) {
+    for (Map.Entry<Comparable<?>, Collection<Preference>> entry : testUserPrefs.entrySet()) {
       for (Preference realPref : entry.getValue()) {
-        User testUser = entry.getKey();
+        Comparable<?> testUserID = entry.getKey();
         try {
-          double estimatedPreference =
-              recommender.estimatePreference(testUser.getID(), realPref.getItemID());
-          if (!Double.isNaN(estimatedPreference)) {
+          float estimatedPreference =
+              recommender.estimatePreference(testUserID, realPref.getItemID());
+          if (!Float.isNaN(estimatedPreference)) {
             average.addDatum(Math.abs(realPref.getValue() - estimatedPreference));
           }
         } catch (NoSuchUserException nsue) {
           // It's possible that an item exists in the test data but not training data in which case
           // NSEE will be thrown. Just ignore it and move on.
-          log.debug("User exists in test data but not training data: {}", testUser.getID(), nsue);
+          log.debug("User exists in test data but not training data: {}", testUserID, nsue);
         } catch (NoSuchItemException nsie) {
           log.debug("Item exists in test data but not training data: {}", realPref.getItemID(), nsie);
         }

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/GenericRecommenderIRStatsEvaluator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/GenericRecommenderIRStatsEvaluator.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/GenericRecommenderIRStatsEvaluator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/GenericRecommenderIRStatsEvaluator.java Tue Aug  4 00:06:46 2009
@@ -22,20 +22,17 @@
 import org.apache.mahout.cf.taste.eval.IRStatistics;
 import org.apache.mahout.cf.taste.eval.RecommenderBuilder;
 import org.apache.mahout.cf.taste.eval.RecommenderIRStatsEvaluator;
+import org.apache.mahout.cf.taste.impl.common.FastMap;
 import org.apache.mahout.cf.taste.impl.common.FastSet;
 import org.apache.mahout.cf.taste.impl.common.FullRunningAverage;
 import org.apache.mahout.cf.taste.impl.common.FullRunningAverageAndStdDev;
 import org.apache.mahout.cf.taste.impl.common.RandomUtils;
 import org.apache.mahout.cf.taste.impl.common.RunningAverage;
 import org.apache.mahout.cf.taste.impl.common.RunningAverageAndStdDev;
-import org.apache.mahout.cf.taste.impl.model.BooleanPrefUser;
-import org.apache.mahout.cf.taste.impl.model.ByValuePreferenceComparator;
 import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
-import org.apache.mahout.cf.taste.impl.model.GenericUser;
-import org.apache.mahout.cf.taste.impl.model.GenericBooleanUserDataModel;
 import org.apache.mahout.cf.taste.model.DataModel;
 import org.apache.mahout.cf.taste.model.Preference;
-import org.apache.mahout.cf.taste.model.User;
+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.apache.mahout.cf.taste.recommender.Rescorer;
@@ -43,17 +40,17 @@
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
 
 /**
- * <p>For each {@link User}, these implementation determine the top <code>n</code> preferences, then evaluate the IR
+ * <p>For each user, these implementation determine the top <code>n</code> preferences, then evaluate the IR
  * statistics based on a {@link DataModel} that does not have these values. This number <code>n</code> is the "at"
  * value, as in "precision at 5". For example, this would mean precision evaluated by removing the top 5 preferences for
- * a {@link User} and then finding the percentage of those 5 items included in the top 5 recommendations for
+ * a user and then finding the percentage of those 5 items included in the top 5 recommendations for
  * that user.</p>
  */
 public final class GenericRecommenderIRStatsEvaluator implements RecommenderIRStatsEvaluator {
@@ -100,49 +97,44 @@
     RunningAverage precision = new FullRunningAverage();
     RunningAverage recall = new FullRunningAverage();
     RunningAverage fallOut = new FullRunningAverage();
-    for (User user : dataModel.getUsers()) {
+    for (Comparable<?> userID : dataModel.getUserIDs()) {
       if (random.nextDouble() < evaluationPercentage) {
         long start = System.currentTimeMillis();
-        Comparable<?> id = user.getID();
         Collection<Comparable<?>> relevantItemIDs = new FastSet<Comparable<?>>(at);
-        Preference[] prefs = user.getPreferencesAsArray();
-        if (prefs.length < 2 * at) {
+        PreferenceArray prefs = dataModel.getPreferencesFromUser(userID);
+        int size = prefs.length();
+        if (size < 2 * at) {
           // Really not enough prefs to meaningfully evaluate this user
           continue;
         }
 
         // List some most-preferred items that would count as (most) "relevant" results
         double theRelevanceThreshold = Double.isNaN(relevanceThreshold) ? computeThreshold(prefs) : relevanceThreshold;
-        Arrays.sort(prefs, Collections.reverseOrder(ByValuePreferenceComparator.getInstance()));
-        for (int i = 0; i < prefs.length && relevantItemIDs.size() < at; i++) {
-          Preference pref = prefs[i];
-          if (pref.getValue() >= theRelevanceThreshold) {
-            relevantItemIDs.add(pref.getItemID());
+        prefs.sortByValueReversed();
+        for (int i = 0; i < size && relevantItemIDs.size() < at; i++) {
+          if (prefs.getValue(i) >= theRelevanceThreshold) {
+            relevantItemIDs.add(prefs.getItemID(i));
           }
         }
         int numRelevantItems = relevantItemIDs.size();
         if (numRelevantItems > 0) {
-          List<User> trainingUsers = new ArrayList<User>(dataModel.getNumUsers());
-          for (User user2 : dataModel.getUsers()) {
-            processOtherUser(id, relevantItemIDs, trainingUsers, user2);
+          Map<Comparable<?>, Collection<Preference>> trainingUsers =
+            new FastMap<Comparable<?>, Collection<Preference>>(dataModel.getNumUsers());
+          for (Comparable userID2 : dataModel.getUserIDs()) {
+            processOtherUser(userID, relevantItemIDs, trainingUsers, userID2, dataModel);
           }
 
-          DataModel trainingModel;
-          if (trainingUsers.get(0) instanceof BooleanPrefUser) {
-            trainingModel = new GenericBooleanUserDataModel(trainingUsers);
-          } else {
-            trainingModel = new GenericDataModel(trainingUsers);
-          }
+          DataModel trainingModel = new GenericDataModel(GenericDataModel.toPrefArrayValues(trainingUsers, true));
           Recommender recommender = recommenderBuilder.buildRecommender(trainingModel);
 
           try {
-            trainingModel.getUser(id);
+            trainingModel.getPreferencesFromUser(userID);
           } catch (NoSuchUserException nsee) {
             continue; // Oops we excluded all prefs for the user -- just move on
           }
 
           int intersectionSize = 0;
-          List<RecommendedItem> recommendedItems = recommender.recommend(id, at, rescorer);
+          List<RecommendedItem> recommendedItems = recommender.recommend(userID, at, rescorer);
           for (RecommendedItem recommendedItem : recommendedItems) {
             if (relevantItemIDs.contains(recommendedItem.getItemID())) {
               intersectionSize++;
@@ -153,13 +145,13 @@
             precision.addDatum((double) intersectionSize / (double) numRecommendedItems);
           }
           recall.addDatum((double) intersectionSize / (double) numRelevantItems);
-          if (numRelevantItems < prefs.length) {
+          if (numRelevantItems < size) {
             fallOut.addDatum((double) (numRecommendedItems - intersectionSize) /
                 (double) (numItems - numRelevantItems));
           }
 
           long end = System.currentTimeMillis();
-          log.info("Evaluated with user " + user + " in " + (end - start) + "ms");
+          log.info("Evaluated with user " + userID + " in " + (end - start) + "ms");
           log.info("Precision/recall/fall-out: {} / {} / {}", new Object[]{
               precision.getAverage(), recall.getAverage(), fallOut.getAverage()
           });
@@ -172,43 +164,34 @@
 
   private static void processOtherUser(Comparable<?> id,
                                        Collection<Comparable<?>> relevantItemIDs,
-                                       Collection<User> trainingUsers,
-                                       User user2) {
-    if (id.equals(user2.getID())) {
-      List<Preference> trainingPrefs = new ArrayList<Preference>();
-      Preference[] prefs2 = user2.getPreferencesAsArray();
-      for (Preference pref : prefs2) {
-        if (!relevantItemIDs.contains(pref.getItemID())) {
-          trainingPrefs.add(pref);
-        }
-      }
-      if (!trainingPrefs.isEmpty()) {
-        // TODO hack
-        User trainingUser;
-        if (user2 instanceof BooleanPrefUser) {
-          FastSet<Comparable<?>> itemIDs = new FastSet<Comparable<?>>();
-          for (Preference pref : trainingPrefs) {
-            itemIDs.add(pref.getItemID());
-          }
-          trainingUser = new BooleanPrefUser(id, itemIDs);
-        } else {
-          trainingUser = new GenericUser(id, trainingPrefs);
+                                       Map<Comparable<?>, Collection<Preference>> trainingUsers,
+                                       Comparable<?> userID2,
+                                       DataModel dataModel) throws TasteException {
+    PreferenceArray prefs2Array = dataModel.getPreferencesFromUser(userID2);
+    List<Preference> prefs2 = new ArrayList<Preference>(prefs2Array.length());
+    for (Preference pref : prefs2Array) {
+      prefs2.add(pref);
+    }
+    if (id.equals(userID2)) {
+      for (Iterator<Preference> iterator = prefs2.iterator(); iterator.hasNext();) {
+        Preference pref = iterator.next();
+        if (relevantItemIDs.contains(pref.getItemID())) {
+          iterator.remove();
         }
-        trainingUsers.add(trainingUser);
       }
-    } else {
-      trainingUsers.add(user2);
     }
+    trainingUsers.put(userID2, prefs2);
   }
 
-  private static double computeThreshold(Preference[] prefs) {
-    if (prefs.length < 2) {
+  private static double computeThreshold(PreferenceArray prefs) {
+    if (prefs.length() < 2) {
       // Not enough data points -- return a threshold that allows everything
       return Double.NEGATIVE_INFINITY;
     }
     RunningAverageAndStdDev stdDev = new FullRunningAverageAndStdDev();
-    for (Preference pref : prefs) {
-      stdDev.addDatum(pref.getValue());
+    int size = prefs.length();
+    for (int i = 0; i < size; i++) {
+      stdDev.addDatum(prefs.getValue(i));
     }
     return stdDev.getAverage() + stdDev.getStandardDeviation();
   }

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/LoadEvaluator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/LoadEvaluator.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/LoadEvaluator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/LoadEvaluator.java Tue Aug  4 00:06:46 2009
@@ -22,7 +22,6 @@
 import org.apache.mahout.cf.taste.impl.common.RunningAverageAndStdDev;
 import org.apache.mahout.cf.taste.impl.common.SamplingIterable;
 import org.apache.mahout.cf.taste.model.DataModel;
-import org.apache.mahout.cf.taste.model.User;
 import org.apache.mahout.cf.taste.recommender.Recommender;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -36,12 +35,13 @@
     DataModel dataModel = recommender.getDataModel();
     int numUsers = dataModel.getNumUsers();
     double sampleRate = 1000.0 / numUsers;
-    SamplingIterable<User> userSampler = new SamplingIterable<User>(dataModel.getUsers(), sampleRate);
+    SamplingIterable<Comparable<?>> userSampler =
+            new SamplingIterable<Comparable<?>>(dataModel.getUserIDs(), sampleRate);
     RunningAverageAndStdDev recommendationTime = new FullRunningAverageAndStdDev();
     int count = 0;
-    for (User user : userSampler) {
+    for (Comparable<?> userID : userSampler) {
       long start = System.currentTimeMillis();
-      recommender.recommend(user.getID(), 10);
+      recommender.recommend(userID, 10);
       long end = System.currentTimeMillis();
       if (count > 0) { // Ignore first as a warmup
         recommendationTime.addDatum(end - start);

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/RMSRecommenderEvaluator.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/RMSRecommenderEvaluator.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/RMSRecommenderEvaluator.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/eval/RMSRecommenderEvaluator.java Tue Aug  4 00:06:46 2009
@@ -22,7 +22,6 @@
 import org.apache.mahout.cf.taste.impl.common.FullRunningAverage;
 import org.apache.mahout.cf.taste.impl.common.RunningAverage;
 import org.apache.mahout.cf.taste.model.Preference;
-import org.apache.mahout.cf.taste.model.User;
 import org.apache.mahout.cf.taste.recommender.Recommender;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -40,24 +39,24 @@
   private static final Logger log = LoggerFactory.getLogger(RMSRecommenderEvaluator.class);
 
   @Override
-  double getEvaluation(Map<User, Collection<Preference>> testUserPrefs,
+  double getEvaluation(Map<Comparable<?>, Collection<Preference>> testUserPrefs,
                        Recommender recommender)
       throws TasteException {
     RunningAverage average = new FullRunningAverage();
-    for (Map.Entry<User, Collection<Preference>> entry : testUserPrefs.entrySet()) {
+    for (Map.Entry<Comparable<?>, Collection<Preference>> entry : testUserPrefs.entrySet()) {
       for (Preference realPref : entry.getValue()) {
-        User testUser = entry.getKey();
+        Comparable<?> testUserID = entry.getKey();
         try {
-          double estimatedPreference =
-              recommender.estimatePreference(testUser.getID(), realPref.getItemID());
-          if (!Double.isNaN(estimatedPreference)) {
+          float estimatedPreference =
+              recommender.estimatePreference(testUserID, realPref.getItemID());
+          if (!Float.isNaN(estimatedPreference)) {
             double diff = realPref.getValue() - estimatedPreference;
             average.addDatum(diff * diff);
           }
         } catch (NoSuchUserException nsee) {
           // It's possible that an item exists in the test data but not training data in which case
           // NSEE will be thrown. Just ignore it and move on.
-          log.info("Element exists in test data but not training data: {}", testUser.getID(), nsee);
+          log.info("Element exists in test data but not training data: {}", testUserID, nsee);
         }
       }
     }

Copied: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanItemPreferenceArray.java (from r797487, lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreferenceArray.java)
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanItemPreferenceArray.java?p2=lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanItemPreferenceArray.java&p1=lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreferenceArray.java&r1=797487&r2=800634&rev=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericPreferenceArray.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanItemPreferenceArray.java Tue Aug  4 00:06:46 2009
@@ -19,70 +19,177 @@
 
 import org.apache.mahout.cf.taste.model.Preference;
 import org.apache.mahout.cf.taste.model.PreferenceArray;
-import org.apache.mahout.cf.taste.model.User;
 
 import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
 
 /**
- * This implementation maintains three parallel arrays, of {@link User}s, items, and values. The idea is to save
- * allocating {@link Preference} objects themselves. On a 64-bit virtual machine, this should save 12 bytes per element
- * (the overhead of an enclosing {@link Preference} object reference and object header).
+ * <p>Like {@link BooleanUserPreferenceArray} but stores preferences for one item (all item IDs the same)
+ * rather than one user.</p>
  *
- * This is not used yet.
+ * @see BooleanPreference
+ * @see BooleanUserPreferenceArray
+ * @see GenericItemPreferenceArray
  */
-public final class GenericPreferenceArray implements PreferenceArray, Serializable {
+public final class BooleanItemPreferenceArray implements PreferenceArray, Serializable {
 
-  private final User[] users;
-  private final Comparable<?>[] itemIDs;
-  private final double[] values;
-
-  public GenericPreferenceArray(int size) {
-    users = new User[size];
-    itemIDs = new Comparable<?>[size];
-    values = new double[size];
+  private final Comparable<?>[] IDs;
+  private Comparable<?> id;
+
+  public BooleanItemPreferenceArray(int size) {
+    if (size < 1) {
+      throw new IllegalArgumentException("size is less than 1");
+    }
+    this.IDs = new Comparable<?>[size];
+  }
+
+  public int length() {
+    return IDs.length;
+  }
+
+  public BooleanItemPreferenceArray(List<Preference> prefs, boolean forOneUser) {
+    this(prefs.size());
+    for (int i = 0; i < prefs.size(); i++) {
+      Preference pref = prefs.get(i);
+      IDs[i] = forOneUser ? pref.getItemID() : pref.getUserID();
+    }
+    id = forOneUser ? prefs.get(0).getUserID() : prefs.get(0).getItemID();
   }
 
   @Override
   public Preference get(int i) {
-    return new GenericPreference(users[i], itemIDs[i], values[i]);
+    return new PreferenceView(i);
   }
 
   @Override
   public void set(int i, Preference pref) {
-    users[i] = pref.getUser();
-    itemIDs[i] = pref.getItemID();
-    values[i] = pref.getValue();
+    id = pref.getItemID();
+    IDs[i] = pref.getUserID();
   }
 
   @Override
-  public User getUser(int i) {
-    return users[i];
+  public Comparable<?> getUserID(int i) {
+    return IDs[i];
   }
 
   @Override
-  public void setUser(int i, User user) {
-    users[i] = user;
+  public void setUserID(int i, Comparable<?> userID) {
+    IDs[i] = userID;
   }
 
   @Override
   public Comparable<?> getItemID(int i) {
-    return itemIDs[i];
+    return id;
   }
 
   @Override
   public void setItemID(int i, Comparable<?> itemID) {
-    itemIDs[i] = itemID;
+    id = itemID;
+  }
+
+  @Override
+  public float getValue(int i) {
+    return 1.0f;
+  }
+
+  @Override
+  public void setValue(int i, float value) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void sortByUser() {
+    selectionSort();
+  }
+
+  @Override
+  public void sortByItem() {
   }
 
+  @Override
+  public void sortByValue() {
+  }
 
   @Override
-  public double getValue(int i) {
-    return values[i];
+  public void sortByValueReversed() {
+  }
+
+  private void selectionSort() {
+    // I think this sort will prove to be too dumb, but, it's in place and OK for tiny, mostly sorted data
+    int max = length();
+    for (int i = 0; i < max; i++) {
+      int min = i;
+      for (int j = i + 1; j < max; j++) {
+        if (((Comparable<Object>) IDs[i]).compareTo(IDs[j]) < 0) {
+          min = j;
+        }
+      }
+      if (i != min) {
+        Comparable<?> temp1 = IDs[i];
+        IDs[i] = IDs[min];
+        IDs[min] = temp1;
+      }
+    }
+  }
+
+  public GenericItemPreferenceArray clone() {
+    try {
+      return (GenericItemPreferenceArray) super.clone();
+    } catch (CloneNotSupportedException cnse) {
+      throw new AssertionError();
+    }
   }
 
   @Override
-  public void setValue(int i, double value) {
-    values[i] = value;
+  public Iterator<Preference> iterator() {
+    return new PreferenceArrayIterator();
+  }
+
+  private final class PreferenceArrayIterator implements Iterator<Preference> {
+    private int i = 0;
+    @Override
+    public boolean hasNext() {
+      return i < length();
+    }
+    @Override
+    public Preference next() {
+      return new PreferenceView(i++);
+    }
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  private final class PreferenceView implements Preference {
+
+    private final int i;
+
+    private PreferenceView(int i) {
+      this.i = i;
+    }
+
+    @Override
+    public Comparable<?> getUserID() {
+      return BooleanItemPreferenceArray.this.getUserID(i);
+    }
+
+    @Override
+    public Comparable<?> getItemID() {
+      return BooleanItemPreferenceArray.this.getItemID(i);
+    }
+
+    @Override
+    public float getValue() {
+      return 1.0f;
+    }
+
+    @Override
+    public void setValue(float value) {
+      throw new UnsupportedOperationException();
+    }
+
   }
 
-}
+}
\ No newline at end of file

Modified: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanPreference.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanPreference.java?rev=800634&r1=800633&r2=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanPreference.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanPreference.java Tue Aug  4 00:06:46 2009
@@ -17,7 +17,7 @@
 
 package org.apache.mahout.cf.taste.impl.model;
 
-import org.apache.mahout.cf.taste.model.User;
+import org.apache.mahout.cf.taste.model.Preference;
 
 import java.io.Serializable;
 
@@ -26,33 +26,22 @@
  * appropriate in situations where users conceptually have only a general "yes" preference for items, rather than a
  * spectrum of preference values.
  */
-public final class BooleanPreference implements SettableUserPreference, Serializable {
+public final class BooleanPreference implements Preference, Serializable {
 
-  private User user;
+  private final Comparable<?> userID;
   private final Comparable<?> itemID;
 
-  public BooleanPreference(User user, Comparable<?> itemID) {
-    if (itemID == null) {
+  public BooleanPreference(Comparable<?> userID, Comparable<?> itemID) {
+    if (userID == null || itemID == null) {
       throw new IllegalArgumentException("itemID is null");
     }
-    this.user = user;
+    this.userID = userID;
     this.itemID = itemID;
   }
 
   @Override
-  public User getUser() {
-    if (user == null) {
-      throw new IllegalStateException("User was never set");
-    }
-    return user;
-  }
-
-  @Override
-  public void setUser(User user) {
-    if (user == null) {
-      throw new IllegalArgumentException("user is null");
-    }
-    this.user = user;
+  public Comparable<?> getUserID() {
+    return userID;
   }
 
   @Override
@@ -61,18 +50,18 @@
   }
 
   @Override
-  public double getValue() {
-    return 1.0;
+  public float getValue() {
+    return 1.0f;
   }
 
   @Override
-  public void setValue(double value) {
+  public void setValue(float value) {
     throw new UnsupportedOperationException();
   }
 
   @Override
   public String toString() {
-    return "BooleanPreference[user: " + user + ", itemID:" + itemID + ']';
+    return "BooleanPreference[userID: " + userID + ", itemID:" + itemID + ']';
   }
 
 }
\ No newline at end of file

Added: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanUserPreferenceArray.java
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanUserPreferenceArray.java?rev=800634&view=auto
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanUserPreferenceArray.java (added)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/BooleanUserPreferenceArray.java Tue Aug  4 00:06:46 2009
@@ -0,0 +1,195 @@
+/**
+ * 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.model;
+
+import org.apache.mahout.cf.taste.model.Preference;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
+
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * <p>Like {@link GenericUserPreferenceArray} but stores, conceptually, {@link BooleanPreference} objects
+ * which have no associated preference value.</p>
+ * 
+ * @see BooleanPreference
+ * @see BooleanItemPreferenceArray
+ * @see GenericUserPreferenceArray
+ */
+public final class BooleanUserPreferenceArray implements PreferenceArray, Serializable {
+
+  private final Comparable<?>[] IDs;
+  private Comparable<?> id;
+
+  public BooleanUserPreferenceArray(int size) {
+    if (size < 1) {
+      throw new IllegalArgumentException("size is less than 1");
+    }
+    this.IDs = new Comparable<?>[size];
+  }
+
+  public int length() {
+    return IDs.length;
+  }
+
+  public BooleanUserPreferenceArray(List<Preference> prefs) {
+    this(prefs.size());
+    for (int i = 0; i < prefs.size(); i++) {
+      Preference pref = prefs.get(i);
+      IDs[i] = pref.getItemID();
+    }
+    id = prefs.get(0).getUserID();
+  }
+
+  @Override
+  public Preference get(int i) {
+    return new PreferenceView(i);
+  }
+
+  @Override
+  public void set(int i, Preference pref) {
+    id = pref.getUserID();
+    IDs[i] = pref.getItemID();
+  }
+
+  @Override
+  public Comparable<?> getUserID(int i) {
+    return id;
+  }
+
+  @Override
+  public void setUserID(int i, Comparable<?> userID) {
+    id = userID;
+  }
+
+  @Override
+  public Comparable<?> getItemID(int i) {
+    return IDs[i];
+  }
+
+  @Override
+  public void setItemID(int i, Comparable<?> itemID) {
+    IDs[i] = itemID;
+  }
+
+  @Override
+  public float getValue(int i) {
+    return 1.0f;
+  }
+
+  @Override
+  public void setValue(int i, float value) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public void sortByUser() {
+  }
+
+  @Override
+  public void sortByItem() {
+    selectionSort();
+  }
+
+  @Override
+  public void sortByValue() {
+  }
+
+  @Override
+  public void sortByValueReversed() {
+  }
+
+  private void selectionSort() {
+    // I think this sort will prove to be too dumb, but, it's in place and OK for tiny, mostly sorted data
+    int max = length();
+    for (int i = 0; i < max; i++) {
+      int min = i;
+      for (int j = i + 1; j < max; j++) {
+        if (((Comparable<Object>) IDs[i]).compareTo(IDs[j]) < 0) {
+          min = j;
+        }
+      }
+      if (i != min) {
+        Comparable<?> temp1 = IDs[i];
+        IDs[i] = IDs[min];
+        IDs[min] = temp1;
+      }
+    }
+  }
+
+  public GenericItemPreferenceArray clone() {
+    try {
+      return (GenericItemPreferenceArray) super.clone();
+    } catch (CloneNotSupportedException cnse) {
+      throw new AssertionError();
+    }
+  }
+
+  @Override
+  public Iterator<Preference> iterator() {
+    return new PreferenceArrayIterator();
+  }
+
+  private final class PreferenceArrayIterator implements Iterator<Preference> {
+    private int i = 0;
+    @Override
+    public boolean hasNext() {
+      return i < length();
+    }
+    @Override
+    public Preference next() {
+      return new PreferenceView(i++);
+    }
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+  private final class PreferenceView implements Preference {
+
+    private final int i;
+
+    private PreferenceView(int i) {
+      this.i = i;
+    }
+
+    @Override
+    public Comparable<?> getUserID() {
+      return BooleanUserPreferenceArray.this.getUserID(i);
+    }
+
+    @Override
+    public Comparable<?> getItemID() {
+      return BooleanUserPreferenceArray.this.getItemID(i);
+    }
+
+    @Override
+    public float getValue() {
+      return 1.0f;
+    }
+
+    @Override
+    public void setValue(float value) {
+      throw new UnsupportedOperationException();
+    }
+
+  }
+
+}
\ No newline at end of file

Copied: lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanPrefDataModel.java (from r797487, lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanUserDataModel.java)
URL: http://svn.apache.org/viewvc/lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanPrefDataModel.java?p2=lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanPrefDataModel.java&p1=lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanUserDataModel.java&r1=797487&r2=800634&rev=800634&view=diff
==============================================================================
--- lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanUserDataModel.java (original)
+++ lucene/mahout/trunk/core/src/main/java/org/apache/mahout/cf/taste/impl/model/GenericBooleanPrefDataModel.java Tue Aug  4 00:06:46 2009
@@ -24,112 +24,188 @@
 import org.apache.mahout.cf.taste.impl.common.FastMap;
 import org.apache.mahout.cf.taste.impl.common.FastSet;
 import org.apache.mahout.cf.taste.model.DataModel;
-import org.apache.mahout.cf.taste.model.Preference;
-import org.apache.mahout.cf.taste.model.User;
+import org.apache.mahout.cf.taste.model.PreferenceArray;
 
 import java.io.Serializable;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.Set;
+import java.util.Map;
 
 /**
- * TODO many methods here have not been implemented properly yet
+ * <p>A simple {@link DataModel} which uses a given {@link List} of users as its data source. This
+ * implementation is mostly useful for small experiments and is not recommended for contexts where performance is
+ * important.</p>
  */
-public final class GenericBooleanUserDataModel implements DataModel, Serializable {
+public final class GenericBooleanPrefDataModel implements DataModel, Serializable {
 
-  private final List<User> users;
-  private final FastMap<Comparable<?>, User> userMap;
-  private final Object[] itemIDs;
-
-  public GenericBooleanUserDataModel(Iterable<? extends User> users) {
-    if (users == null) {
-      throw new IllegalArgumentException("users is null");
-    }
-    this.users = new ArrayList<User>(1003);
-    this.userMap = new FastMap<Comparable<?>, User>(1003);
-    Set<Comparable<?>> itemIDs = new FastSet<Comparable<?>>(1003);
-    for (User user : users) {
-      if (!(user instanceof BooleanPrefUser)) {
-        throw new IllegalArgumentException("Must use a source of BooleanPrefUsers");
+  private final List<Comparable<?>> userIDs;
+  private final Map<Comparable<?>, FastSet<Comparable<?>>> preferenceFromUsers;
+  private final List<Comparable<?>> itemIDs;
+  private final Map<Comparable<?>, FastSet<Comparable<?>>> preferenceForItems;
+
+  /**
+   * <p>Creates a new {@link GenericDataModel} from the given users (and their preferences). This {@link
+   * DataModel} retains all this information in memory and is effectively immutable.</p>
+   *
+   * @param userData users to include
+   */
+  @SuppressWarnings("unchecked")
+  public GenericBooleanPrefDataModel(Map<Comparable<?>, FastSet<Comparable<?>>> userData) {
+    if (userData == null) {
+      throw new IllegalArgumentException("userData is null");
+    }
+
+    this.preferenceFromUsers = userData;
+    this.preferenceForItems = new FastMap<Comparable<?>, FastSet<Comparable<?>>>();
+    FastSet<Comparable<?>> itemIDSet = new FastSet<Comparable<?>>();
+    for (Map.Entry<Comparable<?>, FastSet<Comparable<?>>> entry : preferenceFromUsers.entrySet()) {
+      Comparable<?> userID = entry.getKey();
+      FastSet<Comparable<?>> itemIDs = entry.getValue();
+      itemIDSet.addAll(itemIDs);
+      for (Comparable<?> itemID : itemIDs) {
+        FastSet<Comparable<?>> userIDs = preferenceForItems.get(itemID);
+        if (userIDs == null) {
+          userIDs = new FastSet<Comparable<?>>(2);
+          preferenceForItems.put(itemID, userIDs);
+        }
+        userIDs.add(userID);
       }
-      this.users.add(user);
-      userMap.put(user.getID(), user);
-      itemIDs.addAll(((BooleanPrefUser) user).getItemIDs());
     }
-    userMap.rehash();
-    Collections.sort(this.users);
 
-    this.itemIDs = itemIDs.toArray();
-    itemIDs = null;
-    Arrays.sort(this.itemIDs);
+    this.itemIDs = new ArrayList<Comparable<?>>(itemIDSet);
+    itemIDSet = null;
+    Collections.sort((List<? extends Comparable>) this.itemIDs);
+
+    this.userIDs = new ArrayList(userData.keySet());
+    Collections.sort((List<? extends Comparable>) userIDs);
+
   }
 
-  public GenericBooleanUserDataModel(DataModel dataModel) throws TasteException {
-    this(dataModel.getUsers());
+  /**
+   * <p>Creates a new {@link GenericDataModel} containing an immutable copy of the data from another given {@link
+   * DataModel}.</p>
+   *
+   * @param dataModel {@link DataModel} to copy
+   * @throws TasteException if an error occurs while retrieving the other {@link DataModel}'s users
+   */
+  public GenericBooleanPrefDataModel(DataModel dataModel) throws TasteException {
+    this(toDataMap(dataModel));
+  }
+
+  private static Map<Comparable<?>, FastSet<Comparable<?>>> toDataMap(DataModel dataModel) throws TasteException {
+    Map<Comparable<?>, FastSet<Comparable<?>>> data = 
+            new FastMap<Comparable<?>, FastSet<Comparable<?>>>(dataModel.getNumUsers());
+    for (Comparable<?> userID : dataModel.getUserIDs()) {
+      data.put(userID, dataModel.getItemIDsFromUser(userID));
+    }
+    return data;
+  }
+
+  @Override
+  public Iterable<Comparable<?>> getUserIDs() {
+    return userIDs;
   }
 
+  /** @throws NoSuchUserException if there is no such user */
   @Override
-  public Iterable<? extends User> getUsers() {
-    return users;
+  public PreferenceArray getPreferencesFromUser(Comparable<?> userID) throws NoSuchUserException {
+    FastSet<Comparable<?>> itemIDs = preferenceFromUsers.get(userID);
+    if (itemIDs == null) {
+      throw new NoSuchUserException();
+    }
+    PreferenceArray prefArray = new BooleanUserPreferenceArray(itemIDs.size());
+    int i = 0;
+    for (Comparable<?> itemID : itemIDs) {
+      prefArray.setUserID(i, userID);
+      prefArray.setItemID(i, itemID);
+      i++;
+    }
+    return prefArray;
   }
 
   @Override
-  public User getUser(Comparable<?> id) throws NoSuchUserException {
-    User user = userMap.get(id);
-    if (user == null) {
+  public FastSet<Comparable<?>> getItemIDsFromUser(Comparable<?> userID) throws TasteException {
+    FastSet<Comparable<?>> itemIDs = preferenceFromUsers.get(userID);
+    if (itemIDs == null) {
       throw new NoSuchUserException();
     }
-    return user;
+    return itemIDs;
   }
 
   @Override
   public Iterable<Comparable<?>> getItemIDs() {
-    throw new UnsupportedOperationException();
+    return itemIDs;
   }
 
   @Override
-  public Iterable<? extends Preference> getPreferencesForItem(Comparable<?> itemID) {
-    throw new UnsupportedOperationException();
+  public PreferenceArray getPreferencesForItem(Comparable<?> itemID) throws NoSuchItemException {
+    FastSet<Comparable<?>> userIDs = preferenceForItems.get(itemID);
+    if (userIDs == null) {
+      throw new NoSuchItemException();
+    }
+    PreferenceArray prefArray = new BooleanItemPreferenceArray(userIDs.size());
+    int i = 0;
+    for (Comparable<?> userID : userIDs) {
+      prefArray.setUserID(i, userID);
+      prefArray.setItemID(i, itemID);
+      i++;
+    }
+    return prefArray;
   }
 
   @Override
-  public Preference[] getPreferencesForItemAsArray(Comparable<?> itemID) {
-    throw new UnsupportedOperationException();
+  public Float getPreferenceValue(Comparable<?> userID, Comparable<?> itemID) throws NoSuchUserException, NoSuchItemException {
+    FastSet<Comparable<?>> itemIDs = preferenceFromUsers.get(userID);
+    if (itemIDs == null) {
+      throw new NoSuchUserException();
+    }
+    if (itemIDs.contains(itemID)) {
+      return 1.0f;
+    }
+    return null;
   }
 
   @Override
   public int getNumItems() {
-    return itemIDs.length;
+    return itemIDs.size();
   }
 
   @Override
   public int getNumUsers() {
-    return users.size();
+    return userIDs.size();
   }
 
   @Override
-  public int getNumUsersWithPreferenceFor(Comparable<?>... itemIDs) {
-    if (itemIDs == null) {
-      throw new IllegalArgumentException("itemIDs is null");
+  public int getNumUsersWithPreferenceFor(Comparable<?>... itemIDs) throws NoSuchItemException {
+    if (itemIDs.length == 0) {
+      return 0;
     }
-    int length = itemIDs.length;
-    if (length == 0 || length > 2) {
-      throw new IllegalArgumentException("Illegal number of item IDs: " + length);
+    FastSet<Comparable<?>> intersection = new FastSet<Comparable<?>>();
+    FastSet<Comparable<?>> userIDs = preferenceForItems.get(itemIDs[0]);
+    if (userIDs == null) {
+      throw new NoSuchItemException();
     }
-    throw new UnsupportedOperationException();
+    intersection.addAll(userIDs);
+    int i = 1;
+    while (!intersection.isEmpty() && i < itemIDs.length) {
+      userIDs = preferenceForItems.get(itemIDs[i]);
+      if (userIDs == null) {
+        throw new NoSuchItemException();
+      }
+      intersection.retainAll(userIDs);
+    }
+    return intersection.size();
   }
 
   @Override
-  public void setPreference(Comparable<?> userID, Comparable<?> itemID, double value)
-      throws NoSuchUserException, NoSuchItemException {
+  public void removePreference(Comparable<?> userID, Comparable<?> itemID) throws NoSuchUserException {
     throw new UnsupportedOperationException();
   }
 
   @Override
-  public void removePreference(Comparable<?> userID, Comparable<?> itemID) throws NoSuchUserException {
+  public void setPreference(Comparable<?> userID, Comparable<?> itemID, float value) throws NoSuchUserException {
     throw new UnsupportedOperationException();
   }
 
@@ -140,7 +216,7 @@
 
   @Override
   public String toString() {
-    return "GenericBooleanUserDataModel[users:" + (users.size() > 3 ? users.subList(0, 3) + "..." : users) + ']';
+    return "GenericBooleanPrefDataModel[users:" + (userIDs.size() > 3 ? userIDs.subList(0, 3) + "..." : userIDs) + ']';
   }
 
-}
\ No newline at end of file
+}