Java Code Examples for com.google.common.collect.Sets#cartesianProduct()

The following examples show how to use com.google.common.collect.Sets#cartesianProduct() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ImplicitOutputsFunction.java    From bazel with Apache License 2.0 6 votes vote down vote up
ImmutableList<String> substituteAttributes(
    AttributeMap attributeMap, AttributeValueGetter attributeGetter) {
  if (attributeNames().isEmpty()) {
    return ImmutableList.of(template());
  }

  List<Set<String>> values = Lists.newArrayListWithCapacity(attributeNames().size());
  for (String placeholder : attributeNames()) {
    Set<String> attrValues = attributeGetter.get(attributeMap, placeholder);
    if (attrValues.isEmpty()) {
      return ImmutableList.<String>of();
    }
    values.add(attrValues);
  }
  ImmutableList.Builder<String> out = new ImmutableList.Builder<>();
  for (List<String> combination : Sets.cartesianProduct(values)) {
    out.add(String.format(formatStr(), combination.toArray()));
  }
  return out.build();
}
 
Example 2
Source File: CassandraSession.java    From presto with Apache License 2.0 6 votes vote down vote up
private Iterable<Row> queryPartitionKeysLegacyWithMultipleQueries(CassandraTable table, List<Set<Object>> filterPrefixes)
{
    CassandraTableHandle tableHandle = table.getTableHandle();
    List<CassandraColumnHandle> partitionKeyColumns = table.getPartitionKeyColumns();

    Set<List<Object>> filterCombinations = Sets.cartesianProduct(filterPrefixes);

    ImmutableList.Builder<Row> rowList = ImmutableList.builder();
    for (List<Object> combination : filterCombinations) {
        Select partitionKeys = selectDistinctFrom(tableHandle, partitionKeyColumns);
        addWhereClause(partitionKeys.where(), partitionKeyColumns, combination);

        List<Row> resultRows = execute(partitionKeys).all();
        if (resultRows != null && !resultRows.isEmpty()) {
            rowList.addAll(resultRows);
        }
    }

    return rowList.build();
}
 
Example 3
Source File: CacheBuilderFactory.java    From caffeine with Apache License 2.0 6 votes vote down vote up
/**
 * Sets.cartesianProduct doesn't allow sets that contain null, but we want null to mean
 * "don't call the associated CacheBuilder method" - that is, get the default CacheBuilder
 * behavior. This method wraps the elements in the input sets (which may contain null) as
 * Optionals, calls Sets.cartesianProduct with those, then transforms the result to unwrap
 * the Optionals.
 */
private Iterable<List<Object>> buildCartesianProduct(Set<?>... sets) {
  List<Set<Optional<?>>> optionalSets = Lists.newArrayListWithExpectedSize(sets.length);
  for (Set<?> set : sets) {
    Set<Optional<?>> optionalSet =
        Sets.newLinkedHashSet(Iterables.transform(set, NULLABLE_TO_OPTIONAL));
    optionalSets.add(optionalSet);
  }
  Set<List<Optional<?>>> cartesianProduct = Sets.cartesianProduct(optionalSets);
  return Iterables.transform(cartesianProduct,
      new Function<List<Optional<?>>, List<Object>>() {
        @Override public List<Object> apply(List<Optional<?>> objs) {
          return Lists.transform(objs, OPTIONAL_TO_NULLABLE);
        }
      });
}
 
Example 4
Source File: GraqlTraversalIT.java    From grakn with GNU Affero General Public License v3.0 6 votes vote down vote up
private static Stream<GraqlTraversal> allGraqlTraversals(Pattern pattern) {
    Collection<Conjunction<Statement>> patterns = pattern.getDisjunctiveNormalForm().getPatterns();

    ConceptManager conceptManager = ((TestTransactionProvider.TestTransaction)tx).conceptManager();
    List<Set<List<Fragment>>> collect = patterns.stream()
            .map(conjunction -> new ConjunctionQuery(conjunction, conceptManager, new PropertyExecutorFactoryImpl()))
            .map(ConjunctionQuery::allFragmentOrders)
            .collect(toList());

    Set<List<List<? extends Fragment>>> lists = Sets.cartesianProduct(collect);

    return lists.stream()
            .map(Sets::newHashSet)
            .map(GraqlTraversalIT::createTraversal)
            .flatMap(Streams::optionalToStream);
}
 
