private Set <EntityType> FindReachableTypes(
            DomainConstraintConversionContext <string, ValueCondition> converter,
            Vertex[] mappingConditions)
        {
            Vertex[] vertexArray = new Vertex[this.MappedEntityTypes.Count];
            for (int index1 = 0; index1 < vertexArray.Length; ++index1)
            {
                Vertex left = Vertex.One;
                for (int index2 = 0; index2 < this.NormalizedEntityTypeMappings.Count; ++index2)
                {
                    left = !this.NormalizedEntityTypeMappings[index2].ImpliedEntityTypes[index1] ? converter.Solver.And(left, converter.Solver.Not(mappingConditions[index2])) : converter.Solver.And(left, mappingConditions[index2]);
                }
                vertexArray[index1] = left;
            }
            Set <EntityType> set = new Set <EntityType>();

            for (int i = 0; i < vertexArray.Length; ++i)
            {
                if (!converter.Solver.And(((IEnumerable <Vertex>)vertexArray).Select <Vertex, Vertex>((Func <Vertex, int, Vertex>)((typeCondition, ordinal) =>
                {
                    if (ordinal != i)
                    {
                        return(converter.Solver.Not(typeCondition));
                    }
                    return(typeCondition);
                }))).IsZero())
                {
                    set.Add(this.MappedEntityTypes[i]);
                }
            }
            return(set);
        }
        /// <summary>
        ///     Determines which types are produced by this mapping.
        /// </summary>
        private Set <EntityType> FindUnambiguouslyReachableTypes(
            DomainConstraintConversionContext <string, ValueCondition> converter, Vertex[] mappingConditions)
        {
            // For each entity type, create a candidate function that evaluates to true given
            // discriminator assignments iff. all of that type's conditions evaluate to true.
            var candidateFunctions = new Vertex[MappedEntityTypes.Count];

            for (var i = 0; i < candidateFunctions.Length; i++)
            {
                // Seed the candidate function conjunction with 'true'.
                var candidateFunction = Vertex.One;
                for (var j = 0; j < NormalizedEntityTypeMappings.Count; j++)
                {
                    var entityTypeMapping = NormalizedEntityTypeMappings[j];

                    // Determine if this mapping is a positive or negative case for the current type.
                    if (entityTypeMapping.ImpliedEntityTypes[i])
                    {
                        candidateFunction = converter.Solver.And(candidateFunction, mappingConditions[j]);
                    }
                }
                candidateFunctions[i] = candidateFunction;
            }

            // Make sure that for each type with satisfiable candidateFunction all assignments for the type resolve to only that type.
            var unambigouslyReachableMap = new BitArray(candidateFunctions.Length, true);

            for (var i = 0; i < candidateFunctions.Length; ++i)
            {
                if (candidateFunctions[i].IsZero())
                {
                    // The i-th type is unreachable regardless of other types.
                    unambigouslyReachableMap[i] = false;
                }
                else
                {
                    for (var j = i + 1; j < candidateFunctions.Length; ++j)
                    {
                        if (!converter.Solver.And(candidateFunctions[i], candidateFunctions[j]).IsZero())
                        {
                            // The i-th and j-th types have common assignments, hence they aren't unambiguously reachable.
                            unambigouslyReachableMap[i] = false;
                            unambigouslyReachableMap[j] = false;
                        }
                    }
                }
            }
            var reachableTypes = new Set <EntityType>();

            for (var i = 0; i < candidateFunctions.Length; ++i)
            {
                if (unambigouslyReachableMap[i])
                {
                    reachableTypes.Add(MappedEntityTypes[i]);
                }
            }

            return(reachableTypes);
        }
        private void GetUnreachableTypes(
            bool validateAmbiguity,
            out KeyToListMap <EntityType, LineInfo> unreachableEntityTypes,
            out KeyToListMap <EntityType, LineInfo> unreachableIsTypeOfs)
        {
            DomainVariable <string, ValueCondition>[] variables = this.ConstructDomainVariables();
            DomainConstraintConversionContext <string, ValueCondition> converter = new DomainConstraintConversionContext <string, ValueCondition>();

            Vertex[] vertices = this.ConvertMappingConditionsToVertices((ConversionContext <DomainConstraint <string, ValueCondition> >)converter, variables);
            this.CollectUnreachableTypes(validateAmbiguity ? this.FindUnambiguouslyReachableTypes(converter, vertices) : this.FindReachableTypes(converter, vertices), out unreachableEntityTypes, out unreachableIsTypeOfs);
        }
        /// <summary>
        ///     Determines which types are produced by this mapping.
        /// </summary>
        private Set <EntityType> FindReachableTypes(
            DomainConstraintConversionContext <string, ValueCondition> converter, Vertex[] mappingConditions)
        {
            // For each entity type, create a candidate function that evaluates to true given
            // discriminator assignments iff. all of that type's conditions evaluate to true
            // and its negative conditions evaluate to false.
            var candidateFunctions = new Vertex[MappedEntityTypes.Count];

            for (var i = 0; i < candidateFunctions.Length; i++)
            {
                // Seed the candidate function conjunction with 'true'.
                var candidateFunction = Vertex.One;
                for (var j = 0; j < NormalizedEntityTypeMappings.Count; j++)
                {
                    var entityTypeMapping = NormalizedEntityTypeMappings[j];

                    // Determine if this mapping is a positive or negative case for the current type.
                    if (entityTypeMapping.ImpliedEntityTypes[i])
                    {
                        candidateFunction = converter.Solver.And(candidateFunction, mappingConditions[j]);
                    }
                    else
                    {
                        candidateFunction = converter.Solver.And(candidateFunction, converter.Solver.Not(mappingConditions[j]));
                    }
                }
                candidateFunctions[i] = candidateFunction;
            }

            // Make sure that for each type there is an assignment that resolves to only that type.
            var reachableTypes = new Set <EntityType>();

            for (var i = 0; i < candidateFunctions.Length; i++)
            {
                // Create a function that evaluates to true iff. the current candidate function is true
                // and every other candidate function is false.
                var isExactlyThisTypeCondition = converter.Solver.And(
                    candidateFunctions.Select(
                        (typeCondition, ordinal) => ordinal == i
                                                        ? typeCondition
                                                        : converter.Solver.Not(typeCondition)));

                // If the above conjunction is satisfiable, it means some row configuration exists producing the type.
                if (!isExactlyThisTypeCondition.IsZero())
                {
                    reachableTypes.Add(MappedEntityTypes[i]);
                }
            }

            return(reachableTypes);
        }
        private Set <EntityType> FindUnambiguouslyReachableTypes(
            DomainConstraintConversionContext <string, ValueCondition> converter,
            Vertex[] mappingConditions)
        {
            Vertex[] vertexArray = new Vertex[this.MappedEntityTypes.Count];
            for (int index1 = 0; index1 < vertexArray.Length; ++index1)
            {
                Vertex left = Vertex.One;
                for (int index2 = 0; index2 < this.NormalizedEntityTypeMappings.Count; ++index2)
                {
                    if (this.NormalizedEntityTypeMappings[index2].ImpliedEntityTypes[index1])
                    {
                        left = converter.Solver.And(left, mappingConditions[index2]);
                    }
                }
                vertexArray[index1] = left;
            }
            BitArray bitArray = new BitArray(vertexArray.Length, true);

            for (int index1 = 0; index1 < vertexArray.Length; ++index1)
            {
                if (vertexArray[index1].IsZero())
                {
                    bitArray[index1] = false;
                }
                else
                {
                    for (int index2 = index1 + 1; index2 < vertexArray.Length; ++index2)
                    {
                        if (!converter.Solver.And(vertexArray[index1], vertexArray[index2]).IsZero())
                        {
                            bitArray[index1] = false;
                            bitArray[index2] = false;
                        }
                    }
                }
            }
            Set <EntityType> set = new Set <EntityType>();

            for (int index = 0; index < vertexArray.Length; ++index)
            {
                if (bitArray[index])
                {
                    set.Add(this.MappedEntityTypes[index]);
                }
            }
            return(set);
        }
        /// <summary>
        ///     Determines which explicitly mapped types in the function import mapping cannot be generated.
        ///     For IsTypeOf declarations, reports if no type in hierarchy can be produced.
        ///     Works by:
        ///     - Converting type mapping conditions into vertices
        ///     - Checking that some assignment satisfies
        /// </summary>
        private void GetUnreachableTypes(
            bool validateAmbiguity,
            out KeyToListMap <EntityType, LineInfo> unreachableEntityTypes,
            out KeyToListMap <EntityType, LineInfo> unreachableIsTypeOfs)
        {
            // Contains, for each DiscriminatorColumn, a domain variable where the domain values are
            // integers representing the ordinal within discriminatorDomains.
            var variables = ConstructDomainVariables();

            // Convert type mapping conditions to decision diagram vertices.
            var converter         = new DomainConstraintConversionContext <string, ValueCondition>();
            var mappingConditions = ConvertMappingConditionsToVertices(converter, variables);

            // Find reachable types.
            var reachableTypes = validateAmbiguity
                                     ? FindUnambiguouslyReachableTypes(converter, mappingConditions)
                                     : FindReachableTypes(converter, mappingConditions);

            CollectUnreachableTypes(reachableTypes, out unreachableEntityTypes, out unreachableIsTypeOfs);
        }
        /// <summary>
        ///     Determines which types are produced by this mapping.
        /// </summary>
        private Set<EntityType> FindUnambiguouslyReachableTypes(
            DomainConstraintConversionContext<string, ValueCondition> converter, Vertex[] mappingConditions)
        {
            // For each entity type, create a candidate function that evaluates to true given
            // discriminator assignments iff. all of that type's conditions evaluate to true.
            var candidateFunctions = new Vertex[MappedEntityTypes.Count];
            for (var i = 0; i < candidateFunctions.Length; i++)
            {
                // Seed the candidate function conjunction with 'true'.
                var candidateFunction = Vertex.One;
                for (var j = 0; j < NormalizedEntityTypeMappings.Count; j++)
                {
                    var entityTypeMapping = NormalizedEntityTypeMappings[j];

                    // Determine if this mapping is a positive or negative case for the current type.
                    if (entityTypeMapping.ImpliedEntityTypes[i])
                    {
                        candidateFunction = converter.Solver.And(candidateFunction, mappingConditions[j]);
                    }
                }
                candidateFunctions[i] = candidateFunction;
            }

            // Make sure that for each type with satisfiable candidateFunction all assignments for the type resolve to only that type.
            var unambigouslyReachableMap = new BitArray(candidateFunctions.Length, true);
            for (var i = 0; i < candidateFunctions.Length; ++i)
            {
                if (candidateFunctions[i].IsZero())
                {
                    // The i-th type is unreachable regardless of other types.
                    unambigouslyReachableMap[i] = false;
                }
                else
                {
                    for (var j = i + 1; j < candidateFunctions.Length; ++j)
                    {
                        if (!converter.Solver.And(candidateFunctions[i], candidateFunctions[j]).IsZero())
                        {
                            // The i-th and j-th types have common assignments, hence they aren't unambiguously reachable.
                            unambigouslyReachableMap[i] = false;
                            unambigouslyReachableMap[j] = false;
                        }
                    }
                }
            }
            var reachableTypes = new Set<EntityType>();
            for (var i = 0; i < candidateFunctions.Length; ++i)
            {
                if (unambigouslyReachableMap[i])
                {
                    reachableTypes.Add(MappedEntityTypes[i]);
                }
            }

            return reachableTypes;
        }
        /// <summary>
        ///     Determines which types are produced by this mapping.
        /// </summary>
        private Set<EntityType> FindReachableTypes(
            DomainConstraintConversionContext<string, ValueCondition> converter, Vertex[] mappingConditions)
        {
            // For each entity type, create a candidate function that evaluates to true given
            // discriminator assignments iff. all of that type's conditions evaluate to true
            // and its negative conditions evaluate to false.
            var candidateFunctions = new Vertex[MappedEntityTypes.Count];
            for (var i = 0; i < candidateFunctions.Length; i++)
            {
                // Seed the candidate function conjunction with 'true'.
                var candidateFunction = Vertex.One;
                for (var j = 0; j < NormalizedEntityTypeMappings.Count; j++)
                {
                    var entityTypeMapping = NormalizedEntityTypeMappings[j];

                    // Determine if this mapping is a positive or negative case for the current type.
                    if (entityTypeMapping.ImpliedEntityTypes[i])
                    {
                        candidateFunction = converter.Solver.And(candidateFunction, mappingConditions[j]);
                    }
                    else
                    {
                        candidateFunction = converter.Solver.And(candidateFunction, converter.Solver.Not(mappingConditions[j]));
                    }
                }
                candidateFunctions[i] = candidateFunction;
            }

            // Make sure that for each type there is an assignment that resolves to only that type.
            var reachableTypes = new Set<EntityType>();
            for (var i = 0; i < candidateFunctions.Length; i++)
            {
                // Create a function that evaluates to true iff. the current candidate function is true
                // and every other candidate function is false.
                var isExactlyThisTypeCondition = converter.Solver.And(
                    candidateFunctions.Select(
                        (typeCondition, ordinal) => ordinal == i
                                                        ? typeCondition
                                                        : converter.Solver.Not(typeCondition)));

                // If the above conjunction is satisfiable, it means some row configuration exists producing the type.
                if (!isExactlyThisTypeCondition.IsZero())
                {
                    reachableTypes.Add(MappedEntityTypes[i]);
                }
            }

            return reachableTypes;
        }
        /// <summary>
        ///     Determines which explicitly mapped types in the function import mapping cannot be generated.
        ///     For IsTypeOf declarations, reports if no type in hierarchy can be produced.
        ///     Works by:
        ///     - Converting type mapping conditions into vertices
        ///     - Checking that some assignment satisfies
        /// </summary>
        private void GetUnreachableTypes(
            bool validateAmbiguity,
            out KeyToListMap<EntityType, LineInfo> unreachableEntityTypes,
            out KeyToListMap<EntityType, LineInfo> unreachableIsTypeOfs)
        {
            // Contains, for each DiscriminatorColumn, a domain variable where the domain values are
            // integers representing the ordinal within discriminatorDomains.
            var variables = ConstructDomainVariables();

            // Convert type mapping conditions to decision diagram vertices.
            var converter = new DomainConstraintConversionContext<string, ValueCondition>();
            var mappingConditions = ConvertMappingConditionsToVertices(converter, variables);

            // Find reachable types.
            var reachableTypes = validateAmbiguity
                                     ? FindUnambiguouslyReachableTypes(converter, mappingConditions)
                                     : FindReachableTypes(converter, mappingConditions);

            CollectUnreachableTypes(reachableTypes, out unreachableEntityTypes, out unreachableIsTypeOfs);
        }