public static void inferenceOfUserAndProductStates(List<Edge<UserStates, ProductStates>> edges) {
    int iterationsNumber = 100;
    for (int i = 0; i < iterationsNumber; i++) {
      // Scheduling schema, which described in article:
      // 1) User -> Product
      // 2) User <- Product

      // User -> Product
      for (Edge<UserStates, ProductStates> edge : edges) {
        edge.updateMessagesNode1ToNode2();
      }
      for (Edge<UserStates, ProductStates> edge : edges) {
        edge.refreshMessagesNode1ToNode2();
      }

      // User <- Product
      for (Edge<UserStates, ProductStates> edge : edges) {
        edge.updateMessagesNode2ToNode1();
      }
      for (Edge<UserStates, ProductStates> edge : edges) {
        edge.refreshMessagesNode2ToNode1();
      }

      // Alternative scheduling schema:
      // Simultaneous passing of messages:
      // User -> Product
      // User <- Product
      //
      // for (Edge edge : edges) {
      // edge.updateMessagesNode1ToNode2();
      // edge.updateMessagesNode2ToNode1();
      // }
      // for (Edge edge : edges) {
      // edge.refreshMessagesNode1ToNode2();
      // edge.refreshMessagesNode2ToNode1();
      // }
    }
  }
  public static List<Edge<UserStates, ProductStates>> initializeVotes(
      Map<Integer, User> userIdToUser, Map<Integer, Product> productIdToProduct) {

    Potential<UserStates, ProductStates> positiveVotePotential =
        new UserProductPositiveVotePotential();
    Potential<UserStates, ProductStates> negativeVotePotential =
        new UserProductNegativeVotePotential();

    List<Edge<UserStates, ProductStates>> edges = new ArrayList<>();

    edges.add(Edge.connect(userIdToUser.get(1), productIdToProduct.get(1), positiveVotePotential));
    edges.add(Edge.connect(userIdToUser.get(1), productIdToProduct.get(3), negativeVotePotential));

    edges.add(Edge.connect(userIdToUser.get(2), productIdToProduct.get(1), positiveVotePotential));
    edges.add(Edge.connect(userIdToUser.get(2), productIdToProduct.get(2), positiveVotePotential));
    edges.add(Edge.connect(userIdToUser.get(2), productIdToProduct.get(4), negativeVotePotential));

    edges.add(Edge.connect(userIdToUser.get(3), productIdToProduct.get(1), positiveVotePotential));
    edges.add(Edge.connect(userIdToUser.get(3), productIdToProduct.get(2), positiveVotePotential));
    edges.add(Edge.connect(userIdToUser.get(3), productIdToProduct.get(3), negativeVotePotential));

    edges.add(Edge.connect(userIdToUser.get(4), productIdToProduct.get(2), positiveVotePotential));

    edges.add(Edge.connect(userIdToUser.get(5), productIdToProduct.get(1), negativeVotePotential));
    edges.add(Edge.connect(userIdToUser.get(5), productIdToProduct.get(3), positiveVotePotential));

    edges.add(Edge.connect(userIdToUser.get(6), productIdToProduct.get(2), positiveVotePotential));
    edges.add(Edge.connect(userIdToUser.get(6), productIdToProduct.get(3), positiveVotePotential));
    edges.add(Edge.connect(userIdToUser.get(6), productIdToProduct.get(4), positiveVotePotential));

    return edges;
  }