internal override PivotsExpression ToPivotsExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn)
{
PivotsExpression left, right;
left = left_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn);
if (left.invariant) {
if (left.invariant_result)
return right_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn);
else
return left;
}
right = right_child.ToPivotsExpression(pivotVsPivotValues, get_choice_fn);
if (right.invariant) {
if (right.invariant_result)
return left;
else
return right;
}
HashSet<string> shared_pivots = new HashSet<string>(left.relevant_pivots);
shared_pivots.IntersectWith(right.relevant_pivots);
if (shared_pivots.Count == left.relevant_pivots.Count) {
// All pivots are shared, just intersect the sets.
PivotsExpression result = new PivotsExpression();
result.relevant_pivots = left.relevant_pivots;
result.matching_combinations = new ComparableHashSet<ComparableHashSet<string>>(left.matching_combinations);
result.matching_combinations.IntersectWith(right.matching_combinations);
return result.Simplify(pivotVsPivotValues);
}
if (shared_pivots.Count == 0) {
// No shared pivots, so do a cross product
PivotsExpression result = new PivotsExpression();
result.relevant_pivots = new HashSet<string>(left.relevant_pivots);
result.relevant_pivots.UnionWith(right.relevant_pivots);
result.matching_combinations = new ComparableHashSet<ComparableHashSet<string>>();
foreach (var left_combination in left.matching_combinations) {
foreach (var right_combination in right.matching_combinations) {
ComparableHashSet<string> new_combination = new ComparableHashSet<string>(left_combination);
new_combination.UnionWith(right_combination);
result.matching_combinations.Add(new_combination);
}
}
// It shouldn't be necessary to simplify in this case, as any independent pivots should have been removed already
return result;
}
HashSet<string> shared_pivot_values = new HashSet<string>();
foreach (string pivot in shared_pivots) {
shared_pivot_values.UnionWith(pivotVsPivotValues[pivot].Choices.Keys);
}
// Sort by relevant pivot count
if (left.relevant_pivots.Count > right.relevant_pivots.Count) {
var tmp = left;
left = right;
right = tmp;
}
if (right.relevant_pivots.IsSupersetOf(left.relevant_pivots)) {
// Filter the combintions in right by what's in left.
PivotsExpression result = new PivotsExpression();
result.relevant_pivots = right.relevant_pivots;
result.matching_combinations = new ComparableHashSet<ComparableHashSet<string>>();
foreach (var right_combination in right.matching_combinations) {
ComparableHashSet<string> reduced_combination = new ComparableHashSet<string>(right_combination);
reduced_combination.IntersectWith(shared_pivot_values);
if (left.matching_combinations.Contains(reduced_combination))
result.matching_combinations.Add(right_combination);
}
return result.Simplify(pivotVsPivotValues);
}
else {
Dictionary<ComparableHashSet<string>, List<ComparableHashSet<string>>> shared_values_to_left_values = new Dictionary<ComparableHashSet<string>, List<ComparableHashSet<string>>>();
foreach (var left_combination in left.matching_combinations) {
ComparableHashSet<string> shared_values = new ComparableHashSet<string>();
foreach (var value in left_combination) {
if (shared_pivot_values.Contains(value))
shared_values.Add(value);
}
List<ComparableHashSet<string>> combination_list;
if (!shared_values_to_left_values.TryGetValue(shared_values, out combination_list))
combination_list = shared_values_to_left_values[shared_values] = new List<ComparableHashSet<string>>();
combination_list.Add(left_combination);
}
PivotsExpression result = new PivotsExpression();
result.relevant_pivots = new HashSet<string>(left.relevant_pivots);
result.relevant_pivots.UnionWith(right.relevant_pivots);
result.matching_combinations = new ComparableHashSet<ComparableHashSet<string>>();
foreach (var right_combination in right.matching_combinations) {
ComparableHashSet<string> shared_values = new ComparableHashSet<string>();
foreach (var value in right_combination) {
if (shared_pivot_values.Contains(value))
shared_values.Add(value);
}
List<ComparableHashSet<string>> left_combinations;
if (shared_values_to_left_values.TryGetValue(shared_values, out left_combinations)) {
foreach (var left_combination in left_combinations) {
ComparableHashSet<string> new_combination = new ComparableHashSet<string>(right_combination);
new_combination.UnionWith(left_combination);
result.matching_combinations.Add(new_combination);
}
}
}
return result.Simplify(pivotVsPivotValues);
}
}