internal PivotsExpression Simplify(Dictionary<string, Pivots.Pivot> pivotVsPivotValues) { if (invariant) return this; if (matching_combinations.Count == 0) return False; int possible_combinations = 1; foreach (string pivot in relevant_pivots) { possible_combinations *= pivotVsPivotValues[pivot].Choices.Keys.Count; } if (matching_combinations.Count == possible_combinations) return True; foreach (string pivot in relevant_pivots) { var values = pivotVsPivotValues[pivot].Choices.Keys; if (matching_combinations.Count % values.Count != 0) continue; int reduced_combinations = matching_combinations.Count / values.Count; ComparableHashSet<ComparableHashSet<string>> new_combinations = new ComparableHashSet<ComparableHashSet<string>>(); foreach (var combination in matching_combinations) { ComparableHashSet<string> reduced_combination = new ComparableHashSet<string>(combination); reduced_combination.ExceptWith(values); new_combinations.Add(reduced_combination); if (new_combinations.Count > reduced_combinations) break; } if (new_combinations.Count == reduced_combinations) { PivotsExpression result = new PivotsExpression(); result.relevant_pivots = new HashSet<string>(relevant_pivots); result.relevant_pivots.Remove(pivot); result.matching_combinations = new_combinations; return result.Simplify(pivotVsPivotValues); } } return this; }
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); } }
internal override PivotsExpression ToPivotsExpression(Dictionary<string, Pivots.Pivot> pivotVsPivotValues, GetChoiceDelegate get_choice_fn) { var result = new PivotsExpression(); result.relevant_pivots = new HashSet<string>(); result.relevant_pivots.Add(pivot_name); result.matching_combinations = new ComparableHashSet<ComparableHashSet<string>>(); if (inverted) { foreach (string pivotValue in pivotVsPivotValues[pivot_name].Choices.Keys) { if (pivotValue != pivot_choice) { ComparableHashSet<string> choice = new ComparableHashSet<string>(); choice.Add(pivotValue); result.matching_combinations.Add(choice); } } } else { ComparableHashSet<string> choice = new ComparableHashSet<string>(); choice.Add(pivot_choice); result.matching_combinations.Add(choice); } return result; }
internal ComparableHashSet<ComparableHashSet<string>> GetExpandedChoices(PivotsExpression expr, HashSet<string> pivots, Dictionary<string, Pivots.Pivot> pivotVsPivotValues) { ComparableHashSet<ComparableHashSet<string>> result = expr.matching_combinations; foreach (string pivot in pivots) { if (expr.relevant_pivots.Contains(pivot)) continue; ComparableHashSet<ComparableHashSet<string>> new_result = new ComparableHashSet<ComparableHashSet<string>>(); var pivot_choices = pivotVsPivotValues[pivot].Choices.Keys; foreach (var matching_combination in result) { foreach (string pivot_choice in pivot_choices) { ComparableHashSet<string> choices = new ComparableHashSet<string>(matching_combination); choices.Add(pivot_choice); new_result.Add(choices); } } result = new_result; } return result; }