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