001 /** 002 * CollaborativeRetrievalMethod.java 003 * jCOLIBRI2 framework. 004 * @author Juan A. Recio-García. 005 * GAIA - Group for Artificial Intelligence Applications 006 * http://gaia.fdi.ucm.es 007 * 11/11/2007 008 */ 009 package jcolibri.extensions.recommendation.collaborative; 010 011 import java.util.ArrayList; 012 import java.util.Collection; 013 import java.util.Iterator; 014 015 import jcolibri.cbrcore.CBRCase; 016 import jcolibri.cbrcore.CBRQuery; 017 import jcolibri.extensions.recommendation.collaborative.MatrixCaseBase.RatingTuple; 018 import jcolibri.extensions.recommendation.collaborative.MatrixCaseBase.SimilarTuple; 019 import jcolibri.method.retrieve.RetrievalResult; 020 021 /** 022 * This method returns cases depending on the recommendations of other users. 023 * <br> 024 * It uses a PearsonMatrix Case base to compute the similarity among neighbors. 025 * Then, cases are scored according to a rating that is estimated using the following 026 * formula:<br> 027 * <img src="collaborativerating.jpg"/> 028 * <p> 029 * See:<p> 030 * J. Kelleher and D. Bridge. An accurate and scalable collaborative recommender. 031 * Articial Intelligence Review, 21(3-4):193-213, 2004. 032 * 033 * 034 * @author Juan A. Recio-Garcia 035 * @author Developed at University College Cork (Ireland) in collaboration with Derek Bridge. 036 * @version 1.0 037 * @see jcolibri.test.recommenders.rec12.MoviesRecommender 038 */ 039 public class CollaborativeRetrievalMethod 040 { 041 @SuppressWarnings("unchecked") 042 /** 043 * Returns a list of cases scored following the collaborative recommendation formulae. 044 * @param cb is the case base that contains the cases 045 * @param id of the user 046 * @param kItems is the number of items/ratings to return 047 * @param kUsers defines the number of users taken into account to score the cases. 048 */ 049 public static Collection<RetrievalResult> getRecommendation(PearsonMatrixCaseBase cb, CBRQuery query, int kUsers) 050 { 051 ArrayList<RetrievalResult> result = new ArrayList<RetrievalResult>(); 052 053 int id = (Integer)query.getID(); 054 Collection<SimilarTuple> simil = cb.getSimilar(id); 055 056 if(simil == null) 057 { 058 org.apache.commons.logging.LogFactory.getLog(CollaborativeRetrievalMethod.class).error("Id "+id+" does not exists"); 059 return result; 060 } 061 062 063 ArrayList<SimilarTuple> select = new ArrayList<SimilarTuple>(); 064 int i=0; 065 for(Iterator<SimilarTuple> iter = simil.iterator(); (iter.hasNext() && i<kUsers);i++) 066 select.add(iter.next()); 067 068 069 /////// debug 070 System.out.println("\nQuery: "+ cb.getDescription(id)); 071 System.out.println(cb.getRatingTuples(id).size()+" Ratings: "+cb.getRatingTuples(id)); 072 System.out.println("\nSimilar ratings:"); 073 for(SimilarTuple st: select) 074 { 075 System.out.print(st.getSimilarity()+" <--- "); 076 System.out.println(cb.getDescription(st.getSimilarId())); 077 System.out.println(cb.getRatingTuples(st.getSimilarId()).size()+" Ratings: "+cb.getRatingTuples(st.getSimilarId())); 078 } 079 ///////////// 080 081 for(Integer solId : cb.getSolutions()) 082 { 083 double mean = cb.getAverage(id); 084 double acum = 0; 085 double simacum = 0; 086 for(SimilarTuple st : select) 087 { 088 int other = st.getSimilarId(); 089 double rating = findRating(cb, other, solId); 090 double otherMean = cb.getAverage(other); 091 acum += ((rating - otherMean) * st.getSimilarity()); 092 simacum += st.getSimilarity(); 093 } 094 double res = mean + (acum/simacum); 095 096 CBRCase c = new CBRCase(); 097 c.setDescription(cb.getDescription(id)); 098 c.setSolution(cb.getSolution(solId)); 099 100 result.add(new RetrievalResult(c,res)); 101 } 102 103 java.util.Collections.sort(result); 104 105 return result; 106 } 107 108 private static double findRating(PearsonMatrixCaseBase cb, int descId, int solId) 109 { 110 for(RatingTuple rt: cb.getRatingTuples(descId)) 111 { 112 if(rt.getSolutionId() == solId) 113 return rt.getRating(); 114 } 115 return 0; 116 } 117 }