示例#1
0
        /// <summary>
        /// Aplica o método da factorização em corpos finitos ao polinómio simples.
        /// </summary>
        /// <param name="polynom">O polinómio simples.</param>
        /// <param name="integerModule">O corpo responsável pelas operações sobre os coeficientes.</param>
        /// <param name="polynomField">O corpo responsável pelo produto de polinómios.</param>
        /// <param name="bachetBezoutAlgorithm">O objecto responsável pelo algoritmo de máximo divisor comum.</param>
        /// <returns>A lista dos factores.</returns>
        private FiniteFieldPolynomialFactorizationResult <CoeffType> Factorize(
            UnivariatePolynomialNormalForm <CoeffType> polynom,
            IModularField <CoeffType> integerModule,
            UnivarPolynomEuclideanDomain <CoeffType> polynomField,
            LagrangeAlgorithm <UnivariatePolynomialNormalForm <CoeffType> > bachetBezoutAlgorithm)
        {
            var result = new List <UnivariatePolynomialNormalForm <CoeffType> >();

            var polynomialStack = new Stack <UnivariatePolynomialNormalForm <CoeffType> >();
            var processedPols   = this.Process(
                polynom,
                result,
                integerModule,
                polynomField,
                bachetBezoutAlgorithm);

            foreach (var processedPol in processedPols)
            {
                polynomialStack.Push(processedPol);
            }

            while (polynomialStack.Count > 0)
            {
                var topPolynomial = polynomialStack.Pop();
                processedPols = this.Process(
                    topPolynomial,
                    result,
                    integerModule,
                    polynomField,
                    bachetBezoutAlgorithm);

                foreach (var processedPol in processedPols)
                {
                    polynomialStack.Push(processedPol);
                }
            }

            for (int i = 0; i < result.Count; ++i)
            {
                var leadingMon = result[i].GetLeadingCoefficient(integerModule);
                if (!integerModule.IsMultiplicativeUnity(leadingMon))
                {
                    var invLeadingMon = integerModule.MultiplicativeInverse(leadingMon);
                    result[i] = result[i].ApplyFunction(
                        c => integerModule.Multiply(c, invLeadingMon),
                        integerModule);
                }
            }

            var mainLeadingMon = polynom.GetLeadingCoefficient(integerModule);

            return(new FiniteFieldPolynomialFactorizationResult <CoeffType>(
                       mainLeadingMon,
                       result,
                       polynom));
        }
示例#2
0
        /// <summary>
        /// Quadra um valor um número especificado de vezes.
        /// </summary>
        /// <param name="value">O valor.</param>
        /// <param name="times">O número de vezes.</param>
        /// <param name="modularField">O objecto responsável pelas operações modulares.</param>
        /// <returns>O resultado.</returns>
        private NumberType SquareValue(NumberType value, NumberType times, IModularField <NumberType> modularField)
        {
            var result = value;
            var i      = this.integerNumber.AdditiveUnity;

            for (; this.integerNumber.Compare(i, times) < 0; i = this.integerNumber.Successor(i))
            {
                result = modularField.Multiply(result, result);
            }

            return(result);
        }