Example 5
Source File: InlineParser.java    From sharding-jdbc-1.5.1 with Apache License 2.0 6 votes vote down vote up
@SuppressWarnings("unchecked")
private Set<List<String>> getCartesianValues(final GString segment) {
    List<Set<String>> result = new ArrayList<>(segment.getValues().length);
    for (Object each : segment.getValues()) {
        if (null == each) {
            continue;
        }
        if (each instanceof Collection) {
            result.add(Sets.newHashSet(Collections2.transform((Collection<Object>) each, new Function<Object, String>() {
                
                @Override
                public String apply(final Object input) {
                    return input.toString();
                }
            })));
        } else {
            result.add(Sets.newHashSet(each.toString()));
        }
    }
    return Sets.cartesianProduct(result);
}
 
Example 6
Source File: CartesianProduct.java    From levelup-java-examples with Apache License 2.0 6 votes vote down vote up
@SuppressWarnings("unchecked")
@Test
public void cartesian_product_guava () {
	
	Set<String> first = Sets.newHashSet("a", "b");
	Set<String> second = Sets.newHashSet("c", "d");
	
	Set<List<String>> cartesianProduct = Sets.cartesianProduct(first, second);
	
	logger.info(cartesianProduct);
	
	List<String> b_c = Lists.newArrayList("b", "c");
	List<String> b_d = Lists.newArrayList("b", "d");
	List<String> a_c = Lists.newArrayList("a", "c");
	List<String> a_d = Lists.newArrayList("a", "d");
	
	assertThat(cartesianProduct, 
			anyOf(containsInAnyOrder(b_c, b_d, a_c, a_d)));
}
 
Example 7
Source File: TestExpressionCompiler.java    From presto with Apache License 2.0 5 votes vote down vote up
private static List<String> formatExpression(String expressionPattern, List<Object> values, List<String> types)
{
    Preconditions.checkArgument(values.size() == types.size());

    List<Set<String>> unrolledValues = new ArrayList<>();
    for (int i = 0; i < values.size(); i++) {
        Object value = values.get(i);
        String type = types.get(i);
        if (value != null) {
            if (type.equals("varchar")) {
                value = "'" + value + "'";
            }
            else if (type.equals("bigint")) {
                value = "CAST( " + value + " AS BIGINT)";
            }
            else if (type.equals("double")) {
                value = "CAST( " + value + " AS DOUBLE)";
            }
            unrolledValues.add(ImmutableSet.of(String.valueOf(value)));
        }
        else {
            // todo enable when null output type is supported
            // unrolledValues.add(ImmutableSet.of("null", "cast(null as " + type + ")"));
            unrolledValues.add(ImmutableSet.of("cast(null as " + type + ")"));
        }
    }

    ImmutableList.Builder<String> expressions = ImmutableList.builder();
    Set<List<String>> valueLists = Sets.cartesianProduct(unrolledValues);
    for (List<String> valueList : valueLists) {
        expressions.add(format(expressionPattern, valueList.toArray(new Object[valueList.size()])));
    }
    return expressions.build();
}
 
Example 8
Source File: MetricsSummaryDataTypeHandler.java    From datawave with Apache License 2.0 5 votes vote down vote up
public Multimap<BulkIngestKey,Value> createEntries(RawRecordContainer record, Multimap<String,NormalizedContentInterface> fields,
                ColumnVisibility origVis, long timestamp, IngestHelperInterface iHelper) {
    String hour = getHour(fields);
    if (hour == null) {
        return HashMultimap.create();
    }
    
    Set<Text> rowIds = Sets.newHashSet(metricsSummaryFormatter.format(rowIdFields, fields, hour));
    Set<Text> colFs = Sets.newHashSet(metricsSummaryFormatter.format(colFamFields, fields, null));
    Set<Text> colQs = Sets.newHashSet(metricsSummaryFormatter.getSummaryValuesRegex(colQualFieldsRegexList, fields));
    
    if (log.isTraceEnabled()) {
        log.trace("Creating Keys for...rowIds.size() [" + rowIds.size() + "] colFs.size() [" + colFs.size() + "] colQs.size() [" + colQs.size() + "]");
    }
    
    ColumnVisibility vis = new ColumnVisibility(origVis.flatten());
    
    @SuppressWarnings("unchecked")
    Set<List<Text>> cartesianProduct = Sets.cartesianProduct(rowIds, colFs, colQs);
    
    Multimap<BulkIngestKey,Value> values = ArrayListMultimap.create(cartesianProduct.size(), EXPECTED_VALUES_PER_KEY);
    
    for (List<Text> textComponents : cartesianProduct) {
        Text row = textComponents.get(0);
        Text cf = textComponents.get(1);
        Text cq = textComponents.get(2);
        Preconditions.checkArgument(textComponents.size() == 3);
        Key k = new Key(row, cf, cq, vis, timestamp);
        final BulkIngestKey bk = new BulkIngestKey(metricsSummaryTableName, k);
        values.put(bk, INCREMENT_ONE_VALUE);
    }
    
    if (log.isTraceEnabled()) {
        log.trace("Created [" + values.size() + "] keys for ingest");
    }
    
    return values;
}
 
