/// <summary> /// Set top level and non top level concept types after /// the optimal permutation state has been determined /// </summary> /// <param name="permutationState"><see cref="ChainPermutationState"/> containing the top level and non top level ObjectTypes</param> public void SetConceptTypes(ChainPermutationState permutationState) { Debug.Assert(myConceptTypes == null); int count = permutationState.TopLevelCount + permutationState.NonTopLevelCount; ConceptTypeEntry[] entries = new ConceptTypeEntry[count]; if (count != 0) { int index = 0; foreach (KeyValuePair <ObjectType, ObjectTypeStates> pair in permutationState.EnumerateStates(ObjectTypeStates.TopLevelInPermutation | ObjectTypeStates.NonTopLevelInPermutation)) { entries[index] = new ConceptTypeEntry(pair.Key, 0 != (pair.Value & ObjectTypeStates.TopLevelInPermutation)); ++index; } Debug.Assert(index == count); if (count > 1) { Array.Sort <ConceptTypeEntry>(entries, ConceptTypeEntry.Comparer); } } myConceptTypes = entries; }
private static void FindSmallestPermutationsInTermsOfConceptTypes(Chain chain, ChainPermutationState permutationState) { permutationState.BeginChainEvaluation(chain); IList<Permutation> smallestPermutationsInTermsOfConceptTypes = chain.SmallestPermutationsInTermsOfConceptTypes; int minTopLevelConceptTypesCount = int.MaxValue; int minNonTopLevelConceptTypesCount = int.MaxValue; foreach (Permutation permutation in chain.PossiblePermutations) { bool isNotOptimalPermutation = false; permutationState.BeginPermutation(permutation); foreach (ObjectType objectType in chain.ObjectTypes) { ObjectTypeStates startingState = permutationState.GetState(objectType); if (0 != (startingState & (ObjectTypeStates.PredecidedMustHaveConceptType | ObjectTypeStates.PermutationMustHaveConceptType))) { if (0 != (startingState & (ObjectTypeStates.PredecidedMustNotHaveTopLevelConceptType | ObjectTypeStates.PermutationMustNotHaveTopLevelConceptType))) { if (permutationState.SetNonTopLevel(objectType) && (permutationState.TopLevelCount == minTopLevelConceptTypesCount) && (permutationState.NonTopLevelCount > minNonTopLevelConceptTypesCount)) { // We now have more non-top-level concept types than the minimum, and the same number of top-level concept types as the minimum, so throw this permutation out. isNotOptimalPermutation = true; break; } } else { if (permutationState.SetTopLevel(objectType) && (permutationState.TopLevelCount > minTopLevelConceptTypesCount)) { // We now have more top-level concept types than the minimum, so throw this permutation out. isNotOptimalPermutation = true; break; } } } } if (isNotOptimalPermutation) { // This isn't an optimal permutation, so go on to the next one. continue; } int topLevelCount = permutationState.TopLevelCount; int nonTopLevelCount = permutationState.NonTopLevelCount; Debug.Assert(topLevelCount <= minTopLevelConceptTypesCount, "Permutations with greater than the minimum number of top-level concept types should have been rejected inline."); if (topLevelCount < minTopLevelConceptTypesCount) { // We have a new minimum number of top-level concept types (and hence a new minimum number of non-top-level concept types as well). minTopLevelConceptTypesCount = topLevelCount; minNonTopLevelConceptTypesCount = nonTopLevelCount; smallestPermutationsInTermsOfConceptTypes.Clear(); } else { // We have the same number of top-level concept types as the minimum, so we need to check the number of non-top-level concept types. if (nonTopLevelCount > minNonTopLevelConceptTypesCount) { // This isn't an optimal permutation, so go on to the next one. continue; } else if (nonTopLevelCount < minNonTopLevelConceptTypesCount) { // We have a new minimum number of non-top-level concept type. minNonTopLevelConceptTypesCount = nonTopLevelCount; smallestPermutationsInTermsOfConceptTypes.Clear(); } } permutation.SetConceptTypes(permutationState); smallestPermutationsInTermsOfConceptTypes.Add(permutation); } }
private void PermuteFactTypeMappings() { // UNDONE: We should consider whether we can determine what object types will collapse earlier in the process, which would allow us to // potentially eliminate multiple permutations that have the same result. (Rationale: When an object type is collapsed, it doesn't matter // whether the mappings away from it are shallow or deep; they both result in the same output.) int largestChainCount; FactTypeMappingDictionary allDecidedMappings = myDecidedFactTypeMappings; // Break up the chains of contiguous one-to-one fact types FactTypeChainer chainer = new FactTypeChainer(myPredecidedManyToOneFactTypeMappings, myPredecidedOneToOneFactTypeMappings, myUndecidedOneToOneFactTypeMappings); // If some chains end up at a size we cannot process, then running // the chainer can move some mappings from undecided to predecided. // We pass in the decided mappings so that we do not lose track // of these entries. largestChainCount = chainer.Run(allDecidedMappings); // Perform one-time pass of top-level types for the decided mappings //PrecalculateDecidedConceptTypes(); // This is used in PermuteFactTypeMappings(). We allocate it once, here, for permformance reasons. FactTypeMappingList newlyDecidedFactTypeMappings = new FactTypeMappingList(largestChainCount); // This is used to prevent deep mappings of an object type in two directions. Dictionary<ObjectType, object> deeplyMappedObjectTypes = new Dictionary<ObjectType, object>(largestChainCount); ChainPermutationState permutationStateHelper = new ChainPermutationState(); // Used to eliminate deep mappings towards simple identifiers Dictionary<ObjectType, bool> nonPreferredFunctionalObjectTypesCache = new Dictionary<ObjectType, bool>(); // Loop through each chain, calculating the permutations. foreach (Chain chain in chainer.Chains) { // Find the object types that we already know have deep mappings away from them. foreach (FactTypeMapping decidedMapping in chain.PredecidedOneToOneFactTypeMappings) { if (decidedMapping.MappingDepth == MappingDepth.Deep) { deeplyMappedObjectTypes[decidedMapping.FromObjectType] = null; } } PermuteFactTypeMappings(chain.PossiblePermutations, chain.UndecidedOneToOneFactTypeMappings, newlyDecidedFactTypeMappings, deeplyMappedObjectTypes, 0); EliminateInvalidPermutations(chain, nonPreferredFunctionalObjectTypesCache); FindSmallestPermutationsInTermsOfConceptTypes(chain, permutationStateHelper); #if FALSE // UNDONE: See notes on EliminatePermutationsWithIdenticalResults EliminatePermutationsWithIdenticalResults(chain); #endif // FALSE // Add each mapping from the optimal permutation to the "global" set of decided mappings. foreach (FactTypeMapping optimalMapping in ChooseOptimalPermutation(chain).Mappings) { allDecidedMappings.Add(optimalMapping.FactType, optimalMapping); } // Clear the set of object types that have some deep mapping away from them (they will be different for the next chain). deeplyMappedObjectTypes.Clear(); } }