docs: public EqualityPartition generateEqualitiesPartitionedBy(Predicate<Symbol> symbolScope)
      {
          ImmutableSet.Builder<Expression> scopeEqualities = ImmutableSet.builder();
          ImmutableSet.Builder<Expression> scopeComplementEqualities = ImmutableSet.builder();
          ImmutableSet.Builder<Expression> scopeStraddlingEqualities = ImmutableSet.builder();
  
          for (Collection<Expression> equalitySet : equalitySets.asMap().values()) {
              Set<Expression> scopeExpressions = new LinkedHashSet<>();
              Set<Expression> scopeComplementExpressions = new LinkedHashSet<>();
              Set<Expression> scopeStraddlingExpressions = new LinkedHashSet<>();
  
              // Try to push each non-derived expression into one side of the scope
              for (Expression expression : filter(equalitySet, not(derivedExpressions::contains))) {
                  Expression scopeRewritten = rewriteExpression(expression, symbolScope, false);
                  if (scopeRewritten != null) {
                      scopeExpressions.add(scopeRewritten);
                  }
                  Expression scopeComplementRewritten = rewriteExpression(expression, not(symbolScope), false);
                  if (scopeComplementRewritten != null) {
                      scopeComplementExpressions.add(scopeComplementRewritten);
                  }
                  if (scopeRewritten == null && scopeComplementRewritten == null) {
                      scopeStraddlingExpressions.add(expression);
                  }
              }
              // Compile the equality expressions on each side of the scope
              Expression matchingCanonical = getCanonical(scopeExpressions);
              if (scopeExpressions.size() >= 2) {
                  for (Expression expression : filter(scopeExpressions, not(equalTo(matchingCanonical)))) {
                      scopeEqualities.add(new ComparisonExpression(ComparisonExpression.Operator.EQUAL, matchingCanonical, expression));
                  }
              }
              Expression complementCanonical = getCanonical(scopeComplementExpressions);
              if (scopeComplementExpressions.size() >= 2) {
                  for (Expression expression : filter(scopeComplementExpressions, not(equalTo(complementCanonical)))) {
                      scopeComplementEqualities.add(new ComparisonExpression(ComparisonExpression.Operator.EQUAL, complementCanonical, expression));
                  }
              }
  
              // Compile the scope straddling equality expressions
              List<Expression> connectingExpressions = new ArrayList<>();
              connectingExpressions.add(matchingCanonical);
              connectingExpressions.add(complementCanonical);
              connectingExpressions.addAll(scopeStraddlingExpressions);
              connectingExpressions = ImmutableList.copyOf(filter(connectingExpressions, Predicates.notNull()));
              Expression connectingCanonical = getCanonical(connectingExpressions);
              if (connectingCanonical != null) {
                  for (Expression expression : filter(connectingExpressions, not(equalTo(connectingCanonical)))) {
                      scopeStraddlingEqualities.add(new ComparisonExpression(ComparisonExpression.Operator.EQUAL, connectingCanonical, expression));
                  }
              }
          }
  
          return new EqualityPartition(scopeEqualities.build(), scopeComplementEqualities.build(), scopeStraddlingEqualities.build());
      }