Example 9
Source File: MultipleKeysModuloTableShardingAlgorithm.java    From javabase with Apache License 2.0 5 votes vote down vote up
@Override
    public Collection<String> doSharding(final Collection<String> availableTargetNames, final Collection<ShardingValue<?>> shardingValues) {
        System.out.println("ModuloTableShardingAlgorithm shardingValue.getValue():" + shardingValues);
        Set<Integer> orderIdValueSet = getShardingValue(shardingValues, "order_id");
        Set<Integer> userIdValueSet = getShardingValue(shardingValues, "user_id");

        List<String> result = new ArrayList<>();
        /*
        userIdValueSet[10,11] + orderIdValueSet[101,102] => valueResult[[10,101],[10,102],[11,101],[11,102]]
         */
        Set<List<Integer>> valueResult = Sets.cartesianProduct(userIdValueSet, orderIdValueSet);
        for (List<Integer> value : valueResult) {
            //多个分片
//            t_order_00                      user_id以a偶数   order_id为偶数
//            ├── t_order_01               user_id以a偶数   order_id为奇数
//            ├── t_order_10               user_id以b奇数   order_id为偶数
//            └── t_order_11               user_id以b奇数   order_id为奇数
            String suffix = Joiner.on("").join(value.get(0) % 2, value.get(1) % 2);
            for (String tableName : availableTargetNames) {
                if (tableName.endsWith(suffix)) {
                    result.add(tableName);
                    System.out.println("MultipleKeysModuloTableShardingAlgorithm :tableName:"+tableName);
                }
            }
        }
        return result;
    }
 
Example 10
Source File: InlineExpressionParser.java    From shardingsphere with Apache License 2.0 5 votes vote down vote up
@SuppressWarnings("unchecked")
private Set<List<String>> getCartesianValues(final GString segment) {
    List<Set<String>> result = new ArrayList<>(segment.getValues().length);
    for (Object each : segment.getValues()) {
        if (null == each) {
            continue;
        }
        if (each instanceof Collection) {
            result.add(Sets.newLinkedHashSet(Collections2.transform((Collection<Object>) each, Object::toString)));
        } else {
            result.add(Sets.newHashSet(each.toString()));
        }
    }
    return Sets.cartesianProduct(result);
}
 
Example 11
Source File: IndexScanUnboundedMixedOrderDT.java    From sql-layer with GNU Affero General Public License v3.0 5 votes vote down vote up
public static Collection<List<OrderByOptions>> orderByPermutations() {
    List<Set<OrderByOptions>> optSets = new ArrayList<>();
    for(int i = 0; i < TOTAL_COLS; ++i) {
        optSets.add(EnumSet.allOf(OrderByOptions.class));
    }
    return Sets.cartesianProduct(optSets);
}
 
Example 12
Source File: QuarkCube.java    From quark with Apache License 2.0 5 votes vote down vote up
public static <E, T extends Set<E>> Set<Set<E>> cartesian(List<Set<T>> list) {
  final Set<List<T>> cartesianSet = Sets.cartesianProduct(list);
  return Sets.newHashSet(Iterables.transform(cartesianSet,
      new Function<List<T>, Set<E>>() {
        public Set<E> apply(List<T> l) {
          return Sets.newHashSet(Iterables.concat(l));
        }
      }
  ));
}
 
