code: private ImmutableMultimap<Integer, TermType> collectProposedCastTypes(
              Collection<CQIE> samePredicateRules, ImmutableMap<CQIE, ImmutableList<Optional<TermType>>> termTypeMap,
              Map<Predicate, ImmutableList<TermType>> alreadyKnownCastTypes) {
  
          ImmutableMultimap.Builder<Integer, TermType> indexedCastTypeBuilder = ImmutableMultimap.builder();
  
          int arity = samePredicateRules.iterator().next().getHead().getTerms().size();
  
          /*
           * For each rule...
           */
          samePredicateRules
                  .forEach(rule -> {
                      List<Term> headArguments = rule.getHead().getTerms();
                      ImmutableList<Optional<TermType>> termTypes = termTypeMap.get(rule);
  
                      IntStream.range(0, arity)
                              .forEach(i -> {
  
                                  TermType type = termTypes.get(i)
                                          /*
                                           * If not defined, extracts the cast type of the variable by looking at its defining
                                           * data atom (normally intensional)
                                           */
                                          .orElseGet(() -> getCastTypeFromSubRule(
                                                  immutabilityTools.convertIntoImmutableTerm(headArguments.get(i)),
                                                  extractDataAtoms(rule.getBody()).collect(ImmutableCollectors.toList()),
                                                  alreadyKnownCastTypes));
  
                                  indexedCastTypeBuilder.put(i, type);
                              });
                  });
  
          return indexedCastTypeBuilder.build();
  
      }
docs: Collects the proposed cast types by the definitions of the current predicate