/// <summary> /// Factoriza o polinómio aplicando os métodos conhecidos. /// </summary> /// <param name="polynomial">O polinómio a ser factorizado.</param> /// <param name="primeNumber">O número primo.</param> /// <param name="bound">O limite dos coeficientes que podem representar números inteiros.</param> /// <param name="iterationsNumber">O número de iterações para o algoritmo do levantamento multifactor.</param> /// <param name="factorsList">A lista de factores.</param> /// <returns>O coeficiente independente.</returns> private CoeffType FactorizePolynomial( UnivariatePolynomialNormalForm <CoeffType> polynomial, CoeffType primeNumber, CoeffType bound, int iterationsNumber, List <UnivariatePolynomialNormalForm <CoeffType> > factorsList) { var modularField = this.modularSymmetricFactory.CreateInstance(primeNumber); var linearSystemSolver = new DenseCondensationLinSysAlgorithm <CoeffType>( modularField); var finiteFieldFactAlg = new FiniteFieldPolFactorizationAlgorithm <CoeffType>( linearSystemSolver, this.integerNumber); var finiteFieldFactorizationResult = finiteFieldFactAlg.Run( polynomial, modularField); var multiFactorLiftingStatus = new MultiFactorLiftingStatus <CoeffType>( polynomial, finiteFieldFactorizationResult, primeNumber); var multiFactorLiftingResult = this.multiFactorLiftingAlg.Run( multiFactorLiftingStatus, iterationsNumber); var searchResult = this.searchFactorizationAlgorithm.Run( multiFactorLiftingResult, bound, 3); if (searchResult.IntegerFactors.Count > 0) { factorsList.AddRange(searchResult.IntegerFactors); if (searchResult.NonIntegerFactors.Count > 0) // É necessário factorizar. { var currentFactor = searchResult.IntegerFactors[0]; for (int i = 1; i < searchResult.IntegerFactors.Count; ++i) { currentFactor = currentFactor.Multiply( searchResult.IntegerFactors[i], this.integerNumber); } var nonFactored = MathFunctions.GetIntegerDivision( searchResult.MainPolynomial, currentFactor, this.integerNumber); } } else { } throw new NotImplementedException(); }
/// <summary> /// Aplica o algoritmo um número especificado de vezes ou até ser encontrada uma factorização. /// </summary> /// <param name="multiFactorLiftingStatus">O estado do levantamento multifactor actual.</param> /// <param name="numberOfIterations">O número de iterações a ser efectuado.</param> /// <returns>A lista com os factores.</returns> public MultiFactorLiftingResult <CoeffType> Run( MultiFactorLiftingStatus <CoeffType> multiFactorLiftingStatus, int numberOfIterations) { if (multiFactorLiftingStatus.Factorization.Factors.Count > 1) { var modularField = this.linearLiftAlg.ModularFieldFactory.CreateInstance( multiFactorLiftingStatus.LiftedFactorizationModule); var factorTree = this.MountFactorTree( multiFactorLiftingStatus, modularField); factorTree.RootNode.NodeObject.Polynom = multiFactorLiftingStatus.Polynom; if (factorTree == null) { // Não existem factores suficientes para elevar var result = new List <UnivariatePolynomialNormalForm <CoeffType> >(); result.AddRange(multiFactorLiftingStatus.Factorization.Factors); return(new MultiFactorLiftingResult <CoeffType>( multiFactorLiftingStatus.Polynom, result, multiFactorLiftingStatus.LiftedFactorizationModule)); } else { // A árvore contém factores para elevar var factorQueue = new Queue <TreeNode <LinearLiftingStatus <CoeffType> > >(); var factorTreeRootNode = factorTree.RootNode.NodeObject.Polynom; factorQueue.Enqueue(factorTree.InternalRootNode); while (factorQueue.Count > 0) { var dequeued = factorQueue.Dequeue(); if (dequeued.Count == 2) { this.linearLiftAlg.Run(dequeued.NodeObject, numberOfIterations); if (this.linearLiftAlg.IntegerNumber.Compare( multiFactorLiftingStatus.LiftedFactorizationModule, dequeued.NodeObject.LiftedFactorizationModule) < 0) { multiFactorLiftingStatus.LiftedFactorizationModule = dequeued.NodeObject.LiftedFactorizationModule; } var firstChild = dequeued.ChildsList[0]; var secondChild = dequeued.ChildsList[1]; firstChild.NodeObject.Polynom = dequeued.NodeObject.UFactor; secondChild.NodeObject.Polynom = dequeued.NodeObject.WFactor; factorQueue.Enqueue(firstChild); factorQueue.Enqueue(secondChild); } } var treeSolution = this.GetSolutionFromTree(factorTree, this.linearLiftAlg.IntegerNumber); return(new MultiFactorLiftingResult <CoeffType>( factorTreeRootNode, treeSolution, multiFactorLiftingStatus.LiftedFactorizationModule)); } } else { return(new MultiFactorLiftingResult <CoeffType>( multiFactorLiftingStatus.Polynom, multiFactorLiftingStatus.Factorization.Factors, multiFactorLiftingStatus.LiftedFactorizationModule)); } }
/// <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); } }