示例#3
0
        /// <summary>
        /// Inicialia o estado do algoritmo caso seja aplicável.
        /// </summary>
        /// <param name="status">O estado a ser tratado.</param>
        /// <param name="polynomialDomain">O domínio polinomial.</param>
        /// <param name="modularField">O corpo modular.</param>
        /// <returns>Verdadeiro caso se verifique alguma inicialização e falso caso contrário.</returns>
        /// <exception cref="ArgumentNullException">Se o estado for nulo.</exception>
        private bool Initialize(
            LinearLiftingStatus <T> status,
            IEuclidenDomain <UnivariatePolynomialNormalForm <T> > polynomialDomain,
            IModularField <T> modularField)
        {
            var result = false;

            if (status.NotInitialized)
            {
                var leadingCoeff = status.W1Factor.GetLeadingCoefficient(modularField);
                if (modularField.IsMultiplicativeUnity(leadingCoeff))
                {
                    result = true;

                    var domainAlg = new LagrangeAlgorithm <UnivariatePolynomialNormalForm <T> >(
                        polynomialDomain);
                    var domainResult = domainAlg.Run(status.U1Factor, status.W1Factor);

                    var invGcd = modularField.MultiplicativeInverse(
                        domainResult.GreatestCommonDivisor.GetAsValue(modularField));
                    status.SPol = domainResult.FirstFactor.Multiply(
                        invGcd,
                        modularField);
                    status.TPol = domainResult.SecondFactor.Multiply(
                        invGcd,
                        modularField);

                    status.UFactor = status.U1Factor;
                    status.WFactor = status.W1Factor;

                    modularField.Module = this.integerNumber.Multiply(modularField.Module, modularField.Module);
                    status.InitializedFactorizationModulus = modularField.Module;
                    var ePol = polynomialDomain.Multiply(status.UFactor, status.WFactor);
                    ePol = polynomialDomain.Add(
                        status.Polynom,
                        polynomialDomain.AdditiveInverse(ePol));
                    status.EPol = ePol;

                    status.NotInitialized = false;
                }
                else
                {
                    throw new MathematicsException(
                              "The W factor in lifting algorithm must be a monic polynomial.");
                }
            }

            return(result);
        }
示例#4
0
        /// <summary>
        /// Obtém a representação polinomial a partir de um vector da base do espaço nulo.
        /// </summary>
        /// <param name="vector">O vector.</param>
        /// <param name="module">O corpo responsável pelas operações sobre os ceoficientes do polinómio.</param>
        /// <param name="variableName">O nome da variável.</param>
        /// <returns>O polinómio.</returns>
        private UnivariatePolynomialNormalForm <CoeffType> GetPolynomial(
            IMathVector <CoeffType> vector,
            IModularField <CoeffType> module,
            string variableName)
        {
            var matrixDimension = vector.Length;
            var temporaryDic    = new Dictionary <int, CoeffType>();

            for (int i = 0; i < matrixDimension; ++i)
            {
                temporaryDic.Add(i, vector[i]);
            }

            return(new UnivariatePolynomialNormalForm <CoeffType>(
                       temporaryDic,
                       variableName,
                       module));
        }
示例#5
0
        /// <summary>
        /// Tenta encontrar o índice i tal que temp^(2^i) seja congruente com a unidade.
        /// </summary>
        /// <param name="temp">O valor de temp.</param>
        /// <param name="upperLimit">O valor do limite superior.</param>
        /// <param name="modularField">O objecto responsável pelas operações modulares.</param>
        /// <returns>O índice procurado.</returns>
        private NumberType FindLowestIndex(NumberType temp, NumberType upperLimit, IModularField <NumberType> modularField)
        {
            var result    = this.integerNumber.MapFrom(-1);
            var innerTemp = temp;
            var i         = this.integerNumber.AdditiveUnity;

            for (; this.integerNumber.Compare(i, upperLimit) < 0; i = this.integerNumber.Successor(i))
            {
                if (this.integerNumber.IsMultiplicativeUnity(innerTemp))
                {
                    result = i;
                    i      = upperLimit;
                }
                else
                {
                    innerTemp = modularField.Multiply(innerTemp, innerTemp);
                }
            }

            return(result);
        }
示例#6
0
        /// <summary>
        /// Executa o algoritmo sobre o polinómio com coeficientes inteiros.
        /// </summary>
        /// <remarks>
        /// O polinómio tem de ser livre de quadrados. Caso contrário, o resultado da aplicação do algoritmo
        /// é imprevisível.
        /// </remarks>
        /// <param name="polymomial">O polinómio.</param>
        /// <param name="modularField">O corpo modular.</param>
        /// <returns>A factorização do polinómio.</returns>
        public FiniteFieldPolynomialFactorizationResult <CoeffType> Run(
            UnivariatePolynomialNormalForm <CoeffType> polymomial,
            IModularField <CoeffType> modularField)
        {
            var fractionField = new FractionField <CoeffType>(this.integerNumber);
            var polynomDomain = new UnivarPolynomEuclideanDomain <CoeffType>(
                polymomial.VariableName,
                modularField);
            var bachetBezourAlg = new LagrangeAlgorithm <UnivariatePolynomialNormalForm <CoeffType> >(polynomDomain);

            var polynomialField = new UnivarPolynomEuclideanDomain <CoeffType>(
                polymomial.VariableName,
                modularField);

            var result = this.Factorize(
                polymomial,
                modularField,
                polynomialField,
                bachetBezourAlg);

            return(result);
        }
