/// <summary>
        /// Realiza o passo de simplificação final.
        /// </summary>
        /// <param name="implicantLines">Os implicantes primos.</param>
        /// <param name="usedDataImplicants">Os implicantes utilizados.</param>
        /// <param name="implicantMatrix">A matriz de cobertura.</param>
        /// <returns>Os implicantes primos essenciais.</returns>
        private List <LogicCombinationBitArray> Simplify(
            List <ImplicantLine> implicantLines,
            ImplicantLine[] usedDataImplicants,
            BitArray[] implicantMatrix)
        {
            var result                 = new List <LogicCombinationBitArray>();
            var markImplicantLines     = new BitArray(implicantLines.Count);
            var markUsedDataImplicants = new BitArray(usedDataImplicants.Length);
            var state = default(bool);

            do
            {
                state = false; // Termina o ciclo caso não seja possível encontrar uma coluna única
                for (int i = 0; i < usedDataImplicants.Length; ++i)
                {
                    var implicantMatrixLine = implicantMatrix[i];
                    if (!markUsedDataImplicants[i] &&
                        MathFunctions.CountSettedBits(implicantMatrixLine) == 1)
                    {
                        // Procura pelo índice do item não nulo
                        var index = this.FindBitSettedIndex(implicantMatrixLine);

                        markUsedDataImplicants[i] = true;
                        markImplicantLines[index] = true;
                        for (int j = 0; j < usedDataImplicants.Length; ++j)
                        {
                            implicantMatrix[i][index] = false;
                        }

                        state = true;
                    }
                }
            } while (state);

            var coverMatrix = this.MountMatrix(
                result,
                implicantLines,
                implicantMatrix,
                markImplicantLines,
                markUsedDataImplicants);

            this.ProcessCoverMatrix(coverMatrix);
            for (int i = 0; i < coverMatrix.Count; ++i)
            {
                result.Add(coverMatrix.Keys[i].PrimeImplicant);
            }

            return(result);
        }
        /// <summary>
        /// Constrói a matriz de cobertura numa lista ordenada.
        /// </summary>
        /// <param name="essentialPrimeImplicants">A lista dos implicantes primos resultantes.</param>
        /// <param name="primeImplicants">Os implicantes primos.</param>
        /// <param name="implicantMatrix">A matriz actual dos implicantes.</param>
        /// <param name="markImplicantLines">O vector que marca os implicantes que não vão ser considerados.</param>
        /// <param name="markUsedDataImplicants">
        /// O vector que marca os implicantes iniciais que não vão ser considerados.
        /// </param>
        /// <returns>A matriz requerida.</returns>
        private SortedList <CoverLine, bool> MountMatrix(
            List <LogicCombinationBitArray> essentialPrimeImplicants,
            List <ImplicantLine> primeImplicants,
            BitArray[] implicantMatrix,
            BitArray markImplicantLines,
            BitArray markUsedDataImplicants)
        {
            var result = new SortedList <CoverLine, bool>(new CoverLinesComparer());
            var remainingDataImplicantsNumber = markUsedDataImplicants.Length - MathFunctions.CountSettedBits(
                markUsedDataImplicants);

            for (int i = 0; i < markImplicantLines.Length; ++i)
            {
                if (markImplicantLines[i])
                {
                    essentialPrimeImplicants.Add(primeImplicants[i].LineCombination);
                }
                else
                {
                    var arrayLine          = new BitArray(remainingDataImplicantsNumber);
                    var dataImplicantIndex = 0;
                    for (int j = 0; j < markUsedDataImplicants.Length; ++j)
                    {
                        if (!markUsedDataImplicants[j])
                        {
                            arrayLine[dataImplicantIndex] = implicantMatrix[j][i];
                            ++dataImplicantIndex;
                        }
                    }

                    result.Add(
                        new CoverLine()
                    {
                        Line = arrayLine, PrimeImplicant = primeImplicants[i].LineCombination
                    },
                        false);
                }
            }

            return(result);
        }