3

I am trying to implement a graph that contains Vertices(nodes) that relate to a Profile class(like a Facebook profile but more mediocre). Each of the vertices(Profiles) is stored in a Binary Search Tree which is then loaded or stored in an Array-List.
Just like in a Facebook Profile some (not all since not everyone has friends) instances of the class Profile will have friends which are the edges.
Each edge relationship of the graph is stored in a text file which is then read in and added to the graph by a separate method during the graph construction.

Once this is done I am trying to implement a recommended method:
Two profiles that are not friends but will like to be friends based on the relationship possibly being a triadic closure but I have failed terribly so far and I am currently stuck.

  • Currently, I was able to create a graph using a Matrix but I am stuck with trying to find a possible solution to recommend possible friends for each vertex that has a friend j who has a friend x who is not a friend of the vertex(current Profile).
  • Each one of the recommended friends is supposed to be stored into an array and added to a Binary Search Tree.

    private List<Profile> getRecommendedFriends(){
            Iterator profileIterator = this.vertexProfileMap.entrySet().iterator();
            List<Profile> recommendedProfiles = new ArrayList<>();
            Boolean isContained;
    
            while(profileIterator.hasNext()){
               Map.Entry mapElement = (Map.Entry)profileIterator.next();
               Profile user = (Profile) mapElement.getValue();
               int sizeOfList =  user.numOfFriends();
    
               for(int i = 0;  i < sizeOfList; i++){
                  recommendedProfiles.add(user.getFriend(i));
                  for(int x = 0; x < user.numOfFriends(); x++){
                     for(int j = 0; j < user.numOfFriends(); j++){
                        isContained = user.getFriend(x).getName().equals(user.getFriend(j).getName());
                        if(!isContained){
                           recommendedProfiles.add(user.getFriend(j));
                        }
                     }
                  }
               }
    
            }
            return recommendedProfiles;
    }
    

    I get a range of errors that I cannot explain:(

Rann Lifshitz
  • 3,862
  • 4
  • 18
  • 40
  • 1
    Is your algorithm supposed to, for a specific given user, find all the possibly relevant friends - ie. the friends of the user's friends which do not appear in the user's friends map? – Rann Lifshitz Apr 21 '19 at 08:41
  • The algorithm is supposed to take in a vertex(user[x]) find the users friends[y] by confirming they have an edge relationship in the matrix and see if the user's friend[y] has a friend[z](edge relationship) that is not friends with the current user[x] and put it into an arrayofRecommondations for that user[x]. – Brevyn Kurt Apr 21 '19 at 22:37
  • Thank you for the current solution I will work on it and see if it can apply. :) - Rann Lifshitz – Brevyn Kurt Apr 21 '19 at 22:39

1 Answers1

1

Based on the given algorithm, and assuming the Profile class will have an additional method called containsProfile(Profile p) which checks if a given profile is contained in the friend list of the user, The following brute force approach should work:

private Map<Profile,List<Profile>> getRecommendedFriends(){
    // under the asssumption that vertexProfileMap maps all Profiles/Users
    Iterator profileIterator = this.vertexProfileMap.entrySet().iterator();
    Map<Profile,List<Profile>> recommendedProfiles = new HashMap<>();
    while(profileIterator.hasNext()){
       Map.Entry mapElement = (Map.Entry)profileIterator.next();
       Profile currentUser = (Profile) mapElement.getValue();
       List<Profile> recommendedPerProfile = new ArrayList<>();
       // iterate over all of the friends of the current user
       for(int i = 0, endI = currentUser.numOfFriends(); i < endI; i++){
          Profile checkedFriend = currentUser.getFriend(i);
          // iterate over all of the friends of the currently checked friend
          for(int j = 0; endJ < checkedFriend.numOfFriends(); j < endJ; ++j) {
             Profile possibleRecommendation = checkedFriend.getFriend(j);
             // add a recommended profile if it belongs to a friend of a friend, but is not a friend of the current user
             if(!currentUser.containsProfile(possibleRecommendation)) {
                recommendedPerProfile.add(possibleRecommendation);
             }
          }
       }
       // remove possible duplicate recommendations
       recommendedProfiles = recommendedProfiles.stream()
       .distinct()
       .collect(Collectors.toList());
       // map the current user to a list of friend recommendations
       recommendedProfiles.put(currentUser, recommendedPerProfile);
    }
    return recommendedProfiles;

}

Rann Lifshitz
  • 3,862
  • 4
  • 18
  • 40
  • I made a similar method in the graph class rather than the profile class to get the profile's name(String) label(vertex) from an ArrayList of Profiles(Each of these profiles has been added from Binary Search Tree). I will try to implement your solution with a string as an input rather than a profile object and see if it works. – Brevyn Kurt Apr 21 '19 at 22:30
  • 1
    @BrevynKurt : Happy to help. Note the assumption in the implementation above - the `vertexProfileMap` is a map of all the existing profiles. – Rann Lifshitz Apr 21 '19 at 23:55
  • Oh yeah, my bad then. I have one more question though about the variables endI and endJ, how exactly are they implemented into the conditions? are they declared somewhere else or? – Brevyn Kurt Apr 22 '19 at 02:03
  • @BrevynKurt : endI and endJ are iteration conventions I've been using for years. A slight optimization of for loops, they allow the end condition of the for loop to be evaluated only once during the for loop by being declared alongside the iterator (i and j), and improve readability IMHO. – Rann Lifshitz Apr 22 '19 at 02:34
  • Right, that makes sense. So my implementation will have to translate your translation of for loops to the ordinary standard. Thanks in Advance :) – Brevyn Kurt Apr 22 '19 at 15:38
  • Hi, I tried implementing it but I kept on getting an error on the part where you try to remove any duplicated using the steam API. "Error: Cannot resolve method '.stream()" -Thanks in Advance :) – Brevyn Kurt Apr 22 '19 at 21:29
  • @BrevynKurt : Did you import the required classes for using `Stream` ? java.util.stream.* ? – Rann Lifshitz Apr 23 '19 at 07:15