Example 13
Source File: SingleInputNode.java    From stratosphere with Apache License 2.0 4 votes vote down vote up
protected void instantiateCandidate(OperatorDescriptorSingle dps, Channel in, List<Set<? extends NamedChannel>> broadcastPlanChannels,
		List<PlanNode> target, CostEstimator estimator, RequestedGlobalProperties globPropsReq, RequestedLocalProperties locPropsReq)
{
	final PlanNode inputSource = in.getSource();
	
	for (List<NamedChannel> broadcastChannelsCombination: Sets.cartesianProduct(broadcastPlanChannels)) {
		
		boolean validCombination = true;
		
		// check whether the broadcast inputs use the same plan candidate at the branching point
		for (int i = 0; i < broadcastChannelsCombination.size(); i++) {
			NamedChannel nc = broadcastChannelsCombination.get(i);
			PlanNode bcSource = nc.getSource();
			
			// check branch compatibility against input
			if (!areBranchCompatible(bcSource, inputSource)) {
				validCombination = false;
				break;
			}
			
			// check branch compatibility against all other broadcast variables
			for (int k = 0; k < i; k++) {
				PlanNode otherBcSource = broadcastChannelsCombination.get(k).getSource();
				
				if (!areBranchCompatible(bcSource, otherBcSource)) {
					validCombination = false;
					break;
				}
			}
		}
		
		if (!validCombination) {
			continue;
		}
		
		final SingleInputPlanNode node = dps.instantiate(in, this);
		node.setBroadcastInputs(broadcastChannelsCombination);
		
		// compute how the strategy affects the properties
		GlobalProperties gProps = in.getGlobalProperties().clone();
		LocalProperties lProps = in.getLocalProperties().clone();
		gProps = dps.computeGlobalProperties(gProps);
		lProps = dps.computeLocalProperties(lProps);
		
		// filter by the user code field copies
		gProps = gProps.filterByNodesConstantSet(this, 0);
		lProps = lProps.filterByNodesConstantSet(this, 0);
		
		// apply
		node.initProperties(gProps, lProps);
		node.updatePropertiesWithUniqueSets(getUniqueFields());
		target.add(node);
	}
}
 
Example 14
Source File: CacheGenerator.java    From caffeine with Apache License 2.0 4 votes vote down vote up
/** Returns the Cartesian set of the possible cache configurations. */
@SuppressWarnings("unchecked")
private Set<List<Object>> combinations() {
  Set<Boolean> asyncLoading = ImmutableSet.of(true, false);
  Set<Stats> statistics = filterTypes(options.stats(), cacheSpec.stats());
  Set<ReferenceType> keys = filterTypes(options.keys(), cacheSpec.keys());
  Set<ReferenceType> values = filterTypes(options.values(), cacheSpec.values());
  Set<Compute> computations = filterTypes(options.compute(), cacheSpec.compute());
  Set<Implementation> implementations = filterTypes(
      options.implementation(), cacheSpec.implementation());

  if (isAsyncOnly) {
    values = values.contains(ReferenceType.STRONG)
        ? ImmutableSet.of(ReferenceType.STRONG)
        : ImmutableSet.of();
    computations = Sets.filter(computations, Compute.ASYNC::equals);
  }
  if (isAsyncOnly || computations.equals(ImmutableSet.of(Compute.ASYNC))) {
    implementations = implementations.contains(Implementation.Caffeine)
        ? ImmutableSet.of(Implementation.Caffeine)
        : ImmutableSet.of();
  }
  if (computations.equals(ImmutableSet.of(Compute.SYNC))) {
    asyncLoading = ImmutableSet.of(false);
  }

  if (computations.isEmpty() || implementations.isEmpty() || keys.isEmpty() || values.isEmpty()) {
    return ImmutableSet.of();
  }
  return Sets.cartesianProduct(
      ImmutableSet.copyOf(cacheSpec.initialCapacity()),
      ImmutableSet.copyOf(statistics),
      ImmutableSet.copyOf(cacheSpec.weigher()),
      ImmutableSet.copyOf(cacheSpec.maximumSize()),
      ImmutableSet.copyOf(cacheSpec.expiry()),
      ImmutableSet.copyOf(cacheSpec.expireAfterAccess()),
      ImmutableSet.copyOf(cacheSpec.expireAfterWrite()),
      ImmutableSet.copyOf(cacheSpec.refreshAfterWrite()),
      ImmutableSet.copyOf(cacheSpec.advanceOnPopulation()),
      ImmutableSet.copyOf(keys),
      ImmutableSet.copyOf(values),
      ImmutableSet.copyOf(cacheSpec.executor()),
      ImmutableSet.copyOf(cacheSpec.scheduler()),
      ImmutableSet.copyOf(cacheSpec.removalListener()),
      ImmutableSet.copyOf(cacheSpec.population()),
      ImmutableSet.of(true, isLoadingOnly),
      ImmutableSet.copyOf(asyncLoading),
      ImmutableSet.copyOf(computations),
      ImmutableSet.copyOf(cacheSpec.loader()),
      ImmutableSet.copyOf(cacheSpec.writer()),
      ImmutableSet.copyOf(implementations));
}
 
