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);
			}
		}