docs: public static Set<Fragment> inferRelationTypes(TransactionOLTP tx, Set<Fragment> allFragments) {
  
          Set<Fragment> inferredFragments = new HashSet<>();
  
          Map<Variable, Type> labelVarTypeMap = getLabelVarTypeMap(tx, allFragments);
          if (labelVarTypeMap.isEmpty()) return inferredFragments;
  
          Multimap<Variable, Type> instanceVarTypeMap = getInstanceVarTypeMap(allFragments, labelVarTypeMap);
  
          Multimap<Variable, Variable> relationRolePlayerMap = getRelationRolePlayerMap(allFragments, instanceVarTypeMap);
          if (relationRolePlayerMap.isEmpty()) return inferredFragments;
  
          // for each type, get all possible relation type it could be in
          Multimap<Type, RelationType> relationMap = HashMultimap.create();
          labelVarTypeMap.values().stream().distinct().forEach(
                  type -> addAllPossibleRelations(relationMap, type));
  
          // inferred labels should be kept separately, even if they are already in allFragments set
          Map<Label, Statement> inferredLabels = new HashMap<>();
          relationRolePlayerMap.asMap().forEach((relationVar, rolePlayerVars) -> {
  
              Set<Type> possibleRelationTypes = rolePlayerVars.stream()
                      .filter(instanceVarTypeMap::containsKey)
                      .map(rolePlayer -> getAllPossibleRelationTypes(
                              instanceVarTypeMap.get(rolePlayer), relationMap))
                      .reduce(Sets::intersection).orElse(Collections.emptySet());
  
              //TODO: if possibleRelationTypes here is empty, the query will not match any data
              if (possibleRelationTypes.size() == 1) {
  
                  Type relationType = possibleRelationTypes.iterator().next();
                  Label label = relationType.label();
  
                  // add label fragment if this label has not been inferred
                  if (!inferredLabels.containsKey(label)) {
                      Statement labelVar = var();
                      inferredLabels.put(label, labelVar);
                      Fragment labelFragment = Fragments.label(new TypeProperty(label.getValue()), labelVar.var(), ImmutableSet.of(label));
                      inferredFragments.add(labelFragment);
                  }
  
                  // finally, add inferred isa fragments
                  Statement labelVar = inferredLabels.get(label);
                  IsaProperty isaProperty = new IsaProperty(labelVar);
                  EquivalentFragmentSet isaEquivalentFragmentSet = EquivalentFragmentSets.isa(isaProperty,
                          relationVar, labelVar.var(), relationType.isImplicit());
                  inferredFragments.addAll(isaEquivalentFragmentSet.fragments());
              }
          });
  
          return inferredFragments;
      }