Example 15
Source File: LocalCacheFactoryGenerator.java    From caffeine with Apache License 2.0 4 votes vote down vote up
private Set<List<Object>> combinations() {
  Set<Boolean> options = ImmutableSet.of(true, false);
  List<Set<Boolean>> sets = Collections.nCopies(featureByIndex.length, options);
  return Sets.cartesianProduct(sets);
}
 
Example 16
Source File: XtaProcessSymbol.java    From theta with Apache License 2.0 4 votes vote down vote up
public Set<List<Expr<?>>> getArgumentLists(final Env env) {
	final List<Set<Expr<?>>> argumentValues = parameters.stream().map(p -> p.instantiateValues(env))
			.collect(toList());
	final Set<List<Expr<?>>> argumentLists = Sets.cartesianProduct(argumentValues);
	return argumentLists;
}
 
Example 17
Source File: TwoInputNode.java    From stratosphere with Apache License 2.0 4 votes vote down vote up
protected void instantiate(OperatorDescriptorDual operator, Channel in1, Channel in2,
		List<Set<? extends NamedChannel>> broadcastPlanChannels, List<PlanNode> target, CostEstimator estimator,
		RequestedGlobalProperties globPropsReq1, RequestedGlobalProperties globPropsReq2,
		RequestedLocalProperties locPropsReq1, RequestedLocalProperties locPropsReq2)
{
	final PlanNode inputSource1 = in1.getSource();
	final PlanNode inputSource2 = in2.getSource();
	
	for (List<NamedChannel> broadcastChannelsCombination: Sets.cartesianProduct(broadcastPlanChannels)) {
		
		boolean validCombination = true;
		
		// check whether the broadcast inputs use the same plan candidate at the branching point
		for (int i = 0; i < broadcastChannelsCombination.size(); i++) {
			NamedChannel nc = broadcastChannelsCombination.get(i);
			PlanNode bcSource = nc.getSource();
			
			if (!(areBranchCompatible(bcSource, inputSource1) || areBranchCompatible(bcSource, inputSource2))) {
				validCombination = false;
				break;
			}
			
			// check branch compatibility against all other broadcast variables
			for (int k = 0; k < i; k++) {
				PlanNode otherBcSource = broadcastChannelsCombination.get(k).getSource();
				
				if (!areBranchCompatible(bcSource, otherBcSource)) {
					validCombination = false;
					break;
				}
			}
		}
		
		if (!validCombination) {
			continue;
		}
		
		placePipelineBreakersIfNecessary(operator.getStrategy(), in1, in2);
		
		DualInputPlanNode node = operator.instantiate(in1, in2, this);
		node.setBroadcastInputs(broadcastChannelsCombination);
		
		GlobalProperties gp1 = in1.getGlobalProperties().clone().filterByNodesConstantSet(this, 0);
		GlobalProperties gp2 = in2.getGlobalProperties().clone().filterByNodesConstantSet(this, 1);
		GlobalProperties combined = operator.computeGlobalProperties(gp1, gp2);

		LocalProperties lp1 = in1.getLocalProperties().clone().filterByNodesConstantSet(this, 0);
		LocalProperties lp2 = in2.getLocalProperties().clone().filterByNodesConstantSet(this, 1);
		LocalProperties locals = operator.computeLocalProperties(lp1, lp2);
		
		node.initProperties(combined, locals);
		node.updatePropertiesWithUniqueSets(getUniqueFields());
		target.add(node);
	}
}
 
