/// <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> /// Aplica o lema do levantamento para elevar a factorização módulo m um número superior m'. /// </summary> /// <remarks> /// Não é realizada qualquer verificação da integridade dos dados associados aos parâmetros de entrada. /// Caso estes não sejam iniciados convenientemente, os resultados obtidos poderão não estar correctos. /// </remarks> /// <param name="status">Contém os dados de entrada.</param> /// <param name="iterationsNumber">O número de iterações.</param> /// <returns>Verdadeiro caso seja executada alguma iteração e falso caso contrário.</returns> /// <exception cref="ArgumentNullException"> /// Se os dados de entrada forem passados com um apontador nulo. /// </exception> public bool Run( LinearLiftingStatus <T> status, int iterationsNumber) { if (status == null) { throw new ArgumentNullException("status"); } else if (iterationsNumber < 1) { return(false); } else { var modularField = this.modularFieldFactory.CreateInstance(status.InitializedFactorizationModulus); var polynomialDomain = this.polynomialDomainFactory.CreateInstance( status.Polynom.VariableName, modularField); var result = this.Initialize(status, polynomialDomain, modularField); var k = 0; if (!status.FoundSolution && k < iterationsNumber) { result = true; do { var sigmaProd = polynomialDomain.Multiply( status.SPol, status.EPol); var monicDivisionResult = this.GetMonicDivision( sigmaProd, status.WFactor, modularField); // Cálculo dos factores var firstMultTemp = polynomialDomain.Multiply(status.TPol, status.EPol); var secondMultTemp = polynomialDomain.Multiply( monicDivisionResult.Quotient, status.UFactor); status.UFactor = polynomialDomain.Add(status.UFactor, firstMultTemp); status.UFactor = polynomialDomain.Add(status.UFactor, secondMultTemp); status.WFactor = polynomialDomain.Add(status.WFactor, monicDivisionResult.Remainder); // Cálculo dos restantes parâmetros firstMultTemp = polynomialDomain.Multiply(status.SPol, status.UFactor); secondMultTemp = polynomialDomain.Multiply(status.TPol, status.WFactor); var b = polynomialDomain.Add(firstMultTemp, secondMultTemp); b = b.Add( modularField.AdditiveInverse(modularField.MultiplicativeUnity), modularField); firstMultTemp = polynomialDomain.Multiply(b, status.SPol); monicDivisionResult = this.GetMonicDivision( firstMultTemp, status.WFactor, modularField); status.SPol = polynomialDomain.Add( status.SPol, polynomialDomain.AdditiveInverse(monicDivisionResult.Remainder)); firstMultTemp = polynomialDomain.Multiply(status.TPol, b); secondMultTemp = polynomialDomain.Multiply(status.UFactor, monicDivisionResult.Quotient); firstMultTemp = polynomialDomain.Add(firstMultTemp, secondMultTemp); status.TPol = polynomialDomain.Add( status.TPol, polynomialDomain.AdditiveInverse(firstMultTemp)); status.LiftedFactorizationModule = modularField.Module; modularField.Module = this.integerNumber.Multiply( modularField.Module, modularField.Module); status.InitializedFactorizationModulus = modularField.Module; status.EPol = polynomialDomain.Add( status.Polynom, polynomialDomain.AdditiveInverse(polynomialDomain.Multiply( status.UFactor, status.WFactor))); status.FoundSolution = polynomialDomain.IsAdditiveUnity(status.EPol); ++k; } while (!status.FoundSolution && k < iterationsNumber); } return(result); } }
/// <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); } }