@@ -21,20 +21,23 @@ License, or (at your option) any later version.
2121package common ;
2222
2323import java .util .ArrayList ;
24+ import java .util .LinkedHashMap ;
2425import java .util .List ;
2526import java .util .Map ;
2627
2728public class PredictionData {
2829
2930 private int userID ;
31+ private int resID ;
3032 private int k ;
3133 private List <String > realData ;
3234 private List <String > predictionData ;
3335
3436 private double numFoundRelevantDocs ;
3537
36- public PredictionData (int userID , List <String > realData , List <String > predictionData , int k ) {
38+ public PredictionData (int userID , int resID , List <String > realData , List <String > predictionData , int k ) {
3739 this .userID = userID ;
40+ this .resID = resID ;
3841 this .realData = realData ;
3942 this .k = k ;
4043 if (k == 0 ) {
@@ -102,6 +105,10 @@ public double getMAP() {
102105 return 0.0 ;
103106 }
104107
108+ public double getCoverage () {
109+ return (this .predictionData .size () > 0 ? 1.0 : 0.0 );
110+ }
111+
105112 private double getPrecisionK (int k ) {
106113 if (k != 0 && k <= this .predictionData .size ()) {
107114 List <String > foundRelevantDocs = new ArrayList <String >(this .realData );
@@ -126,15 +133,16 @@ private void determineRelevantDocs() {
126133 }
127134
128135 // Resource-rec metrics
129- private double getNovelty (int targetRes , List <Integer > resources , List <Map <Integer , Double >> resourceTopics ) {
136+ private double getNovelty (int targetRes , List <Integer > resources , List <Map <Integer , Double >> resourceTopics , boolean cosine ) {
130137 double novelty = 0.0 ;
131138
132139 int count = 0 ;
133140 Map <Integer , Double > targetTopics = resourceTopics .get (targetRes );
134141 for (int res : resources ) {
135142 if (targetRes != res ) {
136143 Map <Integer , Double > resTopics = resourceTopics .get (res );
137- double disSim = 1.0 - Utilities .getCosineFloatSim (targetTopics , resTopics );
144+ double sim = (cosine ? Utilities .getCosineFloatSim (targetTopics , resTopics ) : Utilities .getJaccardFloatSim (targetTopics , resTopics ));
145+ double disSim = 1.0 - sim ;
138146 novelty += disSim ;
139147 count ++;
140148 }
@@ -145,7 +153,7 @@ private double getNovelty(int targetRes, List<Integer> resources, List<Map<Integ
145153 return novelty / count ;
146154 }
147155
148- public double getDiversity (List <Map <Integer , Double >> resourceTopics ) {
156+ public double getDiversity (List <Map <Integer , Double >> resourceTopics , boolean cosine ) {
149157 double diversity = 0.0 ;
150158 if (this .predictionData == null || this .predictionData .size () == 0 ) {
151159 return diversity ;
@@ -156,7 +164,7 @@ public double getDiversity(List<Map<Integer, Double>> resourceTopics) {
156164 predictionIDs .add (Integer .valueOf (res ));
157165 }
158166 for (int resID : predictionIDs ) {
159- diversity += getNovelty (resID , predictionIDs , resourceTopics );
167+ diversity += getNovelty (resID , predictionIDs , resourceTopics , cosine );
160168 }
161169 return diversity / this .predictionData .size ();
162170 }
@@ -172,11 +180,72 @@ public double getSerendipity(List<Map<Integer, Double>> resourceTopics, List<Int
172180
173181 for (String res : this .predictionData ) {
174182 int resID = Integer .parseInt (res );
175- serendipity += getNovelty (resID , knownResources , resourceTopics );
183+ serendipity += getNovelty (resID , knownResources , resourceTopics , true );
176184 }
177185 return serendipity / this .predictionData .size ();
178186 }
179187
188+ public double getTagDiversity (List <Map <Integer , Double >> tagEntities ) {
189+ double diversity = 0.0 ;
190+ if (this .predictionData == null || this .predictionData .size () == 0 ) {
191+ return diversity ;
192+ }
193+
194+ List <Integer > predictionIDs = new ArrayList <Integer >();
195+ for (String res : this .predictionData ) {
196+ predictionIDs .add (Integer .valueOf (res ));
197+ }
198+ int k = predictionIDs .size ();
199+ for (int i = 0 ; i < k ; i ++) {
200+ Map <Integer , Double > targetEntities = tagEntities .get (i );
201+ for (int j = i + 1 ; j < k ; j ++) {
202+ Map <Integer , Double > sourceEntities = tagEntities .get (j );
203+ diversity += (1.0 - Utilities .getJaccardFloatSim (targetEntities , sourceEntities ));
204+ }
205+ }
206+ double normConstant = (k * k - k ) / 2.0 ;
207+ if (normConstant > 0.0 ) {
208+ diversity /= normConstant ;
209+ }
210+ return diversity ;
211+ }
212+
213+ public double getTagSerendipity (Map <Integer , Integer > tagFrequencyMap , boolean cosine ) {
214+ Double serendipity = 0.0 ;
215+ if (this .predictionData == null || this .predictionData .size () == 0 ) {
216+ return 0.0 ;
217+ }
218+ if (tagFrequencyMap == null || tagFrequencyMap .size () == 0 ) {
219+ return 1.0 ;
220+ }
221+ if (!cosine ) {
222+ double i = 1.0 ;
223+ double maxIFF = Double .MIN_VALUE ;
224+ for (String tag : this .predictionData ) {
225+ int tagID = Integer .parseInt (tag );
226+ Integer tagCount = tagFrequencyMap .get (tagID );
227+ double iff = Math .log (((double )tagFrequencyMap .size () + 1.0 ) / ((tagCount == null ? 0.0 : tagCount .doubleValue ()) + 1.0 ));
228+ double disc = 1.0 / Math .log (1.0 + i ++);
229+ serendipity += (disc * iff );
230+ if (iff > maxIFF ) {
231+ maxIFF = iff ;
232+ }
233+ }
234+ double normConstant = 0.0 ;
235+ for (double j = 1.0 ; j <= this .predictionData .size (); j ++) {
236+ normConstant += ((1.0 / Math .log (1.0 + j )) * maxIFF );
237+ }
238+ if (normConstant > 0.0 ) {
239+ serendipity /= normConstant ;
240+ }
241+ if (serendipity .isInfinite () || serendipity .isNaN ()) {
242+ serendipity = 1.0 ;
243+ }
244+ } else {
245+ serendipity = (1.0 - Utilities .getCosineSim (getPredictionDataAsMap (), tagFrequencyMap ));
246+ }
247+ return serendipity ;
248+ }
180249
181250 /**
182251 * Compute the normalized discounted cumulative gain (NDCG) of a list of ranked items.
@@ -235,11 +304,24 @@ public int getUserID() {
235304 return this .userID ;
236305 }
237306
307+ public int getResID () {
308+ return this .resID ;
309+ }
310+
238311 public List <String > getRealData () {
239312 return this .realData ;
240313 }
241314
242315 public List <String > getPredictionData () {
243316 return this .predictionData ;
244317 }
318+
319+ public Map <Integer , Integer > getPredictionDataAsMap () {
320+ Map <Integer , Integer > returnMap = new LinkedHashMap <Integer , Integer >();
321+ for (String data : this .predictionData ) {
322+ int intVal = Integer .parseInt (data );
323+ returnMap .put (intVal , 1 );
324+ }
325+ return returnMap ;
326+ }
245327}
0 commit comments