Example 18
Source File: AttributeBasedStratiAmountSelectorAndAssigner.java    From AILibs with GNU Affero General Public License v3.0 4 votes vote down vote up
@Override
public void init(final IDataset<?> dataset, final int stratiAmount) {

	this.logger.debug("init(): enter");

	/* first, conduct some consistency checks */
	if (this.initialized) {
		this.logger.warn("Ignoring further initialization.");
		return;
	}
	if (dataset == null) {
		throw new IllegalArgumentException("Cannot set dataset to NULL");
	}
	this.dataset = dataset;
	this.numAttributes = dataset.getNumAttributes();

	/* consistency check of attribute indices */
	int n = dataset.getNumAttributes();
	for (int i : this.attributeIndices) {
		if (i < 0) {
			throw new IllegalArgumentException("Attribute index for stratified splits must not be negative!");
		}
		if (i > n) {
			throw new IllegalArgumentException("Attribute index for stratified splits must not exceed number of attributes!");
		}
		if (i == n && !(dataset instanceof ILabeledDataset)) {
			throw new IllegalArgumentException("Attribute index for stratified splits must only equal the number of attributes if the dataset is labeled, because then the label column id is the number of attributes!");
		}
	}

	/* now compute the set of strati labels. There is one stratum for each element in the cartesian product of
	 * all possible combinations of (maybe discretized) values for the given attribute indices */
	Map<Integer, Set<Object>> attributeValues = DatasetPropertyComputer.computeAttributeValues(dataset, this.attributeIndices, this.numCPUs);
	this.discretizeAttributeValues(attributeValues);
	List<Set<Object>> sets = new ArrayList<>(attributeValues.values());
	Set<List<Object>> cartesianProduct = Sets.cartesianProduct(sets);
	this.logger.info("There are {} elements in the cartesian product of the attribute values", cartesianProduct.size());

	/* now assign an ID to each stratum. We do not use a list here for more effective look-up later */
	this.logger.info("Assigning stratum numbers to elements in the cartesian product..");
	this.stratumIDs = new HashMap<>();
	int stratumCounter = 0;
	for (List<Object> tuple : cartesianProduct) {
		this.stratumIDs.put(tuple, stratumCounter++);
	}

	this.logger.info("Initialized strati assigner with {} strati.", this.stratumIDs.size());
	this.initialized = true;
}
 
Example 19
Source File: Stacks.java    From elepy with Apache License 2.0 4 votes vote down vote up
public static Set<List<String>> importantStacks() {
    return Sets.cartesianProduct(dataAccessMap.keySet(), routingMap.keySet());
}
 
Example 20
Source File: ExtractCommonPredicatesExpressionRewriter.java    From presto with Apache License 2.0 4 votes vote down vote up
/**
 * Applies the boolean distributive property.
 * <p>
 * For example:
 * ( A & B ) | ( C & D ) => ( A | C ) & ( A | D ) & ( B | C ) & ( B | D)
 * <p>
 * Returns the original expression if the expression is non-deterministic or if the distribution will
 * expand the expression by too much.
 */
private Expression distributeIfPossible(LogicalBinaryExpression expression)
{
    if (!isDeterministic(expression, metadata)) {
        // Do not distribute boolean expressions if there are any non-deterministic elements
        // TODO: This can be optimized further if non-deterministic elements are not repeated
        return expression;
    }
    List<Set<Expression>> subPredicates = getSubPredicates(expression).stream()
            .map(ImmutableSet::copyOf)
            .collect(toList());

    int originalBaseExpressions = subPredicates.stream()
            .mapToInt(Set::size)
            .sum();

    int newBaseExpressions;
    try {
        newBaseExpressions = Math.multiplyExact(subPredicates.stream()
                .mapToInt(Set::size)
                .reduce(Math::multiplyExact)
                .getAsInt(), subPredicates.size());
    }
    catch (ArithmeticException e) {
        // Integer overflow from multiplication means there are too many expressions
        return expression;
    }

    if (newBaseExpressions > originalBaseExpressions * 2) {
        // Do not distribute boolean expressions if it would create 2x more base expressions
        // (e.g. A, B, C, D from the above example). This is just an arbitrary heuristic to
        // avoid cross product expression explosion.
        return expression;
    }

    Set<List<Expression>> crossProduct = Sets.cartesianProduct(subPredicates);

    return combinePredicates(
            metadata,
            expression.getOperator().flip(),
            crossProduct.stream()
                    .map(expressions -> combinePredicates(metadata, expression.getOperator(), expressions))
                    .collect(toImmutableList()));
}