Как сравнить ребра в графе для реализации триадического замыкания, как в сетевых графах, таких как facebook

#java #graph #undirected-graph

#java #График #неориентированный-граф

Вопрос:

Я пытаюсь реализовать граф, содержащий вершины (узлы), которые относятся к Profile классу (например, профиль Facebook, но более посредственный). Каждая из вершин (профилей) хранится в двоичном дереве поиска, которое затем загружается или сохраняется в виде списка-массива.
Точно так же, как в Facebook Profile , у некоторых (не у всех, поскольку не у всех есть друзья) экземпляров класса Profile будут друзья, которые являются ребрами.
Каждая связь ребер графа сохраняется в текстовом файле, который затем считывается и добавляется в график отдельным методом во время построения графика.

Как только это будет сделано, я пытаюсь реализовать рекомендуемый метод:
два профиля, которые не являются друзьями, но хотели бы дружить на основе отношений, возможно, являющихся триадическим замыканием, но до сих пор у меня ничего не получалось, и в настоящее время я застрял.

  • В настоящее время мне удалось создать график, используя a Matrix , но я застрял в попытке найти возможное решение, чтобы рекомендовать возможных друзей для каждой вершины, у которой есть друг j , у которого есть друг x , который не является другом вершины (текущий профиль).
  • Предполагается, что каждый из рекомендованных друзей сохраняется в массиве и добавляется в двоичное дерево поиска.

     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;
    }
      

    Я получаю ряд ошибок, которые я не могу объяснить: (

Комментарии:

1. Предполагается ли, что ваш алгоритм должен для конкретного данного пользователя находить всех возможных релевантных друзей — т.е.. друзья друзей пользователя, которые не отображаются в карте друзей пользователя?

2. Предполагается, что алгоритм берет вершину (user [x]), находит друзей пользователей [y], подтверждая, что у них есть отношение ребер в матрице, и проверяет, есть ли у друга пользователя [y] друг [z] (отношение ребер), который не дружит с текущим пользователем[x] и поместите его в arrayofRecommondations для этого пользователя [x] .

3. Спасибо за текущее решение, я буду работать над ним и посмотрю, может ли оно применяться. 🙂 — Ранн Лифшиц

Ответ №1:

Основываясь на данном алгоритме и предполагая Profile , что у класса будет вызываться дополнительный метод containsProfile(Profile p) , который проверяет, содержится ли данный профиль в списке друзей пользователя, должен работать следующий подход грубой силы:

 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;
  

}

Комментарии:

1. Я создал аналогичный метод в классе graph, а не в классе profile, чтобы получить имя профиля (строка), метку (вершину) профиля из массива профилей (каждый из этих профилей был добавлен из двоичного дерева поиска). Я попытаюсь реализовать ваше решение с помощью строки в качестве входных данных, а не объекта профиля, и посмотреть, работает ли это.

2. @BrevynKurt: Рад помочь. Обратите внимание на предположение в приведенной выше реализации — vertexProfileMap это карта всех существующих профилей.

3. О да, тогда я виноват. Однако у меня есть еще один вопрос о переменных endI и endJ, как именно они реализованы в условиях? они объявлены где-то еще или?

4. @BrevynKurt: endI и endJ — это соглашения об итерациях, которые я использую уже много лет. Небольшая оптимизация циклов for позволяет вычислять конечное условие цикла for только один раз во время цикла for, объявляясь вместе с итератором (i и j), и улучшает читаемость IMHO.

5. Верно, это имеет смысл. Поэтому моя реализация должна будет перевести ваш перевод циклов for в обычный стандарт. Заранее спасибо 🙂