package edu.brown.cs.student.term.hub; import edu.brown.cs.student.term.DatabaseQuerier; import edu.brown.cs.student.term.repl.commands.SetupCommand; import java.time.Instant; import java.util.*; public class HubSearch { LinkMapper mapper; Map> followerToLeaderMap = new HashMap<>(); public HubSearch(LinkMapper mapper){ this.mapper = mapper; } public Map runHubSearch(Instant start, Instant end){ followerToLeaderMap = mapper.makeFollowerLinks(start, end); int numHolders = followerToLeaderMap.size(); List holders = new ArrayList<>(followerToLeaderMap.keySet()); double[] weights = new double[numHolders]; double[] rank = new double[numHolders]; double[] rankPrime = new double[numHolders]; System.err.println(numHolders + "\t" + getDigits(numHolders)); Arrays.fill(rankPrime, 1.0 / numHolders); double thresh = Math.pow(.1, getDigits(numHolders)); while(!withinDistance(rank, rankPrime, thresh)){ rank = Arrays.copyOf(rankPrime, rankPrime.length); //calculating hub rank for ith holder for(int i = 0; i < numHolders; i++){ rankPrime[i] = 0; //iterating through all holders to calculate hub rank for(int j = 0; j < numHolders; j++){ double weightIJ = getWeight(holders.get(i), holders.get(j), numHolders); rankPrime[i] += (weightIJ * rank[j]); } } } //potentially should change this to be a map from holder id => double? Map hubRankMap = new HashMap<>(); for(int i = 0; i < rankPrime.length; i++){ hubRankMap.put(holders.get(i), rankPrime[i]); } return hubRankMap; } private double getWeight(Holder leader, Holder follower, int numHolders){ //dampening factor double damp = 0.15; /* In Hub Search we have the leader and follower if follower links to (follows) leader, then we want to add some weight from follower to leader, but should that weight be diluted by the number of people who followed leader or the number of people who follower followed --- probably the second option ;( */ Set peopleFollowed = followerToLeaderMap.get(follower); int numberFollowed = peopleFollowed.size(); if(peopleFollowed.contains(leader)){ //constructs the leader to follower links as we go for use later on leader.addFollower(new Holder(follower.getId(), follower.getName())); return ((damp / numHolders) + (1 - damp) * (1.0 / numberFollowed)); } else if(numberFollowed == 0){ return ((damp / numHolders) + (1 - damp) * (1.0 / numHolders)); } else { return (damp / numHolders); } } private boolean withinDistance(double[] r, double[] rPrime, double threshold){ double sum = 0.0; for(int i = 0; i < r.length; i++){ sum += Math.pow((r[i] - rPrime[i]), 2); } System.err.println(sum + "\t" + !(sum <= 0.0000001)); return sum <= 0.001*threshold; } private int getDigits(int numFollowers) { int count = 1; int temp = numFollowers; while(temp >= 10) { count++; temp /= 10; System.out.println(temp); } return count; } }