package happy.research.cf;
import happy.coding.io.Logs;
import happy.coding.math.Sims;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Cognitive Trust Model for Recommender Systems Usage: only run under cross validation method
*
* @author guoguibing
*/
public class CogTrust_mt extends DefaultTrust_mt
{
public CogTrust_mt() throws Exception
{
methodId = "CogTrust";
}
protected Map<String, Map<String, Double>> train()
{
Map<String, Map<String, Double>> userTrustMap = new HashMap<>();
Map<String, Double> userIntentions = calcUserIntentions();
double bias = params.COGTRUST_BIAS;
double alpha = params.COGTRUST_ALPHA;
int count = 0;
for (String trustor : testUserRatingsMap.keySet())
{
count++;
if (count % 100 == 0) Logs.debug("Training progresss: {}/{}", count, testUserRatingsMap.size());
Map<String, Rating> asRatings = userRatingsMap.get(trustor);
if (asRatings == null) continue;
for (String trustee : userRatingsMap.keySet())
{
if (trustee.equals(trustor)) continue;
double trust = bias;
Map<String, Rating> bsRatings = userRatingsMap.get(trustee);
if (asRatings == null || asRatings.size() < 1 || bsRatings == null || bsRatings.size() < 1) trust += 0;
else
{
List<Double> as = new ArrayList<>();
List<Double> bs = new ArrayList<>();
for (Entry<String, Rating> en : asRatings.entrySet())
{
String item = en.getKey();
if (bsRatings.containsKey(item))
{
as.add(en.getValue().getRating());
bs.add(bsRatings.get(item).getRating());
}
}
int size = as.size();
if (size < 1) trust += 0.0;
else
{
double similarity = Sims.pcc(as, bs);
if (Double.isNaN(similarity)) similarity = 0.0;
double significance = 1.0;
// double significance = 1 - 1.0 / size;
double capability = similarity * significance;
double intention = 0.0;
if (userIntentions.containsKey(trustee)) intention = userIntentions.get(trustee);
/**
* Three methods can be used to predict trust value: (1) trust = capability * intention + bias ;
* (2) trust = alpha * capability + (1-alpha) * intention + bias; (3) trust =
* hamonicMean(capability, intention) + bias.
*/
trust = alpha * capability + (1 - alpha) * intention + bias;
if (trust > 1) trust = 1.0;
if (trust < -1) trust = -1.0;
}
}
if (trust > params.TRUST_THRESHOLD)
{
Map<String, Double> trusteeMap = null;
if (userTrustMap.containsKey(trustor)) trusteeMap = userTrustMap.get(trustor);
else trusteeMap = new HashMap<>();
trusteeMap.put(trustee, trust);
userTrustMap.put(trustor, trusteeMap);
}
}
}
return userTrustMap;
}
private Map<String, Double> calcUserIntentions()
{
Map<String, Double> userIntensMap = new HashMap<>();
Set<String> as = userRatingsMap.keySet();
Set<String> bs = new HashSet<>(as);
Set<String> correctItems = new HashSet<>();
double epsilon = params.COGTRUST_EPSILON;
for (String a : as)
{
Map<String, Rating> asRatings = userRatingsMap.get(a);
if (asRatings == null) continue;
int size = asRatings.size();
for (String b : bs)
{
if (a.equals(b)) continue;
Map<String, Rating> bsRatings = userRatingsMap.get(b);
if (bsRatings == null) continue;
for (Rating br : bsRatings.values())
{
String item = br.getItemId();
double rating = br.getRating();
if (correctItems.contains(item)) continue;
if (asRatings.containsKey(item))
{
double diff = Math.abs(rating - asRatings.get(item).getRating());
if (diff < epsilon) correctItems.add(item);
}
}
}
double intention = correctItems.size() / (size + 0.0);
userIntensMap.put(a, intention);
}
return userIntensMap;
}
}