示例#7
0
        /// <summary>
        /// Processa o polinómio determinando os respectivos factores.
        /// </summary>
        /// <remarks>
        /// Os factores constantes são ignorados, os factores lineares são anexados ao resultado e os factores
        /// cujos graus são superiores são retornados para futuro processamento. Se o polinómio a ser processado
        /// for irredutível, é adicionado ao resultado.
        /// </remarks>
        /// <param name="polynom">O polinómio a ser processado.</param>
        /// <param name="result">O contentor dos factores sucessivamente processados.</param>
        /// <param name="integerModule">O objecto responsável pelas operações sobre inteiros.</param>
        /// <param name="polynomField">O objecto responsável pelas operações sobre os polinómios.</param>
        /// <param name="inverseAlgorithm">O algoritmo inverso.</param>
        /// <returns></returns>
        List <UnivariatePolynomialNormalForm <CoeffType> > Process(
            UnivariatePolynomialNormalForm <CoeffType> polynom,
            List <UnivariatePolynomialNormalForm <CoeffType> > result,
            IModularField <CoeffType> integerModule,
            UnivarPolynomEuclideanDomain <CoeffType> polynomField,
            LagrangeAlgorithm <UnivariatePolynomialNormalForm <CoeffType> > inverseAlgorithm)
        {
            var resultPol = new List <UnivariatePolynomialNormalForm <CoeffType> >();

            if (polynom.Degree < 2)
            {
                result.Add(polynom);
            }
            else
            {
                var module = new ModularBachetBezoutField <UnivariatePolynomialNormalForm <CoeffType> >(
                    polynom,
                    inverseAlgorithm);

                var degree      = polynom.Degree;
                var arrayMatrix = new ArrayMathMatrix <CoeffType>(degree, degree, integerModule.AdditiveUnity);
                arrayMatrix[0, 0] = integerModule.AdditiveUnity;
                var pol = new UnivariatePolynomialNormalForm <CoeffType>(
                    integerModule.MultiplicativeUnity,
                    1,
                    polynom.VariableName,
                    integerModule);

                var integerModuleValue = this.integerNumber.ConvertToInt(integerModule.Module);

                pol = MathFunctions.Power(pol, integerModuleValue, module);
                foreach (var term in pol)
                {
                    arrayMatrix[term.Key, 1] = term.Value;
                }

                var auxPol = pol;
                for (int i = 2; i < degree; ++i)
                {
                    auxPol = module.Multiply(auxPol, pol);
                    foreach (var term in auxPol)
                    {
                        arrayMatrix[term.Key, i] = term.Value;
                    }
                }

                for (int i = 1; i < degree; ++i)
                {
                    var value = arrayMatrix[i, i];
                    value = integerModule.Add(
                        value,
                        integerModule.AdditiveInverse(integerModule.MultiplicativeUnity));
                    arrayMatrix[i, i] = value;
                }

                var emtpyMatrix          = new ZeroMatrix <CoeffType>(degree, 1, integerModule);
                var linearSystemSolution = this.linearSystemSolver.Run(arrayMatrix, emtpyMatrix);

                var numberOfFactors = linearSystemSolution.VectorSpaceBasis.Count;
                if (numberOfFactors < 2)
                {
                    result.Add(polynom);
                }
                else
                {
                    var hPol = default(UnivariatePolynomialNormalForm <CoeffType>);
                    var linearSystemCount = linearSystemSolution.VectorSpaceBasis.Count;
                    for (int i = 0; i < linearSystemCount; ++i)
                    {
                        var currentBaseSolution = linearSystemSolution.VectorSpaceBasis[i];
                        var rowsLength          = currentBaseSolution.Length;
                        for (int j = 1; j < rowsLength; ++j)
                        {
                            if (!integerModule.IsAdditiveUnity(currentBaseSolution[j]))
                            {
                                hPol = this.GetPolynomial(currentBaseSolution, integerModule, polynom.VariableName);
                                j    = rowsLength;
                            }

                            if (hPol != null)
                            {
                                j = rowsLength;
                            }
                        }

                        if (hPol != null)
                        {
                            i = linearSystemCount;
                        }
                    }

                    for (int i = 0, k = 0; k < numberOfFactors && i < integerModuleValue; ++i)
                    {
                        var converted  = this.integerNumber.MapFrom(i);
                        var currentPol = MathFunctions.GreatCommonDivisor(
                            polynom,
                            hPol.Subtract(converted, integerModule),
                            polynomField);
                        var currentDegree = currentPol.Degree;
                        if (currentDegree == 1)
                        {
                            result.Add(currentPol);
                            ++k;
                        }
                        else if (currentDegree > 1)
                        {
                            resultPol.Add(currentPol);
                            ++k;
                        }
                    }
                }
            }

            return(resultPol);
        }
