/** * Compute SALSA on graph initialized in initializeGraph() method. * * @param nIterations */ public void computeSALSA(int nIterations) { for (int iter = 0; iter < nIterations; iter++) { // Hubs: sum of authority-neighbors values divided by their degree for (SalsaVertex hub : hubs.values()) { double nbSum = 0.0; // Update the degree because not all authorities were selected int degree = 0; for (int authId : hub.neighbors) { SalsaVertex auth = authorities.get(authId); if (auth != null) { nbSum += auth.value / auth.degree; degree++; } } hub.value = nbSum; hub.degree = degree; } // Authorities: push from authority side. // First: set values to zero for (SalsaVertex auth : authorities.values()) { auth.value = 0; } // Then, push hubs values to their auths for (SalsaVertex hub : hubs.values()) { double myContribution = hub.value / hub.degree; for (int authId : hub.neighbors) { SalsaVertex auth = authorities.get(authId); if (auth != null) { auth.value += myContribution; } } } } }
public void initializeGraph(Collection<Integer> circleOfTrust) { hubs = new HashMap<Integer, SalsaVertex>(circleOfTrust.size(), 1.0f); long t = System.currentTimeMillis(); int totalNeighbors = 0; int cacheHits = 0; HashSet<Integer> querySet = new HashSet<Integer>(circleOfTrust.size()); for (int v : circleOfTrust) { hubs.put(v, new SalsaVertex(v)); if (cache.containsKey(v)) { SalsaVertex hub = hubs.get(v); hub.neighbors = cache.get(v); hub.degree = hub.neighbors.size(); cacheHits++; } else { querySet.add(v); } } /* Load neighbors of the circle of trust -- we probably would need some limitation here?? */ HashMap<Integer, ArrayList<Integer>> hubNeighbors = queryService.queryOutNeighbors(querySet); long queryTime = System.currentTimeMillis() - t; /* Initialize salsa */ t = System.currentTimeMillis(); for (Map.Entry<Integer, ArrayList<Integer>> entry : hubNeighbors.entrySet()) { int hubId = entry.getKey(); SalsaVertex hub = hubs.get(hubId); hub.neighbors = entry.getValue(); hub.degree = entry.getValue().size(); cache.put(hubId, entry.getValue()); } // Count total neighbors for (SalsaVertex hub : hubs.values()) { totalNeighbors += hub.neighbors.size(); } long salsaInitTime0 = System.currentTimeMillis() - t; // We do not add neighbors to authorities -- we can push values to authorities // and pull to hubs. int[] authEntries = new int[totalNeighbors]; int j = 0; for (SalsaVertex hub : hubs.values()) { for (int authId : hub.neighbors) { authEntries[j++] = authId; } } assert (j == authEntries.length); // Create map efficiently Arrays.sort(authEntries); int lastId = -1; int count = 0; // int filtered = 0; ArrayList<SalsaVertex> tmpAuth = new ArrayList<SalsaVertex>(1 + authEntries.length / 100); for (int i = 0; i < authEntries.length; i++) { int authId = authEntries[i]; if (lastId != authId) { if (lastId >= 0) { if (count > FILTER_LIMIT) { SalsaVertex auth = new SalsaVertex(lastId); auth.degree = count; tmpAuth.add(auth); } else { // filtered++; } count = 0; } lastId = authId; } count++; } authorities = new HashMap<Integer, SalsaVertex>(tmpAuth.size()); for (SalsaVertex auth : tmpAuth) { authorities.put(auth.id, auth); } // NOTE: remove neighbors! /* long salsaInitTime = System.currentTimeMillis() - t; logger.info("Query took: " + queryTime + " ms, circle of trust size=" + circleOfTrust.size() + ", cache size=" + cache.size() + ", hits=" + cacheHits); logger.info("Salsa init: " + salsaInitTime + " ms, first phase=" + salsaInitTime0 + " ms, hubs=" + hubs.size() + ", auths=" + authorities.size()); logger.info("Filtered: " + filtered); */ }