示例#8
0
        /// <summary>
        /// Obtém a divisão de um polinómio geral por um polinómio mónico.
        /// </summary>
        /// <param name="dividend">O polinómio geral.</param>
        /// <param name="divisor">O polinómio mónico.</param>
        /// <param name="modularField">
        /// O domínio sobre os quais as operações sobre os coeficientes são realizadas.
        /// </param>
        /// <returns>O resultado da divisão.</returns>
        private DomainResult <UnivariatePolynomialNormalForm <T> > GetMonicDivision(
            UnivariatePolynomialNormalForm <T> dividend,
            UnivariatePolynomialNormalForm <T> divisor,
            IModularField <T> modularField)
        {
            if (dividend.IsZero)
            {
                return(new DomainResult <UnivariatePolynomialNormalForm <T> >(
                           dividend,
                           dividend));
            }
            else if (divisor.Degree > dividend.Degree)
            {
                return(new DomainResult <UnivariatePolynomialNormalForm <T> >(
                           new UnivariatePolynomialNormalForm <T>(dividend.VariableName),
                           dividend));
            }
            else
            {
                var remainderSortedCoeffs  = dividend.GetOrderedCoefficients(Comparer <int> .Default);
                var divisorSorteCoeffs     = divisor.GetOrderedCoefficients(Comparer <int> .Default);
                var quotientCoeffs         = new UnivariatePolynomialNormalForm <T>(dividend.VariableName);
                var remainderLeadingDegree = remainderSortedCoeffs.Keys[remainderSortedCoeffs.Keys.Count - 1];
                var divisorLeadingDegree   = divisorSorteCoeffs.Keys[divisorSorteCoeffs.Keys.Count - 1];
                while (remainderLeadingDegree >= divisorLeadingDegree && remainderSortedCoeffs.Count > 0)
                {
                    var remainderLeadingCoeff = remainderSortedCoeffs[remainderLeadingDegree];
                    var differenceDegree      = remainderLeadingDegree - divisorLeadingDegree;
                    quotientCoeffs = quotientCoeffs.Add(remainderLeadingCoeff, differenceDegree, modularField);
                    remainderSortedCoeffs.Remove(remainderLeadingDegree);
                    for (int i = 0; i < divisorSorteCoeffs.Keys.Count - 1; ++i)
                    {
                        var currentDivisorDegree = divisorSorteCoeffs.Keys[i];
                        var currentCoeff         = modularField.Multiply(
                            divisorSorteCoeffs[currentDivisorDegree],
                            remainderLeadingCoeff);
                        currentDivisorDegree += differenceDegree;
                        var addCoeff = default(T);
                        if (remainderSortedCoeffs.TryGetValue(currentDivisorDegree, out addCoeff))
                        {
                            addCoeff = modularField.Add(
                                addCoeff,
                                modularField.AdditiveInverse(currentCoeff));
                            if (modularField.IsAdditiveUnity(addCoeff))
                            {
                                remainderSortedCoeffs.Remove(currentDivisorDegree);
                            }
                            else
                            {
                                remainderSortedCoeffs[currentDivisorDegree] = addCoeff;
                            }
                        }
                        else
                        {
                            remainderSortedCoeffs.Add(
                                currentDivisorDegree,
                                modularField.AdditiveInverse(currentCoeff));
                        }
                    }

                    if (remainderSortedCoeffs.Count > 0)
                    {
                        remainderLeadingDegree = remainderSortedCoeffs.Keys[remainderSortedCoeffs.Keys.Count - 1];
                    }
                    else
                    {
                        remainderLeadingDegree = 0;
                    }
                }

                var remainder = new UnivariatePolynomialNormalForm <T>(
                    remainderSortedCoeffs,
                    dividend.VariableName,
                    modularField);
                return(new DomainResult <UnivariatePolynomialNormalForm <T> >(
                           quotientCoeffs,
                           remainder));
            }
        }
        /// <summary>
        /// Contrói a árvore de factores.
        /// </summary>
        /// <param name="multiFactorLiftingStatus">Contém a factorização que se pretende elevar.</param>
        /// <param name="modularField">O corpo modular sobre o qual são efectuadas as operações.</param>
        /// <returns>A árvore.</returns>
        private Tree <LinearLiftingStatus <CoeffType> > MountFactorTree(
            MultiFactorLiftingStatus <CoeffType> multiFactorLiftingStatus,
            IModularField <CoeffType> modularField)
        {
            var tree             = new Tree <LinearLiftingStatus <CoeffType> >();
            var currentNodes     = new List <TreeNode <LinearLiftingStatus <CoeffType> > >();
            var factorEnumerator = multiFactorLiftingStatus.Factorization.Factors.GetEnumerator();

            if (factorEnumerator.MoveNext())
            {
                var factor = factorEnumerator.Current;
                if (!modularField.IsMultiplicativeUnity(multiFactorLiftingStatus.Factorization.IndependentCoeff))
                {
                    factor = factor.Multiply(multiFactorLiftingStatus.Factorization.IndependentCoeff, modularField);
                }

                currentNodes.Add(new TreeNode <LinearLiftingStatus <CoeffType> >(
                                     new LinearLiftingStatus <CoeffType>(factor, modularField.Module),
                                     tree,
                                     null));

                while (factorEnumerator.MoveNext())
                {
                    factor = factorEnumerator.Current;
                    currentNodes.Add(new TreeNode <LinearLiftingStatus <CoeffType> >(
                                         new LinearLiftingStatus <CoeffType>(factor, modularField.Module),
                                         tree,
                                         null));
                }
            }

            if (currentNodes.Count < 2)
            {
                return(null);
            }
            else
            {
                var temporaryNodes = new List <TreeNode <LinearLiftingStatus <CoeffType> > >();
                var count          = 0;
                while (currentNodes.Count > 1)
                {
                    temporaryNodes.Clear();
                    var i = 0;
                    while (i < currentNodes.Count)
                    {
                        var parentNode = default(TreeNode <LinearLiftingStatus <CoeffType> >);
                        var first      = currentNodes[i];
                        ++i;
                        if (i < currentNodes.Count)
                        {
                            var second  = currentNodes[i];
                            var product = first.NodeObject.Polynom.Multiply(
                                second.NodeObject.Polynom,
                                modularField);

                            var liftingStatus = new LinearLiftingStatus <CoeffType>(
                                product,
                                first.NodeObject.Polynom,
                                second.NodeObject.Polynom,
                                modularField.Module);

                            parentNode = new TreeNode <LinearLiftingStatus <CoeffType> >(
                                liftingStatus,
                                tree,
                                null);

                            first.InternalParent  = parentNode;
                            second.InternalParent = parentNode;
                            parentNode.Add(first);
                            parentNode.Add(second);
                            ++i;
                        }
                        else
                        {
                            parentNode = first;
                        }

                        temporaryNodes.Add(parentNode);
                    }

                    var swap = currentNodes;
                    currentNodes   = temporaryNodes;
                    temporaryNodes = swap;
                    ++count;
                }

                var lastNode = currentNodes[0];
                tree.InternalRootNode = lastNode;
                return(tree);
            }
        }